ia64/xen-unstable

changeset 5343:4c7d2c6e932a

bitkeeper revision 1.1662.1.7 (42a47555156iGoOjUyZtvbuMFZHXkg)

XendDomainInfo.py:
Move guest image handling into seperate file.
image.py:
new file
Signed-off-by: Mike Wray <mike.wray@hp.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Mon Jun 06 16:09:57 2005 +0000 (2005-06-06)
parents a3b60b641063
children e1cd6bd22fb9
files .rootkeys tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py
line diff
     1.1 --- a/.rootkeys	Mon Jun 06 15:06:50 2005 +0000
     1.2 +++ b/.rootkeys	Mon Jun 06 16:09:57 2005 +0000
     1.3 @@ -849,6 +849,7 @@ 40c9c4686jruMyZIqiaZRMiMoqMJtg tools/pyt
     1.4  40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/python/xen/xend/XendVnet.py
     1.5  40c9c468x191zetrVlMnExfsQWHxIQ tools/python/xen/xend/__init__.py
     1.6  40c9c468S2YnCEKmk4ey8XQIST7INg tools/python/xen/xend/encode.py
     1.7 +42a475165HuglqWwNi2fjqNOIHbIKQ tools/python/xen/xend/image.py
     1.8  4266169ezWIlXSfY50n6HSoVFbosmw tools/python/xen/xend/scheduler.py
     1.9  40c9c468IxQabrKJSWs0aEjl-27mRQ tools/python/xen/xend/server/SrvConsole.py
    1.10  40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/python/xen/xend/server/SrvConsoleDir.py
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Mon Jun 06 15:06:50 2005 +0000
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Jun 06 16:09:57 2005 +0000
     2.3 @@ -114,25 +114,6 @@ def get_config_handler(name):
     2.4      """
     2.5      return config_handlers.get(name)
     2.6  
     2.7 -"""Table of handlers for virtual machine images.
     2.8 -Indexed by image type.
     2.9 -"""
    2.10 -image_handlers = {}
    2.11 -
    2.12 -def add_image_handler(name, h):
    2.13 -    """Add a handler for an image type
    2.14 -    @param name:     image type
    2.15 -    @param h:        handler: fn(config, name, memory, image)
    2.16 -    """
    2.17 -    image_handlers[name] = h
    2.18 -
    2.19 -def get_image_handler(name):
    2.20 -    """Get the handler for an image type.
    2.21 -    @param name:     image type
    2.22 -    @return: handler or None
    2.23 -    """
    2.24 -    return image_handlers.get(name)
    2.25 -
    2.26  """Table of handlers for devices.
    2.27  Indexed by device type.
    2.28  """
    2.29 @@ -252,8 +233,6 @@ class XendDomainInfo:
    2.30          self.name = None
    2.31          self.memory = None
    2.32          self.image = None
    2.33 -        self.ramdisk = None
    2.34 -        self.cmdline = None
    2.35  
    2.36          self.channel = None
    2.37          self.controllers = {}
    2.38 @@ -278,8 +257,6 @@ class XendDomainInfo:
    2.39          
    2.40          self.console_port = None
    2.41          self.savedinfo = None
    2.42 -        self.image_handler = None
    2.43 -        self.is_vmx = False
    2.44          self.vcpus = 1
    2.45          self.bootloader = None
    2.46  
    2.47 @@ -330,8 +307,6 @@ class XendDomainInfo:
    2.48          console = self.getConsole()
    2.49          if console:
    2.50              s += " console=" + str(console.console_port)
    2.51 -        if self.image:
    2.52 -            s += " image=" + self.image
    2.53          s += ""
    2.54          return s
    2.55  
    2.56 @@ -484,8 +459,8 @@ class XendDomainInfo:
    2.57              # Initial domain create.
    2.58              self.setName(sxp.child_value(config, 'name'))
    2.59              self.check_name(self.name)
    2.60 +            self.init_image()
    2.61              self.configure_cpus(config)
    2.62 -            self.find_image_handler()
    2.63              self.init_domain()
    2.64              self.register_domain()
    2.65              self.configure_bootloader()
    2.66 @@ -527,29 +502,24 @@ class XendDomainInfo:
    2.67          except:
    2.68              raise VmError('invalid vcpus value')
    2.69  
    2.70 -    def find_image_handler(self):
    2.71 -        """Construct the boot image for the domain.
    2.72 -
    2.73 -        @return vm
    2.74 +    def init_image(self):
    2.75 +        """Create boot image handler for the domain.
    2.76          """
    2.77          image = sxp.child_value(self.config, 'image')
    2.78          if image is None:
    2.79              raise VmError('missing image')
    2.80 -        image_name = sxp.name(image)
    2.81 -        if image_name is None:
    2.82 -            raise VmError('missing image name')
    2.83 -        if image_name == "vmx":
    2.84 -            self.is_vmx = True
    2.85 -        image_handler = get_image_handler(image_name)
    2.86 -        if image_handler is None:
    2.87 -            raise VmError('unknown image type: ' + image_name)
    2.88 -        self.image_handler = image_handler
    2.89 -        return self
    2.90 +        self.image = ImageHandler.create(self, image)
    2.91  
    2.92      def construct_image(self):
    2.93 -        image = sxp.child_value(self.config, 'image')
    2.94 -        self.image_handler(self, image)
    2.95 -        return self
    2.96 +        """Construct the boot image for the domain.
    2.97 +        """
    2.98 +        self.create_channel()
    2.99 +        self.image.createImage()
   2.100 +        #self.image.exportToDB()
   2.101 +        #if self.store_channel:
   2.102 +        #    self.db.introduceDomain(self.id,
   2.103 +        #                            self.store_mfn,
   2.104 +        #                            self.store_channel)
   2.105  
   2.106      def config_devices(self, name):
   2.107          """Get a list of the 'device' nodes of a given type from the config.
   2.108 @@ -596,7 +566,7 @@ class XendDomainInfo:
   2.109          """Completely destroy the vm.
   2.110          """
   2.111          self.cleanup()
   2.112 -        return self.destroy_domain()
   2.113 +        self.destroy_domain()
   2.114  
   2.115      def destroy_domain(self):
   2.116          """Destroy the vm's domain.
   2.117 @@ -606,9 +576,15 @@ class XendDomainInfo:
   2.118          if self.channel:
   2.119              self.channel.close()
   2.120              self.channel = None
   2.121 +        if self.image:
   2.122 +            try:
   2.123 +                self.image.destroy()
   2.124 +                self.image = None
   2.125 +            except:
   2.126 +                pass
   2.127          if self.id is None: return 0
   2.128          try:
   2.129 -            return xc.domain_destroy(dom=self.id)
   2.130 +            xc.domain_destroy(dom=self.id)
   2.131          except Exception, err:
   2.132              log.exception("Domain destroy failed: %s", self.name)
   2.133  
   2.134 @@ -661,80 +637,11 @@ class XendDomainInfo:
   2.135              cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
   2.136          except:
   2.137              raise VmError('invalid cpu')
   2.138 -        cpu_weight = self.cpu_weight
   2.139 -        memory = memory * 1024 + self.pgtable_size(memory)
   2.140 -        dom = xc.domain_create(dom= dom)
   2.141 -        if self.bootloader:
   2.142 -            try:
   2.143 -                if kernel: os.unlink(kernel)
   2.144 -                if ramdisk: os.unlink(ramdisk)
   2.145 -            except OSError, e:
   2.146 -                log.warning('unable to unlink kernel/ramdisk: %s' %(e,))
   2.147 -
   2.148 -        if dom <= 0:
   2.149 -            raise VmError('Creating domain failed: name=%s memory=%d'
   2.150 -                          % (self.name, memory))
   2.151 -        xc.domain_setcpuweight(dom, cpu_weight)
   2.152 -        xc.domain_setmaxmem(dom, memory)
   2.153 -        xc.domain_memory_increase_reservation(dom, memory)
   2.154 -        if cpu != -1:
   2.155 -            xc.domain_pincpu(dom, 0, 1<<int(cpu))
   2.156 -        log.debug('init_domain> Created domain=%d name=%s memory=%d', dom, self.name, memory)
   2.157 -        self.setdom(dom)
   2.158 -
   2.159 -    def build_domain(self, ostype, kernel, ramdisk, cmdline, memmap):
   2.160 -        """Build the domain boot image.
   2.161 -        """
   2.162 -        if self.recreate or self.restore: return
   2.163 -        if not os.path.isfile(kernel):
   2.164 -            raise VmError('Kernel image does not exist: %s' % kernel)
   2.165 -        if ramdisk and not os.path.isfile(ramdisk):
   2.166 -            raise VmError('Kernel ramdisk does not exist: %s' % ramdisk)
   2.167 -        if len(cmdline) >= 256:
   2.168 -            log.warning('kernel cmdline too long, domain %d', self.id)
   2.169 -        dom = self.id
   2.170 -        buildfn = getattr(xc, '%s_build' % ostype)
   2.171 -        flags = 0
   2.172 -        if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
   2.173 -        if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
   2.174 -        #todo generalise this
   2.175 -        if ostype == "vmx":
   2.176 -            log.debug('building vmx domain')            
   2.177 -            err = buildfn(dom            = dom,
   2.178 -                          image          = kernel,
   2.179 -                          control_evtchn = 0,
   2.180 -                          memsize        = self.memory,
   2.181 -                          memmap         = memmap,
   2.182 -                          cmdline        = cmdline,
   2.183 -                          ramdisk        = ramdisk,
   2.184 -                          flags          = flags)
   2.185 -        else:
   2.186 -            log.debug('building dom with %d vcpus', self.vcpus)
   2.187 -            err = buildfn(dom            = dom,
   2.188 -                          image          = kernel,
   2.189 -                          control_evtchn = self.channel.getRemotePort(),
   2.190 -                          cmdline        = cmdline,
   2.191 -                          ramdisk        = ramdisk,
   2.192 -                          flags          = flags,
   2.193 -                          vcpus          = self.vcpus)
   2.194 -            if err != 0:
   2.195 -                raise VmError('Building domain failed: type=%s dom=%d err=%d'
   2.196 -                              % (ostype, dom, err))
   2.197 -            
   2.198 -    def create_domain(self, ostype, kernel, ramdisk, cmdline, memmap=''):
   2.199 -        """Create a domain. Builds the image but does not configure it.
   2.200 -
   2.201 -        @param ostype:  OS type
   2.202 -        @param kernel:  kernel image
   2.203 -        @param ramdisk: kernel ramdisk
   2.204 -        @param cmdline: kernel commandline
   2.205 -        """
   2.206 -
   2.207 -        self.create_channel()
   2.208 -        self.build_domain(ostype, kernel, ramdisk, cmdline, memmap)
   2.209 -        self.image = kernel
   2.210 -        self.ramdisk = ramdisk
   2.211 -        self.cmdline = cmdline
   2.212 +        dom = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight)
   2.213 +        log.debug('init_domain> Created domain=%d name=%s memory=%d',
   2.214 +                  dom, self.name, self.memory)
   2.215 +        if not self.restore:
   2.216 +            self.setdom(dom)
   2.217  
   2.218      def create_channel(self):
   2.219          """Create the control channel to the domain.
   2.220 @@ -773,43 +680,6 @@ class XendDomainInfo:
   2.221                  ctrl.initController(reboot=True)
   2.222          else:
   2.223              self.create_configured_devices()
   2.224 -        if self.is_vmx:
   2.225 -            self.create_vmx_model()
   2.226 -
   2.227 -    def create_vmx_model(self):
   2.228 -        #todo: remove special case for vmx
   2.229 -        device_model = sxp.child_value(self.config, 'device_model')
   2.230 -        if not device_model:
   2.231 -            raise VmError("vmx: missing device model")
   2.232 -        device_config = sxp.child_value(self.config, 'device_config')
   2.233 -        if not device_config:
   2.234 -            raise VmError("vmx: missing device config")
   2.235 -        #todo: self.memory?
   2.236 -        memory = sxp.child_value(self.config, "memory")
   2.237 -        # Create an event channel
   2.238 -        device_channel = channel.eventChannel(0, self.id)
   2.239 -        # see if a vncviewer was specified
   2.240 -        # XXX RN: bit of a hack. should unify this, maybe stick in config space
   2.241 -        vncconnect=""
   2.242 -        image = sxp.child_value(self.config, "image")
   2.243 -        args = sxp.child_value(image, "args")
   2.244 -        if args:
   2.245 -            arg_list = string.split(args)
   2.246 -            for arg in arg_list:
   2.247 -                al = string.split(arg, '=')
   2.248 -                if al[0] == "VNC_VIEWER":
   2.249 -                    vncconnect=" -v %s" % al[1]
   2.250 -                    break
   2.251 -
   2.252 -        # Execute device model.
   2.253 -        #todo: Error handling
   2.254 -        # XXX RN: note that the order of args matter!
   2.255 -        os.system(device_model
   2.256 -                  + " -f %s" % device_config
   2.257 -                  + vncconnect
   2.258 -                  + " -d %d" % self.id
   2.259 -                  + " -p %d" % device_channel['port1']
   2.260 -                  + " -m %s" % memory)
   2.261  
   2.262      def device_create(self, dev_config):
   2.263          """Create a new device.
   2.264 @@ -862,9 +732,7 @@ class XendDomainInfo:
   2.265      def configure_bootloader(self):
   2.266          """Configure boot loader.
   2.267          """
   2.268 -        bl = sxp.child_value(self.config, "bootloader")
   2.269 -        if bl is not None:
   2.270 -            self.bootloader = bl
   2.271 +        self.bootloader = sxp.child_value(self.config, "bootloader")
   2.272  
   2.273      def configure_console(self):
   2.274          """Configure the vm console port.
   2.275 @@ -1052,19 +920,6 @@ class XendDomainInfo:
   2.276                  log.warning("Unknown config field %s", field_name)
   2.277              index[field_name] = field_index + 1
   2.278  
   2.279 -    def pgtable_size(self, memory):
   2.280 -        """Return the size of memory needed for 1:1 page tables for physical
   2.281 -           mode.
   2.282 -
   2.283 -        @param memory: size in MB
   2.284 -        @return size in KB
   2.285 -        """
   2.286 -        if self.is_vmx:
   2.287 -            # Logic x86-32 specific. 
   2.288 -            # 1 page for the PGD + 1 pte page for 4MB of memory (rounded)
   2.289 -            return (1 + ((memory + 3) >> 2)) * 4
   2.290 -        return 0
   2.291 -
   2.292      def mem_target_set(self, target):
   2.293          """Set domain memory target in pages.
   2.294          """
   2.295 @@ -1091,83 +946,6 @@ class XendDomainInfo:
   2.296              return 0
   2.297          return timeout - (time.time() - self.shutdown_pending['start'])
   2.298  
   2.299 -def vm_image_linux(vm, image):
   2.300 -    """Create a VM for a linux image.
   2.301 -
   2.302 -    @param name:      vm name
   2.303 -    @param memory:    vm memory
   2.304 -    @param image:     image config
   2.305 -    @return: vm
   2.306 -    """
   2.307 -    kernel = sxp.child_value(image, "kernel")
   2.308 -    cmdline = ""
   2.309 -    ip = sxp.child_value(image, "ip", None)
   2.310 -    if ip:
   2.311 -        cmdline += " ip=" + ip
   2.312 -    root = sxp.child_value(image, "root")
   2.313 -    if root:
   2.314 -        cmdline += " root=" + root
   2.315 -    args = sxp.child_value(image, "args")
   2.316 -    if args:
   2.317 -        cmdline += " " + args
   2.318 -    ramdisk = sxp.child_value(image, "ramdisk", '')
   2.319 -    log.debug("creating linux domain with cmdline: %s" %(cmdline,))
   2.320 -    vm.create_domain("linux", kernel, ramdisk, cmdline)
   2.321 -    return vm
   2.322 -
   2.323 -def vm_image_plan9(vm, image):
   2.324 -    """Create a VM for a Plan 9 image.
   2.325 -
   2.326 -    name      vm name
   2.327 -    memory    vm memory
   2.328 -    image     image config
   2.329 -
   2.330 -    returns vm 
   2.331 -    """
   2.332 -    kernel = sxp.child_value(image, "kernel")
   2.333 -    cmdline = ""
   2.334 -    ip = sxp.child_value(image, "ip", "dhcp")
   2.335 -    if ip:
   2.336 -        cmdline += "ip=" + ip
   2.337 -    root = sxp.child_value(image, "root")
   2.338 -    if root:
   2.339 -        cmdline += "root=" + root
   2.340 -    args = sxp.child_value(image, "args")
   2.341 -    if args:
   2.342 -        cmdline += " " + args
   2.343 -    ramdisk = sxp.child_value(image, "ramdisk", '')
   2.344 -    log.debug("creating plan9 domain with cmdline: %s" %(cmdline,))
   2.345 -    vm.create_domain("plan9", kernel, ramdisk, cmdline)
   2.346 -    return vm
   2.347 -    
   2.348 -def vm_image_vmx(vm, image):
   2.349 -    """Create a VM for the VMX environment.
   2.350 -
   2.351 -    @param name:      vm name
   2.352 -    @param memory:    vm memory
   2.353 -    @param image:     image config
   2.354 -    @return: vm
   2.355 -    """
   2.356 -    kernel = sxp.child_value(image, "kernel")
   2.357 -    cmdline = ""
   2.358 -    ip = sxp.child_value(image, "ip", "dhcp")
   2.359 -    if ip:
   2.360 -        cmdline += " ip=" + ip
   2.361 -    root = sxp.child_value(image, "root")
   2.362 -    if root:
   2.363 -        cmdline += " root=" + root
   2.364 -    args = sxp.child_value(image, "args")
   2.365 -    if args:
   2.366 -        cmdline += " " + args
   2.367 -    ramdisk = sxp.child_value(image, "ramdisk", '')
   2.368 -    memmap = sxp.child_value(vm.config, "memmap", '')
   2.369 -    memmap = sxp.parse(open(memmap))[0]
   2.370 -    from xen.util.memmap import memmap_parse
   2.371 -    memmap = memmap_parse(memmap)
   2.372 -    log.debug("creating vmx domain with cmdline: %s" %(cmdline,))
   2.373 -    vm.create_domain("vmx", kernel, ramdisk, cmdline, memmap)
   2.374 -    return vm
   2.375 -
   2.376  def vm_field_ignore(vm, config, val, index):
   2.377      """Dummy config field handler used for fields with built-in handling.
   2.378  
   2.379 @@ -1197,9 +975,16 @@ def vm_field_maxmem(vm, config, val, ind
   2.380  
   2.381  #============================================================================
   2.382  # Register image handlers.
   2.383 -add_image_handler('linux', vm_image_linux)
   2.384 -add_image_handler('plan9', vm_image_plan9)
   2.385 -add_image_handler('vmx',   vm_image_vmx)
   2.386 +from image import          \
   2.387 +     addImageHandlerClass, \
   2.388 +     ImageHandler,         \
   2.389 +     LinuxImageHandler,    \
   2.390 +     Plan9ImageHandler,    \
   2.391 +     VmxImageHandler
   2.392 +
   2.393 +addImageHandlerClass(LinuxImageHandler)
   2.394 +addImageHandlerClass(Plan9ImageHandler)
   2.395 +addImageHandlerClass(VmxImageHandler)
   2.396  
   2.397  # Ignore the fields we already handle.
   2.398  add_config_handler('name',       vm_field_ignore)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/python/xen/xend/image.py	Mon Jun 06 16:09:57 2005 +0000
     3.3 @@ -0,0 +1,338 @@
     3.4 +import os
     3.5 +
     3.6 +import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
     3.7 +from xen.xend import sxp
     3.8 +from xen.xend.XendError import VmError
     3.9 +from xen.xend.XendLogging import log
    3.10 +#from xen.xend.xenstore import DBVar
    3.11 +
    3.12 +class ImageHandler:
    3.13 +    """Abstract base class for image handlers.
    3.14 +
    3.15 +    initDomain() is called to initialise the domain memory.
    3.16 +    
    3.17 +    createImage() is called to configure and build the domain from its
    3.18 +    kernel image and ramdisk etc.
    3.19 +
    3.20 +    The method buildDomain() is used to build the domain, and must be
    3.21 +    defined in a subclass.  Usually this is the only method that needs
    3.22 +    defining in a subclass.
    3.23 +
    3.24 +    The method createDeviceModel() is called to create the domain device
    3.25 +    model if it needs one.  The default is to do nothing.
    3.26 +
    3.27 +    The method destroy() is called when the domain is destroyed.
    3.28 +    The default is to do nothing.
    3.29 +    
    3.30 +    """
    3.31 +
    3.32 +    #======================================================================
    3.33 +    # Class vars and methods.
    3.34 +
    3.35 +    """Table of image handler classes for virtual machine images.
    3.36 +    Indexed by image type.
    3.37 +    """
    3.38 +    imageHandlerClasses = {}
    3.39 +
    3.40 +    def addImageHandlerClass(cls, h):
    3.41 +        """Add a handler class for an image type
    3.42 +        @param h:        handler: ImageHandler subclass
    3.43 +        """
    3.44 +        cls.imageHandlerClasses[h.ostype] = h
    3.45 +
    3.46 +    addImageHandlerClass = classmethod(addImageHandlerClass)
    3.47 +
    3.48 +    def findImageHandlerClass(cls, image):
    3.49 +        """Find the image handler class for an image config.
    3.50 +
    3.51 +        @param image config
    3.52 +        @return ImageHandler subclass or None
    3.53 +        """
    3.54 +        ty = sxp.name(image)
    3.55 +        if ty is None:
    3.56 +            raise VmError('missing image type')
    3.57 +        imageClass = cls.imageHandlerClasses.get(ty)
    3.58 +        if imageClass is None:
    3.59 +            raise VmError('unknown image type: ' + ty)
    3.60 +        return imageClass
    3.61 +
    3.62 +    findImageHandlerClass = classmethod(findImageHandlerClass)
    3.63 +
    3.64 +    def create(cls, vm, image):
    3.65 +        """Create an image handler for a vm.
    3.66 +
    3.67 +        @param vm vm
    3.68 +        @param image image config
    3.69 +        @return ImageHandler instance
    3.70 +        """
    3.71 +        imageClass = cls.findImageHandlerClass(image)
    3.72 +        return imageClass(vm, image)
    3.73 +
    3.74 +    create = classmethod(create)
    3.75 +
    3.76 +    #======================================================================
    3.77 +    # Instance vars and methods.
    3.78 +
    3.79 +    #db = None
    3.80 +    ostype = None
    3.81 +
    3.82 +    config = None
    3.83 +    kernel = None
    3.84 +    ramdisk = None
    3.85 +    cmdline = None
    3.86 +    flags = 0
    3.87 +
    3.88 +    #__exports__ = [
    3.89 +    #    DBVar('ostype',  ty='str'),
    3.90 +    #    DBVar('config',  ty='sxpr'),
    3.91 +    #    DBVar('kernel',  ty='str'),
    3.92 +    #    DBVar('ramdisk', ty='str'),
    3.93 +    #    DBVar('cmdline', ty='str'),
    3.94 +    #    DBVar('flags',   ty='int'),
    3.95 +    #    ]
    3.96 +
    3.97 +    def __init__(self, vm, config):
    3.98 +        self.vm = vm
    3.99 +        #self.db = vm.db.addChild('/image')
   3.100 +        self.config = config
   3.101 +
   3.102 +    #def exportToDB(self, save=False):
   3.103 +    #    self.db.exportToDB(self, fields=self.__exports__, save=save)
   3.104 +
   3.105 +    #def importFromDB(self):
   3.106 +    #    self.db.importFromDB(self, fields=self.__exports__)
   3.107 +
   3.108 +    def unlink(self, f):
   3.109 +        if not f: return
   3.110 +        try:
   3.111 +            os.unlink(f)
   3.112 +        except OSError, ex:
   3.113 +            log.warning("error removing bootloader file '%s': %s", f, ex)
   3.114 +
   3.115 +    def initDomain(self, dom, memory, cpu, cpu_weight):
   3.116 +        """Initial domain create.
   3.117 +
   3.118 +        @return domain id
   3.119 +        """
   3.120 +
   3.121 +        mem_kb = self.getDomainMemory(memory)
   3.122 +        if not self.vm.restore:
   3.123 +            dom = xc.domain_create(dom = dom or 0)
   3.124 +            # if bootloader, unlink here. But should go after buildDomain() ?
   3.125 +            if self.vm.bootloader:
   3.126 +                self.unlink(self.kernel)
   3.127 +                self.unlink(self.ramdisk)
   3.128 +            if dom <= 0:
   3.129 +                raise VmError('Creating domain failed: name=%s' % self.vm.name)
   3.130 +        log.debug("initDomain: cpu=%d mem_kb=%d dom=%d", cpu, mem_kb, dom)
   3.131 +        # xc.domain_setuuid(dom, uuid)
   3.132 +        xc.domain_setcpuweight(dom, cpu_weight)
   3.133 +        xc.domain_setmaxmem(dom, mem_kb)
   3.134 +        xc.domain_memory_increase_reservation(dom, mem_kb)
   3.135 +        if cpu != -1:
   3.136 +            xc.domain_pincpu(dom, 0, 1<<int(cpu))
   3.137 +        return dom
   3.138 +
   3.139 +    def createImage(self):
   3.140 +        """Entry point to create domain memory image.
   3.141 +        Override in subclass  if needed.
   3.142 +        """
   3.143 +        self.configure()
   3.144 +        self.createDomain()
   3.145 +
   3.146 +    def configure(self):
   3.147 +        """Config actions common to all unix-like domains."""
   3.148 +        self.kernel = sxp.child_value(self.config, "kernel")
   3.149 +        self.cmdline = ""
   3.150 +        ip = sxp.child_value(self.config, "ip", None)
   3.151 +        if ip:
   3.152 +            self.cmdline += " ip=" + ip
   3.153 +        root = sxp.child_value(self.config, "root")
   3.154 +        if root:
   3.155 +            self.cmdline += " root=" + root
   3.156 +        args = sxp.child_value(self.config, "args")
   3.157 +        if args:
   3.158 +            self.cmdline += " " + args
   3.159 +        self.ramdisk = sxp.child_value(self.config, "ramdisk", '')
   3.160 +        
   3.161 +    def createDomain(self):
   3.162 +        """Build the domain boot image.
   3.163 +        """
   3.164 +        # Set params and call buildDomain().
   3.165 +        self.flags = 0
   3.166 +        if self.vm.netif_backend: self.flags |= SIF_NET_BE_DOMAIN
   3.167 +        if self.vm.blkif_backend: self.flags |= SIF_BLK_BE_DOMAIN
   3.168 +
   3.169 +        if self.vm.recreate or self.vm.restore:
   3.170 +            return
   3.171 +        if not os.path.isfile(self.kernel):
   3.172 +            raise VmError('Kernel image does not exist: %s' % self.kernel)
   3.173 +        if self.ramdisk and not os.path.isfile(self.ramdisk):
   3.174 +            raise VmError('Kernel ramdisk does not exist: %s' % self.ramdisk)
   3.175 +        if len(self.cmdline) >= 256:
   3.176 +            log.warning('kernel cmdline too long, domain %d', self.vm.getDomain())
   3.177 +        
   3.178 +        log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype,
   3.179 +                 self.vm.getDomain(), self.vm.vcpus)
   3.180 +        err = self.buildDomain()
   3.181 +        if err != 0:
   3.182 +            raise VmError('Building domain failed: ostype=%s dom=%d err=%d'
   3.183 +                          % (self.ostype, self.vm.getDomain(), err))
   3.184 +
   3.185 +    def getDomainMemory(self, mem_mb):
   3.186 +        """Memory (in KB) the domain will need for mem_mb (in MB)."""
   3.187 +        return mem_mb * 1024
   3.188 +
   3.189 +    def buildDomain(self):
   3.190 +        """Build the domain. Define in subclass."""
   3.191 +        raise NotImplementedError()
   3.192 +
   3.193 +    def createDeviceModel(self):
   3.194 +        """Create device model for the domain (define in subclass if needed)."""
   3.195 +        pass
   3.196 +    
   3.197 +    def destroy(self):
   3.198 +        """Extra cleanup on domain destroy (define in subclass if needed)."""
   3.199 +        pass
   3.200 +
   3.201 +addImageHandlerClass = ImageHandler.addImageHandlerClass
   3.202 +
   3.203 +class LinuxImageHandler(ImageHandler):
   3.204 +
   3.205 +    ostype = "linux"
   3.206 +
   3.207 +    def buildDomain(self):
   3.208 +        #if self.vm.store_channel:
   3.209 +        #    store_evtchn = self.vm.store_channel.port2
   3.210 +        #else:
   3.211 +        #    store_evtchn = 0
   3.212 +        d  = xc.linux_build(dom            = self.vm.getDomain(),
   3.213 +                            image          = self.kernel,
   3.214 +                            control_evtchn = self.vm.channel.getRemotePort(),
   3.215 +                            #store_evtchn   = store_evtchn,
   3.216 +                            cmdline        = self.cmdline,
   3.217 +                            ramdisk        = self.ramdisk,
   3.218 +                            flags          = self.flags,
   3.219 +                            vcpus          = self.vm.vcpus)
   3.220 +        #if isinstance(d, dict):
   3.221 +        #    self.vm.store_mfn = d.get('store_mfn')
   3.222 +        return 0
   3.223 +
   3.224 +class Plan9ImageHandler(ImageHandler):
   3.225 +
   3.226 +    ostype = "plan9"
   3.227 +
   3.228 +    def buildDomain(self):
   3.229 +        return xc.plan9_build(dom            = self.vm.getDomain(),
   3.230 +                              image          = self.kernel,
   3.231 +                              control_evtchn = self.vm.channel.getRemotePort(),
   3.232 +                              cmdline        = self.cmdline,
   3.233 +                              ramdisk        = self.ramdisk,
   3.234 +                              flags          = self.flags,
   3.235 +                              vcpus          = self.vm.vcpus)
   3.236 +
   3.237 +class VmxImageHandler(ImageHandler):
   3.238 +
   3.239 +    #__exports__ = ImageHandler.__exports__ + [
   3.240 +    #    DBVar('memmap',        ty='str'),
   3.241 +    #    DBVar('memmap_value',  ty='sxpr'),
   3.242 +    #    # device channel?
   3.243 +    #    ]
   3.244 +    
   3.245 +    ostype = "vmx"
   3.246 +    memmap = None
   3.247 +    memmap_value = None
   3.248 +    device_channel = None
   3.249 +
   3.250 +    def createImage(self):
   3.251 +        """Create a VM for the VMX environment.
   3.252 +        """
   3.253 +        self.configure()
   3.254 +        self.parseMemmap()
   3.255 +        self.createDomain()
   3.256 +
   3.257 +    def buildDomain(self):
   3.258 +        return xc.vmx_build(dom            = self.vm.getDomain(),
   3.259 +                            image          = self.kernel,
   3.260 +                            control_evtchn = 0,
   3.261 +                            memsize        = self.vm.memory,
   3.262 +                            memmap         = self.memmap_value,
   3.263 +                            cmdline        = self.cmdline,
   3.264 +                            ramdisk        = self.ramdisk,
   3.265 +                            flags          = self.flags)
   3.266 +
   3.267 +    def parseMemmap(self):
   3.268 +        self.memmap = sxp.child_value(self.vm.config, "memmap")
   3.269 +        if self.memmap is None:
   3.270 +            raise VmError("missing memmap")
   3.271 +        memmap = sxp.parse(open(self.memmap))[0]
   3.272 +        from xen.util.memmap import memmap_parse
   3.273 +        self.memmap_value = memmap_parse(memmap)
   3.274 +        
   3.275 +    def createDeviceModel_old(self):
   3.276 +        device_model = sxp.child_value(self.vm.config, 'device_model')
   3.277 +        if not device_model:
   3.278 +            raise VmError("vmx: missing device model")
   3.279 +        device_config = sxp.child_value(self.vm.config, 'device_config')
   3.280 +        if not device_config:
   3.281 +            raise VmError("vmx: missing device config")
   3.282 +        # Create an event channel.
   3.283 +        self.device_channel = channel.eventChannel(0, self.vm.getDomain())
   3.284 +        # Execute device model.
   3.285 +        #todo: Error handling
   3.286 +        os.system(device_model
   3.287 +                  + " -f %s" % device_config
   3.288 +                  + " -d %d" % self.vm.getDomain()
   3.289 +                  + " -p %d" % self.device_channel['port1']
   3.290 +                  + " -m %s" % self.vm.memory)
   3.291 +
   3.292 +    def createDeviceModel(self):
   3.293 +        device_model = sxp.child_value(self.vm.config, 'device_model')
   3.294 +        if not device_model:
   3.295 +            raise VmError("vmx: missing device model")
   3.296 +        device_config = sxp.child_value(self.vm.config, 'device_config')
   3.297 +        if not device_config:
   3.298 +            raise VmError("vmx: missing device config")
   3.299 +        # Create an event channel
   3.300 +        self.device_channel = channel.eventChannel(0, self.vm.getDomain())
   3.301 +        # Execute device model.
   3.302 +        #todo: Error handling
   3.303 +        # XXX RN: note that the order of args matter!
   3.304 +        os.system(device_model
   3.305 +                  + " -f %s" % device_config
   3.306 +                  + self.vncParams()
   3.307 +                  + " -d %d" % self.vm.getDomain()
   3.308 +                  + " -p %d" % self.device_channel['port1']
   3.309 +                  + " -m %s" % self.vm.memory)
   3.310 +
   3.311 +    def vncParams(self):
   3.312 +        # see if a vncviewer was specified
   3.313 +        # XXX RN: bit of a hack. should unify this, maybe stick in config space
   3.314 +        vncconnect=""
   3.315 +        image = self.config
   3.316 +        args = sxp.child_value(image, "args")
   3.317 +        if args:
   3.318 +            arg_list = string.split(args)
   3.319 +            for arg in arg_list:
   3.320 +                al = string.split(arg, '=')
   3.321 +                if al[0] == "VNC_VIEWER":
   3.322 +                    vncconnect=" -v %s" % al[1]
   3.323 +                    break
   3.324 +        return vncconnect
   3.325 +
   3.326 +    def destroy(self):
   3.327 +        channel.eventChannelClose(self.device_channel)
   3.328 +
   3.329 +    def getDomainMemory(self, mem_mb):
   3.330 +        return (mem_mb * 1024) + self.getPageTableSize(mem_mb)
   3.331 +            
   3.332 +    def getPageTableSize(self, mem_mb):
   3.333 +        """Return the size of memory needed for 1:1 page tables for physical
   3.334 +           mode.
   3.335 +
   3.336 +        @param mem_mb: size in MB
   3.337 +        @return size in KB
   3.338 +        """
   3.339 +        # Logic x86-32 specific. 
   3.340 +        # 1 page for the PGD + 1 pte page for 4MB of memory (rounded)
   3.341 +        return (1 + ((mem_mb + 3) >> 2)) * 4