ia64/xen-unstable

changeset 14480:e2f302488983

Add VBD.runtime_properties dictionary, and use that to implement xm block-list
through the Xen-API. Implement xm block-attach and xm block-detach also.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Mar 20 11:45:44 2007 +0000 (2007-03-20)
parents dace880e871a
children e7c6e6621e85
files tools/python/xen/xend/XendAPI.py tools/python/xen/xend/XendVDI.py tools/python/xen/xm/main.py tools/python/xen/xm/xenapi_create.py
line diff
     1.1 --- a/tools/python/xen/xend/XendAPI.py	Tue Mar 20 11:44:13 2007 +0000
     1.2 +++ b/tools/python/xen/xend/XendAPI.py	Tue Mar 20 11:45:44 2007 +0000
     1.3 @@ -36,6 +36,9 @@ from xen.xend.XendVMMetrics import XendV
     1.4  from xen.xend.XendAPIConstants import *
     1.5  from xen.util.xmlrpclib2 import stringify
     1.6  
     1.7 +from xen.util.blkif import blkdev_name_to_number
     1.8 +
     1.9 +
    1.10  AUTH_NONE = 'none'
    1.11  AUTH_PAM = 'pam'
    1.12  
    1.13 @@ -1555,7 +1558,8 @@ class XendAPI(object):
    1.14      # Xen API: Class VBD
    1.15      # ----------------------------------------------------------------
    1.16  
    1.17 -    VBD_attr_ro = ['metrics']
    1.18 +    VBD_attr_ro = ['metrics',
    1.19 +                   'runtime_properties']
    1.20      VBD_attr_rw = ['VM',
    1.21                     'VDI',
    1.22                     'device',
    1.23 @@ -1596,23 +1600,28 @@ class XendAPI(object):
    1.24      # class methods
    1.25      def VBD_create(self, session, vbd_struct):
    1.26          xendom = XendDomain.instance()
    1.27 +        xennode = XendNode.instance()
    1.28 +        
    1.29          if not xendom.is_valid_vm(vbd_struct['VM']):
    1.30              return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
    1.31          
    1.32          dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
    1.33 -        vbd_ref = ''
    1.34 +        vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
    1.35 +        if not vdi:
    1.36 +            return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
    1.37 +
    1.38 +        # new VBD via VDI/SR
    1.39 +        vdi_image = vdi.get_location()
    1.40 +
    1.41          try:
    1.42 -            # new VBD via VDI/SR
    1.43 -            vdi_ref = vbd_struct.get('VDI')
    1.44 -            vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
    1.45 -            if not vdi:
    1.46 -                return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
    1.47 -            vdi_image = vdi.get_location()
    1.48              vbd_ref = XendTask.log_progress(0, 100,
    1.49                                              dom.create_vbd,
    1.50                                              vbd_struct, vdi_image)
    1.51 -        except XendError:
    1.52 -            return xen_api_todo()
    1.53 +        except XendError, e:
    1.54 +            log.exception("Error in VBD_create")
    1.55 +            return xen_api_error(['INTERNAL_ERROR', str(e)]) 
    1.56 +            
    1.57 +        vdi.addVBD(vbd_ref)
    1.58  
    1.59          xendom.managed_config_save(dom)
    1.60          return xen_api_success(vbd_ref)
    1.61 @@ -1624,7 +1633,14 @@ class XendAPI(object):
    1.62          if not vm:
    1.63              return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
    1.64  
    1.65 +        vdi_ref = XendDomain.instance()\
    1.66 +                  .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
    1.67 +        vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
    1.68 +
    1.69          XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
    1.70 +
    1.71 +        vdi.removeVBD(vbd_ref)
    1.72 +        
    1.73          return xen_api_success_void()
    1.74  
    1.75      def _VBD_get(self, vbd_ref, prop):
    1.76 @@ -1636,6 +1652,26 @@ class XendAPI(object):
    1.77      def VBD_get_metrics(self, _, vbd_ref):
    1.78          return xen_api_success(vbd_ref)
    1.79  
    1.80 +    def VBD_get_runtime_properties(self, _, vbd_ref):
    1.81 +        xendom = XendDomain.instance()
    1.82 +        dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
    1.83 +        device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
    1.84 +        devid = int(device['id'])
    1.85 +        device_sxps = dominfo.getDeviceSxprs('vbd')
    1.86 +
    1.87 +        log.debug("VBD_get_runtime_properties devid: %i device_sxps: %s",
    1.88 +                  devid, device_sxps)
    1.89 +        
    1.90 +        device_dicts  = [dict(device_sxp[1][1:]) for device_sxp in device_sxps]
    1.91 +
    1.92 +        device_dict = [device_dict
    1.93 +                       for device_dict in device_dicts
    1.94 +                       if int(device_dict['virtual-device']) == devid][0]
    1.95 +
    1.96 +        log.debug("VBD_get_runtime_properties device_dict: %s", device_dict)
    1.97 +
    1.98 +        return xen_api_success(device_dict)
    1.99 +
   1.100      # attributes (rw)
   1.101      def VBD_get_VM(self, session, vbd_ref):
   1.102          return self._VBD_get(vbd_ref, 'VM')
   1.103 @@ -1828,7 +1864,8 @@ class XendAPI(object):
   1.104          return XendNode.instance().get_vdi_by_uuid(ref)
   1.105      
   1.106      def VDI_get_VBDs(self, session, vdi_ref):
   1.107 -        return xen_api_todo()
   1.108 +        vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
   1.109 +        return xen_api_success(vdi.getVBDs())
   1.110      
   1.111      def VDI_get_physical_utilisation(self, session, vdi_ref):
   1.112          return xen_api_success(self._get_VDI(vdi_ref).
   1.113 @@ -1898,7 +1935,7 @@ class XendAPI(object):
   1.114              'name_label': image.name_label,
   1.115              'name_description': image.name_description,
   1.116              'SR': image.sr_uuid,
   1.117 -            'VBDs': [], # TODO
   1.118 +            'VBDs': image.getVBDs(),
   1.119              'virtual_size': image.virtual_size,
   1.120              'physical_utilisation': image.physical_utilisation,
   1.121              'type': image.type,
     2.1 --- a/tools/python/xen/xend/XendVDI.py	Tue Mar 20 11:44:13 2007 +0000
     2.2 +++ b/tools/python/xen/xend/XendVDI.py	Tue Mar 20 11:45:44 2007 +0000
     2.3 @@ -72,6 +72,16 @@ class XendVDI(AutoSaveObject):
     2.4          self.read_only = False
     2.5          self.type = "system"
     2.6          self.other_config = {}
     2.7 +        self.vbds = []
     2.8 +
     2.9 +    def addVBD(self, vbd_ref):
    2.10 +        self.vbds.append(vbd_ref)
    2.11 +
    2.12 +    def removeVBD(self, vbd_ref):
    2.13 +        self.vbds.remove(vbd_ref)
    2.14 +
    2.15 +    def getVBDs(self):
    2.16 +        return self.vbds
    2.17  
    2.18      def load_config_dict(self, cfg):
    2.19          """Loads configuration into the object from a dict.
     3.1 --- a/tools/python/xen/xm/main.py	Tue Mar 20 11:44:13 2007 +0000
     3.2 +++ b/tools/python/xen/xm/main.py	Tue Mar 20 11:45:44 2007 +0000
     3.3 @@ -33,7 +33,6 @@ import getopt
     3.4  import socket
     3.5  import traceback
     3.6  import xmlrpclib
     3.7 -import traceback
     3.8  import time
     3.9  import datetime
    3.10  from select import select
    3.11 @@ -50,6 +49,7 @@ from xen.xend.XendConstants import *
    3.12  from xen.xm.opts import OptionError, Opts, wrap, set_true
    3.13  from xen.xm import console
    3.14  from xen.util.xmlrpclib2 import ServerProxy
    3.15 +
    3.16  import XenAPI
    3.17  
    3.18  
    3.19 @@ -492,6 +492,14 @@ def usage(cmd = None):
    3.20  #
    3.21  ####################################################################
    3.22  
    3.23 +def get_default_SR():
    3.24 +    return [sr_ref
    3.25 +            for sr_ref in server.xenapi.SR.get_all()
    3.26 +            if server.xenapi.SR.get_type(sr_ref) == "local"][0]
    3.27 +
    3.28 +def map2sxp(m):
    3.29 +    return [[k, m[k]] for k in m.keys()]
    3.30 +
    3.31  def arg_check(args, name, lo, hi = -1):
    3.32      n = len([i for i in args if i != '--'])
    3.33      
    3.34 @@ -675,9 +683,6 @@ def xm_restore(args):
    3.35  
    3.36  def getDomains(domain_names, state, full = 0):
    3.37      if serverType == SERVER_XEN_API:
    3.38 -        def map2sxp(m):
    3.39 -            return ["domain"] + [[k, m[k]] for k in m.keys()]
    3.40 -        
    3.41          doms_sxp = []
    3.42          doms_dict = []
    3.43          dom_refs = server.xenapi.VM.get_all()
    3.44 @@ -691,11 +696,11 @@ def getDomains(domain_names, state, full
    3.45                              'state':    '-----',
    3.46                              'cpu_time': dom_metrics['vcpus_utilisation']})
    3.47  			
    3.48 -            doms_sxp.append(map2sxp(dom_rec))
    3.49 +            doms_sxp.append(['domain'] + map2sxp(dom_rec))
    3.50              doms_dict.append(dom_rec)
    3.51              
    3.52          if domain_names:
    3.53 -            doms = [map2sxp(dom) for dom in doms_dict
    3.54 +            doms = [['domain'] + map2sxp(dom) for dom in doms_dict
    3.55                      if dom["name"] in domain_names]
    3.56              
    3.57              if len(doms) > 0:
    3.58 @@ -1689,12 +1694,20 @@ def xm_block_list(args):
    3.59      (use_long, params) = arg_check_for_resource_list(args, "block-list")
    3.60  
    3.61      dom = params[0]
    3.62 +
    3.63 +    if serverType == SERVER_XEN_API:
    3.64 +        vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
    3.65 +        vbd_properties = \
    3.66 +            map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
    3.67 +        devs = map(lambda x: [x['virtual-device'], map2sxp(x)], vbd_properties)
    3.68 +    else:
    3.69 +        devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
    3.70 +
    3.71      if use_long:
    3.72 -        devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
    3.73          map(PrettyPrint.prettyprint, devs)
    3.74      else:
    3.75          hdr = 0
    3.76 -        for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
    3.77 +        for x in devs:
    3.78              if hdr == 0:
    3.79                  print 'Vdev  BE handle state evt-ch ring-ref BE-path'
    3.80                  hdr = 1
    3.81 @@ -1767,8 +1780,45 @@ def parse_block_configuration(args):
    3.82  def xm_block_attach(args):
    3.83      arg_check(args, 'block-attach', 4, 5)
    3.84  
    3.85 -    (dom, vbd) = parse_block_configuration(args)
    3.86 -    server.xend.domain.device_create(dom, vbd)
    3.87 +    if serverType == SERVER_XEN_API:
    3.88 +        dom   = args[0]
    3.89 +        uname = args[1]
    3.90 +        dev   = args[2]
    3.91 +        mode  = args[3]
    3.92 +
    3.93 +        # First create new VDI
    3.94 +        vdi_record = {
    3.95 +            "name_label":       "vdi" + str(uname.__hash__()),   
    3.96 +            "name_description": "",
    3.97 +            "SR":               get_default_SR(),
    3.98 +            "virtual_size":     0,
    3.99 +            "sector_size":      512,
   3.100 +            "type":             "system",
   3.101 +            "sharable":         False,
   3.102 +            "read_only":        mode!="w",
   3.103 +            "other_config":     {"location": uname}
   3.104 +        }
   3.105 +
   3.106 +        vdi_ref = server.xenapi.VDI.create(vdi_record)
   3.107 +
   3.108 +        # Now create new VBD
   3.109 +
   3.110 +        vbd_record = {
   3.111 +            "VM":               get_single_vm(dom),
   3.112 +            "VDI":              vdi_ref,
   3.113 +            "device":           dev,
   3.114 +            "bootable":         True,
   3.115 +            "mode":             mode=="w" and "RW" or "RO",
   3.116 +            "type":             "Disk",
   3.117 +            "qos_algorithm_type": "",
   3.118 +            "qos_algorithm_params": {}
   3.119 +        }
   3.120 +
   3.121 +        server.xenapi.VBD.create(vbd_record)
   3.122 +        
   3.123 +    else:
   3.124 +        (dom, vbd) = parse_block_configuration(args)
   3.125 +        server.xend.domain.device_create(dom, vbd)
   3.126  
   3.127  
   3.128  def xm_block_configure(args):
   3.129 @@ -1814,13 +1864,30 @@ def detach(args, command, deviceClass):
   3.130  
   3.131  
   3.132  def xm_block_detach(args):
   3.133 -    try:
   3.134 -        detach(args, 'block-detach', 'vbd')
   3.135 -        return
   3.136 -    except:
   3.137 -        pass
   3.138 -    detach(args, 'block-detach', 'tap')
   3.139 +    if serverType == SERVER_XEN_API:
   3.140 +        arg_check(args, "xm_block_detach", 2, 3)
   3.141 +        dom = args[0]
   3.142 +        dev = args[1]
   3.143 +        vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
   3.144 +        vbd_refs = [vbd_ref for vbd_ref in vbd_refs
   3.145 +                    if server.xenapi.VBD.get_device(vbd_ref) == dev]
   3.146 +        if len(vbd_refs) > 0:
   3.147 +            vbd_ref = vbd_refs[0]
   3.148 +            vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
   3.149  
   3.150 +            server.xenapi.VBD.destroy(vbd_ref)
   3.151 +
   3.152 +            if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
   3.153 +                server.xenapi.VDI.destroy(vdi_ref)
   3.154 +        else:
   3.155 +            print "Cannot find device '%s' in domain '%s'" % (dev,dom)
   3.156 +    else:
   3.157 +        try:
   3.158 +            detach(args, 'block-detach', 'vbd')
   3.159 +            return
   3.160 +        except:
   3.161 +            pass
   3.162 +        detach(args, 'block-detach', 'tap')
   3.163  
   3.164  def xm_network_detach(args):
   3.165      detach(args, 'network-detach', 'vif')
     4.1 --- a/tools/python/xen/xm/xenapi_create.py	Tue Mar 20 11:44:13 2007 +0000
     4.2 +++ b/tools/python/xen/xm/xenapi_create.py	Tue Mar 20 11:45:44 2007 +0000
     4.3 @@ -18,7 +18,7 @@
     4.4  """Domain creation using new XenAPI
     4.5  """
     4.6  
     4.7 -from xen.xm.main import server
     4.8 +from xen.xm.main import server, get_default_SR
     4.9  from xml.dom.minidom import parse, getDOMImplementation
    4.10  from xml.dom.ext import PrettyPrint
    4.11  from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
    4.12 @@ -71,9 +71,7 @@ def try_quietly(fn, *args):
    4.13  class xenapi_create:
    4.14  
    4.15      def __init__(self):
    4.16 -        self.DEFAULT_STORAGE_REPOSITORY = [sr_ref
    4.17 -                  for sr_ref in server.xenapi.SR.get_all()
    4.18 -                  if server.xenapi.SR.get_type(sr_ref) == "local"][0]
    4.19 +        self.DEFAULT_STORAGE_REPOSITORY = get_default_SR()
    4.20  
    4.21          self.dtd = "/usr/lib/python/xen/xm/create.dtd"
    4.22