ia64/xen-unstable

view tools/python/xen/xm/create.py @ 6219:3b0ce44f7b7a

merge?
author cl349@firebug.cl.cam.ac.uk
date Wed Aug 17 08:27:16 2005 +0000 (2005-08-17)
parents 60d20acf8928 3bb1857981e6
children a06430752462 11f556cac45b 509316987d65 23979fb12c49 84ee014ebd41
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) 2005 Nguyen Anh Quynh <aquynh@gmail.com>
17 #============================================================================
19 """Domain creation.
20 """
21 import random
22 import string
23 import sys
24 import socket
25 import commands
27 import xen.lowlevel.xc
29 from xen.xend import sxp
30 from xen.xend import PrettyPrint
31 from xen.xend.XendClient import server, XendError
32 from xen.xend.XendBootloader import bootloader
33 from xen.xend import XendRoot; xroot = XendRoot.instance()
34 from xen.util import blkif
36 from xen.xm.opts import *
38 gopts = Opts(use="""[options] [vars]
40 Create a domain.
42 Domain creation parameters can be set by command-line switches, from
43 a python configuration script or an SXP config file. See documentation
44 for --defconfig, --config. Configuration variables can be set using
45 VAR=VAL on the command line. For example vmid=3 sets vmid to 3.
47 """)
49 gopts.opt('help', short='h',
50 fn=set_true, default=0,
51 use="Print this help.")
53 gopts.opt('help_config',
54 fn=set_true, default=0,
55 use="Print help for the configuration script.")
57 gopts.opt('quiet', short='q',
58 fn=set_true, default=0,
59 use="Quiet.")
61 gopts.opt('path', val='PATH',
62 fn=set_value, default='.:/etc/xen',
63 use="""Search path for configuration scripts.
64 The value of PATH is a colon-separated directory list.""")
66 gopts.opt('defconfig', short='f', val='FILE',
67 fn=set_value, default='xmdefconfig',
68 use="""Use the given Python configuration script.
69 The configuration script is loaded after arguments have been processed.
70 Each command-line option sets a configuration variable named after
71 its long option name, and these variables are placed in the
72 environment of the script before it is loaded.
73 Variables for options that may be repeated have list values.
74 Other variables can be set using VAR=VAL on the command line.
76 After the script is loaded, option values that were not set on the
77 command line are replaced by the values set in the script.""")
79 gopts.default('defconfig')
81 gopts.opt('config', short='F', val='FILE',
82 fn=set_value, default=None,
83 use="""Domain configuration to use (SXP).
84 SXP is the underlying configuration format used by Xen.
85 SXP configurations can be hand-written or generated from Python configuration
86 scripts, using the -n (dryrun) option to print the configuration.""")
88 gopts.opt('load', short='L', val='FILE',
89 fn=set_value, default=None,
90 use='Domain saved state to load.')
92 gopts.opt('dryrun', short='n',
93 fn=set_true, default=0,
94 use="""Dry run - print the configuration but don't create the domain.
95 Loads the configuration script, creates the SXP configuration and prints it.""")
97 gopts.opt('paused', short='p',
98 fn=set_true, default=0,
99 use='Leave the domain paused after it is created.')
101 gopts.opt('console_autoconnect', short='c',
102 fn=set_true, default=0,
103 use="Connect to the console after the domain is created.")
105 gopts.var('vnc', val='no|yes',
106 fn=set_bool, default=None,
107 use="""Spawn a vncviewer listening for a vnc server in the domain.
108 The address of the vncviewer is passed to the domain on the kernel command
109 line using 'VNC_SERVER=<host>:<port>'. The port used by vnc is 5500 + DISPLAY.
110 A display value with a free port is chosen if possible.
111 """)
113 gopts.var('name', val='NAME',
114 fn=set_value, default=None,
115 use="Domain name. Must be unique.")
117 gopts.var('bootloader', val='FILE',
118 fn=set_value, default=None,
119 use="Path to bootloader.")
121 gopts.var('bootentry', val='NAME',
122 fn=set_value, default=None,
123 use="Entry to boot via boot loader")
125 gopts.var('kernel', val='FILE',
126 fn=set_value, default=None,
127 use="Path to kernel image.")
129 gopts.var('ramdisk', val='FILE',
130 fn=set_value, default='',
131 use="Path to ramdisk.")
133 gopts.var('builder', val='FUNCTION',
134 fn=set_value, default='linux',
135 use="Function to use to build the domain.")
137 gopts.var('memory', val='MEMORY',
138 fn=set_int, default=128,
139 use="Domain memory in MB.")
141 gopts.var('ssidref', val='SSIDREF',
142 fn=set_u32, default=-1,
143 use="Security Identifier.")
145 gopts.var('maxmem', val='MEMORY',
146 fn=set_int, default=None,
147 use="Maximum domain memory in MB.")
149 gopts.var('cpu', val='CPU',
150 fn=set_int, default=None,
151 use="CPU to run the domain on.")
153 gopts.var('vcpus', val='VCPUS',
154 fn=set_int, default=1,
155 use="# of Virtual CPUS in domain.")
157 gopts.var('cpu_weight', val='WEIGHT',
158 fn=set_float, default=None,
159 use="""Set the new domain's cpu weight.
160 WEIGHT is a float that controls the domain's share of the cpu.""")
162 gopts.var('restart', val='onreboot|always|never',
163 fn=set_value, default=None,
164 use="""Whether the domain should be restarted on exit.
165 - onreboot: restart on exit with shutdown code reboot
166 - always: always restart on exit, ignore exit code
167 - never: never restart on exit, ignore exit code""")
169 gopts.var('blkif', val='no|yes',
170 fn=set_bool, default=0,
171 use="Make the domain a block device backend.")
173 gopts.var('netif', val='no|yes',
174 fn=set_bool, default=0,
175 use="Make the domain a network interface backend.")
177 gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
178 fn=append_value, default=[],
179 use="""Add a disk device to a domain. The physical device is DEV,
180 which is exported to the domain as VDEV. The disk is read-only if MODE
181 is 'r', read-write if MODE is 'w'. If DOM is specified it defines the
182 backend driver domain to use for the disk.
183 The option may be repeated to add more than one disk.""")
185 gopts.var('pci', val='BUS,DEV,FUNC',
186 fn=append_value, default=[],
187 use="""Add a PCI device to a domain, using given params (in hex).
188 For example '-pci c0,02,1a'.
189 The option may be repeated to add more than one pci device.""")
191 gopts.var('usb', val='PATH',
192 fn=append_value, default=[],
193 use="""Add a physical USB port to a domain, as specified by the path
194 to that port. This option may be repeated to add more than one port.""")
196 gopts.var('ipaddr', val="IPADDR",
197 fn=append_value, default=[],
198 use="Add an IP address to the domain.")
200 gopts.var('vif', val="mac=MAC,be_mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM,vifname=NAME",
201 fn=append_value, default=[],
202 use="""Add a network interface with the given MAC address and bridge.
203 The vif is configured by calling the given configuration script.
204 If mac is not specified a random MAC address is used.
205 The MAC address of the backend interface can be selected with be_mac.
206 If not specified then the network backend chooses it's own MAC address.
207 If bridge is not specified the default bridge is used.
208 If script is not specified the default script is used.
209 If backend is not specified the default backend driver domain is used.
210 If vifname is not specified the backend virtual interface will have name vifD.N
211 where D is the domain id and N is the interface id.
212 This option may be repeated to add more than one vif.
213 Specifying vifs will increase the number of interfaces as needed.""")
215 gopts.var('nics', val="NUM",
216 fn=set_int, default=1,
217 use="""Set the number of network interfaces.
218 Use the vif option to define interface parameters, otherwise
219 defaults are used. Specifying vifs will increase the
220 number of interfaces as needed.""")
222 gopts.var('root', val='DEVICE',
223 fn=set_value, default='',
224 use="""Set the root= parameter on the kernel command line.
225 Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
227 gopts.var('extra', val="ARGS",
228 fn=set_value, default='',
229 use="Set extra arguments to append to the kernel command line.")
231 gopts.var('ip', val='IPADDR',
232 fn=set_value, default='',
233 use="Set the kernel IP interface address.")
235 gopts.var('gateway', val="IPADDR",
236 fn=set_value, default='',
237 use="Set the kernel IP gateway.")
239 gopts.var('netmask', val="MASK",
240 fn=set_value, default = '',
241 use="Set the kernel IP netmask.")
243 gopts.var('hostname', val="NAME",
244 fn=set_value, default='',
245 use="Set the kernel IP hostname.")
247 gopts.var('interface', val="INTF",
248 fn=set_value, default="eth0",
249 use="Set the kernel IP interface name.")
251 gopts.var('dhcp', val="off|dhcp",
252 fn=set_value, default='off',
253 use="Set the kernel dhcp option.")
255 gopts.var('nfs_server', val="IPADDR",
256 fn=set_value, default=None,
257 use="Set the address of the NFS server for NFS root.")
259 gopts.var('nfs_root', val="PATH",
260 fn=set_value, default=None,
261 use="Set the path of the root NFS directory.")
263 gopts.var('memmap', val='FILE',
264 fn=set_value, default='',
265 use="Path to memap SXP file.")
267 gopts.var('device_model', val='FILE',
268 fn=set_value, default='',
269 use="Path to device model program.")
271 gopts.var('fda', val='FILE',
272 fn=set_value, default='',
273 use="Path to fda")
275 gopts.var('fdb', val='FILE',
276 fn=set_value, default='',
277 use="Path to fdb")
279 gopts.var('serial', val='FILE',
280 fn=set_value, default='',
281 use="Path to serial or pty or vc")
283 gopts.var('localtime', val='no|yes',
284 fn=set_bool, default=0,
285 use="Is RTC set to localtime?")
287 gopts.var('stdvga', val='no|yes',
288 fn=set_bool, default=0,
289 use="Use std vga or cirrhus logic graphics")
291 gopts.var('isa', val='no|yes',
292 fn=set_bool, default=0,
293 use="Simulate an ISA only system?")
295 gopts.var('cdrom', val='FILE',
296 fn=set_value, default='',
297 use="Path to cdrom")
299 gopts.var('macaddr', val='MACADDR',
300 fn=set_value, default='',
301 use="Macaddress of the first network interface")
303 gopts.var('boot', val="a|b|c|d",
304 fn=set_value, default='c',
305 use="Default boot device")
307 gopts.var('nographic', val='no|yes',
308 fn=set_bool, default=0,
309 use="Should device models use graphics?")
311 gopts.var('sdl', val='',
312 fn=set_value, default=None,
313 use="""Should the device model use SDL?""")
315 gopts.var('display', val='DISPLAY',
316 fn=set_value, default='localhost:0',
317 use="X11 display to use")
319 def strip(pre, s):
320 """Strip prefix 'pre' if present.
321 """
322 if s.startswith(pre):
323 return s[len(pre):]
324 else:
325 return s
327 def configure_image(opts, config, vals):
328 """Create the image config.
329 """
330 config_image = [ vals.builder ]
331 config_image.append([ 'kernel', os.path.abspath(vals.kernel) ])
332 if vals.ramdisk:
333 config_image.append([ 'ramdisk', os.path.abspath(vals.ramdisk) ])
334 if vals.cmdline_ip:
335 cmdline_ip = strip('ip=', vals.cmdline_ip)
336 config_image.append(['ip', cmdline_ip])
337 if vals.root:
338 cmdline_root = strip('root=', vals.root)
339 config_image.append(['root', cmdline_root])
340 if vals.extra:
341 config_image.append(['args', vals.extra])
342 if vals.vcpus:
343 config_image.append(['vcpus', vals.vcpus])
344 config.append(['image', config_image ])
347 def configure_disks(opts, config_devs, vals):
348 """Create the config for disks (virtual block devices).
349 """
350 for (uname, dev, mode, backend) in vals.disk:
351 config_vbd = ['vbd',
352 ['uname', uname],
353 ['dev', dev ],
354 ['mode', mode ] ]
355 if backend:
356 config_vbd.append(['backend', backend])
357 config_devs.append(['device', config_vbd])
359 def configure_pci(opts, config_devs, vals):
360 """Create the config for pci devices.
361 """
362 for (bus, dev, func) in vals.pci:
363 config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
364 config_devs.append(['device', config_pci])
366 def configure_usb(opts, config_devs, vals):
367 for path in vals.usb:
368 config_usb = ['usb', ['path', path]]
369 config_devs.append(['device', config_usb])
371 def randomMAC():
372 """Generate a random MAC address.
374 Uses OUI (Organizationally Unique Identifier) AA:00:00, an
375 unassigned one that used to belong to DEC. The OUI list is
376 available at 'standards.ieee.org'.
378 The remaining 3 fields are random, with the first bit of the first
379 random field set 0.
381 @return: MAC address string
382 """
383 mac = [ 0xaa, 0x00, 0x00,
384 random.randint(0x00, 0x7f),
385 random.randint(0x00, 0xff),
386 random.randint(0x00, 0xff) ]
387 return ':'.join(map(lambda x: "%02x" % x, mac))
389 def configure_vifs(opts, config_devs, vals):
390 """Create the config for virtual network interfaces.
391 """
392 vifs = vals.vif
393 vifs_n = max(vals.nics, len(vifs))
395 for idx in range(0, vifs_n):
396 if idx < len(vifs):
397 d = vifs[idx]
398 mac = d.get('mac')
399 if not mac:
400 mac = randomMAC()
401 be_mac = d.get('be_mac')
402 bridge = d.get('bridge')
403 script = d.get('script')
404 backend = d.get('backend')
405 ip = d.get('ip')
406 vifname = d.get('vifname')
407 else:
408 mac = randomMAC()
409 be_mac = None
410 bridge = None
411 script = None
412 backend = None
413 ip = None
414 vifname = None
415 config_vif = ['vif']
416 config_vif.append(['mac', mac])
417 if vifname:
418 config_vif.append(['vifname', vifname])
419 if be_mac:
420 config_vif.append(['be_mac', be_mac])
421 if bridge:
422 config_vif.append(['bridge', bridge])
423 if script:
424 config_vif.append(['script', script])
425 if backend:
426 config_vif.append(['backend', backend])
427 if ip:
428 config_vif.append(['ip', ip])
429 config_devs.append(['device', config_vif])
431 def configure_vfr(opts, config, vals):
432 if not vals.ipaddr: return
433 config_vfr = ['vfr']
434 idx = 0 # No way of saying which IP is for which vif?
435 for ip in vals.ipaddr:
436 config_vfr.append(['vif', ['id', idx], ['ip', ip]])
437 config.append(config_vfr)
439 def configure_vmx(opts, config_devs, vals):
440 """Create the config for VMX devices.
441 """
442 args = [ 'memmap', 'device_model', 'cdrom',
443 'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga',
444 'isa', 'nographic', 'vnc', 'sdl', 'display']
445 for a in args:
446 if (vals.__dict__[a]):
447 config_devs.append([a, vals.__dict__[a]])
449 def run_bootloader(opts, config, vals):
450 if not os.access(vals.bootloader, os.X_OK):
451 opts.err("Bootloader isn't executable")
452 if len(vals.disk) < 1:
453 opts.err("No disks configured and boot loader requested")
454 (uname, dev, mode, backend) = vals.disk[0]
455 file = blkif.blkdev_uname_to_file(uname)
457 blcfg = bootloader(vals.bootloader, file, not vals.console_autoconnect,
458 vals.vcpus, vals.blentry)
460 config.append(['bootloader', vals.bootloader])
461 config.append(blcfg)
463 def make_config(opts, vals):
464 """Create the domain configuration.
465 """
467 config = ['vm',
468 ['name', vals.name ],
469 ['memory', vals.memory ],
470 ['ssidref', vals.ssidref ]]
471 if vals.maxmem:
472 config.append(['maxmem', vals.maxmem])
473 if vals.cpu is not None:
474 config.append(['cpu', vals.cpu])
475 if vals.cpu_weight is not None:
476 config.append(['cpu_weight', vals.cpu_weight])
477 if vals.blkif:
478 config.append(['backend', ['blkif']])
479 if vals.netif:
480 config.append(['backend', ['netif']])
481 if vals.restart:
482 config.append(['restart', vals.restart])
484 if vals.bootloader:
485 run_bootloader(opts, config, vals)
486 else:
487 configure_image(opts, config, vals)
488 config_devs = []
489 configure_disks(opts, config_devs, vals)
490 configure_pci(opts, config_devs, vals)
491 configure_vifs(opts, config_devs, vals)
492 configure_usb(opts, config_devs, vals)
493 configure_vmx(opts, config_devs, vals)
494 config += config_devs
496 return config
498 def preprocess_disk(opts, vals):
499 if not vals.disk: return
500 disk = []
501 for v in vals.disk:
502 d = v.split(',')
503 n = len(d)
504 if n == 3:
505 d.append(None)
506 elif n == 4:
507 pass
508 else:
509 opts.err('Invalid disk specifier: ' + v)
510 disk.append(d)
511 vals.disk = disk
513 def preprocess_pci(opts, vals):
514 if not vals.pci: return
515 pci = []
516 for v in vals.pci:
517 d = v.split(',')
518 if len(d) != 3:
519 opts.err('Invalid pci specifier: ' + v)
520 # Components are in hex: add hex specifier.
521 hexd = map(lambda v: '0x'+v, d)
522 pci.append(hexd)
523 vals.pci = pci
525 def preprocess_vifs(opts, vals):
526 if not vals.vif: return
527 vifs = []
528 for vif in vals.vif:
529 d = {}
530 a = vif.split(',')
531 for b in a:
532 (k, v) = b.strip().split('=', 1)
533 k = k.strip()
534 v = v.strip()
535 if k not in ['mac', 'be_mac', 'bridge', 'script', 'backend', 'ip', 'vifname']:
536 opts.err('Invalid vif specifier: ' + vif)
537 d[k] = v
538 vifs.append(d)
539 vals.vif = vifs
541 def preprocess_ip(opts, vals):
542 if vals.ip or vals.dhcp != 'off':
543 dummy_nfs_server = '1.2.3.4'
544 ip = (vals.ip
545 + ':' + (vals.nfs_server or dummy_nfs_server)
546 + ':' + vals.gateway
547 + ':' + vals.netmask
548 + ':' + vals.hostname
549 + ':' + vals.interface
550 + ':' + vals.dhcp)
551 else:
552 ip = ''
553 vals.cmdline_ip = ip
555 def preprocess_nfs(opts, vals):
556 if not vals.nfs_root: return
557 if not vals.nfs_server:
558 opts.err('Must set nfs root and nfs server')
559 nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
560 vals.extra = nfs + ' ' + vals.extra
563 def get_host_addr():
564 host = socket.gethostname()
565 addr = socket.gethostbyname(host)
566 return addr
568 VNC_BASE_PORT = 5500
570 def choose_vnc_display():
571 """Try to choose a free vnc display.
572 """
573 def netstat_local_ports():
574 """Run netstat to get a list of the local ports in use.
575 """
576 l = os.popen("netstat -nat").readlines()
577 r = []
578 # Skip 2 lines of header.
579 for x in l[2:]:
580 # Local port is field 3.
581 y = x.split()[3]
582 # Field is addr:port, split off the port.
583 y = y.split(':')[1]
584 r.append(int(y))
585 return r
587 ports = netstat_local_ports()
588 for d in range(1, 100):
589 port = VNC_BASE_PORT + d
590 if port in ports: continue
591 return d
592 return None
594 vncpid = None
596 def spawn_vnc(display):
597 vncargs = (["vncviewer" + "-log", "*:stdout:0",
598 "-listen", "%d" % (VNC_BASE_PORT + display) ])
599 global vncpid
600 vncpid = os.spawnvp(os.P_NOWAIT, "vncviewer", vncargs)
602 return VNC_BASE_PORT + display
604 def preprocess_vnc(opts, vals):
605 """If vnc was specified, spawn a vncviewer in listen mode
606 and pass its address to the domain on the kernel command line.
607 """
608 if not vals.vnc or vals.dryrun: return
609 vnc_display = choose_vnc_display()
610 if not vnc_display:
611 opts.warn("No free vnc display")
612 return
613 print 'VNC=', vnc_display
614 vnc_port = spawn_vnc(vnc_display)
615 if vnc_port > 0:
616 vnc_host = get_host_addr()
617 vnc = 'VNC_VIEWER=%s:%d' % (vnc_host, vnc_port)
618 vals.extra = vnc + ' ' + vals.extra
620 def preprocess(opts, vals):
621 if not vals.kernel:
622 opts.err("No kernel specified")
623 preprocess_disk(opts, vals)
624 preprocess_pci(opts, vals)
625 preprocess_vifs(opts, vals)
626 preprocess_ip(opts, vals)
627 preprocess_nfs(opts, vals)
628 preprocess_vnc(opts, vals)
630 def make_domain(opts, config):
631 """Create, build and start a domain.
633 @param opts: options
634 @param config: configuration
635 @return: domain id
636 @rtype: int
637 """
639 try:
640 if opts.vals.load:
641 filename = os.path.abspath(opts.vals.load)
642 dominfo = server.xend_domain_restore(filename, config)
643 else:
644 dominfo = server.xend_domain_create(config)
645 except XendError, ex:
646 import signal
647 if vncpid:
648 os.kill(vncpid, signal.SIGKILL)
649 opts.err(str(ex))
651 dom = sxp.child_value(dominfo, 'name')
653 if not opts.vals.paused:
654 if server.xend_domain_unpause(dom) < 0:
655 server.xend_domain_destroy(dom)
656 opts.err("Failed to unpause domain %s" % dom)
657 opts.info("Started domain %s" % (dom))
658 return int(sxp.child_value(dominfo, 'id'))
660 def get_dom0_alloc():
661 """Return current allocation memory of dom0 (in MB). Return 0 on error"""
662 PROC_XEN_BALLOON = "/proc/xen/balloon"
664 f = open(PROC_XEN_BALLOON, "r")
665 line = f.readline()
666 for x in line.split():
667 for n in x:
668 if not n.isdigit():
669 break
670 else:
671 f.close()
672 return int(x)/1024
673 f.close()
674 return 0
676 def balloon_out(dom0_min_mem, opts):
677 """Balloon out to get memory for domU, if necessarily"""
678 SLACK = 4
680 xc = xen.lowlevel.xc.new()
681 pinfo = xc.physinfo()
682 free_mem = pinfo['free_pages']/256
683 if free_mem < opts.vals.memory + SLACK:
684 need_mem = opts.vals.memory + SLACK - free_mem
685 cur_alloc = get_dom0_alloc()
686 if cur_alloc - need_mem >= dom0_min_mem:
687 server.xend_domain_mem_target_set(0, cur_alloc - need_mem)
688 del xc
690 def main(argv):
691 random.seed()
692 opts = gopts
693 args = opts.parse(argv)
694 if opts.vals.help:
695 opts.usage()
696 if opts.vals.help or opts.vals.help_config:
697 opts.load_defconfig(help=1)
698 if opts.vals.help or opts.vals.help_config:
699 return
700 # Process remaining args as config variables.
701 for arg in args:
702 if '=' in arg:
703 (var, val) = arg.strip().split('=', 1)
704 gopts.setvar(var.strip(), val.strip())
705 opts.vals.display = os.getenv("DISPLAY")
706 if opts.vals.config:
707 config = opts.vals.config
708 else:
709 opts.load_defconfig()
710 preprocess(opts, opts.vals)
711 if not opts.getopt('name') and opts.getopt('defconfig'):
712 opts.setopt('name', os.path.basename(opts.getopt('defconfig')))
713 config = make_config(opts, opts.vals)
715 if opts.vals.dryrun:
716 PrettyPrint.prettyprint(config)
717 else:
718 dom0_min_mem = xroot.get_dom0_min_mem()
719 if dom0_min_mem != 0:
720 balloon_out(dom0_min_mem, opts)
722 dom = make_domain(opts, config)
723 if opts.vals.console_autoconnect:
724 cmd = "/usr/libexec/xen/xenconsole %d" % dom
725 os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
727 if __name__ == '__main__':
728 main(sys.argv)