debuggers.hg

view tools/python/xen/xend/XendNode.py @ 13634:2932d0e7c554

[XEND] Fix typo in XendNode

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Wed Jan 24 18:06:14 2007 +0000 (2007-01-24)
parents 665be23d7fe9
children b97780b7080d
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 Xensource Inc.
17 #============================================================================
19 import os
20 import socket
21 import xen.lowlevel.xc
23 from xen.util import Brctl
25 from xen.xend import uuid
26 from xen.xend.XendError import XendError, NetworkAlreadyConnected
27 from xen.xend.XendOptions import instance as xendoptions
28 from xen.xend.XendQCoWStorageRepo import XendQCoWStorageRepo
29 from xen.xend.XendLocalStorageRepo import XendLocalStorageRepo
30 from xen.xend.XendLogging import log
31 from xen.xend.XendPIF import *
32 from xen.xend.XendNetwork import *
33 from xen.xend.XendStateStore import XendStateStore
34 from xen.xend.XendMonitor import XendMonitor
36 class XendNode:
37 """XendNode - Represents a Domain 0 Host."""
39 def __init__(self):
40 """Initalises the state of all host specific objects such as
42 * Host
43 * Host_CPU
44 * PIF
45 * Network
46 * Storage Repository
47 """
49 self.xc = xen.lowlevel.xc.xc()
50 self.state_store = XendStateStore(xendoptions().get_xend_state_path())
51 self.monitor = XendMonitor()
52 self.monitor.start()
54 # load host state from XML file
55 saved_host = self.state_store.load_state('host')
56 if saved_host and len(saved_host.keys()) == 1:
57 self.uuid = saved_host.keys()[0]
58 host = saved_host[self.uuid]
59 self.name = host.get('name_label', socket.gethostname())
60 self.desc = host.get('name_description', '')
61 self.cpus = {}
62 else:
63 self.uuid = uuid.createString()
64 self.name = socket.gethostname()
65 self.desc = ''
66 self.cpus = {}
68 # load CPU UUIDs
69 saved_cpus = self.state_store.load_state('cpu')
70 for cpu_uuid, cpu in saved_cpus.items():
71 self.cpus[cpu_uuid] = cpu
73 # verify we have enough cpus here
74 physinfo = self.physinfo_dict()
75 cpu_count = physinfo['nr_cpus']
76 cpu_features = physinfo['hw_caps']
78 # If the number of CPUs don't match, we should just reinitialise
79 # the CPU UUIDs.
80 if cpu_count != len(self.cpus):
81 self.cpus = {}
82 for i in range(cpu_count):
83 cpu_uuid = uuid.createString()
84 cpu_info = {'uuid': cpu_uuid,
85 'host': self.uuid,
86 'number': i,
87 'features': cpu_features}
88 self.cpus[cpu_uuid] = cpu_info
90 self.pifs = {}
91 self.networks = {}
92 self.srs = {}
94 # initialise networks
95 saved_networks = self.state_store.load_state('network')
96 if saved_networks:
97 for net_uuid, network in saved_networks.items():
98 self.network_create(network.get('name_label'),
99 network.get('name_description', ''),
100 network.get('default_gateway', ''),
101 network.get('default_netmask', ''),
102 False, net_uuid)
103 else:
104 gateway, netmask = linux_get_default_network()
105 self.network_create('net0', '', gateway, netmask, False)
107 # initialise PIFs
108 saved_pifs = self.state_store.load_state('pif')
109 if saved_pifs:
110 for pif_uuid, pif in saved_pifs.items():
111 if pif.get('network') in self.networks:
112 network = self.networks[pif['network']]
113 try:
114 self.PIF_create(pif['name'], pif['MTU'], pif['VLAN'],
115 pif['MAC'], network, False, pif_uuid)
116 except NetworkAlreadyConnected, exn:
117 log.error('Cannot load saved PIF %s, as network %s ' +
118 'is already connected to PIF %s',
119 pif_uuid, pif['network'], exn.pif_uuid)
120 else:
121 for name, mtu, mac in linux_get_phy_ifaces():
122 network = self.networks.values()[0]
123 self.PIF_create(name, mtu, '', mac, network, False)
125 # initialise storage
126 saved_srs = self.state_store.load_state('sr')
127 if saved_srs:
128 for sr_uuid, sr_cfg in saved_srs.items():
129 if sr_cfg['type'] == 'qcow_file':
130 self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
131 elif sr_cfg['type'] == 'local_image':
132 self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)
134 # Create missing SRs if they don't exist
135 if not self.get_sr_by_type('local_image'):
136 image_sr_uuid = uuid.createString()
137 self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
139 if not self.get_sr_by_type('qcow_file'):
140 qcow_sr_uuid = uuid.createString()
141 self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
145 def network_create(self, name_label, name_description,
146 default_gateway, default_netmask, persist = True,
147 net_uuid = None):
148 if net_uuid is None:
149 net_uuid = uuid.createString()
150 self.networks[net_uuid] = XendNetwork(net_uuid, name_label,
151 name_description,
152 default_gateway,
153 default_netmask)
154 if persist:
155 self.save_networks()
156 return net_uuid
159 def network_destroy(self, net_uuid):
160 del self.networks[net_uuid]
161 self.save_networks()
164 def PIF_create(self, name, mtu, vlan, mac, network, persist = True,
165 pif_uuid = None):
166 for pif in self.pifs.values():
167 if pif.network == network:
168 raise NetworkAlreadyConnected(pif.uuid)
170 if pif_uuid is None:
171 pif_uuid = uuid.createString()
172 self.pifs[pif_uuid] = XendPIF(pif_uuid, name, mtu, vlan, mac, network,
173 self)
174 if persist:
175 self.save_PIFs()
176 self.refreshBridges()
177 return pif_uuid
180 def PIF_create_VLAN(self, pif_uuid, network_uuid, vlan):
181 pif = self.pifs[pif_uuid]
182 network = self.networks[network_uuid]
183 return self.PIF_create(pif.name, pif.mtu, vlan, pif.mac, network)
186 def PIF_destroy(self, pif_uuid):
187 del self.pifs[pif_uuid]
188 self.save_PIFs()
191 def save(self):
192 # save state
193 host_record = {self.uuid: {'name_label':self.name,
194 'name_description':self.desc}}
195 self.state_store.save_state('host',host_record)
196 self.state_store.save_state('cpu', self.cpus)
197 self.save_PIFs()
198 self.save_networks()
199 self.save_SRs()
201 def save_PIFs(self):
202 pif_records = dict([(k, v.get_record(transient = False))
203 for k, v in self.pifs.items()])
204 self.state_store.save_state('pif', pif_records)
206 def save_networks(self):
207 net_records = dict([(k, v.get_record(transient = False))
208 for k, v in self.networks.items()])
209 self.state_store.save_state('network', net_records)
211 def save_SRs(self):
212 sr_records = dict([(k, v.get_record(transient = False))
213 for k, v in self.srs.items()])
214 self.state_store.save_state('sr', sr_records)
216 def shutdown(self):
217 return 0
219 def reboot(self):
220 return 0
222 def notify(self, _):
223 return 0
225 #
226 # Ref validation
227 #
229 def is_valid_host(self, host_ref):
230 return (host_ref == self.uuid)
232 def is_valid_cpu(self, cpu_ref):
233 return (cpu_ref in self.cpus)
235 def is_valid_network(self, network_ref):
236 return (network_ref in self.networks)
238 def is_valid_sr(self, sr_ref):
239 return (sr_ref in self.srs)
241 def is_valid_vdi(self, vdi_ref):
242 for sr in self.srs.values():
243 if sr.is_valid_vdi(vdi_ref):
244 return True
245 return False
247 #
248 # Storage Repositories
249 #
251 def get_sr(self, sr_uuid):
252 return self.srs.get(sr_uuid)
254 def get_sr_by_type(self, sr_type):
255 return [sr.uuid for sr in self.srs.values() if sr.type == sr_type]
257 def get_sr_by_name(self, name):
258 return [sr.uuid for sr in self.srs.values() if sr.name_label == name]
260 def get_all_sr_uuid(self):
261 return self.srs.keys()
263 def get_vdi_by_uuid(self, vdi_uuid):
264 for sr in self.srs.values():
265 if sr.is_valid_vdi(vdi_uuid):
266 return sr.get_vdi_by_uuid(vdi_uuid)
267 return None
269 def get_vdi_by_name_label(self, name):
270 for sr in self.srs.values():
271 vdi = sr.get_vdi_by_name_label(name)
272 if vdi:
273 return vdi
274 return None
276 def get_sr_containing_vdi(self, vdi_uuid):
277 for sr in self.srs.values():
278 if sr.is_valid_vdi(vdi_uuid):
279 return sr
280 return None
283 #
284 # Host Functions
285 #
287 def xen_version(self):
288 info = self.xc.xeninfo()
289 try:
290 from xen import VERSION
291 return {'Xen': '%(xen_major)d.%(xen_minor)d' % info,
292 'Xend': VERSION}
293 except (ImportError, AttributeError):
294 return {'Xen': '%(xen_major)d.%(xen_minor)d' % info,
295 'Xend': '3.0.3'}
297 def get_name(self):
298 return self.name
300 def set_name(self, new_name):
301 self.name = new_name
303 def get_description(self):
304 return self.desc
306 def set_description(self, new_desc):
307 self.desc = new_desc
309 def get_uuid(self):
310 return self.uuid
312 #
313 # Host CPU Functions
314 #
316 def get_host_cpu_by_uuid(self, host_cpu_uuid):
317 if host_cpu_uuid in self.cpus:
318 return host_cpu_uuid
319 raise XendError('Invalid CPU UUID')
321 def get_host_cpu_refs(self):
322 return self.cpus.keys()
324 def get_host_cpu_uuid(self, host_cpu_ref):
325 if host_cpu_ref in self.cpus:
326 return host_cpu_ref
327 else:
328 raise XendError('Invalid CPU Reference')
330 def get_host_cpu_features(self, host_cpu_ref):
331 try:
332 return self.cpus[host_cpu_ref]['features']
333 except KeyError:
334 raise XendError('Invalid CPU Reference')
336 def get_host_cpu_number(self, host_cpu_ref):
337 try:
338 return self.cpus[host_cpu_ref]['number']
339 except KeyError:
340 raise XendError('Invalid CPU Reference')
342 def get_host_cpu_load(self, host_cpu_ref):
343 host_cpu = self.cpus.get(host_cpu_ref)
344 if not host_cpu:
345 return 0.0
347 vcpu = int(host_cpu['number'])
348 cpu_loads = self.monitor.get_domain_vcpus_util()
349 if 0 in cpu_loads and vcpu in cpu_loads[0]:
350 return cpu_loads[0][vcpu]
352 return 0.0
354 #
355 # Network Functions
356 #
358 def get_network_refs(self):
359 return self.networks.keys()
361 def get_network(self, network_ref):
362 return self.networks[network_ref]
364 def bridge_to_network(self, bridge):
365 """
366 Determine which network a particular bridge is attached to.
368 @param bridge The name of the bridge. If empty, the default bridge
369 will be used instead (the first one in the list returned by brctl
370 show); this is the behaviour of the vif-bridge script.
371 @return The XendNetwork instance to which this bridge is attached.
372 @raise Exception if the interface is not connected to a network.
373 """
374 if not bridge:
375 rc, bridge = commands.getstatusoutput(
376 'brctl show | cut -d "\n" -f 2 | cut -f 1')
377 if rc != 0 or not bridge:
378 raise Exception(
379 'Could not find default bridge, and none was specified')
381 bridges = Brctl.get_state()
382 if bridge not in bridges:
383 raise Exception('Bridge %s is not up' % bridge)
384 for pif in self.pifs.values():
385 if pif.interface_name() in bridges[bridge]:
386 return pif.network
387 raise Exception('Bridge %s is not connected to a network' % bridge)
390 #
391 # Getting host information.
392 #
394 def info(self):
395 return (self.nodeinfo() + self.physinfo() + self.xeninfo() +
396 self.xendinfo())
398 def nodeinfo(self):
399 (sys, host, rel, ver, mch) = os.uname()
400 return [['system', sys],
401 ['host', host],
402 ['release', rel],
403 ['version', ver],
404 ['machine', mch]]
406 def physinfo(self):
407 info = self.xc.physinfo()
409 info['nr_cpus'] = (info['nr_nodes'] *
410 info['sockets_per_node'] *
411 info['cores_per_socket'] *
412 info['threads_per_core'])
413 info['cpu_mhz'] = info['cpu_khz'] / 1000
414 # physinfo is in KiB
415 info['total_memory'] = info['total_memory'] / 1024
416 info['free_memory'] = info['free_memory'] / 1024
418 ITEM_ORDER = ['nr_cpus',
419 'nr_nodes',
420 'sockets_per_node',
421 'cores_per_socket',
422 'threads_per_core',
423 'cpu_mhz',
424 'hw_caps',
425 'total_memory',
426 'free_memory',
427 ]
429 return [[k, info[k]] for k in ITEM_ORDER]
431 def xenschedinfo(self):
432 sched_id = self.xc.sched_id_get()
433 if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
434 return 'sedf'
435 elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
436 return 'credit'
437 else:
438 return 'unknown'
440 def xeninfo(self):
441 info = self.xc.xeninfo()
442 info['xen_scheduler'] = self.xenschedinfo()
444 ITEM_ORDER = ['xen_major',
445 'xen_minor',
446 'xen_extra',
447 'xen_caps',
448 'xen_scheduler',
449 'xen_pagesize',
450 'platform_params',
451 'xen_changeset',
452 'cc_compiler',
453 'cc_compile_by',
454 'cc_compile_domain',
455 'cc_compile_date',
456 ]
458 return [[k, info[k]] for k in ITEM_ORDER]
460 def xendinfo(self):
461 return [['xend_config_format', 3]]
463 #
464 # utilisation tracking
465 #
467 def get_vcpu_util(self, domid, vcpuid):
468 cpu_loads = self.monitor.get_domain_vcpus_util()
469 if domid in cpu_loads:
470 return cpu_loads[domid].get(vcpuid, 0.0)
471 return 0.0
473 def get_vif_util(self, domid, vifid):
474 vif_loads = self.monitor.get_domain_vifs_util()
475 if domid in vif_loads:
476 return vif_loads[domid].get(vifid, (0.0, 0.0))
477 return (0.0, 0.0)
479 def get_vbd_util(self, domid, vbdid):
480 vbd_loads = self.monitor.get_domain_vbds_util()
481 if domid in vbd_loads:
482 return vbd_loads[domid].get(vbdid, (0.0, 0.0))
483 return (0.0, 0.0)
485 def get_pif_util(self, pifid):
486 pifs_util = self.monitor.get_pifs_util()
487 if pifid in pifs_util:
488 return pifs_util[pifid]
489 return (0.0, 0.0)
491 # dictionary version of *info() functions to get rid of
492 # SXPisms.
493 def nodeinfo_dict(self):
494 return dict(self.nodeinfo())
495 def xendinfo_dict(self):
496 return dict(self.xendinfo())
497 def xeninfo_dict(self):
498 return dict(self.xeninfo())
499 def physinfo_dict(self):
500 return dict(self.physinfo())
501 def info_dict(self):
502 return dict(self.info())
505 def refreshBridges(self):
506 for pif in self.pifs.values():
507 pif.refresh(Brctl.get_state())
510 def instance():
511 global inst
512 try:
513 inst
514 except:
515 inst = XendNode()
516 inst.save()
517 return inst