ia64/xen-unstable

view tools/python/xen/xm/create.py @ 19780:d8b2b1712ea6

xend: pass-through: Add pci_tuple_to_dict()

Signed-off-by: Simon Horman <horms@verge.net.au>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 17 07:38:03 2009 +0100 (2009-06-17)
parents b52a91a45c65
children c0d2838fc10f
line source
1 #============================================================================UTO
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 # Copyright (C) 2005-2006 XenSource Ltd
18 #============================================================================
20 """Domain creation.
21 """
22 import os
23 import os.path
24 import sys
25 import socket
26 import re
27 import time
28 import xmlrpclib
30 from xen.xend import sxp
31 from xen.xend import PrettyPrint as SXPPrettyPrint
32 import xen.xend.XendClient
33 from xen.xend.XendBootloader import bootloader
34 from xen.xend.XendConstants import *
35 from xen.xend.server.DevConstants import xenbusState
36 from xen.util import blkif
37 from xen.util import vscsi_util
38 import xen.util.xsm.xsm as security
39 from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
40 from xen.util import utils, auxbin
41 from xen.util.pci import dev_dict_to_sxp, \
42 parse_pci_name_extended, PciDeviceParseError
44 from xen.xm.opts import *
46 from main import server
47 from main import domain_name_to_domid
48 import console
51 gopts = Opts(use="""[options] [vars]
53 Create a domain.
55 Domain creation parameters can be set by command-line switches, from
56 a python configuration script or an SXP config file. See documentation
57 for --defconfig, --config. Configuration variables can be set using
58 VAR=VAL on the command line. For example vmid=3 sets vmid to 3.
60 """)
62 gopts.opt('help', short='h',
63 fn=set_true, default=0,
64 use="Print this help.")
66 gopts.opt('help_config',
67 fn=set_true, default=0,
68 use="Print the available configuration variables (vars) for the "
69 "configuration script.")
71 gopts.opt('quiet', short='q',
72 fn=set_true, default=0,
73 use="Quiet.")
75 gopts.opt('path', val='PATH',
76 fn=set_value, default='.:' + auxbin.xen_configdir(),
77 use="Search path for configuration scripts. "
78 "The value of PATH is a colon-separated directory list.")
80 gopts.opt('defconfig', short='f', val='FILE',
81 fn=set_value, default='xmdefconfig',
82 use="Use the given Python configuration script."
83 "The configuration script is loaded after arguments have been "
84 "processed. Each command-line option sets a configuration "
85 "variable named after its long option name, and these "
86 "variables are placed in the environment of the script before "
87 "it is loaded. Variables for options that may be repeated have "
88 "list values. Other variables can be set using VAR=VAL on the "
89 "command line. "
90 "After the script is loaded, option values that were not set "
91 "on the command line are replaced by the values set in the script.")
93 gopts.default('defconfig')
95 gopts.opt('config', short='F', val='FILE',
96 fn=set_value, default=None,
97 use="Domain configuration to use (SXP).\n"
98 "SXP is the underlying configuration format used by Xen.\n"
99 "SXP configurations can be hand-written or generated from Python "
100 "configuration scripts, using the -n (dryrun) option to print "
101 "the configuration.")
103 gopts.opt('dryrun', short='n',
104 fn=set_true, default=0,
105 use="Dry run - prints the resulting configuration in SXP but "
106 "does not create the domain.")
108 gopts.opt('xmldryrun', short='x',
109 fn=set_true, default=0,
110 use="XML dry run - prints the resulting configuration in XML but "
111 "does not create the domain.")
113 gopts.opt('skipdtd', short='s',
114 fn=set_true, default=0,
115 use="Skip DTD checking - skips checks on XML before creating. "
116 " Experimental. Can decrease create time." )
118 gopts.opt('paused', short='p',
119 fn=set_true, default=0,
120 use='Leave the domain paused after it is created.')
122 gopts.opt('console_autoconnect', short='c',
123 fn=set_true, default=0,
124 use="Connect to the console after the domain is created.")
126 gopts.opt('vncviewer',
127 fn=set_true, default=0,
128 use="Connect to the VNC display after the domain is created.")
130 gopts.opt('vncviewer-autopass',
131 fn=set_true, default=0,
132 use="Pass VNC password to viewer via stdin and -autopass.")
134 gopts.var('vncpasswd', val='NAME',
135 fn=set_value, default=None,
136 use="Password for VNC console on HVM domain.")
138 gopts.var('vncviewer', val='no|yes',
139 fn=set_bool, default=None,
140 use="Spawn a vncviewer listening for a vnc server in the domain.\n"
141 "The address of the vncviewer is passed to the domain on the "
142 "kernel command line using 'VNC_SERVER=<host>:<port>'. The port "
143 "used by vnc is 5500 + DISPLAY. A display value with a free port "
144 "is chosen if possible.\nOnly valid when vnc=1.\nDEPRECATED")
146 gopts.var('vncconsole', val='no|yes',
147 fn=set_bool, default=None,
148 use="Spawn a vncviewer process for the domain's graphical console.\n"
149 "Only valid when vnc=1.")
151 gopts.var('name', val='NAME',
152 fn=set_value, default=None,
153 use="Domain name. Must be unique.")
155 gopts.var('bootloader', val='FILE',
156 fn=set_value, default=None,
157 use="Path to bootloader.")
159 gopts.var('bootargs', val='NAME',
160 fn=set_value, default=None,
161 use="Arguments to pass to boot loader")
163 gopts.var('bootentry', val='NAME',
164 fn=set_value, default=None,
165 use="DEPRECATED. Entry to boot via boot loader. Use bootargs.")
167 gopts.var('kernel', val='FILE',
168 fn=set_value, default=None,
169 use="Path to kernel image.")
171 gopts.var('ramdisk', val='FILE',
172 fn=set_value, default='',
173 use="Path to ramdisk.")
175 gopts.var('loader', val='FILE',
176 fn=set_value, default='',
177 use="Path to HVM firmware.")
179 gopts.var('features', val='FEATURES',
180 fn=set_value, default='',
181 use="Features to enable in guest kernel")
183 gopts.var('builder', val='FUNCTION',
184 fn=set_value, default='linux',
185 use="Function to use to build the domain.")
187 gopts.var('memory', val='MEMORY',
188 fn=set_int, default=128,
189 use="Domain memory in MB.")
191 gopts.var('maxmem', val='MEMORY',
192 fn=set_int, default=None,
193 use="Maximum domain memory in MB.")
195 gopts.var('shadow_memory', val='MEMORY',
196 fn=set_int, default=0,
197 use="Domain shadow memory in MB.")
199 gopts.var('cpu', val='CPU',
200 fn=set_int, default=None,
201 use="CPU to run the VCPU0 on.")
203 gopts.var('cpus', val='CPUS',
204 fn=set_value, default=None,
205 use="CPUS to run the domain on.")
207 gopts.var('rtc_timeoffset', val='RTC_TIMEOFFSET',
208 fn=set_int, default=0,
209 use="Set RTC offset.")
211 gopts.var('pae', val='PAE',
212 fn=set_int, default=1,
213 use="Disable or enable PAE of HVM domain.")
215 gopts.var('hpet', val='HPET',
216 fn=set_int, default=0,
217 use="Enable virtual high-precision event timer.")
219 gopts.var('timer_mode', val='TIMER_MODE',
220 fn=set_int, default=1,
221 use="""Timer mode (0=delay virtual time when ticks are missed;
222 1=virtual time is always wallclock time.""")
224 gopts.var('vpt_align', val='VPT_ALIGN',
225 fn=set_int, default=1,
226 use="Enable aligning all periodic vpt to reduce timer interrupts.")
228 gopts.var('viridian', val='VIRIDIAN',
229 fn=set_int, default=0,
230 use="""Expose Viridian interface to x86 HVM guest?
231 (Default is 0).""")
233 gopts.var('acpi', val='ACPI',
234 fn=set_int, default=1,
235 use="Disable or enable ACPI of HVM domain.")
237 gopts.var('apic', val='APIC',
238 fn=set_int, default=1,
239 use="Disable or enable APIC mode.")
241 gopts.var('vcpus', val='VCPUS',
242 fn=set_int, default=1,
243 use="# of Virtual CPUS in domain.")
245 gopts.var('vcpu_avail', val='VCPUS',
246 fn=set_long, default=None,
247 use="Bitmask for virtual CPUs to make available immediately.")
249 gopts.var('vhpt', val='VHPT',
250 fn=set_int, default=0,
251 use="Log2 of domain VHPT size for IA64.")
253 gopts.var('cpu_cap', val='CAP',
254 fn=set_int, default=None,
255 use="""Set the maximum amount of cpu.
256 CAP is a percentage that fixes the maximum amount of cpu.""")
258 gopts.var('cpu_weight', val='WEIGHT',
259 fn=set_int, default=None,
260 use="""Set the cpu time ratio to be allocated to the domain.""")
262 gopts.var('restart', val='onreboot|always|never',
263 fn=set_value, default=None,
264 use="""Deprecated. Use on_poweroff, on_reboot, and on_crash
265 instead.
267 Whether the domain should be restarted on exit.
268 - onreboot: restart on exit with shutdown code reboot
269 - always: always restart on exit, ignore exit code
270 - never: never restart on exit, ignore exit code""")
272 gopts.var('on_poweroff', val='destroy|restart|preserve|rename-restart',
273 fn=set_value, default=None,
274 use="""Behaviour when a domain exits with reason 'poweroff'.
275 - destroy: the domain is cleaned up as normal;
276 - restart: a new domain is started in place of the old one;
277 - preserve: no clean-up is done until the domain is manually
278 destroyed (using xm destroy, for example);
279 - rename-restart: the old domain is not cleaned up, but is
280 renamed and a new domain started in its place.
281 """)
283 gopts.var('on_reboot', val='destroy|restart|preserve|rename-restart',
284 fn=set_value, default=None,
285 use="""Behaviour when a domain exits with reason 'reboot'.
286 - destroy: the domain is cleaned up as normal;
287 - restart: a new domain is started in place of the old one;
288 - preserve: no clean-up is done until the domain is manually
289 destroyed (using xm destroy, for example);
290 - rename-restart: the old domain is not cleaned up, but is
291 renamed and a new domain started in its place.
292 """)
294 gopts.var('on_crash', val='destroy|restart|preserve|rename-restart|coredump-destroy|coredump-restart',
295 fn=set_value, default=None,
296 use="""Behaviour when a domain exits with reason 'crash'.
297 - destroy: the domain is cleaned up as normal;
298 - restart: a new domain is started in place of the old one;
299 - preserve: no clean-up is done until the domain is manually
300 destroyed (using xm destroy, for example);
301 - rename-restart: the old domain is not cleaned up, but is
302 renamed and a new domain started in its place.
303 - coredump-destroy: dump the domain's core, followed by destroy
304 - coredump-restart: dump the domain's core, followed by restart
305 """)
307 gopts.var('blkif', val='no|yes',
308 fn=set_bool, default=0,
309 use="Make the domain a block device backend.")
311 gopts.var('netif', val='no|yes',
312 fn=set_bool, default=0,
313 use="Make the domain a network interface backend.")
315 gopts.var('tpmif', val='no|yes',
316 fn=append_value, default=0,
317 use="Make the domain a TPM interface backend.")
319 gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
320 fn=append_value, default=[],
321 use="""Add a disk device to a domain. The physical device is DEV,
322 which is exported to the domain as VDEV. The disk is read-only if MODE
323 is 'r', read-write if MODE is 'w'. If DOM is specified it defines the
324 backend driver domain to use for the disk.
325 The option may be repeated to add more than one disk.""")
327 gopts.var('pci', val='BUS:DEV.FUNC[@VSLOT][,msitranslate=0|1][,power_mgmt=0|1]',
328 fn=append_value, default=[],
329 use="""Add a PCI device to a domain, using given params (in hex).
330 For example 'pci=c0:02.1'.
331 If VSLOT is supplied the device will be inserted into that
332 virtual slot in the guest, else a free slot is selected.
333 If msitranslate is set, MSI-INTx translation is enabled if possible.
334 Guest that doesn't support MSI will get IO-APIC type IRQs
335 translated from physical MSI, HVM only. Default is 1.
336 The option may be repeated to add more than one pci device.
337 If power_mgmt is set, the guest OS will be able to program the power
338 states D0-D3hot of the device, HVM only. Default=0.""")
340 gopts.var('vscsi', val='PDEV,VDEV[,DOM]',
341 fn=append_value, default=[],
342 use="""Add a SCSI device to a domain. The physical device is PDEV,
343 which is exported to the domain as VDEV(X:X:X:X).""")
345 gopts.var('ioports', val='FROM[-TO]',
346 fn=append_value, default=[],
347 use="""Add a legacy I/O range to a domain, using given params (in hex).
348 For example 'ioports=02f8-02ff'.
349 The option may be repeated to add more than one i/o range.""")
351 gopts.var('irq', val='IRQ',
352 fn=append_value, default=[],
353 use="""Add an IRQ (interrupt line) to a domain.
354 For example 'irq=7'.
355 This option may be repeated to add more than one IRQ.""")
357 gopts.var('vfb', val="vnc=1,sdl=1,vncunused=1,vncdisplay=N,vnclisten=ADDR,display=DISPLAY,xauthority=XAUTHORITY,vncpasswd=PASSWORD,opengl=1,keymap=FILE,serial=FILE",
358 fn=append_value, default=[],
359 use="""Make the domain a framebuffer backend.
360 Both sdl=1 and vnc=1 can be enabled at the same time.
361 For vnc=1, connect an external vncviewer. The server will listen
362 on ADDR (default 127.0.0.1) on port N+5900. N defaults to the
363 domain id. If vncunused=1, the server will try to find an arbitrary
364 unused port above 5900. vncpasswd overrides the XenD configured
365 default password.
366 For sdl=1, a viewer will be started automatically using the
367 given DISPLAY and XAUTHORITY, which default to the current user's
368 ones. OpenGL will be used by default unless opengl is set to 0.
369 keymap overrides the XendD configured default layout file.
370 Serial adds a second serial support to qemu.""")
372 gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT," + \
373 "backend=DOM,vifname=NAME,rate=RATE,model=MODEL,accel=ACCEL",
374 fn=append_value, default=[],
375 use="""Add a network interface with the given MAC address and bridge.
376 The vif is configured by calling the given configuration script.
377 If type is not specified, default is netfront.
378 If mac is not specified a random MAC address is used.
379 If not specified then the network backend chooses it's own MAC address.
380 If bridge is not specified the first bridge found is used.
381 If script is not specified the default script is used.
382 If backend is not specified the default backend driver domain is used.
383 If vifname is not specified the backend virtual interface will have name vifD.N
384 where D is the domain id and N is the interface id.
385 If rate is not specified the default rate is used.
386 If model is not specified the default model is used.
387 If accel is not specified an accelerator plugin module is not used.
388 This option may be repeated to add more than one vif.
389 Specifying vifs will increase the number of interfaces as needed.""")
391 gopts.var('vtpm', val="instance=INSTANCE,backend=DOM,type=TYPE",
392 fn=append_value, default=[],
393 use="""Add a TPM interface. On the backend side use the given
394 instance as virtual TPM instance. The given number is merely the
395 preferred instance number. The hotplug script will determine
396 which instance number will actually be assigned to the domain.
397 The associtation between virtual machine and the TPM instance
398 number can be found in /etc/xen/vtpm.db. Use the backend in the
399 given domain.
400 The type parameter can be used to select a specific driver type
401 that the VM can use. To prevent a fully virtualized domain (HVM)
402 from being able to access an emulated device model, you may specify
403 'paravirtualized' here.""")
405 gopts.var('access_control', val="policy=POLICY,label=LABEL",
406 fn=append_value, default=[],
407 use="""Add a security label and the security policy reference that defines it.
408 The local ssid reference is calculated when starting/resuming the domain. At
409 this time, the policy is checked against the active policy as well. This way,
410 migrating through save/restore is covered and local labels are automatically
411 created correctly on the system where a domain is started / resumed.""")
413 gopts.var('nics', val="NUM",
414 fn=set_int, default=-1,
415 use="""DEPRECATED. Use empty vif entries instead.
417 Set the number of network interfaces.
418 Use the vif option to define interface parameters, otherwise
419 defaults are used. Specifying vifs will increase the
420 number of interfaces as needed.""")
422 gopts.var('root', val='DEVICE',
423 fn=set_value, default='',
424 use="""Set the root= parameter on the kernel command line.
425 Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
427 gopts.var('extra', val="ARGS",
428 fn=set_value, default='',
429 use="Set extra arguments to append to the kernel command line.")
431 gopts.var('ip', val='IPADDR',
432 fn=set_value, default='',
433 use="Set the kernel IP interface address.")
435 gopts.var('gateway', val="IPADDR",
436 fn=set_value, default='',
437 use="Set the kernel IP gateway.")
439 gopts.var('netmask', val="MASK",
440 fn=set_value, default = '',
441 use="Set the kernel IP netmask.")
443 gopts.var('hostname', val="NAME",
444 fn=set_value, default='',
445 use="Set the kernel IP hostname.")
447 gopts.var('interface', val="INTF",
448 fn=set_value, default="eth0",
449 use="Set the kernel IP interface name.")
451 gopts.var('dhcp', val="off|dhcp",
452 fn=set_value, default='off',
453 use="Set the kernel dhcp option.")
455 gopts.var('nfs_server', val="IPADDR",
456 fn=set_value, default=None,
457 use="Set the address of the NFS server for NFS root.")
459 gopts.var('nfs_root', val="PATH",
460 fn=set_value, default=None,
461 use="Set the path of the root NFS directory.")
463 gopts.var('device_model', val='FILE',
464 fn=set_value, default=None,
465 use="Path to device model program.")
467 gopts.var('fda', val='FILE',
468 fn=set_value, default='',
469 use="Path to fda")
471 gopts.var('fdb', val='FILE',
472 fn=set_value, default='',
473 use="Path to fdb")
475 gopts.var('serial', val='FILE',
476 fn=set_value, default='',
477 use="Path to serial or pty or vc")
479 gopts.var('monitor', val='no|yes',
480 fn=set_bool, default=0,
481 use="""Should the device model use monitor?""")
483 gopts.var('localtime', val='no|yes',
484 fn=set_bool, default=0,
485 use="Is RTC set to localtime?")
487 gopts.var('keymap', val='FILE',
488 fn=set_value, default='',
489 use="Set keyboard layout used")
491 gopts.var('usb', val='no|yes',
492 fn=set_bool, default=0,
493 use="Emulate USB devices?")
495 gopts.var('usbdevice', val='NAME',
496 fn=set_value, default='',
497 use="Name of USB device to add?")
499 gopts.var('guest_os_type', val='NAME',
500 fn=set_value, default='default',
501 use="Guest OS type running in HVM")
503 gopts.var('stdvga', val='no|yes',
504 fn=set_bool, default=0,
505 use="Use std vga or cirrhus logic graphics")
507 gopts.var('isa', val='no|yes',
508 fn=set_bool, default=0,
509 use="Simulate an ISA only system?")
511 gopts.var('boot', val="a|b|c|d",
512 fn=set_value, default='c',
513 use="Default boot device")
515 gopts.var('nographic', val='no|yes',
516 fn=set_bool, default=0,
517 use="Should device models use graphics?")
519 gopts.var('soundhw', val='audiodev',
520 fn=set_value, default='',
521 use="Should device models enable audio device?")
523 gopts.var('vnc', val='',
524 fn=set_value, default=None,
525 use="""Should the device model use VNC?""")
527 gopts.var('vncdisplay', val='',
528 fn=set_value, default=None,
529 use="""VNC display to use""")
531 gopts.var('vnclisten', val='',
532 fn=set_value, default=None,
533 use="""Address for VNC server to listen on.""")
535 gopts.var('vncunused', val='',
536 fn=set_bool, default=1,
537 use="""Try to find an unused port for the VNC server.
538 Only valid when vnc=1.""")
540 gopts.var('videoram', val='MEMORY',
541 fn=set_int, default=4,
542 use="""Maximum amount of videoram a guest can allocate
543 for frame buffer.""")
545 gopts.var('sdl', val='',
546 fn=set_value, default=None,
547 use="""Should the device model use SDL?""")
549 gopts.var('opengl', val='',
550 fn=set_value, default=None,
551 use="""Enable\Disable OpenGL""")
553 gopts.var('display', val='DISPLAY',
554 fn=set_value, default=None,
555 use="X11 display to use")
557 gopts.var('xauthority', val='XAUTHORITY',
558 fn=set_value, default=None,
559 use="X11 Authority to use")
561 gopts.var('uuid', val='',
562 fn=set_value, default=None,
563 use="""xenstore UUID (universally unique identifier) to use. One
564 will be randomly generated if this option is not set, just like MAC
565 addresses for virtual network interfaces. This must be a unique
566 value across the entire cluster.""")
568 gopts.var('on_xend_start', val='ignore|start',
569 fn=set_value, default='ignore',
570 use='Action to perform when xend starts')
572 gopts.var('on_xend_stop', val='ignore|shutdown|suspend',
573 fn=set_value, default="ignore",
574 use="""Behaviour when Xend stops:
575 - ignore: Domain continues to run;
576 - shutdown: Domain is shutdown;
577 - suspend: Domain is suspended;
578 """)
580 gopts.var('target', val='TARGET',
581 fn=set_int, default=0,
582 use="Set domain target.")
584 gopts.var('hap', val='HAP',
585 fn=set_int, default=1,
586 use="""Hap status (0=hap is disabled;
587 1=hap is enabled.""")
589 gopts.var('s3_integrity', val='TBOOT_MEMORY_PROTECT',
590 fn=set_int, default=1,
591 use="""Should domain memory integrity be verified during S3?
592 (0=protection is disabled; 1=protection is enabled.""")
594 gopts.var('cpuid', val="IN[,SIN]:eax=EAX,ebx=EBX,ecx=ECX,edx=EDX",
595 fn=append_value, default=[],
596 use="""Cpuid description.""")
598 gopts.var('cpuid_check', val="IN[,SIN]:eax=EAX,ebx=EBX,ecx=ECX,edx=EDX",
599 fn=append_value, default=[],
600 use="""Cpuid check description.""")
602 gopts.var('machine_address_size', val='BITS',
603 fn=set_int, default=None,
604 use="""Maximum machine address size""")
606 gopts.var('suppress_spurious_page_faults', val='yes|no',
607 fn=set_bool, default=None,
608 use="""Do not inject spurious page faults into this guest""")
610 gopts.var('pci_msitranslate', val='TRANSLATE',
611 fn=set_int, default=1,
612 use="""Global PCI MSI-INTx translation flag (0=disable;
613 1=enable.""")
615 gopts.var('pci_power_mgmt', val='POWERMGMT',
616 fn=set_int, default=0,
617 use="""Global PCI Power Management flag (0=disable;1=enable).""")
619 gopts.var('xen_platform_pci', val='0|1',
620 fn=set_int, default=1,
621 use="Is xen_platform_pci used?")
623 gopts.var('superpages', val='0|1',
624 fn=set_int, default=0,
625 use="Create domain with superpages")
627 def err(msg):
628 """Print an error to stderr and exit.
629 """
630 print >>sys.stderr, "Error:", msg
631 sys.exit(1)
634 def warn(msg):
635 """Print a warning to stdout.
636 """
637 print >>sys.stderr, "Warning:", msg
640 def strip(pre, s):
641 """Strip prefix 'pre' if present.
642 """
643 if s.startswith(pre):
644 return s[len(pre):]
645 else:
646 return s
648 def configure_image(vals):
649 """Create the image config.
650 """
651 if not vals.builder:
652 return None
653 config_image = [ vals.builder ]
654 if vals.kernel:
655 config_image.append([ 'kernel', os.path.abspath(vals.kernel) ])
656 if vals.ramdisk:
657 config_image.append([ 'ramdisk', os.path.abspath(vals.ramdisk) ])
658 if vals.loader:
659 config_image.append([ 'loader', os.path.abspath(vals.loader) ])
660 if vals.cmdline_ip:
661 cmdline_ip = strip('ip=', vals.cmdline_ip)
662 config_image.append(['ip', cmdline_ip])
663 if vals.root:
664 cmdline_root = strip('root=', vals.root)
665 config_image.append(['root', cmdline_root])
666 if vals.videoram:
667 config_image.append(['videoram', vals.videoram])
668 if vals.extra:
669 config_image.append(['args', vals.extra])
670 if vals.superpages:
671 config_image.append(['superpages', vals.superpages])
673 if vals.builder == 'hvm':
674 configure_hvm(config_image, vals)
676 if vals.vhpt != 0:
677 config_image.append(['vhpt', vals.vhpt])
679 if vals.machine_address_size:
680 config_image.append(['machine_address_size', vals.machine_address_size])
682 if vals.suppress_spurious_page_faults:
683 config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults])
685 return config_image
687 def configure_disks(config_devs, vals):
688 """Create the config for disks (virtual block devices).
689 """
690 for (uname, dev, mode, backend, protocol) in vals.disk:
691 if uname.startswith('tap:'):
692 cls = 'tap'
693 else:
694 cls = 'vbd'
696 config_vbd = [cls,
697 ['uname', uname],
698 ['dev', dev ],
699 ['mode', mode ] ]
700 if backend:
701 config_vbd.append(['backend', backend])
702 if protocol:
703 config_vbd.append(['protocol', protocol])
704 config_devs.append(['device', config_vbd])
706 def configure_pci(config_devs, vals):
707 """Create the config for pci devices.
708 """
709 config_pci = []
710 for pci_tuple in vals.pci:
711 pci_dev = pci_tuple_to_dict(pci_tuple)
712 config_pci.append(dev_dict_to_sxp(pci_dev))
714 if len(config_pci)>0:
715 config_pci.insert(0, 'pci')
716 config_devs.append(['device', config_pci])
718 def configure_vscsis(config_devs, vals):
719 """Create the config for vscsis (virtual scsi devices).
720 """
722 def get_devid(hctl):
723 return int(hctl.split(':')[0])
725 if len(vals.vscsi) == 0:
726 return 0
728 config_scsi = {}
729 pHCTL_list = []
730 vHCTL_list = []
732 scsi_devices = vscsi_util.vscsi_get_scsidevices()
733 for (p_dev, v_dev, backend) in vals.vscsi:
734 (p_hctl, devname) = \
735 vscsi_util.vscsi_get_hctl_and_devname_by(p_dev, scsi_devices)
737 if p_hctl == None:
738 raise ValueError('Cannot find device "%s"' % p_dev)
740 feature_host = 0
741 if v_dev == 'host':
742 if serverType == SERVER_XEN_API:
743 # TODO
744 raise ValueError("SCSI devices assignment by HBA is not implemeted")
745 feature_host = 1
746 scsi_info = []
747 devid = get_devid(p_hctl)
748 for (pHCTL, devname, _, _) in scsi_devices:
749 if get_devid(pHCTL) == devid:
750 scsi_info.append([devid, pHCTL, devname, pHCTL])
751 else:
752 scsi_info = [[get_devid(v_dev), p_hctl, devname, v_dev]]
754 devid_key = scsi_info[0][0]
755 try:
756 config = config_scsi[devid_key]
757 except KeyError:
758 config = {'feature-host': feature_host, 'backend': backend, 'devs': []}
760 devs = config['devs']
761 for (devid, pHCTL, devname, vHCTL) in scsi_info:
762 if pHCTL in pHCTL_list:
763 raise ValueError('The physical device "%s" is already defined' % pHCTL)
764 if vHCTL in vHCTL_list:
765 raise ValueError('The virtual device "%s" is already defined' % vHCTL)
766 pHCTL_list.append(pHCTL)
767 vHCTL_list.append(vHCTL)
768 devs.append(['dev', \
769 ['state', xenbusState['Initialising']], \
770 ['devid', devid], \
771 ['p-dev', pHCTL], \
772 ['p-devname', devname], \
773 ['v-dev', vHCTL] ])
775 if config['feature-host'] != feature_host:
776 raise ValueError('The physical device "%s" cannot define '
777 'because mode is different' % scsi_info[0][1])
778 if config['backend'] != backend:
779 raise ValueError('The physical device "%s" cannot define '
780 'because backend is different' % scsi_info[0][1])
782 config['devs'] = devs
783 config_scsi[devid_key] = config
785 for config in config_scsi.values():
786 device = ['vscsi', ['feature-host', config['feature-host']]]
787 for dev in config['devs']:
788 device.append(dev)
789 if config['backend']:
790 device.append(['backend', config['backend']])
791 config_devs.append(['device', device])
793 def configure_ioports(config_devs, vals):
794 """Create the config for legacy i/o ranges.
795 """
796 for (io_from, io_to) in vals.ioports:
797 config_ioports = ['ioports', ['from', io_from], ['to', io_to]]
798 config_devs.append(['device', config_ioports])
800 def configure_irq(config_devs, vals):
801 """Create the config for irqs.
802 """
803 for irq in vals.irq:
804 config_irq = ['irq', ['irq', irq]]
805 config_devs.append(['device', config_irq])
807 def configure_vfbs(config_devs, vals):
808 for f in vals.vfb:
809 d = comma_sep_kv_to_dict(f)
810 config = ['vfb']
811 #handle the legacy case
812 if d.has_key("type"):
813 d[d['type']] = '1'
814 del d['type']
815 for (k,v) in d.iteritems():
816 if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
817 'videoram', 'xauthority', 'sdl', 'vnc', 'vncpasswd',
818 'opengl', 'keymap', 'serial' ]:
819 err("configuration option %s unknown to vfbs" % k)
820 config.append([k,v])
821 if not d.has_key("keymap"):
822 if vals.keymap:
823 config.append(['keymap',vals.keymap])
824 if not d.has_key("display") and os.environ.has_key("DISPLAY"):
825 config.append(["display", os.environ['DISPLAY']])
826 if not d.has_key("xauthority"):
827 config.append(["xauthority", get_xauthority()])
828 config_devs.append(['device', ['vkbd']])
829 config_devs.append(['device', config])
831 def configure_security(config, vals):
832 """Create the config for ACM security labels.
833 """
834 access_control = vals.access_control
835 num = len(access_control)
836 if num == 1:
837 d = access_control[0]
838 policy = d.get('policy')
839 label = d.get('label')
840 if policy != security.active_policy:
841 err("Security policy (" + policy + ") incompatible with enforced policy ("
842 + security.active_policy + ")." )
843 config_access_control = ['access_control',
844 ['policy', policy],
845 ['label', label] ]
847 security_label = ['security', [ config_access_control ] ]
848 config.append(security_label)
849 elif num > 1:
850 err("VM config error: Multiple access_control definitions!")
852 def configure_mem_prot(config_image, vals):
853 """Create the config for S3 memory integrity verification under tboot.
854 """
855 config_image.append(['s3_integrity', vals.s3_integrity])
857 def configure_vtpm(config_devs, vals):
858 """Create the config for virtual TPM interfaces.
859 """
860 vtpm = vals.vtpm
861 if len(vtpm) > 0:
862 d = vtpm[0]
863 instance = d.get('instance')
864 if instance == "VTPMD":
865 instance = "0"
866 else:
867 if instance != None:
868 try:
869 if int(instance) == 0:
870 err('VM config error: vTPM instance must not be 0.')
871 except ValueError:
872 err('Vm config error: could not parse instance number.')
873 backend = d.get('backend')
874 typ = d.get('type')
875 config_vtpm = ['vtpm']
876 if instance:
877 config_vtpm.append(['pref_instance', instance])
878 if backend:
879 config_vtpm.append(['backend', backend])
880 if typ:
881 config_vtpm.append(['type', type])
882 config_devs.append(['device', config_vtpm])
885 def configure_vifs(config_devs, vals):
886 """Create the config for virtual network interfaces.
887 """
889 vifs = vals.vif
890 vifs_n = len(vifs)
892 if hasattr(vals, 'nics'):
893 if vals.nics > 0:
894 warn("The nics option is deprecated. Please use an empty vif "
895 "entry instead:\n\n vif = [ '' ]\n")
896 for _ in range(vifs_n, vals.nics):
897 vifs.append('')
898 vifs_n = len(vifs)
899 elif vals.nics == 0:
900 warn("The nics option is deprecated. Please remove it.")
902 for c in vifs:
903 d = comma_sep_kv_to_dict(c)
904 config_vif = ['vif']
906 def f(k):
907 if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
908 'vifname', 'rate', 'model', 'accel',
909 'policy', 'label']:
910 err('Invalid vif option: ' + k)
912 config_vif.append([k, d[k]])
914 map(f, d.keys())
915 config_devs.append(['device', config_vif])
918 def configure_hvm(config_image, vals):
919 """Create the config for HVM devices.
920 """
921 args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb', 'timer_mode',
922 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
923 'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
924 'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
925 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
926 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
927 'viridian', 'xen_extended_power_mgmt', 'pci_msitranslate',
928 'vpt_align', 'pci_power_mgmt', 'xen_platform_pci' ]
930 for a in args:
931 if a in vals.__dict__ and vals.__dict__[a] is not None:
932 config_image.append([a, vals.__dict__[a]])
933 if vals.vncpasswd is not None:
934 config_image.append(['vncpasswd', vals.vncpasswd])
937 def make_config(vals):
938 """Create the domain configuration.
939 """
941 config = ['vm']
943 def add_conf(n):
944 if hasattr(vals, n):
945 v = getattr(vals, n)
946 if v:
947 config.append([n, v])
949 map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
950 'restart', 'on_poweroff',
951 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
952 'on_xend_start', 'on_xend_stop', 'target', 'cpuid',
953 'cpuid_check', 'machine_address_size', 'suppress_spurious_page_faults'])
955 if vals.uuid is not None:
956 config.append(['uuid', vals.uuid])
957 if vals.cpu is not None:
958 config.append(['cpu', vals.cpu])
959 if vals.cpus is not None:
960 config.append(['cpus', vals.cpus])
961 if vals.cpu_cap is not None:
962 config.append(['cpu_cap', vals.cpu_cap])
963 if vals.cpu_weight is not None:
964 config.append(['cpu_weight', vals.cpu_weight])
965 if vals.blkif:
966 config.append(['backend', ['blkif']])
967 if vals.netif:
968 config.append(['backend', ['netif']])
969 if vals.tpmif:
970 config.append(['backend', ['tpmif']])
971 if vals.localtime:
972 config.append(['localtime', vals.localtime])
974 config_image = configure_image(vals)
975 if vals.bootloader:
976 if vals.bootloader == "pygrub":
977 vals.bootloader = auxbin.pathTo(vals.bootloader)
979 config.append(['bootloader', vals.bootloader])
980 if vals.bootargs:
981 config.append(['bootloader_args', vals.bootargs])
982 else:
983 if vals.console_autoconnect:
984 config.append(['bootloader_args', ''])
985 else:
986 config.append(['bootloader_args', '-q'])
987 config.append(['image', config_image])
988 configure_mem_prot(config, vals);
990 config_devs = []
991 configure_disks(config_devs, vals)
992 configure_pci(config_devs, vals)
993 configure_vscsis(config_devs, vals)
994 configure_ioports(config_devs, vals)
995 configure_irq(config_devs, vals)
996 configure_vifs(config_devs, vals)
997 configure_vtpm(config_devs, vals)
998 configure_vfbs(config_devs, vals)
999 configure_security(config, vals)
1000 config += config_devs
1002 return config
1004 def preprocess_disk(vals):
1005 if not vals.disk: return
1006 disk = []
1007 for v in vals.disk:
1008 d = v.split(',')
1009 n = len(d)
1010 if n == 3:
1011 d.append(None)
1012 d.append(None)
1013 elif n == 4:
1014 d.append(None)
1015 elif n == 5:
1016 pass
1017 else:
1018 err('Invalid disk specifier: ' + v)
1019 disk.append(d)
1020 vals.disk = disk
1022 def preprocess_cpuid(vals, attr_name):
1023 if not vals.cpuid: return
1024 cpuid = {}
1025 for cpuid_input in getattr(vals, attr_name):
1026 input_re = "(0x)?[0-9A-Fa-f]+(,(0x)?[0-9A-Fa-f]+)?"
1027 cpuid_match = re.match(r'(?P<input>%s):(?P<regs>.*)' % \
1028 input_re, cpuid_input)
1029 if cpuid_match != None:
1030 res_cpuid = cpuid_match.groupdict()
1031 input = res_cpuid['input']
1032 regs = res_cpuid['regs'].split(',')
1033 cpuid[input]= {} # New input
1034 for reg in regs:
1035 reg_match = re.match(r"(?P<reg>eax|ebx|ecx|edx)=(?P<val>.*)", reg)
1036 if reg_match == None:
1037 err("cpuid's syntax is (eax|ebx|ecx|edx)=value")
1038 res = reg_match.groupdict()
1039 if (res['val'][:2] != '0x' and len(res['val']) != 32):
1040 err("cpuid: We should specify all the bits " \
1041 "of the register %s for input %s\n"
1042 % (res['reg'], input) )
1043 cpuid[input][res['reg']] = res['val'] # new register
1044 setattr(vals, attr_name, cpuid)
1046 def pci_dict_to_tuple(dev):
1047 return (dev['domain'], dev['bus'], dev['slot'], dev['func'],
1048 dev['vslot'], dev.get('opts', []))
1050 def pci_tuple_to_dict((domain, bus, slot, func, vslot, opts)):
1051 pci_dev = { 'domain': domain,
1052 'bus': bus,
1053 'slot': slot,
1054 'func': func,
1055 'vslot': vslot}
1056 if len(opts) > 0:
1057 pci_dev['opts'] = opts
1058 return pci_dev
1060 def preprocess_pci(vals):
1061 if not vals.pci:
1062 return
1063 try:
1064 vals.pci = map(pci_dict_to_tuple,
1065 map(parse_pci_name_extended, vals.pci))
1066 except PciDeviceParseError, ex:
1067 err(str(ex))
1069 def preprocess_vscsi(vals):
1070 if not vals.vscsi: return
1071 scsi = []
1072 for scsi_str in vals.vscsi:
1073 d = [tmp.strip() for tmp in scsi_str.split(',')]
1074 n = len(d)
1075 if n == 2:
1076 tmp = d[1].split(':')
1077 if d[1] != 'host' and len(tmp) != 4:
1078 err('vscsi syntax error "%s"' % d[1])
1079 else:
1080 d.append(None)
1081 elif n == 3:
1082 pass
1083 else:
1084 err('vscsi syntax error "%s"' % scsi_str)
1085 scsi.append(d)
1086 vals.vscsi = scsi
1088 def preprocess_ioports(vals):
1089 if not vals.ioports: return
1090 ioports = []
1091 for v in vals.ioports:
1092 d = v.split('-')
1093 if len(d) < 1 or len(d) > 2:
1094 err('Invalid i/o port range specifier: ' + v)
1095 if len(d) == 1:
1096 d.append(d[0])
1097 # Components are in hex: add hex specifier.
1098 hexd = ['0x' + x for x in d]
1099 ioports.append(hexd)
1100 vals.ioports = ioports
1102 def preprocess_irq(vals):
1103 if not vals.irq: return
1104 irq = []
1105 for v in vals.irq:
1106 d = repr(v)
1107 irq.append(d)
1108 vals.irq = irq
1110 def preprocess_vtpm(vals):
1111 if not vals.vtpm: return
1112 vtpms = []
1113 for vtpm in vals.vtpm:
1114 d = {}
1115 a = vtpm.split(',')
1116 for b in a:
1117 (k, v) = b.strip().split('=', 1)
1118 k = k.strip()
1119 v = v.strip()
1120 if k not in ['backend', 'instance']:
1121 err('Invalid vtpm specifier: ' + vtpm)
1122 d[k] = v
1123 vtpms.append(d)
1124 vals.vtpm = vtpms
1126 def preprocess_access_control(vals):
1127 if not vals.access_control:
1128 return
1129 access_controls = []
1130 num = len(vals.access_control)
1131 if num == 1:
1132 access_control = (vals.access_control)[0]
1133 d = {}
1134 a = access_control.split(',')
1135 if len(a) > 2:
1136 err('Too many elements in access_control specifier: ' + access_control)
1137 for b in a:
1138 (k, v) = b.strip().split('=', 1)
1139 k = k.strip()
1140 v = v.strip()
1141 if k not in ['policy','label']:
1142 err('Invalid access_control specifier: ' + access_control)
1143 d[k] = v
1144 access_controls.append(d)
1145 vals.access_control = access_controls
1146 elif num > 1:
1147 err('Multiple access_control definitions.')
1149 def preprocess_ip(vals):
1150 if vals.ip or vals.dhcp != 'off':
1151 dummy_nfs_server = '127.0.255.255'
1152 ip = (vals.ip
1153 + ':' + (vals.nfs_server or dummy_nfs_server)
1154 + ':' + vals.gateway
1155 + ':' + vals.netmask
1156 + ':' + vals.hostname
1157 + ':' + vals.interface
1158 + ':' + vals.dhcp)
1159 else:
1160 ip = ''
1161 vals.cmdline_ip = ip
1163 def preprocess_nfs(vals):
1164 if not vals.nfs_root: return
1165 if not vals.nfs_server:
1166 err('Must set nfs root and nfs server')
1167 nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
1168 vals.extra = nfs + ' ' + vals.extra
1171 def get_host_addr():
1172 host = socket.gethostname()
1173 addr = socket.gethostbyname(host)
1174 return addr
1176 VNC_BASE_PORT = 5500
1178 def choose_vnc_display():
1179 """Try to choose a free vnc display.
1180 """
1181 def netstat_local_ports():
1182 """Run netstat to get a list of the local ports in use.
1183 """
1184 l = os.popen("netstat -nat").readlines()
1185 r = []
1186 # Skip 2 lines of header.
1187 for x in l[2:]:
1188 # Local port is field 3.
1189 y = x.split()[3]
1190 # Field is addr:port, split off the port.
1191 y = y.split(':')[-1]
1192 r.append(int(y))
1193 return r
1195 ports = netstat_local_ports()
1196 for d in range(1, 100):
1197 port = VNC_BASE_PORT + d
1198 if port in ports: continue
1199 return d
1200 return None
1202 def preprocess(vals):
1203 preprocess_disk(vals)
1204 preprocess_pci(vals)
1205 preprocess_vscsi(vals)
1206 preprocess_ioports(vals)
1207 preprocess_ip(vals)
1208 preprocess_irq(vals)
1209 preprocess_nfs(vals)
1210 preprocess_vtpm(vals)
1211 preprocess_access_control(vals)
1212 preprocess_cpuid(vals, 'cpuid')
1213 preprocess_cpuid(vals, 'cpuid_check')
1216 def comma_sep_kv_to_dict(c):
1217 """Convert comma-separated, equals-separated key-value pairs into a
1218 dictionary.
1219 """
1220 d = {}
1221 c = c.strip()
1222 if len(c) > 0:
1223 a = c.split(',')
1224 for b in a:
1225 if b.find('=') == -1:
1226 err("%s should be a pair, separated by an equals sign." % b)
1227 (k, v) = b.split('=', 1)
1228 k = k.strip()
1229 v = v.strip()
1230 d[k] = v
1231 return d
1234 def make_domain(opts, config):
1235 """Create, build and start a domain.
1237 @param opts: options
1238 @param config: configuration
1239 @return: domain id
1240 @rtype: int
1241 """
1243 try:
1244 dominfo = server.xend.domain.create(config)
1245 except xmlrpclib.Fault, ex:
1246 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1247 err("the domain '%s' does not exist." % ex.faultString)
1248 else:
1249 err("%s" % ex.faultString)
1251 dom = sxp.child_value(dominfo, 'name')
1253 try:
1254 server.xend.domain.waitForDevices(dom)
1255 except xmlrpclib.Fault, ex:
1256 server.xend.domain.destroy(dom)
1257 err("%s" % ex.faultString)
1258 except:
1259 server.xend.domain.destroy(dom)
1260 err("Device creation failed for domain %s" % dom)
1262 if not opts.vals.paused:
1263 try:
1264 server.xend.domain.unpause(dom)
1265 except:
1266 server.xend.domain.destroy(dom)
1267 err("Failed to unpause domain %s" % dom)
1268 domid = int(sxp.child_value(dominfo, 'domid'))
1269 opts.info("Started domain %s (id=%d)" % (dom, domid))
1270 return domid
1273 def get_xauthority():
1274 xauth = os.getenv("XAUTHORITY")
1275 if not xauth:
1276 home = os.getenv("HOME")
1277 if not home:
1278 import posix, pwd
1279 home = pwd.getpwuid(posix.getuid())[5]
1280 xauth = home + "/.Xauthority"
1281 return xauth
1284 def parseCommandLine(argv):
1285 gopts.reset()
1286 args = gopts.parse(argv)
1288 if gopts.vals.help or gopts.vals.help_config:
1289 if gopts.vals.help_config:
1290 print gopts.val_usage()
1291 return (None, None)
1293 if not gopts.vals.display:
1294 gopts.vals.display = os.getenv("DISPLAY")
1296 if not gopts.vals.xauthority:
1297 gopts.vals.xauthority = get_xauthority()
1299 gopts.is_xml = False
1301 # Process remaining args as config variables.
1302 for arg in args:
1303 if '=' in arg:
1304 (var, val) = arg.strip().split('=', 1)
1305 gopts.setvar(var.strip(), val.strip())
1306 if gopts.vals.config:
1307 config = gopts.vals.config
1308 else:
1309 try:
1310 gopts.load_defconfig()
1311 preprocess(gopts.vals)
1312 if not gopts.getopt('name') and gopts.getopt('defconfig'):
1313 gopts.setopt('name', os.path.basename(gopts.getopt('defconfig')))
1314 config = make_config(gopts.vals)
1315 except XMLFileError, ex:
1316 XMLFile = ex.getFile()
1317 gopts.is_xml = True
1318 config = ex.getFile()
1320 return (gopts, config)
1322 def help():
1323 return str(gopts)
1325 def main(argv):
1326 is_xml = False
1328 try:
1329 (opts, config) = parseCommandLine(argv)
1330 except StandardError, ex:
1331 err(str(ex))
1333 if not opts:
1334 return
1336 if not opts.is_xml:
1337 if type(config) == str:
1338 try:
1339 config = sxp.parse(file(config))[0]
1340 except IOError, exn:
1341 raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
1343 if serverType == SERVER_XEN_API:
1344 from xen.xm.xenapi_create import sxp2xml
1345 sxp2xml_inst = sxp2xml()
1346 doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
1348 if opts.vals.dryrun and not opts.is_xml:
1349 SXPPrettyPrint.prettyprint(config)
1351 if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
1352 from xml.dom.ext import PrettyPrint as XMLPrettyPrint
1353 XMLPrettyPrint(doc)
1355 if opts.vals.dryrun or opts.vals.xmldryrun:
1356 return
1358 if opts.vals.console_autoconnect:
1359 do_console(sxp.child_value(config, 'name', -1))
1361 if serverType == SERVER_XEN_API:
1362 from xen.xm.xenapi_create import xenapi_create
1363 xenapi_create_inst = xenapi_create()
1364 if opts.is_xml:
1365 vm_refs = xenapi_create_inst.create(filename = config,
1366 skipdtd = opts.vals.skipdtd)
1367 else:
1368 vm_refs = xenapi_create_inst.create(document = doc,
1369 skipdtd = opts.vals.skipdtd)
1371 map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
1372 elif not opts.is_xml:
1373 dom = make_domain(opts, config)
1375 if opts.vals.vncconsole:
1376 domid = domain_name_to_domid(sxp.child_value(config, 'name', -1))
1377 vncviewer_autopass = getattr(opts.vals,'vncviewer-autopass', False)
1378 console.runVncViewer(domid, vncviewer_autopass, True)
1380 def do_console(domain_name):
1381 cpid = os.fork()
1382 if cpid != 0:
1383 for i in range(10):
1384 # Catch failure of the create process
1385 time.sleep(1)
1386 try:
1387 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1388 except OSError:
1389 # Domain has started cleanly and then exiting,
1390 # the child process used to do this has detached
1391 print("Domain has already finished");
1392 break
1393 if os.WIFEXITED(rv):
1394 if os.WEXITSTATUS(rv) != 0:
1395 sys.exit(os.WEXITSTATUS(rv))
1396 try:
1397 domid = domain_name_to_domid(domain_name)
1398 console.execConsole(domid)
1399 except:
1400 pass
1401 print("Could not start console\n");
1402 sys.exit(0)
1404 if __name__ == '__main__':
1405 main(sys.argv)