ia64/xen-unstable

view tools/python/xen/xend/XendDomainInfo.py @ 1727:ea24a5b766a2

bitkeeper revision 1.1058 (40ee95423ht4Gq0VKvBW7yu6DP8hZA)

Pass domain name down to vifctl to avoid recursion.
author mjw@wray-m-3.hpl.hp.com
date Fri Jul 09 12:53:22 2004 +0000 (2004-07-09)
parents 0c56e48ba3b6
children 3e4c28963eba
line source
1 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 """Representation of a single domain.
4 Includes support for domain construction, using
5 open-ended configurations.
7 Author: Mike Wray <mike.wray@hpl.hp.com>
9 """
11 import string
12 import types
13 import re
14 import sys
15 import os
17 from twisted.internet import defer
18 #defer.Deferred.debug = 1
20 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
21 import xen.util.ip
22 from xen.util.ip import _readline, _readlines
24 import sxp
26 import XendConsole
27 xendConsole = XendConsole.instance()
29 import server.SrvDaemon
30 xend = server.SrvDaemon.instance()
32 SIF_BLK_BE_DOMAIN = (1<<4)
33 SIF_NET_BE_DOMAIN = (1<<5)
35 class VmError(ValueError):
36 """Vm construction error."""
38 def __init__(self, value):
39 self.value = value
41 def __str__(self):
42 return self.value
45 def blkdev_name_to_number(name):
46 """Take the given textual block-device name (e.g., '/dev/sda1',
47 'hda') and return the device number used by the OS. """
49 if not re.match( '/dev/', name ):
50 name = '/dev/' + name
52 return os.stat(name).st_rdev
54 def lookup_raw_partn(partition):
55 """Take the given block-device name (e.g., '/dev/sda1', 'hda')
56 and return a dictionary { device, start_sector,
57 nr_sectors, type }
58 device: Device number of the given partition
59 start_sector: Index of first sector of the partition
60 nr_sectors: Number of sectors comprising this partition
61 type: 'Disk' or identifying name for partition type
62 """
64 if not re.match( '/dev/', partition ):
65 partition = '/dev/' + partition
67 """Try and match non-standard scsi raid arraysa
68 """
69 if re.match( '/dev/cciss/c[0-9]+d[0-9]+p[0-9]+', partition ):
70 drive = re.split( 'p[0-9]+', partition )[0]
71 else:
72 drive = re.split( '[0-9]', partition )[0]
74 if drive == partition:
75 fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
76 line = _readline(fd)
77 if line:
78 return [ { 'device' : blkdev_name_to_number(drive),
79 'start_sector' : long(0),
80 'nr_sectors' : long(line) * 2,
81 'type' : 'Disk' } ]
82 return None
84 # determine position on disk
85 fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
87 #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
88 lines = _readlines(fd)
89 for line in lines:
90 m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
91 'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
92 if m:
93 return [ { 'device' : blkdev_name_to_number(drive),
94 'start_sector' : long(m.group(1)),
95 'nr_sectors' : long(m.group(2)),
96 'type' : m.group(3) } ]
98 return None
100 def lookup_disk_uname(uname):
101 """Lookup a list of segments for a physical device.
102 uname [string]: name of the device in the format \'phy:dev\' for a physical device
103 returns [list of dicts]: list of extents that make up the named device
104 """
105 ( type, d_name ) = string.split( uname, ':' )
107 if type == "phy":
108 segments = lookup_raw_partn( d_name )
109 else:
110 segments = None
111 return segments
113 def make_disk(dom, uname, dev, mode, recreate=0):
114 """Create a virtual disk device for a domain.
116 @returns Deferred
117 """
118 segments = lookup_disk_uname(uname)
119 if not segments:
120 raise VmError("vbd: Segments not found: uname=%s" % uname)
121 if len(segments) > 1:
122 raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
123 segment = segments[0]
124 vdev = blkdev_name_to_number(dev)
125 ctrl = xend.blkif_create(dom, recreate=recreate)
127 def fn(ctrl):
128 return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate)
129 ctrl.addCallback(fn)
130 return ctrl
132 def vif_up(iplist):
133 """send an unsolicited ARP reply for all non link-local IP addresses.
135 iplist IP addresses
136 """
138 IP_NONLOCAL_BIND = '/proc/sys/net/ipv4/ip_nonlocal_bind'
140 def get_ip_nonlocal_bind():
141 return int(open(IP_NONLOCAL_BIND, 'r').read()[0])
143 def set_ip_nonlocal_bind(v):
144 print >> open(IP_NONLOCAL_BIND, 'w'), str(v)
146 def link_local(ip):
147 return xen.util.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
149 def arping(ip, gw):
150 cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw)
151 print cmd
152 os.system(cmd)
154 gateway = xen.util.ip.get_current_ipgw() or '255.255.255.255'
155 nlb = get_ip_nonlocal_bind()
156 if not nlb: set_ip_nonlocal_bind(1)
157 try:
158 for ip in iplist:
159 if not link_local(ip):
160 arping(ip, gateway)
161 finally:
162 if not nlb: set_ip_nonlocal_bind(0)
164 config_handlers = {}
166 def add_config_handler(name, h):
167 """Add a handler for a config field.
169 name field name
170 h handler: fn(vm, config, field, index)
171 """
172 config_handlers[name] = h
174 def get_config_handler(name):
175 """Get a handler for a config field.
177 returns handler or None
178 """
179 return config_handlers.get(name)
181 """Table of handlers for virtual machine images.
182 Indexed by image type.
183 """
184 image_handlers = {}
186 def add_image_handler(name, h):
187 """Add a handler for an image type
188 name image type
189 h handler: fn(config, name, memory, image)
190 """
191 image_handlers[name] = h
193 def get_image_handler(name):
194 """Get the handler for an image type.
195 name image type
197 returns handler or None
198 """
199 return image_handlers.get(name)
201 """Table of handlers for devices.
202 Indexed by device type.
203 """
204 device_handlers = {}
206 def add_device_handler(name, h):
207 """Add a handler for a device type.
209 name device type
210 h handler: fn(vm, dev)
211 """
212 device_handlers[name] = h
214 def get_device_handler(name):
215 """Get the handler for a device type.
217 name device type
219 returns handler or None
220 """
221 return device_handlers.get(name)
223 def vm_create(config):
224 """Create a VM from a configuration.
225 If a vm has been partially created and there is an error it
226 is destroyed.
228 config configuration
230 returns Deferred
231 raises VmError for invalid configuration
232 """
233 print 'vm_create>'
234 vm = XendDomainInfo()
235 return vm.construct(config)
237 def vm_recreate(config, info):
238 """Create the VM object for an existing domain.
239 """
240 vm = XendDomainInfo()
241 vm.recreate = 1
242 vm.setdom(info['dom'])
243 vm.name = info['name']
244 vm.memory = info['mem_kb']/1024
245 if config:
246 d = vm.construct(config)
247 else:
248 d = defer.Deferred()
249 d.callback(vm)
250 return d
252 def vm_restore(src, progress=0):
253 """Restore a VM from a disk image.
255 src saved state to restore
256 progress progress reporting flag
257 returns deferred
258 raises VmError for invalid configuration
259 """
260 vm = XendDomainInfo()
261 ostype = "linux" #todo Set from somewhere (store in the src?).
262 restorefn = getattr(xc, "%s_restore" % ostype)
263 d = restorefn(state_file=src, progress=progress)
264 dom = int(d['dom'])
265 if dom < 0:
266 raise VmError('restore failed')
267 vmconfig = sxp.from_string(d['vmconfig'])
268 vm.config = sxp.child_value(vmconfig, 'config')
269 deferred = vm.dom_configure(dom)
270 def vifs_cb(val, vm):
271 vif_up(vm.ipaddrs)
272 deferred.addCallback(vifs_cb, vm)
273 return deferred
275 def dom_get(dom):
276 domlist = xc.domain_getinfo(dom=dom)
277 if domlist and dom == domlist[0]['dom']:
278 return domlist[0]
279 return None
282 def append_deferred(dlist, v):
283 if isinstance(v, defer.Deferred):
284 dlist.append(v)
286 def _vm_configure1(val, vm):
287 d = vm.create_devices()
288 #print '_vm_configure1> made devices...'
289 def cbok(x):
290 #print '_vm_configure1> cbok', x
291 return x
292 d.addCallback(cbok)
293 d.addCallback(_vm_configure2, vm)
294 #print '_vm_configure1<'
295 return d
297 def _vm_configure2(val, vm):
298 #print '>callback _vm_configure2...'
299 d = vm.configure_fields()
300 def cbok(results):
301 #print '_vm_configure2> cbok', results
302 return vm
303 def cberr(err):
304 #print '_vm_configure2> cberr', err
305 vm.destroy()
306 return err
307 d.addCallback(cbok)
308 d.addErrback(cberr)
309 #print '<_vm_configure2'
310 return d
312 class XendDomainInfo:
313 """Virtual machine object."""
315 STATE_OK = "ok"
316 STATE_TERMINATED = "terminated"
318 def __init__(self):
319 self.recreate = 0
320 self.config = None
321 self.id = None
322 self.dom = None
323 self.name = None
324 self.memory = None
325 self.image = None
326 self.ramdisk = None
327 self.cmdline = None
328 self.console = None
329 self.devices = {}
330 self.configs = []
331 self.info = None
332 self.ipaddrs = []
333 self.blkif_backend = 0
334 self.netif_backend = 0
335 #todo: state: running, suspended
336 self.state = self.STATE_OK
337 #todo: set to migrate info if migrating
338 self.migrate = None
339 #Whether to auto-restart
340 self.autorestart = 0
342 def setdom(self, dom):
343 self.dom = int(dom)
344 self.id = str(dom)
346 def update(self, info):
347 """Update with info from xc.domain_getinfo().
348 """
349 self.info = info
350 self.memory = self.info['mem_kb'] / 1024
352 def __str__(self):
353 s = "domain"
354 s += " id=" + self.id
355 s += " name=" + self.name
356 s += " memory=" + str(self.memory)
357 if self.console:
358 s += " console=" + self.console.id
359 if self.image:
360 s += " image=" + self.image
361 s += ""
362 return s
364 __repr__ = __str__
366 def sxpr(self):
367 sxpr = ['domain',
368 ['id', self.id],
369 ['name', self.name],
370 ['memory', self.memory] ]
371 if self.info:
372 run = (self.info['running'] and 'r') or '-'
373 block = (self.info['blocked'] and 'b') or '-'
374 stop = (self.info['paused'] and 'p') or '-'
375 susp = (self.info['shutdown'] and 's') or '-'
376 crash = (self.info['crashed'] and 'c') or '-'
377 state = run + block + stop + susp + crash
378 sxpr.append(['state', state])
379 if self.info['shutdown']:
380 reasons = ["poweroff", "reboot", "suspend"]
381 reason = reasons[self.info['shutdown_reason']]
382 sxpr.append(['shutdown_reason', reason])
383 sxpr.append(['cpu', self.info['cpu']])
384 sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
385 if self.console:
386 sxpr.append(self.console.sxpr())
387 if self.config:
388 sxpr.append(['config', self.config])
389 return sxpr
391 def construct(self, config):
392 # todo - add support for scheduling params?
393 self.config = config
394 try:
395 self.name = sxp.child_value(config, 'name')
396 self.memory = int(sxp.child_value(config, 'memory', '128'))
397 if sxp.child(config, 'autorestart', None):
398 self.autorestart = 1
399 self.configure_backends()
400 image = sxp.child_value(config, 'image')
401 image_name = sxp.name(image)
402 image_handler = get_image_handler(image_name)
403 if image_handler is None:
404 raise VmError('unknown image type: ' + image_name)
405 image_handler(self, image)
406 deferred = self.configure()
407 def cbok(x):
408 print 'vm_create> cbok', x
409 return x
410 def cberr(err):
411 self.destroy()
412 return err
413 deferred.addCallback(cbok)
414 deferred.addErrback(cberr)
415 except StandardError, ex:
416 # Catch errors, cleanup and re-raise.
417 self.destroy()
418 raise
419 print 'vm_create<'
420 return deferred
422 def config_devices(self, name):
423 """Get a list of the 'device' nodes of a given type from the config.
425 name device type
426 return list of device configs
427 """
428 devices = []
429 for d in sxp.children(self.config, 'device'):
430 dev = sxp.child0(d)
431 if dev is None: continue
432 if name == sxp.name(dev):
433 devices.append(dev)
434 return devices
436 def add_device(self, type, dev):
437 """Add a device to a virtual machine.
439 dev device to add
440 """
441 dl = self.devices.get(type, [])
442 dl.append(dev)
443 self.devices[type] = dl
445 def get_devices(self, type):
446 val = self.devices.get(type, [])
447 return val
449 def get_device_by_id(self, type, id):
450 """Get the device with the given id.
452 id device id
454 returns device or None
455 """
456 dl = self.get_devices(type)
457 for d in dl:
458 if d.getprop('id') == id:
459 return d
460 return None
462 def get_device_by_index(self, type, idx):
463 """Get the device with the given index.
465 idx device index
467 returns device or None
468 """
469 dl = self.get_devices(type)
470 if 0 <= idx < len(dl):
471 return dl[idx]
472 else:
473 return None
475 def add_config(self, val):
476 """Add configuration data to a virtual machine.
478 val data to add
479 """
480 self.configs.append(val)
482 def destroy(self):
483 """Completely destroy the vm.
484 """
485 self.cleanup()
486 return self.destroy_domain()
488 def destroy_domain(self):
489 """Destroy the vm's domain.
490 The domain will not finally go away unless all vm
491 devices have been released.
492 """
493 if self.dom is None: return 0
494 chan = xend.getDomChannel(self.dom)
495 if chan:
496 chan.close()
497 return xc.domain_destroy(dom=self.dom)
499 def cleanup(self):
500 """Cleanup vm resources: release devices.
501 """
502 print 'cleanup>', self.dom
503 self.state = self.STATE_TERMINATED
504 self.release_devices()
506 def is_terminated(self):
507 """Check if a domain has been terminated.
508 """
509 return self.state == self.STATE_TERMINATED
511 def release_devices(self):
512 """Release all vm devices.
513 """
514 print 'release_devices>', self.dom
515 self.release_vifs()
516 self.release_vbds()
517 self.devices = {}
519 def release_vifs(self):
520 """Release vm virtual network devices (vifs).
521 """
522 print 'release_vifs>', self.dom
523 if self.dom is None: return
524 ctrl = xend.netif_get(self.dom)
525 if ctrl:
526 ctrl.destroy()
528 def release_vbds(self):
529 """Release vm virtual block devices (vbds).
530 """
531 print 'release_vbds>', self.dom
532 if self.dom is None: return
533 ctrl = xend.blkif_get(self.dom)
534 if ctrl:
535 ctrl.destroy()
537 def show(self):
538 """Print virtual machine info.
539 """
540 print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
541 print "image:"
542 sxp.show(self.image)
543 print
544 for dl in self.devices:
545 for dev in dl:
546 print "device:"
547 sxp.show(dev)
548 print
549 for val in self.configs:
550 print "config:"
551 sxp.show(val)
552 print
553 print "]"
555 def init_domain(self):
556 """Initialize the domain memory.
557 """
558 if self.recreate: return
559 memory = self.memory
560 name = self.name
561 cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
562 print 'init_domain>', memory, name, cpu
563 dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
564 if dom <= 0:
565 raise VmError('Creating domain failed: name=%s memory=%d'
566 % (name, memory))
567 self.setdom(dom)
569 def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
570 """Build the domain boot image.
571 """
572 if self.recreate: return
573 if len(cmdline) >= 256:
574 print 'Warning: kernel cmdline too long'
575 dom = self.dom
576 buildfn = getattr(xc, '%s_build' % ostype)
577 print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
578 flags = 0
579 if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
580 if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
581 err = buildfn(dom = dom,
582 image = kernel,
583 control_evtchn = self.console.port2,
584 cmdline = cmdline,
585 ramdisk = ramdisk,
586 flags = flags)
587 if err != 0:
588 raise VmError('Building domain failed: type=%s dom=%d err=%d'
589 % (ostype, dom, err))
591 def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
592 """Create a domain. Builds the image but does not configure it.
594 ostype OS type
595 kernel kernel image
596 ramdisk kernel ramdisk
597 cmdline kernel commandline
598 vifs_n number of network interfaces
599 """
600 print 'create_domain>', ostype, kernel
601 if not self.recreate:
602 if not os.path.isfile(kernel):
603 raise VmError('Kernel image does not exist: %s' % kernel)
604 if ramdisk and not os.path.isfile(ramdisk):
605 raise VmError('Kernel ramdisk does not exist: %s' % ramdisk)
606 print 'create-domain> init_domain...'
607 self.init_domain()
608 print 'create_domain>', 'dom=', self.dom
609 self.console = xendConsole.console_create(self.dom)
610 self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
611 self.image = kernel
612 self.ramdisk = ramdisk
613 self.cmdline = cmdline
615 def create_devices(self):
616 """Create the devices for a vm.
618 returns Deferred
619 raises VmError for invalid devices
620 """
621 print '>create_devices'
622 dlist = []
623 devices = sxp.children(self.config, 'device')
624 index = {}
625 for d in devices:
626 dev = sxp.child0(d)
627 if dev is None:
628 raise VmError('invalid device')
629 dev_name = sxp.name(dev)
630 dev_index = index.get(dev_name, 0)
631 dev_handler = get_device_handler(dev_name)
632 if dev_handler is None:
633 raise VmError('unknown device type: ' + dev_name)
634 v = dev_handler(self, dev, dev_index)
635 append_deferred(dlist, v)
636 index[dev_name] = dev_index + 1
637 deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
638 print '<create_devices'
639 return deferred
641 def configure_backends(self):
642 """Set configuration flags if the vm is a backend for netif of blkif.
643 """
644 for c in sxp.children(self.config, 'backend'):
645 name = sxp.name(sxp.child0(c))
646 if name == 'blkif':
647 self.blkif_backend = 1
648 elif name == 'netif':
649 self.netif_backend = 1
650 else:
651 raise VmError('invalid backend type:' + str(name))
653 def create_backends(self):
654 """Setup the netif and blkif backends.
655 """
656 if self.blkif_backend:
657 xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
658 if self.netif_backend:
659 xend.netif_set_control_domain(self.dom, recreate=self.recreate)
661 def configure(self):
662 """Configure a vm.
664 vm virtual machine
665 config configuration
667 returns Deferred - calls callback with vm
668 """
669 if self.blkif_backend:
670 d = defer.Deferred()
671 d.callback(1)
672 else:
673 d = xend.blkif_create(self.dom, recreate=self.recreate)
674 d.addCallback(_vm_configure1, self)
675 return d
677 def dom_configure(self, dom):
678 """Configure a domain.
680 dom domain id
681 returns deferred
682 """
683 d = dom_get(dom)
684 if not d:
685 raise VmError("Domain not found: %d" % dom)
686 try:
687 self.setdom(dom)
688 self.name = d['name']
689 self.memory = d['memory']/1024
690 deferred = self.configure()
691 def cberr(err):
692 self.destroy()
693 return err
694 deferred.addErrback(cberr)
695 except StandardError, ex:
696 self.destroy()
697 raise
698 return deferred
700 def configure_fields(self):
701 dlist = []
702 index = {}
703 for field in sxp.children(self.config):
704 field_name = sxp.name(field)
705 field_index = index.get(field_name, 0)
706 field_handler = get_config_handler(field_name)
707 # Ignore unknown fields. Warn?
708 if field_handler:
709 v = field_handler(self, self.config, field, field_index)
710 append_deferred(dlist, v)
711 index[field_name] = field_index + 1
712 d = defer.DeferredList(dlist, fireOnOneErrback=1)
713 return d
716 def vm_image_linux(vm, image):
717 """Create a VM for a linux image.
719 name vm name
720 memory vm memory
721 image image config
723 returns vm
724 """
725 kernel = sxp.child_value(image, "kernel")
726 cmdline = ""
727 ip = sxp.child_value(image, "ip", "dhcp")
728 if ip:
729 cmdline += " ip=" + ip
730 root = sxp.child_value(image, "root")
731 if root:
732 cmdline += " root=" + root
733 args = sxp.child_value(image, "args")
734 if args:
735 cmdline += " " + args
736 ramdisk = sxp.child_value(image, "ramdisk", '')
737 vifs = vm.config_devices("vif")
738 vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
739 return vm
741 def vm_image_netbsd(vm, image):
742 """Create a VM for a bsd image.
744 name vm name
745 memory vm memory
746 image image config
748 returns vm
749 """
750 #todo: Same as for linux. Is that right? If so can unify them.
751 kernel = sxp.child_value(image, "kernel")
752 cmdline = ""
753 ip = sxp.child_value(image, "ip", "dhcp")
754 if ip:
755 cmdline += "ip=" + ip
756 root = sxp.child_value(image, "root")
757 if root:
758 cmdline += "root=" + root
759 args = sxp.child_value(image, "args")
760 if args:
761 cmdline += " " + args
762 ramdisk = sxp.child_value(image, "ramdisk")
763 vifs = vm.config_devices("vif")
764 vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
765 return vm
768 def vm_dev_vif(vm, val, index):
769 """Create a virtual network interface (vif).
771 vm virtual machine
772 val vif config
773 index vif index
774 """
775 if vm.netif_backend:
776 raise VmError('vif: vif in netif backend domain')
777 vif = index #todo
778 vmac = sxp.child_value(val, "mac")
779 xend.netif_create(vm.dom, recreate=vm.recreate)
780 defer = xend.netif_dev_create(vm.dom, vif, val, recreate=vm.recreate)
781 def fn(id):
782 dev = xend.netif_dev(vm.dom, vif)
783 dev.vifctl('up', vmname=vm.name)
784 vm.add_device('vif', dev)
785 print 'vm_dev_vif> created', dev
786 return id
787 defer.addCallback(fn)
788 return defer
790 def vm_dev_vbd(vm, val, index):
791 """Create a virtual block device (vbd).
793 vm virtual machine
794 val vbd config
795 index vbd index
796 """
797 if vm.blkif_backend:
798 raise VmError('vbd: vbd in blkif backend domain')
799 vdev = index
800 uname = sxp.child_value(val, 'uname')
801 if not uname:
802 raise VmError('vbd: Missing uname')
803 dev = sxp.child_value(val, 'dev')
804 if not dev:
805 raise VmError('vbd: Missing dev')
806 mode = sxp.child_value(val, 'mode', 'r')
807 defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
808 def fn(vbd):
809 dev = xend.blkif_dev(vm.dom, vdev)
810 vm.add_device('vbd', dev)
811 return vbd
812 defer.addCallback(fn)
813 return defer
815 def parse_pci(val):
816 if isinstance(val, types.StringType):
817 radix = 10
818 if val.startswith('0x') or val.startswith('0X'):
819 radix = 16
820 v = int(val, radix)
821 else:
822 v = val
823 return v
825 def vm_dev_pci(vm, val, index):
826 bus = sxp.child_value(val, 'bus')
827 if not bus:
828 raise VmError('pci: Missing bus')
829 dev = sxp.child_value(val, 'dev')
830 if not dev:
831 raise VmError('pci: Missing dev')
832 func = sxp.child_value(val, 'func')
833 if not func:
834 raise VmError('pci: Missing func')
835 try:
836 bus = parse_pci(bus)
837 dev = parse_pci(dev)
838 func = parse_pci(func)
839 except:
840 raise VmError('pci: invalid parameter')
841 rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
842 func=func, enable=1)
843 if rc < 0:
844 #todo non-fatal
845 raise VmError('pci: Failed to configure device: bus=%s dev=%s func=%s' %
846 (bus, dev, func))
847 return rc
850 def vm_field_vfr(vm, config, val, index):
851 """Handle a vfr field in a config.
853 vm virtual machine
854 config vm config
855 val vfr field
856 """
857 # Get the rules and add them.
858 # (vfr (vif (id foo) (ip x.x.x.x)) ... )
859 list = sxp.children(val, 'vif')
860 ipaddrs = []
861 for v in list:
862 id = sxp.child_value(v, 'id')
863 if id is None:
864 raise VmError('vfr: missing vif id')
865 id = int(id)
866 dev = vm.get_device_by_index('vif', id)
867 if not dev:
868 raise VmError('vfr: invalid vif id %d' % id)
869 vif = sxp.child_value(dev, 'vif')
870 ip = sxp.child_value(v, 'ip')
871 if not ip:
872 raise VmError('vfr: missing ip address')
873 ipaddrs.append(ip);
874 # todo: Configure the ipaddrs.
875 vm.ipaddrs = ipaddrs
877 def vnet_bridge(vnet, vmac, dom, idx):
878 """Add the device for the vif to the bridge for its vnet.
879 """
880 vif = "vif%d.%d" % (dom, idx)
881 try:
882 cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
883 print "*** vnet_bridge>", cmd
884 out = file("/proc/vnet/policy", "wb")
885 out.write(cmd)
886 err = out.close()
887 print "vnet_bridge>", "err=", err
888 except IOError, ex:
889 print "vnet_bridge>", ex
891 def vm_field_vnet(vm, config, val, index):
892 """Handle a vnet field in a config.
894 vm virtual machine
895 config vm config
896 val vnet field
897 index index
898 """
899 # Get the vif children. For each vif look up the vif device
900 # with the given id and configure its vnet.
901 # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
902 vif_vnets = sxp.children(val, 'vif')
903 for v in vif_vnets:
904 id = sxp.child_value(v, 'id')
905 if id is None:
906 raise VmError('vnet: missing vif id')
907 dev = vm.get_device_by_id('vif', id)
908 #vnet = sxp.child_value(v, 'vnet', 1)
909 #mac = sxp.child_value(dev, 'mac')
910 #vif = sxp.child_value(dev, 'vif')
911 #vnet_bridge(vnet, mac, vm.dom, 0)
912 #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
914 # Register image handlers for linux and bsd.
915 add_image_handler('linux', vm_image_linux)
916 add_image_handler('netbsd', vm_image_netbsd)
918 # Register device handlers for vifs and vbds.
919 add_device_handler('vif', vm_dev_vif)
920 add_device_handler('vbd', vm_dev_vbd)
921 add_device_handler('pci', vm_dev_pci)
923 # Register config handlers for vfr and vnet.
924 add_config_handler('vfr', vm_field_vfr)
925 add_config_handler('vnet', vm_field_vnet)