debuggers.hg

view tools/python/xen/xm/create.py @ 22906:700ac6445812

Now add KDB to the non-kdb tree
author Mukesh Rathor
date Thu Feb 03 15:42:41 2011 -0800 (2011-02-03)
parents 6fdb00dc93a5
children
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('memory_sharing', val='no|yes',
200 fn=set_bool, default=0,
201 use="Should memory be shared?")
203 gopts.var('cpu', val='CPU',
204 fn=set_int, default=None,
205 use="CPU to run the VCPU0 on.")
207 gopts.var('cpus', val='CPUS',
208 fn=set_value, default=None,
209 use="CPUS to run the domain on.")
211 gopts.var('rtc_timeoffset', val='RTC_TIMEOFFSET',
212 fn=set_int, default=0,
213 use="Set RTC offset.")
215 gopts.var('pae', val='PAE',
216 fn=set_int, default=1,
217 use="Disable or enable PAE of HVM domain.")
219 gopts.var('hpet', val='HPET',
220 fn=set_int, default=0,
221 use="Enable virtual high-precision event timer.")
223 gopts.var('timer_mode', val='TIMER_MODE',
224 fn=set_int, default=1,
225 use="""Timer mode (0=delay virtual time when ticks are missed;
226 1=virtual time is always wallclock time.""")
228 gopts.var('tsc_mode', val='TSC_MODE',
229 fn=set_int, default=0,
230 use="""TSC mode (0=default, 1=always emulate, 2=never emulate, 3=pvrdtscp).""")
232 gopts.var('nomigrate', val='NOMIGRATE',
233 fn=set_int, default=0,
234 use="""migratability (0=migration enabled, 1=migration disabled).""")
236 gopts.var('vpt_align', val='VPT_ALIGN',
237 fn=set_int, default=1,
238 use="Enable aligning all periodic vpt to reduce timer interrupts.")
240 gopts.var('viridian', val='VIRIDIAN',
241 fn=set_int, default=0,
242 use="""Expose Viridian interface to x86 HVM guest?
243 (Default is 0).""")
245 gopts.var('acpi', val='ACPI',
246 fn=set_int, default=1,
247 use="Disable or enable ACPI of HVM domain.")
249 gopts.var('apic', val='APIC',
250 fn=set_int, default=1,
251 use="Disable or enable APIC mode.")
253 gopts.var('vcpus', val='VCPUS',
254 fn=set_int, default=1,
255 use="# of Virtual CPUS in domain.")
257 gopts.var('vcpu_avail', val='VCPUS',
258 fn=set_long, default=None,
259 use="Bitmask for virtual CPUs to make available immediately.")
261 gopts.var('vhpt', val='VHPT',
262 fn=set_int, default=0,
263 use="Log2 of domain VHPT size for IA64.")
265 gopts.var('cpu_cap', val='CAP',
266 fn=set_int, default=None,
267 use="""Set the maximum amount of cpu.
268 CAP is a percentage that fixes the maximum amount of cpu.""")
270 gopts.var('cpu_weight', val='WEIGHT',
271 fn=set_int, default=None,
272 use="""Set the cpu time ratio to be allocated to the domain.""")
274 gopts.var('restart', val='onreboot|always|never',
275 fn=set_value, default=None,
276 use="""Deprecated. Use on_poweroff, on_reboot, and on_crash
277 instead.
279 Whether the domain should be restarted on exit.
280 - onreboot: restart on exit with shutdown code reboot
281 - always: always restart on exit, ignore exit code
282 - never: never restart on exit, ignore exit code""")
284 gopts.var('on_poweroff', val='destroy|restart|preserve|rename-restart',
285 fn=set_value, default=None,
286 use="""Behaviour when a domain exits with reason 'poweroff'.
287 - destroy: the domain is cleaned up as normal;
288 - restart: a new domain is started in place of the old one;
289 - preserve: no clean-up is done until the domain is manually
290 destroyed (using xm destroy, for example);
291 - rename-restart: the old domain is not cleaned up, but is
292 renamed and a new domain started in its place.
293 """)
295 gopts.var('on_reboot', val='destroy|restart|preserve|rename-restart',
296 fn=set_value, default=None,
297 use="""Behaviour when a domain exits with reason 'reboot'.
298 - destroy: the domain is cleaned up as normal;
299 - restart: a new domain is started in place of the old one;
300 - preserve: no clean-up is done until the domain is manually
301 destroyed (using xm destroy, for example);
302 - rename-restart: the old domain is not cleaned up, but is
303 renamed and a new domain started in its place.
304 """)
306 gopts.var('on_crash', val='destroy|restart|preserve|rename-restart|coredump-destroy|coredump-restart',
307 fn=set_value, default=None,
308 use="""Behaviour when a domain exits with reason 'crash'.
309 - destroy: the domain is cleaned up as normal;
310 - restart: a new domain is started in place of the old one;
311 - preserve: no clean-up is done until the domain is manually
312 destroyed (using xm destroy, for example);
313 - rename-restart: the old domain is not cleaned up, but is
314 renamed and a new domain started in its place.
315 - coredump-destroy: dump the domain's core, followed by destroy
316 - coredump-restart: dump the domain's core, followed by restart
317 """)
319 gopts.var('blkif', val='no|yes',
320 fn=set_bool, default=0,
321 use="Make the domain a block device backend.")
323 gopts.var('netif', val='no|yes',
324 fn=set_bool, default=0,
325 use="Make the domain a network interface backend.")
327 gopts.var('tpmif', val='no|yes',
328 fn=append_value, default=0,
329 use="Make the domain a TPM interface backend.")
331 gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
332 fn=append_value, default=[],
333 use="""Add a disk device to a domain. The physical device is DEV,
334 which is exported to the domain as VDEV. The disk is read-only if MODE
335 is 'r', read-write if MODE is 'w'. If DOM is specified it defines the
336 backend driver domain to use for the disk.
337 The option may be repeated to add more than one disk.""")
339 gopts.var('pci', val='BUS:DEV.FUNC[@VSLOT][,msitranslate=0|1][,power_mgmt=0|1]',
340 fn=append_value, default=[],
341 use="""Add a PCI device to a domain, using given params (in hex).
342 For example 'pci=c0:02.1'.
343 If VSLOT is supplied the device will be inserted into that
344 virtual slot in the guest, else a free slot is selected.
345 If msitranslate is set, MSI-INTx translation is enabled if possible.
346 Guest that doesn't support MSI will get IO-APIC type IRQs
347 translated from physical MSI, HVM only. Default is 1.
348 The option may be repeated to add more than one pci device.
349 If power_mgmt is set, the guest OS will be able to program the power
350 states D0-D3hot of the device, HVM only. Default=0.""")
352 gopts.var('vscsi', val='PDEV,VDEV[,DOM]',
353 fn=append_value, default=[],
354 use="""Add a SCSI device to a domain. The physical device is PDEV,
355 which is exported to the domain as VDEV(X:X:X:X).""")
357 gopts.var('vusb', val="usbver=USBVER,numports=NUMPORTS," + \
358 "port_1=PORT1,port_2=PORT2,port_3=PORT3,port_4=PORT4" + \
359 "port_5=PORT5,port_6=PORT6,port_7=PORT7,port_8=PORT8" + \
360 "port_9=PORT9,port_10=PORT10,port_11=PORT11,port_12=PORT12" + \
361 "port_13=PORT13,port_14=PORT14,port_15=PORT15,port_16=PORT16",
362 fn=append_value, default=[],
363 use="""Add a Virtual USB Host Controller to a domain.
364 The USB Spec Version is usbver (1|2, default: 2).
365 usbver=1 means USB1.1, usbver=2 mens USB2.0.
366 The number of root ports is numports (1 to 16, default: 8).
367 This option may be repeated to add more than one host controller.""")
369 gopts.var('ioports', val='FROM[-TO]',
370 fn=append_value, default=[],
371 use="""Add a legacy I/O range to a domain, using given params (in hex).
372 For example 'ioports=02f8-02ff'.
373 The option may be repeated to add more than one i/o range.""")
375 gopts.var('irq', val='IRQ',
376 fn=append_value, default=[],
377 use="""Add an IRQ (interrupt line) to a domain.
378 For example 'irq=7'.
379 This option may be repeated to add more than one IRQ.""")
381 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",
382 fn=append_value, default=[],
383 use="""Make the domain a framebuffer backend.
384 Both sdl=1 and vnc=1 can be enabled at the same time.
385 For vnc=1, connect an external vncviewer. The server will listen
386 on ADDR (default 127.0.0.1) on port N+5900. N defaults to the
387 domain id. If vncunused=1, the server will try to find an arbitrary
388 unused port above 5900. vncpasswd overrides the XenD configured
389 default password.
390 For sdl=1, a viewer will be started automatically using the
391 given DISPLAY and XAUTHORITY, which default to the current user's
392 ones. OpenGL will be used by default unless opengl is set to 0.
393 keymap overrides the XendD configured default layout file.
394 Serial adds a second serial support to qemu.
395 Monitor adds a backend for the stubdom monitor.""")
397 gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT," + \
398 "backend=DOM,vifname=NAME,rate=RATE,model=MODEL,accel=ACCEL",
399 fn=append_value, default=[],
400 use="""Add a network interface with the given MAC address and bridge.
401 The vif is configured by calling the given configuration script.
402 If type is not specified, default is netfront.
403 If mac is not specified a random MAC address is used.
404 If not specified then the network backend chooses it's own MAC address.
405 If bridge is not specified the first bridge found is used.
406 If script is not specified the default script is used.
407 If backend is not specified the default backend driver domain is used.
408 If vifname is not specified the backend virtual interface will have name vifD.N
409 where D is the domain id and N is the interface id.
410 If rate is not specified the default rate is used.
411 If model is not specified the default model is used.
412 If accel is not specified an accelerator plugin module is not used.
413 This option may be repeated to add more than one vif.
414 Specifying vifs will increase the number of interfaces as needed.""")
416 gopts.var('vif2', val="front_mac=MAC,back_mac=MAC,backend=DOM,pdev=PDEV,max_bypasses=N,bridge=BRIDGE,filter_mac=<0|1>,front_filter_mac=<0|1>",
417 fn=append_value, default=[],
418 use="""Add a netchannel2 network interface using given front
419 and backend MAC addresses. Randomly generated
420 addresses will be used if either address is missing.""")
422 gopts.var('vtpm', val="instance=INSTANCE,backend=DOM,type=TYPE",
423 fn=append_value, default=[],
424 use="""Add a TPM interface. On the backend side use the given
425 instance as virtual TPM instance. The given number is merely the
426 preferred instance number. The hotplug script will determine
427 which instance number will actually be assigned to the domain.
428 The associtation between virtual machine and the TPM instance
429 number can be found in /etc/xen/vtpm.db. Use the backend in the
430 given domain.
431 The type parameter can be used to select a specific driver type
432 that the VM can use. To prevent a fully virtualized domain (HVM)
433 from being able to access an emulated device model, you may specify
434 'paravirtualized' here.""")
436 gopts.var('access_control', val="policy=POLICY,label=LABEL",
437 fn=append_value, default=[],
438 use="""Add a security label and the security policy reference that defines it.
439 The local ssid reference is calculated when starting/resuming the domain. At
440 this time, the policy is checked against the active policy as well. This way,
441 migrating through save/restore is covered and local labels are automatically
442 created correctly on the system where a domain is started / resumed.""")
444 gopts.var('nics', val="NUM",
445 fn=set_int, default=-1,
446 use="""DEPRECATED. Use empty vif entries instead.
448 Set the number of network interfaces.
449 Use the vif option to define interface parameters, otherwise
450 defaults are used. Specifying vifs will increase the
451 number of interfaces as needed.""")
453 gopts.var('root', val='DEVICE',
454 fn=set_value, default='',
455 use="""Set the root= parameter on the kernel command line.
456 Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
458 gopts.var('extra', val="ARGS",
459 fn=set_value, default='',
460 use="Set extra arguments to append to the kernel command line.")
462 gopts.var('ip', val='IPADDR',
463 fn=set_value, default='',
464 use="Set the kernel IP interface address.")
466 gopts.var('gateway', val="IPADDR",
467 fn=set_value, default='',
468 use="Set the kernel IP gateway.")
470 gopts.var('netmask', val="MASK",
471 fn=set_value, default = '',
472 use="Set the kernel IP netmask.")
474 gopts.var('hostname', val="NAME",
475 fn=set_value, default='',
476 use="Set the kernel IP hostname.")
478 gopts.var('interface', val="INTF",
479 fn=set_value, default="eth0",
480 use="Set the kernel IP interface name.")
482 gopts.var('dhcp', val="off|dhcp",
483 fn=set_value, default='off',
484 use="Set the kernel dhcp option.")
486 gopts.var('nfs_server', val="IPADDR",
487 fn=set_value, default=None,
488 use="Set the address of the NFS server for NFS root.")
490 gopts.var('nfs_root', val="PATH",
491 fn=set_value, default=None,
492 use="Set the path of the root NFS directory.")
494 gopts.var('device_model', val='FILE',
495 fn=set_value, default=None,
496 use="Path to device model program.")
498 gopts.var('fda', val='FILE',
499 fn=set_value, default='',
500 use="Path to fda")
502 gopts.var('fdb', val='FILE',
503 fn=set_value, default='',
504 use="Path to fdb")
506 gopts.var('parallel', val='FILE',
507 fn=set_value, default='',
508 use="Path to parallel or pty or vc")
510 gopts.var('serial', val='FILE',
511 fn=set_value, default='',
512 use="Path to serial or pty or vc")
514 gopts.var('monitor', val='no|yes',
515 fn=set_bool, default=0,
516 use="""Should the device model use monitor?""")
518 gopts.var('monitor_path', val='FILE',
519 fn=set_value, default='',
520 use="Non-default path to device model monitor")
522 gopts.var('localtime', val='no|yes',
523 fn=set_bool, default=0,
524 use="Is RTC set to localtime?")
526 gopts.var('keymap', val='FILE',
527 fn=set_value, default='',
528 use="Set keyboard layout used")
530 gopts.var('usb', val='no|yes',
531 fn=set_bool, default=0,
532 use="Emulate USB devices?")
534 gopts.var('usbdevice', val='NAME',
535 fn=set_value, default='',
536 use="Name of USB device to add?")
538 gopts.var('description', val='NAME',
539 fn=set_value, default='',
540 use="Description of a domain")
542 gopts.var('guest_os_type', val='NAME',
543 fn=set_value, default='default',
544 use="Guest OS type running in HVM")
546 gopts.var('stdvga', val='no|yes',
547 fn=set_bool, default=0,
548 use="Use std vga or cirrhus logic graphics")
550 gopts.var('isa', val='no|yes',
551 fn=set_bool, default=0,
552 use="Simulate an ISA only system?")
554 gopts.var('boot', val="a|b|c|d",
555 fn=set_value, default='c',
556 use="Default boot device")
558 gopts.var('nographic', val='no|yes',
559 fn=set_bool, default=0,
560 use="Should device models use graphics?")
562 gopts.var('soundhw', val='audiodev',
563 fn=set_value, default='',
564 use="Should device models enable audio device?")
566 gopts.var('vnc', val='',
567 fn=set_value, default=None,
568 use="""Should the device model use VNC?""")
570 gopts.var('vncdisplay', val='',
571 fn=set_value, default=None,
572 use="""VNC display to use""")
574 gopts.var('vnclisten', val='',
575 fn=set_value, default=None,
576 use="""Address for VNC server to listen on.""")
578 gopts.var('vncunused', val='',
579 fn=set_bool, default=1,
580 use="""Try to find an unused port for the VNC server.
581 Only valid when vnc=1.""")
583 gopts.var('videoram', val='MEMORY',
584 fn=set_int, default=4,
585 use="""Maximum amount of videoram a guest can allocate
586 for frame buffer.""")
588 gopts.var('sdl', val='',
589 fn=set_value, default=None,
590 use="""Should the device model use SDL?""")
592 gopts.var('gfx_passthru', val='',
593 fn=set_value, default=None,
594 use="""Passthrough graphics card?""")
596 gopts.var('opengl', val='',
597 fn=set_value, default=None,
598 use="""Enable\Disable OpenGL""")
600 gopts.var('display', val='DISPLAY',
601 fn=set_value, default=None,
602 use="X11 display to use")
604 gopts.var('xauthority', val='XAUTHORITY',
605 fn=set_value, default=None,
606 use="X11 Authority to use")
608 gopts.var('uuid', val='',
609 fn=set_value, default=None,
610 use="""xenstore UUID (universally unique identifier) to use. One
611 will be randomly generated if this option is not set, just like MAC
612 addresses for virtual network interfaces. This must be a unique
613 value across the entire cluster.""")
615 gopts.var('on_xend_start', val='ignore|start',
616 fn=set_value, default='ignore',
617 use='Action to perform when xend starts')
619 gopts.var('on_xend_stop', val='ignore|shutdown|suspend',
620 fn=set_value, default="ignore",
621 use="""Behaviour when Xend stops:
622 - ignore: Domain continues to run;
623 - shutdown: Domain is shutdown;
624 - suspend: Domain is suspended;
625 """)
627 gopts.var('target', val='TARGET',
628 fn=set_int, default=0,
629 use="Set domain target.")
631 gopts.var('hap', val='HAP',
632 fn=set_int, default=1,
633 use="""Hap status (0=hap is disabled;
634 1=hap is enabled.""")
636 gopts.var('s3_integrity', val='TBOOT_MEMORY_PROTECT',
637 fn=set_int, default=1,
638 use="""Should domain memory integrity be verified during S3?
639 (0=protection is disabled; 1=protection is enabled.""")
641 gopts.var('oos', val='OOS',
642 fn=set_int, default=1,
643 use="""Should out-of-sync shadow page tabled be enabled?
644 (0=OOS is disabled; 1=OOS is enabled.""")
646 gopts.var('cpuid', val="IN[,SIN]:eax=EAX,ebx=EBX,ecx=ECX,edx=EDX",
647 fn=append_value, default=[],
648 use="""Cpuid description.""")
650 gopts.var('cpuid_check', val="IN[,SIN]:eax=EAX,ebx=EBX,ecx=ECX,edx=EDX",
651 fn=append_value, default=[],
652 use="""Cpuid check description.""")
654 gopts.var('machine_address_size', val='BITS',
655 fn=set_int, default=None,
656 use="""Maximum machine address size""")
658 gopts.var('suppress_spurious_page_faults', val='yes|no',
659 fn=set_bool, default=None,
660 use="""Do not inject spurious page faults into this guest""")
662 gopts.var('pool', val='POOL NAME',
663 fn=set_value, default=None,
664 use="""CPU pool to use for the VM""")
666 gopts.var('pci_msitranslate', val='TRANSLATE',
667 fn=set_int, default=1,
668 use="""Global PCI MSI-INTx translation flag (0=disable;
669 1=enable.""")
671 gopts.var('pci_power_mgmt', val='POWERMGMT',
672 fn=set_int, default=0,
673 use="""Global PCI Power Management flag (0=disable;1=enable).""")
675 gopts.var('xen_platform_pci', val='0|1',
676 fn=set_int, default=1,
677 use="Is xen_platform_pci used?")
679 gopts.var('superpages', val='0|1',
680 fn=set_int, default=0,
681 use="Create domain with superpages")
683 def err(msg):
684 """Print an error to stderr and exit.
685 """
686 print >>sys.stderr, "Error:", msg
687 sys.exit(1)
690 def warn(msg):
691 """Print a warning to stdout.
692 """
693 print >>sys.stderr, "Warning:", msg
696 def strip(pre, s):
697 """Strip prefix 'pre' if present.
698 """
699 if s.startswith(pre):
700 return s[len(pre):]
701 else:
702 return s
704 def configure_image(vals):
705 """Create the image config.
706 """
707 if not vals.builder:
708 return None
709 config_image = [ vals.builder ]
710 if vals.kernel:
711 if vals.bootloader:
712 # If bootloader is specified, vals.kernel will be used
713 # by bootloader when boots DomU. So it is needless to
714 # check the path is existent or not.
715 config_image.append([ 'kernel', vals.kernel ])
716 elif os.path.dirname(vals.kernel) != "" and os.path.exists(vals.kernel):
717 config_image.append([ 'kernel', vals.kernel ])
718 elif vals.kernel == 'hvmloader':
719 # Keep hvmloader w/o a path and let xend find it.
720 # This allows guest migration to a Dom0 having different
721 # xen install pathes.
722 config_image.append([ 'kernel', vals.kernel ])
723 elif os.path.exists(os.path.abspath(vals.kernel)):
724 # Keep old behaviour, if path is valid.
725 config_image.append([ 'kernel', os.path.abspath(vals.kernel) ])
726 else:
727 raise ValueError('Cannot find kernel "%s"' % vals.kernel)
728 if vals.ramdisk:
729 if vals.bootloader:
730 # Same with 'kernel' above
731 config_image.append([ 'ramdisk', vals.ramdisk ])
732 elif os.path.dirname(vals.ramdisk) != "" and os.path.exists(vals.ramdisk):
733 config_image.append([ 'ramdisk', vals.ramdisk ])
734 elif os.path.exists(os.path.abspath(vals.ramdisk)):
735 # Keep old behaviour, if path is valid.
736 config_image.append([ 'ramdisk', os.path.abspath(vals.ramdisk) ])
737 else:
738 raise ValueError('Cannot find ramdisk "%s"' % vals.ramdisk)
739 if vals.loader:
740 if os.path.dirname(vals.loader) != "" and os.path.exists(vals.loader):
741 config_image.append([ 'loader', vals.loader ])
742 elif vals.loader == 'hvmloader':
743 # Keep hvmloader w/o a path and let xend find it.
744 # This allows guest migration to a Dom0 having different
745 # xen install pathes.
746 config_image.append([ 'loader', vals.loader ])
747 elif os.path.exists(os.path.abspath(vals.loader)):
748 # Keep old behaviour, if path is valid.
749 config_image.append([ 'loader', os.path.abspath(vals.loader) ])
750 else:
751 raise ValueError('Cannot find loader "%s"' % vals.loader)
752 if vals.cmdline_ip:
753 cmdline_ip = strip('ip=', vals.cmdline_ip)
754 config_image.append(['ip', cmdline_ip])
755 if vals.root:
756 cmdline_root = strip('root=', vals.root)
757 config_image.append(['root', cmdline_root])
758 if vals.videoram:
759 config_image.append(['videoram', vals.videoram])
760 if vals.parallel:
761 config_image.append(['parallel', vals.parallel])
762 if vals.serial:
763 config_image.append(['serial', vals.serial])
764 if vals.monitor_path:
765 config_image.append(['monitor_path', vals.monitor_path])
766 config_image.append(['monitor', 1])
767 elif vals.monitor:
768 config_image.append(['monitor', vals.monitor])
769 if vals.extra:
770 config_image.append(['args', vals.extra])
771 if vals.superpages:
772 config_image.append(['superpages', vals.superpages])
774 if vals.builder == 'hvm':
775 configure_hvm(config_image, vals)
777 if vals.vhpt != 0:
778 config_image.append(['vhpt', vals.vhpt])
780 if vals.machine_address_size:
781 config_image.append(['machine_address_size', vals.machine_address_size])
783 if vals.suppress_spurious_page_faults:
784 config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults])
786 if vals.tsc_mode is not None:
787 config_image.append(['tsc_mode', vals.tsc_mode])
789 if vals.nomigrate is not None:
790 config_image.append(['nomigrate', vals.nomigrate])
792 return config_image
794 def configure_disks(config_devs, vals):
795 """Create the config for disks (virtual block devices).
796 """
797 for (uname, dev, mode, backend, protocol) in vals.disk:
798 if uname.startswith('tap2:'):
799 cls = 'tap2'
800 elif uname.startswith('tap:'):
801 cls = 'tap'
802 else:
803 cls = 'vbd'
805 config_vbd = [cls,
806 ['uname', uname],
807 ['dev', dev ],
808 ['mode', mode ] ]
809 if backend:
810 config_vbd.append(['backend', backend])
811 if protocol:
812 config_vbd.append(['protocol', protocol])
813 config_devs.append(['device', config_vbd])
815 def configure_pci(config_devs, vals):
816 """Create the config for pci devices.
817 """
818 config_pci = []
819 for pci_tuple in vals.pci:
820 pci_dev = pci_tuple_to_dict(pci_tuple)
821 config_pci.append(dev_dict_to_sxp(pci_dev))
823 if len(config_pci)>0:
824 config_pci.insert(0, 'pci')
825 config_devs.append(['device', config_pci])
827 def configure_vscsis(config_devs, vals):
828 """Create the config for vscsis (virtual scsi devices).
829 """
831 def get_devid(hctl):
832 return int(hctl.split(':')[0])
834 if len(vals.vscsi) == 0:
835 return 0
837 config_scsi = {}
838 pHCTL_list = []
839 vHCTL_list = []
841 scsi_devices = vscsi_util.vscsi_get_scsidevices()
842 for (p_dev, v_dev, backend) in vals.vscsi:
843 (p_hctl, devname) = \
844 vscsi_util.vscsi_get_hctl_and_devname_by(p_dev, scsi_devices)
846 if p_hctl == None:
847 raise ValueError('Cannot find device "%s"' % p_dev)
849 feature_host = 0
850 if v_dev == 'host':
851 feature_host = 1
852 scsi_info = []
853 devid = get_devid(p_hctl)
854 for (pHCTL, devname, _, _) in scsi_devices:
855 if get_devid(pHCTL) == devid:
856 scsi_info.append([devid, pHCTL, devname, pHCTL])
857 else:
858 scsi_info = [[get_devid(v_dev), p_hctl, devname, v_dev]]
860 devid_key = scsi_info[0][0]
861 try:
862 config = config_scsi[devid_key]
863 except KeyError:
864 config = {'feature-host': feature_host, 'backend': backend, 'devs': []}
866 devs = config['devs']
867 for (devid, pHCTL, devname, vHCTL) in scsi_info:
868 if pHCTL in pHCTL_list:
869 raise ValueError('The physical device "%s" is already defined' % pHCTL)
870 if vHCTL in vHCTL_list:
871 raise ValueError('The virtual device "%s" is already defined' % vHCTL)
872 pHCTL_list.append(pHCTL)
873 vHCTL_list.append(vHCTL)
874 devs.append(['dev', \
875 ['state', xenbusState['Initialising']], \
876 ['devid', devid], \
877 ['p-dev', pHCTL], \
878 ['p-devname', devname], \
879 ['v-dev', vHCTL] ])
881 if config['feature-host'] != feature_host:
882 raise ValueError('The physical device "%s" cannot define '
883 'because mode is different' % scsi_info[0][1])
884 if config['backend'] != backend:
885 raise ValueError('The physical device "%s" cannot define '
886 'because backend is different' % scsi_info[0][1])
888 config['devs'] = devs
889 config_scsi[devid_key] = config
891 for config in config_scsi.values():
892 device = ['vscsi', ['feature-host', config['feature-host']]]
893 for dev in config['devs']:
894 device.append(dev)
895 if config['backend']:
896 device.append(['backend', config['backend']])
897 config_devs.append(['device', device])
899 def configure_vusbs(config_devs, vals):
900 """Create the config for virtual usb host controllers.
901 """
902 for f in vals.vusb:
903 d = comma_sep_kv_to_dict(f)
904 config = ['vusb']
906 usbver = 2
907 if d.has_key('usbver'):
908 usbver = int(d['usbver'])
909 if usbver == 1 or usbver == 2:
910 config.append(['usb-ver', str(usbver)])
911 else:
912 err('Invalid vusb option: ' + 'usbver')
914 numports = 8
915 if d.has_key('numports'):
916 numports = d['numports']
917 if int(numports) < 1 or int(numports) > 16:
918 err('Invalid vusb option: ' + 'numports')
919 config.append(['num-ports', str(numports)])
921 port_config = []
922 for i in range(1, int(numports) + 1):
923 if d.has_key('port_%i' % i):
924 port_config.append(['%i' % i, str(d['port_%i' % i])])
925 else:
926 port_config.append(['%i' % i, ""])
927 port_config.insert(0, 'port')
928 config.append(port_config)
929 config_devs.append(['device', config])
931 def configure_ioports(config_devs, vals):
932 """Create the config for legacy i/o ranges.
933 """
934 for (io_from, io_to) in vals.ioports:
935 config_ioports = ['ioports', ['from', io_from], ['to', io_to]]
936 config_devs.append(['device', config_ioports])
938 def configure_irq(config_devs, vals):
939 """Create the config for irqs.
940 """
941 for irq in vals.irq:
942 config_irq = ['irq', ['irq', irq]]
943 config_devs.append(['device', config_irq])
945 def configure_vfbs(config_devs, vals):
946 for f in vals.vfb:
947 d = comma_sep_kv_to_dict(f)
948 config = ['vfb']
949 #handle the legacy case
950 if d.has_key("type"):
951 d[d['type']] = '1'
952 del d['type']
953 for (k,v) in d.iteritems():
954 if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
955 'videoram', 'xauthority', 'sdl', 'vnc', 'vncpasswd',
956 'opengl', 'keymap', 'serial', 'monitor' ]:
957 err("configuration option %s unknown to vfbs" % k)
958 config.append([k,v])
959 if not d.has_key("keymap"):
960 if vals.keymap:
961 config.append(['keymap',vals.keymap])
962 if not d.has_key("display") and os.environ.has_key("DISPLAY"):
963 config.append(["display", os.environ['DISPLAY']])
964 if not d.has_key("xauthority"):
965 config.append(["xauthority", get_xauthority()])
966 config_devs.append(['device', ['vkbd']])
967 config_devs.append(['device', config])
969 def configure_security(config, vals):
970 """Create the config for ACM security labels.
971 """
972 access_control = vals.access_control
973 num = len(access_control)
974 if num == 1:
975 d = access_control[0]
976 policy = d.get('policy')
977 label = d.get('label')
978 if policy != security.active_policy:
979 err("Security policy (" + policy + ") incompatible with enforced policy ("
980 + security.active_policy + ")." )
981 config_access_control = ['access_control',
982 ['policy', policy],
983 ['label', label] ]
985 security_label = ['security', [ config_access_control ] ]
986 config.append(security_label)
987 elif num > 1:
988 err("VM config error: Multiple access_control definitions!")
990 def configure_mem_prot(config_image, vals):
991 """Create the config for S3 memory integrity verification under tboot.
992 """
993 config_image.append(['s3_integrity', vals.s3_integrity])
995 def configure_vtpm(config_devs, vals):
996 """Create the config for virtual TPM interfaces.
997 """
998 vtpm = vals.vtpm
999 if len(vtpm) > 0:
1000 d = vtpm[0]
1001 instance = d.get('instance')
1002 uuid = d.get('uuid')
1003 if instance == "VTPMD":
1004 instance = "0"
1005 else:
1006 if instance != None:
1007 try:
1008 if int(instance) == 0:
1009 err('VM config error: vTPM instance must not be 0.')
1010 except ValueError:
1011 err('Vm config error: could not parse instance number.')
1012 backend = d.get('backend')
1013 typ = d.get('type')
1014 config_vtpm = ['vtpm']
1015 if instance:
1016 config_vtpm.append(['pref_instance', instance])
1017 if backend:
1018 config_vtpm.append(['backend', backend])
1019 if typ:
1020 config_vtpm.append(['type', typ])
1021 if uuid:
1022 config_vtpm.append(['uuid', uuid])
1023 config_devs.append(['device', config_vtpm])
1026 def configure_vifs(config_devs, vals):
1027 """Create the config for virtual network interfaces.
1028 """
1030 vifs = vals.vif
1031 vifs_n = len(vifs)
1032 vifs2 = vals.vif2
1033 vifs2_n = len(vifs2)
1035 if hasattr(vals, 'nics'):
1036 if vals.nics > 0:
1037 warn("The nics option is deprecated. Please use an empty vif "
1038 "entry instead:\n\n vif = [ '' ]\n")
1039 for _ in range(vifs_n, vals.nics):
1040 vifs.append('')
1041 vifs_n = len(vifs)
1042 elif vals.nics == 0:
1043 warn("The nics option is deprecated. Please remove it.")
1045 for c in vifs:
1046 d = comma_sep_kv_to_dict(c)
1047 config_vif = ['vif']
1049 def f(k):
1050 if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
1051 'vifname', 'rate', 'model', 'accel',
1052 'policy', 'label']:
1053 err('Invalid vif option: ' + k)
1055 config_vif.append([k, d[k]])
1057 map(f, d.keys())
1058 config_devs.append(['device', config_vif])
1060 for c in vifs2:
1061 d = comma_sep_kv_to_dict(c)
1062 config_vif = ['vif2']
1064 for k in d.keys():
1065 if k not in ['front_mac', 'back_mac', 'backend', 'trusted',
1066 'back_trusted', 'front_filter_mac', 'filter_mac',
1067 'bridge', 'pdev', 'max_bypasses' ]:
1068 err('Invalid vif2 option: ' + k)
1069 config_vif.append([k, d[k]])
1070 config_devs.append(['device', config_vif])
1073 def configure_hvm(config_image, vals):
1074 """Create the config for HVM devices.
1075 """
1076 args = [ 'acpi', 'apic',
1077 'boot',
1078 'cpuid', 'cpuid_check',
1079 'device_model', 'display',
1080 'fda', 'fdb',
1081 'gfx_passthru', 'guest_os_type',
1082 'hap', 'hpet',
1083 'isa',
1084 'keymap',
1085 'localtime',
1086 'nographic',
1087 'opengl', 'oos',
1088 'pae', 'pci', 'pci_msitranslate', 'pci_power_mgmt',
1089 'rtc_timeoffset',
1090 'sdl', 'soundhw', 'stdvga',
1091 'timer_mode',
1092 'usb', 'usbdevice',
1093 'vcpus', 'vnc', 'vncconsole', 'vncdisplay', 'vnclisten',
1094 'vncunused', 'viridian', 'vpt_align',
1095 'xauthority', 'xen_extended_power_mgmt', 'xen_platform_pci',
1096 'memory_sharing' ]
1098 for a in args:
1099 if a in vals.__dict__ and vals.__dict__[a] is not None:
1100 config_image.append([a, vals.__dict__[a]])
1101 if vals.vncpasswd is not None:
1102 config_image.append(['vncpasswd', vals.vncpasswd])
1105 def make_config(vals):
1106 """Create the domain configuration.
1107 """
1109 config = ['vm']
1111 def vcpu_conf():
1112 maxvcpus = False
1113 vcpus = False
1114 if hasattr(vals, 'maxvcpus'):
1115 maxvcpus = getattr(vals, 'maxvcpus')
1116 if hasattr(vals, 'vcpus'):
1117 vcpus = getattr(vals, 'vcpus')
1119 if maxvcpus and not vcpus:
1120 config.append(['vcpus', maxvcpus])
1121 if maxvcpus and vcpus:
1122 config.append(['vcpu_avail', (1 << vcpus) - 1])
1123 config.append(['vcpus', maxvcpus])
1125 # For case we don't have maxvcpus set but we have vcpus we preserve
1126 # old behaviour
1127 if not maxvcpus and vcpus:
1128 config.append(['vcpus', vcpus])
1130 def add_conf(n):
1131 if hasattr(vals, n):
1132 v = getattr(vals, n)
1133 if v:
1134 config.append([n, v])
1136 map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
1137 'restart', 'on_poweroff', 'tsc_mode', 'nomigrate',
1138 'on_reboot', 'on_crash', 'features', 'on_xend_start',
1139 'on_xend_stop', 'target', 'cpuid', 'cpuid_check',
1140 'machine_address_size', 'suppress_spurious_page_faults',
1141 'description'])
1143 vcpu_conf()
1144 if vals.uuid is not None:
1145 config.append(['uuid', vals.uuid])
1146 if vals.cpu is not None:
1147 config.append(['cpu', vals.cpu])
1148 if vals.cpus is not None:
1149 config.append(['cpus', vals.cpus])
1150 if vals.cpu_cap is not None:
1151 config.append(['cpu_cap', vals.cpu_cap])
1152 if vals.cpu_weight is not None:
1153 config.append(['cpu_weight', vals.cpu_weight])
1154 if vals.blkif:
1155 config.append(['backend', ['blkif']])
1156 if vals.netif:
1157 config.append(['backend', ['netif']])
1158 if vals.tpmif:
1159 config.append(['backend', ['tpmif']])
1160 if vals.localtime:
1161 config.append(['localtime', vals.localtime])
1162 if vals.oos:
1163 config.append(['oos', vals.oos])
1164 if vals.pool:
1165 config.append(['pool_name', vals.pool])
1167 config_image = configure_image(vals)
1168 if vals.bootloader:
1169 if vals.bootloader == "pygrub":
1170 vals.bootloader = auxbin.pathTo(vals.bootloader)
1172 config.append(['bootloader', vals.bootloader])
1173 if vals.bootargs:
1174 config.append(['bootloader_args', vals.bootargs])
1175 else:
1176 if vals.console_autoconnect:
1177 config.append(['bootloader_args', ''])
1178 else:
1179 config.append(['bootloader_args', '-q'])
1180 config.append(['image', config_image])
1181 configure_mem_prot(config, vals);
1183 config_devs = []
1184 configure_disks(config_devs, vals)
1185 configure_pci(config_devs, vals)
1186 configure_vscsis(config_devs, vals)
1187 configure_vusbs(config_devs, vals)
1188 configure_ioports(config_devs, vals)
1189 configure_irq(config_devs, vals)
1190 configure_vifs(config_devs, vals)
1191 configure_vtpm(config_devs, vals)
1192 configure_vfbs(config_devs, vals)
1193 configure_security(config, vals)
1194 config += config_devs
1196 return config
1198 def preprocess_disk(vals):
1199 if not vals.disk: return
1200 disk = []
1201 for v in vals.disk:
1202 d = v.split(',')
1203 n = len(d)
1204 if n == 3:
1205 d.append(None)
1206 d.append(None)
1207 elif n == 4:
1208 d.append(None)
1209 elif n == 5:
1210 pass
1211 else:
1212 err('Invalid disk specifier: ' + v)
1213 disk.append(d)
1214 vals.disk = disk
1216 def preprocess_cpuid(vals, attr_name):
1217 if not vals.cpuid: return
1218 cpuid = {}
1219 for cpuid_input in getattr(vals, attr_name):
1220 input_re = "(0x)?[0-9A-Fa-f]+(,(0x)?[0-9A-Fa-f]+)?"
1221 cpuid_match = re.match(r'(?P<input>%s):(?P<regs>.*)' % \
1222 input_re, cpuid_input)
1223 if cpuid_match != None:
1224 res_cpuid = cpuid_match.groupdict()
1225 input = res_cpuid['input']
1226 regs = res_cpuid['regs'].split(',')
1227 cpuid[input]= {} # New input
1228 for reg in regs:
1229 reg_match = re.match(r"(?P<reg>eax|ebx|ecx|edx)=(?P<val>.*)", reg)
1230 if reg_match == None:
1231 err("cpuid's syntax is (eax|ebx|ecx|edx)=value")
1232 res = reg_match.groupdict()
1233 if (res['val'][:2] != '0x' and len(res['val']) != 32):
1234 err("cpuid: We should specify all the bits " \
1235 "of the register %s for input %s\n"
1236 % (res['reg'], input) )
1237 cpuid[input][res['reg']] = res['val'] # new register
1238 setattr(vals, attr_name, cpuid)
1240 def pci_dict_to_tuple(dev):
1241 return (dev['domain'], dev['bus'], dev['slot'], dev['func'],
1242 dev['vdevfn'], dev.get('opts', []), dev['key'])
1244 def pci_tuple_to_dict((domain, bus, slot, func, vdevfn, opts, key)):
1245 pci_dev = { 'domain': domain,
1246 'bus': bus,
1247 'slot': slot,
1248 'func': func,
1249 'vdevfn': vdevfn,
1250 'key': key}
1251 if len(opts) > 0:
1252 pci_dev['opts'] = opts
1253 return pci_dev
1255 def preprocess_pci(vals):
1256 if not vals.pci:
1257 return
1258 try:
1259 vals.pci = map(pci_dict_to_tuple, reduce(lambda x, y: x + y,
1260 map(parse_pci_name_extended, vals.pci)))
1261 except PciDeviceParseError, ex:
1262 err(str(ex))
1264 def preprocess_vscsi(vals):
1265 if not vals.vscsi: return
1266 scsi = []
1267 for scsi_str in vals.vscsi:
1268 d = [tmp.strip() for tmp in scsi_str.split(',')]
1269 n = len(d)
1270 if n == 2:
1271 tmp = d[1].split(':')
1272 if d[1] != 'host' and len(tmp) != 4:
1273 err('vscsi syntax error "%s"' % d[1])
1274 else:
1275 d.append(None)
1276 elif n == 3:
1277 pass
1278 else:
1279 err('vscsi syntax error "%s"' % scsi_str)
1280 scsi.append(d)
1281 vals.vscsi = scsi
1283 def preprocess_ioports(vals):
1284 if not vals.ioports: return
1285 ioports = []
1286 for v in vals.ioports:
1287 d = v.split('-')
1288 if len(d) < 1 or len(d) > 2:
1289 err('Invalid i/o port range specifier: ' + v)
1290 if len(d) == 1:
1291 d.append(d[0])
1292 # Components are in hex: add hex specifier.
1293 hexd = ['0x' + x for x in d]
1294 ioports.append(hexd)
1295 vals.ioports = ioports
1297 def preprocess_irq(vals):
1298 if not vals.irq: return
1299 irq = []
1300 for v in vals.irq:
1301 d = repr(v)
1302 irq.append(d)
1303 vals.irq = irq
1305 def preprocess_vtpm(vals):
1306 if not vals.vtpm: return
1307 vtpms = []
1308 for vtpm in vals.vtpm:
1309 d = {}
1310 a = vtpm.split(',')
1311 for b in a:
1312 (k, v) = b.strip().split('=', 1)
1313 k = k.strip()
1314 v = v.strip()
1315 if k not in ['backend', 'instance', 'uuid']:
1316 err('Invalid vtpm specifier: ' + vtpm)
1317 d[k] = v
1318 vtpms.append(d)
1319 vals.vtpm = vtpms
1321 def preprocess_access_control(vals):
1322 if not vals.access_control:
1323 return
1324 access_controls = []
1325 num = len(vals.access_control)
1326 if num == 1:
1327 access_control = (vals.access_control)[0]
1328 acc_re = 'policy=(?P<policy>.*),label=(?P<label>.*)'
1329 acc_match = re.match(acc_re,access_control)
1330 if acc_match == None:
1331 err('Invalid access_control specifier: ' + access_control)
1332 d = acc_match.groupdict();
1333 access_controls.append(d)
1334 vals.access_control = access_controls
1335 elif num > 1:
1336 err('Multiple access_control definitions.')
1338 def preprocess_ip(vals):
1339 if vals.ip or vals.dhcp != 'off':
1340 dummy_nfs_server = '127.0.255.255'
1341 ip = (vals.ip
1342 + ':' + (vals.nfs_server or dummy_nfs_server)
1343 + ':' + vals.gateway
1344 + ':' + vals.netmask
1345 + ':' + vals.hostname
1346 + ':' + vals.interface
1347 + ':' + vals.dhcp)
1348 else:
1349 ip = ''
1350 vals.cmdline_ip = ip
1352 def preprocess_nfs(vals):
1353 if not vals.nfs_root: return
1354 if not vals.nfs_server:
1355 err('Must set nfs root and nfs server')
1356 nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
1357 vals.extra = nfs + ' ' + vals.extra
1360 def get_host_addr():
1361 host = socket.gethostname()
1362 addr = socket.gethostbyname(host)
1363 return addr
1365 VNC_BASE_PORT = 5500
1367 def choose_vnc_display():
1368 """Try to choose a free vnc display.
1369 """
1370 def netstat_local_ports():
1371 """Run netstat to get a list of the local ports in use.
1372 """
1373 l = os.popen("netstat -nat").readlines()
1374 r = []
1375 # Skip 2 lines of header.
1376 for x in l[2:]:
1377 # Local port is field 3.
1378 y = x.split()[3]
1379 # Field is addr:port, split off the port.
1380 y = y.split(':')[-1]
1381 r.append(int(y))
1382 return r
1384 ports = netstat_local_ports()
1385 for d in range(1, 100):
1386 port = VNC_BASE_PORT + d
1387 if port in ports: continue
1388 return d
1389 return None
1391 def preprocess(vals):
1392 preprocess_disk(vals)
1393 preprocess_pci(vals)
1394 preprocess_vscsi(vals)
1395 preprocess_ioports(vals)
1396 preprocess_ip(vals)
1397 preprocess_irq(vals)
1398 preprocess_nfs(vals)
1399 preprocess_vtpm(vals)
1400 preprocess_access_control(vals)
1401 preprocess_cpuid(vals, 'cpuid')
1402 preprocess_cpuid(vals, 'cpuid_check')
1405 def comma_sep_kv_to_dict(c):
1406 """Convert comma-separated, equals-separated key-value pairs into a
1407 dictionary.
1408 """
1409 d = {}
1410 c = c.strip()
1411 if len(c) > 0:
1412 a = c.split(',')
1413 for b in a:
1414 if b.find('=') == -1:
1415 err("%s should be a pair, separated by an equals sign." % b)
1416 (k, v) = b.split('=', 1)
1417 k = k.strip()
1418 v = v.strip()
1419 d[k] = v
1420 return d
1423 def make_domain(opts, config):
1424 """Create, build and start a domain.
1426 @param opts: options
1427 @param config: configuration
1428 @return: domain id
1429 @rtype: int
1430 """
1432 try:
1433 dominfo = server.xend.domain.create(config)
1434 except xmlrpclib.Fault, ex:
1435 if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN:
1436 err("the domain '%s' does not exist." % ex.faultString)
1437 else:
1438 err("%s" % ex.faultString)
1440 dom = sxp.child_value(dominfo, 'name')
1442 try:
1443 server.xend.domain.waitForDevices(dom)
1444 except xmlrpclib.Fault, ex:
1445 server.xend.domain.destroy(dom)
1446 err("%s" % ex.faultString)
1447 except:
1448 server.xend.domain.destroy(dom)
1449 err("Device creation failed for domain %s" % dom)
1451 if not opts.vals.paused:
1452 try:
1453 server.xend.domain.unpause(dom)
1454 except:
1455 server.xend.domain.destroy(dom)
1456 err("Failed to unpause domain %s" % dom)
1457 domid = int(sxp.child_value(dominfo, 'domid'))
1458 opts.info("Started domain %s (id=%d)" % (dom, domid))
1459 return domid
1462 def get_xauthority():
1463 xauth = os.getenv("XAUTHORITY")
1464 if not xauth:
1465 home = os.getenv("HOME")
1466 if not home:
1467 import posix, pwd
1468 home = pwd.getpwuid(posix.getuid())[5]
1469 xauth = home + "/.Xauthority"
1470 return xauth
1473 def parseCommandLine(argv):
1474 gopts.reset()
1475 args = gopts.parse(argv)
1477 if gopts.vals.help or gopts.vals.help_config:
1478 if gopts.vals.help_config:
1479 print gopts.val_usage()
1480 return (None, None)
1482 if not gopts.vals.display:
1483 gopts.vals.display = os.getenv("DISPLAY")
1485 if not gopts.vals.xauthority:
1486 gopts.vals.xauthority = get_xauthority()
1488 gopts.is_xml = False
1490 # Process remaining args as config variables.
1491 for arg in args:
1492 if '=' in arg:
1493 (var, val) = arg.strip().split('=', 1)
1494 gopts.setvar(var.strip(), val.strip())
1495 if gopts.vals.config:
1496 config = gopts.vals.config
1497 else:
1498 try:
1499 gopts.load_defconfig()
1500 preprocess(gopts.vals)
1501 if not gopts.getopt('name') and gopts.getopt('defconfig'):
1502 gopts.setopt('name', os.path.basename(gopts.getopt('defconfig')))
1503 config = make_config(gopts.vals)
1504 except XMLFileError, ex:
1505 XMLFile = ex.getFile()
1506 gopts.is_xml = True
1507 config = ex.getFile()
1509 return (gopts, config)
1511 def help():
1512 return str(gopts)
1514 def main(argv):
1515 is_xml = False
1517 try:
1518 (opts, config) = parseCommandLine(argv)
1519 except StandardError, ex:
1520 err(str(ex))
1522 if not opts:
1523 return
1525 if not opts.is_xml:
1526 if type(config) == str:
1527 try:
1528 config = sxp.parse(file(config))[0]
1529 except IOError, exn:
1530 raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
1532 if serverType == SERVER_XEN_API:
1533 from xen.xm.xenapi_create import sxp2xml
1534 sxp2xml_inst = sxp2xml()
1535 doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
1537 if opts.vals.dryrun and not opts.is_xml:
1538 SXPPrettyPrint.prettyprint(config)
1540 if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
1541 from xml.dom.ext import PrettyPrint as XMLPrettyPrint
1542 XMLPrettyPrint(doc)
1544 if opts.vals.dryrun or opts.vals.xmldryrun:
1545 return
1547 if opts.vals.console_autoconnect:
1548 do_console(sxp.child_value(config, 'name', -1))
1550 if serverType == SERVER_XEN_API:
1551 from xen.xm.xenapi_create import xenapi_create
1552 xenapi_create_inst = xenapi_create()
1553 if opts.is_xml:
1554 vm_refs = xenapi_create_inst.create(filename = config,
1555 skipdtd = opts.vals.skipdtd)
1556 else:
1557 vm_refs = xenapi_create_inst.create(document = doc,
1558 skipdtd = opts.vals.skipdtd)
1560 map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
1561 elif not opts.is_xml:
1562 dom = make_domain(opts, config)
1564 if opts.vals.vncconsole:
1565 domid = domain_name_to_domid(sxp.child_value(config, 'name', -1))
1566 vncviewer_autopass = getattr(opts.vals,'vncviewer-autopass', False)
1567 console.runVncViewer(domid, vncviewer_autopass, True)
1569 def do_console(domain_name):
1570 cpid = os.fork()
1571 if cpid != 0:
1572 for i in range(10):
1573 # Catch failure of the create process
1574 time.sleep(1)
1575 try:
1576 (p, rv) = os.waitpid(cpid, os.WNOHANG)
1577 except OSError:
1578 # Domain has started cleanly and then exiting,
1579 # the child process used to do this has detached
1580 print("Domain has already finished");
1581 break
1582 if os.WIFEXITED(rv):
1583 if os.WEXITSTATUS(rv) != 0:
1584 sys.exit(os.WEXITSTATUS(rv))
1585 try:
1586 domid = domain_name_to_domid(domain_name)
1587 console.execConsole(domid)
1588 except:
1589 pass
1590 print("Could not start console\n");
1591 sys.exit(0)
1593 if __name__ == '__main__':
1594 main(sys.argv)