details: Allow setting CPU topology and model

Provide a button 'Copy from host CPU', which effectively sets up the
equiv of qemu -cpu host
This commit is contained in:
Cole Robinson 2010-12-16 16:05:55 -05:00
parent 5512e192aa
commit ecb104dbfb
3 changed files with 452 additions and 12 deletions

View File

@ -279,6 +279,7 @@ class vmmDetails(vmmGObjectUI):
self.ignorePause = False
self.ignoreDetails = False
self._cpu_copy_host = False
self.console = vmmConsolePages(self.vm, self.window)
@ -345,6 +346,12 @@ class vmmDetails(vmmGObjectUI):
"on_config_vcpus_changed": self.config_vcpus_changed,
"on_config_vcpupin_changed": self.config_vcpus_changed,
"on_config_vcpupin_generate_clicked": self.config_vcpupin_generate,
"on_cpu_model_changed": self.config_enable_apply,
"on_cpu_cores_changed": self.config_enable_apply,
"on_cpu_sockets_changed": self.config_enable_apply,
"on_cpu_threads_changed": self.config_enable_apply,
"on_cpu_copy_host_clicked": self.config_cpu_copy_host,
"on_cpu_topology_enable_toggled": self.config_cpu_topology_enable,
"on_config_memory_changed": self.config_memory_changed,
"on_config_maxmem_changed": self.config_maxmem_changed,
@ -1325,6 +1332,24 @@ class vmmDetails(vmmGObjectUI):
self.config_enable_apply()
def config_cpu_copy_host(self, src_ignore):
# Update UI with output copied from host
try:
CPU = virtinst.CPU(self.vm.get_connection().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),
"".join(traceback.format_exc()))
return
def config_cpu_topology_enable(self, src):
do_enable = src.get_active()
self.window.get_widget("cpu-topology-table").set_sensitive(do_enable)
self.config_enable_apply()
# Boot device / Autostart
def config_bootdev_selected(self, ignore):
boot_row = self.get_boot_selection()
@ -1508,15 +1533,35 @@ class vmmDetails(vmmGObjectUI):
vcpus = self.window.get_widget("config-vcpus").get_adjustment().value
cpuset = self.window.get_widget("config-vcpupin").get_text()
do_top = self.window.get_widget("cpu-topology-enable").get_active()
sockets = self.window.get_widget("cpu-sockets").get_value()
cores = self.window.get_widget("cpu-cores").get_value()
threads = self.window.get_widget("cpu-threads").get_value()
model = self.window.get_widget("cpu-model").get_text() or None
logging.info("Setting vcpus for %s to %s, cpuset is %s" %
(self.vm.get_name(), str(vcpus), cpuset))
return self._change_config_helper([self.vm.define_vcpus,
self.vm.define_cpuset],
[(vcpus,),
(cpuset,)],
self.vm.hotplug_vcpus,
(vcpus,))
if not do_top:
sockets = None
cores = None
threads = None
define_funcs = [self.vm.define_vcpus,
self.vm.define_cpuset,
self.vm.define_cpu,
self.vm.define_cpu_topology]
define_args = [(vcpus,),
(cpuset,),
(model, self._cpu_copy_host),
(sockets, cores, threads)]
ret = self._change_config_helper(define_funcs, define_args,
self.vm.hotplug_vcpus,
(vcpus,))
if ret:
self._cpu_copy_host = False
def config_vcpu_pin(self, src_ignore, path, new_text):
vcpu_list = self.window.get_widget("config-vcpu-list")
@ -1911,16 +1956,14 @@ class vmmDetails(vmmGObjectUI):
self.network_traffic_graph.set_property("data_array",
self.vm.network_traffic_vector())
def refresh_config_cpu(self):
def _refresh_cpu_count(self, user_changed):
conn = self.vm.get_connection()
host_active_count = conn.host_active_processor_count()
cpu_max = (self.vm.is_runable() and
conn.get_max_vcpus(self.vm.get_hv_type()) or
self.vm.vcpu_max_count())
curvcpus = self.vm.vcpu_count()
vcpupin = self.vm.vcpu_pinning()
config_apply = self.window.get_widget("config-apply")
vcpus_adj = self.window.get_widget("config-vcpus").get_adjustment()
vcpus_adj.upper = cpu_max
@ -1928,7 +1971,8 @@ class vmmDetails(vmmGObjectUI):
host_active_count)
self.window.get_widget("state-vm-maxvcpus").set_text(str(cpu_max))
if not config_apply.get_property("sensitive"):
# If user manually changes vcpus, don't overwrite the value
if not user_changed:
vcpus_adj.value = curvcpus
self.window.get_widget("state-vm-vcpus").set_text(str(curvcpus))
@ -1937,6 +1981,10 @@ class vmmDetails(vmmGObjectUI):
warn = bool(vcpus_adj.value > host_active_count)
self.window.get_widget("config-vcpus-warn-box").set_property(
"visible", warn)
def _refresh_cpu_pinning(self):
conn = self.vm.get_connection()
host_active_count = conn.host_active_processor_count()
vcpupin = self.vm.vcpu_pinning()
# Populate VCPU pinning
self.window.get_widget("config-vcpupin").set_text(vcpupin)
@ -1976,6 +2024,30 @@ class vmmDetails(vmmGObjectUI):
vcpu_model.append([vcpu, vcpucur, vcpupin])
def _refresh_cpu_config(self, cpu):
model = cpu.model or ""
show_top = bool(cpu.sockets or cpu.cores or cpu.threads)
sockets = cpu.sockets or 1
cores = cpu.cores or 1
threads = cpu.threads or 1
self.window.get_widget("cpu-topology-enable").set_active(show_top)
self.window.get_widget("cpu-model").set_text(model)
self.window.get_widget("cpu-sockets").set_value(sockets)
self.window.get_widget("cpu-cores").set_value(cores)
self.window.get_widget("cpu-threads").set_value(threads)
def refresh_config_cpu(self):
self._cpu_copy_host = False
config_apply = self.window.get_widget("config-apply")
user_changed = config_apply.get_property("sensitive")
cpu = self.vm.get_cpu_config()
self._refresh_cpu_count(user_changed)
self._refresh_cpu_pinning()
self._refresh_cpu_config(cpu)
def refresh_config_memory(self):
host_mem_widget = self.window.get_widget("state-host-memory")
vm_mem_widget = self.window.get_widget("state-vm-memory")

