aboutsummaryrefslogtreecommitdiffstats
path: root/tools/python/xen/xm/create.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/python/xen/xm/create.py')
-rw-r--r--tools/python/xen/xm/create.py366
1 files changed, 366 insertions, 0 deletions
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
new file mode 100644
index 0000000000..12e2e8010c
--- /dev/null
+++ b/tools/python/xen/xm/create.py
@@ -0,0 +1,366 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Domain creation.
+"""
+import string
+import sys
+
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+from xen.xend.XendClient import server
+
+from xen.xm.opts import *
+
+gopts = Opts(use="""[options]
+
+Create a domain.
+""")
+
+gopts.opt('help', short='h',
+ fn=set_true, default=0,
+ use="Print this help.")
+
+gopts.opt('quiet', short='q',
+ fn=set_true, default=0,
+ use="Quiet.")
+
+gopts.opt('path', val='PATH',
+ fn=set_value, default='.:/etc/xen',
+ use="Search path for default scripts.")
+
+gopts.opt('defaults', short='f', val='FILE',
+ fn=set_value, default='xmdefaults',
+ use="Use the given default script.")
+
+gopts.opt('config', short='F', val='FILE',
+ fn=set_value, default=None,
+ use='Domain configuration to use (SXP).')
+
+gopts.opt('load', short='L', val='FILE',
+ fn=set_value, default=None,
+ use='Domain saved state to load.')
+
+gopts.opt('define', short='D', val='VAR=VAL',
+ fn=set_var, default=None,
+ use="""Set a variable before loading defaults, e.g. '-D vmid=3'
+ to set vmid. May be repeated to set more thanone variable.""")
+
+gopts.opt('dryrun', short='n',
+ fn=set_true, default=0,
+ use="Dry run - print the config but don't create the domain.")
+
+gopts.opt('name', short='N', val='NAME',
+ fn=set_value, default=None,
+ use="Domain name.")
+
+gopts.opt('console', short='c',
+ fn=set_true, default=0,
+ use="Connect to console after domain is created.")
+
+gopts.opt('kernel', short='k', val='FILE',
+ fn=set_value, default=None,
+ use="Path to kernel image.")
+
+gopts.opt('ramdisk', short='r', val='FILE',
+ fn=set_value, default='',
+ use="Path to ramdisk.")
+
+gopts.opt('builder', short='b', val='FUNCTION',
+ fn=set_value, default='linux',
+ use="Function to use to build the domain.")
+
+gopts.opt('memory', short='m', val='MEMORY',
+ fn=set_value, default=128,
+ use="Domain memory in MB.")
+
+gopts.opt('blkif',
+ fn=set_true, default=0,
+ use="Make the domain a block device backend.")
+
+gopts.opt('netif',
+ fn=set_true, default=0,
+ use="Make the domain a network interface backend.")
+
+gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
+ fn=append_value, default=[],
+ use="""Add a disk device to a domain. The physical device is DEV, which
+ is exported to the domain as VDEV. The disk is read-only if MODE
+ is 'r', read-write if MODE is 'w'.
+ The option may be repeated to add more than one disk.
+ """)
+
+gopts.opt('pci', val='BUS,DEV,FUNC',
+ fn=append_value, default=[],
+ use="""Add a PCI device to a domain, using given params (in hex).
+ For example '-pci c0,02,1a'.
+ The option may be repeated to add more than one pci device.
+ """)
+
+gopts.opt('ipaddr', short='i', val="IPADDR",
+ fn=append_value, default=[],
+ use="Add an IP address to the domain.")
+
+gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
+ fn=append_value, default=[],
+ use="""Add a network interface with the given MAC address and bridge.
+ If mac is not specified a random MAC address is used.
+ If bridge is not specified the default bridge is used.
+ This option may be repeated to add more than one vif.
+ Specifying vifs will increase the number of interfaces as needed.
+ """)
+
+gopts.opt('nics', val="NUM",
+ fn=set_int, default=1,
+ use="""Set the number of network interfaces.
+ Use the vif option to define interface parameters, otherwise
+ defaults are used. Specifying vifs will increase the
+ number of interfaces as needed.
+ """)
+
+gopts.opt('root', short='R', val='DEVICE',
+ fn=set_value, default='',
+ use="""Set the root= parameter on the kernel command line.
+ Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
+
+gopts.opt('extra', short='E', val="ARGS",
+ fn=set_value, default='',
+ use="Set extra arguments to append to the kernel command line.")
+
+gopts.opt('ip', short='I', val='IPADDR',
+ fn=set_value, default='',
+ use="Set the kernel IP interface address.")
+
+gopts.opt('gateway', val="IPADDR",
+ fn=set_value, default='',
+ use="Set the kernel IP gateway.")
+
+gopts.opt('netmask', val="MASK",
+ fn=set_value, default = '',
+ use="Set the kernel IP netmask.")
+
+gopts.opt('hostname', val="NAME",
+ fn=set_value, default='',
+ use="Set the kernel IP hostname.")
+
+gopts.opt('interface', val="INTF",
+ fn=set_value, default="eth0",
+ use="Set the kernel IP interface name.")
+
+gopts.opt('dhcp', val="off|dhcp",
+ fn=set_value, default='off',
+ use="Set the kernel dhcp option.")
+
+gopts.opt('nfs_server', val="IPADDR",
+ fn=set_value, default=None,
+ use="Set the address of the NFS server for NFS root.")
+
+gopts.opt('nfs_root', val="PATH",
+ fn=set_value, default=None,
+ use="Set the path of the root NFS directory.")
+
+def strip(pre, s):
+ """Strip prefix 'pre' if present.
+ """
+ if s.startswith(pre):
+ return s[len(pre):]
+ else:
+ return s
+
+def configure_image(config, opts):
+ """Create the image config.
+ """
+ config_image = [ opts.builder ]
+ config_image.append([ 'kernel', os.path.abspath(opts.kernel) ])
+ if opts.ramdisk:
+ config_image.append([ 'ramdisk', os.path.abspath(opts.ramdisk) ])
+ if opts.cmdline_ip:
+ cmdline_ip = strip('ip=', opts.cmdline_ip)
+ config_image.append(['ip', cmdline_ip])
+ if opts.root:
+ cmdline_root = strip('root=', opts.root)
+ config_image.append(['root', cmdline_root])
+ if opts.extra:
+ config_image.append(['args', opts.extra])
+ config.append(['image', config_image ])
+
+def configure_disks(config_devs, opts):
+ """Create the config for disks (virtual block devices).
+ """
+ for (uname, dev, mode) in opts.disk:
+ config_vbd = ['vbd',
+ ['uname', uname],
+ ['dev', dev ],
+ ['mode', mode ] ]
+ config_devs.append(['device', config_vbd])
+
+def configure_pci(config_devs, opts):
+ """Create the config for pci devices.
+ """
+ for (bus, dev, func) in opts.pci:
+ config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
+ config_devs.append(['device', config_pci])
+
+def configure_vifs(config_devs, opts):
+ """Create the config for virtual network interfaces.
+ """
+ vifs = opts.vif
+ vifs_n = max(opts.nics, len(vifs))
+
+ for idx in range(0, vifs_n):
+ if idx < len(vifs):
+ d = vifs[idx]
+ mac = d.get('mac')
+ bridge = d.get('bridge')
+ else:
+ mac = None
+ bridge = None
+ config_vif = ['vif']
+ if mac:
+ config_vif.append(['mac', mac])
+ if bridge:
+ config_vif.append(['bridge', bridge])
+ config_devs.append(['device', config_vif])
+
+def configure_vfr(config, opts):
+ if not opts.ipaddr: return
+ config_vfr = ['vfr']
+ idx = 0 # No way of saying which IP is for which vif?
+ for ip in opts.ipaddr:
+ config_vfr.append(['vif', ['id', idx], ['ip', ip]])
+ config.append(config_vfr)
+
+
+def make_config(opts):
+ """Create the domain configuration.
+ """
+
+ config = ['vm',
+ ['name', opts.name ],
+ ['memory', opts.memory ] ]
+ if opts.cpu:
+ config.append(['cpu', opts.cpu])
+ if opts.blkif:
+ config.append(['backend', ['blkif']])
+ if opts.netif:
+ config.append(['backend', ['netif']])
+
+ configure_image(config, opts)
+ config_devs = []
+ configure_disks(config_devs, opts)
+ configure_pci(config_devs, opts)
+ configure_vifs(config_devs, opts)
+ config += config_devs
+ return config
+
+def preprocess_disk(opts):
+ if not opts.disk: return
+ disk = []
+ for v in opts.disk:
+ d = v.split(',')
+ if len(d) != 3:
+ opts.err('Invalid disk specifier: ' + v)
+ disk.append(d)
+ opts.disk = disk
+
+def preprocess_pci(opts):
+ if not opts.pci: return
+ pci = []
+ for v in opts.pci:
+ d = v.split(',')
+ if len(d) != 3:
+ opts.err('Invalid pci specifier: ' + v)
+ # Components are in hex: add hex specifier.
+ hexd = map(lambda v: '0x'+v, d)
+ pci.append(hexd)
+ opts.pci = pci
+
+def preprocess_vifs(opts):
+ if not opts.vif: return
+ vifs = []
+ for vif in opts.vif:
+ d = {}
+ a = vif.split(',')
+ for b in a:
+ (k, v) = b.strip().split('=')
+ k = k.strip()
+ v = v.strip()
+ if k not in ['mac', 'bridge']:
+ opts.err('Invalid vif specifier: ' + vif)
+ d[k] = v
+ vifs.append(d)
+ opts.vif = vifs
+
+def preprocess_ip(opts):
+ setip = (opts.hostname or opts.netmask
+ or opts.gateway or opts.dhcp or opts.interface)
+ if not setip: return
+ #if not opts
+ ip = (opts.ip
+ + ':'
+ + ':' + opts.gateway
+ + ':' + opts.netmask
+ + ':' + opts.hostname
+ + ':' + opts.interface
+ + ':' + opts.dhcp)
+ opts.cmdline_ip = ip
+
+def preprocess_nfs(opts):
+ if (opts.nfs_root or opts.nfs_server):
+ if (not opts.nfs_root) or (not opts.nfs_server):
+ opts.err('Must set nfs root and nfs server')
+ else:
+ return
+ nfs = 'nfsroot=' + opts.nfs_server + ':' + opts.nfs_root
+ opts.extra = nfs + ' ' + opts.extra
+
+def preprocess(opts):
+ if not opts.kernel:
+ opts.err("No kernel specified")
+ preprocess_disk(opts)
+ preprocess_pci(opts)
+ preprocess_vifs(opts)
+ preprocess_ip(opts)
+ preprocess_nfs(opts)
+
+def make_domain(opts, config):
+ """Create, build and start a domain.
+ Returns: [int] the ID of the new domain.
+ """
+ if opts.vals.load:
+ filename = os.path.abspath(opts.vals.load)
+ dominfo = server.xend_domain_restore(filename, config)
+ else:
+ dominfo = server.xend_domain_create(config)
+
+ dom = int(sxp.child_value(dominfo, 'id'))
+ console_info = sxp.child(dominfo, 'console')
+ if console_info:
+ console_port = int(sxp.child_value(console_info, 'port'))
+ else:
+ console_port = None
+
+ if server.xend_domain_unpause(dom) < 0:
+ server.xend_domain_destroy(dom)
+ opts.err("Failed to start domain %d" % dom)
+ opts.info("Started domain %d, console on port %d"
+ % (dom, console_port))
+ return (dom, console_port)
+
+def main(argv):
+ opts = gopts
+ args = opts.parse(argv)
+ if opts.vals.help:
+ opts.usage()
+ return
+ if opts.vals.config:
+ pass
+ else:
+ opts.load_defaults()
+ preprocess(opts.vals)
+ config = make_config(opts.vals)
+ if opts.vals.dryrun:
+ PrettyPrint.prettyprint(config)
+ else:
+ make_domain(opts, config)
+
+if __name__ == '__main__':
+ main(sys.argv)