ia64/xen-unstable

view tools/python/xen/xm/create.py @ 19758:0573bbe19499

xend: pass-through: sxp.merge() cant deal with values being a list

sxp.merge() can't deal with values being a list so instead
of storing pci options as:

[ 'opts', [ 'key1' 'value1'], [ 'key2', 'value2'], ...]

store them as:

[ 'opts', [ 'key1' 'value1'], ['opts', [ 'key2', 'value2']], ...

Signed-off-by: Simon Horman <horms@verge.net.au>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jun 16 11:37:41 2009 +0100 (2009-06-16)
parents eeb0fce9aeaf
children b52a91a45c65
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 split_pci_opts, check_pci_opts, \
42 pci_opts_list_to_sxp
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 (domain, bus, slot, func, vslot, opts) in vals.pci:
711 config_pci_bdf = ['dev', ['domain', domain], ['bus', bus], \
712 ['slot', slot], ['func', func],
713 ['vslot', vslot]]
715 opts_list = split_pci_opts(opts)
716 try:
717 check_pci_opts(opts_list)
718 except PciDeviceParseError, ex:
719 err(str(ex))
721 config_opts = pci_opts_list_to_sxp(split_pci_opts(opts))
722 config_pci.append(sxp.merge(config_pci_bdf, config_opts))
724 if len(config_pci)>0:
725 config_pci.insert(0, 'pci')
726 config_devs.append(['device', config_pci])
728 def configure_vscsis(config_devs, vals):
729 """Create the config for vscsis (virtual scsi devices).
730 """
732 def get_devid(hctl):
733 return int(hctl.split(':')[0])
735 if len(vals.vscsi) == 0:
736 return 0
738 config_scsi = {}
739 pHCTL_list = []
740 vHCTL_list = []
742 scsi_devices = vscsi_util.vscsi_get_scsidevices()
743 for (p_dev, v_dev, backend) in vals.vscsi:
744 (p_hctl, devname) = \
745 vscsi_util.vscsi_get_hctl_and_devname_by(p_dev, scsi_devices)
747 if p_hctl == None:
748 raise ValueError('Cannot find device "%s"' % p_dev)
750 feature_host = 0
751 if v_dev == 'host':
752 if serverType == SERVER_XEN_API:
753 # TODO
754 raise ValueError("SCSI devices assignment by HBA is not implemeted")
755 feature_host = 1
756 scsi_info = []
757 devid = get_devid(p_hctl)
758 for (pHCTL, devname, _, _) in scsi_devices:
759 if get_devid(pHCTL) == devid:
760 scsi_info.append([devid, pHCTL, devname, pHCTL])
761 else:
762 scsi_info = [[get_devid(v_dev), p_hctl, devname, v_dev]]
764 devid_key = scsi_info[0][0]
765 try:
766 config = config_scsi[devid_key]
767 except KeyError:
768 config = {'feature-host': feature_host, 'backend': backend, 'devs': []}
770 devs = config['devs']
771 for (devid, pHCTL, devname, vHCTL) in scsi_info:
772 if pHCTL in pHCTL_list:
773 raise ValueError('The physical device "%s" is already defined' % pHCTL)
774 if vHCTL in vHCTL_list:
775 raise ValueError('The virtual device "%s" is already defined' % vHCTL)
776 pHCTL_list.append(pHCTL)
777 vHCTL_list.append(vHCTL)
778 devs.append(['dev', \
779 ['state', xenbusState['Initialising']], \
780 ['devid', devid], \
781 ['p-dev', pHCTL], \
782 ['p-devname', devname], \
783 ['v-dev', vHCTL] ])
785 if config['feature-host'] != feature_host:
786 raise ValueError('The physical device "%s" cannot define '
787 'because mode is different' % scsi_info[0][1])
788 if config['backend'] != backend:
789 raise ValueError('The physical device "%s" cannot define '
790 'because backend is different' % scsi_info[0][1])
792 config['devs'] = devs
793 config_scsi[devid_key] = config
795 for config in config_scsi.values():
796 device = ['vscsi', ['feature-host', config['feature-host']]]
797 for dev in config['devs']:
798 device.append(dev)
799 if config['backend']:
800 device.append(['backend', config['backend']])
801 config_devs.append(['device', device])
803 def configure_ioports(config_devs, vals):
804 """Create the config for legacy i/o ranges.
805 """
806 for (io_from, io_to) in vals.ioports:
807 config_ioports = ['ioports', ['from', io_from], ['to', io_to]]
808 config_devs.append(['device', config_ioports])
810 def configure_irq(config_devs, vals):
811 """Create the config for irqs.
812 """
813 for irq in vals.irq:
814 config_irq = ['irq', ['irq', irq]]
815 config_devs.append(['device', config_irq])
817 def configure_vfbs(config_devs, vals):
818 for f in vals.vfb:
819 d = comma_sep_kv_to_dict(f)
820 config = ['vfb']
821 #handle the legacy case
822 if d.has_key("type"):
823 d[d['type']] = '1'
824 del d['type']
825 for (k,v) in d.iteritems():
826 if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
827 'videoram', 'xauthority', 'sdl', 'vnc', 'vncpasswd',
828 'opengl', 'keymap', 'serial' ]:
829 err("configuration option %s unknown to vfbs" % k)
830 config.append([k,v])
831 if not d.has_key("keymap"):
832 if vals.keymap:
833 config.append(['keymap',vals.keymap])
834 if not d.has_key("display") and os.environ.has_key("DISPLAY"):
835 config.append(["display", os.environ['DISPLAY']])
836 if not d.has_key("xauthority"):
837 config.append(["xauthority", get_xauthority()])
838 config_devs.append(['device', ['vkbd']])
839 config_devs.append(['device', config])
841 def configure_security(config, vals):
842 """Create the config for ACM security labels.
843 """
844 access_control = vals.access_control
845 num = len(access_control)
846 if num == 1:
847 d = access_control[0]
848 policy = d.get('policy')
849 label = d.get('label')
850 if policy != security.active_policy:
851 err("Security policy (" + policy + ") incompatible with enforced policy ("
852 + security.active_policy + ")." )
853 config_access_control = ['access_control',
854 ['policy', policy],
855 ['label', label] ]
857 security_label = ['security', [ config_access_control ] ]
858 config.append(security_label)
859 elif num > 1:
860 err("VM config error: Multiple access_control definitions!")
862 def configure_mem_prot(config_image, vals):
863 """Create the config for S3 memory integrity verification under tboot.
864 """
865 config_image.append(['s3_integrity', vals.s3_integrity])
867 def configure_vtpm(config_devs, vals):
868 """Create the config for virtual TPM interfaces.
869 """
870 vtpm = vals.vtpm
871 if len(vtpm) > 0:
872 d = vtpm[0]
873 instance = d.get('instance')
874 if instance == "VTPMD":
875 instance = "0"
876 else:
877 if instance != None:
878 try:
879 if int(instance) == 0:
880 err('VM config error: vTPM instance must not be 0.')
881 except ValueError:
882 err('Vm config error: could not parse instance number.')
883 backend = d.get('backend')
884 typ = d.get('type')
885 config_vtpm = ['vtpm']
886 if instance:
887 config_vtpm.append(['pref_instance', instance])
888 if backend:
889 config_vtpm.append(['backend', backend])
890 if typ:
891 config_vtpm.append(['type', type])
892 config_devs.append(['device', config_vtpm])
895 def configure_vifs(config_devs, vals):
896 """Create the config for virtual network interfaces.
897 """
899 vifs = vals.vif
900 vifs_n = len(vifs)
902 if hasattr(vals, 'nics'):
903 if vals.nics > 0:
904 warn("The nics option is deprecated. Please use an empty vif "
905 "entry instead:\n\n vif = [ '' ]\n")
906 for _ in range(vifs_n, vals.nics):
907 vifs.append('')
908 vifs_n = len(vifs)
909 elif vals.nics == 0:
910 warn("The nics option is deprecated. Please remove it.")
912 for c in vifs:
913 d = comma_sep_kv_to_dict(c)
914 config_vif = ['vif']
916 def f(k):
917 if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
918 'vifname', 'rate', 'model', 'accel',
919 'policy', 'label']:
920 err('Invalid vif option: ' + k)
922 config_vif.append([k, d[k]])
924 map(f, d.keys())
925 config_devs.append(['device', config_vif])
928 def configure_hvm(config_image, vals):
929 """Create the config for HVM devices.
930 """
931 args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb', 'timer_mode',
932 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
933 'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
934 'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
935 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
936 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
937 'viridian', 'xen_extended_power_mgmt', 'pci_msitranslate',
938 'vpt_align', 'pci_power_mgmt', 'xen_platform_pci' ]
940 for a in args:
941 if a in vals.__dict__ and vals.__dict__[a] is not None:
942 config_image.append([a, vals.__dict__[a]])
943 if vals.vncpasswd is not None:
944 config_image.append(['vncpasswd', vals.vncpasswd])
947 def make_config(vals):
948 """Create the domain configuration.
949 """
951 config = ['vm']
953 def add_conf(n):
954 if hasattr(vals, n):
955 v = getattr(vals, n)
956 if v:
957 config.append([n, v])
959 map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
960 'restart', 'on_poweroff',
961 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
962 'on_xend_start', 'on_xend_stop', 'target', 'cpuid',
963 'cpuid_check', 'machine_address_size', 'suppress_spurious_page_faults'])
965 if vals.uuid is not None:
966 config.append(['uuid', vals.uuid])
967 if vals.cpu is not None:
968 config.append(['cpu', vals.cpu])
969 if vals.cpus is not None:
970 config.append(['cpus', vals.cpus])
971 if vals.cpu_cap is not None:
972 config.append(['cpu_cap', vals.cpu_cap])
973 if vals.cpu_weight is not None:
974 config.append(['cpu_weight', vals.cpu_weight])
975 if vals.blkif:
976 config.append(['backend', ['blkif']])
977 if vals.netif:
978 config.append(['backend', ['netif']])
979 if vals.tpmif:
980 config.append(['backend', ['tpmif']])
981 if vals.localtime:
982 config.append(['localtime', vals.localtime])
984 config_image = configure_image(vals)
985 if vals.bootloader:
986 if vals.bootloader == "pygrub":
987 vals.bootloader = auxbin.pathTo(vals.bootloader)
989 config.append(['bootloader', vals.bootloader])
990 if vals.bootargs:
991 config.append(['bootloader_args', vals.bootargs])
992 else:
993 if vals.console_autoconnect:
994 config.append(['bootloader_args', ''])
995 else:
996 config.append(['bootloader_args', '-q'])
997 config.append(['image', config_image])
998 configure_mem_prot(config, vals);
1000 config_devs = []
1001 configure_disks(config_devs, vals)
1002 configure_pci(config_devs, vals)
1003 configure_vscsis(config_devs, vals)
1004 configure_ioports(config_devs, vals)
1005 configure_irq(config_devs, vals)
1006 configure_vifs(config_devs, vals)
1007 configure_vtpm(config_devs, vals)
1008 configure_vfbs(config_devs, vals)
1009 configure_security(config, vals)
1010 config += config_devs
1012 return config
1014 def preprocess_disk(vals):
1015 if not vals.disk: return
1016 disk = []
1017 for v in vals.disk:
1018 d = v.split(',')
1019 n = len(d)
1020 if n == 3:
1021 d.append(None)
1022 d.append(None)
1023 elif n == 4:
1024 d.append(None)
1025 elif n == 5:
1026 pass
1027 else:
1028 err('Invalid disk specifier: ' + v)
1029 disk.append(d)
1030 vals.disk = disk
1032 def preprocess_cpuid(vals, attr_name):
1033 if not vals.cpuid: return
1034 cpuid = {}
1035 for cpuid_input in getattr(vals, attr_name):
1036 input_re = "(0x)?[0-9A-Fa-f]+(,(0x)?[0-9A-Fa-f]+)?"
1037 cpuid_match = re.match(r'(?P<input>%s):(?P<regs>.*)' % \
1038 input_re, cpuid_input)
1039 if cpuid_match != None:
1040 res_cpuid = cpuid_match.groupdict()
1041 input = res_cpuid['input']
1042 regs = res_cpuid['regs'].split(',')
1043 cpuid[input]= {} # New input
1044 for reg in regs:
1045 reg_match = re.match(r"(?P<reg>eax|ebx|ecx|edx)=(?P<val>.*)", reg)
1046 if reg_match == None:
1047 err("cpuid's syntax is (eax|ebx|ecx|edx)=value")
1048 res = reg_match.groupdict()
1049 if (res['val'][:2] != '0x' and len(res['val']) != 32):
1050 err("cpuid: We should specify all the bits " \
1051 "of the register %s for input %s\n"
1052 % (res['reg'], input) )
1053 cpuid[input][res['reg']] = res['val'] # new register
1054 setattr(vals, attr_name, cpuid)
1056 def preprocess_pci(vals):
1057 if not vals.pci: return
1058 pci = []
1059 for pci_dev_str in vals.pci:
1060 pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
1061 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
1062 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
1063 r"(?P<func>[0-7])" + \
1064 r"(@(?P<vslot>[01]?[0-9a-fA-F]))?" + \
1065 r"(,(?P<opts>.*))?$", \
1066 pci_dev_str)
1067 if pci_match!=None:
1068 pci_dev_info = pci_match.groupdict('')
1069 if pci_dev_info['domain']=='':
1070 pci_dev_info['domain']='0'
1071 if pci_dev_info['vslot']=='':
1072 pci_dev_info['vslot']="%02x" % AUTO_PHP_SLOT
1073 try:
1074 pci.append( ('0x'+pci_dev_info['domain'], \
1075 '0x'+pci_dev_info['bus'], \
1076 '0x'+pci_dev_info['slot'], \
1077 '0x'+pci_dev_info['func'], \
1078 '0x'+pci_dev_info['vslot'], \
1079 pci_dev_info['opts']))
1080 except IndexError:
1081 err('Error in PCI slot syntax "%s"'%(pci_dev_str))
1082 vals.pci = pci
1084 def preprocess_vscsi(vals):
1085 if not vals.vscsi: return
1086 scsi = []
1087 for scsi_str in vals.vscsi:
1088 d = [tmp.strip() for tmp in scsi_str.split(',')]
1089 n = len(d)
1090 if n == 2:
1091 tmp = d[1].split(':')
1092 if d[1] != 'host' and len(tmp) != 4:
1093 err('vscsi syntax error "%s"' % d[1])
1094 else:
1095 d.append(None)
1096 elif n == 3:
1097 pass
1098 else:
1099 err('vscsi syntax error "%s"' % scsi_str)
1100 scsi.append(d)
1101 vals.vscsi = scsi
1103 def preprocess_ioports(vals):
1104 if not vals.ioports: return
1105 ioports = []
1106 for v in vals.ioports:
1107 d = v.split('-')
1108 if len(d) < 1 or len(d) > 2:
1109 err('Invalid i/o port range specifier: ' + v)
1110 if len(d) == 1:
1111 d.append(d[0])
1112 # Components are in hex: add hex specifier.
1113 hexd = ['0x' + x for x in d]
1114 ioports.append(hexd)
1115 vals.ioports = ioports
1117 def preprocess_irq(vals):
1118 if not vals.irq: return
1119 irq = []
1120 for v in vals.irq:
1121 d = repr(v)
1122 irq.append(d)
1123 vals.irq = irq
1125 def preprocess_vtpm(vals):
1126 if not vals.vtpm: return
1127 vtpms = []
1128 for vtpm in vals.vtpm:
1129 d = {}
1130 a = vtpm.split(',')
1131 for b in a:
1132 (k, v) = b.strip().split('=', 1)
1133 k = k.strip()
1134 v = v.strip()
1135 if k not in ['backend', 'instance']:
1136 err('Invalid vtpm specifier: ' + vtpm)
1137 d[k] = v
1138 vtpms.append(d)
1139 vals.vtpm = vtpms
1141 def preprocess_access_control(vals):
1142 if not vals.access_control:
1143 return
1144 access_controls = []
1145 num = len(vals.access_control)
1146 if num == 1:
1147 access_control = (vals.access_control)[0]
1148 d = {}
1149 a = access_control.split(',')
1150 if len(a) > 2:
1151 err('Too many elements in access_control specifier: ' + access_control)
1152 for b in a:
1153 (k, v) = b.strip().split('=', 1)
1154 k = k.strip()
1155 v = v.strip()
1156 if k not in ['policy','label']:
1157 err('Invalid access_control specifier: ' + access_control)
1158 d[k] = v
1159 access_controls.append(d)
1160 vals.access_control = access_controls
1161 elif num > 1:
1162 err('Multiple access_control definitions.')
1164 def preprocess_ip(vals):
1165 if vals.ip or vals.dhcp != 'off':
1166 dummy_nfs_server = '127.0.255.255'
1167 ip = (vals.ip
1168 + ':' + (vals.nfs_server or dummy_nfs_server)
1169 + ':' + vals.gateway
1170 + ':' + vals.netmask
1171 + ':' + vals.hostname
1172 + ':' + vals.interface
1173 + ':' + vals.dhcp)
1174 else:
1175 ip = ''
1176 vals.cmdline_ip = ip
1178 def preprocess_nfs(vals):
1179 if not vals.nfs_root: return
1180 if not vals.nfs_server:
1181 err('Must set nfs root and nfs server')
1182 nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
1183 vals.extra = nfs + ' ' + vals.extra
1186 def get_host_addr():
1187 host = socket.gethostname()
1188 addr = socket.gethostbyname(host)
1189 return addr
1191 VNC_BASE_PORT = 5500
1193 def choose_vnc_display():
1194 """Try to choose a free vnc display.
1195 """
1196 def netstat_local_ports():
1197 """Run netstat to get a list of the local ports in use.
1198 """
1199 l = os.popen("netstat -nat").readlines()
1200 r = []
1201 # Skip 2 lines of header.
1202 for x in l[2:]:
1203 # Local port is field 3.
1204 y = x.split()[3]
1205 # Field is addr:port, split off the port.
1206 y = y.split(':')[-1]
1207 r.append(int(y))
1208 return r
1210 ports = netstat_local_ports()
1211 for d in range(1, 100):
1212 port = VNC_BASE_PORT + d
1213 if port in ports: continue
1214 return d
1215 return None
1217 def preprocess(vals):
1218 preprocess_disk(vals)
1219 preprocess_pci(vals)
1220 preprocess_vscsi(vals)
1221 preprocess_ioports(vals)
1222 preprocess_ip(vals)
1223 preprocess_irq(vals)
1224 preprocess_nfs(vals)
1225 preprocess_vtpm(vals)
1226 preprocess_access_control(vals)
1227 preprocess_cpuid(vals, 'cpuid')
1228 preprocess_cpuid(vals, 'cpuid_check')
1231 def comma_sep_kv_to_dict(c):
1232 """Convert comma-separated, equals-separated key-value pairs into a
1233 dictionary.
1234 """
1235 d = {}
1236 c = c.strip()
1237 if len(c) > 0:
1238 a = c.split(',')
1239 for b in a:
1240 if b.find('=') == -1:
1241 err("%s should be a pair, separated by an equals sign." % b)
1242 (k, v) = b.split('=', 1)
1243 k = k.strip()
1244 v = v.strip()
1245 d[k] = v
1246 return d
1249 def make_domain(opts, config):
1250 """Create, build and start a domain.
1252 @param opts: options
1253 @param config: configuration
1254 @return: domain id
1255 @rtype: int
1256 """
1258 try:
1259 dominfo = server.xend.domain.create(config)
1260 except xmlrpclib.Fault, ex:
1261 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1262 err("the domain '%s' does not exist." % ex.faultString)
1263 else:
1264 err("%s" % ex.faultString)
1266 dom = sxp.child_value(dominfo, 'name')
1268 try:
1269 server.xend.domain.waitForDevices(dom)
1270 except xmlrpclib.Fault, ex:
1271 server.xend.domain.destroy(dom)
1272 err("%s" % ex.faultString)
1273 except:
1274 server.xend.domain.destroy(dom)
1275 err("Device creation failed for domain %s" % dom)
1277 if not opts.vals.paused:
1278 try:
1279 server.xend.domain.unpause(dom)
1280 except:
1281 server.xend.domain.destroy(dom)
1282 err("Failed to unpause domain %s" % dom)
1283 domid = int(sxp.child_value(dominfo, 'domid'))
1284 opts.info("Started domain %s (id=%d)" % (dom, domid))
1285 return domid
1288 def get_xauthority():
1289 xauth = os.getenv("XAUTHORITY")
1290 if not xauth:
1291 home = os.getenv("HOME")
1292 if not home:
1293 import posix, pwd
1294 home = pwd.getpwuid(posix.getuid())[5]
1295 xauth = home + "/.Xauthority"
1296 return xauth
1299 def parseCommandLine(argv):
1300 gopts.reset()
1301 args = gopts.parse(argv)
1303 if gopts.vals.help or gopts.vals.help_config:
1304 if gopts.vals.help_config:
1305 print gopts.val_usage()
1306 return (None, None)
1308 if not gopts.vals.display:
1309 gopts.vals.display = os.getenv("DISPLAY")
1311 if not gopts.vals.xauthority:
1312 gopts.vals.xauthority = get_xauthority()
1314 gopts.is_xml = False
1316 # Process remaining args as config variables.
1317 for arg in args:
1318 if '=' in arg:
1319 (var, val) = arg.strip().split('=', 1)
1320 gopts.setvar(var.strip(), val.strip())
1321 if gopts.vals.config:
1322 config = gopts.vals.config
1323 else:
1324 try:
1325 gopts.load_defconfig()
1326 preprocess(gopts.vals)
1327 if not gopts.getopt('name') and gopts.getopt('defconfig'):
1328 gopts.setopt('name', os.path.basename(gopts.getopt('defconfig')))
1329 config = make_config(gopts.vals)
1330 except XMLFileError, ex:
1331 XMLFile = ex.getFile()
1332 gopts.is_xml = True
1333 config = ex.getFile()
1335 return (gopts, config)
1337 def help():
1338 return str(gopts)
1340 def main(argv):
1341 is_xml = False
1343 try:
1344 (opts, config) = parseCommandLine(argv)
1345 except StandardError, ex:
1346 err(str(ex))
1348 if not opts:
1349 return
1351 if not opts.is_xml:
1352 if type(config) == str:
1353 try:
1354 config = sxp.parse(file(config))[0]
1355 except IOError, exn:
1356 raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
1358 if serverType == SERVER_XEN_API:
1359 from xen.xm.xenapi_create import sxp2xml
1360 sxp2xml_inst = sxp2xml()
1361 doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
1363 if opts.vals.dryrun and not opts.is_xml:
1364 SXPPrettyPrint.prettyprint(config)
1366 if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
1367 from xml.dom.ext import PrettyPrint as XMLPrettyPrint
1368 XMLPrettyPrint(doc)
1370 if opts.vals.dryrun or opts.vals.xmldryrun:
1371 return
1373 if opts.vals.console_autoconnect:
1374 do_console(sxp.child_value(config, 'name', -1))
1376 if serverType == SERVER_XEN_API:
1377 from xen.xm.xenapi_create import xenapi_create
1378 xenapi_create_inst = xenapi_create()
1379 if opts.is_xml:
1380 vm_refs = xenapi_create_inst.create(filename = config,
1381 skipdtd = opts.vals.skipdtd)
1382 else:
1383 vm_refs = xenapi_create_inst.create(document = doc,
1384 skipdtd = opts.vals.skipdtd)
1386 map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
1387 elif not opts.is_xml:
1388 dom = make_domain(opts, config)
1390 if opts.vals.vncconsole:
1391 domid = domain_name_to_domid(sxp.child_value(config, 'name', -1))
1392 vncviewer_autopass = getattr(opts.vals,'vncviewer-autopass', False)
1393 console.runVncViewer(domid, vncviewer_autopass, True)
1395 def do_console(domain_name):
1396 cpid = os.fork()
1397 if cpid != 0:
1398 for i in range(10):
1399 # Catch failure of the create process
1400 time.sleep(1)
1401 try:
1402 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1403 except OSError:
1404 # Domain has started cleanly and then exiting,
1405 # the child process used to do this has detached
1406 print("Domain has already finished");
1407 break
1408 if os.WIFEXITED(rv):
1409 if os.WEXITSTATUS(rv) != 0:
1410 sys.exit(os.WEXITSTATUS(rv))
1411 try:
1412 domid = domain_name_to_domid(domain_name)
1413 console.execConsole(domid)
1414 except:
1415 pass
1416 print("Could not start console\n");
1417 sys.exit(0)
1419 if __name__ == '__main__':
1420 main(sys.argv)