diff -r 22c89412fc8c tools/python/xen/xend/XendAPI.py --- a/tools/python/xen/xend/XendAPI.py Wed Oct 15 15:58:09 2008 +0100 +++ b/tools/python/xen/xend/XendAPI.py Thu Oct 16 11:45:13 2008 +0900 @@ -42,6 +42,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 XendXSPolicy import XendXSPolicy, XendACMPolicy from XendAPIConstants import * @@ -480,7 +482,9 @@ classes = { 'PBD' : valid_object("PBD"), 'PIF_metrics' : valid_object("PIF_metrics"), 'PPCI' : valid_object("PPCI"), - 'DPCI' : valid_object("DPCI") + 'DPCI' : valid_object("DPCI"), + 'PSCSI' : valid_object("PSCSI"), + 'DSCSI' : valid_object("DSCSI") } autoplug_classes = { @@ -491,6 +495,8 @@ autoplug_classes = { 'PIF_metrics' : XendPIFMetrics, 'PPCI' : XendPPCI, 'DPCI' : XendDPCI, + 'PSCSI' : XendPSCSI, + 'DSCSI' : XendDSCSI, 'XSPolicy' : XendXSPolicy, 'ACMPolicy' : XendACMPolicy, } @@ -881,6 +887,7 @@ class XendAPI(object): 'PBDs', 'PIFs', 'PPCIs', + 'PSCSIs', 'host_CPUs', 'cpu_configuration', 'metrics', @@ -961,6 +968,8 @@ class XendAPI(object): return xen_api_success(XendNode.instance().get_PIF_refs()) def host_get_PPCIs(self, session, ref): 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_host_CPUs(self, session, host_ref): return xen_api_success(XendNode.instance().get_host_cpu_refs()) def host_get_metrics(self, _, ref): @@ -1037,7 +1046,8 @@ class XendAPI(object): 'logging': {}, 'PIFs': XendPIF.get_all(), 'PBDs': XendPBD.get_all(), - 'PPCIs': XendPPCI.get_all()} + 'PPCIs': XendPPCI.get_all(), + 'PSCSIs': XendPSCSI.get_all()} return xen_api_success(record) # class methods @@ -1158,6 +1168,7 @@ class XendAPI(object): 'VBDs', 'VTPMs', 'DPCIs', + 'DSCSIs', 'tools_version', 'domid', 'is_control_domain', @@ -1304,6 +1315,10 @@ class XendAPI(object): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_dpcis()) + def VM_get_DSCSIs(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success(dom.get_dscsis()) + def VM_get_tools_version(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return dom.get_tools_version() @@ -1684,6 +1699,7 @@ class XendAPI(object): 'VBDs': xeninfo.get_vbds(), 'VTPMs': xeninfo.get_vtpms(), 'DPCIs': xeninfo.get_dpcis(), + 'DSCSIs': xeninfo.get_dscsis(), 'PV_bootloader': xeninfo.info.get('PV_bootloader'), 'PV_kernel': xeninfo.info.get('PV_kernel'), 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'), diff -r 22c89412fc8c tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Wed Oct 15 15:58:09 2008 +0100 +++ b/tools/python/xen/xend/XendConfig.py Thu Oct 16 11:52:58 2008 +0900 @@ -26,6 +26,8 @@ from xen.xend import XendAPIStore from xen.xend import XendAPIStore 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.XendError import VmError from xen.xend.XendDevices import XendDevices from xen.xend.PrettyPrint import prettyprintstring @@ -782,8 +784,8 @@ class XendConfig(dict): log.debug('_sxp_to_xapi(%s)' % scrub_password(sxp_cfg)) # _parse_sxp() below will call device_add() and construct devices. - # Some devices (currently only pci) may require VM's uuid, so - # setup self['uuid'] beforehand. + # Some devices may require VM's uuid, so setup self['uuid'] + # beforehand. self['uuid'] = sxp.child_value(sxp_cfg, 'uuid', uuid.createString()) cfg = self._parse_sxp(sxp_cfg) @@ -1222,29 +1224,28 @@ class XendConfig(dict): dev_type = sxp.name(config) dev_info = {} - if dev_type == 'pci' or dev_type == 'vscsi': + if dev_type == 'pci': pci_devs_uuid = sxp.child_value(config, 'uuid', uuid.createString()) pci_dict = self.pci_convert_sxp_to_dict(config) pci_devs = pci_dict['devs'] - if dev_type != 'vscsi': - # create XenAPI DPCI objects. - for pci_dev in pci_devs: - dpci_uuid = pci_dev.get('uuid') - ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], - pci_dev['bus'], - pci_dev['slot'], - pci_dev['func']) - if ppci_uuid is None: - continue - dpci_record = { - 'VM': self['uuid'], - 'PPCI': ppci_uuid, - 'hotplug_slot': pci_dev.get('vslot', 0) - } - XendDPCI(dpci_uuid, dpci_record) + # create XenAPI DPCI objects. + for pci_dev in pci_devs: + dpci_uuid = pci_dev.get('uuid') + ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], + pci_dev['bus'], + pci_dev['slot'], + pci_dev['func']) + if ppci_uuid is None: + continue + dpci_record = { + 'VM': self['uuid'], + 'PPCI': ppci_uuid, + 'hotplug_slot': pci_dev.get('vslot', 0) + } + XendDPCI(dpci_uuid, dpci_record) target['devices'][pci_devs_uuid] = (dev_type, {'devs': pci_devs, @@ -1253,6 +1254,30 @@ class XendConfig(dict): log.debug("XendConfig: reading device: %s" % pci_devs) return pci_devs_uuid + + if dev_type == 'vscsi': + vscsi_devs_uuid = sxp.child_value(config, 'uuid', + uuid.createString()) + vscsi_dict = self.vscsi_convert_sxp_to_dict(config) + vscsi_devs = vscsi_dict['devs'] + + # create XenAPI DSCSI objects. + for vscsi_dev in vscsi_devs: + dscsi_uuid = vscsi_dev.get('uuid') + pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev']) + if pscsi_uuid is None: + continue + dscsi_record = { + 'VM': self['uuid'], + 'PSCSI': pscsi_uuid, + 'virtual_HCTL': vscsi_dev.get('v-dev') + } + XendDSCSI(dscsi_uuid, dscsi_record) + + target['devices'][vscsi_devs_uuid] = \ + (dev_type, {'devs': vscsi_devs, 'uuid': vscsi_devs_uuid} ) + log.debug("XendConfig: reading device: %s" % vscsi_devs) + return vscsi_devs_uuid for opt_val in config[1:]: try: @@ -1559,6 +1584,86 @@ class XendConfig(dict): return dev_config + def vscsi_convert_sxp_to_dict(self, dev_sxp): + """Convert vscsi device sxp to dict + @param dev_sxp: device configuration + @type dev_sxp: SXP object (parsed config) + @return: dev_config + @rtype: dictionary + """ + # Parsing the device SXP's. In most cases, the SXP looks + # like this: + # + # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]] + # + # However, for SCSI devices it looks like this: + # + # [device, + # [vscsi, + # [dev, + # [devid, 0], [p-devname, sdb], [p-dev, 1:0:0:1], + # [v-dev, 0:0:0:0], [state, Initialising] + # ], + # [dev, + # [devid, 0], [p-devname, sdc], [p-dev, 1:0:0:2], + # [v-dev, 0:0:0:1], [satet, Initialising] + # ] + # ], + # [vscsi, + # [dev, + # [devid, 1], [p-devname, sdg], [p-dev, 2:0:0:0], + # [v-dev, 1:0:0:0], [state, Initialising] + # ], + # [dev, + # [devid, 1], [p-devname, sdh], [p-dev, 2:0:0:1], + # [v-dev, 1:0:0:1], [satet, Initialising] + # ] + # ] + # ] + # + # It seems the reasoning for this difference is because + # vscsiif.py needs all the SCSI device configurations with + # same host number at the same time when creating the devices. + + # For SCSI device hotplug support, the SXP of SCSI devices is + # extendend like this: + # + # [device, + # [vscsi, + # [dev, + # [devid, 0], [p-devname, sdd], [p-dev, 1:0:0:3], + # [v-dev, 0:0:0:2], [state, Initialising] + # ] + # ] + # ] + # + # state 'Initialising' indicates that the device is being attached, + # while state 'Closing' indicates that the device is being detached. + # + # The Dict looks like this: + # + # { devs: [ {devid: 0, p-devname: sdd, p-dev: 1:0:0:3, + # v-dev: 0:0:0:2, state: Initialising} ] } + + dev_config = {} + + vscsi_devs = [] + for vscsi_dev in sxp.children(dev_sxp, 'dev'): + vscsi_dev_info = {} + for opt_val in vscsi_dev[1:]: + try: + opt, val = opt_val + vscsi_dev_info[opt] = val + except TypeError: + pass + # append uuid for each vscsi device. + vscsi_uuid = vscsi_dev_info.get('uuid', uuid.createString()) + vscsi_dev_info['uuid'] = vscsi_uuid + vscsi_devs.append(vscsi_dev_info) + dev_config['devs'] = vscsi_devs + + return dev_config + def console_add(self, protocol, location, other_config = {}): dev_uuid = uuid.createString() if protocol == 'vt100': @@ -1632,7 +1737,7 @@ class XendConfig(dict): dev_type, dev_info = self['devices'][dev_uuid] - if dev_type == 'pci' or dev_type == 'vscsi': # Special case for pci + if dev_type == 'pci': # Special case for pci pci_dict = self.pci_convert_sxp_to_dict(config) pci_devs = pci_dict['devs'] @@ -1640,26 +1745,50 @@ class XendConfig(dict): for dpci_uuid in XendDPCI.get_by_VM(self['uuid']): XendAPIStore.deregister(dpci_uuid, "DPCI") - if dev_type != 'vscsi': - # create XenAPI DPCI objects. - for pci_dev in pci_devs: - dpci_uuid = pci_dev.get('uuid') - ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], - pci_dev['bus'], - pci_dev['slot'], - pci_dev['func']) - if ppci_uuid is None: - continue - dpci_record = { - 'VM': self['uuid'], - 'PPCI': ppci_uuid, - 'hotplug_slot': pci_dev.get('vslot', 0) - } - XendDPCI(dpci_uuid, dpci_record) + # create XenAPI DPCI objects. + for pci_dev in pci_devs: + dpci_uuid = pci_dev.get('uuid') + ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], + pci_dev['bus'], + pci_dev['slot'], + pci_dev['func']) + if ppci_uuid is None: + continue + dpci_record = { + 'VM': self['uuid'], + 'PPCI': ppci_uuid, + 'hotplug_slot': pci_dev.get('vslot', 0) + } + XendDPCI(dpci_uuid, dpci_record) self['devices'][dev_uuid] = (dev_type, {'devs': pci_devs, 'uuid': dev_uuid}) + return True + + if dev_type == 'vscsi': # Special case for vscsi + vscsi_dict = self.vscsi_convert_sxp_to_dict(config) + vscsi_devs = vscsi_dict['devs'] + + # destroy existing XenAPI DSCSI objects + for dscsi_uuid in XendDSCSI.get_by_VM(self['uuid']): + XendAPIStore.deregister(dscsi_uuid, "DSCSI") + + # create XenAPI DSCSI objects. + for vscsi_dev in vscsi_devs: + dscsi_uuid = vscsi_dev.get('uuid') + pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev']) + if pscsi_uuid is None: + continue + dscsi_record = { + 'VM': self['uuid'], + 'PSCSI': pscsi_uuid, + 'virtual_HCTL': vscsi_dev.get('v-dev') + } + XendDSCSI(dscsi_uuid, dscsi_record) + + self['devices'][dev_uuid] = \ + (dev_type, {'devs': vscsi_devs, 'uuid': dev_uuid} ) return True for opt_val in config[1:]: diff -r 22c89412fc8c tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Wed Oct 15 15:58:09 2008 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Oct 16 11:56:34 2008 +0900 @@ -55,9 +55,11 @@ from xen.xend.XendAPIConstants import * from xen.xend.XendVMMetrics import XendVMMetrics +from xen.xend import XendAPIStore from xen.xend.XendPPCI import XendPPCI from xen.xend.XendDPCI import XendDPCI -from xen.xend import XendAPIStore +from xen.xend.XendPSCSI import XendPSCSI +from xen.xend.XendDSCSI import XendDSCSI MIGRATE_TIMEOUT = 30.0 BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp' @@ -663,6 +665,9 @@ class XendDomainInfo: if dev_type == 'pci': for dev in dev_config_dict['devs']: XendAPIStore.deregister(dev['uuid'], 'DPCI') + if dev_type == 'vscsi': + for dev in dev_config_dict['devs']: + XendAPIStore.deregister(dev['uuid'], 'DSCSI') elif dev_type == 'tap': self.info['vbd_refs'].remove(dev_uuid) else: @@ -786,12 +791,11 @@ class XendDomainInfo: if dev_class != 'vscsi': return False - dev_config = self.info.pci_convert_sxp_to_dict(dev_sxp) + dev_config = self.info.vscsi_convert_sxp_to_dict(dev_sxp) dev = dev_config['devs'][0] - req_devid = sxp.child_value(dev_sxp, 'devid') - req_devid = int(req_devid) + req_devid = int(dev['devid']) existing_dev_info = self._getDeviceInfo_vscsi(req_devid, dev['v-dev']) - state = sxp.child_value(dev_sxp, 'state') + state = dev['state'] if state == 'Initialising': # new create @@ -3237,6 +3241,9 @@ class XendDomainInfo: def get_dpcis(self): return XendDPCI.get_by_VM(self.info.get('uuid')) + def get_dscsis(self): + return XendDSCSI.get_by_VM(self.info.get('uuid')) + def create_vbd(self, xenapi_vbd, vdi_image_path): """Create a VBD using a VDI from XendStorageRepository. @@ -3416,6 +3423,60 @@ class XendDomainInfo: raise XendError('Failed to create device') return dpci_uuid + + def create_dscsi(self, xenapi_dscsi): + """Create scsi device from the passed struct in Xen API format. + + @param xenapi_dscsi: DSCSI struct from Xen API + @rtype: string + @return: UUID + """ + + dscsi_uuid = uuid.createString() + + # Convert xenapi to sxp + pscsi = XendAPIStore.get(xenapi_dscsi.get('PSCSI'), 'PSCSI') + devid = int(xenapi_dscsi.get('virtual_HCTL').split(':')[0]) + target_vscsi_sxp = \ + ['vscsi', + ['dev', + ['devid', devid], + ['p-devname', pscsi.get_dev_name()], + ['p-dev', pscsi.get_physical_HCTL()], + ['v-dev', xenapi_dscsi.get('virtual_HCTL')], + ['state', 'Initialising'], + ['uuid', dscsi_uuid] + ] + ] + + if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: + + cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid, None) + + if cur_vscsi_sxp is None: + dev_uuid = self.info.device_add('vscsi', cfg_sxp = target_vscsi_sxp) + if not dev_uuid: + raise XendError('Failed to create device') + + else: + new_vscsi_sxp = ['vscsi'] + for existing_dev in sxp.children(cur_vscsi_sxp, 'dev'): + new_vscsi_sxp.append(existing_dev) + new_vscsi_sxp.append(sxp.child0(target_vscsi_sxp, 'dev')) + + dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid') + self.info.device_update(dev_uuid, new_vscsi_sxp) + + xen.xend.XendDomain.instance().managed_config_save(self) + + else: + try: + self.device_configure(target_vscsi_sxp) + + except Exception, exn: + raise XendError('Failed to create device') + + return dscsi_uuid def destroy_device_by_uuid(self, dev_type, dev_uuid): @@ -3484,6 +3545,41 @@ class XendDomainInfo: except Exception, exn: raise XendError('Failed to destroy device') + def destroy_dscsi(self, dev_uuid): + dscsi = XendAPIStore.get(dev_uuid, 'DSCSI') + devid = dscsi.get_virtual_host() + vHCTL = dscsi.get_virtual_HCTL() + cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid, None) + dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid') + + target_dev = None + new_vscsi_sxp = ['vscsi'] + for dev in sxp.children(cur_vscsi_sxp, 'dev'): + if vHCTL == sxp.child_value(dev, 'v-dev'): + target_dev = dev + else: + new_vscsi_sxp.append(dev) + + if target_dev is None: + raise XendError('Failed to destroy device') + + target_dev.append(['state', 'Closing']) + target_vscsi_sxp = ['vscsi', target_dev] + + if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: + + self.info.device_update(dev_uuid, new_vscsi_sxp) + if len(sxp.children(new_vscsi_sxp, 'dev')) == 0: + del self.info['devices'][dev_uuid] + xen.xend.XendDomain.instance().managed_config_save(self) + + else: + try: + self.device_configure(target_vscsi_sxp) + + except Exception, exn: + raise XendError('Failed to destroy device') + def destroy_xapi_instances(self): """Destroy Xen-API instances stored in XendAPIStore. """ @@ -3508,6 +3604,10 @@ class XendDomainInfo: for dpci_uuid in XendDPCI.get_by_VM(self.info.get('uuid')): XendAPIStore.deregister(dpci_uuid, "DPCI") + # Destroy DSCSI instances. + for dscsi_uuid in XendDSCSI.get_by_VM(self.info.get('uuid')): + XendAPIStore.deregister(dscsi_uuid, "DSCSI") + def has_device(self, dev_class, dev_uuid): return (dev_uuid in self.info['%s_refs' % dev_class.lower()]) diff -r 22c89412fc8c tools/python/xen/xend/XendNode.py --- a/tools/python/xen/xend/XendNode.py Wed Oct 15 15:58:09 2008 +0100 +++ b/tools/python/xen/xend/XendNode.py Thu Oct 16 11:57:55 2008 +0900 @@ -22,6 +22,7 @@ import xen.lowlevel.xc from xen.util import Brctl from xen.util import pci as PciUtil +from xen.util import vscsi_util from xen.xend import XendAPIStore from xen.xend import osdep @@ -38,7 +39,8 @@ from XendStateStore import XendStateStor from XendStateStore import XendStateStore from XendMonitor import XendMonitor from XendPPCI import XendPPCI - +from XendPSCSI import XendPSCSI + class XendNode: """XendNode - Represents a Domain 0 Host.""" @@ -53,6 +55,7 @@ class XendNode: * network * Storage Repository * PPCI + * PSCSI """ self.xc = xen.lowlevel.xc.xc() @@ -269,6 +272,24 @@ class XendNode: XendPPCI(ppci_uuid, ppci_record) + # Initialise PSCSIs + saved_pscsis = self.state_store.load_state('pscsi') + saved_pscsi_table = {} + if saved_pscsis: + for pscsi_uuid, pscsi_record in saved_pscsis.items(): + try: + saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid + except KeyError: + pass + + 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) + + ## def network_destroy(self, net_uuid): ## del self.networks[net_uuid] ## self.save_networks() @@ -317,6 +338,15 @@ class XendNode: def get_ppci_by_uuid(self, ppci_uuid): if ppci_uuid in self.get_PPCI_refs(): return ppci_uuid + return None + + + def get_PSCSI_refs(self): + return XendPSCSI.get_all() + + def get_pscsi_by_uuid(self, pscsi_uuid): + if pscsi_uuid in self.get_PSCSI_refs(): + return pscsi_uuid return None @@ -333,6 +363,7 @@ class XendNode: self.save_PBDs() self.save_SRs() self.save_PPCIs() + self.save_PSCSIs() def save_PIFs(self): pif_records = dict([(pif_uuid, XendAPIStore.get( @@ -362,6 +393,12 @@ class XendNode: ppci_uuid, "PPCI").get_record()) for ppci_uuid in XendPPCI.get_all()]) self.state_store.save_state('ppci', ppci_records) + + def save_PSCSIs(self): + pscsi_records = dict([(pscsi_uuid, XendAPIStore.get( + pscsi_uuid, "PSCSI").get_record()) + for pscsi_uuid in XendPSCSI.get_all()]) + self.state_store.save_state('pscsi', pscsi_records) def shutdown(self): return 0 diff -r 22c89412fc8c tools/python/xen/xend/server/vscsiif.py --- a/tools/python/xen/xend/server/vscsiif.py Wed Oct 15 15:58:09 2008 +0100 +++ b/tools/python/xen/xend/server/vscsiif.py Thu Oct 16 11:57:51 2008 +0900 @@ -125,10 +125,10 @@ class VSCSIController(DevController): state = self.readBackend(devid, devpath + '/state') localdevid = self.readBackend(devid, devpath + '/devid') dev_dict = {'p-dev': pdev, - 'p-devname': pdevname, - 'v-dev': pdevname, - 'state': state, - 'devid': localdevid } + 'p-devname': pdevname, + 'v-dev': vdev, + 'state': state, + 'devid': localdevid } vscsi_devs.append(dev_dict) config['devs'] = vscsi_devs @@ -168,17 +168,17 @@ class VSCSIController(DevController): (devid, back, front) = self.getDeviceDetails(config) devid = int(devid) vscsi_config = config['devs'][0] - states = config.get('states', []) + state = vscsi_config.get('state', '') driver_state = self.readBackend(devid, 'state') if str(xenbusState['Connected']) != driver_state: raise VmError("Driver status is not connected") uuid = self.readBackend(devid, 'uuid') - if states[0] == 'Initialising': + if state == 'Initialising': back['uuid'] = uuid self.writeBackend(devid, back) - elif states[0] == 'Closing': + elif state == 'Closing': found = False devs = self.readBackendList(devid, "vscsi-devs") vscsipath = "vscsi-devs/" @@ -197,8 +197,8 @@ class VSCSIController(DevController): raise VmError("Device %s not connected" % vdev) else: - raise XendError('Error configuring device invalid state %s' - % state) + raise XendError("Error configuring device invalid " + "state '%s'" % state) self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring'])) return self.readBackend(devid, 'uuid') diff -r 22c89412fc8c tools/python/xen/xend/XendDSCSI.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/XendDSCSI.py Thu Oct 16 13:25:18 2008 +0900 @@ -0,0 +1,174 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright FUJITSU LIMITED 2008 +# Masaki Kanno +#============================================================================ + +from xen.xend.XendBase import XendBase +from xen.xend.XendPSCSI import XendPSCSI +from xen.xend import XendAPIStore +from xen.xend import sxp +from xen.xend import uuid as genuuid + +import XendDomain, XendNode + +from XendError import * +from XendTask import XendTask +from XendLogging import log + +class XendDSCSI(XendBase): + """Representation of a half-virtualized SCSI device.""" + + def getClass(self): + return "DSCSI" + + def getAttrRO(self): + attrRO = ['VM', + 'PSCSI', + 'virtual_host', + 'virtual_channel', + 'virtual_target', + 'virtual_lun', + 'virtual_HCTL', + 'runtime_properties'] + return XendBase.getAttrRO() + attrRO + + def getAttrRW(self): + attrRW = [] + return XendBase.getAttrRW() + attrRW + + def getAttrInst(self): + attrInst = ['VM', + 'PSCSI', + 'virtual_HCTL'] + 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_struct): + + # Check if VM is valid + xendom = XendDomain.instance() + if not xendom.is_valid_vm(dscsi_struct['VM']): + raise InvalidHandleError('VM', dscsi_struct['VM']) + dom = xendom.get_vm_by_uuid(dscsi_struct['VM']) + + # Check if PSCSI is valid + xennode = XendNode.instance() + pscsi_uuid = xennode.get_pscsi_by_uuid(dscsi_struct['PSCSI']) + if not pscsi_uuid: + raise InvalidHandleError('PSCSI', dscsi_struct['PSCSI']) + + # Assign PSCSI to VM + try: + dscsi_ref = XendTask.log_progress(0, 100, \ + dom.create_dscsi, \ + dscsi_struct) + except XendError, e: + log.exception("Error in create_dscsi") + raise + + return dscsi_ref + + create = classmethod(create) + + def get_by_VM(cls, VM_ref): + result = [] + for dscsi in XendAPIStore.get_all("DSCSI"): + if dscsi.get_VM() == VM_ref: + result.append(dscsi.get_uuid()) + return result + + get_by_VM = classmethod(get_by_VM) + + def __init__(self, uuid, record): + XendBase.__init__(self, uuid, record) + v_hctl = self.virtual_HCTL.split(':') + self.virtual_host = int(v_hctl[0]) + self.virtual_channel = int(v_hctl[1]) + self.virtual_target = int(v_hctl[2]) + self.virtual_lun = int(v_hctl[3]) + + def get_VM(self): + return self.VM + + def get_PSCSI(self): + return self.PSCSI + + def get_virtual_host(self): + return self.virtual_host + + def get_virtual_channel(self): + return self.virtual_channel + + def get_virtual_target(self): + return self.virtual_target + + def get_virtual_lun(self): + return self.virtual_lun + + def get_virtual_HCTL(self): + return self.virtual_HCTL + + def get_runtime_properties(self): + xendom = XendDomain.instance() + dominfo = xendom.get_vm_by_uuid(self.VM) + + try: + device_dict = {} + for device_sxp in dominfo.getDeviceSxprs('vscsi'): + target_dev = None + for dev in device_sxp[1][0][1]: + vdev = sxp.child_value(dev, 'v-dev') + if vdev == self.virtual_HCTL: + target_dev = dev + break + if target_dev is None: + continue + + dev_dict = {} + for info in target_dev[1:]: + dev_dict[info[0]] = info[1] + device_dict['dev'] = dev_dict + for info in device_sxp[1][1:]: + device_dict[info[0]] = info[1] + + return device_dict + except Exception, exn: + log.exception(exn) + return {} + + 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, \ + self.get_uuid()) + diff -r 22c89412fc8c tools/python/xen/xend/XendPSCSI.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/XendPSCSI.py Thu Oct 16 11:59:02 2008 +0900 @@ -0,0 +1,143 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright FUJITSU LIMITED 2008 +# Masaki Kanno +#============================================================================ + +from xen.xend.XendBase import XendBase +from xen.xend.XendBase import XendAPIStore +from xen.xend import uuid as genuuid + +class XendPSCSI(XendBase): + """Representation of a physical SCSI device.""" + + def getClass(self): + return "PSCSI" + + def getAttrRO(self): + attrRO = ['host', + 'physical_host', + 'physical_channel', + 'physical_target', + 'physical_lun', + 'physical_HCTL', + 'vendor_name', + 'model', + 'type_id', + 'type', + 'dev_name', + 'sg_name', + 'revision', + 'scsi_id', + 'scsi_level'] + 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_HCTL(self, physical_HCTL): + for pscsi in XendAPIStore.get_all("PSCSI"): + if pscsi.get_physical_HCTL() == physical_HCTL: + return pscsi.get_uuid() + return None + + get_by_HCTL = classmethod(get_by_HCTL) + + def __init__(self, uuid, record): + self.physical_HCTL = record['physical_HCTL'] + self.vendor_name = record['vendor_name'] + self.model = record['model'] + self.type_id = record['type_id'] + self.type = record['type'] + self.dev_name = record['dev_name'] + self.sg_name = record['sg_name'] + self.revision = record['revision'] + self.scsi_id = record['scsi_id'] + self.scsi_level = record['scsi_level'] + + p_hctl = self.physical_HCTL.split(':') + self.physical_host = int(p_hctl[0]) + self.physical_channel = int(p_hctl[1]) + self.physical_target = int(p_hctl[2]) + self.physical_lun = int(p_hctl[3]) + + 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_physical_channel(self): + return self.physical_channel + + def get_physical_target(self): + return self.physical_target + + def get_physical_lun(self): + return self.physical_lun + + def get_physical_HCTL(self): + return self.physical_HCTL + + def get_vendor_name(self): + return self.vendor_name + + def get_model(self): + return self.model + + def get_type_id(self): + return self.type_id + + def get_type(self): + return self.type + + def get_dev_name(self): + return self.dev_name + + def get_sg_name(self): + return self.sg_name + + def get_revision(self): + return self.revision + + def get_scsi_id(self): + return self.scsi_id + + def get_scsi_level(self): + return self.scsi_level +