View File

@ -301,6 +301,20 @@ class vmmDomainBase(vmmLibvirtObject):
guest.cpuset = cpuset
return self._redefine_guest(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_guest(change)
def define_cpu(self, model, from_host):
def change(guest):
if from_host:
guest.cpu.copy_host_cpu()
guest.cpu.model = model
return self._redefine_guest(change)
def define_both_mem(self, memory, maxmem):
def change(guest):
guest.memory = int(int(memory) / 1024)
@ -512,6 +526,9 @@ class vmmDomainBase(vmmLibvirtObject):
def vcpu_pinning(self):
return self._get_guest().cpuset or ""
def get_cpu_config(self):
return self._get_guest().cpu
def get_boot_device(self):
return self._get_guest().installer.bootconfig.bootorder

View File

@ -2045,6 +2045,356 @@ I/O:</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkExpander" id="expander5">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkAlignment" id="alignment31">
<property name="visible">True</property>
<property name="left_padding">21</property>
<property name="right_padding">12</property>
<child>
<widget class="GtkHBox" id="hbox20">
<property name="visible">True</property>
<child>
<widget class="GtkTable" id="table15">
<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">3</property>
<child>
<widget class="GtkLabel" id="label52">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Model:</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox21">
<property name="visible">True</property>
<child>
<widget class="GtkEntry" id="cpu-model">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="width_chars">15</property>
<signal name="changed" handler="on_cpu_model_changed"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment33">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment37">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</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="GtkHBox" id="hbox25">
<property name="visible">True</property>
<child>
<widget 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"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment38">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</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>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment32">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label49">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Configuration&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkExpander" id="expander6">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkAlignment" id="alignment39">
<property name="visible">True</property>
<property name="left_padding">23</property>
<property name="right_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox15">
<property name="visible">True</property>
<property name="spacing">4</property>
<child>
<widget class="GtkCheckButton" id="cpu-topology-enable">
<property name="label" translatable="yes">Manually set CPU topology</property>
<property name="visible">True</property>
<property name="active">True</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_topology_enable_toggled"/>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox26">
<property name="visible">True</property>
<child>
<widget class="GtkTable" id="cpu-topology-table">
<property name="visible">True</property>
<property name="n_rows">3</property>
<property name="n_columns">2</property>
<property name="column_spacing">12</property>
<property name="row_spacing">4</property>
<child>
<widget class="GtkLabel" id="label59">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Threads:</property>
</widget>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label58">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Cores:</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="GtkLabel" id="label57">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Sockets:</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox27">
<property name="visible">True</property>
<child>
<widget class="GtkSpinButton" id="cpu-threads">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="adjustment">1 1 256 1 10 0</property>
<signal name="change_value" handler="on_cpu_threads_change_value"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment40">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</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">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox28">
<property name="visible">True</property>
<child>
<widget class="GtkSpinButton" id="cpu-cores">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="adjustment">1 1 256 1 10 0</property>
<signal name="changed" handler="on_cpu_cores_changed"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment41">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</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>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox29">
<property name="visible">True</property>
<child>
<widget class="GtkSpinButton" id="cpu-sockets">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="adjustment">1 1 256 1 10 0</property>
<signal name="changed" handler="on_cpu_sockets_changed"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment42">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label62">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Topology&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkExpander" id="expander3">
<property name="visible">True</property>
@ -2223,7 +2573,7 @@ I/O:</property>
<child>
<widget class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;CPU Pinning&lt;/b&gt;</property>
<property name="label" translatable="yes">&lt;b&gt;Pinning&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
@ -2232,7 +2582,8 @@ I/O:</property>
</child>
</widget>
<packing>
<property name="position">1</property>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
</widget>