Repository: RedHatInsights/insights-core

Issue:
Parser CpuInfo can not handle IBM/S390 type
Current CpuInfo data arch is mainly created for x86_64, however, it can not handle IBM/S390 output, and will report condition error in RAT.

~~~
    # cat insights-z144108d-20200615024626/proc/cpuinfo
    vendor_id       : IBM/S390
    # processors    : 10
    bogomips per cpu: 3033.00
    max thread id   : 0
    features        : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx sie
    facilities      : 0 1 2 3 4 6 7 8 9 10 12 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 30 31 32 33 34 35 36 37 40 41 42 43 44 45 46 47 48 49 50 51 52 53 55 57 73 74 75 76 77 80 81 82 128 129
    cache0          : level=1 type=Data scope=Private size=128K line_size=256 associativity=8
    cache1          : level=1 type=Instruction scope=Private size=96K line_size=256 associativity=6
    cache2          : level=2 type=Data scope=Private size=2048K line_size=256 associativity=8
    cache3          : level=2 type=Instruction scope=Private size=2048K line_size=256 associativity=8
    cache4          : level=3 type=Unified scope=Shared size=65536K line_size=256 associativity=16
    cache5          : level=4 type=Unified scope=Shared size=491520K line_size=256 associativity=30
    processor 0: version = FF,  identification = 13C7B7,  machine = 2964
    processor 1: version = FF,  identification = 13C7B7,  machine = 2964
    processor 2: version = FF,  identification = 13C7B7,  machine = 2964
    processor 3: version = FF,  identification = 13C7B7,  machine = 2964
    processor 4: version = FF,  identification = 13C7B7,  machine = 2964
    processor 5: version = FF,  identification = 13C7B7,  machine = 2964
    processor 6: version = FF,  identification = 13C7B7,  machine = 2964
    processor 7: version = FF,  identification = 13C7B7,  machine = 2964
    processor 8: version = FF,  identification = 13C7B7,  machine = 2964
    processor 9: version = FF,  identification = 13C7B7,  machine = 2964
~~~


Discussion:

Resolving patch:
diff --git a/insights/parsers/cpuinfo.py b/insights/parsers/cpuinfo.py
--- a/insights/parsers/cpuinfo.py
+++ b/insights/parsers/cpuinfo.py
@@ -143,17 +143,36 @@ def parse_content(self, content):
             "revision": "revision",
             "address sizes": "address_sizes",
             "bugs": "bugs",
-            "microcode": "microcode"
+            "microcode": "microcode",
+            "cpu MHz static": "clockspeeds",
+            "features": "features"
         }
 
         for line in get_active_lines(content, comment_char="COMMAND>"):
             key, value = [p.strip() for p in line.split(":", 1)]
+            # For s390x the : symbol is after the number instead of before.
+            # So re-split and set the key and value before checking mappings.
+            if key.startswith("processor") and key[-1].isdigit():
+                key, value = key.split(" ", 1)
+
             if key in mappings:
                 self.data[mappings[key]].append(value)
 
         if "cpu" in self.data and "POWER" in self.data["cpu"][0]:
             # this works differently than on x86 and is not per-cpu
-            del self.data["model_ids"]
+            model_id = self.data["model_ids"][0]
+            cpu_cnt = self.cpu_count
+            self.data["model_ids"] = [model_id] * cpu_cnt
+
+        # s390x cpuinfo is setup drastically differently than other arches.
+        # It doesn't print the same information for each cpu, like other arches.
+        # So any info not repeated per cpu, copy, delete and then add for each cpu entry.
+        if "vendors" in self.data and "IBM/S390" in self.data["vendors"][0]:
+            vendor = self.data["vendors"][0]
+            features = self.data["features"][0]
+            cpu_cnt = self.cpu_count
+            self.data["vendors"] = [vendor] * cpu_cnt
+            self.data["features"] = [features] * cpu_cnt
 
         self.data = dict(self.data)
 


