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 <cpu> block, what we've always done)
- nearest host cpu model (just the 'model' from caps->host->cpu)
- copy host cpu (the entire <cpu> 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
This commit is contained in:
Cole Robinson 2014-01-17 15:32:40 -05:00
parent b215b27854
commit 7003a3a528
5 changed files with 232 additions and 125 deletions

View File

@ -207,6 +207,13 @@
<summary>Use selected format for new VM storage</summary>
<description>Use selected format when creating new disk images in new VM wizard</description>
</key>
<key name="cpu-default" type="s">
<default>'default'</default>
<summary>CPU setting to use for new VMs</summary>
<description>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).</description>
</key>
</schema>
<schema id="org.virt-manager.virt-manager.paths"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.0 on Fri Jan 17 15:30:05 2014 -->
<!-- Generated with glade 3.16.0 on Fri Jan 17 17:40:39 2014 -->
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkAdjustment" id="adjustment1">
@ -290,127 +290,172 @@
</packing>
</child>
<child>
<object class="GtkFrame" id="frame4">
<object class="GtkBox" id="box3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkAlignment" id="alignment5">
<object class="GtkFrame" id="frame4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkGrid" id="table4">
<object class="GtkAlignment" id="alignment5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<property name="left_padding">12</property>
<child>
<object class="GtkLabel" id="label162">
<object class="GtkGrid" id="table4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Graphics type:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">prefs-graphics-type</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<child>
<object class="GtkLabel" id="label162">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Graphics type:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">prefs-graphics-type</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label25">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Default storage format for new disk images.</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Storage format:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">prefs-storage-format</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="prefs-graphics-type">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="changed" handler="on_prefs_graphics_type_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="prefs-storage-format">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Default storage format for new disk images.</property>
<signal name="changed" handler="on_prefs_storage_format_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="prefs-new-vm-sound">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_prefs_new_vm_sound_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Add sound device:</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label16">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">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.</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_CPU default:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">prefs-cpu-default</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="prefs-cpu-default">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="changed" handler="on_prefs_cpu_default_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label25">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Default storage format for new disk images.</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Storage format:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">prefs-storage-format</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="prefs-graphics-type">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="changed" handler="on_prefs_graphics_type_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="prefs-storage-format">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Default storage format for new disk images.</property>
<signal name="changed" handler="on_prefs_storage_format_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="prefs-new-vm-sound">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_prefs_new_vm_sound_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Add sound device:</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;New VM Defaults&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;New VM Defaults&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>

View File

@ -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):

View File

@ -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

View File

@ -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())