From 7003a3a52821e2813d41989ab7a88d2b7aa590f1 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Fri, 17 Jan 2014 15:32:40 -0500 Subject: [PATCH] prefs: Allow changing the default VM CPU mode/model config Add a preference for changing the default CPU mode/model. The options are: - default (whatever virt-manager chooses as the default) - hypervisor default (no block, what we've always done) - nearest host cpu model (just the 'model' from caps->host->cpu) - copy host cpu (the entire block from caps->host) The setting only applies to KVM guests, not tested with anything else. The default is left as is for now (hypervisor default). copy host CPU will one day use mode='host-model', when it does what we want. At that point we will probably make it the default --- .../org.virt-manager.virt-manager.gschema.xml | 7 + ui/preferences.ui | 255 ++++++++++-------- virtManager/config.py | 16 +- virtManager/create.py | 24 +- virtManager/preferences.py | 55 ++-- 5 files changed, 232 insertions(+), 125 deletions(-) diff --git a/data/org.virt-manager.virt-manager.gschema.xml b/data/org.virt-manager.virt-manager.gschema.xml index 270a7b0ab..2566e1ac1 100644 --- a/data/org.virt-manager.virt-manager.gschema.xml +++ b/data/org.virt-manager.virt-manager.gschema.xml @@ -207,6 +207,13 @@ Use selected format for new VM storage Use selected format when creating new disk images in new VM wizard + + + 'default' + CPU setting to use for new VMs + CPU setting to use for new VMs. Limited to VMs matching the host architecture. Possible values: default (virt-manager default), hv-default (qemu's default), host-cpu-model (just the model, not the additional features), host-model (libvirt's host-model setting). + + - + @@ -290,127 +290,172 @@ - + True False 12 - 0 - none + vertical + 12 - + True False - 12 + 0 + none - + True False - 6 - 6 + 12 - + True False - 0 - _Graphics type: - True - prefs-graphics-type + 6 + 6 + + + True + False + 0 + _Graphics type: + True + prefs-graphics-type + + + 0 + 1 + 1 + 1 + + + + + True + False + Default storage format for new disk images. + 0 + _Storage format: + True + prefs-storage-format + + + 0 + 2 + 1 + 1 + + + + + True + False + + + + 1 + 1 + 1 + 1 + + + + + True + False + Default storage format for new disk images. + + + + 1 + 2 + 1 + 1 + + + + + True + True + False + True + True + 0 + True + + + + 1 + 0 + 1 + 1 + + + + + True + False + 0 + _Add sound device: + True + + + 0 + 0 + 1 + 1 + + + + + True + False + Default CPU setting for new VMs. This is typically a tradeoff between performance +and migration compatibility: if using the 'copy host' option, your servers will need +identical CPUs in order to migrate the VM. + 0 + _CPU default: + True + prefs-cpu-default + + + 0 + 3 + 1 + 1 + + + + + True + False + + + + 1 + 3 + 1 + 1 + + - - 0 - 1 - 1 - 1 - - - - - True - False - Default storage format for new disk images. - 0 - _Storage format: - True - prefs-storage-format - - - 0 - 2 - 1 - 1 - - - - - True - False - - - - 1 - 1 - 1 - 1 - - - - - True - False - Default storage format for new disk images. - - - - 1 - 2 - 1 - 1 - - - - - True - True - False - True - True - 0 - True - - - - 1 - 0 - 1 - 1 - - - - - True - False - 0 - _Add sound device: - True - - - 0 - 0 - 1 - 1 - + + + True + False + <b>New VM Defaults</b> + True + + - - - - True - False - <b>New VM Defaults</b> - True - + + False + True + 0 + diff --git a/virtManager/config.py b/virtManager/config.py index 2be564b17..7722d4b13 100644 --- a/virtManager/config.py +++ b/virtManager/config.py @@ -167,6 +167,7 @@ class vmmConfig(object): self.askpass_package = cliconfig.askpass_package self.default_graphics_from_config = cliconfig.default_graphics self.default_storage_format_from_config = "qcow2" + self.cpu_default_from_config = "hv-default" self._objects = [] @@ -403,7 +404,8 @@ class vmmConfig(object): self.conf.set("/details/window_width", w) self.conf.set("/details/window_height", h) - # Create sound device for default guest + + # New VM preferences def get_new_vm_sound(self): return self.conf.get("/new-vm/add-sound") def set_new_vm_sound(self, state): @@ -429,6 +431,18 @@ class vmmConfig(object): def set_storage_format(self, typ): self.conf.set("/new-vm/storage-format", typ.lower()) + def get_default_cpu_setting(self, raw=False): + ret = self.conf.get("/new-vm/cpu-default") + whitelist = ["default", "hv-default", "host-cpu-model", "host-model"] + + if ret not in whitelist: + ret = "default" + if ret == "default" and not raw: + ret = self.cpu_default_from_config + return ret + def set_default_cpu_setting(self, val): + self.conf.set("/new-vm/cpu-default", val.lower()) + # URL/Media path history def _url_add_helper(self, gconf_path, url): diff --git a/virtManager/create.py b/virtManager/create.py index daa6701ec..d338bd8bc 100644 --- a/virtManager/create.py +++ b/virtManager/create.py @@ -1510,10 +1510,30 @@ class vmmCreate(vmmGObjectUI): guest.add_default_video_device() guest.add_default_input_device() guest.add_default_console_device() - if self.config.get_new_vm_sound(): - guest.add_default_sound_device() guest.add_default_usb_controller() guest.add_default_channels() + + if self.config.get_new_vm_sound(): + guest.add_default_sound_device() + + if (guest.conn.is_qemu() and + guest.type == "kvm" and + guest.os.is_x86() and + guest.os.arch == guest.conn.caps.host.cpu.arch): + cpu_type = self.config.get_default_cpu_setting() + + if cpu_type == "hv-default": + pass + elif cpu_type == "host-cpu-model": + if guest.conn.caps.host.cpu.model: + guest.cpu.model = guest.conn.caps.host.cpu.model + elif cpu_type == "host-model": + # host-model has known issues, so use our 'copy cpu' + # behavior until host-model does what we need + guest.cpu.copy_host_cpu() + else: + raise RuntimeError("Unknown cpu default '%s'" % cpu_type) + except Exception, e: self.err.show_err(_("Error setting up default devices:") + str(e)) return None diff --git a/virtManager/preferences.py b/virtManager/preferences.py index 4752ba866..b28d523aa 100644 --- a/virtManager/preferences.py +++ b/virtManager/preferences.py @@ -42,6 +42,7 @@ class vmmPreferences(vmmGObjectUI): self.refresh_new_vm_sound() self.refresh_graphics_type() self.refresh_storage_format() + self.refresh_cpu_default() self.refresh_disk_poll() self.refresh_net_poll() self.refresh_memory_poll() @@ -62,6 +63,9 @@ class vmmPreferences(vmmGObjectUI): "on_prefs_close_clicked": self.close, "on_vmm_preferences_delete_event": self.close, "on_prefs_new_vm_sound_toggled": self.change_new_vm_sound, + "on_prefs_graphics_type_changed": self.change_graphics_type, + "on_prefs_storage_format_changed": self.change_storage_format, + "on_prefs_cpu_default_changed": self.change_cpu_default, "on_prefs_stats_enable_disk_toggled": self.change_disk_poll, "on_prefs_stats_enable_net_toggled": self.change_net_poll, "on_prefs_stats_enable_memory_toggled": self.change_memory_poll, @@ -73,8 +77,6 @@ class vmmPreferences(vmmGObjectUI): "on_prefs_confirm_unapplied_toggled": self.change_confirm_unapplied, "on_prefs_confirm_delstorage_toggled": self.change_confirm_delstorage, "on_prefs_btn_keys_define_clicked": self.change_grab_keys, - "on_prefs_graphics_type_changed": self.change_graphics_type, - "on_prefs_storage_format_changed": self.change_storage_format, }) self.bind_escape_key_close() @@ -123,6 +125,18 @@ class vmmPreferences(vmmGObjectUI): combo.set_model(model) uihelpers.set_combo_text_column(combo, 1) + combo = self.widget("prefs-cpu-default") + # [gsettings value, string] + model = Gtk.ListStore(str, str) + for row in [["default", _("System default (%s)") % + self.config.cpu_default_from_config], + ["hv-default", _("Hypervisor default")], + ["host-cpu-model", _("Nearest host CPU model")], + ["host-model", _("Copy host CPU definition")]]: + model.append(row) + combo.set_model(model) + uihelpers.set_combo_text_column(combo, 1) + ######################### # Config Change Options # @@ -147,16 +161,18 @@ class vmmPreferences(vmmGObjectUI): def refresh_new_vm_sound(self): self.widget("prefs-new-vm-sound").set_active( self.config.get_new_vm_sound()) - def refresh_graphics_type(self): combo = self.widget("prefs-graphics-type") gtype = self.config.get_graphics_type(raw=True) uihelpers.set_row_selection(combo, gtype) - def refresh_storage_format(self): combo = self.widget("prefs-storage-format") val = self.config.get_default_storage_format(raw=True) uihelpers.set_row_selection(combo, val) + def refresh_cpu_default(self): + combo = self.widget("prefs-cpu-default") + val = self.config.get_default_cpu_setting(raw=True) + uihelpers.set_row_selection(combo, val) def refresh_disk_poll(self): self.widget("prefs-stats-enable-disk").set_active( @@ -281,6 +297,24 @@ class vmmPreferences(vmmGObjectUI): def change_new_vm_sound(self, src): self.config.set_new_vm_sound(src.get_active()) + def change_graphics_type(self, src): + gtype = 'vnc' + idx = src.get_active() + if idx >= 0: + gtype = src.get_model()[idx][0] + self.config.set_graphics_type(gtype.lower()) + def change_storage_format(self, src): + typ = 'default' + idx = src.get_active() + if idx >= 0: + typ = src.get_model()[idx][0] + self.config.set_storage_format(typ.lower()) + def change_cpu_default(self, src): + typ = 'default' + idx = src.get_active() + if idx >= 0: + typ = src.get_model()[idx][0] + self.config.set_default_cpu_setting(typ.lower()) def change_disk_poll(self, src): self.config.set_stats_enable_disk_poll(src.get_active()) @@ -303,16 +337,3 @@ class vmmPreferences(vmmGObjectUI): self.config.set_confirm_unapplied(src.get_active()) def change_confirm_delstorage(self, src): self.config.set_confirm_delstorage(src.get_active()) - - def change_graphics_type(self, src): - gtype = 'vnc' - idx = src.get_active() - if idx >= 0: - gtype = src.get_model()[idx][0] - self.config.set_graphics_type(gtype.lower()) - def change_storage_format(self, src): - typ = 'default' - idx = src.get_active() - if idx >= 0: - typ = src.get_model()[idx][0] - self.config.set_storage_format(typ.lower())