Test patch:
diff --git a/insights/parsers/tests/test_cpuinfo.py b/insights/parsers/tests/test_cpuinfo.py
--- a/insights/parsers/tests/test_cpuinfo.py
+++ b/insights/parsers/tests/test_cpuinfo.py
@@ -1402,6 +1402,48 @@
 machine		: CHRP IBM,8231-E2D
 """
 
+S390X_CPUINFO_R7 = """
+vendor_id       : IBM/S390
+# processors    : 2
+bogomips per cpu: 24038.00
+max thread id   : 0
+features	: esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs
+facilities      : 0 1 2 3 4 6 7 8 9 10 12 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 30 31 32 33 34 35 36 37 38 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 57 58 59 60 61 73 74 75 76 77 80 81 82 128 129 130 131 133 134 135 146 147 148 150 151 152 155 156 168
+cache0          : level=1 type=Data scope=Private size=128K line_size=256 associativity=8
+cache1          : level=1 type=Instruction scope=Private size=128K line_size=256 associativity=8
+cache2          : level=2 type=Data scope=Private size=4096K line_size=256 associativity=8
+cache3          : level=2 type=Instruction scope=Private size=4096K line_size=256 associativity=8
+cache4          : level=3 type=Unified scope=Shared size=262144K line_size=256 associativity=32
+cache5          : level=4 type=Unified scope=Shared size=983040K line_size=256 associativity=60
+processor 0: version = FF,  identification = 0E19C8,  machine = 8561
+processor 1: version = FF,  identification = 0E19C8,  machine = 8561
+"""
+
+S390X_CPUINFO_R8 = """
+vendor_id       : IBM/S390
+# processors    : 2
+bogomips per cpu: 21881.00
+max thread id   : 0
+features	: esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs
+facilities      : 0 1 2 3 4 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 30 31 32 33 34 35 36 37 38 40 41 42 43 44 45 47 48 49 50 51 52 53 54 57 58 59 60 64 65 69 71 72 73 74 75 76 77 78 80 81 82 129 130 131 133 134 135 138 139 146 147
+cache0          : level=1 type=Data scope=Private size=128K line_size=256 associativity=8
+cache1          : level=1 type=Instruction scope=Private size=128K line_size=256 associativity=8
+cache2          : level=2 type=Data scope=Private size=4096K line_size=256 associativity=8
+cache3          : level=2 type=Instruction scope=Private size=2048K line_size=256 associativity=8
+cache4          : level=3 type=Unified scope=Shared size=131072K line_size=256 associativity=32
+cache5          : level=4 type=Unified scope=Shared size=688128K line_size=256 associativity=42
+processor 0: version = FF,  identification = 1E41E8,  machine = 3906
+processor 1: version = FF,  identification = 1E41E8,  machine = 3906
+
+cpu number      : 0
+cpu MHz dynamic : 5208
+cpu MHz static  : 5208
+
+cpu number      : 1
+cpu MHz dynamic : 5208
+cpu MHz static  : 5208
+"""
+
 
 def test_cpuinfo():
     cpu_info = CpuInfo(context_wrap(CPUINFO))
@@ -1487,6 +1529,25 @@ def test_power_cpuinfo():
     for i, cpu in enumerate(cpu_info):
         assert cpu["cpu"] == "POWER7 (architected), altivec supported"
         assert cpu["revision"] == "2.0 (pvr 004a 0200)"
+        assert cpu["model_ids"] == "IBM,8231-E2D"
+
+
+def test_s390x_cpuinfo():
+    def test_common(info):
+        assert info.cpu_count == 2
+        assert info.socket_count == 0
+        assert info.vendor == "IBM/S390"
+        for i, cpu in enumerate(info):
+            assert cpu["features"] == "esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs"
+
+    # Test r7 output.
+    cpu_info = CpuInfo(context_wrap(S390X_CPUINFO_R7))
+    test_common(cpu_info)
+
+    # Test r8 output.
+    cpu_info = CpuInfo(context_wrap(S390X_CPUINFO_R8))
+    test_common(cpu_info)
+    assert cpu_info.cpu_speed == "5208"
 
 
 def test_cpuinfo_doc_examples():