WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] xend/xm: Add PSCSI_HBA class and DSCSI_HB

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] xend/xm: Add PSCSI_HBA class and DSCSI_HBA class to XenAPI
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 12 Nov 2009 05:20:15 -0800
Delivery-date: Thu, 12 Nov 2009 05:20:28 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1258026044 0
# Node ID b7181e5d466611dca5aa37eaf7efe63a05ab605b
# Parent  368cfc61e7b6993bb599ebf7b0bafb78d245852b
xend/xm: Add PSCSI_HBA class and DSCSI_HBA class to XenAPI

XenAPI (not xapi) has supported only LUN assignment mode for pvSCSI.
But at last, HOST assignment mode also is supported by these patches.
To support HOST assignment mode, these patches add PSCSI_HBA class
and DSCSI_HBA class to XenAPI.

Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
---
 tools/python/xen/xend/XendAPI.py        |   22 ++++-
 tools/python/xen/xend/XendConfig.py     |   16 +++-
 tools/python/xen/xend/XendDSCSI.py      |  125 ++++++++++++++++++++++++++++++++
 tools/python/xen/xend/XendDomainInfo.py |   91 ++++++++++++++++++++++-
 tools/python/xen/xend/XendNode.py       |   97 ++++++++++++++++++++++--
 tools/python/xen/xend/XendPSCSI.py      |   68 +++++++++++++++++
 tools/python/xen/xm/create.dtd          |    6 +
 tools/python/xen/xm/create.py           |    3 
 tools/python/xen/xm/main.py             |   57 +++++++++-----
 tools/python/xen/xm/xenapi_create.py    |   81 ++++++++++++++------
 10 files changed, 501 insertions(+), 65 deletions(-)

diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xend/XendAPI.py  Thu Nov 12 11:40:44 2009 +0000
@@ -48,8 +48,8 @@ from XendPBD import XendPBD
 from XendPBD import XendPBD
 from XendPPCI import XendPPCI
 from XendDPCI import XendDPCI
-from XendPSCSI import XendPSCSI
-from XendDSCSI import XendDSCSI
+from XendPSCSI import XendPSCSI, XendPSCSI_HBA
+from XendDSCSI import XendDSCSI, XendDSCSI_HBA
 from XendXSPolicy import XendXSPolicy, XendACMPolicy
 
 from XendAPIConstants import *
@@ -495,7 +495,9 @@ classes = {
     'PPCI'         : valid_object("PPCI"),
     'DPCI'         : valid_object("DPCI"),
     'PSCSI'        : valid_object("PSCSI"),
-    'DSCSI'        : valid_object("DSCSI")
+    'PSCSI_HBA'    : valid_object("PSCSI_HBA"),
+    'DSCSI'        : valid_object("DSCSI"),
+    'DSCSI_HBA'    : valid_object("DSCSI_HBA"),
 }
 
 autoplug_classes = {
@@ -507,7 +509,9 @@ autoplug_classes = {
     'PPCI'        : XendPPCI,
     'DPCI'        : XendDPCI,
     'PSCSI'       : XendPSCSI,
+    'PSCSI_HBA'   : XendPSCSI_HBA,
     'DSCSI'       : XendDSCSI,
+    'DSCSI_HBA'   : XendDSCSI_HBA,
     'XSPolicy'    : XendXSPolicy,
     'ACMPolicy'   : XendACMPolicy,
 }
@@ -899,6 +903,7 @@ class XendAPI(object):
                     'PIFs',
                     'PPCIs',
                     'PSCSIs',
+                    'PSCSI_HBAs',
                     'host_CPUs',
                     'cpu_configuration',
                     'metrics',
@@ -991,6 +996,8 @@ class XendAPI(object):
         return xen_api_success(XendNode.instance().get_PPCI_refs())
     def host_get_PSCSIs(self, session, ref):
         return xen_api_success(XendNode.instance().get_PSCSI_refs())
+    def host_get_PSCSI_HBAs(self, session, ref):
+        return xen_api_success(XendNode.instance().get_PSCSI_HBA_refs())
     def host_get_host_CPUs(self, session, host_ref):
         return xen_api_success(XendNode.instance().get_host_cpu_refs())
     def host_get_metrics(self, _, ref):
@@ -1068,7 +1075,8 @@ class XendAPI(object):
                   'PIFs': XendPIF.get_all(),
                   'PBDs': XendPBD.get_all(),
                   'PPCIs': XendPPCI.get_all(),
-                  'PSCSIs': XendPSCSI.get_all()}
+                  'PSCSIs': XendPSCSI.get_all(),
+                  'PSCSI_HBAs': XendPSCSI_HBA.get_all()}
         return xen_api_success(record)
 
     def host_tmem_thaw(self, _, host_ref, cli_id):
@@ -1270,6 +1278,7 @@ class XendAPI(object):
                   'VTPMs',
                   'DPCIs',
                   'DSCSIs',
