If the host-model is selected, disable the cpu model drop down and features list. They still show what exact configuration the host-model is using. For the old libvirt which doesn't support <cpu mode='host-model'/> virt-manager still copy cpu configs from caps XML to domain XML. If a certain libvirt version supports host-model, but the UPDATE_CPU flag doesn't exist, a WARN image will show up on UI to give a hint. --- ui/vmm-details.ui | 246 ++++++++++++++++++++++++------------------------- virtManager/details.py | 44 +++++---- virtManager/domain.py | 17 ++-- 3 files changed, 156 insertions(+), 151 deletions(-) diff --git a/ui/vmm-details.ui b/ui/vmm-details.ui index ad0652d..45f3e82 100644 --- a/ui/vmm-details.ui +++ b/ui/vmm-details.ui @@ -2314,192 +2314,184 @@ I/O:</property> <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <object class="GtkTable" id="table15"> + <object class="GtkHBox" id="hbox3"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="column_spacing">12</property> - <property name="row_spacing">3</property> <child> - <object class="GtkLabel" id="label52"> + <object class="GtkCheckButton" id="cpu-host-model-checkbutton"> + <property name="label" translatable="yes">host model</property> + <property name="use_action_appearance">False</property> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Model:</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_cpu_host_model_enable_toggled" swapped="no"/> </object> <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> </packing> </child> <child> - <object class="GtkHBox" id="hbox21"> + <object class="GtkImage" id="host-model-info"> <property name="visible">True</property> <property name="can_focus">False</property> - <child> - <object class="GtkAlignment" id="alignment33"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkComboBox" id="cpu-model"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="has_entry">True</property> - <signal name="changed" handler="on_cpu_model_changed" swapped="no"/> - <child internal-child="entry"> - <object class="GtkEntry" id="combobox-entry"> - <property name="can_focus">True</property> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> + <property name="xalign">0</property> + <property name="stock">gtk-info</property> </object> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="y_options">GTK_FILL</property> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> </packing> </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox14"> + <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <object class="GtkAlignment" id="alignment37"> + <object class="GtkLabel" id="label52"> <property name="visible">True</property> <property name="can_focus">False</property> - <child> - <placeholder/> - </child> + <property name="label" translatable="yes">Model:</property> </object> <packing> - <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> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> </packing> </child> <child> - <object class="GtkHBox" id="hbox25"> + <object class="GtkAlignment" id="alignment12"> <property name="visible">True</property> <property name="can_focus">False</property> <child> - <object class="GtkButton" id="cpu-copy-host"> - <property name="label" translatable="yes">Copy host CPU configuration</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="clicked" handler="on_cpu_copy_host_clicked" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment38"> + <object class="GtkComboBox" id="cpu-model"> <property name="visible">True</property> <property name="can_focus">False</property> - <child> - <placeholder/> + <property name="has_entry">True</property> + <signal name="changed" handler="on_cpu_model_changed" swapped="no"/> + <child internal-child="entry"> + <object class="GtkEntry" id="combobox-entry"> + <property name="can_focus">True</property> + </object> </child> </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> </child> </object> <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="y_options">GTK_FILL</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">0</property> + <property name="position">1</property> </packing> </child> <child> - <object class="GtkExpander" id="cpu-features-expander"> + <object class="GtkHBox" id="hbox21"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can_focus">False</property> <child> - <object class="GtkAlignment" id="alignment29"> + <object class="GtkExpander" id="cpu-features-expander"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">21</property> + <property name="can_focus">True</property> <child> - <object class="GtkHBox" id="hbox19"> + <object class="GtkAlignment" id="alignment29"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="spacing">6</property> + <property name="left_padding">21</property> <child> - <object class="GtkScrolledWindow" id="scrolledwindow4"> - <property name="height_request">150</property> + <object class="GtkHBox" id="hbox19"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">never</property> - <property name="shadow_type">etched-in</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> <child> - <object class="GtkTreeView" id="cpu-features"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection3"/> + <object class="GtkScrolledWindow" id="scrolledwindow4"> + <property name="height_request">150</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">never</property> + <property name="shadow_type">etched-in</property> + <child> + <object class="GtkTreeView" id="cpu-features"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection3"/> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment32"> - <property name="visible">True</property> - <property name="can_focus">False</property> <child> - <placeholder/> + <object class="GtkAlignment" id="alignment32"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> </child> </object> </child> + <child type="label"> + <object class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes"><b>CPU Features</b></property> + <property name="use_markup">True</property> + </object> + </child> </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes"><b>CPU Features</b></property> - <property name="use_markup">True</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkImage" id="cpu-feat-warn-image"> + <property name="visible">False</property> + <property name="can_focus">False</property> + <property name="stock">gtk-dialog-warning</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> </packing> </child> </object> diff --git a/virtManager/details.py b/virtManager/details.py index 29b0627..89d7bdf 100644 --- a/virtManager/details.py +++ b/virtManager/details.py @@ -360,7 +360,6 @@ class vmmDetails(vmmGObjectUI): self.ignorePause = False self.ignoreDetails = False - self._cpu_copy_host = False self.console = vmmConsolePages(self.vm, self.builder, self.topwin) @@ -431,7 +430,7 @@ class vmmDetails(vmmGObjectUI): "on_cpu_cores_changed": lambda *x: self.enable_apply(x, EDIT_TOPOLOGY), "on_cpu_sockets_changed": lambda *x: self.enable_apply(x, EDIT_TOPOLOGY), "on_cpu_threads_changed": lambda *x: self.enable_apply(x, EDIT_TOPOLOGY), - "on_cpu_copy_host_clicked": self.config_cpu_copy_host, + "on_cpu_host_model_enable_toggled": self.config_cpu_host_model_enable, "on_cpu_topology_enable_toggled": self.config_cpu_topology_enable, "on_config_memory_changed": self.config_memory_changed, @@ -916,6 +915,8 @@ class vmmDetails(vmmGObjectUI): feat_model.append([name, "default"]) # CPU model combo + self.widget("host-model-info").set_tooltip_text( + _("Use CPU model which most closely matches the host, this gives close to maximum functionality and performance.")) cpu_model = self.widget("cpu-model") model = Gtk.ListStore(str, object) @@ -1813,17 +1814,11 @@ class vmmDetails(vmmGObjectUI): def config_maxvcpus_changed(self, ignore): self.enable_apply(EDIT_VCPUS) - def config_cpu_copy_host(self, src_ignore): - # Update UI with output copied from host - try: - CPU = virtinst.CPU(self.vm.conn.vmm) - CPU.copy_host_cpu() - - self._refresh_cpu_config(CPU) - self._cpu_copy_host = True - except Exception, e: - self.err.show_err(_("Error copying host CPU: %s") % str(e)) - return + def config_cpu_host_model_enable(self, src): + do_enable = src.get_active() + self.widget("cpu-model").set_sensitive(not bool(do_enable)) + self.widget("cpu-features").set_sensitive(not bool(do_enable)) + self.enable_apply(EDIT_CPU) def config_cpu_topology_enable(self, src): do_enable = src.get_active() @@ -2116,10 +2111,14 @@ class vmmDetails(vmmGObjectUI): add_hotplug(self.config_vcpu_pin_cpuset, cpuset) if self.editted(EDIT_CPU): + from_host = False + if self.widget("cpu-host-model-checkbutton").get_active(): + from_host = True + model, vendor = self.get_config_cpu_model() features = self.get_config_cpu_features() add_define(self.vm.define_cpu, - model, vendor, self._cpu_copy_host, features) + model, vendor, from_host, features) if self.editted(EDIT_TOPOLOGY): do_top = self.widget("cpu-topology-enable").get_active() @@ -2134,8 +2133,6 @@ class vmmDetails(vmmGObjectUI): add_define(self.vm.define_cpu_topology, sockets, cores, threads) ret = self._change_config_helper(df, da, hf, ha) - if ret: - self._cpu_copy_host = False return ret def config_vcpu_pin(self, src_ignore, path, new_text): @@ -2815,6 +2812,7 @@ class vmmDetails(vmmGObjectUI): def _refresh_cpu_config(self, cpu): feature_ui = self.widget("cpu-features") model = cpu.model or "" + mode = cpu.mode caps = self.vm.conn.get_capabilities() capscpu = None @@ -2834,12 +2832,25 @@ class vmmDetails(vmmGObjectUI): cores = cpu.cores or 1 threads = cpu.threads or 1 + if mode == "host-model": + host_model = self.widget("cpu-host-model-checkbutton") + if not host_model.get_active(): + host_model.set_active(True) + self.widget("cpu-topology-enable").set_active(show_top) self.widget("cpu-model").get_child().set_text(model) self.widget("cpu-sockets").set_value(sockets) self.widget("cpu-cores").set_value(cores) self.widget("cpu-threads").set_value(threads) + # Only happened when VIR_DOMAIN_XML_UPDATE_CPU flag doesn't exist + # for host-model mode + if mode == "host-model" and not cpu.features: + cpu_feat_warn = self.widget("cpu-feat-warn-image") + cpu_feat_warn.show() + cpu_feat_warn.set_tooltip_text(_("CPU features failed to show.")) + return + def get_feature_policy(name): for f in cpu.features: if f.name == name: @@ -2855,7 +2866,6 @@ class vmmDetails(vmmGObjectUI): row[1] = get_feature_policy(row[0]) def refresh_config_cpu(self): - self._cpu_copy_host = False cpu = self.vm.get_cpu_config() self._refresh_cpu_count() diff --git a/virtManager/domain.py b/virtManager/domain.py index 82a7ac8..14f8983 100644 --- a/virtManager/domain.py +++ b/virtManager/domain.py @@ -468,16 +468,19 @@ class vmmDomain(vmmLibvirtObject): def define_cpu(self, model, vendor, from_host, featurelist): def change(guest): if from_host: - guest.cpu.copy_host_cpu() - elif guest.cpu.model != model: - # Since we don't expose this in the UI, have host value trump - # caps value - guest.cpu.vendor = vendor + if virtinst.support.check_domain_support(self._backend, + virtinst.support.SUPPORT_DOMAIN_CPU_HOST_MODEL): + guest.cpu.reset() + guest.cpu.mode = "host-model" + else: + guest.cpu.copy_host_cpu() + return guest.cpu.model = model or None + guest.cpu.vendor = vendor or None + if guest.cpu.model is None: - for f in guest.cpu.features: - guest.cpu.remove_feature(f) + guest.cpu.reset() return origfeatures = guest.cpu.features -- 1.7.11.2 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list