ia64/xen-unstable

view tools/python/xen/xend/XendNode.py @ 19792:407e2e7dca5b

Allow tools to see the hypervisor command line.

This is useful from tools in the same way /proc/cmdline is useful for
the domain 0 kernel.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:20:45 2009 +0100 (2009-06-18)
parents 9e36ef77f658
children
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 time
22 import xen.lowlevel.xc
24 from xen.util import Brctl
25 from xen.util import pci as PciUtil
26 from xen.util import vscsi_util
27 from xen.xend import XendAPIStore
28 from xen.xend import osdep
29 from xen.xend.XendConstants import *
31 import uuid, arch
32 from XendPBD import XendPBD
33 from XendError import *
34 from XendOptions import instance as xendoptions
35 from XendQCoWStorageRepo import XendQCoWStorageRepo
36 from XendLocalStorageRepo import XendLocalStorageRepo
37 from XendLogging import log
38 from XendPIF import *
39 from XendPIFMetrics import XendPIFMetrics
40 from XendNetwork import *
41 from XendStateStore import XendStateStore
42 from XendMonitor import XendMonitor
43 from XendPPCI import XendPPCI
44 from XendPSCSI import XendPSCSI
46 class XendNode:
47 """XendNode - Represents a Domain 0 Host."""
49 def __init__(self):
50 """Initalises the state of all host specific objects such as
52 * host
53 * host_CPU
54 * host_metrics
55 * PIF
56 * PIF_metrics
57 * network
58 * Storage Repository
59 * PPCI
60 * PSCSI
61 """
63 self.xc = xen.lowlevel.xc.xc()
64 self.state_store = XendStateStore(xendoptions().get_xend_state_path())
65 self.monitor = XendMonitor()
66 self.monitor.start()
68 # load host state from XML file
69 saved_host = self.state_store.load_state('host')
70 if saved_host and len(saved_host.keys()) == 1:
71 self.uuid = saved_host.keys()[0]
72 host = saved_host[self.uuid]
73 self.name = host.get('name_label', socket.gethostname())
74 self.desc = host.get('name_description', '')
75 self.host_metrics_uuid = host.get('metrics_uuid',
76 uuid.createString())
77 try:
78 self.other_config = eval(host['other_config'])
79 except:
80 self.other_config = {}
81 self.cpus = {}
82 else:
83 self.uuid = uuid.createString()
84 self.name = socket.gethostname()
85 self.desc = ''
86 self.other_config = {}
87 self.cpus = {}
88 self.host_metrics_uuid = uuid.createString()
90 # put some arbitrary params in other_config as this
91 # is directly exposed via XenAPI
92 self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"]
93 self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"]
94 self.other_config["xen_commandline"] = self.xeninfo_dict()["xen_commandline"]
96 # load CPU UUIDs
97 saved_cpus = self.state_store.load_state('cpu')
98 for cpu_uuid, cpu in saved_cpus.items():
99 self.cpus[cpu_uuid] = cpu
101 cpuinfo = osdep.get_cpuinfo()
102 physinfo = self.physinfo_dict()
103 cpu_count = physinfo['nr_cpus']
104 cpu_features = physinfo['hw_caps']
105 virt_caps = physinfo['virt_caps']
107 # If the number of CPUs don't match, we should just reinitialise
108 # the CPU UUIDs.
109 if cpu_count != len(self.cpus):
110 self.cpus = {}
111 for i in range(cpu_count):
112 u = uuid.createString()
113 self.cpus[u] = {'uuid': u, 'number': i }
115 for u in self.cpus.keys():
116 number = self.cpus[u]['number']
117 # We can run off the end of the cpuinfo list if domain0 does not
118 # have #vcpus == #pcpus. In that case we just replicate one that's
119 # in the hash table.
120 if not cpuinfo.has_key(number):
121 number = cpuinfo.keys()[0]
122 if arch.type == "x86":
123 self.cpus[u].update(
124 { 'host' : self.uuid,
125 'features' : cpu_features,
126 'virt_caps': virt_caps,
127 'speed' : int(float(cpuinfo[number]['cpu MHz'])),
128 'vendor' : cpuinfo[number]['vendor_id'],
129 'modelname': cpuinfo[number]['model name'],
130 'stepping' : cpuinfo[number]['stepping'],
131 'flags' : cpuinfo[number]['flags'],
132 })
133 elif arch.type == "ia64":
134 self.cpus[u].update(
135 { 'host' : self.uuid,
136 'features' : cpu_features,
137 'speed' : int(float(cpuinfo[number]['cpu MHz'])),
138 'vendor' : cpuinfo[number]['vendor'],
139 'modelname': cpuinfo[number]['family'],
140 'stepping' : cpuinfo[number]['model'],
141 'flags' : cpuinfo[number]['features'],
142 })
143 else:
144 self.cpus[u].update(
145 { 'host' : self.uuid,
146 'features' : cpu_features,
147 })
149 self.srs = {}
151 self._init_networks()
152 self._init_PIFs()
154 self._init_SRs()
155 self._init_PBDs()
157 self._init_PPCIs()
159 self._init_PSCSIs()
162 def _init_networks(self):
163 # Initialise networks
164 # First configure ones off disk
165 saved_networks = self.state_store.load_state('network')
166 if saved_networks:
167 for net_uuid, network in saved_networks.items():
168 try:
169 XendNetwork.recreate(network, net_uuid)
170 except CreateUnspecifiedAttributeError:
171 log.warn("Error recreating network %s", net_uuid)
173 # Next discover any existing bridges and check
174 # they are not already configured
176 # 'tmpbridge' is a temporary bridge created by network-bridge script.
177 # Wait a couple of seconds for it to be renamed.
178 for i in xrange(20):
179 bridges = Brctl.get_state().keys()
180 if 'tmpbridge' in bridges:
181 time.sleep(0.1)
182 else:
183 break
185 configured_bridges = [XendAPIStore.get(
186 network_uuid, "network")
187 .get_name_label()
188 for network_uuid in XendNetwork.get_all()]
189 unconfigured_bridges = [bridge
190 for bridge in bridges
191 if bridge not in configured_bridges]
192 for unconfigured_bridge in unconfigured_bridges:
193 if unconfigured_bridge != 'tmpbridge':
194 XendNetwork.create_phy(unconfigured_bridge)
196 def _init_PIFs(self):
197 # Initialise PIFs
198 # First configure ones off disk
199 saved_pifs = self.state_store.load_state('pif')
200 if saved_pifs:
201 for pif_uuid, pif in saved_pifs.items():
202 try:
203 XendPIF.recreate(pif, pif_uuid)
204 except CreateUnspecifiedAttributeError:
205 log.warn("Error recreating PIF %s", pif_uuid)
207 # Next discover any existing PIFs and check
208 # they are not already configured
209 configured_pifs = [XendAPIStore.get(
210 pif_uuid, "PIF")
211 .get_interface_name()
212 for pif_uuid in XendPIF.get_all()]
213 unconfigured_pifs = [(name, mtu, mac)
214 for name, mtu, mac in linux_get_phy_ifaces()
215 if name not in configured_pifs]
217 # Get a mapping from interface to bridge
218 if_to_br = dict([(i,b)
219 for (b,ifs) in Brctl.get_state().items()
220 for i in ifs])
222 for name, mtu, mac in unconfigured_pifs:
223 # Check PIF is on bridge
224 # if not, ignore
225 bridge_name = if_to_br.get(name, None)
226 if bridge_name is not None:
227 # Translate bridge name to network uuid
228 for network_uuid in XendNetwork.get_all():
229 network = XendAPIStore.get(
230 network_uuid, 'network')
231 if network.get_name_label() == bridge_name:
232 XendPIF.create_phy(network_uuid, name,
233 mac, mtu)
234 break
235 else:
236 log.debug("Cannot find network for bridge %s "
237 "when configuring PIF %s",
238 (bridge_name, name))
240 def _init_SRs(self):
241 # initialise storage
242 saved_srs = self.state_store.load_state('sr')
243 if saved_srs:
244 for sr_uuid, sr_cfg in saved_srs.items():
245 if sr_cfg['type'] == 'qcow_file':
246 self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
247 elif sr_cfg['type'] == 'local':
248 self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)
250 # Create missing SRs if they don't exist
251 if not self.get_sr_by_type('local'):
252 image_sr_uuid = uuid.createString()
253 self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
255 if not self.get_sr_by_type('qcow_file'):
256 qcow_sr_uuid = uuid.createString()
257 self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
259 def _init_PBDs(self):
260 saved_pbds = self.state_store.load_state('pbd')
261 if saved_pbds:
262 for pbd_uuid, pbd_cfg in saved_pbds.items():
263 try:
264 XendPBD.recreate(pbd_uuid, pbd_cfg)
265 except CreateUnspecifiedAttributeError:
266 log.warn("Error recreating PBD %s", pbd_uuid)
268 def _init_PPCIs(self):
269 saved_ppcis = self.state_store.load_state('ppci')
270 saved_ppci_table = {}
271 if saved_ppcis:
272 for ppci_uuid, ppci_record in saved_ppcis.items():
273 try:
274 saved_ppci_table[ppci_record['name']] = ppci_uuid
275 except KeyError:
276 pass
278 for pci_dev in PciUtil.get_all_pci_devices():
279 ppci_record = {
280 'domain': pci_dev.domain,
281 'bus': pci_dev.bus,
282 'slot': pci_dev.slot,
283 'func': pci_dev.func,
284 'vendor_id': pci_dev.vendor,
285 'vendor_name': pci_dev.vendorname,
286 'device_id': pci_dev.device,
287 'device_name': pci_dev.devicename,
288 'revision_id': pci_dev.revision,
289 'class_code': pci_dev.classcode,
290 'class_name': pci_dev.classname,
291 'subsystem_vendor_id': pci_dev.subvendor,
292 'subsystem_vendor_name': pci_dev.subvendorname,
293 'subsystem_id': pci_dev.subdevice,
294 'subsystem_name': pci_dev.subdevicename,
295 'driver': pci_dev.driver
296 }
297 # If saved uuid exists, use it. Otherwise create one.
298 ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
299 XendPPCI(ppci_uuid, ppci_record)
301 def _init_PSCSIs(self):
302 # Initialise PSCSIs
303 saved_pscsis = self.state_store.load_state('pscsi')
304 saved_pscsi_table = {}
305 if saved_pscsis:
306 for pscsi_uuid, pscsi_record in saved_pscsis.items():
307 try:
308 saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid
309 except KeyError:
310 pass
312 for pscsi_record in vscsi_util.get_all_scsi_devices():
313 if pscsi_record['scsi_id']:
314 # If saved uuid exists, use it. Otherwise create one.
315 pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'],
316 uuid.createString())
317 XendPSCSI(pscsi_uuid, pscsi_record)
320 def add_network(self, interface):
321 # TODO
322 log.debug("add_network(): Not implemented.")
325 def remove_network(self, interface):
326 # TODO
327 log.debug("remove_network(): Not implemented.")
330 def add_PPCI(self, pci_name):
331 # Update lspci info
332 PciUtil.create_lspci_info()
334 # Initialise the PPCI
335 saved_ppcis = self.state_store.load_state('ppci')
336 saved_ppci_table = {}
337 if saved_ppcis:
338 for ppci_uuid, ppci_record in saved_ppcis.items():
339 try:
340 saved_ppci_table[ppci_record['name']] = ppci_uuid
341 except KeyError:
342 pass
344 pci_dev = PciUtil.PciDevice(PciUtil.parse_pci_name(pci_name))
345 ppci_record = {
346 'domain': pci_dev.domain,
347 'bus': pci_dev.bus,
348 'slot': pci_dev.slot,
349 'func': pci_dev.func,
350 'vendor_id': pci_dev.vendor,
351 'vendor_name': pci_dev.vendorname,
352 'device_id': pci_dev.device,
353 'device_name': pci_dev.devicename,
354 'revision_id': pci_dev.revision,
355 'class_code': pci_dev.classcode,
356 'class_name': pci_dev.classname,
357 'subsystem_vendor_id': pci_dev.subvendor,
358 'subsystem_vendor_name': pci_dev.subvendorname,
359 'subsystem_id': pci_dev.subdevice,
360 'subsystem_name': pci_dev.subdevicename,
361 'driver': pci_dev.driver
362 }
363 # If saved uuid exists, use it. Otherwise create one.
364 ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
365 XendPPCI(ppci_uuid, ppci_record)
367 self.save_PPCIs()
370 def remove_PPCI(self, pci_name):
371 # Update lspci info
372 PciUtil.create_lspci_info()
374 # Remove the PPCI
375 (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
376 ppci_ref = XendPPCI.get_by_sbdf(domain, bus, slot, func)
377 XendAPIStore.get(ppci_ref, "PPCI").destroy()
379 self.save_PPCIs()
382 def add_PSCSI(self, add_HCTL):
383 saved_pscsis = self.state_store.load_state('pscsi')
384 saved_pscsi_table = {}
385 if saved_pscsis:
386 for saved_uuid, saved_record in saved_pscsis.items():
387 try:
388 saved_pscsi_table[saved_record['scsi_id']] = saved_uuid
389 except KeyError:
390 pass
392 # Initialise the PSCSI
393 pscsi_record = vscsi_util.get_scsi_device(add_HCTL)
394 if pscsi_record and pscsi_record['scsi_id']:
395 pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'], None)
396 if pscsi_uuid is None:
397 pscsi_uuid = uuid.createString()
398 XendPSCSI(pscsi_uuid, pscsi_record)
399 self.save_PSCSIs()
402 def remove_PSCSI(self, rem_HCTL):
403 saved_pscsis = self.state_store.load_state('pscsi')
404 if not saved_pscsis:
405 return
407 # Remove the PSCSI
408 for pscsi_record in saved_pscsis.values():
409 if rem_HCTL == pscsi_record['physical_HCTL']:
410 pscsi_ref = XendPSCSI.get_by_HCTL(rem_HCTL)
411 XendAPIStore.get(pscsi_ref, "PSCSI").destroy()
412 self.save_PSCSIs()
413 return
416 ## def network_destroy(self, net_uuid):
417 ## del self.networks[net_uuid]
418 ## self.save_networks()
421 def get_PIF_refs(self):
422 log.debug(XendPIF.get_all())
423 return XendPIF.get_all()
425 ## def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
426 ## pif_uuid = None, metrics_uuid = None):
427 ## for pif in self.pifs.values():
428 ## if pif.network == network:
429 ## raise NetworkAlreadyConnected(pif.uuid)
431 ## if pif_uuid is None:
432 ## pif_uuid = uuid.createString()
433 ## if metrics_uuid is None:
434 ## metrics_uuid = uuid.createString()
436 ## metrics = XendPIFMetrics(metrics_uuid)
437 ## pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self)
438 ## metrics.set_PIF(pif)
440 ## self.pif_metrics[metrics_uuid] = metrics
441 ## self.pifs[pif_uuid] = pif
443 ## if persist:
444 ## self.save_PIFs()
445 ## self.refreshBridges()
446 ## return pif_uuid
448 ## def PIF_destroy(self, pif_uuid):
449 ## pif = self.pifs[pif_uuid]
451 ## if pif.vlan == -1:
452 ## raise PIFIsPhysical()
454 ## del self.pifs[pif_uuid]
455 ## self.save_PIFs()
458 def get_PPCI_refs(self):
459 return XendPPCI.get_all()
461 def get_ppci_by_uuid(self, ppci_uuid):
462 if ppci_uuid in self.get_PPCI_refs():
463 return ppci_uuid
464 return None
467 def get_PSCSI_refs(self):
468 return XendPSCSI.get_all()
470 def get_pscsi_by_uuid(self, pscsi_uuid):
471 if pscsi_uuid in self.get_PSCSI_refs():
472 return pscsi_uuid
473 return None
476 def save(self):
477 # save state
478 host_record = {self.uuid: {'name_label':self.name,
479 'name_description':self.desc,
480 'metrics_uuid': self.host_metrics_uuid,
481 'other_config': self.other_config}}
482 self.state_store.save_state('host',host_record)
483 self.state_store.save_state('cpu', self.cpus)
484 self.save_PIFs()
485 self.save_networks()
486 self.save_PBDs()
487 self.save_SRs()
488 self.save_PPCIs()
489 self.save_PSCSIs()
491 def save_PIFs(self):
492 pif_records = dict([(pif_uuid, XendAPIStore.get(
493 pif_uuid, "PIF").get_record())
494 for pif_uuid in XendPIF.get_all()])
495 self.state_store.save_state('pif', pif_records)
497 def save_networks(self):
498 net_records = dict([(network_uuid, XendAPIStore.get(
499 network_uuid, "network").get_record())
500 for network_uuid in XendNetwork.get_all()])
501 self.state_store.save_state('network', net_records)
503 def save_PBDs(self):
504 pbd_records = dict([(pbd_uuid, XendAPIStore.get(
505 pbd_uuid, "PBD").get_record())
506 for pbd_uuid in XendPBD.get_all()])
507 self.state_store.save_state('pbd', pbd_records)
509 def save_SRs(self):
510 sr_records = dict([(k, v.get_record(transient = False))
511 for k, v in self.srs.items()])
512 self.state_store.save_state('sr', sr_records)
514 def save_PPCIs(self):
515 ppci_records = dict([(ppci_uuid, XendAPIStore.get(
516 ppci_uuid, "PPCI").get_record())
517 for ppci_uuid in XendPPCI.get_all()])
518 self.state_store.save_state('ppci', ppci_records)
520 def save_PSCSIs(self):
521 pscsi_records = dict([(pscsi_uuid, XendAPIStore.get(
522 pscsi_uuid, "PSCSI").get_record())
523 for pscsi_uuid in XendPSCSI.get_all()])
524 self.state_store.save_state('pscsi', pscsi_records)
526 def shutdown(self):
527 return 0
529 def reboot(self):
530 return 0
532 def notify(self, _):
533 return 0
535 #
536 # Ref validation
537 #
539 def is_valid_host(self, host_ref):
540 return (host_ref == self.uuid)
542 def is_valid_cpu(self, cpu_ref):
543 return (cpu_ref in self.cpus)
545 def is_valid_sr(self, sr_ref):
546 return (sr_ref in self.srs)
548 def is_valid_vdi(self, vdi_ref):
549 for sr in self.srs.values():
550 if sr.is_valid_vdi(vdi_ref):
551 return True
552 return False
554 #
555 # Storage Repositories
556 #
558 def get_sr(self, sr_uuid):
559 return self.srs.get(sr_uuid)
561 def get_sr_by_type(self, sr_type):
562 return [sr.uuid for sr in self.srs.values() if sr.type == sr_type]
564 def get_sr_by_name(self, name):
565 return [sr.uuid for sr in self.srs.values() if sr.name_label == name]
567 def get_all_sr_uuid(self):
568 return self.srs.keys()
570 def get_vdi_by_uuid(self, vdi_uuid):
571 for sr in self.srs.values():
572 if sr.is_valid_vdi(vdi_uuid):
573 return sr.get_vdi_by_uuid(vdi_uuid)
574 return None
576 def get_vdi_by_name_label(self, name):
577 for sr in self.srs.values():
578 vdi = sr.get_vdi_by_name_label(name)
579 if vdi:
580 return vdi
581 return None
583 def get_sr_containing_vdi(self, vdi_uuid):
584 for sr in self.srs.values():
585 if sr.is_valid_vdi(vdi_uuid):
586 return sr
587 return None
590 #
591 # Host Functions
592 #
594 def xen_version(self):
595 info = self.xc.xeninfo()
597 info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info}
599 # Add xend_config_format
600 info.update(self.xendinfo_dict())
602 # Add version info about machine
603 info.update(self.nodeinfo_dict())
605 # Add specific xen version info
606 xeninfo_dict = self.xeninfo_dict()
608 info.update({
609 "xen_major": xeninfo_dict["xen_major"],
610 "xen_minor": xeninfo_dict["xen_minor"],
611 "xen_extra": xeninfo_dict["xen_extra"],
612 "cc_compiler": xeninfo_dict["cc_compiler"],
613 "cc_compile_by": xeninfo_dict["cc_compile_by"],
614 "cc_compile_domain": xeninfo_dict["cc_compile_domain"],
615 "cc_compile_date": xeninfo_dict["cc_compile_date"],
616 "xen_changeset": xeninfo_dict["xen_changeset"],
617 "xen_commandline": xeninfo_dict["xen_commandline"]
618 })
620 return info
622 def get_name(self):
623 return self.name
625 def set_name(self, new_name):
626 self.name = new_name
628 def get_description(self):
629 return self.desc
631 def set_description(self, new_desc):
632 self.desc = new_desc
634 def get_uuid(self):
635 return self.uuid
637 def get_capabilities(self):
638 return self.xc.xeninfo()['xen_caps'].split(" ")
640 #
641 # Host CPU Functions
642 #
644 def get_host_cpu_by_uuid(self, host_cpu_uuid):
645 if host_cpu_uuid in self.cpus:
646 return host_cpu_uuid
647 raise XendError('Invalid CPU UUID')
649 def get_host_cpu_refs(self):
650 return self.cpus.keys()
652 def get_host_cpu_uuid(self, host_cpu_ref):
653 if host_cpu_ref in self.cpus:
654 return host_cpu_ref
655 else:
656 raise XendError('Invalid CPU Reference')
658 def get_host_cpu_field(self, ref, field):
659 try:
660 return self.cpus[ref][field]
661 except KeyError:
662 raise XendError('Invalid CPU Reference')
664 def get_host_cpu_load(self, host_cpu_ref):
665 host_cpu = self.cpus.get(host_cpu_ref)
666 if not host_cpu:
667 return 0.0
669 vcpu = int(host_cpu['number'])
670 cpu_loads = self.monitor.get_domain_vcpus_util()
671 if 0 in cpu_loads and vcpu in cpu_loads[0]:
672 return cpu_loads[0][vcpu]
674 return 0.0
676 def get_vcpus_policy(self):
677 sched_id = self.xc.sched_id_get()
678 if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
679 return 'sedf'
680 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
681 return 'credit'
682 else:
683 return 'unknown'
685 def get_cpu_configuration(self):
686 phys_info = self.physinfo_dict()
688 cpu_info = {
689 "nr_nodes": phys_info["nr_nodes"],
690 "nr_cpus": phys_info["nr_cpus"],
691 "cores_per_socket": phys_info["cores_per_socket"],
692 "threads_per_core": phys_info["threads_per_core"]
693 }
695 return cpu_info
697 #
698 # Network Functions
699 #
701 def bridge_to_network(self, bridge):
702 """
703 Determine which network a particular bridge is attached to.
705 @param bridge The name of the bridge. If empty, the default bridge
706 will be used instead (the first one in the list returned by brctl
707 show); this is the behaviour of the vif-bridge script.
708 @return The XendNetwork instance to which this bridge is attached.
709 @raise Exception if the interface is not connected to a network.
710 """
711 if not bridge:
712 rc, bridge = commands.getstatusoutput(
713 'brctl show | cut -d "\n" -f 2 | cut -f 1')
714 if rc != 0 or not bridge:
715 raise Exception(
716 'Could not find default bridge, and none was specified')
718 for network_uuid in XendNetwork.get_all():
719 network = XendAPIStore.get(network_uuid, "network")
720 if network.get_name_label() == bridge:
721 return network
722 else:
723 raise Exception('Cannot find network for bridge %s' % bridge)
725 #
726 # Debug keys.
727 #
729 def send_debug_keys(self, keys):
730 return self.xc.send_debug_keys(keys)
732 #
733 # Getting host information.
734 #
736 def info(self):
737 return (self.nodeinfo() + self.physinfo() + self.xeninfo() +
738 self.xendinfo())
740 def nodeinfo(self):
741 (sys, host, rel, ver, mch) = os.uname()
742 return [['system', sys],
743 ['host', host],
744 ['release', rel],
745 ['version', ver],
746 ['machine', mch]]
748 def list_to_rangepairs(self,cmap):
749 cmap.sort()
750 pairs = []
751 x = y = 0
752 for i in range(0,len(cmap)):
753 try:
754 if ((cmap[y+1] - cmap[i]) > 1):
755 pairs.append((cmap[x],cmap[y]))
756 x = y = i+1
757 else:
758 y = y + 1
759 # if we go off the end, then just add x to y
760 except IndexError:
761 pairs.append((cmap[x],cmap[y]))
763 return pairs
765 def format_pairs(self,pairs):
766 if not pairs:
767 return "no cpus"
768 out = ""
769 for f,s in pairs:
770 if (f==s):
771 out += '%d'%f
772 else:
773 out += '%d-%d'%(f,s)
774 out += ','
775 # trim trailing ','
776 return out[:-1]
778 def list_to_strrange(self,list):
779 return self.format_pairs(self.list_to_rangepairs(list))
781 def format_node_to_cpu(self, pinfo):
782 str=''
783 whitespace=''
784 try:
785 node_to_cpu=pinfo['node_to_cpu']
786 for i in range(0, pinfo['nr_nodes']):
787 str+='%snode%d:%s\n' % (whitespace,
788 i,
789 self.list_to_strrange(node_to_cpu[i]))
790 whitespace='%25s' % ''
791 except:
792 str='none\n'
793 return str[:-1];
794 def format_node_to_memory(self, pinfo):
795 str=''
796 whitespace=''
797 try:
798 node_to_memory=pinfo['node_to_memory']
799 for i in range(0, pinfo['nr_nodes']):
800 str+='%snode%d:%d\n' % (whitespace,
801 i,
802 node_to_memory[i] / 1024)
803 whitespace='%25s' % ''
804 except:
805 str='none\n'
806 return str[:-1];
809 def physinfo(self):
810 info = self.xc.physinfo()
812 info['cpu_mhz'] = info['cpu_khz'] / 1000
814 # physinfo is in KiB, need it in MiB
815 info['total_memory'] = info['total_memory'] / 1024
816 info['free_memory'] = info['free_memory'] / 1024
817 info['node_to_cpu'] = self.format_node_to_cpu(info)
818 info['node_to_memory'] = self.format_node_to_memory(info)
820 ITEM_ORDER = ['nr_cpus',
821 'nr_nodes',
822 'cores_per_socket',
823 'threads_per_core',
824 'cpu_mhz',
825 'hw_caps',
826 'virt_caps',
827 'total_memory',
828 'free_memory',
829 'node_to_cpu',
830 'node_to_memory'
831 ]
833 return [[k, info[k]] for k in ITEM_ORDER]
836 def pciinfo(self):
837 # Each element of dev_list is a PciDevice
838 dev_list = PciUtil.find_all_devices_owned_by_pciback()
840 # Each element of devs_list is a list of PciDevice
841 devs_list = PciUtil.check_FLR_capability(dev_list)
843 devs_list = PciUtil.check_mmio_bar(devs_list)
845 # Check if the devices have been assigned to guests.
846 final_devs_list = []
847 for dev_list in devs_list:
848 available = True
849 for d in dev_list:
850 pci_str = '0x%x,0x%x,0x%x,0x%x' %(d.domain, d.bus, d.slot, d.func)
851 # Xen doesn't care what the domid is, so we pass 0 here...
852 domid = 0
853 bdf = self.xc.test_assign_device(domid, pci_str)
854 if bdf != 0:
855 available = False
856 break
857 if available:
858 final_devs_list = final_devs_list + [dev_list]
860 pci_sxp_list = []
861 for dev_list in final_devs_list:
862 for d in dev_list:
863 pci_sxp = ['dev', ['domain', '0x%04x' % d.domain],
864 ['bus', '0x%02x' % d.bus],
865 ['slot', '0x%02x' % d.slot],
866 ['func', '0x%x' % d.func]]
867 pci_sxp_list.append(pci_sxp)
869 return pci_sxp_list
872 def xenschedinfo(self):
873 sched_id = self.xc.sched_id_get()
874 if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
875 return 'sedf'
876 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
877 return 'credit'
878 else:
879 return 'unknown'
881 def xeninfo(self):
882 info = self.xc.xeninfo()
883 info['xen_scheduler'] = self.xenschedinfo()
885 ITEM_ORDER = ['xen_major',
886 'xen_minor',
887 'xen_extra',
888 'xen_caps',
889 'xen_scheduler',
890 'xen_pagesize',
891 'platform_params',
892 'xen_changeset',
893 'xen_commandline',
894 'cc_compiler',
895 'cc_compile_by',
896 'cc_compile_domain',
897 'cc_compile_date',
898 ]
900 return [[k, info[k]] for k in ITEM_ORDER]
902 def xendinfo(self):
903 return [['xend_config_format', 4]]
905 #
906 # utilisation tracking
907 #
909 def get_vcpu_util(self, domid, vcpuid):
910 cpu_loads = self.monitor.get_domain_vcpus_util()
911 if domid in cpu_loads:
912 return cpu_loads[domid].get(vcpuid, 0.0)
913 return 0.0
915 def get_vif_util(self, domid, vifid):
916 vif_loads = self.monitor.get_domain_vifs_util()
917 if domid in vif_loads:
918 return vif_loads[domid].get(vifid, (0.0, 0.0))
919 return (0.0, 0.0)
921 def get_vif_stat(self, domid, vifid):
922 vif_loads = self.monitor.get_domain_vifs_stat()
923 if domid in vif_loads:
924 return vif_loads[domid].get(vifid, (0.0, 0.0))
925 return (0.0, 0.0)
927 def get_vbd_util(self, domid, vbdid):
928 vbd_loads = self.monitor.get_domain_vbds_util()
929 if domid in vbd_loads:
930 return vbd_loads[domid].get(vbdid, (0.0, 0.0))
931 return (0.0, 0.0)
933 # dictionary version of *info() functions to get rid of
934 # SXPisms.
935 def nodeinfo_dict(self):
936 return dict(self.nodeinfo())
937 def xendinfo_dict(self):
938 return dict(self.xendinfo())
939 def xeninfo_dict(self):
940 return dict(self.xeninfo())
941 def physinfo_dict(self):
942 return dict(self.physinfo())
943 def info_dict(self):
944 return dict(self.info())
946 # tmem
947 def tmem_list(self, cli_id, use_long):
948 pool_id = -1
949 subop = TMEMC_LIST
950 arg1 = 32768
951 arg2 = use_long
952 buf = ''
953 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
955 def tmem_thaw(self, cli_id):
956 pool_id = -1
957 subop = TMEMC_THAW
958 arg1 = 0
959 arg2 = 0
960 buf = ''
961 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
963 def tmem_freeze(self, cli_id):
964 pool_id = -1
965 subop = TMEMC_FREEZE
966 arg1 = 0
967 arg2 = 0
968 buf = ''
969 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
971 def tmem_flush(self, cli_id, pages):
972 pool_id = -1
973 subop = TMEMC_FLUSH
974 arg1 = pages
975 arg2 = 0
976 buf = ''
977 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
979 def tmem_destroy(self, cli_id):
980 pool_id = -1
981 subop = TMEMC_DESTROY
982 arg1 = 0
983 arg2 = 0
984 buf = ''
985 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
987 def tmem_set_weight(self, cli_id, arg1):
988 pool_id = -1
989 subop = TMEMC_SET_WEIGHT
990 arg2 = 0
991 buf = ''
992 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
994 def tmem_set_cap(self, cli_id, arg1):
995 pool_id = -1
996 subop = TMEMC_SET_CAP
997 arg2 = 0
998 buf = ''
999 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
1001 def tmem_set_compress(self, cli_id, arg1):
1002 pool_id = -1
1003 subop = TMEMC_SET_COMPRESS
1004 arg2 = 0
1005 buf = ''
1006 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
1009 def instance():
1010 global inst
1011 try:
1012 inst
1013 except:
1014 inst = XendNode()
1015 inst.save()
1016 return inst