+                  'DSCSI_HBAs',
                   'tools_version',
                   'domid',
                   'is_control_domain',
@@ -1420,6 +1429,10 @@ class XendAPI(object):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         return xen_api_success(dom.get_dscsis())
 
+    def VM_get_DSCSI_HBAs(self, session, vm_ref):
+        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+        return xen_api_success(dom.get_dscsi_HBAs())
+
     def VM_get_tools_version(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         return dom.get_tools_version()
@@ -1806,6 +1819,7 @@ class XendAPI(object):
             'VTPMs': xeninfo.get_vtpms(),
             'DPCIs': xeninfo.get_dpcis(),
             'DSCSIs': xeninfo.get_dscsis(),
+            'DSCSI_HBAs': xeninfo.get_dscsi_HBAs(),
             'PV_bootloader': xeninfo.info.get('PV_bootloader'),
             'PV_kernel': xeninfo.info.get('PV_kernel'),
             'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xend/XendConfig.py       Thu Nov 12 11:40:44 2009 +0000
@@ -28,7 +28,7 @@ from xen.xend.XendPPCI import XendPPCI
 from xen.xend.XendPPCI import XendPPCI
 from xen.xend.XendDPCI import XendDPCI
 from xen.xend.XendPSCSI import XendPSCSI
-from xen.xend.XendDSCSI import XendDSCSI
+from xen.xend.XendDSCSI import XendDSCSI, XendDSCSI_HBA
 from xen.xend.XendError import VmError
 from xen.xend.XendDevices import XendDevices
 from xen.xend.PrettyPrint import prettyprintstring
@@ -1355,6 +1355,14 @@ class XendConfig(dict):
                 vscsi_mode = vscsi_dict['feature-host']
                 vscsi_be = vscsi_dict.get('backend', None)
 
+                # create XenAPI DSCSI_HBA objects.
+                dscsi_HBA_record = {
+                    'VM': self['uuid'],
+                    'virtual_host': int(vscsi_devs[0]['v-dev'].split(':')[0]),
+                    'assignment_mode': vscsi_mode and 'HOST' or 'LUN'
+                }
+                XendDSCSI_HBA(vscsi_devs_uuid, dscsi_HBA_record)
+
                 # create XenAPI DSCSI objects.
                 for vscsi_dev in vscsi_devs:
                     dscsi_uuid = vscsi_dev.get('uuid')
@@ -1364,6 +1372,7 @@ class XendConfig(dict):
                     dscsi_record = {
                         'VM': self['uuid'],
                         'PSCSI': pscsi_uuid,
+                        'HBA': vscsi_devs_uuid,
                         'virtual_HCTL': vscsi_dev.get('v-dev')
                     }
                     XendDSCSI(dscsi_uuid, dscsi_record)
@@ -1858,6 +1867,10 @@ class XendConfig(dict):
                     if vscsi_devid == dscsi_inst.get_virtual_host():
                         XendAPIStore.deregister(dscsi_uuid, "DSCSI")
 
+                # destroy existing XenAPI DSCSI_HBA objects
+                if not vscsi_devs:
+                    XendAPIStore.deregister(dev_uuid, 'DSCSI_HBA')
+
                 # create XenAPI DSCSI objects.
                 for vscsi_dev in vscsi_devs:
                     dscsi_uuid = vscsi_dev.get('uuid')
@@ -1867,6 +1880,7 @@ class XendConfig(dict):
                     dscsi_record = {
                         'VM': self['uuid'],
                         'PSCSI': pscsi_uuid,
+                        'HBA': dev_uuid,
                         'virtual_HCTL': vscsi_dev.get('v-dev')
                     }
                     XendDSCSI(dscsi_uuid, dscsi_record)
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xend/XendDSCSI.py
--- a/tools/python/xen/xend/XendDSCSI.py        Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xend/XendDSCSI.py        Thu Nov 12 11:40:44 2009 +0000
@@ -37,6 +37,7 @@ class XendDSCSI(XendBase):
     def getAttrRO(self):
         attrRO = ['VM',
                   'PSCSI',
+                  'HBA',
                   'virtual_host',
                   'virtual_channel',
                   'virtual_target',
@@ -52,6 +53,7 @@ class XendDSCSI(XendBase):
     def getAttrInst(self):
         attrInst = ['VM',
                     'PSCSI',
+                    'HBA',
                     'virtual_HCTL']
         return XendBase.getAttrInst() + attrInst
 
@@ -119,6 +121,9 @@ class XendDSCSI(XendBase):
 
     def get_PSCSI(self):
         return self.PSCSI
+
+    def get_HBA(self):
+        return self.HBA
 
     def get_virtual_host(self):
         return self.virtual_host
@@ -172,3 +177,123 @@ class XendDSCSI(XendBase):
                               dom.destroy_dscsi, \
                               self.get_uuid())
 
+
+class XendDSCSI_HBA(XendBase):
+    """Representation of a half-virtualized SCSI HBA."""
+
+    def getClass(self):
+        return "DSCSI_HBA"
+
+    def getAttrRO(self):
+        attrRO = ['VM',
+                  'PSCSI_HBAs',
+                  'DSCSIs',
+                  'virtual_host',
+                  'assignment_mode']
+        return XendBase.getAttrRO() + attrRO
+
+    def getAttrRW(self):
+        attrRW = []
+        return XendBase.getAttrRW() + attrRW
+
+    def getAttrInst(self):
+        attrInst = ['VM',
+                    'virtual_host',
+                    'assignment_mode']
+        return XendBase.getAttrInst() + attrInst
+
+    def getMethods(self):
+        methods = ['destroy']
+        return XendBase.getMethods() + methods
+
+    def getFuncs(self):
+        funcs = ['create']
+        return XendBase.getFuncs() + funcs
+
+    getClass    = classmethod(getClass)
+    getAttrRO   = classmethod(getAttrRO)
+    getAttrRW   = classmethod(getAttrRW)
+    getAttrInst = classmethod(getAttrInst)
+    getMethods  = classmethod(getMethods)
+    getFuncs    = classmethod(getFuncs)
+ 
+    def create(self, dscsi_HBA_struct):
+
+        # Check if VM is valid
+        xendom = XendDomain.instance()
+        if not xendom.is_valid_vm(dscsi_HBA_struct['VM']):
+            raise InvalidHandleError('VM', dscsi_HBA_struct['VM'])
+        dom = xendom.get_vm_by_uuid(dscsi_HBA_struct['VM'])
+
+        # Check if PSCSI_HBA is valid
+        xennode = XendNode.instance()
+        pscsi_HBA_uuid = 
xennode.get_pscsi_HBA_by_uuid(dscsi_HBA_struct['PSCSI_HBA'])
+        if not pscsi_HBA_uuid:
+            raise InvalidHandleError('PSCSI_HBA', 
dscsi_HBA_struct['PSCSI_HBA'])
+
+        # Assign PSCSI_HBA and PSCSIs to VM
+        try:
+            dscsi_HBA_ref = XendTask.log_progress(0, 100, \
+                                                  dom.create_dscsi_HBA, \
+                                                  dscsi_HBA_struct)
+        except XendError, e:
+            log.exception("Error in create_dscsi_HBA")
+            raise
+
+        return dscsi_HBA_ref
+
+    create = classmethod(create)
+
+    def get_by_VM(cls, VM_ref):
+        result = []
+        for dscsi_HBA in XendAPIStore.get_all("DSCSI_HBA"):
+            if dscsi_HBA.get_VM() == VM_ref:
+                result.append(dscsi_HBA.get_uuid())
+        return result
+
+    get_by_VM = classmethod(get_by_VM)
+
+    def __init__(self, uuid, record):
+        XendBase.__init__(self, uuid, record)
+        self.virtual_host = record['virtual_host']
+        self.assignment_mode = record['assignment_mode']
+
+    def get_VM(self):
+        return self.VM
+
+    def get_PSCSI_HBAs(self):
+        PSCSIs = []
+        uuid = self.get_uuid()
+        for dscsi in XendAPIStore.get_all('DSCSI'):
+            if dscsi.get_VM() == self.VM and dscsi.get_HBA() == uuid:
+                PSCSIs.append(dscsi.get_PSCSI())
+        PSCSI_HBAs = []
+        for pscsi_uuid in PSCSIs:
+            pscsi_HBA_uuid = XendAPIStore.get(pscsi_uuid, 'PSCSI').get_HBA()
+            if not pscsi_HBA_uuid in PSCSI_HBAs:
+                PSCSI_HBAs.append(pscsi_HBA_uuid)
+        return PSCSI_HBAs
+
+    def get_DSCSIs(self):
+        DSCSIs = []
+        uuid = self.get_uuid()
+        for dscsi in XendAPIStore.get_all('DSCSI'):
+            if dscsi.get_VM() == self.VM and dscsi.get_HBA() == uuid:
+                DSCSIs.append(dscsi.get_uuid())
+        return DSCSIs
+
+    def get_virtual_host(self):
+        return self.virtual_host
+
+    def get_assignment_mode(self):
+        return self.assignment_mode
+
+    def destroy(self):
+        xendom = XendDomain.instance()
+        dom = xendom.get_vm_by_uuid(self.get_VM())
+        if not dom:
+            raise InvalidHandleError("VM", self.get_VM())
+        XendTask.log_progress(0, 100, \
+                              dom.destroy_dscsi_HBA, \
+                              self.get_uuid())
+
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Nov 12 11:40:44 2009 +0000
@@ -68,7 +68,7 @@ from xen.xend.XendPPCI import XendPPCI
 from xen.xend.XendPPCI import XendPPCI
 from xen.xend.XendDPCI import XendDPCI
 from xen.xend.XendPSCSI import XendPSCSI
-from xen.xend.XendDSCSI import XendDSCSI
+from xen.xend.XendDSCSI import XendDSCSI, XendDSCSI_HBA
 
 MIGRATE_TIMEOUT = 30.0
 BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
@@ -3752,6 +3752,9 @@ class XendDomainInfo:
     def get_dscsis(self):
         return XendDSCSI.get_by_VM(self.info.get('uuid'))
 
+    def get_dscsi_HBAs(self):
+        return XendDSCSI_HBA.get_by_VM(self.info.get('uuid'))
+
     def create_vbd(self, xenapi_vbd, vdi_image_path):
         """Create a VBD using a VDI from XendStorageRepository.
 
@@ -3986,11 +3989,58 @@ class XendDomainInfo:
         else:
             try:
                 self.device_configure(target_vscsi_sxp)
-
             except Exception, exn:
+                log.exception('create_dscsi: %s', exn)
                 raise XendError('Failed to create device')
 
         return dscsi_uuid
+
+    def create_dscsi_HBA(self, xenapi_dscsi):
+        """Create scsi devices from the passed struct in Xen API format.
+
+        @param xenapi_dscsi: DSCSI_HBA struct from Xen API
+        @rtype: string
+        @return: UUID
+        """
+
+        dscsi_HBA_uuid = uuid.createString()
+
+        # Convert xenapi to sxp
+        feature_host = xenapi_dscsi.get('assignment_mode', 'HOST') == 'HOST' 
and 1 or 0
+        target_vscsi_sxp = \
+            ['vscsi',
+                ['feature-host', feature_host],
+                ['uuid', dscsi_HBA_uuid],
+            ]
+        pscsi_HBA = XendAPIStore.get(xenapi_dscsi.get('PSCSI_HBA'), 
'PSCSI_HBA')
+        devid = pscsi_HBA.get_physical_host()
+        for pscsi_uuid in pscsi_HBA.get_PSCSIs():
+            pscsi = XendAPIStore.get(pscsi_uuid, 'PSCSI')
+            pscsi_HCTL = pscsi.get_physical_HCTL()
+            dscsi_uuid = uuid.createString()
+            dev = \
+                ['dev',
+                    ['devid', devid],
+                    ['p-devname', pscsi.get_dev_name()],
+                    ['p-dev', pscsi_HCTL],
+                    ['v-dev', pscsi_HCTL],
+                    ['state', xenbusState['Initialising']],
+                    ['uuid', dscsi_uuid]
+                ]
+            target_vscsi_sxp.append(dev)
+
+        if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
+            if not self.info.device_add('vscsi', cfg_sxp = target_vscsi_sxp):
+                raise XendError('Failed to create device')
+            xen.xend.XendDomain.instance().managed_config_save(self)
+        else:
+            try:
+                self.device_configure(target_vscsi_sxp)
+            except Exception, exn:
+                log.exception('create_dscsi_HBA: %s', exn)
+                raise XendError('Failed to create device')
+
+        return dscsi_HBA_uuid
 
 
     def change_vdi_of_vbd(self, xenapi_vbd, vdi_image_path):
@@ -4121,9 +4171,40 @@ class XendDomainInfo:
         else:
             try:
                 self.device_configure(target_vscsi_sxp)
-
             except Exception, exn:
+                log.exception('destroy_dscsi: %s', exn)
                 raise XendError('Failed to destroy device')
+
+    def destroy_dscsi_HBA(self, dev_uuid):
+        dscsi_HBA = XendAPIStore.get(dev_uuid, 'DSCSI_HBA')
+        devid = dscsi_HBA.get_virtual_host()
+        cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid)
+        feature_host = sxp.child_value(cur_vscsi_sxp, 'feature-host')
+
+        if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
+            new_vscsi_sxp = ['vscsi', ['feature-host', feature_host]]
+            self.info.device_update(dev_uuid, new_vscsi_sxp)
+            del self.info['devices'][dev_uuid]
+            xen.xend.XendDomain.instance().managed_config_save(self)
+        else:
+            # If feature_host is 1, all devices are destroyed by just
+            # one reconfiguration.
+            # If feature_host is 0, we should reconfigure all devices
+            # one-by-one to destroy all devices.
+            # See reconfigureDevice@VSCSIController. 
+            for dev in sxp.children(cur_vscsi_sxp, 'dev'):
+                target_vscsi_sxp = [
+                    'vscsi',
+                    dev + [['state', xenbusState['Closing']]],
+                    ['feature-host', feature_host]
+                ]
+                try:
+                    self.device_configure(target_vscsi_sxp)
+                except Exception, exn:
+                    log.exception('destroy_dscsi_HBA: %s', exn)
+                    raise XendError('Failed to destroy device')
+                if feature_host:
+                    break
 
     def destroy_xapi_instances(self):
         """Destroy Xen-API instances stored in XendAPIStore.
@@ -4153,6 +4234,10 @@ class XendDomainInfo:
         for dscsi_uuid in XendDSCSI.get_by_VM(self.info.get('uuid')):
             XendAPIStore.deregister(dscsi_uuid, "DSCSI")
             
+        # Destroy DSCSI_HBA instances.
+        for dscsi_HBA_uuid in XendDSCSI_HBA.get_by_VM(self.info.get('uuid')):
+            XendAPIStore.deregister(dscsi_HBA_uuid, "DSCSI_HBA")
+            
     def has_device(self, dev_class, dev_uuid):
         return (dev_uuid in self.info['%s_refs' % dev_class.lower()])
 
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xend/XendNode.py Thu Nov 12 11:40:44 2009 +0000
@@ -41,7 +41,7 @@ from XendStateStore import XendStateStor
 from XendStateStore import XendStateStore
 from XendMonitor import XendMonitor
 from XendPPCI import XendPPCI
-from XendPSCSI import XendPSCSI
+from XendPSCSI import XendPSCSI, XendPSCSI_HBA
 
 class XendNode:
     """XendNode - Represents a Domain 0 Host."""
@@ -299,7 +299,7 @@ class XendNode:
             XendPPCI(ppci_uuid, ppci_record)
 
     def _init_PSCSIs(self):
-        # Initialise PSCSIs
+        # Initialise PSCSIs and PSCSI_HBAs
         saved_pscsis = self.state_store.load_state('pscsi')
         saved_pscsi_table = {}
         if saved_pscsis:
@@ -309,12 +309,52 @@ class XendNode:
                 except KeyError:
                     pass
 
+        saved_pscsi_HBAs = self.state_store.load_state('pscsi_HBA')
+        saved_pscsi_HBA_table = {}
+        if saved_pscsi_HBAs:
+            for pscsi_HBA_uuid, pscsi_HBA_record in saved_pscsi_HBAs.items():
+                try:
+                    physical_host = int(pscsi_HBA_record['physical_host'])
+                    saved_pscsi_HBA_table[physical_host] = pscsi_HBA_uuid
+                except (KeyError, ValueError):
+                    pass
+
+        pscsi_table = {}
+        pscsi_HBA_table = {}
+
         for pscsi_record in vscsi_util.get_all_scsi_devices():
-            if pscsi_record['scsi_id']:
-                # If saved uuid exists, use it. Otherwise create one.
-                pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'],
-                                                   uuid.createString())
-                XendPSCSI(pscsi_uuid, pscsi_record)
+            scsi_id = pscsi_record['scsi_id']
+            if scsi_id:
+                saved_HBA_uuid = None
+
+                pscsi_uuid = saved_pscsi_table.get(scsi_id, None)
+                if pscsi_uuid is None:
+                    pscsi_uuid = uuid.createString()
+                    saved_pscsi_table[scsi_id] = pscsi_uuid
+                else:
+                    saved_HBA_uuid = saved_pscsis[pscsi_uuid].get('HBA', None)
+
+                physical_host = 
int(pscsi_record['physical_HCTL'].split(':')[0])
+                if pscsi_HBA_table.has_key(physical_host):
+                    pscsi_HBA_uuid = pscsi_HBA_table[physical_host]
+                elif saved_pscsi_HBA_table.has_key(physical_host):
+                    pscsi_HBA_uuid = saved_pscsi_HBA_table[physical_host]
+                    pscsi_HBA_table[physical_host] = pscsi_HBA_uuid
+                else:
+                    pscsi_HBA_uuid = uuid.createString()
+                    pscsi_HBA_table[physical_host] = pscsi_HBA_uuid
+
+                if saved_HBA_uuid is not None and \
+                   saved_HBA_uuid != pscsi_HBA_uuid:
+                    log.debug('The PSCSI(%s) host number was changed', scsi_id)
+                pscsi_record['HBA'] = pscsi_HBA_uuid
+                pscsi_table[pscsi_uuid] = pscsi_record
+
+        for pscsi_uuid, pscsi_record in pscsi_table.items():
+            XendPSCSI(pscsi_uuid, pscsi_record)
+
+        for physical_host, pscsi_HBA_uuid in pscsi_HBA_table.items():
+            XendPSCSI_HBA(pscsi_HBA_uuid, {'physical_host': physical_host})
 
 
     def add_network(self, interface):
