Revision 06c9a520 lib/hypervisor/hv_xen.py
b/lib/hypervisor/hv_xen.py | ||
---|---|---|
158 | 158 |
return _ParseXmList(lines, include_node) |
159 | 159 |
|
160 | 160 |
|
161 |
def _ParseNodeInfo(info): |
|
162 |
"""Return information about the node. |
|
163 |
|
|
164 |
@return: a dict with the following keys (memory values in MiB): |
|
165 |
- memory_total: the total memory size on the node |
|
166 |
- memory_free: the available memory on the node for instances |
|
167 |
- nr_cpus: total number of CPUs |
|
168 |
- nr_nodes: in a NUMA system, the number of domains |
|
169 |
- nr_sockets: the number of physical CPU sockets in the node |
|
170 |
- hv_version: the hypervisor version in the form (major, minor) |
|
171 |
|
|
172 |
""" |
|
173 |
result = {} |
|
174 |
cores_per_socket = threads_per_core = nr_cpus = None |
|
175 |
xen_major, xen_minor = None, None |
|
176 |
memory_total = None |
|
177 |
memory_free = None |
|
178 |
|
|
179 |
for line in info.splitlines(): |
|
180 |
fields = line.split(":", 1) |
|
181 |
|
|
182 |
if len(fields) < 2: |
|
183 |
continue |
|
184 |
|
|
185 |
(key, val) = map(lambda s: s.strip(), fields) |
|
186 |
|
|
187 |
# Note: in Xen 3, memory has changed to total_memory |
|
188 |
if key in ("memory", "total_memory"): |
|
189 |
memory_total = int(val) |
|
190 |
elif key == "free_memory": |
|
191 |
memory_free = int(val) |
|
192 |
elif key == "nr_cpus": |
|
193 |
nr_cpus = result["cpu_total"] = int(val) |
|
194 |
elif key == "nr_nodes": |
|
195 |
result["cpu_nodes"] = int(val) |
|
196 |
elif key == "cores_per_socket": |
|
197 |
cores_per_socket = int(val) |
|
198 |
elif key == "threads_per_core": |
|
199 |
threads_per_core = int(val) |
|
200 |
elif key == "xen_major": |
|
201 |
xen_major = int(val) |
|
202 |
elif key == "xen_minor": |
|
203 |
xen_minor = int(val) |
|
204 |
|
|
205 |
if None not in [cores_per_socket, threads_per_core, nr_cpus]: |
|
206 |
result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core) |
|
207 |
|
|
208 |
if memory_free is not None: |
|
209 |
result["memory_free"] = memory_free |
|
210 |
|
|
211 |
if memory_total is not None: |
|
212 |
result["memory_total"] = memory_total |
|
213 |
|
|
214 |
if not (xen_major is None or xen_minor is None): |
|
215 |
result[constants.HV_NODEINFO_KEY_VERSION] = (xen_major, xen_minor) |
|
216 |
|
|
217 |
return result |
|
218 |
|
|
219 |
|
|
220 |
def _MergeInstanceInfo(info, fn): |
|
221 |
"""Updates node information from L{_ParseNodeInfo} with instance info. |
|
222 |
|
|
223 |
@type info: dict |
|
224 |
@param info: Result from L{_ParseNodeInfo} |
|
225 |
@type fn: callable |
|
226 |
@param fn: Function returning result of running C{xm list} |
|
227 |
@rtype: dict |
|
228 |
|
|
229 |
""" |
|
230 |
total_instmem = 0 |
|
231 |
|
|
232 |
for (name, _, mem, vcpus, _, _) in fn(True): |
|
233 |
if name == _DOM0_NAME: |
|
234 |
info["memory_dom0"] = mem |
|
235 |
info["dom0_cpus"] = vcpus |
|
236 |
|
|
237 |
# Include Dom0 in total memory usage |
|
238 |
total_instmem += mem |
|
239 |
|
|
240 |
memory_free = info.get("memory_free") |
|
241 |
memory_total = info.get("memory_total") |
|
242 |
|
|
243 |
# Calculate memory used by hypervisor |
|
244 |
if None not in [memory_total, memory_free, total_instmem]: |
|
245 |
info["memory_hv"] = memory_total - memory_free - total_instmem |
|
246 |
|
|
247 |
return info |
|
248 |
|
|
249 |
|
|
250 |
def _GetNodeInfo(info, fn): |
|
251 |
"""Combines L{_MergeInstanceInfo} and L{_ParseNodeInfo}. |
|
252 |
|
|
253 |
""" |
|
254 |
return _MergeInstanceInfo(_ParseNodeInfo(info), fn) |
|
255 |
|
|
256 |
|
|
161 | 257 |
class XenHypervisor(hv_base.BaseHypervisor): |
162 | 258 |
"""Xen generic hypervisor interface |
163 | 259 |
|
... | ... | |
372 | 468 |
def GetNodeInfo(self): |
373 | 469 |
"""Return information about the node. |
374 | 470 |
|
375 |
@return: a dict with the following keys (memory values in MiB): |
|
376 |
- memory_total: the total memory size on the node |
|
377 |
- memory_free: the available memory on the node for instances |
|
378 |
- memory_dom0: the memory used by the node itself, if available |
|
379 |
- nr_cpus: total number of CPUs |
|
380 |
- nr_nodes: in a NUMA system, the number of domains |
|
381 |
- nr_sockets: the number of physical CPU sockets in the node |
|
382 |
- hv_version: the hypervisor version in the form (major, minor) |
|
471 |
@see: L{_GetNodeInfo} and L{_ParseNodeInfo} |
|
383 | 472 |
|
384 | 473 |
""" |
474 |
# TODO: Abstract running Xen command for testing |
|
385 | 475 |
result = utils.RunCmd([constants.XEN_CMD, "info"]) |
386 | 476 |
if result.failed: |
387 | 477 |
logging.error("Can't run 'xm info' (%s): %s", result.fail_reason, |
388 | 478 |
result.output) |
389 | 479 |
return None |
390 | 480 |
|
391 |
xmoutput = result.stdout.splitlines() |
|
392 |
result = {} |
|
393 |
cores_per_socket = threads_per_core = nr_cpus = None |
|
394 |
xen_major, xen_minor = None, None |
|
395 |
memory_total = None |
|
396 |
memory_free = None |
|
397 |
|
|
398 |
for line in xmoutput: |
|
399 |
splitfields = line.split(":", 1) |
|
400 |
|
|
401 |
if len(splitfields) > 1: |
|
402 |
key = splitfields[0].strip() |
|
403 |
val = splitfields[1].strip() |
|
404 |
|
|
405 |
# note: in xen 3, memory has changed to total_memory |
|
406 |
if key == "memory" or key == "total_memory": |
|
407 |
memory_total = int(val) |
|
408 |
elif key == "free_memory": |
|
409 |
memory_free = int(val) |
|
410 |
elif key == "nr_cpus": |
|
411 |
nr_cpus = result["cpu_total"] = int(val) |
|
412 |
elif key == "nr_nodes": |
|
413 |
result["cpu_nodes"] = int(val) |
|
414 |
elif key == "cores_per_socket": |
|
415 |
cores_per_socket = int(val) |
|
416 |
elif key == "threads_per_core": |
|
417 |
threads_per_core = int(val) |
|
418 |
elif key == "xen_major": |
|
419 |
xen_major = int(val) |
|
420 |
elif key == "xen_minor": |
|
421 |
xen_minor = int(val) |
|
422 |
|
|
423 |
if None not in [cores_per_socket, threads_per_core, nr_cpus]: |
|
424 |
result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core) |
|
425 |
|
|
426 |
total_instmem = 0 |
|
427 |
for (name, _, mem, vcpus, _, _) in self._GetXmList(True): |
|
428 |
if name == _DOM0_NAME: |
|
429 |
result["memory_dom0"] = mem |
|
430 |
result["dom0_cpus"] = vcpus |
|
431 |
|
|
432 |
# Include Dom0 in total memory usage |
|
433 |
total_instmem += mem |
|
434 |
|
|
435 |
if memory_free is not None: |
|
436 |
result["memory_free"] = memory_free |
|
437 |
|
|
438 |
if memory_total is not None: |
|
439 |
result["memory_total"] = memory_total |
|
440 |
|
|
441 |
# Calculate memory used by hypervisor |
|
442 |
if None not in [memory_total, memory_free, total_instmem]: |
|
443 |
result["memory_hv"] = memory_total - memory_free - total_instmem |
|
444 |
|
|
445 |
if not (xen_major is None or xen_minor is None): |
|
446 |
result[constants.HV_NODEINFO_KEY_VERSION] = (xen_major, xen_minor) |
|
447 |
|
|
448 |
return result |
|
481 |
return _GetNodeInfo(result.stdout, self._GetXmList) |
|
449 | 482 |
|
450 | 483 |
@classmethod |
451 | 484 |
def GetInstanceConsole(cls, instance, hvparams, beparams): |
Also available in: Unified diff