ia64/xen-unstable

changeset 1569:815e840634fb

bitkeeper revision 1.1015 (40daefb7Yxmwg11WTNOJcj2lzrnQcA)

trivial
author iap10@labyrinth.cl.cam.ac.uk
date Thu Jun 24 15:13:59 2004 +0000 (2004-06-24)
parents eb20b819c82a f8a6be024808
children e87e1ca75a41
files Makefile docs/xen_config.html linux-2.4.26-xen-sparse/arch/xen/Makefile tools/xenmgr/lib/EventTypes.py tools/xenmgr/lib/XendClient.py tools/xenmgr/lib/XendDomain.py tools/xenmgr/lib/XendDomainInfo.py tools/xenmgr/lib/server/SrvConsoleServer.py tools/xenmgr/lib/server/SrvDomain.py tools/xenmgr/lib/server/blkif.py tools/xenmgr/lib/server/controller.py tools/xenmgr/lib/server/messages.py tools/xenmgr/lib/server/netif.py tools/xenmgr/lib/xm/create.py tools/xenmgr/lib/xm/main.py tools/xenmgr/lib/xm/opts.py tools/xenmgr/lib/xm/shutdown.py
line diff
     1.1 --- a/Makefile	Thu Jun 24 15:04:30 2004 +0000
     1.2 +++ b/Makefile	Thu Jun 24 15:13:59 2004 +0000
     1.3 @@ -4,7 +4,7 @@
     1.4  
     1.5  INSTALL_DIR ?= $(shell pwd)/install
     1.6  
     1.7 -SOURCEFORGE_MIRROR = http://heanet.dl.sourceforge.net/sourceforge
     1.8 +SOURCEFORGE_MIRROR := http://heanet.dl.sourceforge.net/sourceforge
     1.9  #http://voxel.dl.sourceforge.net/sourceforge/
    1.10  #http://easynews.dl.sourceforge.net/sourceforge
    1.11  
    1.12 @@ -25,55 +25,57 @@ dist: all
    1.13  	$(MAKE) linux-xenU
    1.14  	$(MAKE) linux-xen0
    1.15  
    1.16 -LINUX_VER        ?= $(shell ( /bin/ls -ld linux-*-xen-sparse ) 2>/dev/null | sed -e 's!^.*linux-\(.\+\)-xen-sparse!\1!' )
    1.17 +LINUX_VER        ?= $(shell ( /bin/ls -ld linux-*-xen-sparse ) 2>/dev/null | \
    1.18 +                    sed -e 's!^.*linux-\(.\+\)-xen-sparse!\1!' )
    1.19  LINUX_CONFIG_DIR ?= $(INSTALL_DIR)/boot
    1.20  LINUX_SRC_PATH   ?= .:..
    1.21 -LINUX_SRC_X ?= $(firstword $(foreach dir,$(subst :, ,$(LINUX_SRC_PATH)),$(wildcard $(dir)/linux-$(LINUX_VER).tar.*z*)))
    1.22 +LINUX_SRC        ?= $(firstword $(foreach dir,$(subst :, ,$(LINUX_SRC_PATH)),\
    1.23 +                    $(wildcard $(dir)/linux-$(LINUX_VER).tar.*z*)))
    1.24  
    1.25  # search for a pristine kernel tar ball, or try downloading one
    1.26  pristine-linux-src: 
    1.27 -ifneq ($(LINUX_SRC),)
    1.28 -	@[ -r "$(LINUX_SRC)" ] || (echo "Can not find linux src at $(LINUX_SRC)" && false)
    1.29 -LINUX_SRC_X = $(LINUX_SRC)
    1.30 -else 
    1.31 -ifeq ($(LINUX_SRC_X),)
    1.32 -	@echo "Can not find linux-$(LINUX_VER).tar.gz in path $(LINUX_SRC_PATH)"
    1.33 +ifeq ($(LINUX_SRC),)
    1.34 +	@echo "Cannot find linux-$(LINUX_VER).tar.gz in path $(LINUX_SRC_PATH)"
    1.35  	@wget ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-$(LINUX_VER).tar.bz2 -O./linux-$(LINUX_VER).tar.bz2
    1.36 -LINUX_SRC_X = ./linux-$(LINUX_VER).tar.bz2 
    1.37 -endif
    1.38 +LINUX_SRC := ./linux-$(LINUX_VER).tar.bz2 
    1.39  endif
    1.40  
    1.41  patches/ebtables-brnf-5_vs_2.4.25.diff:
    1.42  	mkdir -p patches
    1.43 -	wget $(SOURCEFORGE_MIRROR)/ebtables/ebtables-brnf-5_vs_2.4.25.diff.gz -O- | gunzip -c > $@
    1.44 +	wget $(SOURCEFORGE_MIRROR)/ebtables/ebtables-brnf-5_vs_2.4.25.diff.gz \
    1.45 +	     -O- | gunzip -c > $@
    1.46  
    1.47 -LINUX_TREES = linux-$(LINUX_VER)-xen0 linux-$(LINUX_VER)-xenU
    1.48 +LINUX_TREES := linux-$(LINUX_VER)-xen0 linux-$(LINUX_VER)-xenU
    1.49  
    1.50  # make a linux-xen build tree from a pristine kernel plus sparse tree
    1.51  mk-linux-trees: patches/ebtables-brnf-5_vs_2.4.25.diff pristine-linux-src 
    1.52  	$(RM) -rf $(LINUX_TREES)
    1.53 -ifeq (,$(findstring bz2,$(LINUX_SRC_X)))
    1.54 -	tar -zxf $(LINUX_SRC_X)
    1.55 -else
    1.56 -	tar -jxf $(LINUX_SRC_X)
    1.57 -endif
    1.58 +	echo $(LINUX_SRC) | grep -q bz2 && \
    1.59 +	    tar -jxf $(LINUX_SRC) || tar -zxf $(LINUX_SRC)
    1.60  	mv linux-$(LINUX_VER) linux-$(LINUX_VER)-xen0
    1.61 -	( cd linux-$(LINUX_VER)-xen-sparse ; ./mkbuildtree ../linux-$(LINUX_VER)-xen0 )
    1.62 +	( cd linux-$(LINUX_VER)-xen-sparse ; \
    1.63 +          ./mkbuildtree ../linux-$(LINUX_VER)-xen0 )
    1.64  	cp -al linux-$(LINUX_VER)-xen0 linux-$(LINUX_VER)-xenU
    1.65 -	(cd linux-$(LINUX_VER)-xen0 && patch -p1 -F3 < ../patches/ebtables-brnf-5_vs_2.4.25.diff)
    1.66 +	( cd linux-$(LINUX_VER)-xen0 ; \
    1.67 +          patch -p1 -F3 < ../patches/ebtables-brnf-5_vs_2.4.25.diff )
    1.68  
    1.69  # configure the specified linux tree
    1.70 +CDIR = $(subst config-,linux-$(LINUX_VER)-,$@)
    1.71  config-xen%:
    1.72 -	$(MAKE) -C $(subst config-,linux-$(LINUX_VER)-,$(@)) ARCH=xen mrproper
    1.73 -	cp $(LINUX_CONFIG_DIR)/config-$(LINUX_VER)-$(subst config-,,$(@)) $(subst config-,linux-$(LINUX_VER)-,$(@))/.config || $(MAKE) -C $(subst config-,linux-$(LINUX_VER)-,$(@)) ARCH=xen $(subst config-,,$(@))_config
    1.74 -	$(MAKE) -C $(subst config-,linux-$(LINUX_VER)-,$(@)) ARCH=xen oldconfig
    1.75 -	$(MAKE) -C $(subst config-,linux-$(LINUX_VER)-,$(@)) ARCH=xen dep
    1.76 +	$(MAKE) -C $(CDIR) ARCH=xen mrproper
    1.77 +	cp $(LINUX_CONFIG_DIR)/config-$(LINUX_VER)-$(subst config-,,$@) \
    1.78 +	    $(CDIR)/.config || \
    1.79 +	    $(MAKE) -C $(CDIR) ARCH=xen $(subst config-,,$@)_config
    1.80 +	$(MAKE) -C $(CDIR) ARCH=xen oldconfig
    1.81 +	$(MAKE) -C $(CDIR) ARCH=xen dep
    1.82  
    1.83  # build the specified linux tree
    1.84 +BDIR = $(subst linux-,linux-$(LINUX_VER)-,$@)
    1.85  linux-xen%:	
    1.86 -	$(MAKE) -C $(subst linux-,linux-$(LINUX_VER)-,$(@)) ARCH=xen modules
    1.87 -	$(MAKE) -C $(subst linux-,linux-$(LINUX_VER)-,$(@)) ARCH=xen INSTALL_MOD_PATH=$(INSTALL_DIR) modules_install
    1.88 -	$(MAKE) -C $(subst linux-,linux-$(LINUX_VER)-,$(@)) ARCH=xen INSTALL_PATH=$(INSTALL_DIR) install	
    1.89 +	$(MAKE) -C $(BDIR) ARCH=xen modules
    1.90 +	$(MAKE) -C $(BDIR) ARCH=xen INSTALL_MOD_PATH=$(INSTALL_DIR) \
    1.91 +	    modules_install
    1.92 +	$(MAKE) -C $(BDIR) ARCH=xen INSTALL_PATH=$(INSTALL_DIR) install
    1.93  
    1.94  # build xen, the tools, and a domain 0 plus unprivileged linux-xen images,
    1.95  # and place them in the install directory. 'make install' should then
    1.96 @@ -96,7 +98,6 @@ clean: delete-symlinks
    1.97  mrproper: clean
    1.98  	rm -rf install/* patches $(LINUX_TREES) linux-$(LINUX_VER).tar.*
    1.99  
   1.100 -
   1.101  make-symlinks: delete-symlinks
   1.102  	ln -sf linux-$(LINUX_VER)-xen-sparse linux-xen-sparse
   1.103  
   1.104 @@ -107,12 +108,13 @@ delete-symlinks:
   1.105  install-twisted:
   1.106  	wget http://www.twistedmatrix.com/products/get-current.epy
   1.107  	tar -zxf Twisted-*.tar.gz
   1.108 -	(cd Twisted-* ; python setup.py install)
   1.109 +	( cd Twisted-* ; python setup.py install )
   1.110  
   1.111  # handy target to upgrade iptables (use rpm or apt-get in preference)
   1.112  install-iptables:
   1.113  	wget http://www.netfilter.org/files/iptables-1.2.11.tar.bz2
   1.114  	tar -jxf iptables-*.tar.bz2
   1.115 -	(cd iptables-* ; make PREFIX= KERNEL_DIR=../linux-$(LINUX_VER)-xen0 install)
   1.116 +	( cd iptables-* ; \
   1.117 +	  make PREFIX= KERNEL_DIR=../linux-$(LINUX_VER)-xen0 install)
   1.118  
   1.119  
     2.1 --- a/docs/xen_config.html	Thu Jun 24 15:04:30 2004 +0000
     2.2 +++ b/docs/xen_config.html	Thu Jun 24 15:13:59 2004 +0000
     2.3 @@ -86,13 +86,13 @@ Defines a netbsd kernel image and its co
     2.4      <li>args: string, optional. Extra kernel args.
     2.5  </ul>
     2.6  
     2.7 -<h2>(controller (block)) element</h2>
     2.8 -Define that the vm is a block device controller backend.
     2.9 +<h2>(backend (blkif)) element</h2>
    2.10 +The vm is a block device backend.
    2.11  The vm can have pci devices configured, but no virtual
    2.12  block devices.
    2.13  
    2.14 -<h2>(controller (net)) element</h2>
    2.15 -Define that the vm is a net device controller backend.
    2.16 +<h2>(backend (netif)) element</h2>
    2.17 +The vm is a net device backend.
    2.18  The domain may not have virtual network interfaces (vifs) configured.
    2.19  
    2.20  <h2>(device (vif)) element</h2>
     3.1 --- a/linux-2.4.26-xen-sparse/arch/xen/Makefile	Thu Jun 24 15:04:30 2004 +0000
     3.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/Makefile	Thu Jun 24 15:13:59 2004 +0000
     3.3 @@ -16,15 +16,11 @@
     3.4  #           Added '-march' and '-mpreferred-stack-boundary' support
     3.5  #
     3.6  
     3.7 -override EXTRAVERSION := $(subst linux-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL),,$(shell basename $(TOPDIR)))$(EXTRAVERSION)
     3.8 +override EXTRAVERSION:=$(subst linux-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL),,$(shell basename $(TOPDIR)))$(EXTRAVERSION)
     3.9  
    3.10 -# This following is pretty horrid, but I think the ends justify the
    3.11 -# means: if no .config file exists copy the appropriate defconfig-XXX
    3.12 -# file to .config so that we use it in preference to the plain
    3.13 -# defconfig file. It would be much better if there was a hook in the
    3.14 -# main Makefile to do this, but this works.
    3.15 +# If no .config file exists then use the appropriate defconfig-* file
    3.16  ifneq (.config,$(wildcard .config))
    3.17 -X=$(shell cp $(TOPDIR)/arch/xen/defconfig$(EXTRAVERSION) $(TOPDIR)/.config)
    3.18 +DUMMYX:=$(shell cp $(TOPDIR)/arch/xen/defconfig$(EXTRAVERSION) $(TOPDIR)/.config)
    3.19  -include $(TOPDIR)/.config
    3.20  endif
    3.21  
     4.1 --- a/tools/xenmgr/lib/EventTypes.py	Thu Jun 24 15:04:30 2004 +0000
     4.2 +++ b/tools/xenmgr/lib/EventTypes.py	Thu Jun 24 15:13:59 2004 +0000
     4.3 @@ -8,7 +8,7 @@
     4.4  ## xend.domain.unpause: dom
     4.5  ## xend.domain.pause: dom
     4.6  ## xend.domain.shutdown: dom
     4.7 -## xend.domain.halt: dom
     4.8 +## xend.domain.destroy: dom
     4.9  
    4.10  ## xend.domain.migrate.begin: dom, to
    4.11  ## Begin tells: src host, src domain uri, dst host. Dst id known?
     5.1 --- a/tools/xenmgr/lib/XendClient.py	Thu Jun 24 15:04:30 2004 +0000
     5.2 +++ b/tools/xenmgr/lib/XendClient.py	Thu Jun 24 15:13:59 2004 +0000
     5.3 @@ -199,9 +199,9 @@ class Xend:
     5.4          return xend_call(self.domainurl(id),
     5.5                           {'op'      : 'shutdown'})
     5.6  
     5.7 -    def xend_domain_halt(self, id):
     5.8 +    def xend_domain_destroy(self, id):
     5.9          return xend_call(self.domainurl(id),
    5.10 -                         {'op'      : 'halt'})
    5.11 +                         {'op'      : 'destroy'})
    5.12  
    5.13      def xend_domain_save(self, id, filename):
    5.14          return xend_call(self.domainurl(id),
     6.1 --- a/tools/xenmgr/lib/XendDomain.py	Thu Jun 24 15:04:30 2004 +0000
     6.2 +++ b/tools/xenmgr/lib/XendDomain.py	Thu Jun 24 15:13:59 2004 +0000
     6.3 @@ -6,6 +6,8 @@
     6.4  """
     6.5  import sys
     6.6  
     6.7 +from twisted.internet import defer
     6.8 +
     6.9  import Xc; xc = Xc.new()
    6.10  import xenctl.ip
    6.11  
    6.12 @@ -59,21 +61,26 @@ class XendDomain:
    6.13          for d in domlist:
    6.14              domid = str(d['dom'])
    6.15              doms[domid] = d
    6.16 +        dlist = []
    6.17          for config in self.domain_db.values():
    6.18              domid = str(sxp.child_value(config, 'id'))
    6.19              print "dom=", domid, "config=", config
    6.20              if domid in doms:
    6.21                  print "dom=", domid, "new"
    6.22 -                self._new_domain(config)
    6.23 +                deferred = self._new_domain(config, doms[domid])
    6.24 +                dlist.append(deferred)
    6.25              else:
    6.26                  print "dom=", domid, "del"
    6.27                  self._delete_domain(domid)
    6.28 -        print "doms:"
    6.29 -        for d in self.domain.values(): print 'dom', d
    6.30 -        print "refresh..."
    6.31 -        self.refresh()
    6.32 -        print "doms:"
    6.33 -        for d in self.domain.values(): print 'dom', d
    6.34 +        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
    6.35 +        def cbok(val):
    6.36 +            print "doms:"
    6.37 +            for d in self.domain.values(): print 'dom', d
    6.38 +            print "refresh..."
    6.39 +            self.refresh()
    6.40 +            print "doms:"
    6.41 +            for d in self.domain.values(): print 'dom', d
    6.42 +        deferred.addCallback(cbok)
    6.43  
    6.44      def sync(self):
    6.45          """Sync domain db to disk.
    6.46 @@ -90,31 +97,36 @@ class XendDomain:
    6.47      def close(self):
    6.48          pass
    6.49  
    6.50 -    def _new_domain(self, info):
    6.51 +    def _new_domain(self, savedinfo, info):
    6.52          """Create a domain entry from saved info.
    6.53          """
    6.54 -        console = None
    6.55 -        kernel = None
    6.56 -        id = sxp.child_value(info, 'id')
    6.57 -        dom = int(id)
    6.58 -        name = sxp.child_value(info, 'name')
    6.59 -        memory = int(sxp.child_value(info, 'memory'))
    6.60 -        consoleinfo = sxp.child(info, 'console')
    6.61 -        if consoleinfo:
    6.62 -            consoleid = sxp.child_value(consoleinfo, 'id')
    6.63 -            console = self.xconsole.console_get(consoleid)
    6.64 -        if dom and console is None:
    6.65 -            # Try to connect a console.
    6.66 -            console = self.xconsole.console_create(dom)
    6.67 -        config = sxp.child(info, 'config')
    6.68 -        if config:
    6.69 -            image = sxp.child(info, 'image')
    6.70 -            if image:
    6.71 -                image = sxp.child0(image)
    6.72 -                kernel = sxp.child_value(image, 'kernel')
    6.73 -        dominfo = XendDomainInfo.XendDomainInfo(
    6.74 -            config, dom, name, memory, kernel, console)
    6.75 -        self.domain[id] = dominfo
    6.76 +##         console = None
    6.77 +##         kernel = None
    6.78 +##         id = sxp.child_value(info, 'id')
    6.79 +##         dom = int(id)
    6.80 +##         name = sxp.child_value(info, 'name')
    6.81 +##         memory = int(sxp.child_value(info, 'memory'))
    6.82 +##         consoleinfo = sxp.child(info, 'console')
    6.83 +##         if consoleinfo:
    6.84 +##             consoleid = sxp.child_value(consoleinfo, 'id')
    6.85 +##             console = self.xconsole.console_get(consoleid)
    6.86 +##         if dom and console is None:
    6.87 +##             # Try to connect a console.
    6.88 +##             console = self.xconsole.console_create(dom)
    6.89 +##         config = sxp.child(info, 'config')
    6.90 +##         if config:
    6.91 +##             image = sxp.child(info, 'image')
    6.92 +##             if image:
    6.93 +##                 image = sxp.child0(image)
    6.94 +##                 kernel = sxp.child_value(image, 'kernel')
    6.95 +##         dominfo = XendDomainInfo.XendDomainInfo(
    6.96 +##             config, dom, name, memory, kernel, console)
    6.97 +        config = sxp.child_value(savedinfo, 'config')
    6.98 +        deferred = XendDomainInfo.vm_recreate(config, info)
    6.99 +        def fn(dominfo):
   6.100 +            self.domain[dominfo.id] = dominfo
   6.101 +        deferred.addCallback(fn)
   6.102 +        return deferred
   6.103  
   6.104      def _add_domain(self, id, info, notify=1):
   6.105          self.domain[id] = info
   6.106 @@ -143,10 +155,13 @@ class XendDomain:
   6.107              doms[id] = d
   6.108              if id not in self.domain:
   6.109                  config = None
   6.110 -                image = None
   6.111 -                newinfo = XendDomainInfo.XendDomainInfo(
   6.112 -                    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
   6.113 -                self._add_domain(newinfo.id, newinfo)
   6.114 +                #image = None
   6.115 +                #newinfo = XendDomainInfo.XendDomainInfo(
   6.116 +                #    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
   6.117 +                deferred = XendDomainInfo.vm_recreate(config, d)
   6.118 +                def fn(dominfo):
   6.119 +                    self._add_domain(dominfo.id, dominfo)
   6.120 +                deferred.addCallback(fn)
   6.121          # Remove entries for domains that no longer exist.
   6.122          for d in self.domain.values():
   6.123              dominfo = doms.get(d.id)
   6.124 @@ -217,13 +232,13 @@ class XendDomain:
   6.125          self.refresh()
   6.126          return val
   6.127      
   6.128 -    def domain_halt(self, id):
   6.129 +    def domain_destroy(self, id):
   6.130          """Terminate domain immediately.
   6.131          """
   6.132          dom = int(id)
   6.133          if dom <= 0:
   6.134              return 0
   6.135 -        eserver.inject('xend.domain.halt', id)
   6.136 +        eserver.inject('xend.domain.destroy', id)
   6.137          val = xc.domain_destroy(dom=dom)
   6.138          self.refresh()
   6.139          return val       
   6.140 @@ -235,14 +250,14 @@ class XendDomain:
   6.141          pass
   6.142      
   6.143      def domain_save(self, id, dst, progress=0):
   6.144 -        """Save domain state to file, halt domain.
   6.145 +        """Save domain state to file, destroy domain.
   6.146          """
   6.147          dom = int(id)
   6.148          self.domain_pause(id)
   6.149          eserver.inject('xend.domain.save', id)
   6.150          rc = xc.linux_save(dom=dom, state_file=dst, progress=progress)
   6.151          if rc == 0:
   6.152 -            self.domain_halt(id)
   6.153 +            self.domain_destroy(id)
   6.154          return rc
   6.155      
   6.156      def domain_restore(self, src, config, progress=0):
     7.1 --- a/tools/xenmgr/lib/XendDomainInfo.py	Thu Jun 24 15:04:30 2004 +0000
     7.2 +++ b/tools/xenmgr/lib/XendDomainInfo.py	Thu Jun 24 15:13:59 2004 +0000
     7.3 @@ -60,160 +60,6 @@ class VmError(ValueError):
     7.4          return self.value
     7.5  
     7.6  
     7.7 -class XendDomainInfo:
     7.8 -    """Virtual machine object."""
     7.9 -
    7.10 -    def __init__(self, config, dom, name, memory, image=None, console=None, info=None):
    7.11 -        """Construct a virtual machine object.
    7.12 -
    7.13 -        config   configuration
    7.14 -        dom      domain id
    7.15 -        name     name
    7.16 -        memory   memory size (in MB)
    7.17 -        image    image object
    7.18 -        """
    7.19 -        #todo: add info: runtime, state, ...
    7.20 -        self.config = config
    7.21 -        self.id = str(dom)
    7.22 -        self.dom = dom
    7.23 -        self.name = name
    7.24 -        self.memory = memory
    7.25 -        self.image = image
    7.26 -        self.console = console
    7.27 -        self.devices = {}
    7.28 -        self.configs = []
    7.29 -        self.info = info
    7.30 -        self.ipaddrs = []
    7.31 -        self.block_controller = 0
    7.32 -        self.net_controller = 0
    7.33 -
    7.34 -        #todo: state: running, suspended
    7.35 -        self.state = 'running'
    7.36 -        #todo: set to migrate info if migrating
    7.37 -        self.migrate = None
    7.38 -
    7.39 -    def update(self, info):
    7.40 -        """Update with  info from xc.domain_getinfo().
    7.41 -        """
    7.42 -        self.info = info
    7.43 -
    7.44 -    def __str__(self):
    7.45 -        s = "domain"
    7.46 -        s += " id=" + self.id
    7.47 -        s += " name=" + self.name
    7.48 -        s += " memory=" + str(self.memory)
    7.49 -        if self.console:
    7.50 -            s += " console=" + self.console.id
    7.51 -        if self.image:
    7.52 -            s += " image=" + self.image
    7.53 -        s += ""
    7.54 -        return s
    7.55 -
    7.56 -    __repr__ = __str__
    7.57 -
    7.58 -    def sxpr(self):
    7.59 -        sxpr = ['domain',
    7.60 -                ['id', self.id],
    7.61 -                ['name', self.name],
    7.62 -                ['memory', self.memory] ]
    7.63 -        if self.info:
    7.64 -            run   = (self.info['running'] and 'R') or 'r'
    7.65 -            block = (self.info['blocked'] and 'B') or 'b'
    7.66 -            stop  = (self.info['paused']  and 'P') or 'p'
    7.67 -            susp  = (self.info['shutdown'] and 'S') or 's'
    7.68 -            crash = (self.info['crashed'] and 'C') or 'c'
    7.69 -            state = run + block + stop + susp + crash
    7.70 -            sxpr.append(['state', state])
    7.71 -            if self.info['shutdown']:
    7.72 -                reasons = ["poweroff", "reboot", "suspend"]
    7.73 -                reason = reasons[self.info['shutdown_reason']]
    7.74 -                sxpr.append(['shutdown_reason', reason])
    7.75 -            sxpr.append(['cpu', self.info['cpu']])
    7.76 -            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
    7.77 -        if self.console:
    7.78 -            sxpr.append(self.console.sxpr())
    7.79 -        if self.config:
    7.80 -            sxpr.append(['config', self.config])
    7.81 -        return sxpr
    7.82 -
    7.83 -    def add_device(self, type, dev):
    7.84 -        """Add a device to a virtual machine.
    7.85 -
    7.86 -        dev      device to add
    7.87 -        """
    7.88 -        dl = self.devices.get(type, [])
    7.89 -        dl.append(dev)
    7.90 -        self.devices[type] = dl
    7.91 -
    7.92 -    def get_devices(self, type):
    7.93 -        val = self.devices.get(type, [])
    7.94 -        print 'get_devices', type; sxp.show(val); print
    7.95 -        return val
    7.96 -
    7.97 -    def get_device_by_id(self, type, id):
    7.98 -        """Get the device with the given id.
    7.99 -
   7.100 -        id       device id
   7.101 -
   7.102 -        returns  device or None
   7.103 -        """
   7.104 -        return sxp.child_with_id(self.get_devices(type), id)
   7.105 -
   7.106 -    def get_device_by_index(self, type, idx):
   7.107 -        """Get the device with the given index.
   7.108 -
   7.109 -        idx       device index
   7.110 -
   7.111 -        returns  device or None
   7.112 -        """
   7.113 -        dl = self.get_devices(type)
   7.114 -        if 0 <= idx < len(dl):
   7.115 -            return dl[idx]
   7.116 -        else:
   7.117 -            return None
   7.118 -
   7.119 -    def add_config(self, val):
   7.120 -        """Add configuration data to a virtual machine.
   7.121 -
   7.122 -        val      data to add
   7.123 -        """
   7.124 -        self.configs.append(val)
   7.125 -
   7.126 -    def destroy(self):
   7.127 -        if self.dom <= 0:
   7.128 -            return 0
   7.129 -        return xc.domain_destroy(dom=self.dom)
   7.130 -
   7.131 -    def died(self):
   7.132 -        print 'died>', self.dom
   7.133 -        self.release_vifs()
   7.134 -
   7.135 -    def release_vifs(self):
   7.136 -        print 'release_vifs>', self.dom
   7.137 -        vifs = self.get_devices('vif')
   7.138 -        for v in vifs:
   7.139 -            vif = sxp.child_value(v, 'vif')
   7.140 -            bridge = sxp.child_value(v, 'bridge')
   7.141 -            XendBridge.vif_bridge_rem(self.dom, vif, bridge)
   7.142 -
   7.143 -    def show(self):
   7.144 -        """Print virtual machine info.
   7.145 -        """
   7.146 -        print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
   7.147 -        print "image:"
   7.148 -        sxp.show(self.image)
   7.149 -        print
   7.150 -        for dl in self.devices:
   7.151 -            for dev in dl:
   7.152 -                print "device:"
   7.153 -                sxp.show(dev)
   7.154 -                print
   7.155 -        for val in self.configs:
   7.156 -            print "config:"
   7.157 -            sxp.show(val)
   7.158 -            print
   7.159 -        print "]"
   7.160 -
   7.161  def blkdev_name_to_number(name):
   7.162      """Take the given textual block-device name (e.g., '/dev/sda1',
   7.163      'hda') and return the device number used by the OS. """
   7.164 @@ -264,7 +110,7 @@ def lookup_raw_partn(partition):
   7.165      
   7.166      return None
   7.167  
   7.168 -def lookup_disk_uname( uname ):
   7.169 +def lookup_disk_uname(uname):
   7.170      """Lookup a list of segments for a physical device.
   7.171      uname [string]:  name of the device in the format \'phy:dev\' for a physical device
   7.172      returns [list of dicts]: list of extents that make up the named device
   7.173 @@ -277,7 +123,7 @@ def lookup_disk_uname( uname ):
   7.174          segments = None
   7.175      return segments
   7.176  
   7.177 -def make_disk(dom, uname, dev, mode):
   7.178 +def make_disk(dom, uname, dev, mode, recreate=0):
   7.179      """Create a virtual disk device for a domain.
   7.180  
   7.181      @returns Deferred
   7.182 @@ -289,21 +135,21 @@ def make_disk(dom, uname, dev, mode):
   7.183          raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
   7.184      segment = segments[0]
   7.185      vdev = blkdev_name_to_number(dev)
   7.186 -    ctrl = xend.blkif_create(dom)
   7.187 +    ctrl = xend.blkif_create(dom, recreate=recreate)
   7.188      
   7.189      def fn(ctrl):
   7.190 -        return xend.blkif_dev_create(dom, vdev, mode, segment)
   7.191 +        return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate)
   7.192      ctrl.addCallback(fn)
   7.193      return ctrl
   7.194          
   7.195 -def make_vif(dom, vif, vmac):
   7.196 +def make_vif(dom, vif, vmac, recreate=0):
   7.197      """Create a virtual network device for a domain.
   7.198  
   7.199      
   7.200      @returns Deferred
   7.201      """
   7.202 -    xend.netif_create(dom)
   7.203 -    d = xend.netif_dev_create(dom, vif, vmac)
   7.204 +    xend.netif_create(dom, recreate=recreate)
   7.205 +    d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
   7.206      return d
   7.207  
   7.208  def vif_up(iplist):
   7.209 @@ -338,49 +184,6 @@ def vif_up(iplist):
   7.210      finally:
   7.211          if not nlb: set_ip_nonlocal_bind(0)
   7.212  
   7.213 -def xen_domain_create(config, ostype, name, memory, kernel, ramdisk, cmdline, vifs_n):
   7.214 -    """Create a domain. Builds the image but does not configure it.
   7.215 -
   7.216 -    config  configuration
   7.217 -    ostype  OS type
   7.218 -    name    domain name
   7.219 -    memory  domain memory (MB)
   7.220 -    kernel  kernel image
   7.221 -    ramdisk kernel ramdisk
   7.222 -    cmdline kernel commandline
   7.223 -    vifs_n  number of network interfaces
   7.224 -    returns vm
   7.225 -    """
   7.226 -    flags = 0
   7.227 -    if not os.path.isfile(kernel):
   7.228 -        raise VmError('Kernel image does not exist: %s' % kernel)
   7.229 -    if ramdisk and not os.path.isfile(ramdisk):
   7.230 -        raise VMError('Kernel ramdisk does not exist: %s' % ramdisk)
   7.231 -
   7.232 -    cpu = int(sxp.child_value(config, 'cpu', '-1'))
   7.233 -    print 'xen_domain_create> create ', memory, name, cpu
   7.234 -    dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
   7.235 -    if dom <= 0:
   7.236 -        raise VmError('Creating domain failed: name=%s memory=%d kernel=%s'
   7.237 -                      % (name, memory, kernel))
   7.238 -    console = xendConsole.console_create(dom)
   7.239 -    buildfn = getattr(xc, '%s_build' % ostype)
   7.240 -    
   7.241 -    print 'xen_domain_create> build ', ostype, dom, kernel, cmdline, ramdisk
   7.242 -    if len(cmdline) >= 256:
   7.243 -        print 'Warning: kernel cmdline too long'
   7.244 -    err = buildfn(dom            = dom,
   7.245 -                  image          = kernel,
   7.246 -                  control_evtchn = console.port2,
   7.247 -                  cmdline        = cmdline,
   7.248 -                  ramdisk        = ramdisk,
   7.249 -                  flags          = flags)
   7.250 -    if err != 0:
   7.251 -        raise VmError('Building domain failed: type=%s dom=%d err=%d'
   7.252 -                      % (ostype, dom, err))
   7.253 -    vm = XendDomainInfo(config, dom, name, memory, kernel, console)
   7.254 -    return vm
   7.255 -
   7.256  config_handlers = {}
   7.257  
   7.258  def add_config_handler(name, h):
   7.259 @@ -450,34 +253,27 @@ def vm_create(config):
   7.260      returns Deferred
   7.261      raises VmError for invalid configuration
   7.262      """
   7.263 -    # todo - add support for scheduling params?
   7.264      print 'vm_create>'
   7.265 -    vm = None
   7.266 -    try:
   7.267 -        name = sxp.child_value(config, 'name')
   7.268 -        memory = int(sxp.child_value(config, 'memory', '128'))
   7.269 -        image = sxp.child_value(config, 'image')
   7.270 -        
   7.271 -        image_name = sxp.name(image)
   7.272 -        image_handler = get_image_handler(image_name)
   7.273 -        if image_handler is None:
   7.274 -            raise VmError('unknown image type: ' + image_name)
   7.275 -        vm = image_handler(config, name, memory, image)
   7.276 -        deferred = vm_configure(vm, config)
   7.277 -    except StandardError, ex:
   7.278 -        # Catch errors, cleanup and re-raise.
   7.279 -        if vm:
   7.280 -            vm.destroy()
   7.281 -        raise
   7.282 -    def cbok(x):
   7.283 -        print 'vm_create> cbok', x
   7.284 -        return x
   7.285 -    deferred.addCallback(cbok)
   7.286 -    print 'vm_create<'
   7.287 -    return deferred
   7.288 +    vm = XendDomainInfo()
   7.289 +    return vm.construct(config)
   7.290 +
   7.291 +def vm_recreate(config, info):
   7.292 +    """Create the VM object for an existing domain.
   7.293 +    """
   7.294 +    vm = XendDomainInfo()
   7.295 +    vm.recreate = 1
   7.296 +    vm.setdom(info['dom'])
   7.297 +    vm.name = info['name']
   7.298 +    vm.memory = info['mem_kb']/1024
   7.299 +    if config:
   7.300 +        d = vm.construct(config)
   7.301 +    else:
   7.302 +        d = defer.Deferred()
   7.303 +        d.callback(vm)
   7.304 +    return d
   7.305  
   7.306  def vm_restore(src, config, progress=0):
   7.307 -    """Restore a VM.
   7.308 +    """Restore a VM from a disk image.
   7.309  
   7.310      src      saved state to restore
   7.311      config   configuration
   7.312 @@ -485,11 +281,14 @@ def vm_restore(src, config, progress=0):
   7.313      returns  deferred
   7.314      raises   VmError for invalid configuration
   7.315      """
   7.316 +    vm = XendDomainInfo()
   7.317 +    vm.config = config
   7.318      ostype = "linux" #todo set from config
   7.319      restorefn = getattr(xc, "%s_restore" % ostype)
   7.320      dom = restorefn(state_file=src, progress=progress)
   7.321 -    if dom < 0: return dom
   7.322 -    deferred = dom_configure(dom, config)
   7.323 +    if dom < 0:
   7.324 +        raise VMError('restore failed')
   7.325 +    deferred = vm.dom_configure(dom)
   7.326      def vifs_cb(val, vm):
   7.327          vif_up(vm.ipaddrs)
   7.328      deferred.addCallback(vifs_cb, vm)
   7.329 @@ -501,115 +300,25 @@ def dom_get(dom):
   7.330          return domlist[0]
   7.331      return None
   7.332      
   7.333 -def dom_configure(dom, config):
   7.334 -    """Configure a domain.
   7.335 -
   7.336 -    dom    domain id
   7.337 -    config configuration
   7.338 -    returns deferred
   7.339 -    """
   7.340 -    d = dom_get(dom)
   7.341 -    if not d:
   7.342 -        raise VMError("Domain not found: %d" % dom)
   7.343 -    try:
   7.344 -        name = d['name']
   7.345 -        memory = d['memory']/1024
   7.346 -        image = None
   7.347 -        vm = VM(config, dom, name, memory, image)
   7.348 -        deferred = vm_configure(vm, config)
   7.349 -    except StandardError, ex:
   7.350 -        if vm:
   7.351 -            vm.destroy()
   7.352 -        raise
   7.353 -    return deferred
   7.354  
   7.355  def append_deferred(dlist, v):
   7.356      if isinstance(v, defer.Deferred):
   7.357          dlist.append(v)
   7.358  
   7.359 -def vm_create_devices(vm, config):
   7.360 -    """Create the devices for a vm.
   7.361 -
   7.362 -    vm         virtual machine
   7.363 -    config     configuration
   7.364 -
   7.365 -    returns Deferred
   7.366 -    raises VmError for invalid devices
   7.367 -    """
   7.368 -    print '>vm_create_devices'
   7.369 -    dlist = []
   7.370 -    devices = sxp.children(config, 'device')
   7.371 -    index = {}
   7.372 -    for d in devices:
   7.373 -        dev = sxp.child0(d)
   7.374 -        if dev is None:
   7.375 -            raise VmError('invalid device')
   7.376 -        dev_name = sxp.name(dev)
   7.377 -        dev_index = index.get(dev_name, 0)
   7.378 -        dev_handler = get_device_handler(dev_name)
   7.379 -        if dev_handler is None:
   7.380 -            raise VmError('unknown device type: ' + dev_name)
   7.381 -        v = dev_handler(vm, dev, dev_index)
   7.382 -        append_deferred(dlist, v)
   7.383 -        index[dev_name] = dev_index + 1
   7.384 -    deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
   7.385 -    print '<vm_create_devices'
   7.386 -    return deferred
   7.387 -
   7.388 -def config_controllers(vm, config):
   7.389 -    for c in sxp.children(config, 'controller'):
   7.390 -        name = sxp.name(c)
   7.391 -        if name == 'block':
   7.392 -            vm.block_controller = 1
   7.393 -            xend.blkif_set_control_domain(vm.dom)
   7.394 -        elif name == 'net':
   7.395 -            vm.net_controller = 1
   7.396 -            xend.netif_set_control_domain(vm.dom)
   7.397 -        else:
   7.398 -            raise VmError('invalid controller type:' + str(name))
   7.399 -    
   7.400 -def vm_configure(vm, config):
   7.401 -    """Configure a vm.
   7.402 -
   7.403 -    vm         virtual machine
   7.404 -    config     configuration
   7.405 -
   7.406 -    returns Deferred - calls callback with vm
   7.407 -    """
   7.408 -    config_controllers(vm, config)
   7.409 -    if vm.block_controller:
   7.410 -        d = defer.Deferred()
   7.411 -        d.callback(1)
   7.412 -    else:
   7.413 -        d = xend.blkif_create(vm.dom)
   7.414 -    d.addCallback(_vm_configure1, vm, config)
   7.415 -    return d
   7.416 -
   7.417 -def _vm_configure1(val, vm, config):
   7.418 -    d = vm_create_devices(vm, config)
   7.419 +def _vm_configure1(val, vm):
   7.420 +    d = vm.create_devices()
   7.421      print '_vm_configure1> made devices...'
   7.422      def cbok(x):
   7.423          print '_vm_configure1> cbok', x
   7.424          return x
   7.425      d.addCallback(cbok)
   7.426 -    d.addCallback(_vm_configure2, vm, config)
   7.427 +    d.addCallback(_vm_configure2, vm)
   7.428      print '_vm_configure1<'
   7.429      return d
   7.430  
   7.431 -def _vm_configure2(val, vm, config):
   7.432 +def _vm_configure2(val, vm):
   7.433      print '>callback _vm_configure2...'
   7.434 -    dlist = []
   7.435 -    index = {}
   7.436 -    for field in sxp.children(config):
   7.437 -        field_name = sxp.name(field)
   7.438 -        field_index = index.get(field_name, 0)
   7.439 -        field_handler = get_config_handler(field_name)
   7.440 -        # Ignore unknown fields. Warn?
   7.441 -        if field_handler:
   7.442 -            v = field_handler(vm, config, field, field_index)
   7.443 -            append_deferred(dlist, v)
   7.444 -        index[field_name] = field_index + 1
   7.445 -    d = defer.DeferredList(dlist, fireOnOneErrback=1)
   7.446 +    d = vm.configure_fields()
   7.447      def cbok(results):
   7.448          print '_vm_configure2> cbok', results
   7.449          return vm
   7.450 @@ -622,22 +331,369 @@ def _vm_configure2(val, vm, config):
   7.451      print '<_vm_configure2'
   7.452      return d
   7.453  
   7.454 -def config_devices(config, name):
   7.455 -    """Get a list of the 'device' nodes of a given type from a config.
   7.456 +class XendDomainInfo:
   7.457 +    """Virtual machine object."""
   7.458 +
   7.459 +    def __init__(self):
   7.460 +        self.recreate = 0
   7.461 +        self.config = None
   7.462 +        self.id = None
   7.463 +        self.dom = None
   7.464 +        self.name = None
   7.465 +        self.memory = None
   7.466 +        self.image = None
   7.467 +        self.ramdisk = None
   7.468 +        self.cmdline = None
   7.469 +        self.console = None
   7.470 +        self.devices = {}
   7.471 +        self.configs = []
   7.472 +        self.info = None
   7.473 +        self.ipaddrs = []
   7.474 +        self.blkif_backend = 0
   7.475 +        self.netif_backend = 0
   7.476 +        #todo: state: running, suspended
   7.477 +        self.state = 'running'
   7.478 +        #todo: set to migrate info if migrating
   7.479 +        self.migrate = None
   7.480 +
   7.481 +    def setdom(self, dom):
   7.482 +        self.dom = int(dom)
   7.483 +        self.id = str(dom)
   7.484 +        
   7.485 +    def update(self, info):
   7.486 +        """Update with  info from xc.domain_getinfo().
   7.487 +        """
   7.488 +        self.info = info
   7.489 +
   7.490 +    def __str__(self):
   7.491 +        s = "domain"
   7.492 +        s += " id=" + self.id
   7.493 +        s += " name=" + self.name
   7.494 +        s += " memory=" + str(self.memory)
   7.495 +        if self.console:
   7.496 +            s += " console=" + self.console.id
   7.497 +        if self.image:
   7.498 +            s += " image=" + self.image
   7.499 +        s += ""
   7.500 +        return s
   7.501 +
   7.502 +    __repr__ = __str__
   7.503 +
   7.504 +    def sxpr(self):
   7.505 +        sxpr = ['domain',
   7.506 +                ['id', self.id],
   7.507 +                ['name', self.name],
   7.508 +                ['memory', self.memory] ]
   7.509 +        if self.info:
   7.510 +            run   = (self.info['running'] and 'r') or '-'
   7.511 +            block = (self.info['blocked'] and 'b') or '-'
   7.512 +            stop  = (self.info['paused']  and 'p') or '-'
   7.513 +            susp  = (self.info['shutdown'] and 's') or '-'
   7.514 +            crash = (self.info['crashed'] and 'c') or '-'
   7.515 +            state = run + block + stop + susp + crash
   7.516 +            sxpr.append(['state', state])
   7.517 +            if self.info['shutdown']:
   7.518 +                reasons = ["poweroff", "reboot", "suspend"]
   7.519 +                reason = reasons[self.info['shutdown_reason']]
   7.520 +                sxpr.append(['shutdown_reason', reason])
   7.521 +            sxpr.append(['cpu', self.info['cpu']])
   7.522 +            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
   7.523 +        if self.console:
   7.524 +            sxpr.append(self.console.sxpr())
   7.525 +        if self.config:
   7.526 +            sxpr.append(['config', self.config])
   7.527 +        return sxpr
   7.528 +
   7.529 +    def construct(self, config):
   7.530 +        # todo - add support for scheduling params?
   7.531 +        self.config = config
   7.532 +        try:
   7.533 +            self.name = sxp.child_value(config, 'name')
   7.534 +            self.memory = int(sxp.child_value(config, 'memory', '128'))
   7.535 +            self.configure_backends()
   7.536 +            image = sxp.child_value(config, 'image')
   7.537 +            image_name = sxp.name(image)
   7.538 +            image_handler = get_image_handler(image_name)
   7.539 +            if image_handler is None:
   7.540 +                raise VmError('unknown image type: ' + image_name)
   7.541 +            image_handler(self, image)
   7.542 +            deferred = self.configure()
   7.543 +        except StandardError, ex:
   7.544 +            # Catch errors, cleanup and re-raise.
   7.545 +            self.destroy()
   7.546 +            raise
   7.547 +        def cbok(x):
   7.548 +            print 'vm_create> cbok', x
   7.549 +            return x
   7.550 +        deferred.addCallback(cbok)
   7.551 +        print 'vm_create<'
   7.552 +        return deferred
   7.553 +
   7.554 +    def config_devices(self, name):
   7.555 +        """Get a list of the 'device' nodes of a given type from the config.
   7.556 +
   7.557 +        name	device type
   7.558 +        return list of device configs
   7.559 +        """
   7.560 +        devices = []
   7.561 +        for d in sxp.children(self.config, 'device'):
   7.562 +            dev = sxp.child0(d)
   7.563 +            if dev is None: continue
   7.564 +            if name == sxp.name(dev):
   7.565 +                devices.append(dev)
   7.566 +        return devices
   7.567 +
   7.568 +    def add_device(self, type, dev):
   7.569 +        """Add a device to a virtual machine.
   7.570 +
   7.571 +        dev      device to add
   7.572 +        """
   7.573 +        dl = self.devices.get(type, [])
   7.574 +        dl.append(dev)
   7.575 +        self.devices[type] = dl
   7.576 +
   7.577 +    def get_devices(self, type):
   7.578 +        val = self.devices.get(type, [])
   7.579 +        return val
   7.580 +
   7.581 +    def get_device_by_id(self, type, id):
   7.582 +        """Get the device with the given id.
   7.583 +
   7.584 +        id       device id
   7.585 +
   7.586 +        returns  device or None
   7.587 +        """
   7.588 +        dl = self.get_devices(type)
   7.589 +        for d in dl:
   7.590 +            if d.getprop('id') == id:
   7.591 +                return d
   7.592 +        return None
   7.593 +
   7.594 +    def get_device_by_index(self, type, idx):
   7.595 +        """Get the device with the given index.
   7.596 +
   7.597 +        idx       device index
   7.598 +
   7.599 +        returns  device or None
   7.600 +        """
   7.601 +        dl = self.get_devices(type)
   7.602 +        if 0 <= idx < len(dl):
   7.603 +            return dl[idx]
   7.604 +        else:
   7.605 +            return None
   7.606 +
   7.607 +    def add_config(self, val):
   7.608 +        """Add configuration data to a virtual machine.
   7.609 +
   7.610 +        val      data to add
   7.611 +        """
   7.612 +        self.configs.append(val)
   7.613 +
   7.614 +    def destroy(self):
   7.615 +        if self.dom <= 0:
   7.616 +            return 0
   7.617 +        return xc.domain_destroy(dom=self.dom)
   7.618 +
   7.619 +    def died(self):
   7.620 +        print 'died>', self.dom
   7.621 +        self.release_devices()
   7.622 +
   7.623 +    def release_devices(self):
   7.624 +        print 'release_devices>', self.dom
   7.625 +        self.release_vifs()
   7.626 +        self.release_vbds()
   7.627 +        self.devices = {}
   7.628 +
   7.629 +    def release_vifs(self):
   7.630 +        print 'release_vifs>', self.dom
   7.631 +        if self.dom is None: return
   7.632 +        ctrl = xend.netif_get(self.dom)
   7.633 +        if ctrl:
   7.634 +            ctrl.destroy()
   7.635  
   7.636 -    config	configuration
   7.637 -    name	device type
   7.638 -    return list of device configs
   7.639 -    """
   7.640 -    devices = []
   7.641 -    for d in sxp.children(config, 'device'):
   7.642 -        dev = sxp.child0(d)
   7.643 -        if dev is None: continue
   7.644 -        if name == sxp.name(dev):
   7.645 -            devices.append(dev)
   7.646 -    return devices
   7.647 -        
   7.648 -def vm_image_linux(config, name, memory, image):
   7.649 +    def release_vbds(self):
   7.650 +        print 'release_vbds>', self.dom
   7.651 +        if self.dom is None: return
   7.652 +        ctrl = xend.blkif_get(self.dom)
   7.653 +        if ctrl:
   7.654 +            ctrl.destroy()
   7.655 +
   7.656 +    def show(self):
   7.657 +        """Print virtual machine info.
   7.658 +        """
   7.659 +        print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
   7.660 +        print "image:"
   7.661 +        sxp.show(self.image)
   7.662 +        print
   7.663 +        for dl in self.devices:
   7.664 +            for dev in dl:
   7.665 +                print "device:"
   7.666 +                sxp.show(dev)
   7.667 +                print
   7.668 +        for val in self.configs:
   7.669 +            print "config:"
   7.670 +            sxp.show(val)
   7.671 +            print
   7.672 +        print "]"
   7.673 +
   7.674 +    def init_domain(self):
   7.675 +        """Initialize the domain memory.
   7.676 +        """
   7.677 +        if self.recreate: return
   7.678 +        memory = self.memory
   7.679 +        name = self.name
   7.680 +        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
   7.681 +        print 'init_domain>', memory, name, cpu
   7.682 +        dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
   7.683 +        if dom <= 0:
   7.684 +            raise VmError('Creating domain failed: name=%s memory=%d'
   7.685 +                          % (name, memory))
   7.686 +        self.setdom(dom)
   7.687 +
   7.688 +    def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
   7.689 +        """Build the domain boot image.
   7.690 +        """
   7.691 +        if self.recreate: return
   7.692 +        if len(cmdline) >= 256:
   7.693 +            print 'Warning: kernel cmdline too long'
   7.694 +        dom = self.dom
   7.695 +        buildfn = getattr(xc, '%s_build' % ostype)
   7.696 +        print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
   7.697 +        flags = 0
   7.698 +        if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
   7.699 +        if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
   7.700 +        err = buildfn(dom            = dom,
   7.701 +                      image          = kernel,
   7.702 +                      control_evtchn = self.console.port2,
   7.703 +                      cmdline        = cmdline,
   7.704 +                      ramdisk        = ramdisk,
   7.705 +                      flags          = flags)
   7.706 +        if err != 0:
   7.707 +            raise VmError('Building domain failed: type=%s dom=%d err=%d'
   7.708 +                          % (ostype, dom, err))
   7.709 +
   7.710 +    def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
   7.711 +        """Create a domain. Builds the image but does not configure it.
   7.712 +
   7.713 +        ostype  OS type
   7.714 +        kernel  kernel image
   7.715 +        ramdisk kernel ramdisk
   7.716 +        cmdline kernel commandline
   7.717 +        vifs_n  number of network interfaces
   7.718 +        """
   7.719 +        print 'create_domain>', ostype, kernel
   7.720 +        if not self.recreate:
   7.721 +            if not os.path.isfile(kernel):
   7.722 +                raise VmError('Kernel image does not exist: %s' % kernel)
   7.723 +            if ramdisk and not os.path.isfile(ramdisk):
   7.724 +                raise VMError('Kernel ramdisk does not exist: %s' % ramdisk)
   7.725 +        print 'create-domain> init_domain...'
   7.726 +        self.init_domain()
   7.727 +        print 'create_domain>', 'dom=', self.dom
   7.728 +        self.console = xendConsole.console_create(self.dom)
   7.729 +        self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
   7.730 +        self.image = kernel
   7.731 +        self.ramdisk = ramdisk
   7.732 +        self.cmdline = cmdline
   7.733 +
   7.734 +    def create_devices(self):
   7.735 +        """Create the devices for a vm.
   7.736 +
   7.737 +        returns Deferred
   7.738 +        raises VmError for invalid devices
   7.739 +        """
   7.740 +        print '>create_devices'
   7.741 +        dlist = []
   7.742 +        devices = sxp.children(self.config, 'device')
   7.743 +        index = {}
   7.744 +        for d in devices:
   7.745 +            dev = sxp.child0(d)
   7.746 +            if dev is None:
   7.747 +                raise VmError('invalid device')
   7.748 +            dev_name = sxp.name(dev)
   7.749 +            dev_index = index.get(dev_name, 0)
   7.750 +            dev_handler = get_device_handler(dev_name)
   7.751 +            if dev_handler is None:
   7.752 +                raise VmError('unknown device type: ' + dev_name)
   7.753 +            v = dev_handler(self, dev, dev_index)
   7.754 +            append_deferred(dlist, v)
   7.755 +            index[dev_name] = dev_index + 1
   7.756 +        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
   7.757 +        print '<create_devices'
   7.758 +        return deferred
   7.759 +
   7.760 +    def configure_backends(self):
   7.761 +        """Set configuration flags if the vm is a backend for netif of blkif.
   7.762 +        """
   7.763 +        for c in sxp.children(self.config, 'backend'):
   7.764 +            name = sxp.name(c)
   7.765 +            if name == 'blkif':
   7.766 +                self.blkif_backend = 1
   7.767 +            elif name == 'netif':
   7.768 +                self.netif_backend = 1
   7.769 +            else:
   7.770 +                raise VmError('invalid backend type:' + str(name))
   7.771 +
   7.772 +    def create_backends(self):
   7.773 +        """Setup the netif and blkif backends.
   7.774 +        """
   7.775 +        if self.blkif_backend:
   7.776 +            xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
   7.777 +        if self.netif_backend:
   7.778 +            xend.netif_set_control_domain(self.dom, recreate=self.recreate)
   7.779 +            
   7.780 +    def configure(self):
   7.781 +        """Configure a vm.
   7.782 +
   7.783 +        vm         virtual machine
   7.784 +        config     configuration
   7.785 +
   7.786 +        returns Deferred - calls callback with vm
   7.787 +        """
   7.788 +        if self.blkif_backend:
   7.789 +            d = defer.Deferred()
   7.790 +            d.callback(1)
   7.791 +        else:
   7.792 +            d = xend.blkif_create(self.dom, recreate=self.recreate)
   7.793 +        d.addCallback(_vm_configure1, self)
   7.794 +        return d
   7.795 +
   7.796 +    def dom_configure(self, dom):
   7.797 +        """Configure a domain.
   7.798 +
   7.799 +        dom    domain id
   7.800 +        returns deferred
   7.801 +        """
   7.802 +        d = dom_get(dom)
   7.803 +        if not d:
   7.804 +            raise VMError("Domain not found: %d" % dom)
   7.805 +        try:
   7.806 +            self.setdom(dom)
   7.807 +            self.name = d['name']
   7.808 +            self.memory = d['memory']/1024
   7.809 +            deferred = self.configure()
   7.810 +        except StandardError, ex:
   7.811 +            self.destroy()
   7.812 +            raise
   7.813 +        return deferred
   7.814 +
   7.815 +    def configure_fields(self):
   7.816 +        dlist = []
   7.817 +        index = {}
   7.818 +        for field in sxp.children(self.config):
   7.819 +            field_name = sxp.name(field)
   7.820 +            field_index = index.get(field_name, 0)
   7.821 +            field_handler = get_config_handler(field_name)
   7.822 +            # Ignore unknown fields. Warn?
   7.823 +            if field_handler:
   7.824 +                v = field_handler(self, self.config, field, field_index)
   7.825 +                append_deferred(dlist, v)
   7.826 +            index[field_name] = field_index + 1
   7.827 +        d = defer.DeferredList(dlist, fireOnOneErrback=1)
   7.828 +        return d
   7.829 +
   7.830 +
   7.831 +def vm_image_linux(vm, image):
   7.832      """Create a VM for a linux image.
   7.833  
   7.834      name      vm name
   7.835 @@ -658,12 +714,11 @@ def vm_image_linux(config, name, memory,
   7.836      if args:
   7.837          cmdline += " " + args
   7.838      ramdisk = sxp.child_value(image, "ramdisk", '')
   7.839 -    vifs = config_devices(config, "vif")
   7.840 -    vm = xen_domain_create(config, "linux", name, memory, kernel,
   7.841 -                           ramdisk, cmdline, len(vifs))
   7.842 +    vifs = vm.config_devices("vif")
   7.843 +    vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
   7.844      return vm
   7.845  
   7.846 -def vm_image_netbsd(config, name, memory, image):
   7.847 +def vm_image_netbsd(vm, image):
   7.848      """Create a VM for a bsd image.
   7.849  
   7.850      name      vm name
   7.851 @@ -685,9 +740,8 @@ def vm_image_netbsd(config, name, memory
   7.852      if args:
   7.853          cmdline += " " + args
   7.854      ramdisk = sxp.child_value(image, "ramdisk")
   7.855 -    vifs = config_devices(config, "vif")
   7.856 -    vm = xen_domain_create(config, "netbsd", name, memory, kernel,
   7.857 -                           ramdisk, cmdline, len(vifs))
   7.858 +    vifs = vm.config_devices("vif")
   7.859 +    vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
   7.860      return vm
   7.861  
   7.862  
   7.863 @@ -698,18 +752,18 @@ def vm_dev_vif(vm, val, index):
   7.864      val       vif config
   7.865      index     vif index
   7.866      """
   7.867 -    if vm.net_controller:
   7.868 -        raise VmError('vif: vif in control domain')
   7.869 +    if vm.netif_backend:
   7.870 +        raise VmError('vif: vif in netif backend domain')
   7.871      vif = index #todo
   7.872      vmac = sxp.child_value(val, "mac")
   7.873 -    defer = make_vif(vm.dom, vif, vmac)
   7.874 +    defer = make_vif(vm.dom, vif, vmac, vm.recreate)
   7.875      def fn(id):
   7.876 +        dev = xend.netif_dev(vm.dom, vif)
   7.877 +        devid = sxp.attribute(val, 'id')
   7.878 +        if devid:
   7.879 +            dev.setprop('id', devid)
   7.880          bridge = sxp.child_value(val, "bridge")
   7.881 -        bridge = XendBridge.vif_bridge_add(vm.dom, vif, bridge)
   7.882 -        dev = ['vif', ['vif', vif], ['bridge', bridge] ]
   7.883 -        netdev = xend.netif_dev(vm.dom, vif)
   7.884 -        if netdev and netdev.mac:
   7.885 -            dev += [ 'mac', netdev.mac ]
   7.886 +        dev.bridge_add(bridge)
   7.887          vm.add_device('vif', dev)
   7.888          print 'vm_dev_vif> created', dev
   7.889          return id
   7.890 @@ -723,8 +777,9 @@ def vm_dev_vbd(vm, val, index):
   7.891      val       vbd config
   7.892      index     vbd index
   7.893      """
   7.894 -    if vm.block_controller:
   7.895 -        raise VmError('vbd: vbd in control domain')
   7.896 +    if vm.blkif_backend:
   7.897 +        raise VmError('vbd: vbd in blkif backend domain')
   7.898 +    vdev = index
   7.899      uname = sxp.child_value(val, 'uname')
   7.900      if not uname:
   7.901          raise VMError('vbd: Missing uname')
   7.902 @@ -732,9 +787,10 @@ def vm_dev_vbd(vm, val, index):
   7.903      if not dev:
   7.904          raise VMError('vbd: Missing dev')
   7.905      mode = sxp.child_value(val, 'mode', 'r')
   7.906 -    defer = make_disk(vm.dom, uname, dev, mode)
   7.907 +    defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
   7.908      def fn(vbd):
   7.909 -        vm.add_device('vbd', val)
   7.910 +        dev = xend.blkif_dev(vm.dom, vdev)
   7.911 +        vm.add_device('vbd', dev)
   7.912          return vbd
   7.913      defer.addCallback(fn)
   7.914      return defer
   7.915 @@ -765,7 +821,8 @@ def vm_dev_pci(vm, val, index):
   7.916          func = parse_pci(func)
   7.917      except:
   7.918          raise VMError('pci: invalid parameter')
   7.919 -    rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev, func=func, enable=1)
   7.920 +    rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
   7.921 +                                      func=func, enable=1)
   7.922      if rc < 0:
   7.923          #todo non-fatal
   7.924          raise VMError('pci: Failed to configure device: bus=%s dev=%s func=%s' %
   7.925 @@ -833,13 +890,11 @@ def vm_field_vnet(vm, config, val, index
   7.926          if id is None:
   7.927              raise VmError('vnet: missing vif id')
   7.928          dev = vm.get_device_by_id('vif', id)
   7.929 -        if not sxp.elementp(dev, 'vif'):
   7.930 -            raise VmError('vnet: invalid vif id %s' % id)
   7.931 -        vnet = sxp.child_value(v, 'vnet', 1)
   7.932 -        mac = sxp.child_value(dev, 'mac')
   7.933 -        vif = sxp.child_value(dev, 'vif')
   7.934 -        vnet_bridge(vnet, mac, vm.dom, 0)
   7.935 -        vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
   7.936 +        #vnet = sxp.child_value(v, 'vnet', 1)
   7.937 +        #mac = sxp.child_value(dev, 'mac')
   7.938 +        #vif = sxp.child_value(dev, 'vif')
   7.939 +        #vnet_bridge(vnet, mac, vm.dom, 0)
   7.940 +        #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
   7.941  
   7.942  # Register image handlers for linux and bsd.
   7.943  add_image_handler('linux',  vm_image_linux)
     8.1 --- a/tools/xenmgr/lib/server/SrvConsoleServer.py	Thu Jun 24 15:04:30 2004 +0000
     8.2 +++ b/tools/xenmgr/lib/server/SrvConsoleServer.py	Thu Jun 24 15:13:59 2004 +0000
     8.3 @@ -584,28 +584,31 @@ class Daemon:
     8.4          reactor.diconnectAll()
     8.5          sys.exit(0)
     8.6  
     8.7 -    def blkif_set_control_domain(self, dom):
     8.8 +    def blkif_set_control_domain(self, dom, recreate=0):
     8.9          """Set the block device backend control domain.
    8.10          """
    8.11 -        return self.blkifCF.setControlDomain(dom)
    8.12 +        return self.blkifCF.setControlDomain(dom, recreate=recreate)
    8.13      
    8.14      def blkif_get_control_domain(self, dom):
    8.15          """Get the block device backend control domain.
    8.16          """
    8.17          return self.blkifCF.getControlDomain()
    8.18      
    8.19 -    def blkif_create(self, dom):
    8.20 +    def blkif_create(self, dom, recreate=0):
    8.21          """Create a block device interface controller.
    8.22          
    8.23          Returns Deferred
    8.24          """
    8.25 -        d = self.blkifCF.createInstance(dom)
    8.26 +        d = self.blkifCF.createInstance(dom, recreate=recreate)
    8.27          return d
    8.28  
    8.29 +    def blkif_get(self, dom):
    8.30 +        return self.blkifCF.getInstanceByDom(dom)
    8.31 +
    8.32      def blkif_dev(self, dom, vdev):
    8.33          return self.blkifCF.getDomainDevice(dom, vdev)
    8.34  
    8.35 -    def blkif_dev_create(self, dom, vdev, mode, segment):
    8.36 +    def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0):
    8.37          """Create a block device.
    8.38          
    8.39          Returns Deferred
    8.40 @@ -614,26 +617,29 @@ class Daemon:
    8.41          if not ctrl:
    8.42              raise ValueError('No blkif controller: %d' % dom)
    8.43          print 'blkif_dev_create>', dom, vdev, mode, segment
    8.44 -        d = ctrl.attach_device(vdev, mode, segment)
    8.45 +        d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
    8.46          return d
    8.47  
    8.48 -    def netif_set_control_domain(self, dom):
    8.49 +    def netif_set_control_domain(self, dom, recreate=0):
    8.50          """Set the network interface backend control domain.
    8.51          """
    8.52 -        return self.netifCF.setControlDomain(dom)
    8.53 +        return self.netifCF.setControlDomain(dom, recreate=recreate)
    8.54  
    8.55      def netif_get_control_domain(self, dom):
    8.56          """Get the network interface backend control domain.
    8.57          """
    8.58          return self.netifCF.getControlDomain()
    8.59      
    8.60 -    def netif_create(self, dom):
    8.61 +    def netif_create(self, dom, recreate=0):
    8.62          """Create a network interface controller.
    8.63          
    8.64          """
    8.65 -        return self.netifCF.createInstance(dom)
    8.66 +        return self.netifCF.createInstance(dom, recreate=recreate)
    8.67  
    8.68 -    def netif_dev_create(self, dom, vif, vmac):
    8.69 +    def netif_get(self, dom):
    8.70 +        return self.netifCF.getInstanceByDom(dom)
    8.71 +
    8.72 +    def netif_dev_create(self, dom, vif, vmac, recreate=0):
    8.73          """Create a network device.
    8.74  
    8.75          todo
    8.76 @@ -641,7 +647,7 @@ class Daemon:
    8.77          ctrl = self.netifCF.getInstanceByDom(dom)
    8.78          if not ctrl:
    8.79              raise ValueError('No netif controller: %d' % dom)
    8.80 -        d = ctrl.attach_device(vif, vmac)
    8.81 +        d = ctrl.attachDevice(vif, vmac, recreate=recreate)
    8.82          return d
    8.83  
    8.84      def netif_dev(self, dom, vif):
     9.1 --- a/tools/xenmgr/lib/server/SrvDomain.py	Thu Jun 24 15:04:30 2004 +0000
     9.2 +++ b/tools/xenmgr/lib/server/SrvDomain.py	Thu Jun 24 15:13:59 2004 +0000
     9.3 @@ -32,8 +32,8 @@ class SrvDomain(SrvDir):
     9.4          req.setHeader("Location", "%s/.." % req.prePathURL())
     9.5          return val
     9.6  
     9.7 -    def op_halt(self, op, req):
     9.8 -        val = self.xd.domain_halt(self.dom.id)
     9.9 +    def op_destroy(self, op, req):
    9.10 +        val = self.xd.domain_destroy(self.dom.id)
    9.11          req.setHeader("Location", "%s/.." % req.prePathURL())
    9.12          return val
    9.13  
    9.14 @@ -196,7 +196,7 @@ class SrvDomain(SrvDir):
    9.15          req.write('<input type="submit" name="op" value="unpause">')
    9.16          req.write('<input type="submit" name="op" value="pause">')
    9.17          req.write('<input type="submit" name="op" value="shutdown">')
    9.18 -        req.write('<input type="submit" name="op" value="halt">')
    9.19 +        req.write('<input type="submit" name="op" value="destroy">')
    9.20          req.write('<br><input type="submit" name="op" value="migrate">')
    9.21          req.write('To: <input type="text" name="destination">')
    9.22          req.write('</form>')
    10.1 --- a/tools/xenmgr/lib/server/blkif.py	Thu Jun 24 15:04:30 2004 +0000
    10.2 +++ b/tools/xenmgr/lib/server/blkif.py	Thu Jun 24 15:13:59 2004 +0000
    10.3 @@ -1,3 +1,5 @@
    10.4 +from twisted.internet import defer
    10.5 +
    10.6  import channel
    10.7  import controller
    10.8  from messages import *
    10.9 @@ -22,7 +24,7 @@ class BlkifControllerFactory(controller.
   10.10          self.attached = 1
   10.11          self.registerChannel()
   10.12  
   10.13 -    def createInstance(self, dom):
   10.14 +    def createInstance(self, dom, recreate=0):
   10.15          d = self.addDeferred()
   10.16          blkif = self.getInstanceByDom(dom)
   10.17          if blkif:
   10.18 @@ -30,7 +32,10 @@ class BlkifControllerFactory(controller.
   10.19          else:
   10.20              blkif = BlkifController(self, dom)
   10.21              self.addInstance(blkif)
   10.22 -            blkif.send_be_create()
   10.23 +            if recreate:
   10.24 +                self.callDeferred(blkif)
   10.25 +            else:
   10.26 +                blkif.send_be_create()
   10.27          return d
   10.28  
   10.29      def getDomainDevices(self, dom):
   10.30 @@ -41,10 +46,11 @@ class BlkifControllerFactory(controller.
   10.31          blkif = self.getInstanceByDom(dom)
   10.32          return (blkif and blkif.getDevice(vdev)) or None
   10.33  
   10.34 -    def setControlDomain(self, dom):
   10.35 +    def setControlDomain(self, dom, recreate=0):
   10.36          if self.dom == dom: return
   10.37          self.deregisterChannel()
   10.38 -        self.attached = 0
   10.39 +        if not recreate:
   10.40 +            self.attached = 0
   10.41          self.dom = dom
   10.42          self.registerChannel()
   10.43          #
   10.44 @@ -55,6 +61,28 @@ class BlkifControllerFactory(controller.
   10.45      def getControlDomain(self):
   10.46          return self.dom
   10.47  
   10.48 +    def reattachDevice(self, dom, vdev):
   10.49 +        blkif = self.getInstanceByDom(dom)
   10.50 +        if blkif:
   10.51 +            blkif.reattachDevice(vdev)
   10.52 +        self.attached = self.devicesAttached()
   10.53 +        if self.attached:
   10.54 +            self.reattached()
   10.55 +
   10.56 +    def devicesAttached(self):
   10.57 +        """Check if all devices are attached.
   10.58 +        """
   10.59 +        attached = 1
   10.60 +        for blkif in self.getInstances():
   10.61 +            if not blkif.attached:
   10.62 +                attached = 0
   10.63 +                break
   10.64 +        return attached
   10.65 +                         
   10.66 +    def reattached(self):
   10.67 +        for blkif in self.getInstances():
   10.68 +            blkif.reattached()
   10.69 +
   10.70      def recv_be_create(self, msg, req):
   10.71          #print 'recv_be_create>'
   10.72          val = unpackMsg('blkif_be_create_t', msg)
   10.73 @@ -86,29 +114,7 @@ class BlkifControllerFactory(controller.
   10.74          if self.attached:
   10.75              self.callDeferred(0)
   10.76          else:
   10.77 -            self.reattach_device(val['domid'], val['vdevice'])
   10.78 -
   10.79 -    def reattach_device(self, dom, vdev):
   10.80 -        blkif = self.getInstanceByDom(dom)
   10.81 -        if blkif:
   10.82 -            blkif.reattach_device(vdev)
   10.83 -        self.attached = self.devices_attached()
   10.84 -        if self.attached:
   10.85 -            self.reattached()
   10.86 -
   10.87 -    def devices_attached(self):
   10.88 -        """Check if all devices are attached.
   10.89 -        """
   10.90 -        attached = 1
   10.91 -        for blkif in self.getInstances():
   10.92 -            if not blkif.attached:
   10.93 -                attached = 0
   10.94 -                break
   10.95 -        return attached
   10.96 -                         
   10.97 -    def reattached(self):
   10.98 -        for blkif in self.getInstances():
   10.99 -            blkif.reattached()
  10.100 +            self.reattachDevice(val['domid'], val['vdevice'])
  10.101  
  10.102      def recv_be_driver_status_changed(self, msg, req):
  10.103          val = unpackMsg('blkif_be_driver_status_changed_t', msg)
  10.104 @@ -117,11 +123,12 @@ class BlkifControllerFactory(controller.
  10.105              for blkif in self.getInstances():
  10.106                  blkif.detach()
  10.107  
  10.108 -class BlkDev:
  10.109 +class BlkDev(controller.Dev):
  10.110      """Info record for a block device.
  10.111      """
  10.112  
  10.113 -    def __init__(self, vdev, mode, segment):
  10.114 +    def __init__(self, ctrl, vdev, mode, segment):
  10.115 +        controller.Dev.__init__(self, ctrl)
  10.116          self.vdev = vdev
  10.117          self.mode = mode
  10.118          self.device = segment['device']
  10.119 @@ -131,6 +138,14 @@ class BlkDev:
  10.120  
  10.121      def readonly(self):
  10.122          return 'w' not in self.mode
  10.123 +
  10.124 +    def sxpr(self):
  10.125 +        print 'BlkDev>sxpr>', vars(self)
  10.126 +        val = ['blkif', ['vdev', self.vdev], ['mode', self.mode] ]
  10.127 +        return val
  10.128 +
  10.129 +    def destroy(self):
  10.130 +        self.controller.send_be_vbd_destroy(self.vdev)
  10.131          
  10.132  class BlkifController(controller.Controller):
  10.133      """Block device interface controller. Handles all block devices
  10.134 @@ -154,21 +169,43 @@ class BlkifController(controller.Control
  10.135          self.registerChannel()
  10.136          #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
  10.137  
  10.138 +    def lostChannel(self):
  10.139 +        print 'BlkifController>lostChannel>', 'dom=', self.dom
  10.140 +        #self.destroyDevices()
  10.141 +        controller.Controller.lostChannel(self)
  10.142 +
  10.143      def getDevices(self):
  10.144          return self.devices.values()
  10.145  
  10.146      def getDevice(self, vdev):
  10.147          return self.devices.get(vdev)
  10.148  
  10.149 -    def attach_device(self, vdev, mode, segment):
  10.150 +    def addDevice(self, vdev, mode, segment):
  10.151 +        if vdev in self.devices: return None
  10.152 +        dev = BlkDev(self, vdev, mode, segment)
  10.153 +        self.devices[vdev] = dev
  10.154 +        return dev
  10.155 +
  10.156 +    def attachDevice(self, vdev, mode, segment, recreate=0):
  10.157          """Attach a device to the specified interface.
  10.158          """
  10.159          #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
  10.160 -        if vdev in self.devices: return -1
  10.161 -        dev = BlkDev(vdev, mode, segment)
  10.162 -        self.devices[vdev] = dev
  10.163 -        self.send_be_vbd_create(vdev)
  10.164 -        return self.factory.addDeferred()
  10.165 +        dev = self.addDevice(vdev, mode, segment)
  10.166 +        if not dev: return -1
  10.167 +        if recreate:
  10.168 +            d = defer.Deferred()
  10.169 +            d.callback(self)
  10.170 +        else:
  10.171 +            self.send_be_vbd_create(vdev)
  10.172 +            d = self.factory.addDeferred()
  10.173 +        return d
  10.174 +
  10.175 +    def destroy(self):
  10.176 +        self.destroyDevices()
  10.177 +
  10.178 +    def destroyDevices(self):
  10.179 +        for dev in self.getDevices():
  10.180 +            dev.destroy()
  10.181  
  10.182      def detach(self):
  10.183          """Detach all devices, when the back-end control domain has changed.
  10.184 @@ -178,7 +215,7 @@ class BlkifController(controller.Control
  10.185              dev.attached = 0
  10.186              self.send_be_vbd_create(vdev)
  10.187  
  10.188 -    def reattach_device(self, vdev):
  10.189 +    def reattachDevice(self, vdev):
  10.190          """Reattach a device, when the back-end control domain has changed.
  10.191          """
  10.192          dev = self.devices[vdev]
  10.193 @@ -254,4 +291,13 @@ class BlkifController(controller.Control
  10.194                          'extent.sector_start'  : dev.start_sector,
  10.195                          'extent.sector_length' : dev.nr_sectors })
  10.196          self.factory.writeRequest(msg)
  10.197 +
  10.198 +    def send_be_vbd_destroy(self, vdev):
  10.199 +        dev = self.devices[vdev]
  10.200 +        msg = packMsg('blkif_be_vbd_destroy_t',
  10.201 +                      { 'domid'                : self.dom,
  10.202 +                        'blkif_handle'         : 0,
  10.203 +                        'vdevice'              : dev.vdev })
  10.204 +        del self.devices[vdev]
  10.205 +        self.factory.writeRequest(msg)
  10.206      
    11.1 --- a/tools/xenmgr/lib/server/controller.py	Thu Jun 24 15:04:30 2004 +0000
    11.2 +++ b/tools/xenmgr/lib/server/controller.py	Thu Jun 24 15:13:59 2004 +0000
    11.3 @@ -95,7 +95,7 @@ class ControllerFactory(CtrlMsgRcvr):
    11.4          if instance.idx in self.instances:
    11.5              del self.instances[instance.idx]
    11.6  
    11.7 -    def createInstance(self, dom):
    11.8 +    def createInstance(self, dom, recreate=0):
    11.9          raise NotImplementedError()
   11.10  
   11.11      def instanceClosed(self, instance):
   11.12 @@ -136,3 +136,30 @@ class Controller(CtrlMsgRcvr):
   11.13  
   11.14      def lostChannel(self):
   11.15          self.factory.instanceClosed(self)
   11.16 +
   11.17 +class Dev:
   11.18 +
   11.19 +    def __init__(self, controller):
   11.20 +        self.controller = controller
   11.21 +        self.props = {}
   11.22 +
   11.23 +    def setprop(self, k, v):
   11.24 +        self.props[k] = v
   11.25 +
   11.26 +    def getprop(self, k, v=None):
   11.27 +        return self.props.get(k, v)
   11.28 +
   11.29 +    def hasprop(self, k):
   11.30 +        return k in self.props
   11.31 +
   11.32 +    def delprop(self, k):
   11.33 +        if k in self.props:
   11.34 +            del self.props[k]
   11.35 +
   11.36 +    #def __repr__(self):
   11.37 +    #    return str(self.sxpr())
   11.38 +
   11.39 +    def sxpr(self):
   11.40 +        raise NotImplementedError()
   11.41 +
   11.42 +    
    12.1 --- a/tools/xenmgr/lib/server/messages.py	Thu Jun 24 15:04:30 2004 +0000
    12.2 +++ b/tools/xenmgr/lib/server/messages.py	Thu Jun 24 15:13:59 2004 +0000
    12.3 @@ -76,6 +76,9 @@ blkif_formats = {
    12.4      'blkif_be_vbd_grow_t':
    12.5      (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
    12.6  
    12.7 +    'blkif_be_vbd_destroy_t':
    12.8 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
    12.9 +
   12.10      'blkif_fe_interface_status_changed_t':
   12.11      (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
   12.12  
    13.1 --- a/tools/xenmgr/lib/server/netif.py	Thu Jun 24 15:04:30 2004 +0000
    13.2 +++ b/tools/xenmgr/lib/server/netif.py	Thu Jun 24 15:13:59 2004 +0000
    13.3 @@ -1,5 +1,9 @@
    13.4  import random
    13.5  
    13.6 +from twisted.internet import defer
    13.7 +
    13.8 +from xenmgr import XendBridge
    13.9 +
   13.10  import channel
   13.11  import controller
   13.12  from messages import *
   13.13 @@ -22,7 +26,7 @@ class NetifControllerFactory(controller.
   13.14          self.attached = 1
   13.15          self.registerChannel()
   13.16  
   13.17 -    def createInstance(self, dom):
   13.18 +    def createInstance(self, dom, recreate=0):
   13.19          """Create or find the network interface controller for a domain.
   13.20          """
   13.21          #print 'netif>createInstance> dom=', dom
   13.22 @@ -40,12 +44,13 @@ class NetifControllerFactory(controller.
   13.23          netif = self.getInstanceByDom(dom)
   13.24          return (netif and netif.getDevice(vif)) or None
   13.25          
   13.26 -    def setControlDomain(self, dom):
   13.27 +    def setControlDomain(self, dom, recreate=0):
   13.28          """Set the 'back-end' device driver domain.
   13.29          """
   13.30          if self.dom == dom: return
   13.31          self.deregisterChannel()
   13.32 -        self.attached = 0
   13.33 +        if not recreate:
   13.34 +            self.attached = 0
   13.35          self.dom = dom
   13.36          self.registerChannel()
   13.37          #
   13.38 @@ -98,20 +103,38 @@ class NetifControllerFactory(controller.
   13.39  ##                 print "Done notifying guests"
   13.40  ##                 recovery = False
   13.41                  
   13.42 -class NetDev:
   13.43 +class NetDev(controller.Dev):
   13.44      """Info record for a network device.
   13.45      """
   13.46  
   13.47 -    def __init__(self, vif, mac):
   13.48 +    def __init__(self, ctrl, vif, mac):
   13.49 +        controller.Dev.__init__(self, ctrl)
   13.50          self.vif = vif
   13.51          self.mac = mac
   13.52          self.evtchn = None
   13.53 +        self.bridge = None
   13.54  
   13.55      def sxpr(self):
   13.56          vif = str(self.vif)
   13.57          mac = ':'.join(map(lambda x: "%x" % x, self.mac))
   13.58 -        return ['netif', ['vif', vif], ['mac', mac]]
   13.59 -    
   13.60 +        val = ['netif', ['vif', vif], ['mac', mac]]
   13.61 +        if self.bridge:
   13.62 +            val += ['bridge', self.bridge]
   13.63 +        return val
   13.64 +
   13.65 +    def bridge_add(self, bridge):
   13.66 +        self.bridge = XendBridge.vif_bridge_add(self.controller.dom, self.vif, bridge)
   13.67 +
   13.68 +    def bridge_rem(self):
   13.69 +        if not self.bridge: return
   13.70 +        XendBridge.vif_bridge_rem(self.controller.dom, self.vif, self.bridge)
   13.71 +        self.bridge = None
   13.72 +
   13.73 +    def destroy(self):
   13.74 +        self.bridge_rem()
   13.75 +        self.controller.send_be_destroy(self.vif)
   13.76 +        
   13.77 +
   13.78  class NetifController(controller.Controller):
   13.79      """Network interface controller. Handles all network devices for a domain.
   13.80      """
   13.81 @@ -150,8 +173,7 @@ class NetifController(controller.Control
   13.82  
   13.83      def lostChannel(self):
   13.84          print 'NetifController>lostChannel>', 'dom=', self.dom
   13.85 -        #for vif in self.devices:
   13.86 -        #    self.send_be_destroy(vif)
   13.87 +        #self.destroyDevices()
   13.88          controller.Controller.lostChannel(self)
   13.89  
   13.90      def getDevices(self):
   13.91 @@ -167,11 +189,18 @@ class NetifController(controller.Control
   13.92              mac = [ int(x, 16) for x in vmac.split(':') ]
   13.93          if len(mac) != 6: raise ValueError("invalid mac")
   13.94          #print "attach_device>", "vif=", vif, "mac=", mac
   13.95 -        dev = NetDev(vif, mac)
   13.96 +        dev = NetDev(self, vif, mac)
   13.97          self.devices[vif] = dev
   13.98          return dev
   13.99  
  13.100 -    def attach_device(self, vif, vmac):
  13.101 +    def destroy(self):
  13.102 +        self.destroyDevices()
  13.103 +        
  13.104 +    def destroyDevices(self):
  13.105 +        for dev in self.getDevices():
  13.106 +            dev.destroy()
  13.107 +
  13.108 +    def attachDevice(self, vif, vmac, recreate=0):
  13.109          """Attach a network device.
  13.110          If vmac is None a random mac address is assigned.
  13.111  
  13.112 @@ -179,8 +208,12 @@ class NetifController(controller.Control
  13.113          @param vmac mac address (string)
  13.114          """
  13.115          self.addDevice(vif, vmac)
  13.116 -        d = self.factory.addDeferred()
  13.117 -        self.send_be_create(vif)
  13.118 +        if recreate:
  13.119 +            d = defer.Deferred()
  13.120 +            d.callback(self)
  13.121 +        else:
  13.122 +            d = self.factory.addDeferred()
  13.123 +            self.send_be_create(vif)
  13.124          return d
  13.125  
  13.126      def reattach_devices(self):
    14.1 --- a/tools/xenmgr/lib/xm/create.py	Thu Jun 24 15:04:30 2004 +0000
    14.2 +++ b/tools/xenmgr/lib/xm/create.py	Thu Jun 24 15:13:59 2004 +0000
    14.3 @@ -1,3 +1,6 @@
    14.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    14.5 +"""Domain creation.
    14.6 +"""
    14.7  import string
    14.8  import sys
    14.9  
   14.10 @@ -13,7 +16,7 @@ Create a domain.
   14.11  """)
   14.12  
   14.13  gopts.opt('help', short='h',
   14.14 -         fn=set_value, default=0,
   14.15 +         fn=set_true, default=0,
   14.16           use="Print this help.")
   14.17  
   14.18  gopts.opt('quiet', short='q',
   14.19 @@ -36,21 +39,19 @@ gopts.opt('load', short='L', val='FILE',
   14.20            fn=set_value, default=None,
   14.21            use='Domain saved state to load.')
   14.22  
   14.23 -def set_var(opt, k, v):
   14.24 -    opt.set(v)
   14.25 -    for d in string.split(v, ';' ):
   14.26 -        (k, v) = string.split(d, '=')
   14.27 -        opt.opts.setvar(k, v)
   14.28 -
   14.29  gopts.opt('define', short='D', val='VAR=VAL',
   14.30           fn=set_var, default=None,
   14.31 -         use="""Set variables before loading defaults, e.g. '-D vmid=3;ip=1.2.3.4'
   14.32 -         to set vmid and ip.""")
   14.33 +         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
   14.34 +         to set vmid. May be repeated to set more thanone variable.""")
   14.35  
   14.36  gopts.opt('dryrun', short='n',
   14.37           fn=set_true, default=0,
   14.38           use="Dry run - print the config but don't create the domain.")
   14.39  
   14.40 +gopts.opt('name', short='N', val='NAME',
   14.41 +          fn=set_value, default=None,
   14.42 +          use="Domain name.")
   14.43 +
   14.44  gopts.opt('console', short='c',
   14.45           fn=set_true, default=0,
   14.46           use="Connect to console after domain is created.")
   14.47 @@ -71,34 +72,48 @@ gopts.opt('memory', short='m', val='MEMO
   14.48           fn=set_value, default=128,
   14.49           use="Domain memory in MB.")
   14.50  
   14.51 +gopts.opt('blkif',
   14.52 +          fn=set_true, default=0,
   14.53 +          use="Make the domain a block device backend.")
   14.54 +
   14.55 +gopts.opt('netif',
   14.56 +          fn=set_true, default=0,
   14.57 +          use="Make the domain a network interface backend.")
   14.58 +
   14.59  gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
   14.60           fn=append_value, default=[],
   14.61           use="""Add a disk device to a domain. The physical device is DEV, which
   14.62 -         is exported to the domain as VDEV. The disk is read-only if MODE is r,
   14.63 -         read-write if mode is 'w'.""")
   14.64 +         is exported to the domain as VDEV. The disk is read-only if MODE
   14.65 +         is 'r', read-write if MODE is 'w'.
   14.66 +         The option may be repeated to add more than one disk.
   14.67 +         """)
   14.68  
   14.69  gopts.opt('pci', val='BUS,DEV,FUNC',
   14.70           fn=append_value, default=[],
   14.71 -         use="""Add a PCI device to a domain, using given params (in hex).""")
   14.72 +         use="""Add a PCI device to a domain, using given params (in hex).
   14.73 +         For example '-pci c0,02,1a'.
   14.74 +         The option may be repeated to add more than one pci device.
   14.75 +         """)
   14.76  
   14.77  gopts.opt('ipaddr', short='i', val="IPADDR",
   14.78           fn=append_value, default=[],
   14.79           use="Add an IP address to the domain.")
   14.80  
   14.81 -gopts.opt('mac', short='M', val="MAC",
   14.82 +gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
   14.83           fn=append_value, default=[],
   14.84 -         use="""Add a network interface with the given mac address to the domain.
   14.85 -         More than one interface may be specified. Interfaces with unspecified MAC addresses
   14.86 -         are allocated a random address.""")
   14.87 +         use="""Add a network interface with the given MAC address and bridge.
   14.88 +         If mac is not specified a random MAC address is used.
   14.89 +         If bridge is not specified the default bridge is used.
   14.90 +         This option may be repeated to add more than one vif.
   14.91 +         Specifying vifs will increase the number of interfaces as needed.
   14.92 +         """)
   14.93  
   14.94 -gopts.opt('nics', val="N",
   14.95 +gopts.opt('nics', val="NUM",
   14.96           fn=set_int, default=1,
   14.97 -         use="Set the number of network interfaces.")
   14.98 -
   14.99 -gopts.opt('vnet', val='VNET',
  14.100 -         fn=append_value, default=[],
  14.101 -         use="""Define the vnets for the network interfaces.
  14.102 -         More than one vnet may be given, they are used in order.
  14.103 +         use="""Set the number of network interfaces.
  14.104 +         Use the vif option to define interface parameters, otherwise
  14.105 +         defaults are used. Specifying vifs will increase the
  14.106 +         number of interfaces as needed.
  14.107           """)
  14.108  
  14.109  gopts.opt('root', short='R', val='DEVICE',
  14.110 @@ -116,15 +131,15 @@ gopts.opt('ip', short='I', val='IPADDR',
  14.111  
  14.112  gopts.opt('gateway', val="IPADDR",
  14.113           fn=set_value, default='',
  14.114 -         use="Set kernel IP gateway.")
  14.115 +         use="Set the kernel IP gateway.")
  14.116  
  14.117  gopts.opt('netmask', val="MASK",
  14.118           fn=set_value, default = '',
  14.119 -         use="Set kernel IP netmask.")
  14.120 +         use="Set the kernel IP netmask.")
  14.121  
  14.122  gopts.opt('hostname', val="NAME",
  14.123           fn=set_value, default='',
  14.124 -         use="Set kernel IP hostname.")
  14.125 +         use="Set the kernel IP hostname.")
  14.126  
  14.127  gopts.opt('interface', val="INTF",
  14.128           fn=set_value, default="eth0",
  14.129 @@ -132,7 +147,7 @@ gopts.opt('interface', val="INTF",
  14.130  
  14.131  gopts.opt('dhcp', val="off|dhcp",
  14.132           fn=set_value, default='off',
  14.133 -         use="Set kernel dhcp option.")
  14.134 +         use="Set the kernel dhcp option.")
  14.135  
  14.136  gopts.opt('nfs_server', val="IPADDR",
  14.137           fn=set_value, default=None,
  14.138 @@ -143,19 +158,16 @@ gopts.opt('nfs_root', val="PATH",
  14.139           use="Set the path of the root NFS directory.")
  14.140  
  14.141  def strip(pre, s):
  14.142 +    """Strip prefix 'pre' if present.
  14.143 +    """
  14.144      if s.startswith(pre):
  14.145          return s[len(pre):]
  14.146      else:
  14.147          return s
  14.148  
  14.149 -def make_config(opts):
  14.150 -    
  14.151 -    config = ['config',
  14.152 -              ['name', opts.name ],
  14.153 -              ['memory', opts.memory ] ]
  14.154 -    if opts.cpu:
  14.155 -        config.append(['cpu', opts.cpu])
  14.156 -    
  14.157 +def configure_image(config, opts):
  14.158 +    """Create the image config.
  14.159 +    """
  14.160      config_image = [ opts.builder ]
  14.161      config_image.append([ 'kernel', os.path.abspath(opts.kernel) ])
  14.162      if opts.ramdisk:
  14.163 @@ -169,8 +181,10 @@ def make_config(opts):
  14.164      if opts.extra:
  14.165          config_image.append(['args', opts.extra])
  14.166      config.append(['image', config_image ])
  14.167 -    	
  14.168 -    config_devs = []
  14.169 +    
  14.170 +def configure_disks(config_devs, opts):
  14.171 +    """Create the config for disks (virtual block devices).
  14.172 +    """
  14.173      for (uname, dev, mode) in opts.disk:
  14.174          config_vbd = ['vbd',
  14.175                        ['uname', uname],
  14.176 @@ -178,18 +192,34 @@ def make_config(opts):
  14.177                        ['mode', mode ] ]
  14.178          config_devs.append(['device', config_vbd])
  14.179  
  14.180 +def configure_pci(config_devs, opts):
  14.181 +    """Create the config for pci devices.
  14.182 +    """
  14.183      for (bus, dev, func) in opts.pci:
  14.184          config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
  14.185          config_devs.append(['device', config_pci])
  14.186  
  14.187 -    for idx in range(0, opts.nics):
  14.188 -        config_vif = ['vif', ['@', ['id', 'vif%d' % idx]]]
  14.189 -        if idx < len(opts.mac):
  14.190 -            config_vif.append(['mac', opts.mac[idx]])
  14.191 +def configure_vifs(config_devs, opts):
  14.192 +    """Create the config for virtual network interfaces.
  14.193 +    """
  14.194 +    vifs = opts.vif
  14.195 +    vifs_n = max(opts.nics, len(vifs))
  14.196 +
  14.197 +    for idx in range(0, vifs_n):
  14.198 +        if idx < len(vifs):
  14.199 +            d = vifs[idx]
  14.200 +            mac = d.get('mac')
  14.201 +            bridge = d.get('bridge')
  14.202 +        else:
  14.203 +            mac = None
  14.204 +            bridge = None
  14.205 +        config_vif = ['vif']
  14.206 +        if mac:
  14.207 +            config_vif.append(['mac', mac])
  14.208 +        if bridge:
  14.209 +            config_vif.append(['bridge', bridge])
  14.210          config_devs.append(['device', config_vif])
  14.211  
  14.212 -    config += config_devs
  14.213 -
  14.214  ##     if vfr_ipaddr:
  14.215  ##         config_vfr = ['vfr']
  14.216  ##         idx = 0 # No way of saying which IP is for which vif?
  14.217 @@ -197,15 +227,27 @@ def make_config(opts):
  14.218  ##             config_vfr.append(['vif', ['id', idx], ['ip', ip]])
  14.219  ##         config.append(config_vfr)
  14.220  
  14.221 -    if opts.vnet:
  14.222 -        config_vnet = ['vnet']
  14.223 -        idx = 0
  14.224 -        for vnet in opts.vnet:
  14.225 -            config_vif = ['vif', ['id', 'vif%d' % idx], ['vnet', vnet]]
  14.226 -            config_vnet.append(config_vif)
  14.227 -            idx += 1
  14.228 -        config.append(config_vnet)
  14.229 -            
  14.230 +
  14.231 +def make_config(opts):
  14.232 +    """Create the domain configuration.
  14.233 +    """
  14.234 +    
  14.235 +    config = ['vm',
  14.236 +              ['name', opts.name ],
  14.237 +              ['memory', opts.memory ] ]
  14.238 +    if opts.cpu:
  14.239 +        config.append(['cpu', opts.cpu])
  14.240 +    if opts.blkif:
  14.241 +        config.append(['backend', ['blkif']])
  14.242 +    if opts.netif:
  14.243 +        config.append(['backend', ['netif']])
  14.244 +    
  14.245 +    configure_image(config, opts)
  14.246 +    config_devs = []
  14.247 +    configure_disks(config_devs, opts)
  14.248 +    configure_pci(config_devs, opts)
  14.249 +    configure_vifs(config_devs, opts)
  14.250 +    config += config_devs
  14.251      return config
  14.252  
  14.253  def preprocess_disk(opts):
  14.254 @@ -213,7 +255,6 @@ def preprocess_disk(opts):
  14.255      disk = []
  14.256      for v in opts.disk:
  14.257          d = v.split(',')
  14.258 -        print 'disk', v, d
  14.259          if len(d) != 3:
  14.260              opts.err('Invalid disk specifier: ' + v)
  14.261          disk.append(d)
  14.262 @@ -231,6 +272,22 @@ def preprocess_pci(opts):
  14.263          pci.append(hexd)
  14.264      opts.pci = pci
  14.265  
  14.266 +def preprocess_vifs(opts):
  14.267 +    if not opts.vif: return
  14.268 +    vifs = []
  14.269 +    for vif in opts.vif:
  14.270 +        d = {}
  14.271 +        a = vif.split(',')
  14.272 +        for b in a:
  14.273 +            (k, v) = b.strip().split('=')
  14.274 +            k = k.strip()
  14.275 +            v = v.strip()
  14.276 +            if k not in ['mac', 'bridge']:
  14.277 +                opts.err('Invalid vif specifier: ' + vif)
  14.278 +            d[k] = v
  14.279 +        vifs.append(d)
  14.280 +    opts.vif = vifs
  14.281 +
  14.282  def preprocess_ip(opts):
  14.283      setip = (opts.hostname or opts.netmask
  14.284               or opts.gateway or opts.dhcp or opts.interface)
  14.285 @@ -259,6 +316,7 @@ def preprocess(opts):
  14.286          opts.err("No kernel specified")
  14.287      preprocess_disk(opts)
  14.288      preprocess_pci(opts)
  14.289 +    preprocess_vifs(opts)
  14.290      preprocess_ip(opts)
  14.291      preprocess_nfs(opts)
  14.292           
  14.293 @@ -266,8 +324,8 @@ def make_domain(opts, config):
  14.294      """Create, build and start a domain.
  14.295      Returns: [int] the ID of the new domain.
  14.296      """
  14.297 -    if opts.load:
  14.298 -        filename = os.path.abspath(opts.load)
  14.299 +    if opts.vals.load:
  14.300 +        filename = os.path.abspath(opts.vals.load)
  14.301          dominfo = server.xend_domain_restore(filename, config)
  14.302      else:
  14.303          dominfo = server.xend_domain_create(config)
  14.304 @@ -280,7 +338,7 @@ def make_domain(opts, config):
  14.305          console_port = None
  14.306      
  14.307      if server.xend_domain_unpause(dom) < 0:
  14.308 -        server.xend_domain_halt(dom)
  14.309 +        server.xend_domain_destroy(dom)
  14.310          opts.err("Failed to start domain %d" % dom)
  14.311      opts.info("Started domain %d, console on port %d"
  14.312                % (dom, console_port))
  14.313 @@ -289,16 +347,16 @@ def make_domain(opts, config):
  14.314  def main(argv):
  14.315      opts = gopts
  14.316      args = opts.parse(argv)
  14.317 -    if opts.help:
  14.318 +    if opts.vals.help:
  14.319          opts.usage()
  14.320          return
  14.321 -    if opts.config:
  14.322 +    if opts.vals.config:
  14.323          pass
  14.324      else:
  14.325          opts.load_defaults()
  14.326 -    preprocess(opts)
  14.327 -    config = make_config(opts)
  14.328 -    if opts.dryrun:
  14.329 +    preprocess(opts.vals)
  14.330 +    config = make_config(opts.vals)
  14.331 +    if opts.vals.dryrun:
  14.332          PrettyPrint.prettyprint(config)
  14.333      else:
  14.334          make_domain(opts, config)
    15.1 --- a/tools/xenmgr/lib/xm/main.py	Thu Jun 24 15:04:30 2004 +0000
    15.2 +++ b/tools/xenmgr/lib/xm/main.py	Thu Jun 24 15:13:59 2004 +0000
    15.3 @@ -10,27 +10,72 @@ from xenmgr import sxp
    15.4  from xenmgr.XendClient import server
    15.5  from xenmgr.xm import create, shutdown
    15.6  
    15.7 +class Prog:
    15.8 +    """Base class for sub-programs.
    15.9 +    """
   15.10 +
   15.11 +    """Program group it belongs to"""
   15.12 +    group = 'all'
   15.13 +    """Program name."""
   15.14 +    name = '??'
   15.15 +    """Short program info."""
   15.16 +    info = ''
   15.17 +
   15.18 +    def __init__(self, xm):
   15.19 +        self.xm = xm
   15.20 +
   15.21 +    def err(self, msg):
   15.22 +        self.xm.err(msg)
   15.23 +
   15.24 +    def help(self, args):
   15.25 +        self.shortHelp(args)
   15.26 +
   15.27 +    def shortHelp(self, args):
   15.28 +        print "%-14s %s" % (self.name, self.info)
   15.29 +
   15.30 +    def main(self, args):
   15.31 +        """Program main entry point.
   15.32 +        """
   15.33 +        pass
   15.34 +
   15.35 +
   15.36 +class ProgUnknown(Prog):
   15.37 +
   15.38 +    name = 'unknown'
   15.39 +    info = ''
   15.40 +    
   15.41 +    def help(self, args):
   15.42 +        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
   15.43 +                    % (args[0], self.xm.name))
   15.44 +
   15.45 +    main = help
   15.46 +
   15.47  class Xm:
   15.48 +    """Main application.
   15.49 +    """
   15.50  
   15.51      def __init__(self):
   15.52 -        self.prog = 'xm'
   15.53 -        pass
   15.54 +        self.name = 'xm'
   15.55 +        self.unknown = ProgUnknown(self)
   15.56 +        self.progs = {}
   15.57  
   15.58      def err(self, msg):
   15.59          print >>sys.stderr, "Error:", msg
   15.60          sys.exit(1)
   15.61  
   15.62      def main(self, args):
   15.63 -        """Main entry point. Dispatches to the xm_ methods.
   15.64 +        """Main entry point. Dispatches to the progs.
   15.65          """
   15.66 -        self.prog = args[0]
   15.67 +        self.name = args[0]
   15.68          if len(args) < 2:
   15.69              self.err("Missing command\nTry '%s help' for more information."
   15.70 -                     % self.prog)
   15.71 -        prog = 'xm_' + args[1]
   15.72 +                     % self.name)
   15.73          help = self.helparg(args)
   15.74 -        fn = getattr(self, prog, self.unknown)
   15.75 -        fn(help, args[1:])
   15.76 +        p = self.getprog(args[1], self.unknown)
   15.77 +        if help:
   15.78 +            p.help(args[1:])
   15.79 +        else:
   15.80 +            p.main(args[1:])
   15.81  
   15.82      def helparg(self, args):
   15.83          for a in args:
   15.84 @@ -38,40 +83,88 @@ class Xm:
   15.85                  return 1
   15.86          return 0
   15.87  
   15.88 -    def unknown(self, help, args):
   15.89 -        if help and len(args) == 1:
   15.90 -            self.xm_help(help, args)
   15.91 -        else:
   15.92 -            self.err("Unknown command: %s\nTry '%s help' for more information."
   15.93 -                     % (args[0], self.prog))
   15.94 +    def prog(self, pklass):
   15.95 +        """Add a sub-program.
   15.96  
   15.97 -    def help(self, meth, args):
   15.98 -        """Print help on an xm_ method.
   15.99 -        Uses the method documentation string if there is one.
  15.100 +        pklass  program class (Prog subclass)
  15.101 +        """
  15.102 +        p = pklass(self)
  15.103 +        self.progs[p.name] = p
  15.104 +        return p
  15.105 +
  15.106 +    def getprog(self, name, val=None):
  15.107 +        """Get a sub-program.
  15.108 +        """
  15.109 +        return self.progs.get(name, val)
  15.110 +
  15.111 +    def proglist(self):
  15.112 +        """Get a list of sub-programs, ordered by group.
  15.113          """
  15.114 -        name = meth[3:]
  15.115 -        f = getattr(self, meth)
  15.116 -        print "%-14s %s" % (name, f.__doc__ or '')
  15.117 +        groups = {}
  15.118 +        for p in self.progs.values():
  15.119 +            l = groups.get(p.group, [])
  15.120 +            l.append(p)
  15.121 +            groups[p.group] = l
  15.122 +        kl = groups.keys()
  15.123 +        kl.sort()
  15.124 +        pl = []
  15.125 +        for k in kl:
  15.126 +            l = groups[k]
  15.127 +            l.sort()
  15.128 +            pl += l
  15.129 +        return pl
  15.130 +        
  15.131 +# Create the application object, then add the sub-program classes.
  15.132 +xm = Xm()
  15.133 +
  15.134 +class ProgHelp(Prog):
  15.135  
  15.136 -    def xm_help(self, help, args):
  15.137 -        """Print help."""
  15.138 -        for k in dir(self):
  15.139 -            if not k.startswith('xm_'): continue
  15.140 -            self.help(k, args)
  15.141 -        print "\nTry '%s CMD -h' for help on CMD" % self.prog
  15.142 -                
  15.143 -    def xm_create(self, help, args):
  15.144 -        """Create a domain."""
  15.145 +    name = "help"
  15.146 +    info = "Print help."
  15.147 +    
  15.148 +    def help(self, args):
  15.149 +        if len(args) == 2:
  15.150 +            name = args[1]
  15.151 +            p = self.xm.getprog(name)
  15.152 +            if p:
  15.153 +                p.help(args)
  15.154 +            else:
  15.155 +                print '%s: Unknown command: %s' % (self.name, name)
  15.156 +        else:
  15.157 +            for p in self.xm.proglist():
  15.158 +                p.shortHelp(args)
  15.159 +            print "\nTry '%s help CMD' for help on CMD" % self.xm.name
  15.160 +
  15.161 +    main = help
  15.162 +
  15.163 +xm.prog(ProgHelp)
  15.164 +
  15.165 +class ProgCreate(Prog):
  15.166 +
  15.167 +    group = 'domain'
  15.168 +    name = "create"
  15.169 +    info = """Create a domain."""
  15.170 +
  15.171 +    def help(self, args):
  15.172 +        create.main([args[0], '-h'])
  15.173 +
  15.174 +    def main(self, args):
  15.175          create.main(args)
  15.176  
  15.177 -    def xm_save(self, help, args):
  15.178 -        """Save domain state (and config) to file."""
  15.179 -        if help:
  15.180 -            print args[0], "DOM FILE [CONFIG]"
  15.181 -            print """\nSave domain with id DOM to FILE.
  15.182 -            Optionally save config to CONFIG."""
  15.183 -            return
  15.184 -        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
  15.185 +xm.prog(ProgCreate)
  15.186 +
  15.187 +class ProgSave(Prog):
  15.188 +    group = 'domain'
  15.189 +    name = "save"
  15.190 +    info = """Save domain state (and config) to file."""
  15.191 +
  15.192 +    def help(self, args):
  15.193 +        print self.name, "DOM FILE [CONFIG]"
  15.194 +        print """\nSave domain with id DOM to FILE.
  15.195 +        Optionally save config to CONFIG."""
  15.196 +        
  15.197 +    def main(self, args):
  15.198 +        if len(args) < 3: self.err("%s: Missing arguments" % self.name)
  15.199          dom = args[1]
  15.200          savefile = os.path.abspath(args[2])
  15.201          configfile = None
  15.202 @@ -83,23 +176,45 @@ class Xm:
  15.203              PrettyPrint.prettyprint(config, out=out)
  15.204              out.close()
  15.205          server.xend_domain_save(dom, savefile)
  15.206 -            
  15.207 -    def xm_restore(self, help, args):
  15.208 -        """Create a domain from a saved state."""
  15.209 -        if help:
  15.210 -            print args[0], "FILE CONFIG"
  15.211 -            print "\nRestore a domain from FILE using configuration CONFIG."
  15.212 -            return
  15.213 -        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
  15.214 +
  15.215 +xm.prog(ProgSave)
  15.216 +
  15.217 +class ProgRestore(Prog):
  15.218 +    group = 'domain'
  15.219 +    name = "restore"
  15.220 +    info = """Create a domain from a saved state."""
  15.221 +
  15.222 +    def help(self, args):
  15.223 +        print self.name, "FILE CONFIG"
  15.224 +        print "\nRestore a domain from FILE using configuration CONFIG."
  15.225 +    
  15.226 +    def main(self, help, args):
  15.227 +        if len(args) < 3: self.err("%s: Missing arguments" % self.name)
  15.228          savefile =  os.path.abspath(args[1])
  15.229          configfile = os.path.abspath(args[2])
  15.230          info = server.xend_domain_restore(savefile, configfile)
  15.231          PrettyPrint.prettyprint(info)
  15.232  
  15.233 -    def xm_domains(self, help, args):
  15.234 -        """List domains."""
  15.235 -        if help: self.help('xm_' + args[0], args); return
  15.236 -        doms = server.xend_domains()
  15.237 +xm.prog(ProgRestore)
  15.238 +
  15.239 +class ProgList(Prog):
  15.240 +    group = 'domain'
  15.241 +    name = "list"
  15.242 +    info = """List info about domains."""
  15.243 +
  15.244 +    def help(self, args):
  15.245 +        if help:
  15.246 +            print self.name, '[DOM...]'
  15.247 +            print """\nGet information about domains.
  15.248 +            Either all domains or the domains given."""
  15.249 +            return
  15.250 +        
  15.251 +    def main(self, args):
  15.252 +        n = len(args)
  15.253 +        if n == 1:
  15.254 +            doms = server.xend_domains()
  15.255 +        else:
  15.256 +            doms = map(int, args[1:])
  15.257          doms.sort()
  15.258          print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
  15.259          for dom in doms:
  15.260 @@ -113,111 +228,167 @@ class Xm:
  15.261              d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
  15.262              print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
  15.263  
  15.264 -    def xm_domain(self, help, args):
  15.265 -        """Get information about a domain."""
  15.266 -        if help:
  15.267 -            print args[0], 'DOM'
  15.268 -            print '\nGet information about domain DOM.'
  15.269 -            return
  15.270 -        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  15.271 -        dom = args[1]
  15.272 -        info = server.xend_domain(dom)
  15.273 -        PrettyPrint.prettyprint(info)
  15.274 -        print
  15.275 +xm.prog(ProgList)
  15.276 +
  15.277 +class ProgDestroy(Prog):
  15.278 +    group = 'domain'
  15.279 +    name = "destroy"
  15.280 +    info = """Terminate a domain immediately."""
  15.281 +
  15.282 +    def help(self, args):
  15.283 +        print self.name, 'DOM'
  15.284 +        print '\nTerminate domain DOM immediately.'
  15.285  
  15.286 -    def xm_halt(self, help, args):
  15.287 -        """Terminate a domain immediately."""
  15.288 -        if help:
  15.289 -            print args[0], 'DOM'
  15.290 -            print '\nTerminate domain DOM immediately.'
  15.291 -            return
  15.292 -        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  15.293 +    def main(self, args):
  15.294 +        if len(args) < 2: self.err("%s: Missing domain" % self.name)
  15.295          dom = args[1]
  15.296 -        server.xend_domain_halt(dom)
  15.297 +        server.xend_domain_destroy(dom)
  15.298 +
  15.299 +xm.prog(ProgDestroy)
  15.300  
  15.301 -    def xm_shutdown(self, help, args):
  15.302 -        """Shutdown a domain."""
  15.303 +class ProgShutdown(Prog):
  15.304 +    group = 'domain'
  15.305 +    name = "shutdown"
  15.306 +    info = """Shutdown a domain."""
  15.307 +
  15.308 +    def help(self, args):
  15.309 +        print self.name, 'DOM'
  15.310 +        print '\nSignal domain DOM to shutdown.'
  15.311 +    
  15.312 +    def main(self, args):
  15.313          shutdown.main(args)
  15.314  
  15.315 -    def xm_pause(self, help, args):
  15.316 -        """Pause execution of a domain."""
  15.317 -        if help:
  15.318 -            print args[0], 'DOM'
  15.319 -            print '\nPause execution of domain DOM.'
  15.320 -            return
  15.321 -        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  15.322 +xm.prog(ProgShutdown)
  15.323 +
  15.324 +class ProgPause(Prog):
  15.325 +    group = 'domain'
  15.326 +    name = "pause"
  15.327 +    info = """Pause execution of a domain."""
  15.328 +
  15.329 +    def help(self, args):
  15.330 +        print self.name, 'DOM'
  15.331 +        print '\nPause execution of domain DOM.'
  15.332 +
  15.333 +    def main(self, args):
  15.334 +        if len(args) < 2: self.err("%s: Missing domain" % self.name)
  15.335          dom = args[1]
  15.336          server.xend_domain_pause(dom)
  15.337  
  15.338 -    def xm_unpause(self, help, args):
  15.339 -        """Unpause a paused domain."""
  15.340 -        if help:
  15.341 -            print args[0], 'DOM'
  15.342 -            print '\nUnpause execution of domain DOM.'
  15.343 -            return
  15.344 -        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  15.345 +xm.prog(ProgPause)
  15.346 +
  15.347 +class ProgUnpause(Prog):
  15.348 +    group = 'domain'
  15.349 +    name = "unpause"
  15.350 +    info = """Unpause a paused domain."""
  15.351 +
  15.352 +    def help(self, args):
  15.353 +        print self.name, 'DOM'
  15.354 +        print '\nUnpause execution of domain DOM.'
  15.355 +
  15.356 +    def main(self, args):
  15.357 +        if len(args) < 2: self.err("%s: Missing domain" % self.name)
  15.358          dom = args[1]
  15.359          server.xend_domain_unpause(dom)
  15.360  
  15.361 -    def xm_pincpu(self, help, args):
  15.362 -        """Pin a domain to a cpu. """
  15.363 -        if help:
  15.364 -            print args[0],'DOM CPU'
  15.365 -            print '\nPin domain DOM to cpu CPU.'
  15.366 -            return
  15.367 -        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
  15.368 +xm.prog(ProgUnpause)
  15.369 +
  15.370 +class ProgPincpu(Prog):
  15.371 +    group = 'domain'
  15.372 +    name = "pincpu"
  15.373 +    info = """Pin a domain to a cpu. """
  15.374 +
  15.375 +    def help(self, args):
  15.376 +        print self.name,'DOM CPU'
  15.377 +        print '\nPin domain DOM to cpu CPU.'
  15.378 +
  15.379 +    def main(self, args):
  15.380 +        if len(args) != 3: self.err("%s: Invalid argument(s)" % self.name)
  15.381          v = map(int, args[1:3])
  15.382          server.xend_domain_pincpu(*v)
  15.383  
  15.384 -    def xm_bvt(self, help, args):
  15.385 -        """Set BVT scheduler parameters."""
  15.386 -        if help:
  15.387 -            print args[0], "DOM MCUADV WARP WARPL WARPU"
  15.388 -            print '\nSet Borrowed Virtual Time scheduler parameters.'
  15.389 -            return
  15.390 -        if len(args) != 6: self.err("%s: Invalid argument(s)" % args[0])
  15.391 +xm.prog(ProgPincpu)
  15.392 +
  15.393 +class ProgBvt(Prog):
  15.394 +    group = 'scheduler'
  15.395 +    name = "bvt"
  15.396 +    info = """Set BVT scheduler parameters."""
  15.397 +    
  15.398 +    def help(self, args):
  15.399 +        print self.name, "DOM MCUADV WARP WARPL WARPU"
  15.400 +        print '\nSet Borrowed Virtual Time scheduler parameters.'
  15.401 +
  15.402 +    def main(self, args):
  15.403 +        if len(args) != 6: self.err("%s: Invalid argument(s)" % self.name)
  15.404          v = map(int, args[1:6])
  15.405          server.xend_domain_cpu_bvt_set(*v)
  15.406  
  15.407 -    def xm_bvtslice(self, help, args):
  15.408 -        """Set the BVT scheduler slice."""
  15.409 -        if help:
  15.410 -            print args[0], 'SLICE'
  15.411 -            print '\nSet Borrowed Virtual Time scheduler slice.'
  15.412 -            return
  15.413 -        if len(args) < 2: self.err('%s: Missing slice' % args[0])
  15.414 +xm.prog(ProgBvt)
  15.415 +
  15.416 +class ProgBvtslice(Prog):
  15.417 +    group = 'scheduler'
  15.418 +    name = "bvtslice"
  15.419 +    info = """Set the BVT scheduler slice."""
  15.420 +
  15.421 +    def help(self, args):
  15.422 +        print self.name, 'SLICE'
  15.423 +        print '\nSet Borrowed Virtual Time scheduler slice.'
  15.424 +
  15.425 +    def main(self, args):
  15.426 +        if len(args) < 2: self.err('%s: Missing slice' % self.name)
  15.427          server.xend_node_cpu_bvt_slice_set(slice)
  15.428  
  15.429 -    def xm_atropos(self, help, args):
  15.430 -        """Set atropos parameters."""
  15.431 -        if help:
  15.432 -            print args[0], "DOM PERIOD SLICE LATENCY XTRATIME"
  15.433 -            print "\nSet atropos parameters."
  15.434 -            return
  15.435 -        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
  15.436 +xm.prog(ProgBvtslice)
  15.437 +
  15.438 +class ProgAtropos(Prog):
  15.439 +    group = 'scheduler'
  15.440 +    name= "atropos"
  15.441 +    info = """Set atropos parameters."""
  15.442 +
  15.443 +    def help(self, args):
  15.444 +        print self.name, "DOM PERIOD SLICE LATENCY XTRATIME"
  15.445 +        print "\nSet atropos parameters."
  15.446 +
  15.447 +    def main(self, args):
  15.448 +        if len(args) != 5: self.err("%s: Invalid argument(s)" % self.name)
  15.449          v = map(int, args[1:5])
  15.450          server.xend_domain_cpu_atropos_set(*v)
  15.451  
  15.452 -    def xm_rrobin(self, help, args):
  15.453 -        """Set round robin slice."""
  15.454 -        if help:
  15.455 -            print args[0], "SLICE"
  15.456 -            print "\nSet round robin scheduler slice."
  15.457 -            return
  15.458 -        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
  15.459 +xm.prog(ProgAtropos)
  15.460 +
  15.461 +class ProgRrobin(Prog):
  15.462 +    group = 'scheduler'
  15.463 +    name = "rrobin"
  15.464 +    info = """Set round robin slice."""
  15.465 +
  15.466 +    def help(self, args):
  15.467 +        print self.name, "SLICE"
  15.468 +        print "\nSet round robin scheduler slice."
  15.469 +
  15.470 +    def main(self, args):
  15.471 +        if len(args) != 2: self.err("%s: Invalid argument(s)" % self.name)
  15.472          rrslice = int(args[1])
  15.473          server.xend_node_rrobin_set(rrslice)
  15.474  
  15.475 -    def xm_info(self, help, args):
  15.476 -        """Get information about the xen host."""
  15.477 -        if help: self.help('xm_' + args[0], args); return
  15.478 +xm.prog(ProgRrobin)
  15.479 +
  15.480 +class ProgInfo(Prog):
  15.481 +    group = 'host'
  15.482 +    name = "info"
  15.483 +    info = """Get information about the xen host."""
  15.484 +
  15.485 +    def main(self, args):
  15.486          info = server.xend_node()
  15.487          for x in info[1:]:
  15.488              print "%-23s:" % x[0], x[1]
  15.489  
  15.490 -    def xm_consoles(self, help, args):
  15.491 -        """Get information about domain consoles."""
  15.492 -        if help: self.help('xm_' + args[0], args); return
  15.493 +xm.prog(ProgInfo)
  15.494 +
  15.495 +class ProgConsoles(Prog):
  15.496 +    group = 'console'
  15.497 +    name = "consoles"
  15.498 +    info = """Get information about domain consoles."""
  15.499 +
  15.500 +    def main(self, args):
  15.501          l = server.xend_consoles()
  15.502          print "Dom Port  Id"
  15.503          for x in l:
  15.504 @@ -228,13 +399,19 @@ class Xm:
  15.505              d['id'] = sxp.child_value(info, 'id', '?')
  15.506              print "%(dom)3s %(port)4s %(id)3s" % d
  15.507  
  15.508 -    def xm_console(self, help, args):
  15.509 -        """Open a console to a domain."""
  15.510 -        if help:
  15.511 -            print "console DOM"
  15.512 -            print "\nOpen a console to domain DOM."
  15.513 -            return
  15.514 -        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  15.515 +xm.prog(ProgConsoles)
  15.516 +
  15.517 +class ProgConsole(Prog):
  15.518 +    group = 'console'
  15.519 +    name = "console"
  15.520 +    info = """Open a console to a domain."""
  15.521 +    
  15.522 +    def help(self, args):
  15.523 +        print self.name, "DOM"
  15.524 +        print "\nOpen a console to domain DOM."
  15.525 +
  15.526 +    def main(self, args):
  15.527 +        if len(args) < 2: self.err("%s: Missing domain" % self.name)
  15.528          dom = args[1]
  15.529          info = server.xend_domain(dom)
  15.530          console = sxp.child(info, "console")
  15.531 @@ -244,6 +421,7 @@ class Xm:
  15.532          from xenctl import console_client
  15.533          console_client.connect("localhost", int(port))
  15.534  
  15.535 +xm.prog(ProgConsole)
  15.536 +
  15.537  def main(args):
  15.538 -    xm = Xm()
  15.539      xm.main(args)
    16.1 --- a/tools/xenmgr/lib/xm/opts.py	Thu Jun 24 15:04:30 2004 +0000
    16.2 +++ b/tools/xenmgr/lib/xm/opts.py	Thu Jun 24 15:13:59 2004 +0000
    16.3 @@ -1,3 +1,6 @@
    16.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    16.5 +"""Object-oriented command-line option support.
    16.6 +"""
    16.7  from getopt import getopt
    16.8  import os
    16.9  import os.path
   16.10 @@ -5,8 +8,22 @@ import sys
   16.11  import types
   16.12  
   16.13  class Opt:
   16.14 +    """An individual option.
   16.15 +    """
   16.16      def __init__(self, opts, name, short=None, long=None,
   16.17                   val=None, fn=None, use=None, default=None):
   16.18 +        """Create an option.
   16.19 +
   16.20 +        opts    parent options object
   16.21 +        name    name of the field it controls
   16.22 +        short   short (1-char) command line switch (optional)
   16.23 +        long    long command-line switch. Defaults to option name.
   16.24 +        val     string used to print option args in help.
   16.25 +                If val is not specified the option has no arg.
   16.26 +        fn      function to call when the option is specified.
   16.27 +        use     usage (help) string
   16.28 +        default default value if not specified on command-line
   16.29 +        """
   16.30          self.opts = opts
   16.31          self.name = name
   16.32          self.short = short
   16.33 @@ -24,18 +41,34 @@ class Opt:
   16.34          self.fn = fn
   16.35          self.specified_opt = None
   16.36          self.specified_val = None
   16.37 +        self.value = None
   16.38          self.set(default)
   16.39  
   16.40 +    def __repr__(self):
   16.41 +        return self.name + '=' + str(self.specified_val)
   16.42 +
   16.43 +    __str__ = __repr__
   16.44 +
   16.45      def set(self, value):
   16.46 -        setattr(self.opts, self.name, value)
   16.47 +        """Set the option value.
   16.48 +        """
   16.49 +        self.opts.setopt(self.name, value)
   16.50  
   16.51      def get(self):
   16.52 -        return getattr(self.opts, self.name)
   16.53 +        """Get the option value.
   16.54 +        """
   16.55 +        return self.opts.getopt(self.name)
   16.56  
   16.57      def append(self, value):
   16.58 -        self.set(self.get().append(value))
   16.59 +        """Append a value to the option value.
   16.60 +        """
   16.61 +        v = self.get() or []
   16.62 +        v.append(value)
   16.63 +        self.set(v)
   16.64  
   16.65      def short_opt(self):
   16.66 +        """Short option spec.
   16.67 +        """
   16.68          if self.short:
   16.69              if self.val:
   16.70                  return self.short + ':'
   16.71 @@ -45,6 +78,8 @@ class Opt:
   16.72              return None
   16.73  
   16.74      def long_opt(self):
   16.75 +        """Long option spec.
   16.76 +        """
   16.77          if self.long:
   16.78              if self.val:
   16.79                  return self.long + '='
   16.80 @@ -68,6 +103,12 @@ class Opt:
   16.81              print '\tDefault', self.default or 'None'
   16.82  
   16.83      def specify(self, k, v):
   16.84 +        """Specify the option. Called when the option is set
   16.85 +        from the command line.
   16.86 +
   16.87 +        k  option switch used
   16.88 +        v  optional value given (if any)
   16.89 +        """
   16.90          if k in self.optkeys:
   16.91              if self.val is None and v:
   16.92                  self.opts.err("Option '%s' does not take a value" % k)
   16.93 @@ -80,52 +121,113 @@ class Opt:
   16.94              return 0
   16.95  
   16.96      def specified(self):
   16.97 +        """Test whether the option has been specified: set
   16.98 +        from the command line.
   16.99 +        """
  16.100          return self.specified_opt
  16.101  
  16.102 +class OptVals:
  16.103 +    """Class to hold option values.
  16.104 +    """
  16.105 +    pass
  16.106 +
  16.107  class Opts:
  16.108 +    """Container for options.
  16.109 +    """
  16.110      def __init__(self, use=None):
  16.111 -        self._usage = use
  16.112 -        self._options = []
  16.113 -        self._options_map = {}
  16.114 -        self._argv = []
  16.115 -        self._vals = {}
  16.116 -        self._globals = {}
  16.117 -        self._locals = {}
  16.118 -        self.quiet = 0
  16.119 +        """Options constructor.
  16.120 +
  16.121 +        use  usage string
  16.122 +        """
  16.123 +        self.use = use
  16.124 +        # List of options.
  16.125 +        self.options = []
  16.126 +        # Options indexed by name.
  16.127 +        self.options_map = {}
  16.128 +        # Command-line arguments.
  16.129 +        self.argv = []
  16.130 +        # Option values.
  16.131 +        self.vals = OptVals()
  16.132 +        self.vals.quiet = 0
  16.133 +        # Variables for default scripts.
  16.134 +        self.vars = {}
  16.135 +
  16.136 +    def __repr__(self):
  16.137 +        return '\n'.join(map(str, self.options))
  16.138 +
  16.139 +    __str__ = __repr__
  16.140  
  16.141      def opt(self, name, **args):
  16.142 +        """Add an option.
  16.143 +
  16.144 +        name    option name
  16.145 +        **args  keyword params for option constructor
  16.146 +        """
  16.147          x = Opt(self, name, **args)
  16.148 -        self._options.append(x)
  16.149 -        self._options_map[name] = x
  16.150 +        self.options.append(x)
  16.151 +        self.options_map[name] = x
  16.152          return x
  16.153  
  16.154 +    def setvar(self, var, val):
  16.155 +        """Set a default script variable.
  16.156 +        """
  16.157 +        self.vars[var] = val
  16.158 +
  16.159 +    def getvar(self, var):
  16.160 +        """Get a default script variable.
  16.161 +        """
  16.162 +        return self.vars.get(var)
  16.163 +
  16.164 +    def option(self, name):
  16.165 +        """Get an option (object).
  16.166 +        """
  16.167 +        return self.options_map.get(name)
  16.168 +
  16.169 +    def setopt(self, name, val):
  16.170 +        """Set an option value.
  16.171 +        An option can also be set using 'opts.vals.name = val'.
  16.172 +        """
  16.173 +        setattr(self.vals, name, val)
  16.174 +
  16.175      def getopt(self, name):
  16.176 -        return self._options_map.get(name)
  16.177 +        """Get an option value.
  16.178 +        An option value can also be got using 'opts.vals.name'.
  16.179 +        """
  16.180 +        getattr(self.vals, name)
  16.181  
  16.182      def specified(self, name):
  16.183 -        opt = self.getopt(name)
  16.184 +        """Test if an option has been specified.
  16.185 +        """
  16.186 +        opt = self.option(name)
  16.187          return opt and opt.specified()
  16.188  
  16.189 -    def setvar(self, name, val):
  16.190 -        self._globals[name] = val
  16.191 -
  16.192      def err(self, msg):
  16.193 +        """Print an error to stderr and exit.
  16.194 +        """
  16.195          print >>sys.stderr, "Error:", msg
  16.196          sys.exit(1)
  16.197  
  16.198      def info(self, msg):
  16.199 -        if self.quiet: return
  16.200 +        """Print a message to stdout (unless quiet is set).
  16.201 +        """
  16.202 +        if self.vals.quiet: return
  16.203          print msg
  16.204  
  16.205      def warn(self, msg):
  16.206 +        """Print a warning to stdout.
  16.207 +        """
  16.208          print >>sys.stderr, "Warning:", msg
  16.209  
  16.210      def parse(self, argv):
  16.211 -        self._argv = argv
  16.212 +        """Parse arguments argv using the options.
  16.213 +
  16.214 +        return remaining arguments
  16.215 +        """
  16.216 +        self.argv = argv
  16.217          (vals, args) = getopt(argv[1:], self.short_opts(), self.long_opts())
  16.218 -        self._args = args
  16.219 +        self.args = args
  16.220          for (k, v) in vals:
  16.221 -            for opt in self._options:
  16.222 +            for opt in self.options:
  16.223                  if opt.specify(k, v): break
  16.224              else:
  16.225                  print >>sys.stderr, "Error: Unknown option:", k
  16.226 @@ -133,63 +235,92 @@ class Opts:
  16.227          return args
  16.228  
  16.229      def short_opts(self):
  16.230 +        """Get short options specifier for getopt.
  16.231 +        """
  16.232          l = []
  16.233 -        for x in self._options:
  16.234 +        for x in self.options:
  16.235              y = x.short_opt()
  16.236              if not y: continue
  16.237              l.append(y)
  16.238          return ''.join(l)
  16.239  
  16.240      def long_opts(self):
  16.241 +        """Get long options specifier for getopt.
  16.242 +        """
  16.243          l = []
  16.244 -        for x in self._options:
  16.245 +        for x in self.options:
  16.246              y = x.long_opt()
  16.247              if not y: continue
  16.248              l.append(y)
  16.249 -        return ''.join(l)
  16.250 +        return l
  16.251  
  16.252      def usage(self):
  16.253 -        print 'Usage: ', self._argv[0], self._usage or 'OPTIONS'
  16.254 -        for opt in self._options:
  16.255 +        print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
  16.256 +        for opt in self.options:
  16.257              opt.show()
  16.258  
  16.259      def load_defaults(self):
  16.260 -        for x in [ '' ] + self.path.split(':'):
  16.261 +        """Load a defaults script. Assumes these options set:
  16.262 +        'path'    search path
  16.263 +        'default' script name
  16.264 +        """
  16.265 +        for x in [ '' ] + self.vals.path.split(':'):
  16.266              if x:
  16.267 -                p = os.path.join(x, self.defaults)
  16.268 +                p = os.path.join(x, self.vals.defaults)
  16.269              else:
  16.270 -                p = self.defaults
  16.271 +                p = self.vals.defaults
  16.272              if os.path.exists(p):
  16.273                  self.load(p)
  16.274                  break
  16.275          else:
  16.276              self.err("Cannot open defaults file %s" % self.defaults)
  16.277  
  16.278 -    def load(self, defaults):
  16.279 -        self._globals['sys'] = sys
  16.280 -        self._globals['config_file'] = defaults
  16.281 -        execfile(defaults, self._globals, self._locals)
  16.282 +    def load(self, defaults, help=0):
  16.283 +        """Load a defaults file. Local variables in the file
  16.284 +        are used to set options with the same names.
  16.285 +        Variables are not used to set options that are already specified.
  16.286 +        """
  16.287 +        # Create global and lobal dicts for the file.
  16.288 +        # Initialize locals to the vars.
  16.289 +        # Use exec to do the standard imports and
  16.290 +        # define variables we are passing to the script.
  16.291 +        globals = {}
  16.292 +        locals = {}
  16.293 +        locals.update(self.vars)
  16.294 +        cmd = '\n'.join(["import sys",
  16.295 +                         "import os",
  16.296 +                         "import os.path",
  16.297 +                         "xm_file = '%s'" % defaults,
  16.298 +                         "xm_help = %d" % help ])
  16.299 +        exec cmd in globals, locals
  16.300 +        execfile(defaults, globals, locals)
  16.301 +        if help: return
  16.302 +        # Extract the values set by the script and set the corresponding
  16.303 +        # options, if not set on the command line.
  16.304          vtypes = [ types.StringType,
  16.305                     types.ListType,
  16.306                     types.IntType,
  16.307                     types.FloatType
  16.308                     ]
  16.309 -        for (k, v) in self._locals.items():
  16.310 +        for (k, v) in locals.items():
  16.311              if self.specified(k): continue
  16.312              if not(type(v) in vtypes): continue
  16.313 -            print 'SET ', k, v
  16.314 -            setattr(self, k, v)
  16.315 +            self.setopt(k, v)
  16.316  
  16.317  def set_true(opt, k, v):
  16.318 +    """Set an option true."""
  16.319      opt.set(1)
  16.320  
  16.321  def set_false(opt, k, v):
  16.322 +    """Set an option false."""
  16.323      opt.set(0)
  16.324  
  16.325  def set_value(opt, k, v):
  16.326 +    """Set an option to a valoue."""
  16.327      opt.set(v)
  16.328  
  16.329  def set_int(opt, k, v):
  16.330 +    """Set an option to an integer value."""
  16.331      try:
  16.332          v = int(v)
  16.333      except:
  16.334 @@ -197,4 +328,12 @@ def set_int(opt, k, v):
  16.335      opt.set(v)
  16.336  
  16.337  def append_value(opt, k, v):
  16.338 +    """Append a value to a list option."""
  16.339      opt.append(v)
  16.340 +
  16.341 +def set_var(opt, k, v):
  16.342 +    """Set a default script variable.
  16.343 +    """
  16.344 +    (var, val) = v.strip().split('=')
  16.345 +    opt.opts.setvar(var.strip(), val.strip())
  16.346 +
    17.1 --- a/tools/xenmgr/lib/xm/shutdown.py	Thu Jun 24 15:04:30 2004 +0000
    17.2 +++ b/tools/xenmgr/lib/xm/shutdown.py	Thu Jun 24 15:13:59 2004 +0000
    17.3 @@ -1,3 +1,6 @@
    17.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    17.5 +"""Domain shutdown.
    17.6 +"""
    17.7  import string
    17.8  import sys
    17.9  import time
   17.10 @@ -43,7 +46,7 @@ def shutdown(opts, doms, wait):
   17.11          opts.info("All domains terminated")
   17.12  
   17.13  def main_all(opts, args):
   17.14 -    shutdown(opts, None, opts.wait)
   17.15 +    shutdown(opts, None, opts.vals.wait)
   17.16  
   17.17  def main_dom(opts, args):
   17.18      if len(args) < 1: opts.err('Missing domain')
   17.19 @@ -52,16 +55,16 @@ def main_dom(opts, args):
   17.20          domid = int(dom)
   17.21      except:
   17.22          opts.err('Invalid domain: ' + dom)
   17.23 -    shutdown(opts, [ domid ], opts.wait)
   17.24 +    shutdown(opts, [ domid ], opts.vals.wait)
   17.25      
   17.26  def main(argv):
   17.27      opts = gopts
   17.28      args = opts.parse(argv)
   17.29 -    if opts.help:
   17.30 +    if opts.vals.help:
   17.31          opts.usage()
   17.32          return
   17.33      print 'shutdown.main>', len(args), args
   17.34 -    if opts.all:
   17.35 +    if opts.vals.all:
   17.36          main_all(opts, args)
   17.37      else:
   17.38          main_dom(opts, args)