debuggers.hg

view tools/python/xen/xend/XendNode.py @ 17989:e65fe28b5288

XenAPI: Add Physical PCI Device (PPCI) Support

Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@ab.jp.nec.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jul 03 10:26:16 2008 +0100 (2008-07-03)
parents 250606290439
children f8221241d187
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 # Copyright (c) 2006, 2007 Xensource Inc.
17 #============================================================================
19 import os
20 import socket
21 import xen.lowlevel.xc
23 from xen.util import Brctl
24 from xen.util import pci as PciUtil
25 from xen.xend import XendAPIStore
27 import uuid, arch
28 from XendPBD import XendPBD
29 from XendError import *
30 from XendOptions import instance as xendoptions
31 from XendQCoWStorageRepo import XendQCoWStorageRepo
32 from XendLocalStorageRepo import XendLocalStorageRepo
33 from XendLogging import log
34 from XendPIF import *
35 from XendPIFMetrics import XendPIFMetrics
36 from XendNetwork import *
37 from XendStateStore import XendStateStore
38 from XendMonitor import XendMonitor
39 from XendPPCI import XendPPCI
41 class XendNode:
42 """XendNode - Represents a Domain 0 Host."""
44 def __init__(self):
45 """Initalises the state of all host specific objects such as
47 * host
48 * host_CPU
49 * host_metrics
50 * PIF
51 * PIF_metrics
52 * network
53 * Storage Repository
54 * PPCI
55 """
57 self.xc = xen.lowlevel.xc.xc()
58 self.state_store = XendStateStore(xendoptions().get_xend_state_path())
59 self.monitor = XendMonitor()
60 self.monitor.start()
62 # load host state from XML file
63 saved_host = self.state_store.load_state('host')
64 if saved_host and len(saved_host.keys()) == 1:
65 self.uuid = saved_host.keys()[0]
66 host = saved_host[self.uuid]
67 self.name = host.get('name_label', socket.gethostname())
68 self.desc = host.get('name_description', '')
69 self.host_metrics_uuid = host.get('metrics_uuid',
70 uuid.createString())
71 try:
72 self.other_config = eval(host['other_config'])
73 except:
74 self.other_config = {}
75 self.cpus = {}
76 else:
77 self.uuid = uuid.createString()
78 self.name = socket.gethostname()
79 self.desc = ''
80 self.other_config = {}
81 self.cpus = {}
82 self.host_metrics_uuid = uuid.createString()
84 # put some arbitrary params in other_config as this
85 # is directly exposed via XenAPI
86 self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
87 self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"]
89 # load CPU UUIDs
90 saved_cpus = self.state_store.load_state('cpu')
91 for cpu_uuid, cpu in saved_cpus.items():
92 self.cpus[cpu_uuid] = cpu
94 cpuinfo = parse_proc_cpuinfo()
95 physinfo = self.physinfo_dict()
96 cpu_count = physinfo['nr_cpus']
97 cpu_features = physinfo['hw_caps']
98 virt_caps = physinfo['virt_caps']
100 # If the number of CPUs don't match, we should just reinitialise
101 # the CPU UUIDs.
102 if cpu_count != len(self.cpus):
103 self.cpus = {}
104 for i in range(cpu_count):
105 u = uuid.createString()
106 self.cpus[u] = {'uuid': u, 'number': i }
108 for u in self.cpus.keys():
109 number = self.cpus[u]['number']
110 # We can run off the end of the cpuinfo list if domain0 does not
111 # have #vcpus == #pcpus. In that case we just replicate one that's
112 # in the hash table.
113 if not cpuinfo.has_key(number):
114 number = cpuinfo.keys()[0]
115 if arch.type == "x86":
116 self.cpus[u].update(
117 { 'host' : self.uuid,
118 'features' : cpu_features,
119 'virt_caps': virt_caps,
120 'speed' : int(float(cpuinfo[number]['cpu MHz'])),
121 'vendor' : cpuinfo[number]['vendor_id'],
122 'modelname': cpuinfo[number]['model name'],
123 'stepping' : cpuinfo[number]['stepping'],
124 'flags' : cpuinfo[number]['flags'],
125 })
126 elif arch.type == "ia64":
127 self.cpus[u].update(
128 { 'host' : self.uuid,
129 'features' : cpu_features,
130 'speed' : int(float(cpuinfo[number]['cpu MHz'])),
131 'vendor' : cpuinfo[number]['vendor'],
132 'modelname': cpuinfo[number]['family'],
133 'stepping' : cpuinfo[number]['model'],
134 'flags' : cpuinfo[number]['features'],
135 })
136 else:
137 self.cpus[u].update(
138 { 'host' : self.uuid,
139 'features' : cpu_features,
140 })
142 self.srs = {}
144 # Initialise networks
145 # First configure ones off disk
146 saved_networks = self.state_store.load_state('network')
147 if saved_networks:
148 for net_uuid, network in saved_networks.items():
149 try:
150 XendNetwork.recreate(network, net_uuid)
151 except CreateUnspecifiedAttributeError:
152 log.warn("Error recreating network %s", net_uuid)
154 # Next discover any existing bridges and check
155 # they are not already configured
156 bridges = Brctl.get_state().keys()
157 configured_bridges = [XendAPIStore.get(
158 network_uuid, "network")
159 .get_name_label()
160 for network_uuid in XendNetwork.get_all()]
161 unconfigured_bridges = [bridge
162 for bridge in bridges
163 if bridge not in configured_bridges]
164 for unconfigured_bridge in unconfigured_bridges:
165 XendNetwork.create_phy(unconfigured_bridge)
167 # Initialise PIFs
168 # First configure ones off disk
169 saved_pifs = self.state_store.load_state('pif')
170 if saved_pifs:
171 for pif_uuid, pif in saved_pifs.items():
172 try:
173 XendPIF.recreate(pif, pif_uuid)
174 except CreateUnspecifiedAttributeError:
175 log.warn("Error recreating PIF %s", pif_uuid)
177 # Next discover any existing PIFs and check
178 # they are not already configured
179 configured_pifs = [XendAPIStore.get(
180 pif_uuid, "PIF")
181 .get_interface_name()
182 for pif_uuid in XendPIF.get_all()]
183 unconfigured_pifs = [(name, mtu, mac)
184 for name, mtu, mac in linux_get_phy_ifaces()
185 if name not in configured_pifs]
187 # Get a mapping from interface to bridge
188 if_to_br = dict([(i,b)
189 for (b,ifs) in Brctl.get_state().items()
190 for i in ifs])
192 for name, mtu, mac in unconfigured_pifs:
193 # Check PIF is on bridge
194 # if not, ignore
195 bridge_name = if_to_br.get(name, None)
196 if bridge_name is not None:
197 # Translate bridge name to network uuid
198 for network_uuid in XendNetwork.get_all():
199 network = XendAPIStore.get(
200 network_uuid, 'network')
201 if network.get_name_label() == bridge_name:
202 XendPIF.create_phy(network_uuid, name,
203 mac, mtu)
204 break
205 else:
206 log.debug("Cannot find network for bridge %s "
207 "when configuring PIF %s",
208 (bridge_name, name))
210 # initialise storage
211 saved_srs = self.state_store.load_state('sr')
212 if saved_srs:
213 for sr_uuid, sr_cfg in saved_srs.items():
214 if sr_cfg['type'] == 'qcow_file':
215 self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
216 elif sr_cfg['type'] == 'local':
217 self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)
219 # Create missing SRs if they don't exist
220 if not self.get_sr_by_type('local'):
221 image_sr_uuid = uuid.createString()
222 self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
224 if not self.get_sr_by_type('qcow_file'):
225 qcow_sr_uuid = uuid.createString()
226 self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
228 saved_pbds = self.state_store.load_state('pbd')
229 if saved_pbds:
230 for pbd_uuid, pbd_cfg in saved_pbds.items():
231 try:
232 XendPBD.recreate(pbd_uuid, pbd_cfg)
233 except CreateUnspecifiedAttributeError:
234 log.warn("Error recreating PBD %s", pbd_uuid)
237 # Initialise PPCIs
238 saved_ppcis = self.state_store.load_state('ppci')
239 saved_ppci_table = {}
240 if saved_ppcis:
241 for ppci_uuid, ppci_record in saved_ppcis.items():
242 try:
243 saved_ppci_table[ppci_record['name']] = ppci_uuid
244 except KeyError:
245 pass
247 for pci_dev in PciUtil.get_all_pci_devices():
248 ppci_record = {
249 'domain': pci_dev.domain,
250 'bus': pci_dev.bus,
251 'slot': pci_dev.slot,
252 'func': pci_dev.func,
253 'vendor_id': pci_dev.vendor,
254 'vendor_name': pci_dev.vendorname,
255 'device_id': pci_dev.device,
256 'device_name': pci_dev.devicename,
257 'revision_id': pci_dev.revision,
258 'class_code': pci_dev.classcode,
259 'class_name': pci_dev.classname,
260 'subsystem_vendor_id': pci_dev.subvendor,
261 'subsystem_vendor_name': pci_dev.subvendorname,
262 'subsystem_id': pci_dev.subdevice,
263 'subsystem_name': pci_dev.subdevicename,
264 'driver': pci_dev.driver
265 }
266 # If saved uuid exists, use it. Otherwise create one.
267 ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
268 XendPPCI(ppci_uuid, ppci_record)
271 ## def network_destroy(self, net_uuid):
272 ## del self.networks[net_uuid]
273 ## self.save_networks()
276 def get_PIF_refs(self):
277 log.debug(XendPIF.get_all())
278 return XendPIF.get_all()
280 ## def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
281 ## pif_uuid = None, metrics_uuid = None):
282 ## for pif in self.pifs.values():
283 ## if pif.network == network:
284 ## raise NetworkAlreadyConnected(pif.uuid)
286 ## if pif_uuid is None:
287 ## pif_uuid = uuid.createString()
288 ## if metrics_uuid is None:
289 ## metrics_uuid = uuid.createString()
291 ## metrics = XendPIFMetrics(metrics_uuid)
292 ## pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self)
293 ## metrics.set_PIF(pif)
295 ## self.pif_metrics[metrics_uuid] = metrics
296 ## self.pifs[pif_uuid] = pif
298 ## if persist:
299 ## self.save_PIFs()
300 ## self.refreshBridges()
301 ## return pif_uuid
303 ## def PIF_destroy(self, pif_uuid):
304 ## pif = self.pifs[pif_uuid]
306 ## if pif.vlan == -1:
307 ## raise PIFIsPhysical()
309 ## del self.pifs[pif_uuid]
310 ## self.save_PIFs()
313 def get_PPCI_refs(self):
314 return XendPPCI.get_all()
316 def get_ppci_by_uuid(self, ppci_uuid):
317 if ppci_uuid in self.get_PPCI_refs():
318 return ppci_uuid
319 return None
322 def save(self):
323 # save state
324 host_record = {self.uuid: {'name_label':self.name,
325 'name_description':self.desc,
326 'metrics_uuid': self.host_metrics_uuid,
327 'other_config': self.other_config}}
328 self.state_store.save_state('host',host_record)
329 self.state_store.save_state('cpu', self.cpus)
330 self.save_PIFs()
331 self.save_networks()
332 self.save_PBDs()
333 self.save_SRs()
334 self.save_PPCIs()
336 def save_PIFs(self):
337 pif_records = dict([(pif_uuid, XendAPIStore.get(
338 pif_uuid, "PIF").get_record())
339 for pif_uuid in XendPIF.get_all()])
340 self.state_store.save_state('pif', pif_records)
342 def save_networks(self):
343 net_records = dict([(network_uuid, XendAPIStore.get(
344 network_uuid, "network").get_record())
345 for network_uuid in XendNetwork.get_all()])
346 self.state_store.save_state('network', net_records)
348 def save_PBDs(self):
349 pbd_records = dict([(pbd_uuid, XendAPIStore.get(
350 pbd_uuid, "PBD").get_record())
351 for pbd_uuid in XendPBD.get_all()])
352 self.state_store.save_state('pbd', pbd_records)
354 def save_SRs(self):
355 sr_records = dict([(k, v.get_record(transient = False))
356 for k, v in self.srs.items()])
357 self.state_store.save_state('sr', sr_records)
359 def save_PPCIs(self):
360 ppci_records = dict([(ppci_uuid, XendAPIStore.get(
361 ppci_uuid, "PPCI").get_record())
362 for ppci_uuid in XendPPCI.get_all()])
363 self.state_store.save_state('ppci', ppci_records)
365 def shutdown(self):
366 return 0
368 def reboot(self):
369 return 0
371 def notify(self, _):
372 return 0
374 #
375 # Ref validation
376 #
378 def is_valid_host(self, host_ref):
379 return (host_ref == self.uuid)
381 def is_valid_cpu(self, cpu_ref):
382 return (cpu_ref in self.cpus)
384 def is_valid_sr(self, sr_ref):
385 return (sr_ref in self.srs)
387 def is_valid_vdi(self, vdi_ref):
388 for sr in self.srs.values():
389 if sr.is_valid_vdi(vdi_ref):
390 return True
391 return False
393 #
394 # Storage Repositories
395 #
397 def get_sr(self, sr_uuid):
398 return self.srs.get(sr_uuid)
400 def get_sr_by_type(self, sr_type):
401 return [sr.uuid for sr in self.srs.values() if sr.type == sr_type]
403 def get_sr_by_name(self, name):
404 return [sr.uuid for sr in self.srs.values() if sr.name_label == name]
406 def get_all_sr_uuid(self):
407 return self.srs.keys()
409 def get_vdi_by_uuid(self, vdi_uuid):
410 for sr in self.srs.values():
411 if sr.is_valid_vdi(vdi_uuid):
412 return sr.get_vdi_by_uuid(vdi_uuid)
413 return None
415 def get_vdi_by_name_label(self, name):
416 for sr in self.srs.values():
417 vdi = sr.get_vdi_by_name_label(name)
418 if vdi:
419 return vdi
420 return None
422 def get_sr_containing_vdi(self, vdi_uuid):
423 for sr in self.srs.values():
424 if sr.is_valid_vdi(vdi_uuid):
425 return sr
426 return None
429 #
430 # Host Functions
431 #
433 def xen_version(self):
434 info = self.xc.xeninfo()
436 info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info}
438 # Add xend_config_format
439 info.update(self.xendinfo_dict())
441 # Add version info about machine
442 info.update(self.nodeinfo_dict())
444 # Add specific xen version info
445 xeninfo_dict = self.xeninfo_dict()
447 info.update({
448 "xen_major": xeninfo_dict["xen_major"],
449 "xen_minor": xeninfo_dict["xen_minor"],
450 "xen_extra": xeninfo_dict["xen_extra"],
451 "cc_compiler": xeninfo_dict["cc_compiler"],
452 "cc_compile_by": xeninfo_dict["cc_compile_by"],
453 "cc_compile_domain": xeninfo_dict["cc_compile_domain"],
454 "cc_compile_date": xeninfo_dict["cc_compile_date"],
455 "xen_changeset": xeninfo_dict["xen_changeset"]
456 })
458 return info
460 def get_name(self):
461 return self.name
463 def set_name(self, new_name):
464 self.name = new_name
466 def get_description(self):
467 return self.desc
469 def set_description(self, new_desc):
470 self.desc = new_desc
472 def get_uuid(self):
473 return self.uuid
475 def get_capabilities(self):
476 return self.xc.xeninfo()['xen_caps'].split(" ")
478 #
479 # Host CPU Functions
480 #
482 def get_host_cpu_by_uuid(self, host_cpu_uuid):
483 if host_cpu_uuid in self.cpus:
484 return host_cpu_uuid
485 raise XendError('Invalid CPU UUID')
487 def get_host_cpu_refs(self):
488 return self.cpus.keys()
490 def get_host_cpu_uuid(self, host_cpu_ref):
491 if host_cpu_ref in self.cpus:
492 return host_cpu_ref
493 else:
494 raise XendError('Invalid CPU Reference')
496 def get_host_cpu_field(self, ref, field):
497 try:
498 return self.cpus[ref][field]
499 except KeyError:
500 raise XendError('Invalid CPU Reference')
502 def get_host_cpu_load(self, host_cpu_ref):
503 host_cpu = self.cpus.get(host_cpu_ref)
504 if not host_cpu:
505 return 0.0
507 vcpu = int(host_cpu['number'])
508 cpu_loads = self.monitor.get_domain_vcpus_util()
509 if 0 in cpu_loads and vcpu in cpu_loads[0]:
510 return cpu_loads[0][vcpu]
512 return 0.0
514 def get_vcpus_policy(self):
515 sched_id = self.xc.sched_id_get()
516 if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
517 return 'sedf'
518 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
519 return 'credit'
520 else:
521 return 'unknown'
523 def get_cpu_configuration(self):
524 phys_info = self.physinfo_dict()
526 cpu_info = {
527 "nr_nodes": phys_info["nr_nodes"],
528 "nr_cpus": phys_info["nr_cpus"],
529 "cores_per_socket": phys_info["cores_per_socket"],
530 "threads_per_core": phys_info["threads_per_core"]
531 }
533 return cpu_info
535 #
536 # Network Functions
537 #
539 def bridge_to_network(self, bridge):
540 """
541 Determine which network a particular bridge is attached to.
543 @param bridge The name of the bridge. If empty, the default bridge
544 will be used instead (the first one in the list returned by brctl
545 show); this is the behaviour of the vif-bridge script.
546 @return The XendNetwork instance to which this bridge is attached.
547 @raise Exception if the interface is not connected to a network.
548 """
549 if not bridge:
550 rc, bridge = commands.getstatusoutput(
551 'brctl show | cut -d "\n" -f 2 | cut -f 1')
552 if rc != 0 or not bridge:
553 raise Exception(
554 'Could not find default bridge, and none was specified')
556 for network_uuid in XendNetwork.get_all():
557 network = XendAPIStore.get(network_uuid, "network")
558 if network.get_name_label() == bridge:
559 return network
560 else:
561 raise Exception('Cannot find network for bridge %s' % bridge)
563 #
564 # Debug keys.
565 #
567 def send_debug_keys(self, keys):
568 return self.xc.send_debug_keys(keys)
570 #
571 # Getting host information.
572 #
574 def info(self):
575 return (self.nodeinfo() + self.physinfo() + self.xeninfo() +
576 self.xendinfo())
578 def nodeinfo(self):
579 (sys, host, rel, ver, mch) = os.uname()
580 return [['system', sys],
581 ['host', host],
582 ['release', rel],
583 ['version', ver],
584 ['machine', mch]]
586 def list_to_rangepairs(self,cmap):
587 cmap.sort()
588 pairs = []
589 x = y = 0
590 for i in range(0,len(cmap)):
591 try:
592 if ((cmap[y+1] - cmap[i]) > 1):
593 pairs.append((cmap[x],cmap[y]))
594 x = y = i+1
595 else:
596 y = y + 1
597 # if we go off the end, then just add x to y
598 except IndexError:
599 pairs.append((cmap[x],cmap[y]))
601 return pairs
603 def format_pairs(self,pairs):
604 if not pairs:
605 return "no cpus"
606 out = ""
607 for f,s in pairs:
608 if (f==s):
609 out += '%d'%f
610 else:
611 out += '%d-%d'%(f,s)
612 out += ','
613 # trim trailing ','
614 return out[:-1]
616 def list_to_strrange(self,list):
617 return self.format_pairs(self.list_to_rangepairs(list))
619 def format_node_to_cpu(self, pinfo):
620 str=''
621 whitespace=''
622 try:
623 node_to_cpu=pinfo['node_to_cpu']
624 for i in range(0, pinfo['nr_nodes']):
625 str+='%snode%d:%s\n' % (whitespace,
626 i,
627 self.list_to_strrange(node_to_cpu[i]))
628 whitespace='%25s' % ''
629 except:
630 str='none\n'
631 return str[:-1];
632 def format_node_to_memory(self, pinfo):
633 str=''
634 whitespace=''
635 try:
636 node_to_memory=pinfo['node_to_memory']
637 for i in range(0, pinfo['nr_nodes']):
638 str+='%snode%d:%d\n' % (whitespace,
639 i,
640 node_to_memory[i] / 1024)
641 whitespace='%25s' % ''
642 except:
643 str='none\n'
644 return str[:-1];
647 def physinfo(self):
648 info = self.xc.physinfo()
650 info['cpu_mhz'] = info['cpu_khz'] / 1000
652 # physinfo is in KiB, need it in MiB
653 info['total_memory'] = info['total_memory'] / 1024
654 info['free_memory'] = info['free_memory'] / 1024
655 info['node_to_cpu'] = self.format_node_to_cpu(info)
656 info['node_to_memory'] = self.format_node_to_memory(info)
658 ITEM_ORDER = ['nr_cpus',
659 'nr_nodes',
660 'cores_per_socket',
661 'threads_per_core',
662 'cpu_mhz',
663 'hw_caps',
664 'virt_caps',
665 'total_memory',
666 'free_memory',
667 'node_to_cpu',
668 'node_to_memory'
669 ]
671 return [[k, info[k]] for k in ITEM_ORDER]
673 def xenschedinfo(self):
674 sched_id = self.xc.sched_id_get()
675 if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
676 return 'sedf'
677 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
678 return 'credit'
679 else:
680 return 'unknown'
682 def xeninfo(self):
683 info = self.xc.xeninfo()
684 info['xen_scheduler'] = self.xenschedinfo()
686 ITEM_ORDER = ['xen_major',
687 'xen_minor',
688 'xen_extra',
689 'xen_caps',
690 'xen_scheduler',
691 'xen_pagesize',
692 'platform_params',
693 'xen_changeset',
694 'cc_compiler',
695 'cc_compile_by',
696 'cc_compile_domain',
697 'cc_compile_date',
698 ]
700 return [[k, info[k]] for k in ITEM_ORDER]
702 def xendinfo(self):
703 return [['xend_config_format', 4]]
705 #
706 # utilisation tracking
707 #
709 def get_vcpu_util(self, domid, vcpuid):
710 cpu_loads = self.monitor.get_domain_vcpus_util()
711 if domid in cpu_loads:
712 return cpu_loads[domid].get(vcpuid, 0.0)
713 return 0.0
715 def get_vif_util(self, domid, vifid):
716 vif_loads = self.monitor.get_domain_vifs_util()
717 if domid in vif_loads:
718 return vif_loads[domid].get(vifid, (0.0, 0.0))
719 return (0.0, 0.0)
721 def get_vif_stat(self, domid, vifid):
722 vif_loads = self.monitor.get_domain_vifs_stat()
723 if domid in vif_loads:
724 return vif_loads[domid].get(vifid, (0.0, 0.0))
725 return (0.0, 0.0)
727 def get_vbd_util(self, domid, vbdid):
728 vbd_loads = self.monitor.get_domain_vbds_util()
729 if domid in vbd_loads:
730 return vbd_loads[domid].get(vbdid, (0.0, 0.0))
731 return (0.0, 0.0)
733 # dictionary version of *info() functions to get rid of
734 # SXPisms.
735 def nodeinfo_dict(self):
736 return dict(self.nodeinfo())
737 def xendinfo_dict(self):
738 return dict(self.xendinfo())
739 def xeninfo_dict(self):
740 return dict(self.xeninfo())
741 def physinfo_dict(self):
742 return dict(self.physinfo())
743 def info_dict(self):
744 return dict(self.info())
746 def parse_proc_cpuinfo():
747 cpuinfo = {}
748 f = file('/proc/cpuinfo', 'r')
749 try:
750 p = -1
751 d = {}
752 for line in f:
753 keyvalue = line.split(':')
754 if len(keyvalue) != 2:
755 continue
756 key = keyvalue[0].strip()
757 val = keyvalue[1].strip()
758 if key == 'processor':
759 if p != -1:
760 cpuinfo[p] = d
761 p = int(val)
762 d = {}
763 else:
764 d[key] = val
765 cpuinfo[p] = d
766 return cpuinfo
767 finally:
768 f.close()
771 def instance():
772 global inst
773 try:
774 inst
775 except:
776 inst = XendNode()
777 inst.save()
778 return inst