@@ -389,14 +429,32 @@ class XendNode:
                 except KeyError:
                     pass
 
-        # Initialise the PSCSI
+        saved_pscsi_HBAs = self.state_store.load_state('pscsi_HBA')
+        saved_pscsi_HBA_table = {}
+        if saved_pscsi_HBAs:
+            for saved_HBA_uuid, saved_HBA_record in saved_pscsi_HBAs.items():
+                try:
+                    physical_host = int(saved_HBA_record['physical_host'])
+                    saved_pscsi_HBA_table[physical_host] = saved_HBA_uuid
+                except (KeyError, ValueError):
+                    pass
+
+        # Initialise the PSCSI and the PSCSI_HBA
         pscsi_record = vscsi_util.get_scsi_device(add_HCTL)
         if pscsi_record and pscsi_record['scsi_id']:
             pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'], None)
             if pscsi_uuid is None:
+                physical_host = int(add_HCTL.split(':')[0])
+                pscsi_HBA_uuid = saved_pscsi_HBA_table.get(physical_host, None)
+                if pscsi_HBA_uuid is None:
+                    pscsi_HBA_uuid = uuid.createString()
+                    XendPSCSI_HBA(pscsi_HBA_uuid, {'physical_host': 
physical_host})
+                pscsi_record['HBA'] = pscsi_HBA_uuid
+
                 pscsi_uuid = uuid.createString()
                 XendPSCSI(pscsi_uuid, pscsi_record)
                 self.save_PSCSIs()
