ia64/xen-unstable

view tools/python/xen/xm/create.py @ 19791:c0d2838fc10f

stubdoms: qemu monitor support

Add support for the qemu monitor in a stubdom, the same way the
emulated serial support was added few days ago. The stubdom exports
the monitor as a pty and minios opens a console frontend; qemu in dom0
provides the correspondent backend for this additional pv console that
happens to be the qemu monitor.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:20:17 2009 +0100 (2009-06-18)
parents d8b2b1712ea6
children b55070edb185
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,monitor=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.
371 Monitor adds a backend for the stubdom monitor.""")
373 gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT," + \
374 "backend=DOM,vifname=NAME,rate=RATE,model=MODEL,accel=ACCEL",
375 fn=append_value, default=[],
376 use="""Add a network interface with the given MAC address and bridge.
377 The vif is configured by calling the given configuration script.
378 If type is not specified, default is netfront.
379 If mac is not specified a random MAC address is used.
380 If not specified then the network backend chooses it's own MAC address.
381 If bridge is not specified the first bridge found is used.
382 If script is not specified the default script is used.
383 If backend is not specified the default backend driver domain is used.
384 If vifname is not specified the backend virtual interface will have name vifD.N
385 where D is the domain id and N is the interface id.
386 If rate is not specified the default rate is used.
387 If model is not specified the default model is used.
388 If accel is not specified an accelerator plugin module is not used.
389 This option may be repeated to add more than one vif.
390 Specifying vifs will increase the number of interfaces as needed.""")
392 gopts.var('vtpm', val="instance=INSTANCE,backend=DOM,type=TYPE",
393 fn=append_value, default=[],
394 use="""Add a TPM interface. On the backend side use the given
395 instance as virtual TPM instance. The given number is merely the
396 preferred instance number. The hotplug script will determine
397 which instance number will actually be assigned to the domain.
398 The associtation between virtual machine and the TPM instance
399 number can be found in /etc/xen/vtpm.db. Use the backend in the
400 given domain.
401 The type parameter can be used to select a specific driver type
402 that the VM can use. To prevent a fully virtualized domain (HVM)
403 from being able to access an emulated device model, you may specify
404 'paravirtualized' here.""")
406 gopts.var('access_control', val="policy=POLICY,label=LABEL",
407 fn=append_value, default=[],
408 use="""Add a security label and the security policy reference that defines it.
409 The local ssid reference is calculated when starting/resuming the domain. At
410 this time, the policy is checked against the active policy as well. This way,
411 migrating through save/restore is covered and local labels are automatically
412 created correctly on the system where a domain is started / resumed.""")
414 gopts.var('nics', val="NUM",
415 fn=set_int, default=-1,
416 use="""DEPRECATED. Use empty vif entries instead.
418 Set the number of network interfaces.
419 Use the vif option to define interface parameters, otherwise
420 defaults are used. Specifying vifs will increase the
421 number of interfaces as needed.""")
423 gopts.var('root', val='DEVICE',
424 fn=set_value, default='',
425 use="""Set the root= parameter on the kernel command line.
426 Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
428 gopts.var('extra', val="ARGS",
429 fn=set_value, default='',
430 use="Set extra arguments to append to the kernel command line.")
432 gopts.var('ip', val='IPADDR',
433 fn=set_value, default='',
434 use="Set the kernel IP interface address.")
436 gopts.var('gateway', val="IPADDR",
437 fn=set_value, default='',
438 use="Set the kernel IP gateway.")
440 gopts.var('netmask', val="MASK",
441 fn=set_value, default = '',
442 use="Set the kernel IP netmask.")
444 gopts.var('hostname', val="NAME",
445 fn=set_value, default='',
446 use="Set the kernel IP hostname.")
448 gopts.var('interface', val="INTF",
449 fn=set_value, default="eth0",
450 use="Set the kernel IP interface name.")
452 gopts.var('dhcp', val="off|dhcp",
453 fn=set_value, default='off',
454 use="Set the kernel dhcp option.")
456 gopts.var('nfs_server', val="IPADDR",
457 fn=set_value, default=None,
458 use="Set the address of the NFS server for NFS root.")
460 gopts.var('nfs_root', val="PATH",
461 fn=set_value, default=None,
462 use="Set the path of the root NFS directory.")
464 gopts.var('device_model', val='FILE',
465 fn=set_value, default=None,
466 use="Path to device model program.")
468 gopts.var('fda', val='FILE',
469 fn=set_value, default='',
470 use="Path to fda")
472 gopts.var('fdb', val='FILE',
473 fn=set_value, default='',
474 use="Path to fdb")
476 gopts.var('serial', val='FILE',
477 fn=set_value, default='',
478 use="Path to serial or pty or vc")
480 gopts.var('monitor', val='no|yes',
481 fn=set_bool, default=0,
482 use="""Should the device model use monitor?""")
484 gopts.var('localtime', val='no|yes',
485 fn=set_bool, default=0,
486 use="Is RTC set to localtime?")
488 gopts.var('keymap', val='FILE',
489 fn=set_value, default='',
490 use="Set keyboard layout used")
492 gopts.var('usb', val='no|yes',
493 fn=set_bool, default=0,
494 use="Emulate USB devices?")
496 gopts.var('usbdevice', val='NAME',
497 fn=set_value, default='',
498 use="Name of USB device to add?")
500 gopts.var('guest_os_type', val='NAME',
501 fn=set_value, default='default',
502 use="Guest OS type running in HVM")
504 gopts.var('stdvga', val='no|yes',
505 fn=set_bool, default=0,
506 use="Use std vga or cirrhus logic graphics")
508 gopts.var('isa', val='no|yes',
509 fn=set_bool, default=0,
510 use="Simulate an ISA only system?")
512 gopts.var('boot', val="a|b|c|d",
513 fn=set_value, default='c',
514 use="Default boot device")
516 gopts.var('nographic', val='no|yes',
517 fn=set_bool, default=0,
518 use="Should device models use graphics?")
520 gopts.var('soundhw', val='audiodev',
521 fn=set_value, default='',
522 use="Should device models enable audio device?")
524 gopts.var('vnc', val='',
525 fn=set_value, default=None,
526 use="""Should the device model use VNC?""")
528 gopts.var('vncdisplay', val='',
529 fn=set_value, default=None,
530 use="""VNC display to use""")
532 gopts.var('vnclisten', val='',
533 fn=set_value, default=None,
534 use="""Address for VNC server to listen on.""")
536 gopts.var('vncunused', val='',
537 fn=set_bool, default=1,
538 use="""Try to find an unused port for the VNC server.
539 Only valid when vnc=1.""")
541 gopts.var('videoram', val='MEMORY',
542 fn=set_int, default=4,
543 use="""Maximum amount of videoram a guest can allocate
544 for frame buffer.""")
546 gopts.var('sdl', val='',
547 fn=set_value, default=None,
548 use="""Should the device model use SDL?""")
550 gopts.var('opengl', val='',
551 fn=set_value, default=None,
552 use="""Enable\Disable OpenGL""")
554 gopts.var('display', val='DISPLAY',
555 fn=set_value, default=None,
556 use="X11 display to use")
558 gopts.var('xauthority', val='XAUTHORITY',
559 fn=set_value, default=None,
560 use="X11 Authority to use")
562 gopts.var('uuid', val='',
563 fn=set_value, default=None,
564 use="""xenstore UUID (universally unique identifier) to use. One
565 will be randomly generated if this option is not set, just like MAC
566 addresses for virtual network interfaces. This must be a unique
567 value across the entire cluster.""")
569 gopts.var('on_xend_start', val='ignore|start',
570 fn=set_value, default='ignore',
571 use='Action to perform when xend starts')
573 gopts.var('on_xend_stop', val='ignore|shutdown|suspend',
574 fn=set_value, default="ignore",
575 use="""Behaviour when Xend stops:
576 - ignore: Domain continues to run;
577 - shutdown: Domain is shutdown;
578 - suspend: Domain is suspended;
579 """)
581 gopts.var('target', val='TARGET',
582 fn=set_int, default=0,
583 use="Set domain target.")
585 gopts.var('hap', val='HAP',
586 fn=set_int, default=1,
587 use="""Hap status (0=hap is disabled;
588 1=hap is enabled.""")
590 gopts.var('s3_integrity', val='TBOOT_MEMORY_PROTECT',
591 fn=set_int, default=1,
592 use="""Should domain memory integrity be verified during S3?
593 (0=protection is disabled; 1=protection is enabled.""")
595 gopts.var('cpuid', val="IN[,SIN]:eax=EAX,ebx=EBX,ecx=ECX,edx=EDX",
596 fn=append_value, default=[],
597 use="""Cpuid description.""")
599 gopts.var('cpuid_check', val="IN[,SIN]:eax=EAX,ebx=EBX,ecx=ECX,edx=EDX",
600 fn=append_value, default=[],
601 use="""Cpuid check description.""")
603 gopts.var('machine_address_size', val='BITS',
604 fn=set_int, default=None,
605 use="""Maximum machine address size""")
607 gopts.var('suppress_spurious_page_faults', val='yes|no',
608 fn=set_bool, default=None,
609 use="""Do not inject spurious page faults into this guest""")
611 gopts.var('pci_msitranslate', val='TRANSLATE',
612 fn=set_int, default=1,
613 use="""Global PCI MSI-INTx translation flag (0=disable;
614 1=enable.""")
616 gopts.var('pci_power_mgmt', val='POWERMGMT',
617 fn=set_int, default=0,
618 use="""Global PCI Power Management flag (0=disable;1=enable).""")
620 gopts.var('xen_platform_pci', val='0|1',
621 fn=set_int, default=1,
622 use="Is xen_platform_pci used?")
624 gopts.var('superpages', val='0|1',
625 fn=set_int, default=0,
626 use="Create domain with superpages")
628 def err(msg):
629 """Print an error to stderr and exit.
630 """
631 print >>sys.stderr, "Error:", msg
632 sys.exit(1)
635 def warn(msg):
636 """Print a warning to stdout.
637 """
638 print >>sys.stderr, "Warning:", msg
641 def strip(pre, s):
642 """Strip prefix 'pre' if present.
643 """
644 if s.startswith(pre):
645 return s[len(pre):]
646 else:
647 return s
649 def configure_image(vals):
650 """Create the image config.
651 """
652 if not vals.builder:
653 return None
654 config_image = [ vals.builder ]
655 if vals.kernel:
656 config_image.append([ 'kernel', os.path.abspath(vals.kernel) ])
657 if vals.ramdisk:
658 config_image.append([ 'ramdisk', os.path.abspath(vals.ramdisk) ])
659 if vals.loader:
660 config_image.append([ 'loader', os.path.abspath(vals.loader) ])
661 if vals.cmdline_ip:
662 cmdline_ip = strip('ip=', vals.cmdline_ip)
663 config_image.append(['ip', cmdline_ip])
664 if vals.root:
665 cmdline_root = strip('root=', vals.root)
666 config_image.append(['root', cmdline_root])
667 if vals.videoram:
668 config_image.append(['videoram', vals.videoram])
669 if vals.extra:
670 config_image.append(['args', vals.extra])
671 if vals.superpages:
672 config_image.append(['superpages', vals.superpages])
674 if vals.builder == 'hvm':
675 configure_hvm(config_image, vals)
677 if vals.vhpt != 0:
678 config_image.append(['vhpt', vals.vhpt])
680 if vals.machine_address_size:
681 config_image.append(['machine_address_size', vals.machine_address_size])
683 if vals.suppress_spurious_page_faults:
684 config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults])
686 return config_image
688 def configure_disks(config_devs, vals):
689 """Create the config for disks (virtual block devices).
690 """
691 for (uname, dev, mode, backend, protocol) in vals.disk:
692 if uname.startswith('tap:'):
693 cls = 'tap'
694 else:
695 cls = 'vbd'
697 config_vbd = [cls,
698 ['uname', uname],
699 ['dev', dev ],
700 ['mode', mode ] ]
701 if backend:
702 config_vbd.append(['backend', backend])
703 if protocol:
704 config_vbd.append(['protocol', protocol])
705 config_devs.append(['device', config_vbd])
707 def configure_pci(config_devs, vals):
708 """Create the config for pci devices.
709 """
710 config_pci = []
711 for pci_tuple in vals.pci:
712 pci_dev = pci_tuple_to_dict(pci_tuple)
713 config_pci.append(dev_dict_to_sxp(pci_dev))
715 if len(config_pci)>0:
716 config_pci.insert(0, 'pci')
717 config_devs.append(['device', config_pci])
719 def configure_vscsis(config_devs, vals):
720 """Create the config for vscsis (virtual scsi devices).
721 """
723 def get_devid(hctl):
724 return int(hctl.split(':')[0])
726 if len(vals.vscsi) == 0:
727 return 0
729 config_scsi = {}
730 pHCTL_list = []
731 vHCTL_list = []
733 scsi_devices = vscsi_util.vscsi_get_scsidevices()
734 for (p_dev, v_dev, backend) in vals.vscsi:
735 (p_hctl, devname) = \
736 vscsi_util.vscsi_get_hctl_and_devname_by(p_dev, scsi_devices)
738 if p_hctl == None:
739 raise ValueError('Cannot find device "%s"' % p_dev)
741 feature_host = 0
742 if v_dev == 'host':
743 if serverType == SERVER_XEN_API:
744 # TODO
745 raise ValueError("SCSI devices assignment by HBA is not implemeted")
746 feature_host = 1
747 scsi_info = []
748 devid = get_devid(p_hctl)
749 for (pHCTL, devname, _, _) in scsi_devices:
750 if get_devid(pHCTL) == devid:
751 scsi_info.append([devid, pHCTL, devname, pHCTL])
752 else:
753 scsi_info = [[get_devid(v_dev), p_hctl, devname, v_dev]]
755 devid_key = scsi_info[0][0]
756 try:
757 config = config_scsi[devid_key]
758 except KeyError:
759 config = {'feature-host': feature_host, 'backend': backend, 'devs': []}
761 devs = config['devs']
762 for (devid, pHCTL, devname, vHCTL) in scsi_info:
763 if pHCTL in pHCTL_list:
764 raise ValueError('The physical device "%s" is already defined' % pHCTL)
765 if vHCTL in vHCTL_list:
766 raise ValueError('The virtual device "%s" is already defined' % vHCTL)
767 pHCTL_list.append(pHCTL)
768 vHCTL_list.append(vHCTL)
769 devs.append(['dev', \
770 ['state', xenbusState['Initialising']], \
771 ['devid', devid], \
772 ['p-dev', pHCTL], \
773 ['p-devname', devname], \
774 ['v-dev', vHCTL] ])
776 if config['feature-host'] != feature_host:
777 raise ValueError('The physical device "%s" cannot define '
778 'because mode is different' % scsi_info[0][1])
779 if config['backend'] != backend:
780 raise ValueError('The physical device "%s" cannot define '
781 'because backend is different' % scsi_info[0][1])
783 config['devs'] = devs
784 config_scsi[devid_key] = config
786 for config in config_scsi.values():
787 device = ['vscsi', ['feature-host', config['feature-host']]]
788 for dev in config['devs']:
789 device.append(dev)
790 if config['backend']:
791 device.append(['backend', config['backend']])
792 config_devs.append(['device', device])
794 def configure_ioports(config_devs, vals):
795 """Create the config for legacy i/o ranges.
796 """
797 for (io_from, io_to) in vals.ioports:
798 config_ioports = ['ioports', ['from', io_from], ['to', io_to]]
799 config_devs.append(['device', config_ioports])
801 def configure_irq(config_devs, vals):
802 """Create the config for irqs.
803 """
804 for irq in vals.irq:
805 config_irq = ['irq', ['irq', irq]]
806 config_devs.append(['device', config_irq])
808 def configure_vfbs(config_devs, vals):
809 for f in vals.vfb:
810 d = comma_sep_kv_to_dict(f)
811 config = ['vfb']
812 #handle the legacy case
813 if d.has_key("type"):
814 d[d['type']] = '1'
815 del d['type']
816 for (k,v) in d.iteritems():
817 if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
818 'videoram', 'xauthority', 'sdl', 'vnc', 'vncpasswd',
819 'opengl', 'keymap', 'serial', 'monitor' ]:
820 err("configuration option %s unknown to vfbs" % k)
821 config.append([k,v])
822 if not d.has_key("keymap"):
823 if vals.keymap:
824 config.append(['keymap',vals.keymap])
825 if not d.has_key("display") and os.environ.has_key("DISPLAY"):
826 config.append(["display", os.environ['DISPLAY']])
827 if not d.has_key("xauthority"):
828 config.append(["xauthority", get_xauthority()])
829 config_devs.append(['device', ['vkbd']])
830 config_devs.append(['device', config])
832 def configure_security(config, vals):
833 """Create the config for ACM security labels.
834 """
835 access_control = vals.access_control
836 num = len(access_control)
837 if num == 1:
838 d = access_control[0]
839 policy = d.get('policy')
840 label = d.get('label')
841 if policy != security.active_policy:
842 err("Security policy (" + policy + ") incompatible with enforced policy ("
843 + security.active_policy + ")." )
844 config_access_control = ['access_control',
845 ['policy', policy],
846 ['label', label] ]
848 security_label = ['security', [ config_access_control ] ]
849 config.append(security_label)
850 elif num > 1:
851 err("VM config error: Multiple access_control definitions!")
853 def configure_mem_prot(config_image, vals):
854 """Create the config for S3 memory integrity verification under tboot.
855 """
856 config_image.append(['s3_integrity', vals.s3_integrity])
858 def configure_vtpm(config_devs, vals):
859 """Create the config for virtual TPM interfaces.
860 """
861 vtpm = vals.vtpm
862 if len(vtpm) > 0:
863 d = vtpm[0]
864 instance = d.get('instance')
865 if instance == "VTPMD":
866 instance = "0"
867 else:
868 if instance != None:
869 try:
870 if int(instance) == 0:
871 err('VM config error: vTPM instance must not be 0.')
872 except ValueError:
873 err('Vm config error: could not parse instance number.')
874 backend = d.get('backend')
875 typ = d.get('type')
876 config_vtpm = ['vtpm']
877 if instance:
878 config_vtpm.append(['pref_instance', instance])
879 if backend:
880 config_vtpm.append(['backend', backend])
881 if typ:
882 config_vtpm.append(['type', type])
883 config_devs.append(['device', config_vtpm])
886 def configure_vifs(config_devs, vals):
887 """Create the config for virtual network interfaces.
888 """
890 vifs = vals.vif
891 vifs_n = len(vifs)
893 if hasattr(vals, 'nics'):
894 if vals.nics > 0:
895 warn("The nics option is deprecated. Please use an empty vif "
896 "entry instead:\n\n vif = [ '' ]\n")
897 for _ in range(vifs_n, vals.nics):
898 vifs.append('')
899 vifs_n = len(vifs)
900 elif vals.nics == 0:
901 warn("The nics option is deprecated. Please remove it.")
903 for c in vifs:
904 d = comma_sep_kv_to_dict(c)
905 config_vif = ['vif']
907 def f(k):
908 if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
909 'vifname', 'rate', 'model', 'accel',
910 'policy', 'label']:
911 err('Invalid vif option: ' + k)
913 config_vif.append([k, d[k]])
915 map(f, d.keys())
916 config_devs.append(['device', config_vif])
919 def configure_hvm(config_image, vals):
920 """Create the config for HVM devices.
921 """
922 args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb', 'timer_mode',
923 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
924 'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
925 'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
926 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
927 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
928 'viridian', 'xen_extended_power_mgmt', 'pci_msitranslate',
929 'vpt_align', 'pci_power_mgmt', 'xen_platform_pci' ]
931 for a in args:
932 if a in vals.__dict__ and vals.__dict__[a] is not None:
933 config_image.append([a, vals.__dict__[a]])
934 if vals.vncpasswd is not None:
935 config_image.append(['vncpasswd', vals.vncpasswd])
938 def make_config(vals):
939 """Create the domain configuration.
940 """
942 config = ['vm']
944 def add_conf(n):
945 if hasattr(vals, n):
946 v = getattr(vals, n)
947 if v:
948 config.append([n, v])
950 map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
951 'restart', 'on_poweroff',
952 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
953 'on_xend_start', 'on_xend_stop', 'target', 'cpuid',
954 'cpuid_check', 'machine_address_size', 'suppress_spurious_page_faults'])
956 if vals.uuid is not None:
957 config.append(['uuid', vals.uuid])
958 if vals.cpu is not None:
959 config.append(['cpu', vals.cpu])
960 if vals.cpus is not None:
961 config.append(['cpus', vals.cpus])
962 if vals.cpu_cap is not None:
963 config.append(['cpu_cap', vals.cpu_cap])
964 if vals.cpu_weight is not None:
965 config.append(['cpu_weight', vals.cpu_weight])
966 if vals.blkif:
967 config.append(['backend', ['blkif']])
968 if vals.netif:
969 config.append(['backend', ['netif']])
970 if vals.tpmif:
971 config.append(['backend', ['tpmif']])
972 if vals.localtime:
973 config.append(['localtime', vals.localtime])
975 config_image = configure_image(vals)
976 if vals.bootloader:
977 if vals.bootloader == "pygrub":
978 vals.bootloader = auxbin.pathTo(vals.bootloader)
980 config.append(['bootloader', vals.bootloader])
981 if vals.bootargs:
982 config.append(['bootloader_args', vals.bootargs])
983 else:
984 if vals.console_autoconnect:
985 config.append(['bootloader_args', ''])
986 else:
987 config.append(['bootloader_args', '-q'])
988 config.append(['image', config_image])
989 configure_mem_prot(config, vals);
991 config_devs = []
992 configure_disks(config_devs, vals)
993 configure_pci(config_devs, vals)
994 configure_vscsis(config_devs, vals)
995 configure_ioports(config_devs, vals)
996 configure_irq(config_devs, vals)
997 configure_vifs(config_devs, vals)
998 configure_vtpm(config_devs, vals)
999 configure_vfbs(config_devs, vals)
1000 configure_security(config, vals)
1001 config += config_devs
1003 return config
1005 def preprocess_disk(vals):
1006 if not vals.disk: return
1007 disk = []
1008 for v in vals.disk:
1009 d = v.split(',')
1010 n = len(d)
1011 if n == 3:
1012 d.append(None)
1013 d.append(None)
1014 elif n == 4:
1015 d.append(None)
1016 elif n == 5:
1017 pass
1018 else:
1019 err('Invalid disk specifier: ' + v)
1020 disk.append(d)
1021 vals.disk = disk
1023 def preprocess_cpuid(vals, attr_name):
1024 if not vals.cpuid: return
1025 cpuid = {}
1026 for cpuid_input in getattr(vals, attr_name):
1027 input_re = "(0x)?[0-9A-Fa-f]+(,(0x)?[0-9A-Fa-f]+)?"
1028 cpuid_match = re.match(r'(?P<input>%s):(?P<regs>.*)' % \
1029 input_re, cpuid_input)
1030 if cpuid_match != None:
1031 res_cpuid = cpuid_match.groupdict()
1032 input = res_cpuid['input']
1033 regs = res_cpuid['regs'].split(',')
1034 cpuid[input]= {} # New input
1035 for reg in regs:
1036 reg_match = re.match(r"(?P<reg>eax|ebx|ecx|edx)=(?P<val>.*)", reg)
1037 if reg_match == None:
1038 err("cpuid's syntax is (eax|ebx|ecx|edx)=value")
1039 res = reg_match.groupdict()
1040 if (res['val'][:2] != '0x' and len(res['val']) != 32):
1041 err("cpuid: We should specify all the bits " \
1042 "of the register %s for input %s\n"
1043 % (res['reg'], input) )
1044 cpuid[input][res['reg']] = res['val'] # new register
1045 setattr(vals, attr_name, cpuid)
1047 def pci_dict_to_tuple(dev):
1048 return (dev['domain'], dev['bus'], dev['slot'], dev['func'],
1049 dev['vslot'], dev.get('opts', []))
1051 def pci_tuple_to_dict((domain, bus, slot, func, vslot, opts)):
1052 pci_dev = { 'domain': domain,
1053 'bus': bus,
1054 'slot': slot,
1055 'func': func,
1056 'vslot': vslot}
1057 if len(opts) > 0:
1058 pci_dev['opts'] = opts
1059 return pci_dev
1061 def preprocess_pci(vals):
1062 if not vals.pci:
1063 return
1064 try:
1065 vals.pci = map(pci_dict_to_tuple,
1066 map(parse_pci_name_extended, vals.pci))
1067 except PciDeviceParseError, ex:
1068 err(str(ex))
1070 def preprocess_vscsi(vals):
1071 if not vals.vscsi: return
1072 scsi = []
1073 for scsi_str in vals.vscsi:
1074 d = [tmp.strip() for tmp in scsi_str.split(',')]
1075 n = len(d)
1076 if n == 2:
1077 tmp = d[1].split(':')
1078 if d[1] != 'host' and len(tmp) != 4:
1079 err('vscsi syntax error "%s"' % d[1])
1080 else:
1081 d.append(None)
1082 elif n == 3:
1083 pass
1084 else:
1085 err('vscsi syntax error "%s"' % scsi_str)
1086 scsi.append(d)
1087 vals.vscsi = scsi
1089 def preprocess_ioports(vals):
1090 if not vals.ioports: return
1091 ioports = []
1092 for v in vals.ioports:
1093 d = v.split('-')
1094 if len(d) < 1 or len(d) > 2:
1095 err('Invalid i/o port range specifier: ' + v)
1096 if len(d) == 1:
1097 d.append(d[0])
1098 # Components are in hex: add hex specifier.
1099 hexd = ['0x' + x for x in d]
1100 ioports.append(hexd)
1101 vals.ioports = ioports
1103 def preprocess_irq(vals):
1104 if not vals.irq: return
1105 irq = []
1106 for v in vals.irq:
1107 d = repr(v)
1108 irq.append(d)
1109 vals.irq = irq
1111 def preprocess_vtpm(vals):
1112 if not vals.vtpm: return
1113 vtpms = []
1114 for vtpm in vals.vtpm:
1115 d = {}
1116 a = vtpm.split(',')
1117 for b in a:
1118 (k, v) = b.strip().split('=', 1)
1119 k = k.strip()
1120 v = v.strip()
1121 if k not in ['backend', 'instance']:
1122 err('Invalid vtpm specifier: ' + vtpm)
1123 d[k] = v
1124 vtpms.append(d)
1125 vals.vtpm = vtpms
1127 def preprocess_access_control(vals):
1128 if not vals.access_control:
1129 return
1130 access_controls = []
1131 num = len(vals.access_control)
1132 if num == 1:
1133 access_control = (vals.access_control)[0]
1134 d = {}
1135 a = access_control.split(',')
1136 if len(a) > 2:
1137 err('Too many elements in access_control specifier: ' + access_control)
1138 for b in a:
1139 (k, v) = b.strip().split('=', 1)
1140 k = k.strip()
1141 v = v.strip()
1142 if k not in ['policy','label']:
1143 err('Invalid access_control specifier: ' + access_control)
1144 d[k] = v
1145 access_controls.append(d)
1146 vals.access_control = access_controls
1147 elif num > 1:
1148 err('Multiple access_control definitions.')
1150 def preprocess_ip(vals):
1151 if vals.ip or vals.dhcp != 'off':
1152 dummy_nfs_server = '127.0.255.255'
1153 ip = (vals.ip
1154 + ':' + (vals.nfs_server or dummy_nfs_server)
1155 + ':' + vals.gateway
1156 + ':' + vals.netmask
1157 + ':' + vals.hostname
1158 + ':' + vals.interface
1159 + ':' + vals.dhcp)
1160 else:
1161 ip = ''
1162 vals.cmdline_ip = ip
1164 def preprocess_nfs(vals):
1165 if not vals.nfs_root: return
1166 if not vals.nfs_server:
1167 err('Must set nfs root and nfs server')
1168 nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
1169 vals.extra = nfs + ' ' + vals.extra
1172 def get_host_addr():
1173 host = socket.gethostname()
1174 addr = socket.gethostbyname(host)
1175 return addr
1177 VNC_BASE_PORT = 5500
1179 def choose_vnc_display():
1180 """Try to choose a free vnc display.
1181 """
1182 def netstat_local_ports():
1183 """Run netstat to get a list of the local ports in use.
1184 """
1185 l = os.popen("netstat -nat").readlines()
1186 r = []
1187 # Skip 2 lines of header.
1188 for x in l[2:]:
1189 # Local port is field 3.
1190 y = x.split()[3]
1191 # Field is addr:port, split off the port.
1192 y = y.split(':')[-1]
1193 r.append(int(y))
1194 return r
1196 ports = netstat_local_ports()
1197 for d in range(1, 100):
1198 port = VNC_BASE_PORT + d
1199 if port in ports: continue
1200 return d
1201 return None
1203 def preprocess(vals):
1204 preprocess_disk(vals)
1205 preprocess_pci(vals)
1206 preprocess_vscsi(vals)
1207 preprocess_ioports(vals)
1208 preprocess_ip(vals)
1209 preprocess_irq(vals)
1210 preprocess_nfs(vals)
1211 preprocess_vtpm(vals)
1212 preprocess_access_control(vals)
1213 preprocess_cpuid(vals, 'cpuid')
1214 preprocess_cpuid(vals, 'cpuid_check')
1217 def comma_sep_kv_to_dict(c):
1218 """Convert comma-separated, equals-separated key-value pairs into a
1219 dictionary.
1220 """
1221 d = {}
1222 c = c.strip()
1223 if len(c) > 0:
1224 a = c.split(',')
1225 for b in a:
1226 if b.find('=') == -1:
1227 err("%s should be a pair, separated by an equals sign." % b)
1228 (k, v) = b.split('=', 1)
1229 k = k.strip()
1230 v = v.strip()
1231 d[k] = v
1232 return d
1235 def make_domain(opts, config):
1236 """Create, build and start a domain.
1238 @param opts: options
1239 @param config: configuration
1240 @return: domain id
1241 @rtype: int
1242 """
1244 try:
1245 dominfo = server.xend.domain.create(config)
1246 except xmlrpclib.Fault, ex:
1247 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1248 err("the domain '%s' does not exist." % ex.faultString)
1249 else:
1250 err("%s" % ex.faultString)
1252 dom = sxp.child_value(dominfo, 'name')
1254 try:
1255 server.xend.domain.waitForDevices(dom)
1256 except xmlrpclib.Fault, ex:
1257 server.xend.domain.destroy(dom)
1258 err("%s" % ex.faultString)
1259 except:
1260 server.xend.domain.destroy(dom)
1261 err("Device creation failed for domain %s" % dom)
1263 if not opts.vals.paused:
1264 try:
1265 server.xend.domain.unpause(dom)
1266 except:
1267 server.xend.domain.destroy(dom)
1268 err("Failed to unpause domain %s" % dom)
1269 domid = int(sxp.child_value(dominfo, 'domid'))
1270 opts.info("Started domain %s (id=%d)" % (dom, domid))
1271 return domid
1274 def get_xauthority():
1275 xauth = os.getenv("XAUTHORITY")
1276 if not xauth:
1277 home = os.getenv("HOME")
1278 if not home:
1279 import posix, pwd
1280 home = pwd.getpwuid(posix.getuid())[5]
1281 xauth = home + "/.Xauthority"
1282 return xauth
1285 def parseCommandLine(argv):
1286 gopts.reset()
1287 args = gopts.parse(argv)
1289 if gopts.vals.help or gopts.vals.help_config:
1290 if gopts.vals.help_config:
1291 print gopts.val_usage()
1292 return (None, None)
1294 if not gopts.vals.display:
1295 gopts.vals.display = os.getenv("DISPLAY")
1297 if not gopts.vals.xauthority:
1298 gopts.vals.xauthority = get_xauthority()
1300 gopts.is_xml = False
1302 # Process remaining args as config variables.
1303 for arg in args:
1304 if '=' in arg:
1305 (var, val) = arg.strip().split('=', 1)
1306 gopts.setvar(var.strip(), val.strip())
1307 if gopts.vals.config:
1308 config = gopts.vals.config
1309 else:
1310 try:
1311 gopts.load_defconfig()
1312 preprocess(gopts.vals)
1313 if not gopts.getopt('name') and gopts.getopt('defconfig'):
1314 gopts.setopt('name', os.path.basename(gopts.getopt('defconfig')))
1315 config = make_config(gopts.vals)
1316 except XMLFileError, ex:
1317 XMLFile = ex.getFile()
1318 gopts.is_xml = True
1319 config = ex.getFile()
1321 return (gopts, config)
1323 def help():
1324 return str(gopts)
1326 def main(argv):
1327 is_xml = False
1329 try:
1330 (opts, config) = parseCommandLine(argv)
1331 except StandardError, ex:
1332 err(str(ex))
1334 if not opts:
1335 return
1337 if not opts.is_xml:
1338 if type(config) == str:
1339 try:
1340 config = sxp.parse(file(config))[0]
1341 except IOError, exn:
1342 raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
1344 if serverType == SERVER_XEN_API:
1345 from xen.xm.xenapi_create import sxp2xml
1346 sxp2xml_inst = sxp2xml()
1347 doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
1349 if opts.vals.dryrun and not opts.is_xml:
1350 SXPPrettyPrint.prettyprint(config)
1352 if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
1353 from xml.dom.ext import PrettyPrint as XMLPrettyPrint
1354 XMLPrettyPrint(doc)
1356 if opts.vals.dryrun or opts.vals.xmldryrun:
1357 return
1359 if opts.vals.console_autoconnect:
1360 do_console(sxp.child_value(config, 'name', -1))
1362 if serverType == SERVER_XEN_API:
1363 from xen.xm.xenapi_create import xenapi_create
1364 xenapi_create_inst = xenapi_create()
1365 if opts.is_xml:
1366 vm_refs = xenapi_create_inst.create(filename = config,
1367 skipdtd = opts.vals.skipdtd)
1368 else:
1369 vm_refs = xenapi_create_inst.create(document = doc,
1370 skipdtd = opts.vals.skipdtd)
1372 map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
1373 elif not opts.is_xml:
1374 dom = make_domain(opts, config)
1376 if opts.vals.vncconsole:
1377 domid = domain_name_to_domid(sxp.child_value(config, 'name', -1))
1378 vncviewer_autopass = getattr(opts.vals,'vncviewer-autopass', False)
1379 console.runVncViewer(domid, vncviewer_autopass, True)
1381 def do_console(domain_name):
1382 cpid = os.fork()
1383 if cpid != 0:
1384 for i in range(10):
1385 # Catch failure of the create process
1386 time.sleep(1)
1387 try:
1388 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1389 except OSError:
1390 # Domain has started cleanly and then exiting,
1391 # the child process used to do this has detached
1392 print("Domain has already finished");
1393 break
1394 if os.WIFEXITED(rv):
1395 if os.WEXITSTATUS(rv) != 0:
1396 sys.exit(os.WEXITSTATUS(rv))
1397 try:
1398 domid = domain_name_to_domid(domain_name)
1399 console.execConsole(domid)
1400 except:
1401 pass
1402 print("Could not start console\n");
1403 sys.exit(0)
1405 if __name__ == '__main__':
1406 main(sys.argv)