WARNING - OLD ARCHIVES

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

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Enhance XenAPI for pvSCSI
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 22 Oct 2008 07:50:09 -0700
Delivery-date: Wed, 22 Oct 2008 07:50:08 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Enhance XenAPI for pvSCSI, Xen patchbot-unstable <=