+                self.save_PSCSI_HBAs()
 
 
     def remove_PSCSI(self, rem_HCTL):
@@ -410,6 +468,14 @@ class XendNode:
                 pscsi_ref = XendPSCSI.get_by_HCTL(rem_HCTL)
                 XendAPIStore.get(pscsi_ref, "PSCSI").destroy()
                 self.save_PSCSIs()
+
+                physical_host = int(rem_HCTL.split(':')[0])
+                pscsi_HBA_ref = 
XendPSCSI_HBA.get_by_physical_host(physical_host)
+                if pscsi_HBA_ref:
+                    if not XendAPIStore.get(pscsi_HBA_ref, 
'PSCSI_HBA').get_PSCSIs():
+                        XendAPIStore.get(pscsi_HBA_ref, 'PSCSI_HBA').destroy()
+                self.save_PSCSI_HBAs()
+
                 return
 
 
@@ -470,6 +536,14 @@ class XendNode:
     def get_pscsi_by_uuid(self, pscsi_uuid):
         if pscsi_uuid in self.get_PSCSI_refs():
             return pscsi_uuid
+        return None
+
+    def get_PSCSI_HBA_refs(self):
+        return XendPSCSI_HBA.get_all()
+
+    def get_pscsi_HBA_by_uuid(self, pscsi_HBA_uuid):
+        if pscsi_HBA_uuid in self.get_PSCSI_HBA_refs():
+            return pscsi_HBA_uuid
         return None
 
 
