[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Enhance XenAPI for pvSCSI



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1224147018 -3600
# Node ID 9404bcb6d32e2a3873289254a42b0dbf6663a41c
# Parent  22c89412fc8c0b7d47b73b7d67f0ef88b07b935e
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@xxxxxxxxxxxxxx>
---
 tools/python/xen/util/pci.py            |   21 ---
 tools/python/xen/util/utils.py          |   26 ++++
 tools/python/xen/util/vscsi_util.py     |  113 +++++++++++++++++
 tools/python/xen/xend/XendAPI.py        |   20 ++-
 tools/python/xen/xend/XendConfig.py     |  201 ++++++++++++++++++++++++++------
 tools/python/xen/xend/XendDSCSI.py      |  174 +++++++++++++++++++++++++++
 tools/python/xen/xend/XendDomainInfo.py |  110 ++++++++++++++++-
 tools/python/xen/xend/XendNode.py       |   39 ++++++
 tools/python/xen/xend/XendPSCSI.py      |  143 ++++++++++++++++++++++
 tools/python/xen/xend/server/vscsiif.py |   18 +-
 tools/python/xen/xm/create.dtd          |    5 
 tools/python/xen/xm/main.py             |  140 ++++++++++++++--------
 tools/python/xen/xm/xenapi_create.py    |   59 +++++++++
 13 files changed, 947 insertions(+), 122 deletions(-)

diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/util/pci.py
--- a/tools/python/xen/util/pci.py      Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/util/pci.py      Thu Oct 16 09:50:18 2008 +0100
@@ -12,8 +12,8 @@ import types
 import types
 import struct
 import time
-
-PROC_MNT_PATH = '/proc/mounts'
+from xen.util import utils
+
 PROC_PCI_PATH = '/proc/bus/pci/devices'
 PROC_PCI_NUM_RESOURCES = 7
 
@@ -97,9 +97,6 @@ MSIX_SIZE_MASK = 0x7ff
 # Global variable to store information from lspci
 lspci_info = None
 
-# Global variable to store the sysfs mount point
-sysfs_mnt_point = None
-
 #Calculate PAGE_SHIFT: number of bits to shift an address to get the page 
number
 PAGE_SIZE = resource.getpagesize()
 PAGE_SHIFT = 0
@@ -141,20 +138,8 @@ def parse_pci_name(pci_name_string):
  
 
 def find_sysfs_mnt():
-    global sysfs_mnt_point
-    if not sysfs_mnt_point is None:
-        return sysfs_mnt_point
-
     try:
-        mounts_file = open(PROC_MNT_PATH,'r')
-
-        for line in mounts_file:
-            sline = line.split()
-            if len(sline)<3:
-                continue
-            if sline[2]=='sysfs':
-                sysfs_mnt_point= sline[1]
-                return sysfs_mnt_point
+        return utils.find_sysfs_mount()
     except IOError, (errno, strerr):
         raise PciDeviceParseError(('Failed to locate sysfs mount: %s: %s (%d)'%
             (PROC_PCI_PATH, strerr, errno)))
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/util/utils.py
--- a/tools/python/xen/util/utils.py    Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/util/utils.py    Thu Oct 16 09:50:18 2008 +0100
@@ -48,3 +48,29 @@ def daemonize(prog, args, stdin_tmpfile=
     os.waitpid(pid, 0)
     return daemon_pid
 
+# Global variable to store the sysfs mount point
+sysfs_mount_point = None
+
+PROC_MOUNTS_PATH = '/proc/mounts'
+
+def find_sysfs_mount():
+    global sysfs_mount_point
+
+    if not sysfs_mount_point is None:
+        return sysfs_mount_point
+
+    try:
+        mounts_file = open(PROC_MOUNTS_PATH, 'r')
+
+        for line in mounts_file:
+            sline = line.split()
+            if len(sline) < 3:
+                continue
+            if sline[2] == 'sysfs':
+                sysfs_mount_point= sline[1]
+                return sysfs_mount_point
+    except IOError, (errno, strerr):
+        raise
+
+    return None
+
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/util/vscsi_util.py
--- a/tools/python/xen/util/vscsi_util.py       Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/util/vscsi_util.py       Thu Oct 16 09:50:18 2008 +0100
@@ -23,9 +23,18 @@
 """Support for VSCSI Devices.
 """
 import os
+import os.path
 import sys
 import re
 import string
+from xen.util import utils
+
+SYSFS_SCSI_PATH = "/bus/scsi/devices"
+SYSFS_SCSI_DEV_VENDOR_PATH = '/vendor'
+SYSFS_SCSI_DEV_MODEL_PATH = '/model'
+SYSFS_SCSI_DEV_TYPEID_PATH = '/type'
+SYSFS_SCSI_DEV_REVISION_PATH = '/rev'
+SYSFS_SCSI_DEV_SCSILEVEL_PATH = '/scsi_level'
 
 def _vscsi_hctl_block(name, scsi_devices):
     """ block-device name is convert into hctl. (e.g., '/dev/sda',
@@ -84,10 +93,10 @@ def vscsi_get_scsidevices():
 def vscsi_get_scsidevices():
     """ get all scsi devices"""
 
-    SERCH_SCSI_PATH = "/sys/bus/scsi/devices"
     devices = []
-
-    for dirpath, dirnames, files in os.walk(SERCH_SCSI_PATH):
+    sysfs_mnt = utils.find_sysfs_mount() 
+
+    for dirpath, dirnames, files in os.walk(sysfs_mnt + SYSFS_SCSI_PATH):
         for hctl in dirnames:
             paths = os.path.join(dirpath, hctl)
             block = "-"
@@ -131,3 +140,101 @@ def vscsi_search_hctl_and_block(device):
 
     return (hctl, block)
 
+
+def get_scsi_vendor(pHCTL):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_scsi_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+        scsi_vendor = \
+            os.popen('cat ' + sysfs_scsi_dev_path + \
+                              SYSFS_SCSI_DEV_VENDOR_PATH).read()
+        return scsi_vendor.splitlines()[0]
+    except:
+        return None
+
+def get_scsi_model(pHCTL):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_scsi_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+        scsi_model = \
+            os.popen('cat ' + sysfs_scsi_dev_path + \
+                              SYSFS_SCSI_DEV_MODEL_PATH).read()
+        return scsi_model.splitlines()[0]
+    except:
+        return None
+
+def get_scsi_typeid(pHCTL):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_scsi_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+        scsi_typeid = \
+            os.popen('cat ' + sysfs_scsi_dev_path + \
+                              SYSFS_SCSI_DEV_TYPEID_PATH).read()
+        return int(scsi_typeid.splitlines()[0])
+    except:
+        return None
+
+def get_scsi_revision(pHCTL):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_scsi_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+        scsi_revision = \
+            os.popen('cat ' + sysfs_scsi_dev_path + \
+                              SYSFS_SCSI_DEV_REVISION_PATH).read()
+        return scsi_revision.splitlines()[0]
+    except:
+        return None
+
+def get_scsi_scsilevel(pHCTL):
+    try:
+        sysfs_mnt = utils.find_sysfs_mount() 
+        sysfs_scsi_dev_path = \
+            os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+        scsi_scsilevel = \
+            os.popen('cat ' + sysfs_scsi_dev_path + \
+                              SYSFS_SCSI_DEV_SCSILEVEL_PATH).read()
+        return int(scsi_scsilevel.splitlines()[0])
+    except:
+        return None
+
+def get_all_scsi_devices():
+
+    scsi_devs = []
+
+    for scsi_info in vscsi_get_scsidevices():
+        scsi_dev = {
+            'physical_HCTL': scsi_info[0],
+            'dev_name': None,
+            'sg_name': scsi_info[2],
+            'scsi_id': None
+        }
+        if scsi_info[1] != '-':
+            scsi_dev['dev_name'] = scsi_info[1] 
+        if scsi_info[3] != '-':
+            scsi_dev['scsi_id'] = scsi_info[3] 
+
+        scsi_dev['vendor_name'] = \
+            get_scsi_vendor(scsi_dev['physical_HCTL'])
+        scsi_dev['model'] = \
+            get_scsi_model(scsi_dev['physical_HCTL'])
+        scsi_dev['type_id'] = \
+            get_scsi_typeid(scsi_dev['physical_HCTL'])
+        scsi_dev['revision'] = \
+            get_scsi_revision(scsi_dev['physical_HCTL'])
+        scsi_dev['scsi_level'] = \
+            get_scsi_scsilevel(scsi_dev['physical_HCTL'])
+
+        try:
+            lsscsi_info = os.popen('lsscsi ' + 
scsi_dev['physical_HCTL']).read().split()
+            scsi_dev['type'] = lsscsi_info[1]
+        except:
+            scsi_dev['type'] = None
+
+        scsi_devs.append(scsi_dev)
+
+    return scsi_devs
+
diff -r 22c89412fc8c -r 9404bcb6d32e 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 09:50:18 2008 +0100
@@ -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 -r 9404bcb6d32e 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 09:50:18 2008 +0100
@@ -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 -r 9404bcb6d32e 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 09:50:18 2008 +0100
@@ -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 <kanno.masaki@xxxxxxxxxxxxxx>
+#============================================================================
+
+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 -r 9404bcb6d32e 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 09:50:18 2008 +0100
@@ -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 -r 9404bcb6d32e 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 09:50:18 2008 +0100
@@ -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 -r 9404bcb6d32e 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 09:50:18 2008 +0100
@@ -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 <kanno.masaki@xxxxxxxxxxxxxx>
+#============================================================================
+
+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
+
diff -r 22c89412fc8c -r 9404bcb6d32e 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 09:50:18 2008 +0100
@@ -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 -r 9404bcb6d32e tools/python/xen/xm/create.dtd
--- a/tools/python/xen/xm/create.dtd    Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xm/create.dtd    Thu Oct 16 09:50:18 2008 +0100
@@ -40,6 +40,7 @@
                  vif*,
                  vtpm*,
                  pci*,
+                 vscsi*,
                  console*,
                  platform*,
                  vcpu_param*,
@@ -87,6 +88,10 @@
                  slot            CDATA #REQUIRED
                  func            CDATA #REQUIRED
                  vslt            CDATA #IMPLIED>
+
+<!ELEMENT vscsi  EMPTY>
+<!ATTLIST vscsi  p-dev           CDATA #REQUIRED
+                 v-dev           CDATA #REQUIRED>
 
 <!ELEMENT console (other_config*)>
 <!ATTLIST console protocol       (vt100|rfb|rdp) #REQUIRED>
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xm/main.py       Thu Oct 16 09:50:18 2008 +0100
@@ -2235,12 +2235,34 @@ def vscsi_convert_sxp_to_dict(dev_sxp):
     return dev_dict
 
 def xm_scsi_list(args):
-    xenapi_unsupported()
     (use_long, params) = arg_check_for_resource_list(args, "scsi-list")
 
     dom = params[0]
 
-    devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
+    devs = []
+    if serverType == SERVER_XEN_API:
+
+        dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
+        dscsi_properties = \
+            map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
+        dscsi_dict = {}
+        for dscsi_property in dscsi_properties:
+            devid = int(dscsi_property['dev']['devid'])
+            try:
+                dscsi_sxp = dscsi_dict[devid]
+            except:
+                dscsi_sxp = [['devs', []]]
+                for key, value in dscsi_property.items():
+                    if key != 'dev':
+                        dscsi_sxp.append([key, value])
+            dev_sxp = ['dev']
+            dev_sxp.extend(map2sxp(dscsi_property['dev']))
+            dscsi_sxp[0][1].append(dev_sxp)
+            dscsi_dict[devid] = dscsi_sxp
+        devs = map2sxp(dscsi_dict)
+
+    else:
+        devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
 
     if use_long:
         map(PrettyPrint.prettyprint, devs)
@@ -2464,37 +2486,60 @@ def xm_pci_attach(args):
     else:
         server.xend.domain.device_configure(dom, pci)
 
+def parse_scsi_configuration(p_scsi, v_hctl, state):
+    v = v_hctl.split(':')
+    if len(v) != 4:
+        raise OptionError("Invalid argument: %s" % v_hctl)
+
+    if p_scsi is not None:
+        (p_hctl, block) = vscsi_util.vscsi_search_hctl_and_block(p_scsi)
+        if p_hctl == None:
+            raise OptionError("Cannot find device '%s'" % p_scsi)
+    else:
+        p_hctl = ''
+        block = ''
+
+    scsi = ['vscsi']
+    scsi.append(['dev', \
+                 ['state', state], \
+                 ['devid', int(v[0])], \
+                 ['p-dev', p_hctl], \
+                 ['p-devname', block], \
+                 ['v-dev', v_hctl] \
+               ])
+
+    return scsi
+
 def xm_scsi_attach(args):
-    xenapi_unsupported()
-
     arg_check(args, 'scsi-attach', 3, 4)
-    p_devname = args[1]
-    v_dev = args[2]
-
-    v_hctl = v_dev.split(':')
-    if len(v_hctl) != 4:
-        raise OptionError("Invalid argument: %s" % v_dev)
-
-    (p_hctl, block) = vscsi_util.vscsi_search_hctl_and_block(p_devname)
-
-    if p_hctl == None:
-        raise OptionError("Cannot find device \"%s\"" % p_devname)
-
     dom = args[0]
-    vscsi = ['vscsi']
-    vscsi.append(['dev', \
-                ['state', 'Initialising'], \
-                ['devid', v_hctl[0]], \
-                ['p-dev', p_hctl], \
-                ['p-devname', block], \
-                ['v-dev', v_dev] ])
-
-    if len(args) == 4:
-        vscsi.append(['backend', args[3]])
-
-    vscsi.append(['state', 'Initialising'])
-    vscsi.append(['devid', v_hctl[0]])
-    server.xend.domain.device_configure(dom, vscsi)
+    p_scsi = args[1]
+    v_hctl = args[2]
+    scsi = parse_scsi_configuration(p_scsi, v_hctl, 'Initialising')
+
+    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)
+
+    else:
+        if len(args) == 4:
+            scsi.append(['backend', args[3]])
+        server.xend.domain.device_configure(dom, scsi)
 
 def detach(args, deviceClass):
     rm_cfg = True
@@ -2587,26 +2632,25 @@ def xm_pci_detach(args):
         server.xend.domain.device_configure(dom, pci)
 
 def xm_scsi_detach(args):
-    xenapi_unsupported()
     arg_check(args, 'scsi-detach', 2)
-
-    v_dev = args[1]
-    v_hctl = v_dev.split(':')
-    if len(v_hctl) != 4:
-        raise OptionError("Invalid argument: %s" % v_dev)
-
     dom = args[0]
-    vscsi = ['vscsi']
-    vscsi.append(['dev', \
-                ['state', 'Closing'], \
-                ['devid', v_hctl[0]], \
-                ['p-dev', ''], \
-                ['p-devname', ''], \
-                ['v-dev', v_dev] ])
-
-    vscsi.append(['state', 'Closing'])
-    vscsi.append(['devid', v_hctl[0]])
-    server.xend.domain.device_configure(dom, vscsi)
+    v_hctl = args[1]
+    scsi = parse_scsi_configuration(None, v_hctl, 'Closing')
+
+    if serverType == SERVER_XEN_API:
+
+        target_ref = None
+        for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
+            if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
+                target_ref = dscsi_ref
+                break
+        if target_ref is None:
+            raise OptionError("Device %s not assigned" % v_hctl)
+
+        server.xenapi.DSCSI.destroy(target_ref)
+
+    else:
+        server.xend.domain.device_configure(dom, scsi)
 
 def xm_vnet_list(args):
     xenapi_unsupported()
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xm/xenapi_create.py
--- a/tools/python/xen/xm/xenapi_create.py      Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xm/xenapi_create.py      Thu Oct 16 09:50:18 2008 +0100
@@ -375,6 +375,12 @@ class xenapi_create:
 
             self.create_pcis(vm_ref, pcis)
 
+            # Now create scsis
+
+            scsis = vm.getElementsByTagName("vscsi")
+
+            self.create_scsis(vm_ref, scsis)
+
             return vm_ref
         except:
             server.xenapi.VM.destroy(vm_ref)
@@ -532,6 +538,33 @@ class xenapi_create:
 
         return server.xenapi.DPCI.create(dpci_record)
 
+    def create_scsis(self, vm_ref, scsis):
+        log(DEBUG, "create_scsis")
+        return map(lambda scsi: self.create_scsi(vm_ref, scsi), scsis)
+
+    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)
+
 def get_child_by_name(exp, childname, default = None):
     try:
         return [child for child in sxp.children(exp)
@@ -562,6 +595,9 @@ class sxp2xml:
 
         pcis_sxp = map(lambda x: x[1], [device for device in devices
                                         if device[1][0] == "pci"])
+
+        scsis_sxp = map(lambda x: x[1], [device for device in devices
+                                         if device[1][0] == "vscsi"])
 
         # Create XML Document
         
@@ -704,6 +740,12 @@ class sxp2xml:
 
         map(vm.appendChild, pcis)
 
+        # And now the scsis
+
+        scsis = self.extract_scsis(scsis_sxp, document)
+
+        map(vm.appendChild, scsis)
+
         # Last but not least the consoles...
 
         consoles = self.extract_consoles(image, document)
@@ -893,6 +935,23 @@ class sxp2xml:
                 pcis.append(pci)
 
         return pcis
+
+    def extract_scsis(self, scsis_sxp, document):
+
+        scsis = []
+
+        for scsi_sxp in scsis_sxp:
+            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)
+
+        return scsis
 
     def mk_other_config(self, key, value, document):
         other_config = document.createElement("other_config")

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.