ia64/xen-unstable
changeset 18642:9404bcb6d32e
Enhance XenAPI for pvSCSI
Basically, I implemented XenAPI for pvSCSI according to the patch of
XenAPI document which I sent before. However, I renamed the class
name of virtual SCSI devices to "DSCSI".
Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
Basically, I implemented XenAPI for pvSCSI according to the patch of
XenAPI document which I sent before. However, I renamed the class
name of virtual SCSI devices to "DSCSI".
Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Thu Oct 16 09:50:18 2008 +0100 (2008-10-16) |
parents | 22c89412fc8c |
children | 819ab49deef1 |
files | tools/python/xen/util/pci.py tools/python/xen/util/utils.py tools/python/xen/util/vscsi_util.py tools/python/xen/xend/XendAPI.py tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDSCSI.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/XendNode.py tools/python/xen/xend/XendPSCSI.py tools/python/xen/xend/server/vscsiif.py tools/python/xen/xm/create.dtd tools/python/xen/xm/main.py tools/python/xen/xm/xenapi_create.py |
line diff
1.1 --- a/tools/python/xen/util/pci.py Wed Oct 15 15:58:09 2008 +0100 1.2 +++ b/tools/python/xen/util/pci.py Thu Oct 16 09:50:18 2008 +0100 1.3 @@ -12,8 +12,8 @@ import re 1.4 import types 1.5 import struct 1.6 import time 1.7 +from xen.util import utils 1.8 1.9 -PROC_MNT_PATH = '/proc/mounts' 1.10 PROC_PCI_PATH = '/proc/bus/pci/devices' 1.11 PROC_PCI_NUM_RESOURCES = 7 1.12 1.13 @@ -97,9 +97,6 @@ MSIX_SIZE_MASK = 0x7ff 1.14 # Global variable to store information from lspci 1.15 lspci_info = None 1.16 1.17 -# Global variable to store the sysfs mount point 1.18 -sysfs_mnt_point = None 1.19 - 1.20 #Calculate PAGE_SHIFT: number of bits to shift an address to get the page number 1.21 PAGE_SIZE = resource.getpagesize() 1.22 PAGE_SHIFT = 0 1.23 @@ -141,20 +138,8 @@ def parse_pci_name(pci_name_string): 1.24 1.25 1.26 def find_sysfs_mnt(): 1.27 - global sysfs_mnt_point 1.28 - if not sysfs_mnt_point is None: 1.29 - return sysfs_mnt_point 1.30 - 1.31 try: 1.32 - mounts_file = open(PROC_MNT_PATH,'r') 1.33 - 1.34 - for line in mounts_file: 1.35 - sline = line.split() 1.36 - if len(sline)<3: 1.37 - continue 1.38 - if sline[2]=='sysfs': 1.39 - sysfs_mnt_point= sline[1] 1.40 - return sysfs_mnt_point 1.41 + return utils.find_sysfs_mount() 1.42 except IOError, (errno, strerr): 1.43 raise PciDeviceParseError(('Failed to locate sysfs mount: %s: %s (%d)'% 1.44 (PROC_PCI_PATH, strerr, errno)))
2.1 --- a/tools/python/xen/util/utils.py Wed Oct 15 15:58:09 2008 +0100 2.2 +++ b/tools/python/xen/util/utils.py Thu Oct 16 09:50:18 2008 +0100 2.3 @@ -48,3 +48,29 @@ def daemonize(prog, args, stdin_tmpfile= 2.4 os.waitpid(pid, 0) 2.5 return daemon_pid 2.6 2.7 +# Global variable to store the sysfs mount point 2.8 +sysfs_mount_point = None 2.9 + 2.10 +PROC_MOUNTS_PATH = '/proc/mounts' 2.11 + 2.12 +def find_sysfs_mount(): 2.13 + global sysfs_mount_point 2.14 + 2.15 + if not sysfs_mount_point is None: 2.16 + return sysfs_mount_point 2.17 + 2.18 + try: 2.19 + mounts_file = open(PROC_MOUNTS_PATH, 'r') 2.20 + 2.21 + for line in mounts_file: 2.22 + sline = line.split() 2.23 + if len(sline) < 3: 2.24 + continue 2.25 + if sline[2] == 'sysfs': 2.26 + sysfs_mount_point= sline[1] 2.27 + return sysfs_mount_point 2.28 + except IOError, (errno, strerr): 2.29 + raise 2.30 + 2.31 + return None 2.32 +
3.1 --- a/tools/python/xen/util/vscsi_util.py Wed Oct 15 15:58:09 2008 +0100 3.2 +++ b/tools/python/xen/util/vscsi_util.py Thu Oct 16 09:50:18 2008 +0100 3.3 @@ -23,9 +23,18 @@ 3.4 """Support for VSCSI Devices. 3.5 """ 3.6 import os 3.7 +import os.path 3.8 import sys 3.9 import re 3.10 import string 3.11 +from xen.util import utils 3.12 + 3.13 +SYSFS_SCSI_PATH = "/bus/scsi/devices" 3.14 +SYSFS_SCSI_DEV_VENDOR_PATH = '/vendor' 3.15 +SYSFS_SCSI_DEV_MODEL_PATH = '/model' 3.16 +SYSFS_SCSI_DEV_TYPEID_PATH = '/type' 3.17 +SYSFS_SCSI_DEV_REVISION_PATH = '/rev' 3.18 +SYSFS_SCSI_DEV_SCSILEVEL_PATH = '/scsi_level' 3.19 3.20 def _vscsi_hctl_block(name, scsi_devices): 3.21 """ block-device name is convert into hctl. (e.g., '/dev/sda', 3.22 @@ -84,10 +93,10 @@ def _vscsi_block_scsiid_to_hctl(phyname, 3.23 def vscsi_get_scsidevices(): 3.24 """ get all scsi devices""" 3.25 3.26 - SERCH_SCSI_PATH = "/sys/bus/scsi/devices" 3.27 devices = [] 3.28 + sysfs_mnt = utils.find_sysfs_mount() 3.29 3.30 - for dirpath, dirnames, files in os.walk(SERCH_SCSI_PATH): 3.31 + for dirpath, dirnames, files in os.walk(sysfs_mnt + SYSFS_SCSI_PATH): 3.32 for hctl in dirnames: 3.33 paths = os.path.join(dirpath, hctl) 3.34 block = "-" 3.35 @@ -131,3 +140,101 @@ def vscsi_search_hctl_and_block(device): 3.36 3.37 return (hctl, block) 3.38 3.39 + 3.40 +def get_scsi_vendor(pHCTL): 3.41 + try: 3.42 + sysfs_mnt = utils.find_sysfs_mount() 3.43 + sysfs_scsi_dev_path = \ 3.44 + os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) 3.45 + scsi_vendor = \ 3.46 + os.popen('cat ' + sysfs_scsi_dev_path + \ 3.47 + SYSFS_SCSI_DEV_VENDOR_PATH).read() 3.48 + return scsi_vendor.splitlines()[0] 3.49 + except: 3.50 + return None 3.51 + 3.52 +def get_scsi_model(pHCTL): 3.53 + try: 3.54 + sysfs_mnt = utils.find_sysfs_mount() 3.55 + sysfs_scsi_dev_path = \ 3.56 + os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) 3.57 + scsi_model = \ 3.58 + os.popen('cat ' + sysfs_scsi_dev_path + \ 3.59 + SYSFS_SCSI_DEV_MODEL_PATH).read() 3.60 + return scsi_model.splitlines()[0] 3.61 + except: 3.62 + return None 3.63 + 3.64 +def get_scsi_typeid(pHCTL): 3.65 + try: 3.66 + sysfs_mnt = utils.find_sysfs_mount() 3.67 + sysfs_scsi_dev_path = \ 3.68 + os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) 3.69 + scsi_typeid = \ 3.70 + os.popen('cat ' + sysfs_scsi_dev_path + \ 3.71 + SYSFS_SCSI_DEV_TYPEID_PATH).read() 3.72 + return int(scsi_typeid.splitlines()[0]) 3.73 + except: 3.74 + return None 3.75 + 3.76 +def get_scsi_revision(pHCTL): 3.77 + try: 3.78 + sysfs_mnt = utils.find_sysfs_mount() 3.79 + sysfs_scsi_dev_path = \ 3.80 + os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) 3.81 + scsi_revision = \ 3.82 + os.popen('cat ' + sysfs_scsi_dev_path + \ 3.83 + SYSFS_SCSI_DEV_REVISION_PATH).read() 3.84 + return scsi_revision.splitlines()[0] 3.85 + except: 3.86 + return None 3.87 + 3.88 +def get_scsi_scsilevel(pHCTL): 3.89 + try: 3.90 + sysfs_mnt = utils.find_sysfs_mount() 3.91 + sysfs_scsi_dev_path = \ 3.92 + os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) 3.93 + scsi_scsilevel = \ 3.94 + os.popen('cat ' + sysfs_scsi_dev_path + \ 3.95 + SYSFS_SCSI_DEV_SCSILEVEL_PATH).read() 3.96 + return int(scsi_scsilevel.splitlines()[0]) 3.97 + except: 3.98 + return None 3.99 + 3.100 +def get_all_scsi_devices(): 3.101 + 3.102 + scsi_devs = [] 3.103 + 3.104 + for scsi_info in vscsi_get_scsidevices(): 3.105 + scsi_dev = { 3.106 + 'physical_HCTL': scsi_info[0], 3.107 + 'dev_name': None, 3.108 + 'sg_name': scsi_info[2], 3.109 + 'scsi_id': None 3.110 + } 3.111 + if scsi_info[1] != '-': 3.112 + scsi_dev['dev_name'] = scsi_info[1] 3.113 + if scsi_info[3] != '-': 3.114 + scsi_dev['scsi_id'] = scsi_info[3] 3.115 + 3.116 + scsi_dev['vendor_name'] = \ 3.117 + get_scsi_vendor(scsi_dev['physical_HCTL']) 3.118 + scsi_dev['model'] = \ 3.119 + get_scsi_model(scsi_dev['physical_HCTL']) 3.120 + scsi_dev['type_id'] = \ 3.121 + get_scsi_typeid(scsi_dev['physical_HCTL']) 3.122 + scsi_dev['revision'] = \ 3.123 + get_scsi_revision(scsi_dev['physical_HCTL']) 3.124 + scsi_dev['scsi_level'] = \ 3.125 + get_scsi_scsilevel(scsi_dev['physical_HCTL']) 3.126 + 3.127 + try: 3.128 + lsscsi_info = os.popen('lsscsi ' + scsi_dev['physical_HCTL']).read().split() 3.129 + scsi_dev['type'] = lsscsi_info[1] 3.130 + except: 3.131 + scsi_dev['type'] = None 3.132 + 3.133 + scsi_devs.append(scsi_dev) 3.134 + 3.135 + return scsi_devs 3.136 +
4.1 --- a/tools/python/xen/xend/XendAPI.py Wed Oct 15 15:58:09 2008 +0100 4.2 +++ b/tools/python/xen/xend/XendAPI.py Thu Oct 16 09:50:18 2008 +0100 4.3 @@ -42,6 +42,8 @@ from XendPIF import XendPIF 4.4 from XendPBD import XendPBD 4.5 from XendPPCI import XendPPCI 4.6 from XendDPCI import XendDPCI 4.7 +from XendPSCSI import XendPSCSI 4.8 +from XendDSCSI import XendDSCSI 4.9 from XendXSPolicy import XendXSPolicy, XendACMPolicy 4.10 4.11 from XendAPIConstants import * 4.12 @@ -480,7 +482,9 @@ classes = { 4.13 'PBD' : valid_object("PBD"), 4.14 'PIF_metrics' : valid_object("PIF_metrics"), 4.15 'PPCI' : valid_object("PPCI"), 4.16 - 'DPCI' : valid_object("DPCI") 4.17 + 'DPCI' : valid_object("DPCI"), 4.18 + 'PSCSI' : valid_object("PSCSI"), 4.19 + 'DSCSI' : valid_object("DSCSI") 4.20 } 4.21 4.22 autoplug_classes = { 4.23 @@ -491,6 +495,8 @@ autoplug_classes = { 4.24 'PIF_metrics' : XendPIFMetrics, 4.25 'PPCI' : XendPPCI, 4.26 'DPCI' : XendDPCI, 4.27 + 'PSCSI' : XendPSCSI, 4.28 + 'DSCSI' : XendDSCSI, 4.29 'XSPolicy' : XendXSPolicy, 4.30 'ACMPolicy' : XendACMPolicy, 4.31 } 4.32 @@ -881,6 +887,7 @@ class XendAPI(object): 4.33 'PBDs', 4.34 'PIFs', 4.35 'PPCIs', 4.36 + 'PSCSIs', 4.37 'host_CPUs', 4.38 'cpu_configuration', 4.39 'metrics', 4.40 @@ -961,6 +968,8 @@ class XendAPI(object): 4.41 return xen_api_success(XendNode.instance().get_PIF_refs()) 4.42 def host_get_PPCIs(self, session, ref): 4.43 return xen_api_success(XendNode.instance().get_PPCI_refs()) 4.44 + def host_get_PSCSIs(self, session, ref): 4.45 + return xen_api_success(XendNode.instance().get_PSCSI_refs()) 4.46 def host_get_host_CPUs(self, session, host_ref): 4.47 return xen_api_success(XendNode.instance().get_host_cpu_refs()) 4.48 def host_get_metrics(self, _, ref): 4.49 @@ -1037,7 +1046,8 @@ class XendAPI(object): 4.50 'logging': {}, 4.51 'PIFs': XendPIF.get_all(), 4.52 'PBDs': XendPBD.get_all(), 4.53 - 'PPCIs': XendPPCI.get_all()} 4.54 + 'PPCIs': XendPPCI.get_all(), 4.55 + 'PSCSIs': XendPSCSI.get_all()} 4.56 return xen_api_success(record) 4.57 4.58 # class methods 4.59 @@ -1158,6 +1168,7 @@ class XendAPI(object): 4.60 'VBDs', 4.61 'VTPMs', 4.62 'DPCIs', 4.63 + 'DSCSIs', 4.64 'tools_version', 4.65 'domid', 4.66 'is_control_domain', 4.67 @@ -1304,6 +1315,10 @@ class XendAPI(object): 4.68 dom = XendDomain.instance().get_vm_by_uuid(vm_ref) 4.69 return xen_api_success(dom.get_dpcis()) 4.70 4.71 + def VM_get_DSCSIs(self, session, vm_ref): 4.72 + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) 4.73 + return xen_api_success(dom.get_dscsis()) 4.74 + 4.75 def VM_get_tools_version(self, session, vm_ref): 4.76 dom = XendDomain.instance().get_vm_by_uuid(vm_ref) 4.77 return dom.get_tools_version() 4.78 @@ -1684,6 +1699,7 @@ class XendAPI(object): 4.79 'VBDs': xeninfo.get_vbds(), 4.80 'VTPMs': xeninfo.get_vtpms(), 4.81 'DPCIs': xeninfo.get_dpcis(), 4.82 + 'DSCSIs': xeninfo.get_dscsis(), 4.83 'PV_bootloader': xeninfo.info.get('PV_bootloader'), 4.84 'PV_kernel': xeninfo.info.get('PV_kernel'), 4.85 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
5.1 --- a/tools/python/xen/xend/XendConfig.py Wed Oct 15 15:58:09 2008 +0100 5.2 +++ b/tools/python/xen/xend/XendConfig.py Thu Oct 16 09:50:18 2008 +0100 5.3 @@ -26,6 +26,8 @@ from xen.xend import XendOptions 5.4 from xen.xend import XendAPIStore 5.5 from xen.xend.XendPPCI import XendPPCI 5.6 from xen.xend.XendDPCI import XendDPCI 5.7 +from xen.xend.XendPSCSI import XendPSCSI 5.8 +from xen.xend.XendDSCSI import XendDSCSI 5.9 from xen.xend.XendError import VmError 5.10 from xen.xend.XendDevices import XendDevices 5.11 from xen.xend.PrettyPrint import prettyprintstring 5.12 @@ -782,8 +784,8 @@ class XendConfig(dict): 5.13 log.debug('_sxp_to_xapi(%s)' % scrub_password(sxp_cfg)) 5.14 5.15 # _parse_sxp() below will call device_add() and construct devices. 5.16 - # Some devices (currently only pci) may require VM's uuid, so 5.17 - # setup self['uuid'] beforehand. 5.18 + # Some devices may require VM's uuid, so setup self['uuid'] 5.19 + # beforehand. 5.20 self['uuid'] = sxp.child_value(sxp_cfg, 'uuid', uuid.createString()) 5.21 5.22 cfg = self._parse_sxp(sxp_cfg) 5.23 @@ -1222,29 +1224,28 @@ class XendConfig(dict): 5.24 dev_type = sxp.name(config) 5.25 dev_info = {} 5.26 5.27 - if dev_type == 'pci' or dev_type == 'vscsi': 5.28 + if dev_type == 'pci': 5.29 pci_devs_uuid = sxp.child_value(config, 'uuid', 5.30 uuid.createString()) 5.31 5.32 pci_dict = self.pci_convert_sxp_to_dict(config) 5.33 pci_devs = pci_dict['devs'] 5.34 5.35 - if dev_type != 'vscsi': 5.36 - # create XenAPI DPCI objects. 5.37 - for pci_dev in pci_devs: 5.38 - dpci_uuid = pci_dev.get('uuid') 5.39 - ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], 5.40 - pci_dev['bus'], 5.41 - pci_dev['slot'], 5.42 - pci_dev['func']) 5.43 - if ppci_uuid is None: 5.44 - continue 5.45 - dpci_record = { 5.46 - 'VM': self['uuid'], 5.47 - 'PPCI': ppci_uuid, 5.48 - 'hotplug_slot': pci_dev.get('vslot', 0) 5.49 - } 5.50 - XendDPCI(dpci_uuid, dpci_record) 5.51 + # create XenAPI DPCI objects. 5.52 + for pci_dev in pci_devs: 5.53 + dpci_uuid = pci_dev.get('uuid') 5.54 + ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], 5.55 + pci_dev['bus'], 5.56 + pci_dev['slot'], 5.57 + pci_dev['func']) 5.58 + if ppci_uuid is None: 5.59 + continue 5.60 + dpci_record = { 5.61 + 'VM': self['uuid'], 5.62 + 'PPCI': ppci_uuid, 5.63 + 'hotplug_slot': pci_dev.get('vslot', 0) 5.64 + } 5.65 + XendDPCI(dpci_uuid, dpci_record) 5.66 5.67 target['devices'][pci_devs_uuid] = (dev_type, 5.68 {'devs': pci_devs, 5.69 @@ -1254,6 +1255,30 @@ class XendConfig(dict): 5.70 5.71 return pci_devs_uuid 5.72 5.73 + if dev_type == 'vscsi': 5.74 + vscsi_devs_uuid = sxp.child_value(config, 'uuid', 5.75 + uuid.createString()) 5.76 + vscsi_dict = self.vscsi_convert_sxp_to_dict(config) 5.77 + vscsi_devs = vscsi_dict['devs'] 5.78 + 5.79 + # create XenAPI DSCSI objects. 5.80 + for vscsi_dev in vscsi_devs: 5.81 + dscsi_uuid = vscsi_dev.get('uuid') 5.82 + pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev']) 5.83 + if pscsi_uuid is None: 5.84 + continue 5.85 + dscsi_record = { 5.86 + 'VM': self['uuid'], 5.87 + 'PSCSI': pscsi_uuid, 5.88 + 'virtual_HCTL': vscsi_dev.get('v-dev') 5.89 + } 5.90 + XendDSCSI(dscsi_uuid, dscsi_record) 5.91 + 5.92 + target['devices'][vscsi_devs_uuid] = \ 5.93 + (dev_type, {'devs': vscsi_devs, 'uuid': vscsi_devs_uuid} ) 5.94 + log.debug("XendConfig: reading device: %s" % vscsi_devs) 5.95 + return vscsi_devs_uuid 5.96 + 5.97 for opt_val in config[1:]: 5.98 try: 5.99 opt, val = opt_val 5.100 @@ -1559,6 +1584,86 @@ class XendConfig(dict): 5.101 5.102 return dev_config 5.103 5.104 + def vscsi_convert_sxp_to_dict(self, dev_sxp): 5.105 + """Convert vscsi device sxp to dict 5.106 + @param dev_sxp: device configuration 5.107 + @type dev_sxp: SXP object (parsed config) 5.108 + @return: dev_config 5.109 + @rtype: dictionary 5.110 + """ 5.111 + # Parsing the device SXP's. In most cases, the SXP looks 5.112 + # like this: 5.113 + # 5.114 + # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]] 5.115 + # 5.116 + # However, for SCSI devices it looks like this: 5.117 + # 5.118 + # [device, 5.119 + # [vscsi, 5.120 + # [dev, 5.121 + # [devid, 0], [p-devname, sdb], [p-dev, 1:0:0:1], 5.122 + # [v-dev, 0:0:0:0], [state, Initialising] 5.123 + # ], 5.124 + # [dev, 5.125 + # [devid, 0], [p-devname, sdc], [p-dev, 1:0:0:2], 5.126 + # [v-dev, 0:0:0:1], [satet, Initialising] 5.127 + # ] 5.128 + # ], 5.129 + # [vscsi, 5.130 + # [dev, 5.131 + # [devid, 1], [p-devname, sdg], [p-dev, 2:0:0:0], 5.132 + # [v-dev, 1:0:0:0], [state, Initialising] 5.133 + # ], 5.134 + # [dev, 5.135 + # [devid, 1], [p-devname, sdh], [p-dev, 2:0:0:1], 5.136 + # [v-dev, 1:0:0:1], [satet, Initialising] 5.137 + # ] 5.138 + # ] 5.139 + # ] 5.140 + # 5.141 + # It seems the reasoning for this difference is because 5.142 + # vscsiif.py needs all the SCSI device configurations with 5.143 + # same host number at the same time when creating the devices. 5.144 + 5.145 + # For SCSI device hotplug support, the SXP of SCSI devices is 5.146 + # extendend like this: 5.147 + # 5.148 + # [device, 5.149 + # [vscsi, 5.150 + # [dev, 5.151 + # [devid, 0], [p-devname, sdd], [p-dev, 1:0:0:3], 5.152 + # [v-dev, 0:0:0:2], [state, Initialising] 5.153 + # ] 5.154 + # ] 5.155 + # ] 5.156 + # 5.157 + # state 'Initialising' indicates that the device is being attached, 5.158 + # while state 'Closing' indicates that the device is being detached. 5.159 + # 5.160 + # The Dict looks like this: 5.161 + # 5.162 + # { devs: [ {devid: 0, p-devname: sdd, p-dev: 1:0:0:3, 5.163 + # v-dev: 0:0:0:2, state: Initialising} ] } 5.164 + 5.165 + dev_config = {} 5.166 + 5.167 + vscsi_devs = [] 5.168 + for vscsi_dev in sxp.children(dev_sxp, 'dev'): 5.169 + vscsi_dev_info = {} 5.170 + for opt_val in vscsi_dev[1:]: 5.171 + try: 5.172 + opt, val = opt_val 5.173 + vscsi_dev_info[opt] = val 5.174 + except TypeError: 5.175 + pass 5.176 + # append uuid for each vscsi device. 5.177 + vscsi_uuid = vscsi_dev_info.get('uuid', uuid.createString()) 5.178 + vscsi_dev_info['uuid'] = vscsi_uuid 5.179 + vscsi_devs.append(vscsi_dev_info) 5.180 + dev_config['devs'] = vscsi_devs 5.181 + 5.182 + return dev_config 5.183 + 5.184 def console_add(self, protocol, location, other_config = {}): 5.185 dev_uuid = uuid.createString() 5.186 if protocol == 'vt100': 5.187 @@ -1632,7 +1737,7 @@ class XendConfig(dict): 5.188 5.189 dev_type, dev_info = self['devices'][dev_uuid] 5.190 5.191 - if dev_type == 'pci' or dev_type == 'vscsi': # Special case for pci 5.192 + if dev_type == 'pci': # Special case for pci 5.193 pci_dict = self.pci_convert_sxp_to_dict(config) 5.194 pci_devs = pci_dict['devs'] 5.195 5.196 @@ -1640,28 +1745,52 @@ class XendConfig(dict): 5.197 for dpci_uuid in XendDPCI.get_by_VM(self['uuid']): 5.198 XendAPIStore.deregister(dpci_uuid, "DPCI") 5.199 5.200 - if dev_type != 'vscsi': 5.201 - # create XenAPI DPCI objects. 5.202 - for pci_dev in pci_devs: 5.203 - dpci_uuid = pci_dev.get('uuid') 5.204 - ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], 5.205 - pci_dev['bus'], 5.206 - pci_dev['slot'], 5.207 - pci_dev['func']) 5.208 - if ppci_uuid is None: 5.209 - continue 5.210 - dpci_record = { 5.211 - 'VM': self['uuid'], 5.212 - 'PPCI': ppci_uuid, 5.213 - 'hotplug_slot': pci_dev.get('vslot', 0) 5.214 - } 5.215 - XendDPCI(dpci_uuid, dpci_record) 5.216 + # create XenAPI DPCI objects. 5.217 + for pci_dev in pci_devs: 5.218 + dpci_uuid = pci_dev.get('uuid') 5.219 + ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], 5.220 + pci_dev['bus'], 5.221 + pci_dev['slot'], 5.222 + pci_dev['func']) 5.223 + if ppci_uuid is None: 5.224 + continue 5.225 + dpci_record = { 5.226 + 'VM': self['uuid'], 5.227 + 'PPCI': ppci_uuid, 5.228 + 'hotplug_slot': pci_dev.get('vslot', 0) 5.229 + } 5.230 + XendDPCI(dpci_uuid, dpci_record) 5.231 5.232 self['devices'][dev_uuid] = (dev_type, 5.233 {'devs': pci_devs, 5.234 'uuid': dev_uuid}) 5.235 return True 5.236 5.237 + if dev_type == 'vscsi': # Special case for vscsi 5.238 + vscsi_dict = self.vscsi_convert_sxp_to_dict(config) 5.239 + vscsi_devs = vscsi_dict['devs'] 5.240 + 5.241 + # destroy existing XenAPI DSCSI objects 5.242 + for dscsi_uuid in XendDSCSI.get_by_VM(self['uuid']): 5.243 + XendAPIStore.deregister(dscsi_uuid, "DSCSI") 5.244 + 5.245 + # create XenAPI DSCSI objects. 5.246 + for vscsi_dev in vscsi_devs: 5.247 + dscsi_uuid = vscsi_dev.get('uuid') 5.248 + pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev']) 5.249 + if pscsi_uuid is None: 5.250 + continue 5.251 + dscsi_record = { 5.252 + 'VM': self['uuid'], 5.253 + 'PSCSI': pscsi_uuid, 5.254 + 'virtual_HCTL': vscsi_dev.get('v-dev') 5.255 + } 5.256 + XendDSCSI(dscsi_uuid, dscsi_record) 5.257 + 5.258 + self['devices'][dev_uuid] = \ 5.259 + (dev_type, {'devs': vscsi_devs, 'uuid': dev_uuid} ) 5.260 + return True 5.261 + 5.262 for opt_val in config[1:]: 5.263 try: 5.264 opt, val = opt_val
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/tools/python/xen/xend/XendDSCSI.py Thu Oct 16 09:50:18 2008 +0100 6.3 @@ -0,0 +1,174 @@ 6.4 +#============================================================================ 6.5 +# This library is free software; you can redistribute it and/or 6.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public 6.7 +# License as published by the Free Software Foundation. 6.8 +# 6.9 +# This library is distributed in the hope that it will be useful, 6.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of 6.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 6.12 +# Lesser General Public License for more details. 6.13 +# 6.14 +# You should have received a copy of the GNU Lesser General Public 6.15 +# License along with this library; if not, write to the Free Software 6.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6.17 +#============================================================================ 6.18 +# Copyright FUJITSU LIMITED 2008 6.19 +# Masaki Kanno <kanno.masaki@jp.fujitsu.com> 6.20 +#============================================================================ 6.21 + 6.22 +from xen.xend.XendBase import XendBase 6.23 +from xen.xend.XendPSCSI import XendPSCSI 6.24 +from xen.xend import XendAPIStore 6.25 +from xen.xend import sxp 6.26 +from xen.xend import uuid as genuuid 6.27 + 6.28 +import XendDomain, XendNode 6.29 + 6.30 +from XendError import * 6.31 +from XendTask import XendTask 6.32 +from XendLogging import log 6.33 + 6.34 +class XendDSCSI(XendBase): 6.35 + """Representation of a half-virtualized SCSI device.""" 6.36 + 6.37 + def getClass(self): 6.38 + return "DSCSI" 6.39 + 6.40 + def getAttrRO(self): 6.41 + attrRO = ['VM', 6.42 + 'PSCSI', 6.43 + 'virtual_host', 6.44 + 'virtual_channel', 6.45 + 'virtual_target', 6.46 + 'virtual_lun', 6.47 + 'virtual_HCTL', 6.48 + 'runtime_properties'] 6.49 + return XendBase.getAttrRO() + attrRO 6.50 + 6.51 + def getAttrRW(self): 6.52 + attrRW = [] 6.53 + return XendBase.getAttrRW() + attrRW 6.54 + 6.55 + def getAttrInst(self): 6.56 + attrInst = ['VM', 6.57 + 'PSCSI', 6.58 + 'virtual_HCTL'] 6.59 + return XendBase.getAttrInst() + attrInst 6.60 + 6.61 + def getMethods(self): 6.62 + methods = ['destroy'] 6.63 + return XendBase.getMethods() + methods 6.64 + 6.65 + def getFuncs(self): 6.66 + funcs = ['create'] 6.67 + return XendBase.getFuncs() + funcs 6.68 + 6.69 + getClass = classmethod(getClass) 6.70 + getAttrRO = classmethod(getAttrRO) 6.71 + getAttrRW = classmethod(getAttrRW) 6.72 + getAttrInst = classmethod(getAttrInst) 6.73 + getMethods = classmethod(getMethods) 6.74 + getFuncs = classmethod(getFuncs) 6.75 + 6.76 + def create(self, dscsi_struct): 6.77 + 6.78 + # Check if VM is valid 6.79 + xendom = XendDomain.instance() 6.80 + if not xendom.is_valid_vm(dscsi_struct['VM']): 6.81 + raise InvalidHandleError('VM', dscsi_struct['VM']) 6.82 + dom = xendom.get_vm_by_uuid(dscsi_struct['VM']) 6.83 + 6.84 + # Check if PSCSI is valid 6.85 + xennode = XendNode.instance() 6.86 + pscsi_uuid = xennode.get_pscsi_by_uuid(dscsi_struct['PSCSI']) 6.87 + if not pscsi_uuid: 6.88 + raise InvalidHandleError('PSCSI', dscsi_struct['PSCSI']) 6.89 + 6.90 + # Assign PSCSI to VM 6.91 + try: 6.92 + dscsi_ref = XendTask.log_progress(0, 100, \ 6.93 + dom.create_dscsi, \ 6.94 + dscsi_struct) 6.95 + except XendError, e: 6.96 + log.exception("Error in create_dscsi") 6.97 + raise 6.98 + 6.99 + return dscsi_ref 6.100 + 6.101 + create = classmethod(create) 6.102 + 6.103 + def get_by_VM(cls, VM_ref): 6.104 + result = [] 6.105 + for dscsi in XendAPIStore.get_all("DSCSI"): 6.106 + if dscsi.get_VM() == VM_ref: 6.107 + result.append(dscsi.get_uuid()) 6.108 + return result 6.109 + 6.110 + get_by_VM = classmethod(get_by_VM) 6.111 + 6.112 + def __init__(self, uuid, record): 6.113 + XendBase.__init__(self, uuid, record) 6.114 + v_hctl = self.virtual_HCTL.split(':') 6.115 + self.virtual_host = int(v_hctl[0]) 6.116 + self.virtual_channel = int(v_hctl[1]) 6.117 + self.virtual_target = int(v_hctl[2]) 6.118 + self.virtual_lun = int(v_hctl[3]) 6.119 + 6.120 + def get_VM(self): 6.121 + return self.VM 6.122 + 6.123 + def get_PSCSI(self): 6.124 + return self.PSCSI 6.125 + 6.126 + def get_virtual_host(self): 6.127 + return self.virtual_host 6.128 + 6.129 + def get_virtual_channel(self): 6.130 + return self.virtual_channel 6.131 + 6.132 + def get_virtual_target(self): 6.133 + return self.virtual_target 6.134 + 6.135 + def get_virtual_lun(self): 6.136 + return self.virtual_lun 6.137 + 6.138 + def get_virtual_HCTL(self): 6.139 + return self.virtual_HCTL 6.140 + 6.141 + def get_runtime_properties(self): 6.142 + xendom = XendDomain.instance() 6.143 + dominfo = xendom.get_vm_by_uuid(self.VM) 6.144 + 6.145 + try: 6.146 + device_dict = {} 6.147 + for device_sxp in dominfo.getDeviceSxprs('vscsi'): 6.148 + target_dev = None 6.149 + for dev in device_sxp[1][0][1]: 6.150 + vdev = sxp.child_value(dev, 'v-dev') 6.151 + if vdev == self.virtual_HCTL: 6.152 + target_dev = dev 6.153 + break 6.154 + if target_dev is None: 6.155 + continue 6.156 + 6.157 + dev_dict = {} 6.158 + for info in target_dev[1:]: 6.159 + dev_dict[info[0]] = info[1] 6.160 + device_dict['dev'] = dev_dict 6.161 + for info in device_sxp[1][1:]: 6.162 + device_dict[info[0]] = info[1] 6.163 + 6.164 + return device_dict 6.165 + except Exception, exn: 6.166 + log.exception(exn) 6.167 + return {} 6.168 + 6.169 + def destroy(self): 6.170 + xendom = XendDomain.instance() 6.171 + dom = xendom.get_vm_by_uuid(self.get_VM()) 6.172 + if not dom: 6.173 + raise InvalidHandleError("VM", self.get_VM()) 6.174 + XendTask.log_progress(0, 100, \ 6.175 + dom.destroy_dscsi, \ 6.176 + self.get_uuid()) 6.177 +
7.1 --- a/tools/python/xen/xend/XendDomainInfo.py Wed Oct 15 15:58:09 2008 +0100 7.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Oct 16 09:50:18 2008 +0100 7.3 @@ -55,9 +55,11 @@ from xen.xend.XendAPIConstants import * 7.4 7.5 from xen.xend.XendVMMetrics import XendVMMetrics 7.6 7.7 +from xen.xend import XendAPIStore 7.8 from xen.xend.XendPPCI import XendPPCI 7.9 from xen.xend.XendDPCI import XendDPCI 7.10 -from xen.xend import XendAPIStore 7.11 +from xen.xend.XendPSCSI import XendPSCSI 7.12 +from xen.xend.XendDSCSI import XendDSCSI 7.13 7.14 MIGRATE_TIMEOUT = 30.0 7.15 BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp' 7.16 @@ -663,6 +665,9 @@ class XendDomainInfo: 7.17 if dev_type == 'pci': 7.18 for dev in dev_config_dict['devs']: 7.19 XendAPIStore.deregister(dev['uuid'], 'DPCI') 7.20 + if dev_type == 'vscsi': 7.21 + for dev in dev_config_dict['devs']: 7.22 + XendAPIStore.deregister(dev['uuid'], 'DSCSI') 7.23 elif dev_type == 'tap': 7.24 self.info['vbd_refs'].remove(dev_uuid) 7.25 else: 7.26 @@ -786,12 +791,11 @@ class XendDomainInfo: 7.27 if dev_class != 'vscsi': 7.28 return False 7.29 7.30 - dev_config = self.info.pci_convert_sxp_to_dict(dev_sxp) 7.31 + dev_config = self.info.vscsi_convert_sxp_to_dict(dev_sxp) 7.32 dev = dev_config['devs'][0] 7.33 - req_devid = sxp.child_value(dev_sxp, 'devid') 7.34 - req_devid = int(req_devid) 7.35 + req_devid = int(dev['devid']) 7.36 existing_dev_info = self._getDeviceInfo_vscsi(req_devid, dev['v-dev']) 7.37 - state = sxp.child_value(dev_sxp, 'state') 7.38 + state = dev['state'] 7.39 7.40 if state == 'Initialising': 7.41 # new create 7.42 @@ -3237,6 +3241,9 @@ class XendDomainInfo: 7.43 def get_dpcis(self): 7.44 return XendDPCI.get_by_VM(self.info.get('uuid')) 7.45 7.46 + def get_dscsis(self): 7.47 + return XendDSCSI.get_by_VM(self.info.get('uuid')) 7.48 + 7.49 def create_vbd(self, xenapi_vbd, vdi_image_path): 7.50 """Create a VBD using a VDI from XendStorageRepository. 7.51 7.52 @@ -3417,6 +3424,60 @@ class XendDomainInfo: 7.53 7.54 return dpci_uuid 7.55 7.56 + def create_dscsi(self, xenapi_dscsi): 7.57 + """Create scsi device from the passed struct in Xen API format. 7.58 + 7.59 + @param xenapi_dscsi: DSCSI struct from Xen API 7.60 + @rtype: string 7.61 + @return: UUID 7.62 + """ 7.63 + 7.64 + dscsi_uuid = uuid.createString() 7.65 + 7.66 + # Convert xenapi to sxp 7.67 + pscsi = XendAPIStore.get(xenapi_dscsi.get('PSCSI'), 'PSCSI') 7.68 + devid = int(xenapi_dscsi.get('virtual_HCTL').split(':')[0]) 7.69 + target_vscsi_sxp = \ 7.70 + ['vscsi', 7.71 + ['dev', 7.72 + ['devid', devid], 7.73 + ['p-devname', pscsi.get_dev_name()], 7.74 + ['p-dev', pscsi.get_physical_HCTL()], 7.75 + ['v-dev', xenapi_dscsi.get('virtual_HCTL')], 7.76 + ['state', 'Initialising'], 7.77 + ['uuid', dscsi_uuid] 7.78 + ] 7.79 + ] 7.80 + 7.81 + if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: 7.82 + 7.83 + cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid, None) 7.84 + 7.85 + if cur_vscsi_sxp is None: 7.86 + dev_uuid = self.info.device_add('vscsi', cfg_sxp = target_vscsi_sxp) 7.87 + if not dev_uuid: 7.88 + raise XendError('Failed to create device') 7.89 + 7.90 + else: 7.91 + new_vscsi_sxp = ['vscsi'] 7.92 + for existing_dev in sxp.children(cur_vscsi_sxp, 'dev'): 7.93 + new_vscsi_sxp.append(existing_dev) 7.94 + new_vscsi_sxp.append(sxp.child0(target_vscsi_sxp, 'dev')) 7.95 + 7.96 + dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid') 7.97 + self.info.device_update(dev_uuid, new_vscsi_sxp) 7.98 + 7.99 + xen.xend.XendDomain.instance().managed_config_save(self) 7.100 + 7.101 + else: 7.102 + try: 7.103 + self.device_configure(target_vscsi_sxp) 7.104 + 7.105 + except Exception, exn: 7.106 + raise XendError('Failed to create device') 7.107 + 7.108 + return dscsi_uuid 7.109 + 7.110 7.111 def destroy_device_by_uuid(self, dev_type, dev_uuid): 7.112 if dev_uuid not in self.info['devices']: 7.113 @@ -3484,6 +3545,41 @@ class XendDomainInfo: 7.114 except Exception, exn: 7.115 raise XendError('Failed to destroy device') 7.116 7.117 + def destroy_dscsi(self, dev_uuid): 7.118 + dscsi = XendAPIStore.get(dev_uuid, 'DSCSI') 7.119 + devid = dscsi.get_virtual_host() 7.120 + vHCTL = dscsi.get_virtual_HCTL() 7.121 + cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid, None) 7.122 + dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid') 7.123 + 7.124 + target_dev = None 7.125 + new_vscsi_sxp = ['vscsi'] 7.126 + for dev in sxp.children(cur_vscsi_sxp, 'dev'): 7.127 + if vHCTL == sxp.child_value(dev, 'v-dev'): 7.128 + target_dev = dev 7.129 + else: 7.130 + new_vscsi_sxp.append(dev) 7.131 + 7.132 + if target_dev is None: 7.133 + raise XendError('Failed to destroy device') 7.134 + 7.135 + target_dev.append(['state', 'Closing']) 7.136 + target_vscsi_sxp = ['vscsi', target_dev] 7.137 + 7.138 + if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: 7.139 + 7.140 + self.info.device_update(dev_uuid, new_vscsi_sxp) 7.141 + if len(sxp.children(new_vscsi_sxp, 'dev')) == 0: 7.142 + del self.info['devices'][dev_uuid] 7.143 + xen.xend.XendDomain.instance().managed_config_save(self) 7.144 + 7.145 + else: 7.146 + try: 7.147 + self.device_configure(target_vscsi_sxp) 7.148 + 7.149 + except Exception, exn: 7.150 + raise XendError('Failed to destroy device') 7.151 + 7.152 def destroy_xapi_instances(self): 7.153 """Destroy Xen-API instances stored in XendAPIStore. 7.154 """ 7.155 @@ -3508,6 +3604,10 @@ class XendDomainInfo: 7.156 for dpci_uuid in XendDPCI.get_by_VM(self.info.get('uuid')): 7.157 XendAPIStore.deregister(dpci_uuid, "DPCI") 7.158 7.159 + # Destroy DSCSI instances. 7.160 + for dscsi_uuid in XendDSCSI.get_by_VM(self.info.get('uuid')): 7.161 + XendAPIStore.deregister(dscsi_uuid, "DSCSI") 7.162 + 7.163 def has_device(self, dev_class, dev_uuid): 7.164 return (dev_uuid in self.info['%s_refs' % dev_class.lower()]) 7.165
8.1 --- a/tools/python/xen/xend/XendNode.py Wed Oct 15 15:58:09 2008 +0100 8.2 +++ b/tools/python/xen/xend/XendNode.py Thu Oct 16 09:50:18 2008 +0100 8.3 @@ -22,6 +22,7 @@ import xen.lowlevel.xc 8.4 8.5 from xen.util import Brctl 8.6 from xen.util import pci as PciUtil 8.7 +from xen.util import vscsi_util 8.8 from xen.xend import XendAPIStore 8.9 from xen.xend import osdep 8.10 8.11 @@ -38,7 +39,8 @@ from XendNetwork import * 8.12 from XendStateStore import XendStateStore 8.13 from XendMonitor import XendMonitor 8.14 from XendPPCI import XendPPCI 8.15 - 8.16 +from XendPSCSI import XendPSCSI 8.17 + 8.18 class XendNode: 8.19 """XendNode - Represents a Domain 0 Host.""" 8.20 8.21 @@ -53,6 +55,7 @@ class XendNode: 8.22 * network 8.23 * Storage Repository 8.24 * PPCI 8.25 + * PSCSI 8.26 """ 8.27 8.28 self.xc = xen.lowlevel.xc.xc() 8.29 @@ -269,6 +272,24 @@ class XendNode: 8.30 XendPPCI(ppci_uuid, ppci_record) 8.31 8.32 8.33 + # Initialise PSCSIs 8.34 + saved_pscsis = self.state_store.load_state('pscsi') 8.35 + saved_pscsi_table = {} 8.36 + if saved_pscsis: 8.37 + for pscsi_uuid, pscsi_record in saved_pscsis.items(): 8.38 + try: 8.39 + saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid 8.40 + except KeyError: 8.41 + pass 8.42 + 8.43 + for pscsi_record in vscsi_util.get_all_scsi_devices(): 8.44 + if pscsi_record['scsi_id']: 8.45 + # If saved uuid exists, use it. Otherwise create one. 8.46 + pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'], 8.47 + uuid.createString()) 8.48 + XendPSCSI(pscsi_uuid, pscsi_record) 8.49 + 8.50 + 8.51 ## def network_destroy(self, net_uuid): 8.52 ## del self.networks[net_uuid] 8.53 ## self.save_networks() 8.54 @@ -320,6 +341,15 @@ class XendNode: 8.55 return None 8.56 8.57 8.58 + def get_PSCSI_refs(self): 8.59 + return XendPSCSI.get_all() 8.60 + 8.61 + def get_pscsi_by_uuid(self, pscsi_uuid): 8.62 + if pscsi_uuid in self.get_PSCSI_refs(): 8.63 + return pscsi_uuid 8.64 + return None 8.65 + 8.66 + 8.67 def save(self): 8.68 # save state 8.69 host_record = {self.uuid: {'name_label':self.name, 8.70 @@ -333,6 +363,7 @@ class XendNode: 8.71 self.save_PBDs() 8.72 self.save_SRs() 8.73 self.save_PPCIs() 8.74 + self.save_PSCSIs() 8.75 8.76 def save_PIFs(self): 8.77 pif_records = dict([(pif_uuid, XendAPIStore.get( 8.78 @@ -363,6 +394,12 @@ class XendNode: 8.79 for ppci_uuid in XendPPCI.get_all()]) 8.80 self.state_store.save_state('ppci', ppci_records) 8.81 8.82 + def save_PSCSIs(self): 8.83 + pscsi_records = dict([(pscsi_uuid, XendAPIStore.get( 8.84 + pscsi_uuid, "PSCSI").get_record()) 8.85 + for pscsi_uuid in XendPSCSI.get_all()]) 8.86 + self.state_store.save_state('pscsi', pscsi_records) 8.87 + 8.88 def shutdown(self): 8.89 return 0 8.90
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/tools/python/xen/xend/XendPSCSI.py Thu Oct 16 09:50:18 2008 +0100 9.3 @@ -0,0 +1,143 @@ 9.4 +#============================================================================ 9.5 +# This library is free software; you can redistribute it and/or 9.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public 9.7 +# License as published by the Free Software Foundation. 9.8 +# 9.9 +# This library is distributed in the hope that it will be useful, 9.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of 9.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9.12 +# Lesser General Public License for more details. 9.13 +# 9.14 +# You should have received a copy of the GNU Lesser General Public 9.15 +# License along with this library; if not, write to the Free Software 9.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 9.17 +#============================================================================ 9.18 +# Copyright FUJITSU LIMITED 2008 9.19 +# Masaki Kanno <kanno.masaki@jp.fujitsu.com> 9.20 +#============================================================================ 9.21 + 9.22 +from xen.xend.XendBase import XendBase 9.23 +from xen.xend.XendBase import XendAPIStore 9.24 +from xen.xend import uuid as genuuid 9.25 + 9.26 +class XendPSCSI(XendBase): 9.27 + """Representation of a physical SCSI device.""" 9.28 + 9.29 + def getClass(self): 9.30 + return "PSCSI" 9.31 + 9.32 + def getAttrRO(self): 9.33 + attrRO = ['host', 9.34 + 'physical_host', 9.35 + 'physical_channel', 9.36 + 'physical_target', 9.37 + 'physical_lun', 9.38 + 'physical_HCTL', 9.39 + 'vendor_name', 9.40 + 'model', 9.41 + 'type_id', 9.42 + 'type', 9.43 + 'dev_name', 9.44 + 'sg_name', 9.45 + 'revision', 9.46 + 'scsi_id', 9.47 + 'scsi_level'] 9.48 + return XendBase.getAttrRO() + attrRO 9.49 + 9.50 + def getAttrRW(self): 9.51 + attrRW = [] 9.52 + return XendBase.getAttrRW() + attrRW 9.53 + 9.54 + def getAttrInst(self): 9.55 + attrInst = [] 9.56 + return XendBase.getAttrInst() + attrInst 9.57 + 9.58 + def getMethods(self): 9.59 + methods = [] 9.60 + return XendBase.getMethods() + methods 9.61 + 9.62 + def getFuncs(self): 9.63 + funcs = [] 9.64 + return XendBase.getFuncs() + funcs 9.65 + 9.66 + getClass = classmethod(getClass) 9.67 + getAttrRO = classmethod(getAttrRO) 9.68 + getAttrRW = classmethod(getAttrRW) 9.69 + getAttrInst = classmethod(getAttrInst) 9.70 + getMethods = classmethod(getMethods) 9.71 + getFuncs = classmethod(getFuncs) 9.72 + 9.73 + def get_by_HCTL(self, physical_HCTL): 9.74 + for pscsi in XendAPIStore.get_all("PSCSI"): 9.75 + if pscsi.get_physical_HCTL() == physical_HCTL: 9.76 + return pscsi.get_uuid() 9.77 + return None 9.78 + 9.79 + get_by_HCTL = classmethod(get_by_HCTL) 9.80 + 9.81 + def __init__(self, uuid, record): 9.82 + self.physical_HCTL = record['physical_HCTL'] 9.83 + self.vendor_name = record['vendor_name'] 9.84 + self.model = record['model'] 9.85 + self.type_id = record['type_id'] 9.86 + self.type = record['type'] 9.87 + self.dev_name = record['dev_name'] 9.88 + self.sg_name = record['sg_name'] 9.89 + self.revision = record['revision'] 9.90 + self.scsi_id = record['scsi_id'] 9.91 + self.scsi_level = record['scsi_level'] 9.92 + 9.93 + p_hctl = self.physical_HCTL.split(':') 9.94 + self.physical_host = int(p_hctl[0]) 9.95 + self.physical_channel = int(p_hctl[1]) 9.96 + self.physical_target = int(p_hctl[2]) 9.97 + self.physical_lun = int(p_hctl[3]) 9.98 + 9.99 + XendBase.__init__(self, uuid, record) 9.100 + 9.101 + def get_host(self): 9.102 + from xen.xend import XendNode 9.103 + return XendNode.instance().get_uuid() 9.104 + 9.105 + def get_physical_host(self): 9.106 + return self.physical_host 9.107 + 9.108 + def get_physical_channel(self): 9.109 + return self.physical_channel 9.110 + 9.111 + def get_physical_target(self): 9.112 + return self.physical_target 9.113 + 9.114 + def get_physical_lun(self): 9.115 + return self.physical_lun 9.116 + 9.117 + def get_physical_HCTL(self): 9.118 + return self.physical_HCTL 9.119 + 9.120 + def get_vendor_name(self): 9.121 + return self.vendor_name 9.122 + 9.123 + def get_model(self): 9.124 + return self.model 9.125 + 9.126 + def get_type_id(self): 9.127 + return self.type_id 9.128 + 9.129 + def get_type(self): 9.130 + return self.type 9.131 + 9.132 + def get_dev_name(self): 9.133 + return self.dev_name 9.134 + 9.135 + def get_sg_name(self): 9.136 + return self.sg_name 9.137 + 9.138 + def get_revision(self): 9.139 + return self.revision 9.140 + 9.141 + def get_scsi_id(self): 9.142 + return self.scsi_id 9.143 + 9.144 + def get_scsi_level(self): 9.145 + return self.scsi_level 9.146 +
10.1 --- a/tools/python/xen/xend/server/vscsiif.py Wed Oct 15 15:58:09 2008 +0100 10.2 +++ b/tools/python/xen/xend/server/vscsiif.py Thu Oct 16 09:50:18 2008 +0100 10.3 @@ -125,10 +125,10 @@ class VSCSIController(DevController): 10.4 state = self.readBackend(devid, devpath + '/state') 10.5 localdevid = self.readBackend(devid, devpath + '/devid') 10.6 dev_dict = {'p-dev': pdev, 10.7 - 'p-devname': pdevname, 10.8 - 'v-dev': pdevname, 10.9 - 'state': state, 10.10 - 'devid': localdevid } 10.11 + 'p-devname': pdevname, 10.12 + 'v-dev': vdev, 10.13 + 'state': state, 10.14 + 'devid': localdevid } 10.15 vscsi_devs.append(dev_dict) 10.16 10.17 config['devs'] = vscsi_devs 10.18 @@ -168,17 +168,17 @@ class VSCSIController(DevController): 10.19 (devid, back, front) = self.getDeviceDetails(config) 10.20 devid = int(devid) 10.21 vscsi_config = config['devs'][0] 10.22 - states = config.get('states', []) 10.23 + state = vscsi_config.get('state', '') 10.24 driver_state = self.readBackend(devid, 'state') 10.25 if str(xenbusState['Connected']) != driver_state: 10.26 raise VmError("Driver status is not connected") 10.27 10.28 uuid = self.readBackend(devid, 'uuid') 10.29 - if states[0] == 'Initialising': 10.30 + if state == 'Initialising': 10.31 back['uuid'] = uuid 10.32 self.writeBackend(devid, back) 10.33 10.34 - elif states[0] == 'Closing': 10.35 + elif state == 'Closing': 10.36 found = False 10.37 devs = self.readBackendList(devid, "vscsi-devs") 10.38 vscsipath = "vscsi-devs/" 10.39 @@ -197,8 +197,8 @@ class VSCSIController(DevController): 10.40 raise VmError("Device %s not connected" % vdev) 10.41 10.42 else: 10.43 - raise XendError('Error configuring device invalid state %s' 10.44 - % state) 10.45 + raise XendError("Error configuring device invalid " 10.46 + "state '%s'" % state) 10.47 10.48 self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring'])) 10.49 return self.readBackend(devid, 'uuid')
11.1 --- a/tools/python/xen/xm/create.dtd Wed Oct 15 15:58:09 2008 +0100 11.2 +++ b/tools/python/xen/xm/create.dtd Thu Oct 16 09:50:18 2008 +0100 11.3 @@ -40,6 +40,7 @@ 11.4 vif*, 11.5 vtpm*, 11.6 pci*, 11.7 + vscsi*, 11.8 console*, 11.9 platform*, 11.10 vcpu_param*, 11.11 @@ -88,6 +89,10 @@ 11.12 func CDATA #REQUIRED 11.13 vslt CDATA #IMPLIED> 11.14 11.15 +<!ELEMENT vscsi EMPTY> 11.16 +<!ATTLIST vscsi p-dev CDATA #REQUIRED 11.17 + v-dev CDATA #REQUIRED> 11.18 + 11.19 <!ELEMENT console (other_config*)> 11.20 <!ATTLIST console protocol (vt100|rfb|rdp) #REQUIRED> 11.21
12.1 --- a/tools/python/xen/xm/main.py Wed Oct 15 15:58:09 2008 +0100 12.2 +++ b/tools/python/xen/xm/main.py Thu Oct 16 09:50:18 2008 +0100 12.3 @@ -2235,12 +2235,34 @@ def vscsi_convert_sxp_to_dict(dev_sxp): 12.4 return dev_dict 12.5 12.6 def xm_scsi_list(args): 12.7 - xenapi_unsupported() 12.8 (use_long, params) = arg_check_for_resource_list(args, "scsi-list") 12.9 12.10 dom = params[0] 12.11 12.12 - devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi') 12.13 + devs = [] 12.14 + if serverType == SERVER_XEN_API: 12.15 + 12.16 + dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom)) 12.17 + dscsi_properties = \ 12.18 + map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs) 12.19 + dscsi_dict = {} 12.20 + for dscsi_property in dscsi_properties: 12.21 + devid = int(dscsi_property['dev']['devid']) 12.22 + try: 12.23 + dscsi_sxp = dscsi_dict[devid] 12.24 + except: 12.25 + dscsi_sxp = [['devs', []]] 12.26 + for key, value in dscsi_property.items(): 12.27 + if key != 'dev': 12.28 + dscsi_sxp.append([key, value]) 12.29 + dev_sxp = ['dev'] 12.30 + dev_sxp.extend(map2sxp(dscsi_property['dev'])) 12.31 + dscsi_sxp[0][1].append(dev_sxp) 12.32 + dscsi_dict[devid] = dscsi_sxp 12.33 + devs = map2sxp(dscsi_dict) 12.34 + 12.35 + else: 12.36 + devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi') 12.37 12.38 if use_long: 12.39 map(PrettyPrint.prettyprint, devs) 12.40 @@ -2464,37 +2486,60 @@ def xm_pci_attach(args): 12.41 else: 12.42 server.xend.domain.device_configure(dom, pci) 12.43 12.44 +def parse_scsi_configuration(p_scsi, v_hctl, state): 12.45 + v = v_hctl.split(':') 12.46 + if len(v) != 4: 12.47 + raise OptionError("Invalid argument: %s" % v_hctl) 12.48 + 12.49 + if p_scsi is not None: 12.50 + (p_hctl, block) = vscsi_util.vscsi_search_hctl_and_block(p_scsi) 12.51 + if p_hctl == None: 12.52 + raise OptionError("Cannot find device '%s'" % p_scsi) 12.53 + else: 12.54 + p_hctl = '' 12.55 + block = '' 12.56 + 12.57 + scsi = ['vscsi'] 12.58 + scsi.append(['dev', \ 12.59 + ['state', state], \ 12.60 + ['devid', int(v[0])], \ 12.61 + ['p-dev', p_hctl], \ 12.62 + ['p-devname', block], \ 12.63 + ['v-dev', v_hctl] \ 12.64 + ]) 12.65 + 12.66 + return scsi 12.67 + 12.68 def xm_scsi_attach(args): 12.69 - xenapi_unsupported() 12.70 - 12.71 arg_check(args, 'scsi-attach', 3, 4) 12.72 - p_devname = args[1] 12.73 - v_dev = args[2] 12.74 - 12.75 - v_hctl = v_dev.split(':') 12.76 - if len(v_hctl) != 4: 12.77 - raise OptionError("Invalid argument: %s" % v_dev) 12.78 - 12.79 - (p_hctl, block) = vscsi_util.vscsi_search_hctl_and_block(p_devname) 12.80 - 12.81 - if p_hctl == None: 12.82 - raise OptionError("Cannot find device \"%s\"" % p_devname) 12.83 - 12.84 dom = args[0] 12.85 - vscsi = ['vscsi'] 12.86 - vscsi.append(['dev', \ 12.87 - ['state', 'Initialising'], \ 12.88 - ['devid', v_hctl[0]], \ 12.89 - ['p-dev', p_hctl], \ 12.90 - ['p-devname', block], \ 12.91 - ['v-dev', v_dev] ]) 12.92 - 12.93 - if len(args) == 4: 12.94 - vscsi.append(['backend', args[3]]) 12.95 - 12.96 - vscsi.append(['state', 'Initialising']) 12.97 - vscsi.append(['devid', v_hctl[0]]) 12.98 - server.xend.domain.device_configure(dom, vscsi) 12.99 + p_scsi = args[1] 12.100 + v_hctl = args[2] 12.101 + scsi = parse_scsi_configuration(p_scsi, v_hctl, 'Initialising') 12.102 + 12.103 + if serverType == SERVER_XEN_API: 12.104 + 12.105 + scsi_dev = sxp.children(scsi, 'dev')[0] 12.106 + p_hctl = sxp.child_value(scsi_dev, 'p-dev') 12.107 + target_ref = None 12.108 + for pscsi_ref in server.xenapi.PSCSI.get_all(): 12.109 + if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref): 12.110 + target_ref = pscsi_ref 12.111 + break 12.112 + if target_ref is None: 12.113 + raise OptionError("Cannot find device '%s'" % p_scsi) 12.114 + 12.115 + dscsi_record = { 12.116 + "VM": get_single_vm(dom), 12.117 + "PSCSI": target_ref, 12.118 + "virtual_HCTL": v_hctl 12.119 + } 12.120 + server.xenapi.DSCSI.create(dscsi_record) 12.121 + 12.122 + else: 12.123 + if len(args) == 4: 12.124 + scsi.append(['backend', args[3]]) 12.125 + server.xend.domain.device_configure(dom, scsi) 12.126 12.127 def detach(args, deviceClass): 12.128 rm_cfg = True 12.129 @@ -2587,26 +2632,25 @@ def xm_pci_detach(args): 12.130 server.xend.domain.device_configure(dom, pci) 12.131 12.132 def xm_scsi_detach(args): 12.133 - xenapi_unsupported() 12.134 arg_check(args, 'scsi-detach', 2) 12.135 - 12.136 - v_dev = args[1] 12.137 - v_hctl = v_dev.split(':') 12.138 - if len(v_hctl) != 4: 12.139 - raise OptionError("Invalid argument: %s" % v_dev) 12.140 - 12.141 dom = args[0] 12.142 - vscsi = ['vscsi'] 12.143 - vscsi.append(['dev', \ 12.144 - ['state', 'Closing'], \ 12.145 - ['devid', v_hctl[0]], \ 12.146 - ['p-dev', ''], \ 12.147 - ['p-devname', ''], \ 12.148 - ['v-dev', v_dev] ]) 12.149 - 12.150 - vscsi.append(['state', 'Closing']) 12.151 - vscsi.append(['devid', v_hctl[0]]) 12.152 - server.xend.domain.device_configure(dom, vscsi) 12.153 + v_hctl = args[1] 12.154 + scsi = parse_scsi_configuration(None, v_hctl, 'Closing') 12.155 + 12.156 + if serverType == SERVER_XEN_API: 12.157 + 12.158 + target_ref = None 12.159 + for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)): 12.160 + if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref): 12.161 + target_ref = dscsi_ref 12.162 + break 12.163 + if target_ref is None: 12.164 + raise OptionError("Device %s not assigned" % v_hctl) 12.165 + 12.166 + server.xenapi.DSCSI.destroy(target_ref) 12.167 + 12.168 + else: 12.169 + server.xend.domain.device_configure(dom, scsi) 12.170 12.171 def xm_vnet_list(args): 12.172 xenapi_unsupported()
13.1 --- a/tools/python/xen/xm/xenapi_create.py Wed Oct 15 15:58:09 2008 +0100 13.2 +++ b/tools/python/xen/xm/xenapi_create.py Thu Oct 16 09:50:18 2008 +0100 13.3 @@ -375,6 +375,12 @@ class xenapi_create: 13.4 13.5 self.create_pcis(vm_ref, pcis) 13.6 13.7 + # Now create scsis 13.8 + 13.9 + scsis = vm.getElementsByTagName("vscsi") 13.10 + 13.11 + self.create_scsis(vm_ref, scsis) 13.12 + 13.13 return vm_ref 13.14 except: 13.15 server.xenapi.VM.destroy(vm_ref) 13.16 @@ -532,6 +538,33 @@ class xenapi_create: 13.17 13.18 return server.xenapi.DPCI.create(dpci_record) 13.19 13.20 + def create_scsis(self, vm_ref, scsis): 13.21 + log(DEBUG, "create_scsis") 13.22 + return map(lambda scsi: self.create_scsi(vm_ref, scsi), scsis) 13.23 + 13.24 + def create_scsi(self, vm_ref, scsi): 13.25 + log(DEBUG, "create_scsi") 13.26 + 13.27 + target_ref = None 13.28 + for pscsi_ref in server.xenapi.PSCSI.get_all(): 13.29 + if scsi.attributes["p-dev"].value == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref): 13.30 + target_ref = pscsi_ref 13.31 + break 13.32 + if target_ref is None: 13.33 + log(DEBUG, "create_scsi: scsi device not found") 13.34 + return None 13.35 + 13.36 + dscsi_record = { 13.37 + "VM": 13.38 + vm_ref, 13.39 + "PSCSI": 13.40 + target_ref, 13.41 + "virtual_HCTL": 13.42 + scsi.attributes["v-dev"].value 13.43 + } 13.44 + 13.45 + return server.xenapi.DSCSI.create(dscsi_record) 13.46 + 13.47 def get_child_by_name(exp, childname, default = None): 13.48 try: 13.49 return [child for child in sxp.children(exp) 13.50 @@ -563,6 +596,9 @@ class sxp2xml: 13.51 pcis_sxp = map(lambda x: x[1], [device for device in devices 13.52 if device[1][0] == "pci"]) 13.53 13.54 + scsis_sxp = map(lambda x: x[1], [device for device in devices 13.55 + if device[1][0] == "vscsi"]) 13.56 + 13.57 # Create XML Document 13.58 13.59 impl = getDOMImplementation() 13.60 @@ -704,6 +740,12 @@ class sxp2xml: 13.61 13.62 map(vm.appendChild, pcis) 13.63 13.64 + # And now the scsis 13.65 + 13.66 + scsis = self.extract_scsis(scsis_sxp, document) 13.67 + 13.68 + map(vm.appendChild, scsis) 13.69 + 13.70 # Last but not least the consoles... 13.71 13.72 consoles = self.extract_consoles(image, document) 13.73 @@ -894,6 +936,23 @@ class sxp2xml: 13.74 13.75 return pcis 13.76 13.77 + def extract_scsis(self, scsis_sxp, document): 13.78 + 13.79 + scsis = [] 13.80 + 13.81 + for scsi_sxp in scsis_sxp: 13.82 + for dev_sxp in sxp.children(scsi_sxp, "dev"): 13.83 + scsi = document.createElement("vscsi") 13.84 + 13.85 + scsi.attributes["p-dev"] \ 13.86 + = get_child_by_name(dev_sxp, "p-dev") 13.87 + scsi.attributes["v-dev"] \ 13.88 + = get_child_by_name(dev_sxp, "v-dev") 13.89 + 13.90 + scsis.append(scsi) 13.91 + 13.92 + return scsis 13.93 + 13.94 def mk_other_config(self, key, value, document): 13.95 other_config = document.createElement("other_config") 13.96 other_config.attributes["key"] = key