@@ -487,6 +561,7 @@ class XendNode:
         self.save_SRs()
         self.save_PPCIs()
         self.save_PSCSIs()
+        self.save_PSCSI_HBAs()
 
     def save_PIFs(self):
         pif_records = dict([(pif_uuid, XendAPIStore.get(
@@ -522,6 +597,12 @@ class XendNode:
                                   pscsi_uuid, "PSCSI").get_record())
                             for pscsi_uuid in XendPSCSI.get_all()])
         self.state_store.save_state('pscsi', pscsi_records)
+
+    def save_PSCSI_HBAs(self):
+        pscsi_HBA_records = dict([(pscsi_HBA_uuid, XendAPIStore.get(
+                                      pscsi_HBA_uuid, 
"PSCSI_HBA").get_record())
+                                for pscsi_HBA_uuid in XendPSCSI_HBA.get_all()])
+        self.state_store.save_state('pscsi_HBA', pscsi_HBA_records)
 
     def shutdown(self):
         return 0
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xend/XendPSCSI.py
--- a/tools/python/xen/xend/XendPSCSI.py        Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xend/XendPSCSI.py        Thu Nov 12 11:40:44 2009 +0000
@@ -33,6 +33,7 @@ class XendPSCSI(XendBase):
                   'physical_target',
                   'physical_lun',
                   'physical_HCTL',
