ia64/xen-unstable

view tools/python/xen/xend/XendNode.py @ 19776:9e36ef77f658

xend: pass-through: Common parse_pci_name()

Share some parsing code between different parts of xm.

This has the side-effect that the device specification for
hot-plug may now include the VSLOT and OPTS as per device
specifictions in the domain configuration file.

SEQ:BUS:DEV.FUNC[,OPT...]

e.g. 0000:00:01.00@6

Signed-off-by: Simon Horman <horms@verge.net.au>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 17 07:34:59 2009 +0100 (2009-06-17)
parents f210a633571c
children 407e2e7dca5b
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"]
95 # load CPU UUIDs
96 saved_cpus = self.state_store.load_state('cpu')
97 for cpu_uuid, cpu in saved_cpus.items():
98 self.cpus[cpu_uuid] = cpu
100 cpuinfo = osdep.get_cpuinfo()
101 physinfo = self.physinfo_dict()
102 cpu_count = physinfo['nr_cpus']
103 cpu_features = physinfo['hw_caps']
104 virt_caps = physinfo['virt_caps']
106 # If the number of CPUs don't match, we should just reinitialise
107 # the CPU UUIDs.
108 if cpu_count != len(self.cpus):
109 self.cpus = {}
110 for i in range(cpu_count):
111 u = uuid.createString()
112 self.cpus[u] = {'uuid': u, 'number': i }
114 for u in self.cpus.keys():
115 number = self.cpus[u]['number']
116 # We can run off the end of the cpuinfo list if domain0 does not
117 # have #vcpus == #pcpus. In that case we just replicate one that's
118 # in the hash table.
119 if not cpuinfo.has_key(number):
120 number = cpuinfo.keys()[0]
121 if arch.type == "x86":
122 self.cpus[u].update(
123 { 'host' : self.uuid,
124 'features' : cpu_features,
125 'virt_caps': virt_caps,
126 'speed' : int(float(cpuinfo[number]['cpu MHz'])),
127 'vendor' : cpuinfo[number]['vendor_id'],
128 'modelname': cpuinfo[number]['model name'],
129 'stepping' : cpuinfo[number]['stepping'],
130 'flags' : cpuinfo[number]['flags'],
131 })
132 elif arch.type == "ia64":
133 self.cpus[u].update(
134 { 'host' : self.uuid,
135 'features' : cpu_features,
136 'speed' : int(float(cpuinfo[number]['cpu MHz'])),
137 'vendor' : cpuinfo[number]['vendor'],
138 'modelname': cpuinfo[number]['family'],
139 'stepping' : cpuinfo[number]['model'],
140 'flags' : cpuinfo[number]['features'],
141 })
142 else:
143 self.cpus[u].update(
144 { 'host' : self.uuid,
145 'features' : cpu_features,
146 })
148 self.srs = {}
150 self._init_networks()
151 self._init_PIFs()
153 self._init_SRs()
154 self._init_PBDs()
156 self._init_PPCIs()
158 self._init_PSCSIs()
161 def _init_networks(self):
162 # Initialise networks
163 # First configure ones off disk
164 saved_networks = self.state_store.load_state('network')
165 if saved_networks:
166 for net_uuid, network in saved_networks.items():
167 try:
168 XendNetwork.recreate(network, net_uuid)
169 except CreateUnspecifiedAttributeError:
170 log.warn("Error recreating network %s", net_uuid)
172 # Next discover any existing bridges and check
173 # they are not already configured
175 # 'tmpbridge' is a temporary bridge created by network-bridge script.
176 # Wait a couple of seconds for it to be renamed.
177 for i in xrange(20):
178 bridges = Brctl.get_state().keys()
179 if 'tmpbridge' in bridges:
180 time.sleep(0.1)
181 else:
182 break
184 configured_bridges = [XendAPIStore.get(
185 network_uuid, "network")
186 .get_name_label()
187 for network_uuid in XendNetwork.get_all()]
188 unconfigured_bridges = [bridge
189 for bridge in bridges
190 if bridge not in configured_bridges]
191 for unconfigured_bridge in unconfigured_bridges:
192 if unconfigured_bridge != 'tmpbridge':
193 XendNetwork.create_phy(unconfigured_bridge)
195 def _init_PIFs(self):
196 # Initialise PIFs
197 # First configure ones off disk
198 saved_pifs = self.state_store.load_state('pif')
199 if saved_pifs:
200 for pif_uuid, pif in saved_pifs.items():
201 try:
202 XendPIF.recreate(pif, pif_uuid)
203 except CreateUnspecifiedAttributeError:
204 log.warn("Error recreating PIF %s", pif_uuid)
206 # Next discover any existing PIFs and check
207 # they are not already configured
208 configured_pifs = [XendAPIStore.get(
209 pif_uuid, "PIF")
210 .get_interface_name()
211 for pif_uuid in XendPIF.get_all()]
212 unconfigured_pifs = [(name, mtu, mac)
213 for name, mtu, mac in linux_get_phy_ifaces()
214 if name not in configured_pifs]
216 # Get a mapping from interface to bridge
217 if_to_br = dict([(i,b)
218 for (b,ifs) in Brctl.get_state().items()
219 for i in ifs])
221 for name, mtu, mac in unconfigured_pifs:
222 # Check PIF is on bridge
223 # if not, ignore
224 bridge_name = if_to_br.get(name, None)
225 if bridge_name is not None:
226 # Translate bridge name to network uuid
227 for network_uuid in XendNetwork.get_all():
228 network = XendAPIStore.get(
229 network_uuid, 'network')
230 if network.get_name_label() == bridge_name:
231 XendPIF.create_phy(network_uuid, name,
232 mac, mtu)
233 break
234 else:
235 log.debug("Cannot find network for bridge %s "
236 "when configuring PIF %s",
237 (bridge_name, name))
239 def _init_SRs(self):
240 # initialise storage
241 saved_srs = self.state_store.load_state('sr')
242 if saved_srs:
243 for sr_uuid, sr_cfg in saved_srs.items():
244 if sr_cfg['type'] == 'qcow_file':
245 self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
246 elif sr_cfg['type'] == 'local':
247 self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)
249 # Create missing SRs if they don't exist
250 if not self.get_sr_by_type('local'):
251 image_sr_uuid = uuid.createString()
252 self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
254 if not self.get_sr_by_type('qcow_file'):
255 qcow_sr_uuid = uuid.createString()
256 self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
258 def _init_PBDs(self):
259 saved_pbds = self.state_store.load_state('pbd')
260 if saved_pbds:
261 for pbd_uuid, pbd_cfg in saved_pbds.items():
262 try:
263 XendPBD.recreate(pbd_uuid, pbd_cfg)
264 except CreateUnspecifiedAttributeError:
265 log.warn("Error recreating PBD %s", pbd_uuid)
267 def _init_PPCIs(self):
268 saved_ppcis = self.state_store.load_state('ppci')
269 saved_ppci_table = {}
270 if saved_ppcis:
271 for ppci_uuid, ppci_record in saved_ppcis.items():
272 try:
273 saved_ppci_table[ppci_record['name']] = ppci_uuid
274 except KeyError:
275 pass
277 for pci_dev in PciUtil.get_all_pci_devices():
278 ppci_record = {
279 'domain': pci_dev.domain,
280 'bus': pci_dev.bus,
281 'slot': pci_dev.slot,
282 'func': pci_dev.func,
283 'vendor_id': pci_dev.vendor,
284 'vendor_name': pci_dev.vendorname,
285 'device_id': pci_dev.device,
286 'device_name': pci_dev.devicename,
287 'revision_id': pci_dev.revision,
288 'class_code': pci_dev.classcode,
289 'class_name': pci_dev.classname,
290 'subsystem_vendor_id': pci_dev.subvendor,
291 'subsystem_vendor_name': pci_dev.subvendorname,
292 'subsystem_id': pci_dev.subdevice,
293 'subsystem_name': pci_dev.subdevicename,
294 'driver': pci_dev.driver
295 }
296 # If saved uuid exists, use it. Otherwise create one.
297 ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
298 XendPPCI(ppci_uuid, ppci_record)
300 def _init_PSCSIs(self):
301 # Initialise PSCSIs
302 saved_pscsis = self.state_store.load_state('pscsi')
303 saved_pscsi_table = {}
304 if saved_pscsis:
305 for pscsi_uuid, pscsi_record in saved_pscsis.items():
306 try:
307 saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid
308 except KeyError:
309 pass
311 for pscsi_record in vscsi_util.get_all_scsi_devices():
312 if pscsi_record['scsi_id']:
313 # If saved uuid exists, use it. Otherwise create one.
314 pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'],
315 uuid.createString())
316 XendPSCSI(pscsi_uuid, pscsi_record)
319 def add_network(self, interface):
320 # TODO
321 log.debug("add_network(): Not implemented.")
324 def remove_network(self, interface):
325 # TODO
326 log.debug("remove_network(): Not implemented.")
329 def add_PPCI(self, pci_name):
330 # Update lspci info
331 PciUtil.create_lspci_info()
333 # Initialise the PPCI
334 saved_ppcis = self.state_store.load_state('ppci')
335 saved_ppci_table = {}
336 if saved_ppcis:
337 for ppci_uuid, ppci_record in saved_ppcis.items():
338 try:
339 saved_ppci_table[ppci_record['name']] = ppci_uuid
340 except KeyError:
341 pass
343 pci_dev = PciUtil.PciDevice(PciUtil.parse_pci_name(pci_name))
344 ppci_record = {
345 'domain': pci_dev.domain,
346 'bus': pci_dev.bus,
347 'slot': pci_dev.slot,
348 'func': pci_dev.func,
349 'vendor_id': pci_dev.vendor,
350 'vendor_name': pci_dev.vendorname,
351 'device_id': pci_dev.device,
352 'device_name': pci_dev.devicename,
353 'revision_id': pci_dev.revision,
354 'class_code': pci_dev.classcode,
355 'class_name': pci_dev.classname,
356 'subsystem_vendor_id': pci_dev.subvendor,
357 'subsystem_vendor_name': pci_dev.subvendorname,
358 'subsystem_id': pci_dev.subdevice,
359 'subsystem_name': pci_dev.subdevicename,
360 'driver': pci_dev.driver
361 }
362 # If saved uuid exists, use it. Otherwise create one.
363 ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
364 XendPPCI(ppci_uuid, ppci_record)
366 self.save_PPCIs()
369 def remove_PPCI(self, pci_name):
370 # Update lspci info
371 PciUtil.create_lspci_info()
373 # Remove the PPCI
374 (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
375 ppci_ref = XendPPCI.get_by_sbdf(domain, bus, slot, func)
376 XendAPIStore.get(ppci_ref, "PPCI").destroy()
378 self.save_PPCIs()
381 def add_PSCSI(self, add_HCTL):
382 saved_pscsis = self.state_store.load_state('pscsi')
383 saved_pscsi_table = {}
384 if saved_pscsis:
385 for saved_uuid, saved_record in saved_pscsis.items():
386 try:
387 saved_pscsi_table[saved_record['scsi_id']] = saved_uuid
388 except KeyError:
389 pass
391 # Initialise the PSCSI
392 pscsi_record = vscsi_util.get_scsi_device(add_HCTL)
393 if pscsi_record and pscsi_record['scsi_id']:
394 pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'], None)
395 if pscsi_uuid is None:
396 pscsi_uuid = uuid.createString()
397 XendPSCSI(pscsi_uuid, pscsi_record)
398 self.save_PSCSIs()
401 def remove_PSCSI(self, rem_HCTL):
402 saved_pscsis = self.state_store.load_state('pscsi')
403 if not saved_pscsis:
404 return
406 # Remove the PSCSI
407 for pscsi_record in saved_pscsis.values():
408 if rem_HCTL == pscsi_record['physical_HCTL']:
409 pscsi_ref = XendPSCSI.get_by_HCTL(rem_HCTL)
410 XendAPIStore.get(pscsi_ref, "PSCSI").destroy()
411 self.save_PSCSIs()
412 return
415 ## def network_destroy(self, net_uuid):
416 ## del self.networks[net_uuid]
417 ## self.save_networks()
420 def get_PIF_refs(self):
421 log.debug(XendPIF.get_all())
422 return XendPIF.get_all()
424 ## def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
425 ## pif_uuid = None, metrics_uuid = None):
426 ## for pif in self.pifs.values():
427 ## if pif.network == network:
428 ## raise NetworkAlreadyConnected(pif.uuid)
430 ## if pif_uuid is None:
431 ## pif_uuid = uuid.createString()
432 ## if metrics_uuid is None:
433 ## metrics_uuid = uuid.createString()
435 ## metrics = XendPIFMetrics(metrics_uuid)
436 ## pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self)
437 ## metrics.set_PIF(pif)
439 ## self.pif_metrics[metrics_uuid] = metrics
440 ## self.pifs[pif_uuid] = pif
442 ## if persist:
443 ## self.save_PIFs()
444 ## self.refreshBridges()
445 ## return pif_uuid
447 ## def PIF_destroy(self, pif_uuid):
448 ## pif = self.pifs[pif_uuid]
450 ## if pif.vlan == -1:
451 ## raise PIFIsPhysical()
453 ## del self.pifs[pif_uuid]
454 ## self.save_PIFs()
457 def get_PPCI_refs(self):
458 return XendPPCI.get_all()
460 def get_ppci_by_uuid(self, ppci_uuid):
461 if ppci_uuid in self.get_PPCI_refs():
462 return ppci_uuid
463 return None
466 def get_PSCSI_refs(self):
467 return XendPSCSI.get_all()
469 def get_pscsi_by_uuid(self, pscsi_uuid):
470 if pscsi_uuid in self.get_PSCSI_refs():
471 return pscsi_uuid
472 return None
475 def save(self):
476 # save state
477 host_record = {self.uuid: {'name_label':self.name,
478 'name_description':self.desc,
479 'metrics_uuid': self.host_metrics_uuid,
480 'other_config': self.other_config}}
481 self.state_store.save_state('host',host_record)
482 self.state_store.save_state('cpu', self.cpus)
483 self.save_PIFs()
484 self.save_networks()
485 self.save_PBDs()
486 self.save_SRs()
487 self.save_PPCIs()
488 self.save_PSCSIs()
490 def save_PIFs(self):
491 pif_records = dict([(pif_uuid, XendAPIStore.get(
492 pif_uuid, "PIF").get_record())
493 for pif_uuid in XendPIF.get_all()])
494 self.state_store.save_state('pif', pif_records)
496 def save_networks(self):
497 net_records = dict([(network_uuid, XendAPIStore.get(
498 network_uuid, "network").get_record())
499 for network_uuid in XendNetwork.get_all()])
500 self.state_store.save_state('network', net_records)
502 def save_PBDs(self):
503 pbd_records = dict([(pbd_uuid, XendAPIStore.get(
504 pbd_uuid, "PBD").get_record())
505 for pbd_uuid in XendPBD.get_all()])
506 self.state_store.save_state('pbd', pbd_records)
508 def save_SRs(self):
509 sr_records = dict([(k, v.get_record(transient = False))
510 for k, v in self.srs.items()])
511 self.state_store.save_state('sr', sr_records)
513 def save_PPCIs(self):
514 ppci_records = dict([(ppci_uuid, XendAPIStore.get(
515 ppci_uuid, "PPCI").get_record())
516 for ppci_uuid in XendPPCI.get_all()])
517 self.state_store.save_state('ppci', ppci_records)
519 def save_PSCSIs(self):
520 pscsi_records = dict([(pscsi_uuid, XendAPIStore.get(
521 pscsi_uuid, "PSCSI").get_record())
522 for pscsi_uuid in XendPSCSI.get_all()])
523 self.state_store.save_state('pscsi', pscsi_records)
525 def shutdown(self):
526 return 0
528 def reboot(self):
529 return 0
531 def notify(self, _):
532 return 0
534 #
535 # Ref validation
536 #
538 def is_valid_host(self, host_ref):
539 return (host_ref == self.uuid)
541 def is_valid_cpu(self, cpu_ref):
542 return (cpu_ref in self.cpus)
544 def is_valid_sr(self, sr_ref):
545 return (sr_ref in self.srs)
547 def is_valid_vdi(self, vdi_ref):
548 for sr in self.srs.values():
549 if sr.is_valid_vdi(vdi_ref):
550 return True
551 return False
553 #
554 # Storage Repositories
555 #
557 def get_sr(self, sr_uuid):
558 return self.srs.get(sr_uuid)
560 def get_sr_by_type(self, sr_type):
561 return [sr.uuid for sr in self.srs.values() if sr.type == sr_type]
563 def get_sr_by_name(self, name):
564 return [sr.uuid for sr in self.srs.values() if sr.name_label == name]
566 def get_all_sr_uuid(self):
567 return self.srs.keys()
569 def get_vdi_by_uuid(self, vdi_uuid):
570 for sr in self.srs.values():
571 if sr.is_valid_vdi(vdi_uuid):
572 return sr.get_vdi_by_uuid(vdi_uuid)
573 return None
575 def get_vdi_by_name_label(self, name):
576 for sr in self.srs.values():
577 vdi = sr.get_vdi_by_name_label(name)
578 if vdi:
579 return vdi
580 return None
582 def get_sr_containing_vdi(self, vdi_uuid):
583 for sr in self.srs.values():
584 if sr.is_valid_vdi(vdi_uuid):
585 return sr
586 return None
589 #
590 # Host Functions
591 #
593 def xen_version(self):
594 info = self.xc.xeninfo()
596 info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info}
598 # Add xend_config_format
599 info.update(self.xendinfo_dict())
601 # Add version info about machine
602 info.update(self.nodeinfo_dict())
604 # Add specific xen version info
605 xeninfo_dict = self.xeninfo_dict()
607 info.update({
608 "xen_major": xeninfo_dict["xen_major"],
609 "xen_minor": xeninfo_dict["xen_minor"],
610 "xen_extra": xeninfo_dict["xen_extra"],
611 "cc_compiler": xeninfo_dict["cc_compiler"],
612 "cc_compile_by": xeninfo_dict["cc_compile_by"],
613 "cc_compile_domain": xeninfo_dict["cc_compile_domain"],
614 "cc_compile_date": xeninfo_dict["cc_compile_date"],
615 "xen_changeset": xeninfo_dict["xen_changeset"]
616 })
618 return info
620 def get_name(self):
621 return self.name
623 def set_name(self, new_name):
624 self.name = new_name
626 def get_description(self):
627 return self.desc
629 def set_description(self, new_desc):
630 self.desc = new_desc
632 def get_uuid(self):
633 return self.uuid
635 def get_capabilities(self):
636 return self.xc.xeninfo()['xen_caps'].split(" ")
638 #
639 # Host CPU Functions
640 #
642 def get_host_cpu_by_uuid(self, host_cpu_uuid):
643 if host_cpu_uuid in self.cpus:
644 return host_cpu_uuid
645 raise XendError('Invalid CPU UUID')
647 def get_host_cpu_refs(self):
648 return self.cpus.keys()
650 def get_host_cpu_uuid(self, host_cpu_ref):
651 if host_cpu_ref in self.cpus:
652 return host_cpu_ref
653 else:
654 raise XendError('Invalid CPU Reference')
656 def get_host_cpu_field(self, ref, field):
657 try:
658 return self.cpus[ref][field]
659 except KeyError:
660 raise XendError('Invalid CPU Reference')
662 def get_host_cpu_load(self, host_cpu_ref):
663 host_cpu = self.cpus.get(host_cpu_ref)
664 if not host_cpu:
665 return 0.0
667 vcpu = int(host_cpu['number'])
668 cpu_loads = self.monitor.get_domain_vcpus_util()
669 if 0 in cpu_loads and vcpu in cpu_loads[0]:
670 return cpu_loads[0][vcpu]
672 return 0.0
674 def get_vcpus_policy(self):
675 sched_id = self.xc.sched_id_get()
676 if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
677 return 'sedf'
678 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
679 return 'credit'
680 else:
681 return 'unknown'
683 def get_cpu_configuration(self):
684 phys_info = self.physinfo_dict()
686 cpu_info = {
687 "nr_nodes": phys_info["nr_nodes"],
688 "nr_cpus": phys_info["nr_cpus"],
689 "cores_per_socket": phys_info["cores_per_socket"],
690 "threads_per_core": phys_info["threads_per_core"]
691 }
693 return cpu_info
695 #
696 # Network Functions
697 #
699 def bridge_to_network(self, bridge):
700 """
701 Determine which network a particular bridge is attached to.
703 @param bridge The name of the bridge. If empty, the default bridge
704 will be used instead (the first one in the list returned by brctl
705 show); this is the behaviour of the vif-bridge script.
706 @return The XendNetwork instance to which this bridge is attached.
707 @raise Exception if the interface is not connected to a network.
708 """
709 if not bridge:
710 rc, bridge = commands.getstatusoutput(
711 'brctl show | cut -d "\n" -f 2 | cut -f 1')
712 if rc != 0 or not bridge:
713 raise Exception(
714 'Could not find default bridge, and none was specified')
716 for network_uuid in XendNetwork.get_all():
717 network = XendAPIStore.get(network_uuid, "network")
718 if network.get_name_label() == bridge:
719 return network
720 else:
721 raise Exception('Cannot find network for bridge %s' % bridge)
723 #
724 # Debug keys.
725 #
727 def send_debug_keys(self, keys):
728 return self.xc.send_debug_keys(keys)
730 #
731 # Getting host information.
732 #
734 def info(self):
735 return (self.nodeinfo() + self.physinfo() + self.xeninfo() +
736 self.xendinfo())
738 def nodeinfo(self):
739 (sys, host, rel, ver, mch) = os.uname()
740 return [['system', sys],
741 ['host', host],
742 ['release', rel],
743 ['version', ver],
744 ['machine', mch]]
746 def list_to_rangepairs(self,cmap):
747 cmap.sort()
748 pairs = []
749 x = y = 0
750 for i in range(0,len(cmap)):
751 try:
752 if ((cmap[y+1] - cmap[i]) > 1):
753 pairs.append((cmap[x],cmap[y]))
754 x = y = i+1
755 else:
756 y = y + 1
757 # if we go off the end, then just add x to y
758 except IndexError:
759 pairs.append((cmap[x],cmap[y]))
761 return pairs
763 def format_pairs(self,pairs):
764 if not pairs:
765 return "no cpus"
766 out = ""
767 for f,s in pairs:
768 if (f==s):
769 out += '%d'%f
770 else:
771 out += '%d-%d'%(f,s)
772 out += ','
773 # trim trailing ','
774 return out[:-1]
776 def list_to_strrange(self,list):
777 return self.format_pairs(self.list_to_rangepairs(list))
779 def format_node_to_cpu(self, pinfo):
780 str=''
781 whitespace=''
782 try:
783 node_to_cpu=pinfo['node_to_cpu']
784 for i in range(0, pinfo['nr_nodes']):
785 str+='%snode%d:%s\n' % (whitespace,
786 i,
787 self.list_to_strrange(node_to_cpu[i]))
788 whitespace='%25s' % ''
789 except:
790 str='none\n'
791 return str[:-1];
792 def format_node_to_memory(self, pinfo):
793 str=''
794 whitespace=''
795 try:
796 node_to_memory=pinfo['node_to_memory']
797 for i in range(0, pinfo['nr_nodes']):
798 str+='%snode%d:%d\n' % (whitespace,
799 i,
800 node_to_memory[i] / 1024)
801 whitespace='%25s' % ''
802 except:
803 str='none\n'
804 return str[:-1];
807 def physinfo(self):
808 info = self.xc.physinfo()
810 info['cpu_mhz'] = info['cpu_khz'] / 1000
812 # physinfo is in KiB, need it in MiB
813 info['total_memory'] = info['total_memory'] / 1024
814 info['free_memory'] = info['free_memory'] / 1024
815 info['node_to_cpu'] = self.format_node_to_cpu(info)
816 info['node_to_memory'] = self.format_node_to_memory(info)
818 ITEM_ORDER = ['nr_cpus',
819 'nr_nodes',
820 'cores_per_socket',
821 'threads_per_core',
822 'cpu_mhz',
823 'hw_caps',
824 'virt_caps',
825 'total_memory',
826 'free_memory',
827 'node_to_cpu',
828 'node_to_memory'
829 ]
831 return [[k, info[k]] for k in ITEM_ORDER]
834 def pciinfo(self):
835 # Each element of dev_list is a PciDevice
836 dev_list = PciUtil.find_all_devices_owned_by_pciback()
838 # Each element of devs_list is a list of PciDevice
839 devs_list = PciUtil.check_FLR_capability(dev_list)
841 devs_list = PciUtil.check_mmio_bar(devs_list)
843 # Check if the devices have been assigned to guests.
844 final_devs_list = []
845 for dev_list in devs_list:
846 available = True
847 for d in dev_list:
848 pci_str = '0x%x,0x%x,0x%x,0x%x' %(d.domain, d.bus, d.slot, d.func)
849 # Xen doesn't care what the domid is, so we pass 0 here...
850 domid = 0
851 bdf = self.xc.test_assign_device(domid, pci_str)
852 if bdf != 0:
853 available = False
854 break
855 if available:
856 final_devs_list = final_devs_list + [dev_list]
858 pci_sxp_list = []
859 for dev_list in final_devs_list:
860 for d in dev_list:
861 pci_sxp = ['dev', ['domain', '0x%04x' % d.domain],
862 ['bus', '0x%02x' % d.bus],
863 ['slot', '0x%02x' % d.slot],
864 ['func', '0x%x' % d.func]]
865 pci_sxp_list.append(pci_sxp)
867 return pci_sxp_list
870 def xenschedinfo(self):
871 sched_id = self.xc.sched_id_get()
872 if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
873 return 'sedf'
874 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
875 return 'credit'
876 else:
877 return 'unknown'
879 def xeninfo(self):
880 info = self.xc.xeninfo()
881 info['xen_scheduler'] = self.xenschedinfo()
883 ITEM_ORDER = ['xen_major',
884 'xen_minor',
885 'xen_extra',
886 'xen_caps',
887 'xen_scheduler',
888 'xen_pagesize',
889 'platform_params',
890 'xen_changeset',
891 'cc_compiler',
892 'cc_compile_by',
893 'cc_compile_domain',
894 'cc_compile_date',
895 ]
897 return [[k, info[k]] for k in ITEM_ORDER]
899 def xendinfo(self):
900 return [['xend_config_format', 4]]
902 #
903 # utilisation tracking
904 #
906 def get_vcpu_util(self, domid, vcpuid):
907 cpu_loads = self.monitor.get_domain_vcpus_util()
908 if domid in cpu_loads:
909 return cpu_loads[domid].get(vcpuid, 0.0)
910 return 0.0
912 def get_vif_util(self, domid, vifid):
913 vif_loads = self.monitor.get_domain_vifs_util()
914 if domid in vif_loads:
915 return vif_loads[domid].get(vifid, (0.0, 0.0))
916 return (0.0, 0.0)
918 def get_vif_stat(self, domid, vifid):
919 vif_loads = self.monitor.get_domain_vifs_stat()
920 if domid in vif_loads:
921 return vif_loads[domid].get(vifid, (0.0, 0.0))
922 return (0.0, 0.0)
924 def get_vbd_util(self, domid, vbdid):
925 vbd_loads = self.monitor.get_domain_vbds_util()
926 if domid in vbd_loads:
927 return vbd_loads[domid].get(vbdid, (0.0, 0.0))
928 return (0.0, 0.0)
930 # dictionary version of *info() functions to get rid of
931 # SXPisms.
932 def nodeinfo_dict(self):
933 return dict(self.nodeinfo())
934 def xendinfo_dict(self):
935 return dict(self.xendinfo())
936 def xeninfo_dict(self):
937 return dict(self.xeninfo())
938 def physinfo_dict(self):
939 return dict(self.physinfo())
940 def info_dict(self):
941 return dict(self.info())
943 # tmem
944 def tmem_list(self, cli_id, use_long):
945 pool_id = -1
946 subop = TMEMC_LIST
947 arg1 = 32768
948 arg2 = use_long
949 buf = ''
950 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
952 def tmem_thaw(self, cli_id):
953 pool_id = -1
954 subop = TMEMC_THAW
955 arg1 = 0
956 arg2 = 0
957 buf = ''
958 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
960 def tmem_freeze(self, cli_id):
961 pool_id = -1
962 subop = TMEMC_FREEZE
963 arg1 = 0
964 arg2 = 0
965 buf = ''
966 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
968 def tmem_flush(self, cli_id, pages):
969 pool_id = -1
970 subop = TMEMC_FLUSH
971 arg1 = pages
972 arg2 = 0
973 buf = ''
974 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
976 def tmem_destroy(self, cli_id):
977 pool_id = -1
978 subop = TMEMC_DESTROY
979 arg1 = 0
980 arg2 = 0
981 buf = ''
982 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
984 def tmem_set_weight(self, cli_id, arg1):
985 pool_id = -1
986 subop = TMEMC_SET_WEIGHT
987 arg2 = 0
988 buf = ''
989 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
991 def tmem_set_cap(self, cli_id, arg1):
992 pool_id = -1
993 subop = TMEMC_SET_CAP
994 arg2 = 0
995 buf = ''
996 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
998 def tmem_set_compress(self, cli_id, arg1):
999 pool_id = -1
1000 subop = TMEMC_SET_COMPRESS
1001 arg2 = 0
1002 buf = ''
1003 return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, buf)
1006 def instance():
1007 global inst
1008 try:
1009 inst
1010 except:
1011 inst = XendNode()
1012 inst.save()
1013 return inst