ia64/xen-unstable

view tools/python/xen/xm/create.py @ 19639:205b1badbcfd

Add support for superpages (hugepages) in PV domain

This patch adds the option "superpages" to the domain configuration
file. If it is set, the domain is populated using 2M pages.

This code does not support fallback to small pages. If the domain can
not be created with 2M pages, the create will fail.

The patch also includes support for saving and restoring domains with
the superpage flag set. However, if a domain has freed small pages
within its physical page array and then extended the array, the
restore will fill in those freed pages. It will then attempt to
allocate more than its memory limit and will fail. This is
significant because apparently Linux does this during boot, thus a
freshly booted Linux image can not be saved and restored successfully.

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