+                  'HBA',
                   'vendor_name',
                   'model',
                   'type_id',
@@ -77,6 +78,7 @@ class XendPSCSI(XendBase):
 
     def __init__(self, uuid, record):
         self.physical_HCTL = record['physical_HCTL']
+        self.physical_HBA = record['HBA']
         self.vendor_name = record['vendor_name']
         self.model = record['model']
         self.type_id = record['type_id']
@@ -114,6 +116,9 @@ class XendPSCSI(XendBase):
     def get_physical_HCTL(self):
         return self.physical_HCTL
 
+    def get_HBA(self):
+        return self.physical_HBA
+
     def get_vendor_name(self):
         return self.vendor_name
 
@@ -141,3 +146,66 @@ class XendPSCSI(XendBase):
     def get_scsi_level(self):
         return self.scsi_level
 
+
+class XendPSCSI_HBA(XendBase):
+    """Representation of a physical SCSI HBA."""
+
+    def getClass(self):
+        return "PSCSI_HBA"
+
+    def getAttrRO(self):
+        attrRO = ['host',
+                  'physical_host',
+                  'PSCSIs']
+        return XendBase.getAttrRO() + attrRO
+
+    def getAttrRW(self):
+        attrRW = []
+        return XendBase.getAttrRW() + attrRW
+
+    def getAttrInst(self):
+        attrInst = []
+        return XendBase.getAttrInst() + attrInst
+
+    def getMethods(self):
+        methods = []
+        return XendBase.getMethods() + methods
+
+    def getFuncs(self):
+        funcs = []
+        return XendBase.getFuncs() + funcs
+
+    getClass    = classmethod(getClass)
+    getAttrRO   = classmethod(getAttrRO)
+    getAttrRW   = classmethod(getAttrRW)
+    getAttrInst = classmethod(getAttrInst)
+    getMethods  = classmethod(getMethods)
+    getFuncs    = classmethod(getFuncs)
+ 
+    def get_by_physical_host(self, physical_host):
+        for pscsi_HBA in XendAPIStore.get_all('PSCSI_HBA'):
+            if pscsi_HBA.get_physical_host() == physical_host:
+                return pscsi_HBA.get_uuid()
+        return None
+
+    get_by_physical_host = classmethod(get_by_physical_host)
+
+    def __init__(self, uuid, record):
+        self.physical_host = record['physical_host']
+        XendBase.__init__(self, uuid, record)
+
+    def get_host(self):
+        from xen.xend import XendNode
+        return XendNode.instance().get_uuid()
+
+    def get_physical_host(self):
+        return self.physical_host
+
+    def get_PSCSIs(self):
+        PSCSIs = []
+        uuid = self.get_uuid()
+        for pscsi in XendAPIStore.get_all('PSCSI'):
+            if pscsi.get_HBA() == uuid:
+                PSCSIs.append(pscsi.get_uuid())
+        return PSCSIs
+
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xm/create.dtd
--- a/tools/python/xen/xm/create.dtd    Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xm/create.dtd    Thu Nov 12 11:40:44 2009 +0000
@@ -94,8 +94,10 @@
                  key             CDATA #IMPLIED>
 
 <!ELEMENT vscsi  EMPTY>
