summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCole Robinson <crobinso@redhat.com>2014-03-22 14:34:23 -0400
committerCole Robinson <crobinso@redhat.com>2014-03-22 16:48:00 -0400
commiteee5061af89b35ee718280441aa244e8f6825677 (patch)
treec402c28f168a33336a099e306ed4551d297a37df
parent9050998028d89048044345b140710a219f89ca8d (diff)
downloadvirt-manager-eee5061af89b35ee718280441aa244e8f6825677.tar.gz
details: Rework all define and hotplug operations
Rather than register a bunch of functions to call, lump it all into one function per page. This allows us to easily call UpdateDevice unconditionally, to pick up any addition hotplug operations that become available via libvirt and qemu.
-rw-r--r--virtManager/details.py435
-rw-r--r--virtManager/domain.py625
2 files changed, 480 insertions, 580 deletions
diff --git a/virtManager/details.py b/virtManager/details.py
index e0ad25ab..c1833ae7 100644
--- a/virtManager/details.py
+++ b/virtManager/details.py
@@ -1410,12 +1410,10 @@ class vmmDetails(vmmGObjectUI):
str(e)))
def remove_xml_dev(self, src_ignore):
- info = self.get_hw_selection(HW_LIST_COL_DEVICE)
- if not info:
+ devobj = self.get_hw_selection(HW_LIST_COL_DEVICE)
+ if not devobj:
return
-
- devtype = info.virtual_device_type
- self.remove_device(devtype, info)
+ self.remove_device(devobj)
def set_pause_state(self, paused):
# Set pause widget states
@@ -1947,45 +1945,27 @@ class vmmDetails(vmmGObjectUI):
def edited(self, pagetype):
return pagetype in self.active_edits
- def make_apply_data(self):
- definefuncs = []
- defineargs = []
- hotplugfuncs = []
- hotplugargs = []
-
- def add_define(func, *args):
- definefuncs.append(func)
- defineargs.append(args)
- def add_hotplug(func, *args):
- hotplugfuncs.append(func)
- hotplugargs.append(args)
-
- return (definefuncs, defineargs, add_define,
- hotplugfuncs, hotplugargs, add_hotplug)
-
- # Overview section
def config_overview_apply(self):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ kwargs = {}
+ hotplug_args = {}
if self.edited(EDIT_NAME):
- name = self.widget("overview-name").get_text()
- add_define(self.vm.define_name, name)
+ # Renaming is pretty convoluted, so do it here synchronously
+ self.vm.define_name(self.widget("overview-name").get_text())
if self.edited(EDIT_TITLE):
- title = self.widget("overview-title").get_text()
- add_define(self.vm.define_title, title)
- add_hotplug(self.vm.hotplug_title, title)
+ kwargs["title"] = self.widget("overview-title").get_text()
+ hotplug_args["title"] = kwargs["title"]
if self.edited(EDIT_MACHTYPE):
- machtype = uiutil.get_combo_entry(self.widget("machine-type"))
- add_define(self.vm.define_machtype, machtype)
+ kwargs["machine"] = uiutil.get_combo_entry(
+ self.widget("machine-type"))
if self.edited(EDIT_DESC):
desc_widget = self.widget("overview-description")
- desc = desc_widget.get_buffer().get_property("text") or ""
- add_define(self.vm.define_description, desc)
- add_hotplug(self.vm.hotplug_description, desc)
+ kwargs["description"] = (
+ desc_widget.get_buffer().get_property("text") or "")
+ hotplug_args["description"] = kwargs["description"]
if self.edited(EDIT_IDMAP):
enable_idmap = self.widget("config-idmap-checkbutton").get_active()
@@ -1998,46 +1978,42 @@ class vmmDetails(vmmGObjectUI):
idmap_list = [uid_target, uid_count, gid_target, gid_count]
else:
idmap_list = None
+ kwargs["idmap_list"] = idmap_list
- add_define(self.vm.define_idmap, idmap_list)
+ return self._change_config_helper(self.vm.define_overview, kwargs,
+ hotplug_args=hotplug_args)
- return self._change_config_helper(df, da, hf, ha)
-
- # CPUs
def config_vcpus_apply(self):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
+ kwargs = {}
+ hotplug_args = {}
if self.edited(EDIT_VCPUS):
- vcpus = self.config_get_vcpus()
- maxv = self.config_get_maxvcpus()
- add_define(self.vm.define_vcpus, vcpus, maxv)
- add_hotplug(self.vm.hotplug_vcpus, vcpus)
+ kwargs["vcpus"] = self.config_get_vcpus()
+ kwargs["maxvcpus"] = self.config_get_maxvcpus()
+ hotplug_args["vcpus"] = kwargs["vcpus"]
if self.edited(EDIT_CPUSET):
- cpuset = self.get_text("config-vcpupin")
- add_define(self.vm.define_cpuset, cpuset)
+ kwargs["cpuset"] = self.get_text("config-vcpupin")
if self.edited(EDIT_CPU):
- val = self.get_config_cpu_model()
- add_define(self.vm.define_cpu, val)
+ kwargs["model"] = self.get_config_cpu_model()
if self.edited(EDIT_TOPOLOGY):
do_top = self.widget("cpu-topology-enable").get_active()
- sockets = self.widget("cpu-sockets").get_value()
- cores = self.widget("cpu-cores").get_value()
- threads = self.widget("cpu-threads").get_value()
+ kwargs["sockets"] = self.widget("cpu-sockets").get_value()
+ kwargs["cores"] = self.widget("cpu-cores").get_value()
+ kwargs["threads"] = self.widget("cpu-threads").get_value()
if not do_top:
- sockets = None
- cores = None
- threads = None
-
- add_define(self.vm.define_cpu_topology, sockets, cores, threads)
+ kwargs["sockets"] = None
+ kwargs["cores"] = None
+ kwargs["threads"] = None
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_cpu, kwargs,
+ hotplug_args=hotplug_args)
- # Memory
def config_memory_apply(self):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
+ kwargs = {}
+ hotplug_args = {}
if self.edited(EDIT_MEM):
curmem = None
@@ -2050,15 +2026,16 @@ class vmmDetails(vmmGObjectUI):
if maxmem:
maxmem = int(maxmem) * 1024
- add_define(self.vm.define_both_mem, curmem, maxmem)
- add_hotplug(self.vm.hotplug_both_mem, curmem, maxmem)
+ kwargs["memory"] = curmem
+ kwargs["maxmem"] = maxmem
+ hotplug_args["memory"] = kwargs["memory"]
+ hotplug_args["maxmem"] = kwargs["maxmem"]
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_memory, kwargs,
+ hotplug_args=hotplug_args)
- # Boot device / Autostart
def config_boot_options_apply(self):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ kwargs = {}
if self.edited(EDIT_AUTOSTART):
auto = self.widget("config-autostart")
@@ -2070,246 +2047,221 @@ class vmmDetails(vmmGObjectUI):
return False
if self.edited(EDIT_BOOTORDER):
- bootdevs = self.get_config_boot_order()
- add_define(self.vm.set_boot_order, bootdevs)
+ kwargs["boot_order"] = self.get_config_boot_order()
if self.edited(EDIT_BOOTMENU):
- bootmenu = self.widget("boot-menu").get_active()
- add_define(self.vm.set_boot_menu, bootmenu)
+ kwargs["boot_menu"] = self.widget("boot-menu").get_active()
if self.edited(EDIT_KERNEL):
- kernel = self.get_text("boot-kernel", checksens=True)
- initrd = self.get_text("boot-initrd", checksens=True)
- dtb = self.get_text("boot-dtb", checksens=True)
- args = self.get_text("boot-kernel-args", checksens=True)
+ kwargs["kernel"] = self.get_text("boot-kernel", checksens=True)
+ kwargs["initrd"] = self.get_text("boot-initrd", checksens=True)
+ kwargs["dtb"] = self.get_text("boot-dtb", checksens=True)
+ kwargs["kernel_args"] = self.get_text("boot-kernel-args",
+ checksens=True)
- if initrd and not kernel:
+ if kwargs["initrd"] and not kwargs["kernel"]:
return self.err.val_err(
_("Cannot set initrd without specifying a kernel path"))
- if args and not kernel:
+ if kwargs["kernel_args"] and not kwargs["kernel"]:
return self.err.val_err(
_("Cannot set kernel arguments without specifying a kernel path"))
- add_define(self.vm.set_boot_kernel, kernel, initrd, dtb, args)
-
if self.edited(EDIT_INIT):
- init = self.get_text("boot-init-path")
- if not init:
+ kwargs["init"] = self.get_text("boot-init-path")
+ if not kwargs["init"]:
return self.err.val_err(_("An init path must be specified"))
- add_define(self.vm.set_boot_init, init)
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_boot, kwargs)
- # CDROM
- def change_storage_media(self, dev_id_info, newpath):
- return self._change_config_helper(self.vm.define_storage_media,
- (dev_id_info, newpath),
- self.vm.hotplug_storage_media,
- (dev_id_info, newpath))
+ # <device> defining
+ def change_storage_media(self, devobj, newpath):
+ kwargs = {"path": newpath}
+ hotplug_args = {"storage_path": True}
- # Disk options
- def config_disk_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ return self._change_config_helper(self.vm.define_disk, kwargs,
+ devobj=devobj,
+ hotplug_args=hotplug_args)
+
+ def config_disk_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_DISK_RO):
- do_readonly = self.widget("disk-readonly").get_active()
- add_define(self.vm.define_disk_readonly, dev_id_info, do_readonly)
+ kwargs["readonly"] = self.widget("disk-readonly").get_active()
if self.edited(EDIT_DISK_SHARE):
- do_shareable = self.widget("disk-shareable").get_active()
- add_define(self.vm.define_disk_shareable,
- dev_id_info, do_shareable)
+ kwargs["shareable"] = self.widget("disk-shareable").get_active()
if self.edited(EDIT_DISK_REMOVABLE):
- do_removable = bool(self.widget("disk-removable").get_active())
- add_define(self.vm.define_disk_removable, dev_id_info, do_removable)
+ kwargs["removeable"] = bool(
+ self.widget("disk-removable").get_active())
if self.edited(EDIT_DISK_CACHE):
- cache = uiutil.get_combo_entry(self.widget("disk-cache"))
- add_define(self.vm.define_disk_cache, dev_id_info, cache)
+ kwargs["cache"] = uiutil.get_combo_entry(self.widget("disk-cache"))
if self.edited(EDIT_DISK_IO):
- io = uiutil.get_combo_entry(self.widget("disk-io"))
- add_define(self.vm.define_disk_io, dev_id_info, io)
+ kwargs["io"] = uiutil.get_combo_entry(self.widget("disk-io"))
if self.edited(EDIT_DISK_FORMAT):
- fmt = uiutil.get_combo_entry(self.widget("disk-format"))
- add_define(self.vm.define_disk_driver_type, dev_id_info, fmt)
+ kwargs["driver_type"] = uiutil.get_combo_entry(
+ self.widget("disk-format"))
if self.edited(EDIT_DISK_SERIAL):
- serial = self.get_text("disk-serial")
- add_define(self.vm.define_disk_serial, dev_id_info, serial)
+ kwargs["serial"] = self.get_text("disk-serial")
if self.edited(EDIT_DISK_IOTUNE):
- iotune_rbs = int(self.widget("disk-iotune-rbs").get_value() * 1024)
- iotune_ris = int(self.widget("disk-iotune-ris").get_value())
- iotune_tbs = int(self.widget("disk-iotune-tbs").get_value() * 1024)
- iotune_tis = int(self.widget("disk-iotune-tis").get_value())
- iotune_wbs = int(self.widget("disk-iotune-wbs").get_value() * 1024)
- iotune_wis = int(self.widget("disk-iotune-wis").get_value())
-
- add_define(self.vm.define_disk_iotune_rbs, dev_id_info, iotune_rbs)
- add_define(self.vm.define_disk_iotune_ris, dev_id_info, iotune_ris)
- add_define(self.vm.define_disk_iotune_tbs, dev_id_info, iotune_tbs)
- add_define(self.vm.define_disk_iotune_tis, dev_id_info, iotune_tis)
- add_define(self.vm.define_disk_iotune_wbs, dev_id_info, iotune_wbs)
- add_define(self.vm.define_disk_iotune_wis, dev_id_info, iotune_wis)
-
- # Do this last since it can change uniqueness info of the dev
+ kwargs["iotune_rbs"] = int(
+ self.widget("disk-iotune-rbs").get_value() * 1024)
+ kwargs["iotune_ris"] = int(
+ self.widget("disk-iotune-ris").get_value())
+ kwargs["iotune_tbs"] = int(
+ self.widget("disk-iotune-tbs").get_value() * 1024)
+ kwargs["iotune_tis"] = int(
+ self.widget("disk-iotune-tis").get_value())
+ kwargs["iotune_wbs"] = int(
+ self.widget("disk-iotune-wbs").get_value() * 1024)
+ kwargs["iotune_wis"] = int(
+ self.widget("disk-iotune-wis").get_value())
+
if self.edited(EDIT_DISK_BUS):
bus = uiutil.get_combo_entry(self.widget("disk-bus"))
addr = None
if bus == "spapr-vscsi":
bus = "scsi"
addr = "spapr-vio"
- add_define(self.vm.define_disk_bus, dev_id_info, bus, addr)
- return self._change_config_helper(df, da, hf, ha)
+ kwargs["bus"] = bus
+ kwargs["addrstr"] = addr
- # Audio options
- def config_sound_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ return self._change_config_helper(self.vm.define_disk, kwargs,
+ devobj=devobj)
+
+ def config_sound_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_SOUND_MODEL):
model = uiutil.get_combo_entry(self.widget("sound-model"))
if model:
- add_define(self.vm.define_sound_model, dev_id_info, model)
+ kwargs["model"] = model
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_sound, kwargs,
+ devobj=devobj)
- # Smartcard options
- def config_smartcard_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ def config_smartcard_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_SMARTCARD_MODE):
model = uiutil.get_combo_entry(self.widget("smartcard-mode"))
if model:
- add_define(self.vm.define_smartcard_mode, dev_id_info, model)
+ kwargs["model"] = model
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_smartcard, kwargs,
+ devobj=devobj)
- # Network options
- def config_network_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ def config_network_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_NET_MODEL):
model = uiutil.get_combo_entry(self.widget("network-model"))
- addr = None
+ addrstr = None
if model == "spapr-vlan":
- addr = "spapr-vio"
- add_define(self.vm.define_network_model, dev_id_info, model, addr)
+ addrstr = "spapr-vio"
+ kwargs["model"] = model
+ kwargs["addrstr"] = addrstr
if self.edited(EDIT_NET_SOURCE):
- nettype, source, mode = self.netlist.get_network_selection()
- add_define(self.vm.define_network_source, dev_id_info,
- nettype, source, mode)
+ kwargs["ntype"], kwargs["source"], kwargs["mode"] = (
+ self.netlist.get_network_selection())
if self.edited(EDIT_NET_VPORT):
- (vport_type, vport_managerid, vport_typeid,
- vport_idver, vport_instid) = self.netlist.get_vport()
+ (kwargs["vtype"], kwargs["managerid"],
+ kwargs["typeid"], kwargs["typeidversion"],
+ kwargs["instanceid"]) = self.netlist.get_vport()
- add_define(self.vm.define_virtualport, dev_id_info,
- vport_type, vport_managerid, vport_typeid,
- vport_idver, vport_instid)
-
- return self._change_config_helper(df, da, hf, ha)
-
- # Graphics options
- def config_graphics_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
+ return self._change_config_helper(self.vm.define_network, kwargs,
+ devobj)
+ def config_graphics_apply(self, devobj):
(gtype, port,
tlsport, addr, passwd, keymap) = self.gfxdetails.get_values()
- if self.edited(EDIT_GFX_PASSWD):
- add_define(self.vm.define_graphics_password, dev_id_info, passwd)
- add_hotplug(self.vm.hotplug_graphics_password, dev_id_info,
- passwd)
+ kwargs = {}
+ if self.edited(EDIT_GFX_PASSWD):
+ kwargs["passwd"] = passwd
if self.edited(EDIT_GFX_ADDRESS):
- add_define(self.vm.define_graphics_address, dev_id_info, addr)
+ kwargs["listen"] = addr
if self.edited(EDIT_GFX_KEYMAP):
- add_define(self.vm.define_graphics_keymap, dev_id_info, keymap)
+ kwargs["keymap"] = keymap
if self.edited(EDIT_GFX_PORT):
- add_define(self.vm.define_graphics_port, dev_id_info, port)
+ kwargs["port"] = port
if self.edited(EDIT_GFX_TLSPORT):
- add_define(self.vm.define_graphics_tlsport, dev_id_info, tlsport)
-
- # Do this last since it can change graphics unique ID
+ kwargs["tlsport"] = tlsport
if self.edited(EDIT_GFX_TYPE):
- add_define(self.vm.define_graphics_type, dev_id_info, gtype)
+ kwargs["gtype"] = gtype
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_graphics, kwargs,
+ devobj=devobj)
- # Video options
- def config_video_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ def config_video_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_VIDEO_MODEL):
model = uiutil.get_combo_entry(self.widget("video-model"))
if model:
- add_define(self.vm.define_video_model, dev_id_info, model)
+ kwargs["model"] = model
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_video, kwargs,
+ devobj=devobj)
- # Controller options
- def config_controller_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ def config_controller_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_CONTROLLER_MODEL):
model = uiutil.get_combo_entry(self.widget("controller-model"))
if model:
- add_define(self.vm.define_controller_model, dev_id_info, model)
+ kwargs["model"] = model
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_controller,
+ kwargs, devobj=devobj)
- # Watchdog options
- def config_watchdog_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ def config_watchdog_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_WATCHDOG_MODEL):
- model = uiutil.get_combo_entry(self.widget("watchdog-model"))
- add_define(self.vm.define_watchdog_model, dev_id_info, model)
+ kwargs["model"] = uiutil.get_combo_entry(
+ self.widget("watchdog-model"))
if self.edited(EDIT_WATCHDOG_ACTION):
- action = uiutil.get_combo_entry(self.widget("watchdog-action"))
- add_define(self.vm.define_watchdog_action, dev_id_info, action)
+ kwargs["action"] = uiutil.get_combo_entry(
+ self.widget("watchdog-action"))
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_watchdog, kwargs,
+ devobj=devobj)
- # Filesystem options
- def config_filesystem_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ def config_filesystem_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_FS):
if self.fsDetails.validate_page_filesystem() is False:
return False
- add_define(self.vm.define_filesystem, dev_id_info,
- self.fsDetails.get_dev())
+ kwargs["newdev"] = self.fsDetails.get_dev()
- return self._change_config_helper(df, da, hf, ha)
+ return self._change_config_helper(self.vm.define_filesystem,
+ kwargs, devobj=devobj)
- def config_hostdev_apply(self, dev_id_info):
- df, da, add_define, hf, ha, add_hotplug = self.make_apply_data()
- ignore = add_hotplug
+ def config_hostdev_apply(self, devobj):
+ kwargs = {}
if self.edited(EDIT_HOSTDEV_ROMBAR):
- add_define(self.vm.define_hostdev_rombar, dev_id_info,
- self.widget("hostdev-rombar").get_active())
+ kwargs["rom_bar"] = self.widget("hostdev-rombar").get_active()
+
+ return self._change_config_helper(self.vm.define_hostdev, kwargs,
+ devobj=devobj)
- return self._change_config_helper(df, da, hf, ha)
# Device removal
- def remove_device(self, dev_type, dev_id_info):
- logging.debug("Removing device: %s %s", dev_type, dev_id_info)
+ def remove_device(self, devobj):
+ logging.debug("Removing device: %s", devobj)
if not self.err.chkbox_helper(self.config.get_confirm_removedev,
self.config.set_confirm_removedev,
@@ -2318,7 +2270,7 @@ class vmmDetails(vmmGObjectUI):
# Define the change
try:
- self.vm.remove_device(dev_id_info)
+ self.vm.remove_device(devobj)
except Exception, e:
self.err.show_err(_("Error Removing Device: %s" % str(e)))
return
@@ -2327,7 +2279,7 @@ class vmmDetails(vmmGObjectUI):
detach_err = False
try:
if self.vm.is_active():
- self.vm.detach_device(dev_id_info)
+ self.vm.detach_device(devobj)
except Exception, e:
logging.debug("Device could not be hotUNplugged: %s", str(e))
detach_err = (str(e), "".join(traceback.format_exc()))
@@ -2344,47 +2296,18 @@ class vmmDetails(vmmGObjectUI):
buttons=Gtk.ButtonsType.OK,
dialog_type=Gtk.MessageType.INFO)
- # Generic config change helpers
- def _change_config_helper(self,
- define_funcs, define_funcs_args,
- hotplug_funcs=None, hotplug_funcs_args=None):
- """
- Requires at least a 'define' function and arglist to be specified
- (a function where we change the inactive guest config).
-
- Arguments can be a single arg or a list or appropriate arg type (e.g.
- a list of functions for define_funcs)
- """
- define_funcs = util.listify(define_funcs)
- define_funcs_args = util.listify(define_funcs_args)
- hotplug_funcs = util.listify(hotplug_funcs)
- hotplug_funcs_args = util.listify(hotplug_funcs_args)
-
- hotplug_err = []
- active = self.vm.is_active()
-
- # Hotplug change
- func = None
- if active and hotplug_funcs:
- for idx in range(len(hotplug_funcs)):
- func = hotplug_funcs[idx]
- args = hotplug_funcs_args[idx]
- try:
- func(*args)
- except Exception, e:
- logging.debug("Hotplug failed: func=%s: %s",
- func, str(e))
- hotplug_err.append((str(e),
- "".join(traceback.format_exc())))
+ def _change_config_helper(self, define_func, define_args,
+ devobj=None,
+ hotplug_args=None):
+ hotplug_args = hotplug_args or {}
# Persistent config change
try:
- for idx in range(len(define_funcs)):
- func = define_funcs[idx]
- args = define_funcs_args[idx]
- func(*args)
- if define_funcs:
- self.vm.redefine_cached()
+ if devobj:
+ define_func(devobj, False, **define_args)
+ else:
+ define_func(**define_args)
+ self.vm.redefine_cached()
except Exception, e:
self.err.show_err((_("Error changing VM configuration: %s") %
str(e)))
@@ -2392,20 +2315,33 @@ class vmmDetails(vmmGObjectUI):
self.vm.refresh_xml()
return False
+ # Hotplug change
+ hotplug_err = None
+ if self.vm.is_active():
+ try:
+ if devobj:
+ hotplug_args["device"] = define_func(
+ devobj, True, **define_args)
+ if hotplug_args:
+ self.vm.hotplug(**hotplug_args)
+ except Exception, e:
+ logging.debug("Hotplug failed: %s", str(e))
+ hotplug_err = ((str(e), "".join(traceback.format_exc())))
- if (hotplug_err or
- (active and not len(hotplug_funcs) == len(define_funcs))):
- if len(define_funcs) > 1:
+ if (hotplug_err or (self.vm.is_active() and not hotplug_args)):
+ if len(define_args) > 1:
msg = _("Some changes may require a guest shutdown "
"to take effect.")
else:
msg = _("These changes will take effect after "
"the next guest shutdown.")
- dtype = hotplug_err and Gtk.MessageType.WARNING or Gtk.MessageType.INFO
+ dtype = (hotplug_err and
+ Gtk.MessageType.WARNING or Gtk.MessageType.INFO)
hotplug_msg = ""
- for err1, tb in hotplug_err:
- hotplug_msg += (err1 + "\n\n" + tb + "\n")
+ if hotplug_err:
+ hotplug_msg += (hotplug_err[0] + "\n\n" +
+ hotplug_err[1] + "\n")
self.err.show_err(msg,
details=hotplug_msg,
@@ -2414,6 +2350,7 @@ class vmmDetails(vmmGObjectUI):
return True
+
########################
# Details page refresh #
########################
diff --git a/virtManager/domain.py b/virtManager/domain.py
index 37f8f35d..135706d2 100644
--- a/virtManager/domain.py
+++ b/virtManager/domain.py
@@ -51,6 +51,10 @@ vm_status_icons = {
}
+class _SENTINEL(object):
+ pass
+
+
def compare_device(origdev, newdev, idx):
devprops = {
"disk" : ["target", "bus"],
@@ -529,21 +533,20 @@ class vmmDomain(vmmLibvirtObject):
raise RuntimeError(_("Could not find specified device in the "
"inactive VM configuration: %s") % repr(origdev))
- def _redefine_device(self, cb, origdev):
- dev = self._lookup_device_to_define(origdev)
+ def _redefine_device(self, cb, origdev, use_live_device):
+ if not use_live_device:
+ dev = self._lookup_device_to_define(origdev)
+ else:
+ dev = origdev
if dev:
- return cb(dev)
+ cb(dev)
+ return dev
##############################
# Persistent XML change APIs #
##############################
- def define_name(self, newname):
- return self._define_name_helper("domain",
- self.conn.rename_vm,
- newname)
-
# Device Add/Remove
def add_device(self, devobj):
"""
@@ -573,107 +576,89 @@ class vmmDomain(vmmLibvirtObject):
guest.remove_device(rmcon)
guest.remove_device(editdev)
- return self._redefine_device(rmdev, devobj)
+ return self._redefine_device(rmdev, devobj, False)
ret = self._redefine(change)
self.redefine_cached()
return ret
- # CPU define methods
- def define_vcpus(self, vcpus, maxvcpus):
- def change(guest):
- guest.curvcpus = int(vcpus)
- guest.vcpus = int(maxvcpus)
- return self._redefine(change)
- def define_cpuset(self, cpuset):
- def change(guest):
- guest.cpuset = cpuset
- return self._redefine(change)
-
- def define_cpu_topology(self, sockets, cores, threads):
- def change(guest):
- cpu = guest.cpu
- cpu.sockets = sockets
- cpu.cores = cores
- cpu.threads = threads
- return self._redefine(change)
- def define_cpu(self, val):
+ def define_cpu(self, vcpus=_SENTINEL, maxvcpus=_SENTINEL,
+ cpuset=_SENTINEL, model=_SENTINEL, sockets=_SENTINEL,
+ cores=_SENTINEL, threads=_SENTINEL):
def change(guest):
- if val in guest.cpu.SPECIAL_MODES:
- guest.cpu.set_special_mode(val)
- else:
- guest.cpu.model = val
+ if vcpus != _SENTINEL:
+ guest.curvcpus = int(vcpus)
+ if maxvcpus != _SENTINEL:
+ guest.vcpus = int(maxvcpus)
+ if cpuset != _SENTINEL:
+ guest.cpuset = cpuset
+
+ if sockets != _SENTINEL:
+ guest.cpu.sockets = sockets
+ guest.cpu.cores = cores
+ guest.cpu.threads = threads
+
+ if model != _SENTINEL:
+ if model in guest.cpu.SPECIAL_MODES:
+ guest.cpu.set_special_mode(model)
+ else:
+ guest.cpu.model = model
return self._redefine(change)
- # Mem define methods
- def define_both_mem(self, memory, maxmem):
+ def define_memory(self, memory=_SENTINEL, maxmem=_SENTINEL):
def change(guest):
- guest.memory = int(memory)
- guest.maxmemory = int(maxmem)
+ if memory != _SENTINEL:
+ guest.memory = int(memory)
+ if maxmem != _SENTINEL:
+ guest.maxmemory = int(maxmem)
return self._redefine(change)
- # Machine config define methods
- def define_machtype(self, newvalue):
- def change(guest):
- guest.os.machine = newvalue
- return self._redefine(change)
+ def define_name(self, newname):
+ return self._define_name_helper("domain",
+ self.conn.rename_vm,
+ newname)
- def define_description(self, newvalue):
+ def define_overview(self, machine=_SENTINEL, description=_SENTINEL,
+ title=_SENTINEL, idmap_list=_SENTINEL):
def change(guest):
- guest.description = newvalue or None
- return self._redefine(change)
+ if machine != _SENTINEL:
+ guest.os.machine = machine
+ if description != _SENTINEL:
+ guest.description = description or None
+ if title != _SENTINEL:
+ guest.title = title or None
+
+ if idmap_list != _SENTINEL:
+ if idmap_list is not None:
+ # pylint: disable=unpacking-non-sequence
+ (uid_target, uid_count, gid_target, gid_count) = idmap_list
+ guest.idmap.uid_start = 0
+ guest.idmap.uid_target = uid_target
+ guest.idmap.uid_count = uid_count
+ guest.idmap.gid_start = 0
+ guest.idmap.gid_target = gid_target
+ guest.idmap.gid_count = gid_count
+ else:
+ guest.idmap.clear()
- def define_title(self, newvalue):
- def change(guest):
- guest.title = newvalue or None
return self._redefine(change)
- # Idmap config define methods
- def define_idmap(self, idmap_list):
- def change(guest):
- guest.idmap.uid_start = 0
- guest.idmap.uid_target = uid_target
- guest.idmap.uid_count = uid_count
- guest.idmap.gid_start = 0
- guest.idmap.gid_target = gid_target
- guest.idmap.gid_count = gid_count
- def clear(guest):
- guest.idmap.clear()
- if idmap_list is not None:
- (uid_target, uid_count, gid_target,
- gid_count) = idmap_list
- return self._redefine(change)
- else:
- return self._redefine(clear)
-
- # Boot define methods
- def can_use_device_boot_order(self):
- # Return 'True' if guest can use new style boot device ordering
- return self.conn.check_support(
- self.conn.SUPPORT_CONN_DEVICE_BOOTORDER)
+ def define_boot(self, boot_order=_SENTINEL, boot_menu=_SENTINEL,
+ kernel=_SENTINEL, initrd=_SENTINEL, dtb=_SENTINEL,
+ kernel_args=_SENTINEL, init=_SENTINEL):
- def get_bootable_devices(self):
- devs = self.get_disk_devices()
- devs += self.get_network_devices()
- devs += self.get_hostdev_devices()
+ def _change_boot_order(guest):
+ boot_dev_order = []
+ devmap = dict((dev.vmmidstr, dev) for dev in
+ self.get_bootable_devices())
+ for b in boot_order:
+ if b in devmap:
+ boot_dev_order.append(devmap[b])
- # redirdev can also be marked bootable, but it should be rarely
- # used and clutters the UI
- return devs
-
- def _set_device_boot_order(self, boot_list):
- boot_dev_order = []
- devmap = dict((dev.vmmidstr, dev) for dev in
- self.get_bootable_devices())
- for b in boot_list:
- if b in devmap:
- boot_dev_order.append(devmap[b])
-
- def change(guest):
# Unset the traditional boot order
guest.os.bootorder = []
- # Unset standard boot order
+ # Unset device boot order
for dev in guest.get_all_devices():
dev.boot.order = None
@@ -685,72 +670,44 @@ class vmmDomain(vmmLibvirtObject):
dev.boot.order = count
count += 1
- return self._redefine(change)
-
- def set_boot_order(self, boot_list):
- if self.can_use_device_boot_order():
- return self._set_device_boot_order(boot_list)
-
- def change(guest):
- guest.os.bootorder = boot_list
- return self._redefine(change)
- def set_boot_menu(self, newval):
- def change(guest):
- guest.os.enable_bootmenu = bool(newval)
- return self._redefine(change)
- def set_boot_kernel(self, kernel, initrd, dtb, args):
def change(guest):
- guest.os.kernel = kernel or None
- guest.os.initrd = initrd or None
- guest.os.dtb = dtb or None
- guest.os.kernel_args = args or None
- return self._redefine(change)
- def set_boot_init(self, init):
- def change(guest):
- guest.os.init = init
+ if boot_order != _SENTINEL:
+ if self.can_use_device_boot_order():
+ _change_boot_order(guest)
+ else:
+ guest.os.bootorder = boot_order
+
+ if boot_menu != _SENTINEL:
+ guest.os.enable_bootmenu = bool(boot_menu)
+ if init != _SENTINEL:
+ guest.os.init = init
+
+ if kernel != _SENTINEL:
+ guest.os.kernel = kernel or None
+ if initrd != _SENTINEL:
+ guest.os.initrd = initrd or None
+ if dtb != _SENTINEL:
+ guest.os.dtb = dtb or None
+ if kernel_args != _SENTINEL:
+ guest.os.kernel_args = kernel_args or None
return self._redefine(change)
- # Disk define methods
- def define_storage_media(self, devobj, newpath):
- def change(editdev):
- editdev.path = newpath
- editdev.sync_path_props()
- return self._redefine_device(change, devobj)
- def define_disk_readonly(self, devobj, do_readonly):
- def change(editdev):
- editdev.read_only = do_readonly
- return self._redefine_device(change, devobj)
- def define_disk_shareable(self, devobj, do_shareable):
- def change(editdev):
- editdev.shareable = do_shareable
- return self._redefine_device(change, devobj)
- def define_disk_removable(self, devobj, do_removable):
- def change(editdev):
- editdev.removable = do_removable
- return self._redefine_device(change, devobj)
- def define_disk_cache(self, devobj, new_cache):
- def change(editdev):
- editdev.driver_cache = new_cache or None
- return self._redefine_device(change, devobj)
- def define_disk_io(self, devobj, val):
- def change(editdev):
- editdev.driver_io = val or None
- return self._redefine_device(change, devobj)
- def define_disk_driver_type(self, devobj, new_driver_type):
- def change(editdev):
- editdev.driver_type = new_driver_type or None
- return self._redefine_device(change, devobj)
- def define_disk_bus(self, devobj, newval, addr):
- def change(editdev):
+ def define_disk(self, devobj, use_live_device,
+ path=_SENTINEL, readonly=_SENTINEL, serial=_SENTINEL,
+ shareable=_SENTINEL, removable=_SENTINEL, cache=_SENTINEL,
+ io=_SENTINEL, driver_type=_SENTINEL, bus=_SENTINEL, addrstr=_SENTINEL,
+ iotune_rbs=_SENTINEL, iotune_ris=_SENTINEL, iotune_tbs=_SENTINEL,
+ iotune_tis=_SENTINEL, iotune_wbs=_SENTINEL, iotune_wis=_SENTINEL):
+ def _change_bus(editdev):
oldprefix = editdev.get_target_prefix()[0]
oldbus = editdev.bus
- editdev.bus = newval
+ editdev.bus = bus
- if oldbus == newval:
+ if oldbus == bus:
return
editdev.address.clear()
- editdev.address.set_addrstr(addr)
+ editdev.address.set_addrstr(addrstr)
if oldprefix == editdev.get_target_prefix()[0]:
return
@@ -766,114 +723,107 @@ class vmmDomain(vmmLibvirtObject):
editdev.target = None
editdev.generate_target(used)
- return self._redefine_device(change, devobj)
- def define_disk_serial(self, devobj, val):
- def change(editdev):
- if val != editdev.serial:
- editdev.serial = val or None
- return self._redefine_device(change, devobj)
- def define_disk_iotune_rbs(self, devobj, val):
def change(editdev):
- editdev.iotune_rbs = val
- return self._redefine_device(change, devobj)
+ if path != _SENTINEL:
+ editdev.path = path
+ if not use_live_device:
+ editdev.sync_path_props()
+
+ if readonly != _SENTINEL:
+ editdev.read_only = readonly
+ if shareable != _SENTINEL:
+ editdev.shareable = shareable
+ if removable != _SENTINEL:
+ editdev.removable = removable
+
+ if cache != _SENTINEL:
+ editdev.driver_cache = cache or None
+ if io != _SENTINEL:
+ editdev.driver_io = io or None
+ if driver_type != _SENTINEL:
+ editdev.driver_type = driver_type or None
+ if serial != _SENTINEL:
+ editdev.serial = serial or None
+
+ if iotune_rbs != _SENTINEL:
+ editdev.iotune_rbs = iotune_rbs
+ if iotune_ris != _SENTINEL:
+ editdev.iotune_ris = iotune_ris
+ if iotune_tbs != _SENTINEL:
+ editdev.iotune_tbs = iotune_tbs
+ if iotune_tis != _SENTINEL:
+ editdev.iotune_tis = iotune_tis
+ if iotune_wbs != _SENTINEL:
+ editdev.iotune_wbs = iotune_wbs
+ if iotune_wis != _SENTINEL:
+ editdev.iotune_wis = iotune_wis
+
+ if bus != _SENTINEL:
+ _change_bus(editdev)
+
+ return self._redefine_device(change, devobj, use_live_device)
+
+ def define_network(self, devobj, use_live_device,
+ ntype=_SENTINEL, source=_SENTINEL,
+ mode=_SENTINEL, model=_SENTINEL, addrstr=_SENTINEL,
+ vtype=_SENTINEL, managerid=_SENTINEL, typeid=_SENTINEL,
+ typeidversion=_SENTINEL, instanceid=_SENTINEL):
- def define_disk_iotune_ris(self, devobj, val):
def change(editdev):
- editdev.iotune_ris = val
- return self._redefine_device(change, devobj)
-
- def define_disk_iotune_tbs(self, devobj, val):
+ if ntype != _SENTINEL:
+ editdev.source = None
+
+ editdev.type = ntype
+ editdev.source = source
+ editdev.source_mode = mode or None
+
+ if model != _SENTINEL:
+ if editdev.model != model:
+ editdev.address.clear()
+ editdev.address.set_addrstr(addrstr)
+ editdev.model = model
+
+ if vtype != _SENTINEL:
+ editdev.virtualport.type = vtype or None
+ editdev.virtualport.managerid = managerid or None
+ editdev.virtualport.typeid = typeid or None
+ editdev.virtualport.typeidversion = typeidversion or None
+ editdev.virtualport.instanceid = instanceid or None
+ return self._redefine_device(change, devobj, use_live_device)
+
+ def define_graphics(self, devobj, use_live_device,
+ listen=_SENTINEL, port=_SENTINEL, tlsport=_SENTINEL,
+ passwd=_SENTINEL, keymap=_SENTINEL, gtype=_SENTINEL):
def change(editdev):
- editdev.iotune_tbs = val
- return self._redefine_device(change, devobj)
-
- def define_disk_iotune_tis(self, devobj, val):
+ if listen != _SENTINEL:
+ editdev.listen = listen
+ if port != _SENTINEL:
+ editdev.port = port
+ if tlsport != _SENTINEL:
+ editdev.tlsPort = tlsport
+ if passwd != _SENTINEL:
+ editdev.passwd = passwd
+ if keymap != _SENTINEL:
+ editdev.keymap = keymap
+ if gtype != _SENTINEL:
+ editdev.type = gtype
+ return self._redefine_device(change, devobj, use_live_device)
+
+ def define_sound(self, devobj, use_live_device, model=_SENTINEL):
def change(editdev):
- editdev.iotune_tis = val
- return self._redefine_device(change, devobj)
+ if model != _SENTINEL:
+ if editdev.model != model:
+ editdev.address.clear()
+ editdev.model = model
+ return self._redefine_device(change, devobj, use_live_device)
- def define_disk_iotune_wbs(self, devobj, val):
+ def define_video(self, devobj, use_live_device, model=_SENTINEL):
def change(editdev):
- editdev.iotune_wbs = val
- return self._redefine_device(change, devobj)
-
- def define_disk_iotune_wis(self, devobj, val):
- def change(editdev):
- editdev.iotune_wis = val
- return self._redefine_device(change, devobj)
-
-
- # Network define methods
- def define_network_source(self, devobj, newtype, newsource, newmode):
- def change(editdev):
- if not newtype:
+ if model == _SENTINEL or model == editdev.model:
return
- editdev.source = None
- editdev.type = newtype
- editdev.source = newsource
- editdev.source_mode = newmode or None
- return self._redefine_device(change, devobj)
- def define_network_model(self, devobj, newmodel, addr):
- def change(editdev):
- if editdev.model != newmodel:
- editdev.address.clear()
- editdev.address.set_addrstr(addr)
- editdev.model = newmodel
- return self._redefine_device(change, devobj)
-
- def define_virtualport(self, devobj, newtype, newmanagerid,
- newtypeid, newtypeidversion, newinstanceid):
- def change(editdev):
- editdev.virtualport.type = newtype or None
- editdev.virtualport.managerid = newmanagerid or None
- editdev.virtualport.typeid = newtypeid or None
- editdev.virtualport.typeidversion = newtypeidversion or None
- editdev.virtualport.instanceid = newinstanceid or None
- return self._redefine_device(change, devobj)
-
- # Graphics define methods
- def define_graphics_address(self, devobj, newval):
- def change(editdev):
- editdev.listen = newval
- return self._redefine_device(change, devobj)
- def define_graphics_port(self, devobj, newval):
- def change(editdev):
- editdev.port = newval
- return self._redefine_device(change, devobj)
- def define_graphics_tlsport(self, devobj, newval):
- def change(editdev):
- editdev.tlsPort = newval
- return self._redefine_device(change, devobj)
- def define_graphics_password(self, devobj, newval):
- def change(editdev):
- editdev.passwd = newval
- return self._redefine_device(change, devobj)
- def define_graphics_keymap(self, devobj, newval):
- def change(editdev):
- editdev.keymap = newval
- return self._redefine_device(change, devobj)
- def define_graphics_type(self, devobj, newval):
- def change(editdev):
- editdev.type = newval
- return self._redefine_device(change, devobj)
-
- # Sound define methods
- def define_sound_model(self, devobj, newmodel):
- def change(editdev):
- if editdev.model != newmodel:
- editdev.address.clear()
- editdev.model = newmodel
- return self._redefine_device(change, devobj)
-
- # Video define methods
- def define_video_model(self, devobj, newmodel):
- def change(editdev):
- if newmodel == editdev.model:
- return
-
- editdev.model = newmodel
+ editdev.model = model
editdev.address.clear()
# Clear out heads/ram values so they reset to default. If
@@ -883,32 +833,29 @@ class vmmDomain(vmmLibvirtObject):
editdev.heads = None
editdev.ram = None
- return self._redefine_device(change, devobj)
+ return self._redefine_device(change, devobj, use_live_device)
- # Watchdog define methods
- def define_watchdog_model(self, devobj, newval):
+ def define_watchdog(self, devobj, use_live_device,
+ model=_SENTINEL, action=_SENTINEL):
def change(editdev):
- if editdev.model != newval:
- editdev.address.clear()
- editdev.model = newval
- return self._redefine_device(change, devobj)
- def define_watchdog_action(self, devobj, newval):
- def change(editdev):
- editdev.action = newval
- return self._redefine_device(change, devobj)
+ if model != _SENTINEL:
+ if editdev.model != model:
+ editdev.address.clear()
+ editdev.model = model
- # Smartcard define methods
- def define_smartcard_mode(self, devobj, newmodel):
- def change(editdev):
- editdev.mode = newmodel
- editdev.type = editdev.TYPE_DEFAULT
- return self._redefine_device(change, devobj)
+ if action != _SENTINEL:
+ editdev.action = action
+ return self._redefine_device(change, devobj, use_live_device)
- # Controller define methods
- def define_controller_model(self, devobj, newmodel):
+ def define_smartcard(self, devobj, use_live_device, model=_SENTINEL):
def change(editdev):
- ignore = editdev
+ if model != _SENTINEL:
+ editdev.mode = model
+ editdev.type = editdev.TYPE_DEFAULT
+ return self._redefine_device(change, devobj, use_live_device)
+ def define_controller(self, devobj, use_live_device, model=_SENTINEL):
+ def _change_model(editdev):
if editdev.type == "usb":
guest = self._get_xmlobj_to_define()
ctrls = guest.get_devices("controller")
@@ -917,27 +864,36 @@ class vmmDomain(vmmLibvirtObject):
for dev in ctrls:
guest.remove_device(dev)
- if newmodel == "ich9-ehci1":
+ if model == "ich9-ehci1":
for dev in VirtualController.get_usb2_controllers(
guest.conn):
guest.add_device(dev)
else:
dev = VirtualController(guest.conn)
dev.type = "usb"
- if newmodel != "default":
- dev.model = newmodel
+ if model != "default":
+ dev.model = model
guest.add_device(dev)
+
elif editdev.type == "scsi":
- if newmodel == "default":
+ if model == "default":
editdev.model = None
else:
- editdev.model = newmodel
- self.update_device(editdev)
+ editdev.model = model
+ self.hotplug(device=editdev)
- return self._redefine_device(change, devobj)
+ def change(editdev):
+ if model != _SENTINEL:
+ _change_model(editdev)
+
+ return self._redefine_device(change, devobj, use_live_device)
- def define_filesystem(self, devobj, newdev):
+ def define_filesystem(self, devobj, use_live_device, newdev=_SENTINEL):
def change(editdev):
+ if newdev == _SENTINEL:
+ return
+
+ # pylint: disable=maybe-no-member
editdev.type = newdev.type
editdev.mode = newdev.mode
editdev.wrpolicy = newdev.wrpolicy
@@ -948,12 +904,14 @@ class vmmDomain(vmmLibvirtObject):
editdev.source = newdev.source
editdev.target = newdev.target
- return self._redefine_device(change, devobj)
+ return self._redefine_device(change, devobj, use_live_device)
- def define_hostdev_rombar(self, devobj, val):
+
+ def define_hostdev(self, devobj, use_live_device, rom_bar=_SENTINEL):
def change(editdev):
- editdev.rom_bar = val
- return self._redefine_device(change, devobj)
+ if rom_bar != _SENTINEL:
+ editdev.rom_bar = rom_bar
+ return self._redefine_device(change, devobj, use_live_device)
####################
@@ -980,79 +938,70 @@ class vmmDomain(vmmLibvirtObject):
xml = devobj.get_xml_config()
self._backend.detachDevice(xml)
- def update_device(self, devobj, flags=1):
- if not self.is_active():
- return
+ def _update_device(self, devobj, flags=None):
+ if flags is None:
+ flags = getattr(libvirt, "VIR_DOMAIN_DEVICE_MODIFY_LIVE", 1)
- # Default flag is VIR_DOMAIN_DEVICE_MODIFY_LIVE
xml = devobj.get_xml_config()
+ logging.debug("Calling update_device with xml=\n%s", xml)
self._backend.updateDeviceFlags(xml, flags)
- def hotplug_vcpus(self, vcpus):
- vcpus = int(vcpus)
- if vcpus != self.vcpu_count():
- self._backend.setVcpus(vcpus)
+ def hotplug(self, vcpus=_SENTINEL, memory=_SENTINEL, maxmem=_SENTINEL,
+ description=_SENTINEL, title=_SENTINEL, storage_path=_SENTINEL,
+ device=_SENTINEL):
+ if not self.is_active():
+ return
+
+ def _hotplug_memory(val):
+ if val != self.get_memory():
+ self._backend.setMemory(val)
+ def _hotplug_maxmem(val):
+ if val != self.maximum_memory():
+ self._backend.setMaxMemory(val)
- def hotplug_memory(self, memory):
- if memory != self.get_memory():
- self._backend.setMemory(memory)
+ def _hotplug_metadata(val, mtype):
+ if not self.conn.check_support(
+ self.conn.SUPPORT_DOMAIN_SET_METADATA, self._backend):
+ return
+ flags = (libvirt.VIR_DOMAIN_AFFECT_LIVE |
+ libvirt.VIR_DOMAIN_AFFECT_CONFIG)
+ self._backend.setMetadata(mtype, val, None, None, flags)
- def hotplug_maxmem(self, maxmem):
- if maxmem != self.maximum_memory():
- self._backend.setMaxMemory(maxmem)
+ if vcpus != _SENTINEL:
+ vcpus = int(vcpus)
+ if vcpus != self.vcpu_count():
+ self._backend.setVcpus(vcpus)
- def hotplug_both_mem(self, memory, maxmem):
- logging.info("Hotplugging curmem=%s maxmem=%s for VM '%s'",
- memory, maxmem, self.get_name())
+ if memory != _SENTINEL:
+ logging.info("Hotplugging curmem=%s maxmem=%s for VM '%s'",
+ memory, maxmem, self.get_name())
- if self.is_active():
actual_cur = self.get_memory()
if memory:
if maxmem < actual_cur:
# Set current first to avoid error
- self.hotplug_memory(memory)
- self.hotplug_maxmem(maxmem)
+ _hotplug_memory(memory)
+ _hotplug_maxmem(maxmem)
else:
- self.hotplug_maxmem(maxmem)
- self.hotplug_memory(memory)
+ _hotplug_maxmem(maxmem)
+ _hotplug_memory(memory)
else:
- self.hotplug_maxmem(maxmem)
-
- def hotplug_storage_media(self, devobj, newpath):
- devobj.path = newpath
- self.attach_device(devobj)
-
- def hotplug_graphics_password(self, devobj, newval):
- devobj.passwd = newval
- self.update_device(devobj)
-
- def hotplug_description(self, desc):
- # We already fake hotplug like behavior, by reading the
- # description from the inactive XML from a running VM
- #
- # libvirt since 0.9.10 provides a SetMetadata API that provides
- # actual <description> 'hotplug', and using that means checking
- # for support, version, etc.
- if not self.conn.check_support(
- self.conn.SUPPORT_DOMAIN_SET_METADATA, self._backend):
- return
+ _hotplug_maxmem(maxmem)
- flags = (libvirt.VIR_DOMAIN_AFFECT_LIVE |
- libvirt.VIR_DOMAIN_AFFECT_CONFIG)
- self._backend.setMetadata(
- libvirt.VIR_DOMAIN_METADATA_DESCRIPTION,
- desc, None, None, flags)
+ if description != _SENTINEL:
+ _hotplug_metadata(description,
+ libvirt.VIR_DOMAIN_METADATA_DESCRIPTION)
+ if title != _SENTINEL:
+ _hotplug_metadata(title, libvirt.VIR_DOMAIN_METADATA_TITLE)
- def hotplug_title(self, title):
- if not self.conn.check_support(
- self.conn.SUPPORT_DOMAIN_SET_METADATA, self._backend):
- return
+ if storage_path != _SENTINEL:
+ # qemu originally only supported attach_device for updating
+ # a device's path. Stick with that. We may need to differentiate
+ # for other drivers that don't maintain back compat though
+ self.attach_device(device)
- flags = (libvirt.VIR_DOMAIN_AFFECT_LIVE |
- libvirt.VIR_DOMAIN_AFFECT_CONFIG)
- self._backend.setMetadata(
- libvirt.VIR_DOMAIN_METADATA_TITLE,
- title, None, None, flags)
+ elif device != _SENTINEL:
+ self._update_device(device)
########################
@@ -1303,6 +1252,20 @@ class vmmDomain(vmmLibvirtObject):
return devs
+ def can_use_device_boot_order(self):
+ # Return 'True' if guest can use new style boot device ordering
+ return self.conn.check_support(
+ self.conn.SUPPORT_CONN_DEVICE_BOOTORDER)
+
+ def get_bootable_devices(self):
+ devs = self.get_disk_devices()
+ devs += self.get_network_devices()
+ devs += self.get_hostdev_devices()
+
+ # redirdev can also be marked bootable, but it should be rarely
+ # used and clutters the UI
+ return devs
+
############################
# Domain lifecycle methods #