[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[virt-tools-list] [PATCH] Virt-manager CPU pinning support



Hi all,
since having virt-manager with CPU pinning support would be a nice new feature I've added this support to my virt-manager (that has been updated from hg repository today to the newest version so there should be no problem with codebase). Basically it shows "CPU Affinity string" entry on Processor tab in VM details. Apply button is not applicable when you provide bad CPU pinning string so that you should double-check the pinning string if you can't apply changes. If you want to disable CPU pinning, just delete the string to default value (zero length string) and it will unset this entry in libvirt XML file it won't be used for domain creation then.

Michal
# HG changeset patch
# User Michal Novotny <minovotn redhat com>
# Date 1248191243 -7200
# Node ID 7b75297ebac421bc6593c30f8ab2ee491acd7f10
# Parent  e26f11f4234cfd4c6e802b92a570e30fef0b7291
CPU Pinning support

Virt-manager doesn't consider CPU pinning settings in the Processor tab yet so
this is the patch to provide CPU pinning support for virt-manager. It's using
only CPU definition for libvirt itself and it doesn't support CPU pinning for
domains that are currently in running state since this feature will be rarely
used for already running domains in my opinion.

diff -r e26f11f4234c -r 7b75297ebac4 src/virtManager/details.py
--- a/src/virtManager/details.py	Mon Jul 20 15:09:32 2009 -0400
+++ b/src/virtManager/details.py	Tue Jul 21 17:47:23 2009 +0200
@@ -288,6 +288,7 @@
             "on_details_pages_switch_page": self.switch_page,
 
             "on_config_vcpus_changed": self.config_vcpus_changed,
+            "on_config_vcpupin_changed": self.config_vcpupin_changed,
             "on_config_memory_changed": self.config_memory_changed,
             "on_config_maxmem_changed": self.config_maxmem_changed,
             "on_config_boot_device_changed": self.config_boot_options_changed,
@@ -1592,10 +1593,29 @@
     def config_vcpus_changed(self, src):
         self.window.get_widget("config-apply").set_sensitive(True)
 
+    def config_vcpupin_changed(self, src):
+        val = src.get_text()
+
+        # Since for cpuset we require None for define_vcpus, we'll change this now
+        if len(val) == 0:
+            val = None
+
+        enable = False
+        if self.vm.check_cpuset_syntax(val):
+           enable = True
+        self.window.get_widget("config-apply").set_sensitive(enable)
+
     def config_vcpus_apply(self):
         vcpus = self.window.get_widget("config-vcpus").get_adjustment().value
-        logging.info("Setting vcpus for %s to %s" % (self.vm.get_name(),
-                                                     str(vcpus)))
+        cpuset = self.window.get_widget("config-vcpupin").get_text()
+
+        # Since for cpuset we require None for define_vcpus, we'll change this now
+        if len(cpuset) == 0:
+            cpuset = None
+
+        logging.info("Setting vcpus for %s to %s, cpuset is %s" % 
+                                    (self.vm.get_name(), str(vcpus), cpuset))
+
         hotplug_err = False
 
         try:
@@ -1607,7 +1627,7 @@
 
         # Change persistent config
         try:
-            self.vm.define_vcpus(vcpus)
+            self.vm.define_vcpus(vcpus, cpuset)
         except Exception, e:
             self.err.show_err(_("Error changing vcpu value: %s" % str(e)),
                               "".join(traceback.format_exc()))
diff -r e26f11f4234c -r 7b75297ebac4 src/virtManager/domain.py
--- a/src/virtManager/domain.py	Mon Jul 20 15:09:32 2009 -0400
+++ b/src/virtManager/domain.py	Tue Jul 21 17:47:23 2009 +0200
@@ -24,6 +24,7 @@
 import logging
 import time
 import difflib
+import re
 
 from virtManager import util
 import virtinst.util as vutil
@@ -1304,19 +1305,65 @@
         if vcpus != self.vcpu_count():
             self.vm.setVcpus(vcpus)
 
-    def define_vcpus(self, vcpus):
+    # This function checks the cpuset mask syntax, None is allowed
+    def check_cpuset_syntax(self, val):
+        if val is None:
+            return True
+        if type(val) is not type("string") or len(val) == 0:
+            logging.debug("Cpuset mask error must be string")
+            return False
+
+        if re.match("^[0-9,-]*$", val) is None:
+            logging.debug("Cpuset mask can only contain numeric, ',', or "
+                                "'-' characters")
+            return False
+
+        pcpus = vutil.get_phy_cpus(self.connection.vmm)
+        for c in val.split(','):
+            if c.find('-') != -1:
+                (x, y) = c.split('-')
+                if int(x) > int(y):
+                    logging.debug("Cpuset mask contains invalid format.")
+                    return False
+
+                if int(x) >= pcpus or int(y) >= pcpus:
+                    logging.debug("Cpuset mask pCPU numbers must be less "
+                                  "than pCPUs.")
+                    return False
+            else:
+                if int(c) >= pcpus:
+                    logging.debug("Cpuset mask pCPU numbers must be less "
+                                  "than pCPUs.")
+        return True
+
+    def define_vcpus(self, vcpus, cpuset=None):
         vcpus = int(vcpus)
 
         def set_node(doc, ctx, val, xpath):
             node = ctx.xpathEval(xpath)
             node = (node and node[0] or None)
 
+            # Val argument is a tuple of vcpu count and cpu mask
+            if type(val) == tuple and len(val) > 1:
+                vcpus = val[0]
+                cpumask = val[1]
+            else:
+                vcpus = val
+ 
             if node:
-                node.setContent(str(val))
+                node.setContent(str(vcpus))
+
+                # If cpuset mask is not valid, don't change it
+                # If cpuset mask is None, we don't want to use cpuset
+                if cpumask is None or (cpumask is not None
+                    and len(cpumask) == 0):
+                    node.unsetProp("cpuset")
+                elif self.check_cpuset_syntax(cpumask):
+                    node.setProp("cpuset", cpumask)
             return doc.serialize()
 
         def change_vcpu_xml(xml, vcpus):
-            return util.xml_parse_wrapper(xml, set_node, vcpus,
+            return util.xml_parse_wrapper(xml, set_node, (vcpus, cpuset),
                                           "/domain/vcpu[1]")
 
         self.redefine(change_vcpu_xml, vcpus)
diff -r e26f11f4234c -r 7b75297ebac4 src/vmm-details.glade
--- a/src/vmm-details.glade	Mon Jul 20 15:09:32 2009 -0400
+++ b/src/vmm-details.glade	Tue Jul 21 17:47:23 2009 +0200
@@ -1567,14 +1567,27 @@
                                               </packing>
                                             </child>
                                             <child>
+                                              <widget class="GtkLabel" id="label336">
+                                                <property name="visible">True</property>
+                                                <property name="xalign">1</property>
+                                                <property name="label" translatable="yes">CPU Affinity string:</property>
+                                              </widget>
+                                              <packing>
+                                                <property name="top_attach">2</property>
+                                                <property name="bottom_attach">3</property>
+                                                <property name="x_options">GTK_FILL</property>
+                                                <property name="y_options"></property>
+                                              </packing>
+                                            </child>
+                                            <child>
                                               <widget class="GtkLabel" id="label335">
                                                 <property name="visible">True</property>
                                                 <property name="xalign">1</property>
                                                 <property name="label" translatable="yes">Maximum allocation:</property>
                                               </widget>
                                               <packing>
-                                                <property name="top_attach">2</property>
-                                                <property name="bottom_attach">3</property>
+                                                <property name="top_attach">3</property>
+                                                <property name="bottom_attach">4</property>
                                                 <property name="x_options">GTK_FILL</property>
                                                 <property name="y_options"></property>
                                               </packing>
@@ -1586,8 +1599,8 @@
                                                 <property name="label" translatable="yes">Total CPUs on host machine:</property>
                                               </widget>
                                               <packing>
-                                                <property name="top_attach">3</property>
-                                                <property name="bottom_attach">4</property>
+                                                <property name="top_attach">4</property>
+                                                <property name="bottom_attach">5</property>
                                                 <property name="x_options">GTK_FILL</property>
                                                 <property name="y_options"></property>
                                               </packing>
@@ -1657,6 +1670,24 @@
                                                 <property name="y_options"></property>
                                               </packing>
                                             </child>
+		                            <child>
+		                              <widget class="GtkEntry" id="config-vcpupin">
+		                                <property name="visible">True</property>
+		                                <property name="can_focus">True</property>
+		                                <property name="editable">True</property>
+		                                <accessibility>
+		                                  <atkproperty name="AtkObject::accessible-name" translatable="yes">Virtual CPU Affinity Select</atkproperty>                                    </accessibility>
+		                                <signal name="changed" handler="on_config_vcpupin_changed"/>
+		                              </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>
+		                                <property name="x_options">GTK_FILL</property>
+		                                <property name="y_options"></property>
+		                              </packing>
+		                            </child>
                                           </widget>
                                           <packing>
                                             <property name="expand">False</property>

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]