-<!ATTLIST vscsi  p-dev           CDATA #REQUIRED
-                 v-dev           CDATA #REQUIRED>
+<!ATTLIST vscsi  feature-host    CDATA #REQUIRED
+                 p-dev           CDATA #IMPLIED
+                 v-dev           CDATA #IMPLIED
+                 devid           CDATA #IMPLIED>
 
 <!ELEMENT console (other_config*)>
 <!ATTLIST console protocol       (vt100|rfb|rdp) #REQUIRED>
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xm/create.py     Thu Nov 12 11:40:44 2009 +0000
@@ -801,9 +801,6 @@ def configure_vscsis(config_devs, vals):
 
         feature_host = 0
         if v_dev == 'host':
-            if serverType == SERVER_XEN_API:
-                # TODO
-                raise ValueError("SCSI devices assignment by HBA is not 
implemeted")
             feature_host = 1
             scsi_info = []
             devid = get_devid(p_hctl)
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xm/main.py       Thu Nov 12 11:40:44 2009 +0000
@@ -2672,9 +2672,6 @@ def parse_scsi_configuration(p_scsi, v_h
     if p_scsi is not None:
         # xm scsi-attach
         if v_hctl == "host":
-            if serverType == SERVER_XEN_API:
-                # TODO
-                raise OptionError("SCSI devices assignment by HBA is not 
implemeted")
             host_mode = 1
             scsi_devices = vscsi_util.vscsi_get_scsidevices()
         elif len(v_hctl.split(':')) != 4:
@@ -2718,21 +2715,39 @@ def xm_scsi_attach(args):
     if serverType == SERVER_XEN_API:
 
         scsi_dev = sxp.children(scsi, 'dev')[0]
-        p_hctl = sxp.child_value(scsi_dev, 'p-dev')
-        target_ref = None
-        for pscsi_ref in server.xenapi.PSCSI.get_all():
-            if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
-                target_ref = pscsi_ref
-                break
-        if target_ref is None:
-            raise OptionError("Cannot find device '%s'" % p_scsi)
-
-        dscsi_record = {
-            "VM":           get_single_vm(dom),
-            "PSCSI":        target_ref,
-            "virtual_HCTL": v_hctl
-        }
-        server.xenapi.DSCSI.create(dscsi_record)
+
+        if sxp.child_value(scsi, 'feature-host'):
+            p_host = sxp.child_value(scsi_dev, 'devid')
+            target_ref = None
+            for pscsi_ref in server.xenapi.PSCSI_HBA.get_all():
+                if p_host == 
int(server.xenapi.PSCSI_HBA.get_physical_host(pscsi_ref)):
+                    target_ref = pscsi_ref
+                    break
+            if target_ref is None:
+                raise OptionError("Cannot find device '%s'" % p_scsi)
+
+            dscsi_record = {
+                "VM":              get_single_vm(dom),
+                "PSCSI_HBA":       target_ref,
+                "assignment_mode": "HOST"
+            }
+            server.xenapi.DSCSI_HBA.create(dscsi_record)
+        else:
+            p_hctl = sxp.child_value(scsi_dev, 'p-dev')
+            target_ref = None
+            for pscsi_ref in server.xenapi.PSCSI.get_all():
+                if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
+                    target_ref = pscsi_ref
+                    break
+            if target_ref is None:
+                raise OptionError("Cannot find device '%s'" % p_scsi)
+
+            dscsi_record = {
+                "VM":           get_single_vm(dom),
+                "PSCSI":        target_ref,
+                "virtual_HCTL": v_hctl
+            }
+            server.xenapi.DSCSI.create(dscsi_record)
 
     else:
         if len(args) == 4:
@@ -2894,7 +2909,11 @@ def xm_scsi_detach(args):
         if target_ref is None:
             raise OptionError("Device %s not assigned" % v_hctl)
 
-        server.xenapi.DSCSI.destroy(target_ref)
+        target_HBA_ref = server.xenapi.DSCSI.get_HBA(target_ref)
+        if server.xenapi.DSCSI_HBA.get_assignment_mode(target_HBA_ref) == 
"HOST":
+            server.xenapi.DSCSI_HBA.destroy(target_HBA_ref)
+        else:
+            server.xenapi.DSCSI.destroy(target_ref)
 
     else:
         server.xend.domain.device_configure(dom, scsi)
diff -r 368cfc61e7b6 -r b7181e5d4666 tools/python/xen/xm/xenapi_create.py
--- a/tools/python/xen/xm/xenapi_create.py      Thu Nov 12 11:39:51 2009 +0000
+++ b/tools/python/xen/xm/xenapi_create.py      Thu Nov 12 11:40:44 2009 +0000
@@ -567,25 +567,48 @@ class xenapi_create:
     def create_scsi(self, vm_ref, scsi):
         log(DEBUG, "create_scsi")
 
-        target_ref = None
-        for pscsi_ref in server.xenapi.PSCSI.get_all():
-            if scsi.attributes["p-dev"].value == 
server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
-                target_ref = pscsi_ref
-                break
-        if target_ref is None:
-            log(DEBUG, "create_scsi: scsi device not found")
-            return None
-
-        dscsi_record = {
-            "VM":
-                vm_ref,
-            "PSCSI":
-                target_ref,
-            "virtual_HCTL":
-                scsi.attributes["v-dev"].value
-        }
-
-        return server.xenapi.DSCSI.create(dscsi_record)
+        if scsi.attributes["feature-host"].value == "True":
+            target_HBA_ref = None
+            for pscsi_HBA_ref in server.xenapi.PSCSI_HBA.get_all():
+                if int(scsi.attributes["devid"].value) == \
+                   
int(server.xenapi.PSCSI_HBA.get_physical_host(pscsi_HBA_ref)):
+                    target_HBA_ref = pscsi_HBA_ref
+                    break
+            if target_HBA_ref is None:
+                log(DEBUG, "create_scsi: scsi device not found")
+                return None
+
+            dscsi_record = {
+                "VM":
+                    vm_ref,
+                "PSCSI_HBA":
+                    target_HBA_ref,
+                "assignment_mode":
+                    "HOST"
+            }
+
+            return server.xenapi.DSCSI_HBA.create(dscsi_record)
+        else:
+            target_ref = None
+            for pscsi_ref in server.xenapi.PSCSI.get_all():
+                if scsi.attributes["p-dev"].value == \
+                   server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
+                    target_ref = pscsi_ref
+                    break
+            if target_ref is None:
+                log(DEBUG, "create_scsi: scsi device not found")
+                return None
+
+            dscsi_record = {
+                "VM":
+                    vm_ref,
+                "PSCSI":
+                    target_ref,
+                "virtual_HCTL":
+                    scsi.attributes["v-dev"].value
+            }
+
+            return server.xenapi.DSCSI.create(dscsi_record)
 
 def get_child_by_name(exp, childname, default = None):
     try:
@@ -981,15 +1004,23 @@ class sxp2xml:
         scsis = []
 
         for scsi_sxp in scsis_sxp:
+            feature_host = sxp.child_value(scsi_sxp, "feature-host")
             for dev_sxp in sxp.children(scsi_sxp, "dev"):
                 scsi = document.createElement("vscsi")
 
-                scsi.attributes["p-dev"] \
-                    = get_child_by_name(dev_sxp, "p-dev")
-                scsi.attributes["v-dev"] \
-                    = get_child_by_name(dev_sxp, "v-dev")
-
-                scsis.append(scsi)
+                scsi.attributes["feature-host"] \
+                    = feature_host and "True" or "False"
+                if feature_host:
+                    scsi.attributes["devid"] \
+                        = str(get_child_by_name(dev_sxp, "devid"))
+                    scsis.append(scsi)
+                    break
+                else:
+                    scsi.attributes["p-dev"] \
+                        = get_child_by_name(dev_sxp, "p-dev")
+                    scsi.attributes["v-dev"] \
+                        = get_child_by_name(dev_sxp, "v-dev")
+                    scsis.append(scsi)
 
         return scsis
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] xend/xm: Add PSCSI_HBA class and DSCSI_HBA class to XenAPI, Xen patchbot-unstable <=