diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/xenmgr/lib/EventServer.py | 3 | ||||
-rw-r--r-- | tools/xenmgr/lib/XendClient.py | 29 | ||||
-rw-r--r-- | tools/xenmgr/lib/XendConsole.py | 2 | ||||
-rw-r--r-- | tools/xenmgr/lib/XendDomain.py | 61 | ||||
-rw-r--r-- | tools/xenmgr/lib/XendDomainInfo.py | 56 | ||||
-rw-r--r-- | tools/xenmgr/lib/server/SrvConsoleServer.py | 50 | ||||
-rwxr-xr-x | tools/xenmgr/lib/server/blkif.py | 28 | ||||
-rwxr-xr-x | tools/xenmgr/lib/server/controller.py | 4 | ||||
-rw-r--r-- | tools/xenmgr/lib/server/messages.py | 28 | ||||
-rwxr-xr-x | tools/xenmgr/lib/server/netif.py | 13 | ||||
-rw-r--r-- | tools/xenmgr/lib/xm/create.py | 71 | ||||
-rw-r--r-- | tools/xenmgr/lib/xm/main.py | 81 | ||||
-rw-r--r-- | tools/xenmgr/lib/xm/opts.py | 1 | ||||
-rw-r--r-- | tools/xenmgr/lib/xm/shutdown.py | 11 | ||||
-rw-r--r-- | tools/xenmgr/netfix | 5 |
15 files changed, 262 insertions, 181 deletions
diff --git a/tools/xenmgr/lib/EventServer.py b/tools/xenmgr/lib/EventServer.py index 9749e119fb..6fae2b9ccf 100644 --- a/tools/xenmgr/lib/EventServer.py +++ b/tools/xenmgr/lib/EventServer.py @@ -85,7 +85,8 @@ class EventServer: hl = self.handlers.get(event) if hl is None: return - hl.remove(handler) + if handler in hl: + hl.remove(handler) def inject(self, event, val): """Inject an event. Handlers for it are called if runing, otherwise diff --git a/tools/xenmgr/lib/XendClient.py b/tools/xenmgr/lib/XendClient.py index 76f49f49bd..7eec62290f 100644 --- a/tools/xenmgr/lib/XendClient.py +++ b/tools/xenmgr/lib/XendClient.py @@ -244,29 +244,12 @@ class Xend: return xend_get(self.domainurl(id), { 'op' : 'vifs' }) - def xend_domain_vif_stats(self, id, vif): - return xend_get(self.domainurl(id), - { 'op' : 'vif_stats', - 'vif' : vif}) - def xend_domain_vif_ip_add(self, id, vif, ipaddr): return xend_call(self.domainurl(id), {'op' : 'vif_ip_add', 'vif' : vif, 'ip' : ipaddr }) - def xend_domain_vif_scheduler_set(id, vif, bytes, usecs): - return xend_call(self.domainurl(id), - {'op' : 'vif_scheduler_set', - 'vif' : vif, - 'bytes' : bytes, - 'usecs' : usecs }) - - def xend_domain_vif_scheduler_get(id, vif): - return xend_get(self.domainurl(id), - {'op' : 'vif_scheduler_get', - 'vif' : vif}) - def xend_domain_vbds(self, id): return xend_get(self.domainurl(id), {'op' : 'vbds'}) @@ -276,18 +259,6 @@ class Xend: {'op' : 'vbd', 'vbd' : vbd}) -## def xend_domain_vbd_add(self, id, uname, dev, mode): -## return xend_call(self.domainurl(id), -## {'op' : 'vbd_add', -## 'uname' : uname, -## 'dev' : dev, -## 'mode' : mode}) - -## def xend_domain_vbd_remove(self, id, dev): -## return xend_call(self.domainurl(id), -## {'op' : 'vbd_remove', -## 'dev' : dev}) - def xend_consoles(self): return xend_get(self.consoleurl()) diff --git a/tools/xenmgr/lib/XendConsole.py b/tools/xenmgr/lib/XendConsole.py index 041e6c4d44..19ad7eeae3 100644 --- a/tools/xenmgr/lib/XendConsole.py +++ b/tools/xenmgr/lib/XendConsole.py @@ -104,8 +104,10 @@ class XendConsole: self._delete_console(c.id) def onDomainDied(self, event, val): + print 'onDomainDied', "dom=", dom, dom = int(val) for c in self.consoles(): + print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2 if (c.dom1 == dom) or (c.dom2 == dom): self._delete_console(c.id) diff --git a/tools/xenmgr/lib/XendDomain.py b/tools/xenmgr/lib/XendDomain.py index 94afe3e87d..9ed3c6370d 100644 --- a/tools/xenmgr/lib/XendDomain.py +++ b/tools/xenmgr/lib/XendDomain.py @@ -18,6 +18,9 @@ import XendDomainInfo import XendConsole import EventServer +from xenmgr.server import SrvConsoleServer +xend = SrvConsoleServer.instance() + eserver = EventServer.instance() __all__ = [ "XendDomain" ] @@ -49,15 +52,16 @@ class XendDomain: def initial_refresh(self): """Refresh initial domain info from domain_db. """ - print "initial_refresh> db=", self.domain_db.values() + print "initial_refresh>" + for d in self.domain_db.values(): print 'db dom=', d domlist = xc.domain_getinfo() - print "doms=", domlist + for d in domlist: print 'xc dom=', d doms = {} for d in domlist: domid = str(d['dom']) doms[domid] = d for config in self.domain_db.values(): - domid = int(sxp.child_value(config, 'id')) + domid = str(sxp.child_value(config, 'id')) print "dom=", domid, "config=", config if domid in doms: print "dom=", domid, "new" @@ -141,7 +145,7 @@ class XendDomain: config = None image = None newinfo = XendDomainInfo.XendDomainInfo( - config, d['dom'], d['name'], d['mem_kb']/1024, image) + config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d) self._add_domain(newinfo.id, newinfo) # Remove entries for domains that no longer exist. for d in self.domain.values(): @@ -193,13 +197,13 @@ class XendDomain: """ dom = int(id) eserver.inject('xend.domain.start', id) - return xc.domain_start(dom=dom) + return xend.domain_start(dom) def domain_stop(self, id): """Stop domain running. """ dom = int(id) - return xc.domain_stop(dom=dom) + return xend.domain_stop(dom) def domain_shutdown(self, id): """Shutdown domain (nicely). @@ -208,7 +212,7 @@ class XendDomain: if dom <= 0: return 0 eserver.inject('xend.domain.shutdown', id) - val = xc.domain_destroy(dom=dom, force=0) + val = xend.domain_destroy(dom, force=0) self.refresh() return val @@ -219,7 +223,7 @@ class XendDomain: if dom <= 0: return 0 eserver.inject('xend.domain.halt', id) - val = xc.domain_destroy(dom=dom, force=1) + val = xend.domain_destroy(dom, force=1) self.refresh() return val @@ -247,21 +251,6 @@ class XendDomain: self._add_domain(dominfo.id, dominfo) return dominfo - def domain_device_add(self, id, info): - """Add a device to a domain. - """ - pass - - def domain_device_remove(self, id, dev): - """Delete a device from a domain. - """ - pass - - def domain_device_configure(self, id, dev, info): - """Configure a domain device. - """ - pass - #============================================================================ # Backward compatibility stuff from here on. @@ -297,23 +286,10 @@ class XendDomain: if not dominfo: return None return dominfo.get_device_by_index(vif) - def domain_vif_stats(self, dom, vif): - dom = int(dom) - return xc.vif_stats_get(dom=dom, vif=vif) - def domain_vif_ip_add(self, dom, vif, ip): dom = int(dom) return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip) - def domain_vif_scheduler_set(self, dom, vif, bytes, usecs): - dom = int(dom) - return xc.xc_vif_scheduler_set(dom=dom, vif=vif, - credit_bytes=bytes, credit_usecs=usecs) - - def domain_vif_scheduler_get(self, dom, vif): - dom = int(dom) - return xc.vif_scheduler_get(dom=dom, vif=vif) - def domain_vbd_ls(self, dom): dominfo = self.domain_get(dom) if not dominfo: return [] @@ -329,19 +305,6 @@ class XendDomain: return v return None -## def domain_vbd_add(self, dom, uname, dev, mode): -## dom = int(dom) -## vbd = vm.make_disk(dom, uname, dev, mode) -## return vbd - -## def domain_vbd_remove(self, dom, dev): -## dom = int(dom) -## vbd = xenctl.vdisk.blkdev_name_to_number(dev) -## if vbd < 0: return vbd -## err = xc.vbd_destroy(dom, vbd) -## if err < 0: return err -## return vbd - def domain_shadow_control(self, dom, op): dom = int(dom) return xc.shadow_control(dom, op) diff --git a/tools/xenmgr/lib/XendDomainInfo.py b/tools/xenmgr/lib/XendDomainInfo.py index 61a9b21c5a..f05397c169 100644 --- a/tools/xenmgr/lib/XendDomainInfo.py +++ b/tools/xenmgr/lib/XendDomainInfo.py @@ -28,6 +28,9 @@ xendConsole = XendConsole.instance() import server.SrvConsoleServer xend = server.SrvConsoleServer.instance() +SIF_BLK_BE_DOMAIN = (1<<4) +SIF_NET_BE_DOMAIN = (1<<5) + def readlines(fd): """Version of readlines safe against EINTR. """ @@ -59,7 +62,7 @@ class VmError(ValueError): class XendDomainInfo: """Virtual machine object.""" - def __init__(self, config, dom, name, memory, image=None, console=None): + def __init__(self, config, dom, name, memory, image=None, console=None, info=None): """Construct a virtual machine object. config configuration @@ -78,8 +81,10 @@ class XendDomainInfo: self.console = console self.devices = {} self.configs = [] - self.info = None + self.info = info self.ipaddrs = [] + self.block_controller = 0 + self.net_controller = 0 #todo: state: running, suspended self.state = 'running' @@ -329,23 +334,28 @@ def xen_domain_create(config, ostype, name, memory, kernel, ramdisk, cmdline, vi vifs_n number of network interfaces returns vm """ + flags = 0 if not os.path.isfile(kernel): raise VmError('Kernel image does not exist: %s' % kernel) if ramdisk and not os.path.isfile(ramdisk): raise VMError('Kernel ramdisk does not exist: %s' % ramdisk) cpu = int(sxp.child_value(config, 'cpu', '-1')) + print 'xen_domain_create> create ', memory, name, cpu dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu) if dom <= 0: raise VmError('Creating domain failed: name=%s memory=%d kernel=%s' % (name, memory, kernel)) console = xendConsole.console_create(dom) buildfn = getattr(xc, '%s_build' % ostype) + + print 'xen_domain_create> build ', ostype, dom, kernel, cmdline, ramdisk err = buildfn(dom = dom, image = kernel, control_evtchn = console.port2, cmdline = cmdline, - ramdisk = ramdisk) + ramdisk = ramdisk, + flags = flags) if err != 0: raise VmError('Building domain failed: type=%s dom=%d err=%d' % (ostype, dom, err)) @@ -528,6 +538,18 @@ def vm_create_devices(vm, config): print '<vm_create_devices' return deferred +def config_controllers(vm, config): + for c in sxp.children(config, 'controller'): + name = sxp.name(c) + if name == 'block': + vm.block_controller = 1 + xend.blkif_set_control_domain(vm.dom) + elif name == 'net': + vm.net_controller = 1 + xend.netif_set_control_domain(vm.dom) + else: + raise VmError('invalid controller type:' + str(name)) + def vm_configure(vm, config): """Configure a vm. @@ -536,7 +558,12 @@ def vm_configure(vm, config): returns Deferred - calls callback with vm """ - d = xend.blkif_create(vm.dom) + config_controllers(vm, config) + if vm.block_controller: + d = defer.Deferred() + d.callback(1) + else: + d = xend.blkif_create(vm.dom) d.addCallback(_vm_configure1, vm, config) return d @@ -653,8 +680,11 @@ def vm_dev_vif(vm, val, index): val vif config index vif index """ + if vm.net_controller: + raise VmError('vif: vif in control domain') vif = index #todo vmac = sxp.child_value(val, "mac") + bridge = sxp.child_value(val, "bridge") # todo defer = make_vif(vm.dom, vif, vmac) def fn(id): dev = val + ['vif', vif] @@ -671,6 +701,8 @@ def vm_dev_vbd(vm, val, index): val vbd config index vbd index """ + if vm.block_controller: + raise VmError('vbd: vbd in control domain') uname = sxp.child_value(val, 'uname') if not uname: raise VMError('vbd: Missing uname') @@ -686,6 +718,16 @@ def vm_dev_vbd(vm, val, index): defer.addCallback(fn) return defer +def parse_pci(val): + if isinstance(val, StringType): + radix = 10 + if val.startswith('0x') or val.startswith('0X'): + radix = 16 + v = int(val, radix) + else: + v = val + return v + def vm_dev_pci(vm, val, index): bus = sxp.child_value(val, 'bus') if not bus: @@ -697,9 +739,9 @@ def vm_dev_pci(vm, val, index): if not func: raise VMError('pci: Missing func') try: - bus = int(bus, 16) - dev = int(dev, 16) - func = int(func, 16) + bus = parse_pci(bus) + dev = parse_pci(dev) + func = parse_pci(func) except: raise VMError('pci: invalid parameter') rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev, func=func, enable=1) diff --git a/tools/xenmgr/lib/server/SrvConsoleServer.py b/tools/xenmgr/lib/server/SrvConsoleServer.py index 88f3964811..6059ef2ebf 100644 --- a/tools/xenmgr/lib/server/SrvConsoleServer.py +++ b/tools/xenmgr/lib/server/SrvConsoleServer.py @@ -21,6 +21,8 @@ from twisted.internet import protocol from twisted.internet import abstract from twisted.internet import defer +import Xc; xc = Xc.new() + import xend.utils from xenmgr import sxp @@ -289,6 +291,12 @@ class EventProtocol(protocol.Protocol): else: self.send_error() + def loseConnection(self): + if self.transport: + self.transport.loseConnection() + if self.connected: + reactor.callLater(0, self.connectionLost) + def connectionLost(self, reason=None): self.unsubscribe() @@ -559,6 +567,16 @@ class Daemon: reactor.diconnectAll() sys.exit(0) + def blkif_set_control_domain(self, dom): + """Set the block device backend control domain. + """ + return self.blkifCF.setControlDomain(dom) + + def blkif_get_control_domain(self, dom): + """Get the block device backend control domain. + """ + return self.blkifCF.getControlDomain() + def blkif_create(self, dom): """Create a block device interface controller. @@ -579,6 +597,16 @@ class Daemon: d = ctrl.attach_device(vdev, mode, segment) return d + def netif_set_control_domain(self, dom): + """Set the network interface backend control domain. + """ + return self.netifCF.setControlDomain(dom) + + def netif_get_control_domain(self, dom): + """Get the network interface backend control domain. + """ + return self.netifCF.getControlDomain() + def netif_create(self, dom): """Create a network interface controller. @@ -622,6 +650,28 @@ class Daemon: if console.conn: console.conn.loseConnection() + def domain_start(self, id): + """Start domain running. + """ + dom = int(id) + if dom <= 0: return 0 + return xc.domain_start(dom=dom) + + def domain_stop(self, id): + """Stop domain running. + """ + dom = int(id) + if dom <= 0: return 0 + xc.domain_stop(dom=dom) + + def domain_destroy(self, id, force=0): + """Destroy a domain. Shutdown if force=0, terminate immediately if force=1. + """ + dom = int(id) + if dom <= 0: return 0 + return xc.domain_destroy(dom=dom, force=force) + + def instance(): global inst try: diff --git a/tools/xenmgr/lib/server/blkif.py b/tools/xenmgr/lib/server/blkif.py index ae2736da43..7ffa35179d 100755 --- a/tools/xenmgr/lib/server/blkif.py +++ b/tools/xenmgr/lib/server/blkif.py @@ -34,9 +34,9 @@ class BlkifControllerFactory(controller.ControllerFactory): return d def setControlDomain(self, dom): - if self.channel: - self.deregisterChannel() - self.attached = 0 + if self.dom == dom: return + self.deregisterChannel() + self.attached = 0 self.dom = dom self.registerChannel() # @@ -44,6 +44,9 @@ class BlkifControllerFactory(controller.ControllerFactory): # xend.blkif.recovery = True #xend.blkif.be_port = xend.main.port_from_dom(dom) + def getControlDomain(self): + return self.dom + def recv_be_create(self, msg, req): #print 'recv_be_create>' val = unpackMsg('blkif_be_create_t', msg) @@ -81,15 +84,20 @@ class BlkifControllerFactory(controller.ControllerFactory): blkif = self.getInstanceByDom(dom) if blkif: blkif.reattach_device(vdev) + self.attached = self.devices_attached() + if self.attached: + self.reattached() + + def devices_attached(self): + """Check if all devices are attached. + """ attached = 1 for blkif in self.getInstances(): if not blkif.attached: attached = 0 break - self.attached = attached - if self.attached: - self.reattached() - + return attached + def reattached(self): for blkif in self.getInstances(): blkif.reattached() @@ -149,12 +157,16 @@ class BlkifController(controller.Controller): return self.factory.addDeferred() def detach(self): + """Detach all devices, when the back-end control domain has changed. + """ self.attached = 0 for dev in self.devices.values(): dev.attached = 0 self.send_be_vbd_create(vdev) def reattach_device(self, vdev): + """Reattach a device, when the back-end control domain has changed. + """ dev = self.devices[vdev] dev.attached = 1 attached = 1 @@ -166,6 +178,8 @@ class BlkifController(controller.Controller): return self.attached def reattached(self): + """All devices have been reattached after the back-end control domain has changed. + """ msg = packMsg('blkif_fe_interface_status_changed_t', { 'handle' : 0, 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED}) diff --git a/tools/xenmgr/lib/server/controller.py b/tools/xenmgr/lib/server/controller.py index 793ac85968..23b0f7fde1 100755 --- a/tools/xenmgr/lib/server/controller.py +++ b/tools/xenmgr/lib/server/controller.py @@ -37,9 +37,7 @@ class CtrlMsgRcvr: def registerChannel(self): self.channel = self.channelFactory.domChannel(self.dom) - #print 'registerChannel> channel=', self.channel, self self.idx = self.channel.getIndex() - #print 'registerChannel> idx=', self.idx if self.majorTypes: self.channel.registerDevice(self.majorTypes, self) @@ -90,7 +88,7 @@ class ControllerFactory(CtrlMsgRcvr): return None def delInstance(self, instance): - if instance in self.instances: + if instance.idx in self.instances: del self.instances[instance.idx] def createInstance(self, dom): diff --git a/tools/xenmgr/lib/server/messages.py b/tools/xenmgr/lib/server/messages.py index f918e5d440..649629105c 100644 --- a/tools/xenmgr/lib/server/messages.py +++ b/tools/xenmgr/lib/server/messages.py @@ -142,6 +142,34 @@ netif_formats = { msg_formats.update(netif_formats) #============================================================================ +CMSG_SUSPEND = 5 +CMSG_SHUTDOWN = 6 + +CMSG_SHUTDOWN_HALT = 0 +CMSG_SHUTDOWN_POWEROFF = 1 +CMSG_SHUTDOWN_REBOOT = 2 + +STOPCODE_shutdown = 0 +STOPCODE_reboot = 1 +STOPCODE_suspend = 2 + +ctrlif_formats = { + 'ctrlif_suspend_t': + (CMSG_SUSPEND, 0, "??"), + + 'ctrlif_shutdown_halt_t': + (CMSG_SHUTDOWN, CMSG_SHUTDOWN_HALT, "??"), + + 'ctrlif_shutdown_poweroff_t': + (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF, "??"), + + 'ctrlif_shutdown_reboot_t': + (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT, "??"), + } + +msg_formats.update(ctrlif_formats) + +#============================================================================ class Msg: pass diff --git a/tools/xenmgr/lib/server/netif.py b/tools/xenmgr/lib/server/netif.py index 7403054409..13bdd96486 100755 --- a/tools/xenmgr/lib/server/netif.py +++ b/tools/xenmgr/lib/server/netif.py @@ -35,6 +35,7 @@ class NetifControllerFactory(controller.ControllerFactory): def setControlDomain(self, dom): """Set the 'back-end' device driver domain. """ + if self.dom == dom: return self.deregisterChannel() self.attached = 0 self.dom = dom @@ -44,7 +45,9 @@ class NetifControllerFactory(controller.ControllerFactory): # xend.netif.recovery = True # xend.netif.be_port = xend.main.port_from_dom(dom) # - pass + + def getControlDomain(self): + return self.dom def recv_be_create(self, msg, req): self.callDeferred(0) @@ -64,6 +67,8 @@ class NetifControllerFactory(controller.ControllerFactory): val = unpackMsg('netif_be_driver_status_changed_t', msg) status = val['status'] if status == NETIF_DRIVER_STATUS_UP and not self.attached: + # If we are not attached the driver domain was changed, and + # this signals the new driver domain is ready. for netif in self.getInstances(): netif.reattach_devices() self.attached = 1 @@ -149,6 +154,8 @@ class NetifController(controller.Controller): return d def reattach_devices(self): + """Reattach all devices when the back-end control domain has changed. + """ d = self.factory.addDeferred() self.send_be_create(vif) self.attach_fe_devices(0) @@ -182,10 +189,6 @@ class NetifController(controller.Controller): 'rx_shmem_frame' : val['rx_shmem_frame'] }) self.factory.writeRequest(msg) - #def recv_fe_interface_status_changed(self): - # print 'recv_fe_interface_status_changed>' - # pass - def send_interface_connected(self, vif): dev = self.devices[vif] msg = packMsg('netif_fe_interface_status_changed_t', diff --git a/tools/xenmgr/lib/xm/create.py b/tools/xenmgr/lib/xm/create.py index 863227ad4c..3843007a10 100644 --- a/tools/xenmgr/lib/xm/create.py +++ b/tools/xenmgr/lib/xm/create.py @@ -7,28 +7,28 @@ from xenmgr.XendClient import server from xenmgr.xm.opts import * -opts = Opts(use="""[options] +gopts = Opts(use="""[options] Create a domain. """) -opts.opt('help', short='h', +gopts.opt('help', short='h', fn=set_value, default=0, use="Print this help.") -opts.opt('quiet', short='q', +gopts.opt('quiet', short='q', fn=set_true, default=0, use="Quiet.") -opts.opt('path', val='PATH', +gopts.opt('path', val='PATH', fn=set_value, default='.:/etc/xc', use="Search path for default scripts.") -opts.opt('defaults', short='f', val='FILE', +gopts.opt('defaults', short='f', val='FILE', fn=set_value, default='xmdefaults', use="Use the given default script.") -opts.opt('config', short='F', val='FILE', +gopts.opt('config', short='F', val='FILE', fn=set_value, default=None, use='Domain configuration to use.') @@ -38,102 +38,103 @@ def set_var(opt, k, v): (k, v) = string.split(d, '=') opt.opts.setvar(k, v) -opts.opt('define', short='D', val='VAR=VAL', +gopts.opt('define', short='D', val='VAR=VAL', fn=set_var, default=None, use="""Set variables before loading defaults, e.g. '-D vmid=3;ip=1.2.3.4' to set vmid and ip.""") -opts.opt('dryrun', short='n', +gopts.opt('dryrun', short='n', fn=set_true, default=0, use="Dry run - print the config but don't create the domain.") -opts.opt('console', short='c', +gopts.opt('console', short='c', fn=set_true, default=0, use="Connect to console after domain is created.") -opts.opt('kernel', short='k', val='FILE', +gopts.opt('kernel', short='k', val='FILE', + fn=set_value, default=None, use="Path to kernel image.") -opts.opt('ramdisk', short='r', val='FILE', +gopts.opt('ramdisk', short='r', val='FILE', fn=set_value, default='', use="Path to ramdisk.") -opts.opt('builder', short='b', val='FUNCTION', +gopts.opt('builder', short='b', val='FUNCTION', fn=set_value, default='linux', use="Function to use to build the domain.") -opts.opt('memory', short='m', val='MEMORY', +gopts.opt('memory', short='m', val='MEMORY', fn=set_value, default=128, use="Domain memory in MB.") -opts.opt('disk', short='d', val='phy:DEV,VDEV,MODE', +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'.""") -opts.opt('pci', val='BUS,DEV,FUNC', +gopts.opt('pci', val='BUS,DEV,FUNC', fn=append_value, default=[], - use="""Add a PCI device to a domain.""") + use="""Add a PCI device to a domain, using given params (in hex).""") -opts.opt('ipaddr', short='i', val="IPADDR", +gopts.opt('ipaddr', short='i', val="IPADDR", fn=append_value, default=[], use="Add an IP address to the domain.") -opts.opt('mac', short='M', val="MAC", +gopts.opt('mac', short='M', val="MAC", fn=append_value, default=[], use="""Add a network interface with the given mac address to the domain. More than one interface may be specified. Interfaces with unspecified MAC addresses are allocated a random address.""") -opts.opt('nics', val="N", +gopts.opt('nics', val="N", fn=set_int, default=1, use="Set the number of network interfaces.") -opts.opt('vnet', val='VNET', +gopts.opt('vnet', val='VNET', fn=append_value, default=[], use="""Define the vnets for the network interfaces. More than one vnet may be given, they are used in order. """) -opts.opt('root', short='R', val='DEVICE', +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.""") -opts.opt('extra', short='E', val="ARGS", +gopts.opt('extra', short='E', val="ARGS", fn=set_value, default='', use="Set extra arguments to append to the kernel command line.") -opts.opt('ip', short='I', val='IPADDR', +gopts.opt('ip', short='I', val='IPADDR', fn=set_value, default='', use="Set the kernel IP interface address.") -opts.opt('gateway', val="IPADDR", +gopts.opt('gateway', val="IPADDR", fn=set_value, default='', use="Set kernel IP gateway.") -opts.opt('netmask', val="MASK", +gopts.opt('netmask', val="MASK", fn=set_value, default = '', use="Set kernel IP netmask.") -opts.opt('hostname', val="NAME", +gopts.opt('hostname', val="NAME", fn=set_value, default='', use="Set kernel IP hostname.") -opts.opt('interface', val="INTF", +gopts.opt('interface', val="INTF", fn=set_value, default="eth0", use="Set the kernel IP interface name.") -opts.opt('dhcp', val="off|dhcp", +gopts.opt('dhcp', val="off|dhcp", fn=set_value, default='off', use="Set kernel dhcp option.") -opts.opt('nfs_server', val="IPADDR", +gopts.opt('nfs_server', val="IPADDR", fn=set_value, default=None, use="Set the address of the NFS server for NFS root.") -opts.opt('nfs_root', val="PATH", +gopts.opt('nfs_root', val="PATH", fn=set_value, default=None, use="Set the path of the root NFS directory.") @@ -160,7 +161,7 @@ def make_config(opts): config_image.append(['ip', cmdline_ip]) if opts.root: cmdline_root = strip('root=', opts.root) - config_image.append(['root', opts.root]) + config_image.append(['root', cmdline_root]) if opts.extra: config_image.append(['args', opts.extra]) config.append(['image', config_image ]) @@ -221,7 +222,9 @@ def preprocess_pci(opts): d = v.split(',') if len(d) != 3: opts.err('Invalid pci specifier: ' + v) - pci.append(d) + # Components are in hex: add hex specifier. + hexd = map(lambda v: '0x'+v, d) + pci.append(hexd) opts.pci = pci def preprocess_ip(opts): @@ -247,6 +250,8 @@ def preprocess_nfs(opts): opts.extra = nfs + ' ' + opts.extra def preprocess(opts): + if not opts.kernel: + opts.err("No kernel specified") preprocess_disk(opts) preprocess_pci(opts) preprocess_ip(opts) @@ -278,6 +283,7 @@ def make_domain(opts, config): return (dom, console_port) def main(argv): + opts = gopts args = opts.parse(argv) if opts.config: pass @@ -285,6 +291,7 @@ def main(argv): opts.load_defaults() if opts.help: opts.usage() + return preprocess(opts) config = make_config(opts) if opts.dryrun: diff --git a/tools/xenmgr/lib/xm/main.py b/tools/xenmgr/lib/xm/main.py index 4c70717521..32a7be879b 100644 --- a/tools/xenmgr/lib/xm/main.py +++ b/tools/xenmgr/lib/xm/main.py @@ -1,7 +1,7 @@ #!/usr/bin/python -import string import sys +from xenmgr import PrettyPrint from xenmgr import sxp from xenmgr.XendClient import server from xenmgr.xm import create, shutdown @@ -39,7 +39,7 @@ class Xm: def help(self, meth, args): name = meth[3:] f = getattr(self, meth) - print "%s\t%s" % (name, f.__doc__ or '') + print "%-14s %s" % (name, f.__doc__ or '') def xm_help(self, help, args): """Print help.""" @@ -69,12 +69,14 @@ class Xm: print args[0], "FILE" print "\nRestore a domain from FILE." if len(args) < 2: self.err("%s: Missing file" % args[0]) - server.xend_domain_restore(dom, None, filename) + filename = args[1] + server.xend_domain_restore(None, filename) - def xm_ls(self, help, args): + def xm_domains(self, help, args): """List domains.""" - if help: self.help('xm_' + args[0]); return + if help: self.help('xm_' + args[0], args); return doms = server.xend_domains() + doms.sort() print 'Dom Name Mem(MB) CPU State Time(s)' for dom in doms: info = server.xend_domain(dom) @@ -85,7 +87,19 @@ class Xm: d['cpu'] = int(sxp.child_value(info, 'cpu', '0')) d['state'] = sxp.child_value(info, 'state', '??') d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0')) - print ("%(dom)-4d %(name)-16s %(mem)4d %(cpu)3d %(state)5s %(cpu_time)10.2f" % d) + print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)7.1f" % d) + + def xm_domain(self, help, args): + """Get information about a domain.""" + if help: + print args[0], 'DOM' + print '\nGet information about domain DOM.' + return + if len(args) < 2: self.err("%s: Missing domain" % args[0]) + dom = args[1] + info = server.xend_domain(dom) + PrettyPrint.prettyprint(info) + print def xm_halt(self, help, args): """Terminate a domain immediately.""" @@ -101,8 +115,8 @@ class Xm: """Shutdown a domain.""" shutdown.main(args) - def xm_stop(self, help, args): - """Stop execution of a domain.""" + def xm_pause(self, help, args): + """Pause execution of a domain.""" if help: print args[0], 'DOM' print '\nStop execution of domain DOM.' @@ -111,11 +125,11 @@ class Xm: dom = args[1] server.xend_domain_stop(dom) - def xm_start(self, help, args): - """Start execution of a domain.""" + def xm_unpause(self, help, args): + """Unpause a paused domain.""" if help: print args[0], 'DOM' - print '\nStart execution of domain DOM.' + print '\nUnpause execution of domain DOM.' return if len(args) < 2: self.err("%s: Missing domain" % args[0]) dom = args[1] @@ -131,32 +145,6 @@ class Xm: v = map(int, args[1:3]) server.xend_domain_pincpu(*v) - def xm_vif_stats(self, help, args): - """Get stats for a virtual interface.""" - if help: - print args[0], 'DOM VIF' - print '\nGet stats for interface VIF on domain DOM.' - return - if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0]) - v = map(int, args[1:3]) - print server.xend_domain_vif_stats(*v) - - def xm_vif_rate(self, help, args): - """Set or get vif rate params.""" - if help: - print args[0], "DOM VIF [BYTES USECS]" - print '\nSet or get rate controls for interface VIF on domain DOM.' - return - n = len(args) - if n == 3: - v = map(int, args[1:n]) - print server.xend_domain_vif_scheduler_get(*v) - elif n == 5: - v = map(int, args[1:n]) - server.xend_domain_vif_scheduler_set(*v) - else: - self.err("%s: Invalid argument(s)" % args[0]) - def xm_bvt(self, help, args): """Set BVT scheduler parameters.""" if help: @@ -193,16 +181,29 @@ class Xm: print "\nSet round robin scheduler slice." return if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0]) - slice = int(args[1]) - server.xend_node_rrobin_set(slice) + rrslice = int(args[1]) + server.xend_node_rrobin_set(rrslice) def xm_info(self, help, args): """Get information about the xen host.""" - if help: self.help('xm_info'); return + if help: self.help('xm_' + args[0], args); return info = server.xend_node() for x in info[1:]: print "%-23s:" % x[0], x[1] + def xm_consoles(self, help, args): + """Get information about domain consoles.""" + if help: self.help('xm_' + args[0], args); return + l = server.xend_consoles() + print "Dom Port Id" + for x in l: + info = server.xend_console(x) + d = {} + d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1] + d['port'] = sxp.child_value(info, 'port', '?') + d['id'] = sxp.child_value(info, 'id', '?') + print "%(dom)3s %(port)4s %(id)3s" % d + def xm_console(self, help, args): """Open a console to a domain.""" if help: diff --git a/tools/xenmgr/lib/xm/opts.py b/tools/xenmgr/lib/xm/opts.py index 7b32daeae2..426a6d24d1 100644 --- a/tools/xenmgr/lib/xm/opts.py +++ b/tools/xenmgr/lib/xm/opts.py @@ -91,6 +91,7 @@ class Opts: self._vals = {} self._globals = {} self._locals = {} + self.quiet = 0 def opt(self, name, **args): x = Opt(self, name, **args) diff --git a/tools/xenmgr/lib/xm/shutdown.py b/tools/xenmgr/lib/xm/shutdown.py index 805af2929d..8c7a517e96 100644 --- a/tools/xenmgr/lib/xm/shutdown.py +++ b/tools/xenmgr/lib/xm/shutdown.py @@ -5,19 +5,19 @@ import time from xenmgr.XendClient import server from xenmgr.xm.opts import * -opts = Opts(use="""[options] [DOM] +gopts = Opts(use="""[options] [DOM] Shutdown one or more domains gracefully.""") -opts.opt('help', short='h', +gopts.opt('help', short='h', fn=set_value, default=0, use="Print this help.") -opts.opt('all', short='a', +gopts.opt('all', short='a', fn=set_true, default=0, use="Shutdown all domains.") -opts.opt('wait', short='w', +gopts.opt('wait', short='w', fn=set_true, default=0, use='Wait for shutdown to complete.') @@ -28,7 +28,7 @@ def shutdown(opts, doms, wait): if 0 in doms: doms.remove(0) for d in doms: - server.xend_domain_shutdown(dom) + server.xend_domain_shutdown(d) if wait: while doms: alive = domains() @@ -55,6 +55,7 @@ def main_dom(opts, args): shutdown(opts, [ domid ], opts.wait) def main(argv): + opts = gopts args = opts.parse(argv) if opts.help: opts.usage() diff --git a/tools/xenmgr/netfix b/tools/xenmgr/netfix index 26c965260d..65c354490d 100644 --- a/tools/xenmgr/netfix +++ b/tools/xenmgr/netfix @@ -85,11 +85,10 @@ def reconfigure(interface, bridge): if not intf_info['gateway']: print 'Gateway not found: ', interface return - cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info) cmd(CMD_IFCONFIG, '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up' % intf_info) cmd(CMD_ROUTE, 'add default gateway %(gateway)s dev %(bridge)s' % intf_info) - if os.path.exists(CMD_BRCTL): - cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info) + cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info) + cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info) defaults = { 'interface': 'eth0', |