watchdog support: Add, remove, edit in place, and enumerate existing devs

This commit is contained in:
Cole Robinson 2010-03-24 00:22:17 -04:00
parent 28bdbd599c
commit b93d1b362a
6 changed files with 494 additions and 10 deletions

View File

@ -27,7 +27,8 @@ import gtk.gdk
import gtk.glade
import virtinst
from virtinst import VirtualCharDevice, VirtualDevice, VirtualVideoDevice
from virtinst import (VirtualCharDevice, VirtualDevice, VirtualVideoDevice,
VirtualWatchdog)
import virtManager.util as util
import virtManager.uihelpers as uihelpers
@ -50,7 +51,8 @@ PAGE_SOUND = 5
PAGE_HOSTDEV = 6
PAGE_CHAR = 7
PAGE_VIDEO = 8
PAGE_SUMMARY = 9
PAGE_WATCHDOG = 9
PAGE_SUMMARY = 10
char_widget_mappings = {
"source_path" : "char-path",
@ -298,6 +300,14 @@ class vmmAddHardware(gobject.GObject):
self.window.get_widget("char-info-box").modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("grey"))
# Watchdog widgets
combo = self.window.get_widget("watchdog-model")
uihelpers.build_watchdogmodel_combo(self.vm, combo)
combo = self.window.get_widget("watchdog-action")
uihelpers.build_watchdogaction_combo(self.vm, combo)
def reset_state(self):
is_local = not self.conn.is_remote()
is_storage_capable = self.conn.is_storage_capable()
@ -423,6 +433,9 @@ class vmmAddHardware(gobject.GObject):
self.vm.get_connection().vmm,
virtinst.support.SUPPORT_CONN_DOMAIN_VIDEO),
_("Libvirt version does not support video devices."))
add_hw_option("Watchdog", "device_pci", PAGE_WATCHDOG,
self.vm.is_hvm(),
_("Not supported for this guest type."))
self.window.get_widget("hardware-type").set_active(0)
@ -617,6 +630,13 @@ class vmmAddHardware(gobject.GObject):
modbox = self.window.get_widget("video-model")
return modbox.get_model()[modbox.get_active()][0]
# Watchdog getters
def get_config_watchdog_model(self):
modbox = self.window.get_widget("watchdog-model")
return modbox.get_model()[modbox.get_active()][0]
def get_config_watchdog_action(self):
modbox = self.window.get_widget("watchdog-action")
return modbox.get_model()[modbox.get_active()][0]
################
# UI listeners #
@ -830,6 +850,13 @@ class vmmAddHardware(gobject.GObject):
]
title = _("Video")
elif hwpage == PAGE_WATCHDOG:
title = _("Watchdog")
info_list = [
(_("Model:"), self._dev.model),
(_("Action:"), self._dev.get_action_desc(self._dev.action))
]
set_table(title, info_list)
@ -1051,6 +1078,8 @@ class vmmAddHardware(gobject.GObject):
return self.validate_page_char()
elif page_num == PAGE_VIDEO:
return self.validate_page_video()
elif page_num == PAGE_WATCHDOG:
return self.validate_page_watchdog()
def validate_page_intro(self):
if self.get_config_hardware_type() == None:
@ -1248,7 +1277,7 @@ class vmmAddHardware(gobject.GObject):
# Dump XML for sanity checking
self._dev.get_xml_config()
except Exception, e:
return self.err.val_err(_("%s device parameter error.") %
return self.err.val_err(_("%s device parameter error") %
chartype.capitalize(), str(e))
def validate_page_video(self):
@ -1259,7 +1288,20 @@ class vmmAddHardware(gobject.GObject):
self._dev = VirtualVideoDevice(conn=conn)
self._dev.model_type = model
except Exception, e:
return self.err.val_err(_("Video device parameter error.") %
return self.err.val_err(_("Video device parameter error"),
str(e))
def validate_page_watchdog(self):
conn = self.vm.get_connection().vmm
model = self.get_config_watchdog_model()
action = self.get_config_watchdog_action()
try:
self._dev = VirtualWatchdog(conn=conn)
self._dev.model = model
self._dev.action = action
except Exception, e:
return self.err.val_err(_("Watchdog parameter error"),
str(e))

View File

@ -58,10 +58,12 @@ HW_LIST_TYPE_SOUND = 9
HW_LIST_TYPE_CHAR = 10
HW_LIST_TYPE_HOSTDEV = 11
HW_LIST_TYPE_VIDEO = 12
HW_LIST_TYPE_WATCHDOG = 13
remove_pages = [ HW_LIST_TYPE_NIC, HW_LIST_TYPE_INPUT,
HW_LIST_TYPE_GRAPHICS, HW_LIST_TYPE_SOUND, HW_LIST_TYPE_CHAR,
HW_LIST_TYPE_HOSTDEV, HW_LIST_TYPE_DISK, HW_LIST_TYPE_VIDEO]
HW_LIST_TYPE_HOSTDEV, HW_LIST_TYPE_DISK, HW_LIST_TYPE_VIDEO,
HW_LIST_TYPE_WATCHDOG]
# Boot device columns
BOOT_DEV_TYPE = 0
@ -264,6 +266,9 @@ class vmmDetails(gobject.GObject):
"on_video_model_combo_changed": self.config_enable_apply,
"on_watchdog_model_combo_changed": self.config_enable_apply,
"on_watchdog_action_combo_changed": self.config_enable_apply,
"on_config_apply_clicked": self.config_apply,
"on_details_help_activate": self.show_help,
@ -563,6 +568,16 @@ class vmmDetails(gobject.GObject):
video_dev = self.window.get_widget("video-model-combo")
uihelpers.build_video_combo(self.vm, video_dev, no_default=no_default)
# Watchdog model combo
combo = self.window.get_widget("watchdog-model-combo")
uihelpers.build_watchdogmodel_combo(self.vm, combo,
no_default=no_default)
# Watchdog action combo
combo = self.window.get_widget("watchdog-action-combo")
uihelpers.build_watchdogaction_combo(self.vm, combo,
no_default=no_default)
# Helper function to handle the combo/label pattern used for
# video model, sound model, network model, etc.
def set_combo_label(self, prefix, model_idx, value):
@ -741,6 +756,8 @@ class vmmDetails(gobject.GObject):
self.refresh_hostdev_page()
elif pagetype == HW_LIST_TYPE_VIDEO:
self.refresh_video_page()
elif pagetype == HW_LIST_TYPE_WATCHDOG:
self.refresh_watchdog_page()
else:
pagetype = -1
except Exception, e:
@ -1193,6 +1210,8 @@ class vmmDetails(gobject.GObject):
ret = self.config_sound_apply(info[1])
elif pagetype is HW_LIST_TYPE_VIDEO:
ret = self.config_video_apply(info[1])
elif pagetype is HW_LIST_TYPE_WATCHDOG:
ret = self.config_watchdog_apply(info[1])
else:
ret = False
@ -1360,6 +1379,16 @@ class vmmDetails(gobject.GObject):
return self._change_config_helper(self.vm.define_video_model,
(dev_id_info, model))
# Watchdog options
def config_watchdog_apply(self, dev_id_info):
model = self.get_combo_label_value("watchdog-model")
action = self.get_combo_label_value("watchdog-action")
if model or action:
return self._change_config_helper([self.vm.define_watchdog_model,
self.vm.define_watchdog_action],
[(dev_id_info, model),
(dev_id_info, action)])
# Device removal
def remove_device(self, dev_type, dev_id_info):
logging.debug("Removing device: %s %s" % (dev_type, dev_id_info))
@ -1937,6 +1966,16 @@ class vmmDetails(gobject.GObject):
self.set_combo_label("video-model", 0, model)
def refresh_watchdog_page(self):
watchinfo = self.get_hw_selection(HW_LIST_COL_DEVICE)
if not watchinfo:
return
ignore, ignore, model, action = watchinfo
self.set_combo_label("watchdog-model", 0, model)
self.set_combo_label("watchdog-action", 0, action)
def refresh_boot_page(self):
# Refresh autostart
try:
@ -1992,6 +2031,7 @@ class vmmDetails(gobject.GObject):
currentChars = {}
currentHostdevs = {}
currentVids = {}
currentWatchdogs = {}
def add_hw_list_option(idx, name, page_id, info, icon_name):
hw_list_model.insert(idx, [name, icon_name,
@ -2094,6 +2134,11 @@ class vmmDetails(gobject.GObject):
update_hwlist(HW_LIST_TYPE_VIDEO, vidinfo, _("Video"),
"video-display")
for watchinfo in self.vm.get_watchdog_devices():
currentWatchdogs[watchinfo[1]] = 1
update_hwlist(HW_LIST_TYPE_WATCHDOG, watchinfo, _("Watchdog"),
"device_pci")
# Now remove any no longer current devs
devs = range(len(hw_list_model))
devs.reverse()
@ -2111,6 +2156,7 @@ class vmmDetails(gobject.GObject):
HW_LIST_TYPE_CHAR : currentChars,
HW_LIST_TYPE_HOSTDEV : currentHostdevs,
HW_LIST_TYPE_VIDEO : currentVids,
HW_LIST_TYPE_WATCHDOG : currentWatchdogs,
}

View File

@ -173,11 +173,18 @@ class vmmDomainBase(vmmLibvirtObject):
def define_network_model(self, dev_id_info, newmodel):
raise NotImplementedError()
def define_sound_model(self, dev_id_info, newmodel):
raise NotImplementedError()
def define_video_model(self, dev_id_info, newmodel):
raise NotImplementedError()
def define_watchdog_model(self, dev_id_info, newmodel):
raise NotImplementedError()
def define_watchdog_action(self, dev_id_info, newmodel):
raise NotImplementedError()
########################
# XML Parsing routines #
########################
@ -716,6 +723,24 @@ class vmmDomainBase(vmmLibvirtObject):
return hostdevs
return self._parse_device_xml(_parse_hostdev_devs)
def get_watchdog_devices(self):
def _parse_devs(ctx):
vids = []
devs = ctx.xpathEval("/domain/devices/watchdog")
count = 0
for dev in devs:
model = dev.prop("model")
action = dev.prop("action")
unique = count
count += 1
row = ["watchdog", unique, model, action]
vids.append(row)
return vids
return self._parse_device_xml(_parse_devs)
def _parse_device_xml(self, parse_function, refresh_if_necc=True,
inactive=False):
@ -777,6 +802,9 @@ class vmmDomainBase(vmmLibvirtObject):
elif dev_type == "video":
xpath = "/domain/devices/video[%s]" % (int(dev_id_info) + 1)
elif dev_type == "watchdog":
xpath = "/domain/devices/watchdog[%s]" % (int(dev_id_info) + 1)
else:
raise RuntimeError(_("Unknown device type '%s'") % dev_type)
@ -1814,6 +1842,34 @@ class vmmDomain(vmmDomainBase):
return self._redefine(util.xml_parse_wrapper, change_model,
dev_id_info, newmodel)
def define_watchdog_model(self, dev_id_info, newval):
devtype = "watchdog"
if not self._check_device_is_present(devtype, dev_id_info):
return
def change(doc, ctx):
dev_node = self._get_device_xml_nodes(ctx, devtype, dev_id_info)[0]
if newval:
dev_node.setProp("model", newval)
return doc.serialize()
return self._redefine(util.xml_parse_wrapper, change)
def define_watchdog_action(self, dev_id_info, newval):
devtype = "watchdog"
if not self._check_device_is_present(devtype, dev_id_info):
return
def change(doc, ctx):
dev_node = self._get_device_xml_nodes(ctx, devtype, dev_id_info)[0]
if newval:
dev_node.setProp("action", newval)
return doc.serialize()
return self._redefine(util.xml_parse_wrapper, change)
########################
# End XML Altering API #
########################
@ -2091,6 +2147,22 @@ class vmmDomainVirtinst(vmmDomainBase):
dev.model_type = newmodel
self._redefine(change_video_model)
def define_watchdog_model(self, dev_id_info, newval):
devtype = VirtualDevice.VIRTUAL_DEV_WATCHDOG
dev = self._get_device_xml_object(devtype, dev_id_info)
def change():
dev.model = newval
self._redefine(change)
def define_watchdog_action(self, dev_id_info, newval):
devtype = VirtualDevice.VIRTUAL_DEV_WATCHDOG
dev = self._get_device_xml_object(devtype, dev_id_info)
def change():
dev.action = newval
self._redefine(change)
# Helper functions
def _redefine(self, alter_func):
origxml = self.get_xml()
@ -2162,6 +2234,9 @@ class vmmDomainVirtinst(vmmDomainBase):
elif dev_type == VirtualDevice.VIRTUAL_DEV_VIDEO:
count = int(dev_id_info)
elif dev_type == VirtualDevice.VIRTUAL_DEV_WATCHDOG:
count = int(dev_id_info)
else:
raise RuntimeError(_("Unknown device type '%s'") % dev_type)

View File

@ -137,6 +137,36 @@ def build_sound_combo(vm, combo, no_default=False):
if len(dev_model) > 0:
combo.set_active(0)
def build_watchdogmodel_combo(vm, combo, no_default=False):
dev_model = gtk.ListStore(str)
combo.set_model(dev_model)
text = gtk.CellRendererText()
combo.pack_start(text, True)
combo.add_attribute(text, 'text', 0)
dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
for m in virtinst.VirtualWatchdog.MODELS:
if m == virtinst.VirtualAudio.MODEL_DEFAULT and no_default:
continue
dev_model.append([m])
if len(dev_model) > 0:
combo.set_active(0)
def build_watchdogaction_combo(vm, combo, no_default=False):
dev_model = gtk.ListStore(str, str)
combo.set_model(dev_model)
text = gtk.CellRendererText()
combo.pack_start(text, True)
combo.add_attribute(text, 'text', 1)
dev_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
for m in virtinst.VirtualWatchdog.ACTIONS:
if m == virtinst.VirtualWatchdog.ACTION_DEFAULT and no_default:
continue
dev_model.append([m, virtinst.VirtualWatchdog.get_action_desc(m)])
if len(dev_model) > 0:
combo.set_active(0)
def build_netmodel_combo(vm, combo):
dev_model = gtk.ListStore(str, str)
combo.set_model(dev_model)

View File

@ -2150,6 +2150,141 @@ to connect to the virtual machine.</property>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox12">
<property name="visible">True</property>
<property name="border_width">1</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkEventBox" id="page9-title">
<property name="visible">True</property>
<child>
<widget class="GtkLabel" id="label19">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="xpad">5</property>
<property name="ypad">6</property>
<property name="label" translatable="yes">&lt;span weight="heavy" size="xx-large" foreground="#FFF"&gt;Watchdog Device&lt;/span&gt;</property>
<property name="use_markup">True</property>
<property name="justify">fill</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox13">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkLabel" id="label24">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="xpad">20</property>
<property name="ypad">10</property>
<property name="label" translatable="yes">Please indicate what watchdog device type
and default action should be used.</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment18">
<property name="visible">True</property>
<property name="left_padding">20</property>
<property name="right_padding">15</property>
<child>
<widget class="GtkTable" id="table6">
<property name="visible">True</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<property name="column_spacing">12</property>
<property name="row_spacing">12</property>
<child>
<widget class="GtkComboBox" id="watchdog-model">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label26">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Model:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">watchdog-model</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label27">
<property name="visible">True</property>
<property name="label" translatable="yes">Ac_tion:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">watchdog-action</property>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="watchdog-action">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">9</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label11">
<property name="visible">True</property>
<property name="label">wdog</property>
</widget>
<packing>
<property name="position">10</property>
<property name="tab_fill">False</property>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox41">
<property name="visible">True</property>
@ -2160,7 +2295,7 @@ to connect to the virtual machine.</property>
<widget class="GtkAlignment" id="alignment95">
<property name="visible">True</property>
<child>
<widget class="GtkEventBox" id="page9-title">
<widget class="GtkEventBox" id="page10-title">
<property name="visible">True</property>
<child>
<widget class="GtkLabel" id="label247">
@ -2291,7 +2426,7 @@ to connect to the virtual machine.</property>
</child>
</widget>
<packing>
<property name="position">9</property>
<property name="position">10</property>
</packing>
</child>
<child>
@ -2300,7 +2435,7 @@ to connect to the virtual machine.</property>
<property name="label">finish</property>
</widget>
<packing>
<property name="position">9</property>
<property name="position">10</property>
<property name="tab_fill">False</property>
<property name="type">tab</property>
</packing>

View File

@ -2897,7 +2897,10 @@ I/O:</property>
<widget class="GtkLabel" id="label509">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Device model:</property>
<property name="yalign">0.47999998927116394</property>
<property name="label" translatable="yes">Device m_odel:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">network-model-combo</property>
</widget>
<packing>
<property name="top_attach">1</property>
@ -3377,7 +3380,9 @@ I/O:</property>
<widget class="GtkLabel" id="label452">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Device Model:</property>
<property name="label" translatable="yes">Device m_odel:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">sound-model-combo</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
@ -3804,6 +3809,157 @@ I/O:</property>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox12">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkFrame" id="frame15">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<widget class="GtkAlignment" id="alignment22">
<property name="visible">True</property>
<property name="top_padding">3</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkTable" id="table8">
<property name="visible">True</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<property name="column_spacing">8</property>
<property name="row_spacing">4</property>
<child>
<widget class="GtkLabel" id="label26">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">A_ction:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">watchdog-action-combo</property>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label27">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">M_odel:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">watchdog-model-combo</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox12">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<widget class="GtkComboBox" id="watchdog-model-combo">
<property name="visible">True</property>
<signal name="changed" handler="on_watchdog_model_combo_changed"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="watchdog-model-label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label">label</property>
<property name="selectable">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox13">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<widget class="GtkComboBox" id="watchdog-action-combo">
<property name="visible">True</property>
<signal name="changed" handler="on_watchdog_action_combo_changed"/>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="watchdog-action-label">
<property name="visible">True</property>
<property name="label">label</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="hostdev-title2">
<property name="visible">True</property>
<property name="label">&lt;b&gt;Watchdog&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">12</property>
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="position">13</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label25">
<property name="visible">True</property>
<property name="label">wdog</property>
</widget>
<packing>
<property name="position">13</property>
<property name="tab_fill">False</property>
<property name="type">tab</property>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>