aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/xend/lib/domain_controller.h7
-rw-r--r--tools/xend/lib/utils.c1
-rw-r--r--tools/xenmgr/lib/XendDomainInfo.py3
-rwxr-xr-xtools/xenmgr/lib/server/channel.py141
-rw-r--r--tools/xenmgr/lib/xm/create.py20
-rw-r--r--tools/xenmgr/lib/xm/main.py52
6 files changed, 178 insertions, 46 deletions
diff --git a/tools/xend/lib/domain_controller.h b/tools/xend/lib/domain_controller.h
index af202b5ec3..8a9cea0664 100644
--- a/tools/xend/lib/domain_controller.h
+++ b/tools/xend/lib/domain_controller.h
@@ -523,21 +523,20 @@ typedef struct {
*/
/*
- * Subtypes for console messages.
+ * Subtypes for suspend messages.
*/
/* None. */
/******************************************************************************
- * CONSOLE DEFINITIONS
+ * SHUTDOWN DEFINITIONS
*/
/*
- * Subtypes for console messages.
+ * Subtypes for shutdown messages.
*/
#define CMSG_SHUTDOWN_HALT 0 /* Shutdown and halt (don't die). */
#define CMSG_SHUTDOWN_POWEROFF 1 /* 'Poweroff' => clean death. */
#define CMSG_SHUTDOWN_REBOOT 2 /* Shutdown and restart. */
-
#endif /* __DOMAIN_CONTROLLER_H__ */
diff --git a/tools/xend/lib/utils.c b/tools/xend/lib/utils.c
index f761490648..2d96577203 100644
--- a/tools/xend/lib/utils.c
+++ b/tools/xend/lib/utils.c
@@ -607,6 +607,7 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
P2C(netif_fe_driver_status_changed_t, status, u32);
P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
+ break;
}
if ( dict_items_parsed != PyDict_Size(payload) )
diff --git a/tools/xenmgr/lib/XendDomainInfo.py b/tools/xenmgr/lib/XendDomainInfo.py
index f05397c169..db636136a2 100644
--- a/tools/xenmgr/lib/XendDomainInfo.py
+++ b/tools/xenmgr/lib/XendDomainInfo.py
@@ -350,6 +350,8 @@ def xen_domain_create(config, ostype, name, memory, kernel, ramdisk, cmdline, vi
buildfn = getattr(xc, '%s_build' % ostype)
print 'xen_domain_create> build ', ostype, dom, kernel, cmdline, ramdisk
+ if len(cmdline) >= 256:
+ print 'Warning: kernel cmdline too long'
err = buildfn(dom = dom,
image = kernel,
control_evtchn = console.port2,
@@ -433,7 +435,6 @@ def vm_create(config):
"""
# todo - add support for scheduling params?
print 'vm_create>'
- xenctl.vdisk.VBD_EXPERT_MODE = 0
vm = None
try:
name = sxp.child_value(config, 'name')
diff --git a/tools/xenmgr/lib/server/channel.py b/tools/xenmgr/lib/server/channel.py
index 04f7441f7a..130d23254f 100755
--- a/tools/xenmgr/lib/server/channel.py
+++ b/tools/xenmgr/lib/server/channel.py
@@ -41,14 +41,28 @@ class ChannelFactory:
def domChannel(self, dom):
"""Get the channel for the given domain.
+ Construct if necessary.
"""
for chan in self.channels.values():
+ if not isinstance(chan, Channel): continue
if chan.dom == dom:
return chan
chan = Channel(self, dom)
self.addChannel(chan)
return chan
+ def virqChannel(self, virq):
+ """Get the channel for the given virq.
+ Construct if necessary.
+ """
+ for chan in self.channels.values():
+ if not isinstance(chan, VirqChannel): continue
+ if chan.virq == virq:
+ return chan
+ chan = VirqChannel(self, virq)
+ self.addChannel(chan)
+ return chan
+
def channelClosed(self, channel):
"""The given channel has been closed - remove it.
"""
@@ -70,28 +84,127 @@ def channelFactory():
inst = ChannelFactory()
return inst
-class Channel:
+class BaseChannel:
+ """Abstract superclass for channels.
+
+ The subclass constructor must set idx to the port to use.
+ """
+
+ def __init__(self, factory):
+ self.factory = factory
+ self.idx = -1
+ self.closed = 0
+
+ def getIndex(self):
+ """Get the channel index.
+ """
+ return self.idx
+
+ def notificationReceived(self, type):
+ """Called when a notification is received.
+ Closes the channel on error, otherwise calls
+ handleNotification(type), which should be defined
+ in a subclass.
+ """
+ #print 'notificationReceived> type=', type, self
+ if self.closed: return
+ if type == self.factory.notifier.EXCEPTION:
+ print 'notificationReceived> EXCEPTION'
+ info = xc.evtchn_status(self.idx)
+ if info['status'] == 'unbound':
+ print 'notificationReceived> EXCEPTION closing...'
+ self.close()
+ return
+ self.handleNotification(type)
+
+ def close(self):
+ """Close the channel. Calls channelClosed() on the factory.
+ Override in subclass.
+ """
+ self.factory.channelClosed(self)
+
+ def handleNotification(self, type):
+ """Handle notification.
+ Define in subclass.
+ """
+ pass
+
+
+class VirqChannel(BaseChannel):
+ """A channel for handling a virq.
+ """
+
+ def __init__(self, factory, virq):
+ """Create a channel for the given virq using the given factory.
+
+ Do not call directly, use virqChannel on the factory.
+ """
+ BaseChannel.__init__(self, factory)
+ self.virq = virq
+ # Notification port (int).
+ self.port = xc.evtchn_bind_virq(virq)
+ self.idx = port
+ # Clients to call when a virq arrives.
+ self.clients = []
+
+ def __repr__(self):
+ return ('<VirqChannel virq=%d port=%d>'
+ % (self.virq, self.port))
+
+ def getVirq(self):
+ """Get the channel's virq.
+ """
+ return self.virq
+
+ def close(self):
+ """Close the channel. Calls lostChannel(self) on all its clients and
+ channelClosed() on the factory.
+ """
+ for c in self.clients:
+ c.lostChannel(self)
+ del self.clients
+ BaseChannel.close(self)
+
+ def registerClient(self, client):
+ """Register a client. The client will be called with
+ client.virqReceived(virq) when a virq is received.
+ The client will be called with client.lostChannel(self) if the
+ channel is closed.
+ """
+ self.clients.append(client)
+
+ def handleNotification(self, type):
+ for c in self.clients:
+ c.virqReceived(self.virq)
+
+ def notify(self):
+ xc.evtchn_send(self.port)
+
+
+class Channel(BaseChannel):
"""A control channel to a domain. Messages for the domain device controllers
are multiplexed over the channel (console, block devs, net devs).
"""
def __init__(self, factory, dom):
"""Create a channel to the given domain using the given factory.
+
+ Do not call directly, use domChannel on the factory.
"""
- self.factory = factory
+ BaseChannel.__init__(self, factory)
+ # Domain.
self.dom = dom
+ # Domain port (object).
self.port = self.factory.createPort(dom)
+ # Channel port (int).
self.idx = self.port.local_port
+ # Registered devices.
self.devs = []
+ # Devices indexed by the message types they handle.
self.devs_by_type = {}
- self.closed = 0
+ # Output queue.
self.queue = []
- def getIndex(self):
- """Get the channel index.
- """
- return self.idx
-
def getLocalPort(self):
"""Get the local port.
"""
@@ -153,23 +266,13 @@ class Channel:
self.port.local_port,
self.port.remote_port))
- def notificationReceived(self, type):
- #print 'notificationReceived> type=', type, self
- if self.closed: return
- if type == self.factory.notifier.EXCEPTION:
- print 'notificationReceived> EXCEPTION'
- info = xc.evtchn_status(self.idx)
- if info['status'] == 'unbound':
- print 'notificationReceived> EXCEPTION closing...'
- self.close()
- return
+ def handleNotification(self, type):
work = 0
work += self.handleRequests()
work += self.handleResponses()
work += self.handleWrites()
if work:
self.notify()
- #print 'notificationReceived<', work
def notify(self):
self.port.notify()
diff --git a/tools/xenmgr/lib/xm/create.py b/tools/xenmgr/lib/xm/create.py
index 3843007a10..a5e9e888c5 100644
--- a/tools/xenmgr/lib/xm/create.py
+++ b/tools/xenmgr/lib/xm/create.py
@@ -30,7 +30,11 @@ gopts.opt('defaults', short='f', val='FILE',
gopts.opt('config', short='F', val='FILE',
fn=set_value, default=None,
- use='Domain configuration to use.')
+ use='Domain configuration to use (SXP).')
+
+gopts.opt('load', short='L', val='FILE',
+ fn=set_value, default=None,
+ use='Domain saved state to load.')
def set_var(opt, k, v):
opt.set(v)
@@ -231,6 +235,7 @@ 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
@@ -261,10 +266,9 @@ def make_domain(opts, config):
"""Create, build and start a domain.
Returns: [int] the ID of the new domain.
"""
- restore = 0 #todo
-
- if restore:
- dominfo = server.xend_domain_restore(state_file, config)
+ if opts.load:
+ filename = os.path.abspath(opts.load)
+ dominfo = server.xend_domain_restore(filename, config)
else:
dominfo = server.xend_domain_create(config)
@@ -285,13 +289,13 @@ def make_domain(opts, config):
def main(argv):
opts = gopts
args = opts.parse(argv)
+ if opts.help:
+ opts.usage()
+ return
if opts.config:
pass
else:
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 32a7be879b..fb7d839f4a 100644
--- a/tools/xenmgr/lib/xm/main.py
+++ b/tools/xenmgr/lib/xm/main.py
@@ -1,4 +1,8 @@
-#!/usr/bin/python
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+"""Grand unified management application for Xen.
+"""
+import os
+import os.path
import sys
from xenmgr import PrettyPrint
@@ -17,6 +21,8 @@ class Xm:
sys.exit(1)
def main(self, args):
+ """Main entry point. Dispatches to the xm_ methods.
+ """
self.prog = args[0]
if len(args) < 2:
self.err("Missing command\nTry '%s help' for more information."
@@ -33,10 +39,16 @@ class Xm:
return 0
def unknown(self, help, args):
- self.err("Unknown command: %s\nTry '%s help' for more information."
- % (args[0], self.prog))
+ if help and len(args) == 1:
+ self.xm_help(help, args)
+ else:
+ self.err("Unknown command: %s\nTry '%s help' for more information."
+ % (args[0], self.prog))
def help(self, meth, args):
+ """Print help on an xm_ method.
+ Uses the method documentation string if there is one.
+ """
name = meth[3:]
f = getattr(self, meth)
print "%-14s %s" % (name, f.__doc__ or '')
@@ -53,24 +65,36 @@ class Xm:
create.main(args)
def xm_save(self, help, args):
- """Save domain state to file."""
+ """Save domain state (and config) to file."""
if help:
- print args[0], "DOM FILE"
- print "\nSave domain with id DOM to FILE."
+ print args[0], "DOM FILE [CONFIG]"
+ print """\nSave domain with id DOM to FILE.
+ Optionally save config to CONFIG."""
return
if len(args) < 3: self.err("%s: Missing arguments" % args[0])
dom = args[1]
- filename = args[2]
- server.xend_domain_save(dom, filename)
-
+ savefile = os.path.abspath(args[2])
+ configfile = None
+ if len(args) == 4:
+ configfile = os.path.abspath(args[3])
+ if configfile:
+ out = file(configfile, 'w')
+ config = server.xend_domain(dom)
+ PrettyPrint.prettyprint(config, out=out)
+ out.close()
+ server.xend_domain_save(dom, savefile)
+
def xm_restore(self, help, args):
"""Create a domain from a saved state."""
if help:
- print args[0], "FILE"
- print "\nRestore a domain from FILE."
- if len(args) < 2: self.err("%s: Missing file" % args[0])
- filename = args[1]
- server.xend_domain_restore(None, filename)
+ print args[0], "FILE CONFIG"
+ print "\nRestore a domain from FILE using configuration CONFIG."
+ return
+ if len(args) < 3: self.err("%s: Missing arguments" % args[0])
+ savefile = os.path.abspath(args[1])
+ configfile = os.path.abspath(args[2])
+ info = server.xend_domain_restore(savefile, configfile)
+ PrettyPrint.prettyprint(info)
def xm_domains(self, help, args):
"""List domains."""