[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] xend/xm: Add PSCSI_HBA class and DSCSI_HBA class to XenAPI
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |