Vitor de Lima has uploaded a new change for review.

Change subject: Capabilities: List capabilities of the IBM POWER familiy
......................................................................

Capabilities: List capabilities of the IBM POWER familiy

This introduces a parser capable of interpreting the /proc/cpuinfo
present in IBM POWER hosts. It also retrieves the possible emulated
machines for QEMU guests. The POWER 7 processors are not compatible
between themselves so only the host CPU is reported as compatible
in the _getCompatibleCpuModels() function.

There is also a bug on libvirt that prevents the host CPU from being
properly detected. This code has a workaround for this.

A upcoming 'fake KVM on POWER' mode is partially included, adding
a configuration parameter indicating to VDSM if it must report fake
capabilities, so a x86_64 host could be used to validate POWER specific
code.

Change-Id: I42c4d00ace06805edbe765d975b40c9311a1fa9b
Signed-off-by: Vitor de Lima <[email protected]>
---
M lib/vdsm/config.py.in
M tests/capsTests.py
M vdsm/caps.py
3 files changed, 93 insertions(+), 36 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/37/17437/1

diff --git a/lib/vdsm/config.py.in b/lib/vdsm/config.py.in
index bdbd91a..d9b0db4 100644
--- a/lib/vdsm/config.py.in
+++ b/lib/vdsm/config.py.in
@@ -135,6 +135,8 @@
 
         ('fake_kvm_support', 'false', None),
 
+        ('fake_kvm_architecture', 'x86_64', None),
+
         ('xmlrpc_enable', 'true', 'Enable the xmlrpc server'),
 
         ('jsonrpc_enable', 'true', 'Enable the JSON RPC server'),
diff --git a/tests/capsTests.py b/tests/capsTests.py
index 9c7ea12..5c7c16c 100644
--- a/tests/capsTests.py
+++ b/tests/capsTests.py
@@ -31,7 +31,7 @@
         testPath = os.path.realpath(__file__)
         dirName = os.path.split(testPath)[0]
         path = os.path.join(dirName, "cpu_info.out")
-        c = caps.CpuInfo(path)
+        c = caps.CpuInfo(path, 'x86_64')
         self.assertEqual(set(c.flags()), set("""fpu vme de pse tsc msr pae
                                                 mce cx8 apic mtrr pge mca
                                                 cmov pat pse36 clflush dts
@@ -79,7 +79,7 @@
         testPath = os.path.realpath(__file__)
         dirName = os.path.split(testPath)[0]
         path = os.path.join(dirName, "caps_libvirt_amd_6274.out")
-        machines = caps._getEmulatedMachines(file(path).read())
+        machines = caps._getEmulatedMachines('x86_64', file(path).read())
         expectedMachines = ['pc-0.15', 'pc', 'pc-1.0', 'pc-0.14',
                             'pc-0.13', 'pc-0.12', 'pc-0.11',
                             'pc-0.10', 'isapc']
diff --git a/vdsm/caps.py b/vdsm/caps.py
index 3a7a6a2..e19ffcb 100644
--- a/vdsm/caps.py
+++ b/vdsm/caps.py
@@ -38,6 +38,8 @@
 from vdsm import utils
 import storage.hba
 
+import platform
+
 # For debian systems we can use python-apt if available
 try:
     import apt
@@ -64,10 +66,12 @@
 
 
 class CpuInfo(object):
-    def __init__(self, cpuinfo='/proc/cpuinfo'):
+    def __init__(self, cpuinfo='/proc/cpuinfo', hostArch='x86_64'):
         """Parse /proc/cpuinfo"""
         self._info = {}
         p = {}
+        self.arch = hostArch
+
         for line in file(cpuinfo):
             if line.strip() == '':
                 p = {}
@@ -79,13 +83,23 @@
                 p[key] = value
 
     def flags(self):
-        return self._info.itervalues().next()['flags'].split()
+        if self.arch == 'x86_64':
+            return self._info.itervalues().next()['flags'].split()
+        elif self.arch == 'ppc64':
+            return ['powernv']
 
     def mhz(self):
-        return self._info.itervalues().next()['cpu MHz']
+        if self.arch == 'x86_64':
+            return self._info.itervalues().next()['cpu MHz']
+        elif self.arch == 'ppc64':
+            clock = self._info.itervalues().next()['clock']
+            return clock[:-3]
 
     def model(self):
-        return self._info.itervalues().next()['model name']
+        if self.arch == 'x86_64':
+            return self._info.itervalues().next()['model name']
+        elif self.arch == 'ppc64':
+            return self._info.itervalues().next()['cpu']
 
 
 class CpuTopology(object):
@@ -131,46 +145,76 @@
 
 
 @utils.memoized
-def _getEmulatedMachines(capabilities=None):
+def _getEmulatedMachines(arch='x86_64', capabilities=None):
     if capabilities is None:
         capabilities = _getCapsXMLStr()
     caps = minidom.parseString(capabilities)
+
     for archTag in caps.getElementsByTagName('arch'):
-        if archTag.getAttribute('name') == 'x86_64':
+        if archTag.getAttribute('name') == arch:
             return [m.firstChild.data for m in archTag.childNodes
                     if m.nodeName == 'machine']
     return []
 
 
-def _getAllCpuModels():
+def _getAllCpuModels(arch):
     cpu_map = minidom.parseString(
         file('/usr/share/libvirt/cpu_map.xml').read())
 
+    if arch == 'x86_64':
+        arch = 'x86'
+
+    architectureElements = cpu_map.getElementsByTagName('arch')
+
     allModels = dict()
-    for m in cpu_map.getElementsByTagName('arch')[0].childNodes:
-        if m.nodeName != 'model':
-            continue
-        element = m.getElementsByTagName('vendor')
-        if element:
-            vendor = element[0].getAttribute('name')
-        else:
-            # If current model doesn't have a vendor, check if it has a model
-            # that it is based on. The models in the cpu_map.xml file are
-            # sorted in a way that the base model is always defined before.
-            element = m.getElementsByTagName('model')
-            if element:
-                vendor = allModels.get(element[0].getAttribute('name'), None)
-            else:
-                vendor = None
-        allModels[m.getAttribute('name')] = vendor
+
+    for a in architectureElements:
+        if a.getAttribute('name') == arch:
+            for m in a.childNodes:
+                if m.nodeName != 'model':
+                    continue
+                element = m.getElementsByTagName('vendor')
+                if element:
+                    vendor = element[0].getAttribute('name')
+                else:
+                    # If current model doesn't have a vendor, check if it has
+                    # a model that it is based on. The models in the
+                    # cpu_map.xml file are sorted in a way that the base model
+                    # is always defined before.
+                    element = m.getElementsByTagName('model')
+                    if element:
+                        baseModel = element[0].getAttribute('name')
+                        vendor = allModels.get(baseModel, None)
+                    else:
+                        vendor = None
+                allModels[m.getAttribute('name')] = vendor
 
     return allModels
 
 
 @utils.memoized
-def _getCompatibleCpuModels():
+def _getCompatibleCpuModels(arch):
+
+    if arch == 'ppc64':
+        # The entire POWER7 family is incompatible with each other, so
+        # it is enough to list only the host processor and its version
+        # This is also a hack around libvirt BZ#988077
+
+        for line in file('/proc/cpuinfo'):
+            if line.strip() == '':
+                continue
+            key, value = map(str.strip, line.split(':', 1))
+
+            if key == 'revision':
+                revision = value.split()[0]
+
+        if revision == '2.0':
+            return ['model_POWER7']
+        else:
+            return ['model_POWER7_v' + revision]
+
     c = libvirtconnection.get()
-    allModels = _getAllCpuModels()
+    allModels = _getAllCpuModels(arch)
 
     def compatible(model, vendor):
         if not vendor:
@@ -251,13 +295,20 @@
 
 
 def get():
+    hostArch = platform.machine()
+
+    if config.getboolean('vars', 'fake_kvm_support'):
+        targetArch = config.get('vars', 'fake_kvm_architecture')
+    else:
+        targetArch = hostArch
+
     caps = {}
 
     caps['kvmEnabled'] = \
         str(config.getboolean('vars', 'fake_kvm_support') or
             os.path.exists('/dev/kvm')).lower()
 
-    cpuInfo = CpuInfo()
+    cpuInfo = CpuInfo(hostArch=hostArch)
     cpuTopology = CpuTopology()
     if config.getboolean('vars', 'report_host_threads_as_cores'):
         caps['cpuCores'] = str(cpuTopology.threads())
@@ -268,16 +319,20 @@
     caps['cpuSockets'] = str(cpuTopology.sockets())
     caps['cpuSpeed'] = cpuInfo.mhz()
     if config.getboolean('vars', 'fake_kvm_support'):
-        caps['cpuModel'] = 'Intel(Fake) CPU'
-        flags = set(cpuInfo.flags() + ['vmx', 'sse2', 'nx'])
-        caps['cpuFlags'] = ','.join(flags) + 'model_486,model_pentium,' \
-            'model_pentium2,model_pentium3,model_pentiumpro,model_qemu32,' \
-            'model_coreduo,model_core2duo,model_n270,model_Conroe,' \
-            'model_Penryn,model_Nehalem,model_Opteron_G1'
+        if config.get('vars', 'fake_kvm_architecture') == 'x86_64':
+            caps['cpuModel'] = 'Intel(Fake) CPU'
+            flags = set(cpuInfo.flags() + ['vmx', 'sse2', 'nx'])
+            caps['cpuFlags'] = ','.join(flags) + 'model_486,model_pentium,' \
+                'model_pentium2,model_pentium3,model_pentiumpro,' \
+                'model_qemu32,model_coreduo,model_core2duo,model_n270,' \
+                'model_Conroe,model_Penryn,model_Nehalem,model_Opteron_G1'
+        elif config.get('vars', 'fake_kvm_architecture') == 'ppc64':
+            caps['cpuModel'] = 'POWER 7 (fake)'
+            caps['cpuFlags'] = 'powernv,model_POWER7'
     else:
         caps['cpuModel'] = cpuInfo.model()
         caps['cpuFlags'] = ','.join(cpuInfo.flags() +
-                                    _getCompatibleCpuModels())
+                                    _getCompatibleCpuModels(hostArch))
 
     caps.update(dsaversion.version_info)
     caps.update(netinfo.get())
@@ -290,7 +345,7 @@
     caps['operatingSystem'] = osversion()
     caps['uuid'] = utils.getHostUUID()
     caps['packages2'] = _getKeyPackages()
-    caps['emulatedMachines'] = _getEmulatedMachines()
+    caps['emulatedMachines'] = _getEmulatedMachines(targetArch)
     caps['ISCSIInitiatorName'] = _getIscsiIniName()
     caps['HBAInventory'] = storage.hba.HBAInventory()
     caps['vmTypes'] = ['kvm']


-- 
To view, visit http://gerrit.ovirt.org/17437
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I42c4d00ace06805edbe765d975b40c9311a1fa9b
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Vitor de Lima <[email protected]>
_______________________________________________
vdsm-patches mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches

Reply via email to