ia64/xen-unstable

changeset 1539:b26fa300bcc8

bitkeeper revision 1.996.1.1 (40d819aaW-H1hGnlbaPFjS7bKHhEaw)

Sundry small fixes, domain save/restore in xm.
author mjw@wray-m-3.hpl.hp.com
date Tue Jun 22 11:36:10 2004 +0000 (2004-06-22)
parents 793f5eb5d149
children 2e43f83e8d44
files tools/xend/lib/domain_controller.h tools/xend/lib/utils.c tools/xenmgr/lib/XendDomainInfo.py tools/xenmgr/lib/server/channel.py tools/xenmgr/lib/xm/create.py tools/xenmgr/lib/xm/main.py
line diff
     1.1 --- a/tools/xend/lib/domain_controller.h	Tue Jun 22 08:54:26 2004 +0000
     1.2 +++ b/tools/xend/lib/domain_controller.h	Tue Jun 22 11:36:10 2004 +0000
     1.3 @@ -523,21 +523,20 @@ typedef struct {
     1.4   */
     1.5  
     1.6  /*
     1.7 - * Subtypes for console messages.
     1.8 + * Subtypes for suspend messages.
     1.9   */
    1.10  /* None. */
    1.11  
    1.12  
    1.13  /******************************************************************************
    1.14 - * CONSOLE DEFINITIONS
    1.15 + * SHUTDOWN DEFINITIONS
    1.16   */
    1.17  
    1.18  /*
    1.19 - * Subtypes for console messages.
    1.20 + * Subtypes for shutdown messages.
    1.21   */
    1.22  #define CMSG_SHUTDOWN_HALT      0   /* Shutdown and halt (don't die). */
    1.23  #define CMSG_SHUTDOWN_POWEROFF  1   /* 'Poweroff' => clean death.     */
    1.24  #define CMSG_SHUTDOWN_REBOOT    2   /* Shutdown and restart.          */
    1.25  
    1.26 -
    1.27  #endif /* __DOMAIN_CONTROLLER_H__ */
     2.1 --- a/tools/xend/lib/utils.c	Tue Jun 22 08:54:26 2004 +0000
     2.2 +++ b/tools/xend/lib/utils.c	Tue Jun 22 11:36:10 2004 +0000
     2.3 @@ -607,6 +607,7 @@ static PyObject *xu_message_new(PyObject
     2.4      case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
     2.5          P2C(netif_fe_driver_status_changed_t, status,        u32);
     2.6          P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32);
     2.7 +        break;
     2.8      }
     2.9  
    2.10      if ( dict_items_parsed != PyDict_Size(payload) )
     3.1 --- a/tools/xenmgr/lib/XendDomainInfo.py	Tue Jun 22 08:54:26 2004 +0000
     3.2 +++ b/tools/xenmgr/lib/XendDomainInfo.py	Tue Jun 22 11:36:10 2004 +0000
     3.3 @@ -350,6 +350,8 @@ def xen_domain_create(config, ostype, na
     3.4      buildfn = getattr(xc, '%s_build' % ostype)
     3.5      
     3.6      print 'xen_domain_create> build ', ostype, dom, kernel, cmdline, ramdisk
     3.7 +    if len(cmdline) >= 256:
     3.8 +        print 'Warning: kernel cmdline too long'
     3.9      err = buildfn(dom            = dom,
    3.10                    image          = kernel,
    3.11                    control_evtchn = console.port2,
    3.12 @@ -433,7 +435,6 @@ def vm_create(config):
    3.13      """
    3.14      # todo - add support for scheduling params?
    3.15      print 'vm_create>'
    3.16 -    xenctl.vdisk.VBD_EXPERT_MODE = 0
    3.17      vm = None
    3.18      try:
    3.19          name = sxp.child_value(config, 'name')
     4.1 --- a/tools/xenmgr/lib/server/channel.py	Tue Jun 22 08:54:26 2004 +0000
     4.2 +++ b/tools/xenmgr/lib/server/channel.py	Tue Jun 22 11:36:10 2004 +0000
     4.3 @@ -41,14 +41,28 @@ class ChannelFactory:
     4.4  
     4.5      def domChannel(self, dom):
     4.6          """Get the channel for the given domain.
     4.7 +        Construct if necessary.
     4.8          """
     4.9          for chan in self.channels.values():
    4.10 +            if not isinstance(chan, Channel): continue
    4.11              if chan.dom == dom:
    4.12                  return chan
    4.13          chan = Channel(self, dom)
    4.14          self.addChannel(chan)
    4.15          return chan
    4.16  
    4.17 +    def virqChannel(self, virq):
    4.18 +        """Get the channel for the given virq.
    4.19 +        Construct if necessary.
    4.20 +        """
    4.21 +        for chan in self.channels.values():
    4.22 +            if not isinstance(chan, VirqChannel): continue
    4.23 +            if chan.virq == virq:
    4.24 +                return chan
    4.25 +        chan = VirqChannel(self, virq)
    4.26 +        self.addChannel(chan)
    4.27 +        return chan
    4.28 +
    4.29      def channelClosed(self, channel):
    4.30          """The given channel has been closed - remove it.
    4.31          """
    4.32 @@ -70,28 +84,127 @@ def channelFactory():
    4.33          inst = ChannelFactory()
    4.34      return inst
    4.35  
    4.36 -class Channel:
    4.37 +class BaseChannel:
    4.38 +    """Abstract superclass for channels.
    4.39 +
    4.40 +    The subclass constructor must set idx to the port to use.
    4.41 +    """
    4.42 +
    4.43 +    def __init__(self, factory):
    4.44 +        self.factory = factory
    4.45 +        self.idx = -1
    4.46 +        self.closed = 0
    4.47 +
    4.48 +    def getIndex(self):
    4.49 +        """Get the channel index.
    4.50 +        """
    4.51 +        return self.idx
    4.52 +
    4.53 +    def notificationReceived(self, type):
    4.54 +        """Called when a notification is received.
    4.55 +        Closes the channel on error, otherwise calls
    4.56 +        handleNotification(type), which should be defined
    4.57 +        in a subclass.
    4.58 +        """
    4.59 +        #print 'notificationReceived> type=', type, self
    4.60 +        if self.closed: return
    4.61 +        if type == self.factory.notifier.EXCEPTION:
    4.62 +            print 'notificationReceived> EXCEPTION'
    4.63 +            info = xc.evtchn_status(self.idx)
    4.64 +            if info['status'] == 'unbound':
    4.65 +                print 'notificationReceived> EXCEPTION closing...'
    4.66 +                self.close()
    4.67 +                return
    4.68 +        self.handleNotification(type)
    4.69 +
    4.70 +    def close(self):
    4.71 +        """Close the channel. Calls channelClosed() on the factory.
    4.72 +        Override in subclass.
    4.73 +        """
    4.74 +        self.factory.channelClosed(self)
    4.75 +
    4.76 +    def handleNotification(self, type):
    4.77 +        """Handle notification.
    4.78 +        Define in subclass.
    4.79 +        """
    4.80 +        pass
    4.81 +        
    4.82 +
    4.83 +class VirqChannel(BaseChannel):
    4.84 +    """A channel for handling a virq.
    4.85 +    """
    4.86 +    
    4.87 +    def __init__(self, factory, virq):
    4.88 +        """Create a channel for the given virq using the given factory.
    4.89 +
    4.90 +        Do not call directly, use virqChannel on the factory.
    4.91 +        """
    4.92 +        BaseChannel.__init__(self, factory)
    4.93 +        self.virq = virq
    4.94 +        # Notification port (int).
    4.95 +        self.port = xc.evtchn_bind_virq(virq)
    4.96 +        self.idx = port
    4.97 +        # Clients to call when a virq arrives.
    4.98 +        self.clients = []
    4.99 +
   4.100 +    def __repr__(self):
   4.101 +        return ('<VirqChannel virq=%d port=%d>'
   4.102 +                % (self.virq, self.port))
   4.103 +
   4.104 +    def getVirq(self):
   4.105 +        """Get the channel's virq.
   4.106 +        """
   4.107 +        return self.virq
   4.108 +
   4.109 +    def close(self):
   4.110 +        """Close the channel. Calls lostChannel(self) on all its clients and
   4.111 +        channelClosed() on the factory.
   4.112 +        """
   4.113 +        for c in self.clients:
   4.114 +            c.lostChannel(self)
   4.115 +        del self.clients
   4.116 +        BaseChannel.close(self)
   4.117 +
   4.118 +    def registerClient(self, client):
   4.119 +        """Register a client. The client will be called with
   4.120 +        client.virqReceived(virq) when a virq is received.
   4.121 +        The client will be called with client.lostChannel(self) if the
   4.122 +        channel is closed.
   4.123 +        """
   4.124 +        self.clients.append(client)
   4.125 +
   4.126 +    def handleNotification(self, type):
   4.127 +        for c in self.clients:
   4.128 +            c.virqReceived(self.virq)
   4.129 +
   4.130 +    def notify(self):
   4.131 +        xc.evtchn_send(self.port)
   4.132 +
   4.133 +
   4.134 +class Channel(BaseChannel):
   4.135      """A control channel to a domain. Messages for the domain device controllers
   4.136      are multiplexed over the channel (console, block devs, net devs).
   4.137      """
   4.138  
   4.139      def __init__(self, factory, dom):
   4.140          """Create a channel to the given domain using the given factory.
   4.141 +
   4.142 +        Do not call directly, use domChannel on the factory.
   4.143          """
   4.144 -        self.factory = factory
   4.145 +        BaseChannel.__init__(self, factory)
   4.146 +        # Domain.
   4.147          self.dom = dom
   4.148 +        # Domain port (object).
   4.149          self.port = self.factory.createPort(dom)
   4.150 +        # Channel port (int).
   4.151          self.idx = self.port.local_port
   4.152 +        # Registered devices.
   4.153          self.devs = []
   4.154 +        # Devices indexed by the message types they handle.
   4.155          self.devs_by_type = {}
   4.156 -        self.closed = 0
   4.157 +        # Output queue.
   4.158          self.queue = []
   4.159  
   4.160 -    def getIndex(self):
   4.161 -        """Get the channel index.
   4.162 -        """
   4.163 -        return self.idx
   4.164 -
   4.165      def getLocalPort(self):
   4.166          """Get the local port.
   4.167          """
   4.168 @@ -153,23 +266,13 @@ class Channel:
   4.169                     self.port.local_port,
   4.170                     self.port.remote_port))
   4.171  
   4.172 -    def notificationReceived(self, type):
   4.173 -        #print 'notificationReceived> type=', type, self
   4.174 -        if self.closed: return
   4.175 -        if type == self.factory.notifier.EXCEPTION:
   4.176 -            print 'notificationReceived> EXCEPTION'
   4.177 -            info = xc.evtchn_status(self.idx)
   4.178 -            if info['status'] == 'unbound':
   4.179 -                print 'notificationReceived> EXCEPTION closing...'
   4.180 -                self.close()
   4.181 -                return
   4.182 +    def handleNotification(self, type):
   4.183          work = 0
   4.184          work += self.handleRequests()
   4.185          work += self.handleResponses()
   4.186          work += self.handleWrites()
   4.187          if work:
   4.188              self.notify()
   4.189 -        #print 'notificationReceived<', work
   4.190  
   4.191      def notify(self):
   4.192          self.port.notify()
     5.1 --- a/tools/xenmgr/lib/xm/create.py	Tue Jun 22 08:54:26 2004 +0000
     5.2 +++ b/tools/xenmgr/lib/xm/create.py	Tue Jun 22 11:36:10 2004 +0000
     5.3 @@ -30,7 +30,11 @@ gopts.opt('defaults', short='f', val='FI
     5.4  
     5.5  gopts.opt('config', short='F', val='FILE',
     5.6           fn=set_value, default=None,
     5.7 -         use='Domain configuration to use.')
     5.8 +         use='Domain configuration to use (SXP).')
     5.9 +
    5.10 +gopts.opt('load', short='L', val='FILE',
    5.11 +          fn=set_value, default=None,
    5.12 +          use='Domain saved state to load.')
    5.13  
    5.14  def set_var(opt, k, v):
    5.15      opt.set(v)
    5.16 @@ -231,6 +235,7 @@ def preprocess_ip(opts):
    5.17      setip = (opts.hostname or opts.netmask
    5.18               or opts.gateway or opts.dhcp or opts.interface)
    5.19      if not setip: return
    5.20 +    if not opts
    5.21      ip = (opts.ip
    5.22            + ':'
    5.23            + ':' + opts.gateway
    5.24 @@ -261,10 +266,9 @@ def make_domain(opts, config):
    5.25      """Create, build and start a domain.
    5.26      Returns: [int] the ID of the new domain.
    5.27      """
    5.28 -    restore = 0 #todo
    5.29 -
    5.30 -    if restore:
    5.31 -        dominfo = server.xend_domain_restore(state_file, config)
    5.32 +    if opts.load:
    5.33 +        filename = os.path.abspath(opts.load)
    5.34 +        dominfo = server.xend_domain_restore(filename, config)
    5.35      else:
    5.36          dominfo = server.xend_domain_create(config)
    5.37  
    5.38 @@ -285,13 +289,13 @@ def make_domain(opts, config):
    5.39  def main(argv):
    5.40      opts = gopts
    5.41      args = opts.parse(argv)
    5.42 +    if opts.help:
    5.43 +        opts.usage()
    5.44 +        return
    5.45      if opts.config:
    5.46          pass
    5.47      else:
    5.48          opts.load_defaults()
    5.49 -    if opts.help:
    5.50 -        opts.usage()
    5.51 -        return
    5.52      preprocess(opts)
    5.53      config = make_config(opts)
    5.54      if opts.dryrun:
     6.1 --- a/tools/xenmgr/lib/xm/main.py	Tue Jun 22 08:54:26 2004 +0000
     6.2 +++ b/tools/xenmgr/lib/xm/main.py	Tue Jun 22 11:36:10 2004 +0000
     6.3 @@ -1,4 +1,8 @@
     6.4 -#!/usr/bin/python
     6.5 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     6.6 +"""Grand unified management application for Xen.
     6.7 +"""
     6.8 +import os
     6.9 +import os.path
    6.10  import sys
    6.11  
    6.12  from xenmgr import PrettyPrint
    6.13 @@ -17,6 +21,8 @@ class Xm:
    6.14          sys.exit(1)
    6.15  
    6.16      def main(self, args):
    6.17 +        """Main entry point. Dispatches to the xm_ methods.
    6.18 +        """
    6.19          self.prog = args[0]
    6.20          if len(args) < 2:
    6.21              self.err("Missing command\nTry '%s help' for more information."
    6.22 @@ -33,10 +39,16 @@ class Xm:
    6.23          return 0
    6.24  
    6.25      def unknown(self, help, args):
    6.26 -        self.err("Unknown command: %s\nTry '%s help' for more information."
    6.27 -                 % (args[0], self.prog))
    6.28 +        if help and len(args) == 1:
    6.29 +            self.xm_help(help, args)
    6.30 +        else:
    6.31 +            self.err("Unknown command: %s\nTry '%s help' for more information."
    6.32 +                     % (args[0], self.prog))
    6.33  
    6.34      def help(self, meth, args):
    6.35 +        """Print help on an xm_ method.
    6.36 +        Uses the method documentation string if there is one.
    6.37 +        """
    6.38          name = meth[3:]
    6.39          f = getattr(self, meth)
    6.40          print "%-14s %s" % (name, f.__doc__ or '')
    6.41 @@ -53,24 +65,36 @@ class Xm:
    6.42          create.main(args)
    6.43  
    6.44      def xm_save(self, help, args):
    6.45 -        """Save domain state to file."""
    6.46 +        """Save domain state (and config) to file."""
    6.47          if help:
    6.48 -            print args[0], "DOM FILE"
    6.49 -            print "\nSave domain with id DOM to FILE."
    6.50 +            print args[0], "DOM FILE [CONFIG]"
    6.51 +            print """\nSave domain with id DOM to FILE.
    6.52 +            Optionally save config to CONFIG."""
    6.53              return
    6.54          if len(args) < 3: self.err("%s: Missing arguments" % args[0])
    6.55          dom = args[1]
    6.56 -        filename = args[2]
    6.57 -        server.xend_domain_save(dom, filename)
    6.58 -
    6.59 +        savefile = os.path.abspath(args[2])
    6.60 +        configfile = None
    6.61 +        if len(args) == 4:
    6.62 +            configfile = os.path.abspath(args[3])
    6.63 +        if configfile:
    6.64 +            out = file(configfile, 'w')
    6.65 +            config = server.xend_domain(dom)
    6.66 +            PrettyPrint.prettyprint(config, out=out)
    6.67 +            out.close()
    6.68 +        server.xend_domain_save(dom, savefile)
    6.69 +            
    6.70      def xm_restore(self, help, args):
    6.71          """Create a domain from a saved state."""
    6.72          if help:
    6.73 -            print args[0], "FILE"
    6.74 -            print "\nRestore a domain from FILE."
    6.75 -        if len(args) < 2: self.err("%s: Missing file" % args[0])
    6.76 -        filename = args[1]
    6.77 -        server.xend_domain_restore(None, filename)
    6.78 +            print args[0], "FILE CONFIG"
    6.79 +            print "\nRestore a domain from FILE using configuration CONFIG."
    6.80 +            return
    6.81 +        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
    6.82 +        savefile =  os.path.abspath(args[1])
    6.83 +        configfile = os.path.abspath(args[2])
    6.84 +        info = server.xend_domain_restore(savefile, configfile)
    6.85 +        PrettyPrint.prettyprint(info)
    6.86  
    6.87      def xm_domains(self, help, args):
    6.88          """List domains."""