diff --git a/src/virtManager/details.py b/src/virtManager/details.py
index 66454a3ad..8fc50fcac 100644
--- a/src/virtManager/details.py
+++ b/src/virtManager/details.py
@@ -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")
diff --git a/src/virtManager/domain.py b/src/virtManager/domain.py
index 79c0bfdbc..632d654fd 100644
--- a/src/virtManager/domain.py
+++ b/src/virtManager/domain.py
@@ -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
diff --git a/src/vmm-details.glade b/src/vmm-details.glade
index 8d50d453c..e399a4965 100644
--- a/src/vmm-details.glade
+++ b/src/vmm-details.glade
@@ -2045,6 +2045,356 @@ I/O:
0
+
+
+ True
+ True
+
+
+ True
+ 21
+ 12
+
+
+ True
+
+
+ True
+ 2
+ 2
+ 12
+ 3
+
+
+ True
+ 0
+ Model:
+
+
+ GTK_FILL
+
+
+
+
+ True
+
+
+ True
+ True
+ ●
+ 15
+
+
+
+ False
+ 0
+
+
+
+
+ True
+
+
+
+
+
+ 1
+
+
+
+
+ 1
+ 2
+
+
+
+
+ True
+
+
+
+
+
+ 1
+ 2
+ GTK_FILL
+
+
+
+
+ True
+
+
+ Copy host CPU configuration
+ True
+ True
+ True
+
+
+
+ False
+ 0
+
+
+
+
+ True
+
+
+
+
+
+ 1
+
+
+
+
+ 1
+ 2
+ 1
+ 2
+
+
+
+
+ 0
+
+
+
+
+ True
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ True
+ <b>Configuration</b>
+ True
+
+
+ label_item
+
+
+
+
+ False
+ 1
+
+
+
+
+ True
+ True
+
+
+ True
+ 23
+ 12
+
+
+ True
+ 4
+
+
+ Manually set CPU topology
+ True
+ True
+ True
+ False
+ True
+
+
+
+ 0
+
+
+
+
+ True
+
+
+ True
+ 3
+ 2
+ 12
+ 4
+
+
+ True
+ 0
+ Threads:
+
+
+ 2
+ 3
+ GTK_FILL
+
+
+
+
+ True
+ 0
+ Cores:
+
+
+ 1
+ 2
+ GTK_FILL
+
+
+
+
+ True
+ 0
+ Sockets:
+
+
+ GTK_FILL
+
+
+
+
+ True
+
+
+ True
+ True
+ ●
+ 1 1 256 1 10 0
+
+
+
+ False
+ 0
+
+
+
+
+ True
+
+
+
+
+
+ 1
+
+
+
+
+ 1
+ 2
+ 2
+ 3
+
+
+
+
+ True
+
+
+ True
+ True
+ ●
+ 1 1 256 1 10 0
+
+
+
+ False
+ 0
+
+
+
+
+ True
+
+
+
+
+
+ 1
+
+
+
+
+ 1
+ 2
+ 1
+ 2
+
+
+
+
+ True
+
+
+ True
+ True
+ ●
+ 1 1 256 1 10 0
+
+
+
+ False
+ 0
+
+
+
+
+ True
+
+
+
+
+
+ 1
+
+
+
+
+ 1
+ 2
+
+
+
+
+ 0
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ True
+ <b>Topology</b>
+ True
+
+
+ label_item
+
+
+
+
+ False
+ 2
+
+
True
@@ -2223,7 +2573,7 @@ I/O:
True
- <b>CPU Pinning</b>
+ <b>Pinning</b>
True
@@ -2232,7 +2582,8 @@ I/O:
- 1
+ False
+ 3