Browse code

Update libvirt cpu map before starting nova

We are trying to get a working 64bit qemu cpu model in the gate for nova
live migration testing. It appears that we need to make this change
prior to nova starting.

Make the change in configure_libvirt() to handle this along with the
other libvirt config updates. This allows us to restart the libvirt
service once. This function calls a python tool which parses and updates
the XML if necessary.

Change-Id: I00667713bfba67ab8cedbcb1660ff94d4f4bcc07

Clark Boylan authored on 2015/03/28 01:19:57
Showing 2 changed files
... ...
@@ -110,10 +110,18 @@ EOF
110 110
         fi
111 111
     fi
112 112
 
113
+    # Update the libvirt cpu map with a gate64 cpu model. This enables nova
114
+    # live migration for 64bit guest OSes on heterogenous cloud "hardware".
115
+    if [[ -f /usr/share/libvirt/cpu_map.xml ]] ; then
116
+        sudo $TOP_DIR/tools/cpu_map_update.py /usr/share/libvirt/cpu_map.xml
117
+    fi
118
+
113 119
     # libvirt detects various settings on startup, as we potentially changed
114 120
     # the system configuration (modules, filesystems), we need to restart
115
-    # libvirt to detect those changes.
116
-    restart_service $LIBVIRT_DAEMON
121
+    # libvirt to detect those changes. Use a stop start as otherwise the new
122
+    # cpu_map is not loaded properly on some systems (Ubuntu).
123
+    stop_service $LIBVIRT_DAEMON
124
+    start_service $LIBVIRT_DAEMON
117 125
 }
118 126
 
119 127
 
120 128
new file mode 100755
... ...
@@ -0,0 +1,89 @@
0
+#!/usr/bin/env python
1
+#
2
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
3
+# not use this file except in compliance with the License. You may obtain
4
+# a copy of the License at
5
+#
6
+#      http://www.apache.org/licenses/LICENSE-2.0
7
+#
8
+# Unless required by applicable law or agreed to in writing, software
9
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
+# License for the specific language governing permissions and limitations
12
+# under the License.
13
+
14
+# This small script updates the libvirt CPU map to add a gate64 cpu model
15
+# that can be used to enable a common 64bit capable feature set across
16
+# devstack nodes so that features like nova live migration work.
17
+
18
+import sys
19
+import xml.etree.ElementTree as ET
20
+from xml.dom import minidom
21
+
22
+
23
+def update_cpu_map(tree):
24
+    root = tree.getroot()
25
+    cpus = root#.find("cpus")
26
+    x86 = None
27
+    for arch in cpus.findall("arch"):
28
+        if arch.get("name") == "x86":
29
+            x86 = arch
30
+            break
31
+    if x86 is not None:
32
+        # Create a gate64 cpu model that is core2duo less monitor and pse36
33
+        gate64 = ET.SubElement(x86, "model")
34
+        gate64.set("name", "gate64")
35
+        ET.SubElement(gate64, "vendor").set("name", "Intel")
36
+        ET.SubElement(gate64, "feature").set("name", "fpu")
37
+        ET.SubElement(gate64, "feature").set("name", "de")
38
+        ET.SubElement(gate64, "feature").set("name", "pse")
39
+        ET.SubElement(gate64, "feature").set("name", "tsc")
40
+        ET.SubElement(gate64, "feature").set("name", "msr")
41
+        ET.SubElement(gate64, "feature").set("name", "pae")
42
+        ET.SubElement(gate64, "feature").set("name", "mce")
43
+        ET.SubElement(gate64, "feature").set("name", "cx8")
44
+        ET.SubElement(gate64, "feature").set("name", "apic")
45
+        ET.SubElement(gate64, "feature").set("name", "sep")
46
+        ET.SubElement(gate64, "feature").set("name", "pge")
47
+        ET.SubElement(gate64, "feature").set("name", "cmov")
48
+        ET.SubElement(gate64, "feature").set("name", "pat")
49
+        ET.SubElement(gate64, "feature").set("name", "mmx")
50
+        ET.SubElement(gate64, "feature").set("name", "fxsr")
51
+        ET.SubElement(gate64, "feature").set("name", "sse")
52
+        ET.SubElement(gate64, "feature").set("name", "sse2")
53
+        ET.SubElement(gate64, "feature").set("name", "vme")
54
+        ET.SubElement(gate64, "feature").set("name", "mtrr")
55
+        ET.SubElement(gate64, "feature").set("name", "mca")
56
+        ET.SubElement(gate64, "feature").set("name", "clflush")
57
+        ET.SubElement(gate64, "feature").set("name", "pni")
58
+        ET.SubElement(gate64, "feature").set("name", "nx")
59
+        ET.SubElement(gate64, "feature").set("name", "ssse3")
60
+        ET.SubElement(gate64, "feature").set("name", "syscall")
61
+        ET.SubElement(gate64, "feature").set("name", "lm")
62
+
63
+
64
+def format_xml(root):
65
+    # Adapted from http://pymotw.com/2/xml/etree/ElementTree/create.html
66
+    # thank you dhellmann
67
+    rough_string = ET.tostring(root, encoding="UTF-8")
68
+    dom_parsed = minidom.parseString(rough_string)
69
+    return dom_parsed.toprettyxml("  ", encoding="UTF-8")
70
+
71
+
72
+def main():
73
+    if len(sys.argv) != 2:
74
+        raise Exception("Must pass path to cpu_map.xml to update")
75
+    cpu_map = sys.argv[1]
76
+    tree = ET.parse(cpu_map)
77
+    for model in tree.getroot().iter("model"):
78
+        if model.get("name") == "gate64":
79
+            # gate64 model is already present
80
+            return
81
+    update_cpu_map(tree)
82
+    pretty_xml = format_xml(tree.getroot())
83
+    with open(cpu_map, 'w') as f:
84
+        f.write(pretty_xml)
85
+
86
+
87
+if __name__ == "__main__":
88
+    main()