debuggers.hg

view tools/python/xen/xm/create.py @ 19975:e845326ae203

python: Remove tab indents.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 14 14:43:19 2009 +0100 (2009-07-14)
parents 72db35d854f3
children dde06d43143b
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 if os.path.dirname(vals.kernel) != "" and os.path.exists(vals.kernel):
657 config_image.append([ 'kernel', vals.kernel ])
658 elif vals.kernel == 'hvmloader':
659 # Keep hvmloader w/o a path and let xend find it.
660 # This allows guest migration to a Dom0 having different
661 # xen install pathes.
662 config_image.append([ 'kernel', vals.kernel ])
663 elif os.path.exists(os.path.abspath(vals.kernel)):
664 # Keep old behaviour, if path is valid.
665 config_image.append([ 'kernel', os.path.abspath(vals.kernel) ])
666 else:
667 raise ValueError('Cannot find kernel "%s"' % vals.kernel)
668 if vals.ramdisk:
669 if os.path.dirname(vals.ramdisk) != "" and os.path.exists(vals.ramdisk):
670 config_image.append([ 'ramdisk', vals.ramdisk ])
671 elif os.path.exists(os.path.abspath(vals.ramdisk)):
672 # Keep old behaviour, if path is valid.
673 config_image.append([ 'ramdisk', os.path.abspath(vals.ramdisk) ])
674 else:
675 raise ValueError('Cannot find ramdisk "%s"' % vals.ramdisk)
676 if vals.loader:
677 if os.path.dirname(vals.loader) != "" and os.path.exists(vals.loader):
678 config_image.append([ 'loader', vals.loader ])
679 elif vals.loader == 'hvmloader':
680 # Keep hvmloader w/o a path and let xend find it.
681 # This allows guest migration to a Dom0 having different
682 # xen install pathes.
683 config_image.append([ 'loader', vals.loader ])
684 elif os.path.exists(os.path.abspath(vals.loader)):
685 # Keep old behaviour, if path is valid.
686 config_image.append([ 'loader', os.path.abspath(vals.loader) ])
687 else:
688 raise ValueError('Cannot find loader "%s"' % vals.loader)
689 if vals.cmdline_ip:
690 cmdline_ip = strip('ip=', vals.cmdline_ip)
691 config_image.append(['ip', cmdline_ip])
692 if vals.root:
693 cmdline_root = strip('root=', vals.root)
694 config_image.append(['root', cmdline_root])
695 if vals.videoram:
696 config_image.append(['videoram', vals.videoram])
697 if vals.extra:
698 config_image.append(['args', vals.extra])
699 if vals.superpages:
700 config_image.append(['superpages', vals.superpages])
702 if vals.builder == 'hvm':
703 configure_hvm(config_image, vals)
705 if vals.vhpt != 0:
706 config_image.append(['vhpt', vals.vhpt])
708 if vals.machine_address_size:
709 config_image.append(['machine_address_size', vals.machine_address_size])
711 if vals.suppress_spurious_page_faults:
712 config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults])
714 return config_image
716 def configure_disks(config_devs, vals):
717 """Create the config for disks (virtual block devices).
718 """
719 for (uname, dev, mode, backend, protocol) in vals.disk:
720 if uname.startswith('tap:'):
721 cls = 'tap2'
722 else:
723 cls = 'vbd'
725 config_vbd = [cls,
726 ['uname', uname],
727 ['dev', dev ],
728 ['mode', mode ] ]
729 if backend:
730 config_vbd.append(['backend', backend])
731 if protocol:
732 config_vbd.append(['protocol', protocol])
733 config_devs.append(['device', config_vbd])
735 def configure_pci(config_devs, vals):
736 """Create the config for pci devices.
737 """
738 config_pci = []
739 for pci_tuple in vals.pci:
740 pci_dev = pci_tuple_to_dict(pci_tuple)
741 config_pci.append(dev_dict_to_sxp(pci_dev))
743 if len(config_pci)>0:
744 config_pci.insert(0, 'pci')
745 config_devs.append(['device', config_pci])
747 def configure_vscsis(config_devs, vals):
748 """Create the config for vscsis (virtual scsi devices).
749 """
751 def get_devid(hctl):
752 return int(hctl.split(':')[0])
754 if len(vals.vscsi) == 0:
755 return 0
757 config_scsi = {}
758 pHCTL_list = []
759 vHCTL_list = []
761 scsi_devices = vscsi_util.vscsi_get_scsidevices()
762 for (p_dev, v_dev, backend) in vals.vscsi:
763 (p_hctl, devname) = \
764 vscsi_util.vscsi_get_hctl_and_devname_by(p_dev, scsi_devices)
766 if p_hctl == None:
767 raise ValueError('Cannot find device "%s"' % p_dev)
769 feature_host = 0
770 if v_dev == 'host':
771 if serverType == SERVER_XEN_API:
772 # TODO
773 raise ValueError("SCSI devices assignment by HBA is not implemeted")
774 feature_host = 1
775 scsi_info = []
776 devid = get_devid(p_hctl)
777 for (pHCTL, devname, _, _) in scsi_devices:
778 if get_devid(pHCTL) == devid:
779 scsi_info.append([devid, pHCTL, devname, pHCTL])
780 else:
781 scsi_info = [[get_devid(v_dev), p_hctl, devname, v_dev]]
783 devid_key = scsi_info[0][0]
784 try:
785 config = config_scsi[devid_key]
786 except KeyError:
787 config = {'feature-host': feature_host, 'backend': backend, 'devs': []}
789 devs = config['devs']
790 for (devid, pHCTL, devname, vHCTL) in scsi_info:
791 if pHCTL in pHCTL_list:
792 raise ValueError('The physical device "%s" is already defined' % pHCTL)
793 if vHCTL in vHCTL_list:
794 raise ValueError('The virtual device "%s" is already defined' % vHCTL)
795 pHCTL_list.append(pHCTL)
796 vHCTL_list.append(vHCTL)
797 devs.append(['dev', \
798 ['state', xenbusState['Initialising']], \
799 ['devid', devid], \
800 ['p-dev', pHCTL], \
801 ['p-devname', devname], \
802 ['v-dev', vHCTL] ])
804 if config['feature-host'] != feature_host:
805 raise ValueError('The physical device "%s" cannot define '
806 'because mode is different' % scsi_info[0][1])
807 if config['backend'] != backend:
808 raise ValueError('The physical device "%s" cannot define '
809 'because backend is different' % scsi_info[0][1])
811 config['devs'] = devs
812 config_scsi[devid_key] = config
814 for config in config_scsi.values():
815 device = ['vscsi', ['feature-host', config['feature-host']]]
816 for dev in config['devs']:
817 device.append(dev)
818 if config['backend']:
819 device.append(['backend', config['backend']])
820 config_devs.append(['device', device])
822 def configure_ioports(config_devs, vals):
823 """Create the config for legacy i/o ranges.
824 """
825 for (io_from, io_to) in vals.ioports:
826 config_ioports = ['ioports', ['from', io_from], ['to', io_to]]
827 config_devs.append(['device', config_ioports])
829 def configure_irq(config_devs, vals):
830 """Create the config for irqs.
831 """
832 for irq in vals.irq:
833 config_irq = ['irq', ['irq', irq]]
834 config_devs.append(['device', config_irq])
836 def configure_vfbs(config_devs, vals):
837 for f in vals.vfb:
838 d = comma_sep_kv_to_dict(f)
839 config = ['vfb']
840 #handle the legacy case
841 if d.has_key("type"):
842 d[d['type']] = '1'
843 del d['type']
844 for (k,v) in d.iteritems():
845 if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
846 'videoram', 'xauthority', 'sdl', 'vnc', 'vncpasswd',
847 'opengl', 'keymap', 'serial', 'monitor' ]:
848 err("configuration option %s unknown to vfbs" % k)
849 config.append([k,v])
850 if not d.has_key("keymap"):
851 if vals.keymap:
852 config.append(['keymap',vals.keymap])
853 if not d.has_key("display") and os.environ.has_key("DISPLAY"):
854 config.append(["display", os.environ['DISPLAY']])
855 if not d.has_key("xauthority"):
856 config.append(["xauthority", get_xauthority()])
857 config_devs.append(['device', ['vkbd']])
858 config_devs.append(['device', config])
860 def configure_security(config, vals):
861 """Create the config for ACM security labels.
862 """
863 access_control = vals.access_control
864 num = len(access_control)
865 if num == 1:
866 d = access_control[0]
867 policy = d.get('policy')
868 label = d.get('label')
869 if policy != security.active_policy:
870 err("Security policy (" + policy + ") incompatible with enforced policy ("
871 + security.active_policy + ")." )
872 config_access_control = ['access_control',
873 ['policy', policy],
874 ['label', label] ]
876 security_label = ['security', [ config_access_control ] ]
877 config.append(security_label)
878 elif num > 1:
879 err("VM config error: Multiple access_control definitions!")
881 def configure_mem_prot(config_image, vals):
882 """Create the config for S3 memory integrity verification under tboot.
883 """
884 config_image.append(['s3_integrity', vals.s3_integrity])
886 def configure_vtpm(config_devs, vals):
887 """Create the config for virtual TPM interfaces.
888 """
889 vtpm = vals.vtpm
890 if len(vtpm) > 0:
891 d = vtpm[0]
892 instance = d.get('instance')
893 if instance == "VTPMD":
894 instance = "0"
895 else:
896 if instance != None:
897 try:
898 if int(instance) == 0:
899 err('VM config error: vTPM instance must not be 0.')
900 except ValueError:
901 err('Vm config error: could not parse instance number.')
902 backend = d.get('backend')
903 typ = d.get('type')
904 config_vtpm = ['vtpm']
905 if instance:
906 config_vtpm.append(['pref_instance', instance])
907 if backend:
908 config_vtpm.append(['backend', backend])
909 if typ:
910 config_vtpm.append(['type', type])
911 config_devs.append(['device', config_vtpm])
914 def configure_vifs(config_devs, vals):
915 """Create the config for virtual network interfaces.
916 """
918 vifs = vals.vif
919 vifs_n = len(vifs)
921 if hasattr(vals, 'nics'):
922 if vals.nics > 0:
923 warn("The nics option is deprecated. Please use an empty vif "
924 "entry instead:\n\n vif = [ '' ]\n")
925 for _ in range(vifs_n, vals.nics):
926 vifs.append('')
927 vifs_n = len(vifs)
928 elif vals.nics == 0:
929 warn("The nics option is deprecated. Please remove it.")
931 for c in vifs:
932 d = comma_sep_kv_to_dict(c)
933 config_vif = ['vif']
935 def f(k):
936 if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
937 'vifname', 'rate', 'model', 'accel',
938 'policy', 'label']:
939 err('Invalid vif option: ' + k)
941 config_vif.append([k, d[k]])
943 map(f, d.keys())
944 config_devs.append(['device', config_vif])
947 def configure_hvm(config_image, vals):
948 """Create the config for HVM devices.
949 """
950 args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb', 'timer_mode',
951 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
952 'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
953 'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
954 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
955 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
956 'viridian', 'xen_extended_power_mgmt', 'pci_msitranslate',
957 'vpt_align', 'pci_power_mgmt', 'xen_platform_pci' ]
959 for a in args:
960 if a in vals.__dict__ and vals.__dict__[a] is not None:
961 config_image.append([a, vals.__dict__[a]])
962 if vals.vncpasswd is not None:
963 config_image.append(['vncpasswd', vals.vncpasswd])
966 def make_config(vals):
967 """Create the domain configuration.
968 """
970 config = ['vm']
972 def add_conf(n):
973 if hasattr(vals, n):
974 v = getattr(vals, n)
975 if v:
976 config.append([n, v])
978 map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
979 'restart', 'on_poweroff',
980 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
981 'on_xend_start', 'on_xend_stop', 'target', 'cpuid',
982 'cpuid_check', 'machine_address_size', 'suppress_spurious_page_faults'])
984 if vals.uuid is not None:
985 config.append(['uuid', vals.uuid])
986 if vals.cpu is not None:
987 config.append(['cpu', vals.cpu])
988 if vals.cpus is not None:
989 config.append(['cpus', vals.cpus])
990 if vals.cpu_cap is not None:
991 config.append(['cpu_cap', vals.cpu_cap])
992 if vals.cpu_weight is not None:
993 config.append(['cpu_weight', vals.cpu_weight])
994 if vals.blkif:
995 config.append(['backend', ['blkif']])
996 if vals.netif:
997 config.append(['backend', ['netif']])
998 if vals.tpmif:
999 config.append(['backend', ['tpmif']])
1000 if vals.localtime:
1001 config.append(['localtime', vals.localtime])
1003 config_image = configure_image(vals)
1004 if vals.bootloader:
1005 if vals.bootloader == "pygrub":
1006 vals.bootloader = auxbin.pathTo(vals.bootloader)
1008 config.append(['bootloader', vals.bootloader])
1009 if vals.bootargs:
1010 config.append(['bootloader_args', vals.bootargs])
1011 else:
1012 if vals.console_autoconnect:
1013 config.append(['bootloader_args', ''])
1014 else:
1015 config.append(['bootloader_args', '-q'])
1016 config.append(['image', config_image])
1017 configure_mem_prot(config, vals);
1019 config_devs = []
1020 configure_disks(config_devs, vals)
1021 configure_pci(config_devs, vals)
1022 configure_vscsis(config_devs, vals)
1023 configure_ioports(config_devs, vals)
1024 configure_irq(config_devs, vals)
1025 configure_vifs(config_devs, vals)
1026 configure_vtpm(config_devs, vals)
1027 configure_vfbs(config_devs, vals)
1028 configure_security(config, vals)
1029 config += config_devs
1031 return config
1033 def preprocess_disk(vals):
1034 if not vals.disk: return
1035 disk = []
1036 for v in vals.disk:
1037 d = v.split(',')
1038 n = len(d)
1039 if n == 3:
1040 d.append(None)
1041 d.append(None)
1042 elif n == 4:
1043 d.append(None)
1044 elif n == 5:
1045 pass
1046 else:
1047 err('Invalid disk specifier: ' + v)
1048 disk.append(d)
1049 vals.disk = disk
1051 def preprocess_cpuid(vals, attr_name):
1052 if not vals.cpuid: return
1053 cpuid = {}
1054 for cpuid_input in getattr(vals, attr_name):
1055 input_re = "(0x)?[0-9A-Fa-f]+(,(0x)?[0-9A-Fa-f]+)?"
1056 cpuid_match = re.match(r'(?P<input>%s):(?P<regs>.*)' % \
1057 input_re, cpuid_input)
1058 if cpuid_match != None:
1059 res_cpuid = cpuid_match.groupdict()
1060 input = res_cpuid['input']
1061 regs = res_cpuid['regs'].split(',')
1062 cpuid[input]= {} # New input
1063 for reg in regs:
1064 reg_match = re.match(r"(?P<reg>eax|ebx|ecx|edx)=(?P<val>.*)", reg)
1065 if reg_match == None:
1066 err("cpuid's syntax is (eax|ebx|ecx|edx)=value")
1067 res = reg_match.groupdict()
1068 if (res['val'][:2] != '0x' and len(res['val']) != 32):
1069 err("cpuid: We should specify all the bits " \
1070 "of the register %s for input %s\n"
1071 % (res['reg'], input) )
1072 cpuid[input][res['reg']] = res['val'] # new register
1073 setattr(vals, attr_name, cpuid)
1075 def pci_dict_to_tuple(dev):
1076 return (dev['domain'], dev['bus'], dev['slot'], dev['func'],
1077 dev['vdevfn'], dev.get('opts', []), dev['key'])
1079 def pci_tuple_to_dict((domain, bus, slot, func, vdevfn, opts, key)):
1080 pci_dev = { 'domain': domain,
1081 'bus': bus,
1082 'slot': slot,
1083 'func': func,
1084 'vdevfn': vdevfn,
1085 'key': key}
1086 if len(opts) > 0:
1087 pci_dev['opts'] = opts
1088 return pci_dev
1090 def preprocess_pci(vals):
1091 if not vals.pci:
1092 return
1093 try:
1094 vals.pci = map(pci_dict_to_tuple, reduce(lambda x, y: x + y,
1095 map(parse_pci_name_extended, vals.pci)))
1096 except PciDeviceParseError, ex:
1097 err(str(ex))
1099 def preprocess_vscsi(vals):
1100 if not vals.vscsi: return
1101 scsi = []
1102 for scsi_str in vals.vscsi:
1103 d = [tmp.strip() for tmp in scsi_str.split(',')]
1104 n = len(d)
1105 if n == 2:
1106 tmp = d[1].split(':')
1107 if d[1] != 'host' and len(tmp) != 4:
1108 err('vscsi syntax error "%s"' % d[1])
1109 else:
1110 d.append(None)
1111 elif n == 3:
1112 pass
1113 else:
1114 err('vscsi syntax error "%s"' % scsi_str)
1115 scsi.append(d)
1116 vals.vscsi = scsi
1118 def preprocess_ioports(vals):
1119 if not vals.ioports: return
1120 ioports = []
1121 for v in vals.ioports:
1122 d = v.split('-')
1123 if len(d) < 1 or len(d) > 2:
1124 err('Invalid i/o port range specifier: ' + v)
1125 if len(d) == 1:
1126 d.append(d[0])
1127 # Components are in hex: add hex specifier.
1128 hexd = ['0x' + x for x in d]
1129 ioports.append(hexd)
1130 vals.ioports = ioports
1132 def preprocess_irq(vals):
1133 if not vals.irq: return
1134 irq = []
1135 for v in vals.irq:
1136 d = repr(v)
1137 irq.append(d)
1138 vals.irq = irq
1140 def preprocess_vtpm(vals):
1141 if not vals.vtpm: return
1142 vtpms = []
1143 for vtpm in vals.vtpm:
1144 d = {}
1145 a = vtpm.split(',')
1146 for b in a:
1147 (k, v) = b.strip().split('=', 1)
1148 k = k.strip()
1149 v = v.strip()
1150 if k not in ['backend', 'instance']:
1151 err('Invalid vtpm specifier: ' + vtpm)
1152 d[k] = v
1153 vtpms.append(d)
1154 vals.vtpm = vtpms
1156 def preprocess_access_control(vals):
1157 if not vals.access_control:
1158 return
1159 access_controls = []
1160 num = len(vals.access_control)
1161 if num == 1:
1162 access_control = (vals.access_control)[0]
1163 d = {}
1164 a = access_control.split(',')
1165 if len(a) > 2:
1166 err('Too many elements in access_control specifier: ' + access_control)
1167 for b in a:
1168 (k, v) = b.strip().split('=', 1)
1169 k = k.strip()
1170 v = v.strip()
1171 if k not in ['policy','label']:
1172 err('Invalid access_control specifier: ' + access_control)
1173 d[k] = v
1174 access_controls.append(d)
1175 vals.access_control = access_controls
1176 elif num > 1:
1177 err('Multiple access_control definitions.')
1179 def preprocess_ip(vals):
1180 if vals.ip or vals.dhcp != 'off':
1181 dummy_nfs_server = '127.0.255.255'
1182 ip = (vals.ip
1183 + ':' + (vals.nfs_server or dummy_nfs_server)
1184 + ':' + vals.gateway
1185 + ':' + vals.netmask
1186 + ':' + vals.hostname
1187 + ':' + vals.interface
1188 + ':' + vals.dhcp)
1189 else:
1190 ip = ''
1191 vals.cmdline_ip = ip
1193 def preprocess_nfs(vals):
1194 if not vals.nfs_root: return
1195 if not vals.nfs_server:
1196 err('Must set nfs root and nfs server')
1197 nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
1198 vals.extra = nfs + ' ' + vals.extra
1201 def get_host_addr():
1202 host = socket.gethostname()
1203 addr = socket.gethostbyname(host)
1204 return addr
1206 VNC_BASE_PORT = 5500
1208 def choose_vnc_display():
1209 """Try to choose a free vnc display.
1210 """
1211 def netstat_local_ports():
1212 """Run netstat to get a list of the local ports in use.
1213 """
1214 l = os.popen("netstat -nat").readlines()
1215 r = []
1216 # Skip 2 lines of header.
1217 for x in l[2:]:
1218 # Local port is field 3.
1219 y = x.split()[3]
1220 # Field is addr:port, split off the port.
1221 y = y.split(':')[-1]
1222 r.append(int(y))
1223 return r
1225 ports = netstat_local_ports()
1226 for d in range(1, 100):
1227 port = VNC_BASE_PORT + d
1228 if port in ports: continue
1229 return d
1230 return None
1232 def preprocess(vals):
1233 preprocess_disk(vals)
1234 preprocess_pci(vals)
1235 preprocess_vscsi(vals)
1236 preprocess_ioports(vals)
1237 preprocess_ip(vals)
1238 preprocess_irq(vals)
1239 preprocess_nfs(vals)
1240 preprocess_vtpm(vals)
1241 preprocess_access_control(vals)
1242 preprocess_cpuid(vals, 'cpuid')
1243 preprocess_cpuid(vals, 'cpuid_check')
1246 def comma_sep_kv_to_dict(c):
1247 """Convert comma-separated, equals-separated key-value pairs into a
1248 dictionary.
1249 """
1250 d = {}
1251 c = c.strip()
1252 if len(c) > 0:
1253 a = c.split(',')
1254 for b in a:
1255 if b.find('=') == -1:
1256 err("%s should be a pair, separated by an equals sign." % b)
1257 (k, v) = b.split('=', 1)
1258 k = k.strip()
1259 v = v.strip()
1260 d[k] = v
1261 return d
1264 def make_domain(opts, config):
1265 """Create, build and start a domain.
1267 @param opts: options
1268 @param config: configuration
1269 @return: domain id
1270 @rtype: int
1271 """
1273 try:
1274 dominfo = server.xend.domain.create(config)
1275 except xmlrpclib.Fault, ex:
1276 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1277 err("the domain '%s' does not exist." % ex.faultString)
1278 else:
1279 err("%s" % ex.faultString)
1281 dom = sxp.child_value(dominfo, 'name')
1283 try:
1284 server.xend.domain.waitForDevices(dom)
1285 except xmlrpclib.Fault, ex:
1286 server.xend.domain.destroy(dom)
1287 err("%s" % ex.faultString)
1288 except:
1289 server.xend.domain.destroy(dom)
1290 err("Device creation failed for domain %s" % dom)
1292 if not opts.vals.paused:
1293 try:
1294 server.xend.domain.unpause(dom)
1295 except:
1296 server.xend.domain.destroy(dom)
1297 err("Failed to unpause domain %s" % dom)
1298 domid = int(sxp.child_value(dominfo, 'domid'))
1299 opts.info("Started domain %s (id=%d)" % (dom, domid))
1300 return domid
1303 def get_xauthority():
1304 xauth = os.getenv("XAUTHORITY")
1305 if not xauth:
1306 home = os.getenv("HOME")
1307 if not home:
1308 import posix, pwd
1309 home = pwd.getpwuid(posix.getuid())[5]
1310 xauth = home + "/.Xauthority"
1311 return xauth
1314 def parseCommandLine(argv):
1315 gopts.reset()
1316 args = gopts.parse(argv)
1318 if gopts.vals.help or gopts.vals.help_config:
1319 if gopts.vals.help_config:
1320 print gopts.val_usage()
1321 return (None, None)
1323 if not gopts.vals.display:
1324 gopts.vals.display = os.getenv("DISPLAY")
1326 if not gopts.vals.xauthority:
1327 gopts.vals.xauthority = get_xauthority()
1329 gopts.is_xml = False
1331 # Process remaining args as config variables.
1332 for arg in args:
1333 if '=' in arg:
1334 (var, val) = arg.strip().split('=', 1)
1335 gopts.setvar(var.strip(), val.strip())
1336 if gopts.vals.config:
1337 config = gopts.vals.config
1338 else:
1339 try:
1340 gopts.load_defconfig()
1341 preprocess(gopts.vals)
1342 if not gopts.getopt('name') and gopts.getopt('defconfig'):
1343 gopts.setopt('name', os.path.basename(gopts.getopt('defconfig')))
1344 config = make_config(gopts.vals)
1345 except XMLFileError, ex:
1346 XMLFile = ex.getFile()
1347 gopts.is_xml = True
1348 config = ex.getFile()
1350 return (gopts, config)
1352 def help():
1353 return str(gopts)
1355 def main(argv):
1356 is_xml = False
1358 try:
1359 (opts, config) = parseCommandLine(argv)
1360 except StandardError, ex:
1361 err(str(ex))
1363 if not opts:
1364 return
1366 if not opts.is_xml:
1367 if type(config) == str:
1368 try:
1369 config = sxp.parse(file(config))[0]
1370 except IOError, exn:
1371 raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
1373 if serverType == SERVER_XEN_API:
1374 from xen.xm.xenapi_create import sxp2xml
1375 sxp2xml_inst = sxp2xml()
1376 doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
1378 if opts.vals.dryrun and not opts.is_xml:
1379 SXPPrettyPrint.prettyprint(config)
1381 if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
1382 from xml.dom.ext import PrettyPrint as XMLPrettyPrint
1383 XMLPrettyPrint(doc)
1385 if opts.vals.dryrun or opts.vals.xmldryrun:
1386 return
1388 if opts.vals.console_autoconnect:
1389 do_console(sxp.child_value(config, 'name', -1))
1391 if serverType == SERVER_XEN_API:
1392 from xen.xm.xenapi_create import xenapi_create
1393 xenapi_create_inst = xenapi_create()
1394 if opts.is_xml:
1395 vm_refs = xenapi_create_inst.create(filename = config,
1396 skipdtd = opts.vals.skipdtd)
1397 else:
1398 vm_refs = xenapi_create_inst.create(document = doc,
1399 skipdtd = opts.vals.skipdtd)
1401 map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
1402 elif not opts.is_xml:
1403 dom = make_domain(opts, config)
1405 if opts.vals.vncconsole:
1406 domid = domain_name_to_domid(sxp.child_value(config, 'name', -1))
1407 vncviewer_autopass = getattr(opts.vals,'vncviewer-autopass', False)
1408 console.runVncViewer(domid, vncviewer_autopass, True)
1410 def do_console(domain_name):
1411 cpid = os.fork()
1412 if cpid != 0:
1413 for i in range(10):
1414 # Catch failure of the create process
1415 time.sleep(1)
1416 try:
1417 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1418 except OSError:
1419 # Domain has started cleanly and then exiting,
1420 # the child process used to do this has detached
1421 print("Domain has already finished");
1422 break
1423 if os.WIFEXITED(rv):
1424 if os.WEXITSTATUS(rv) != 0:
1425 sys.exit(os.WEXITSTATUS(rv))
1426 try:
1427 domid = domain_name_to_domid(domain_name)
1428 console.execConsole(domid)
1429 except:
1430 pass
1431 print("Could not start console\n");
1432 sys.exit(0)
1434 if __name__ == '__main__':
1435 main(sys.argv)