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

[Xen-changelog] [xen-unstable] pvSCSI: xend changes



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1215088746 -3600
# Node ID 6ae87b27cceadaf8339b42b7489f81b66ea03cf1
# Parent  d90c5e8d4ac2c547a81d4a464c83a7b8090c1946
pvSCSI: xend changes

Signed-off-by: Tomonari Horikoshi <t.horikoshi@xxxxxxxxxxxxxx>
Signed-off-by: Jun Kamada <kama@xxxxxxxxxxxxxx>
---
 tools/examples/vscsi                    |   22 +++
 tools/examples/xen-backend.agent        |    3 
 tools/examples/xen-backend.rules        |    1 
 tools/examples/xmexample.hvm            |   23 +++
 tools/examples/xmexample.vti            |   22 +++
 tools/examples/xmexample1               |   25 +++
 tools/examples/xmexample2               |   24 +++
 tools/python/xen/util/vscsi_util.py     |  133 ++++++++++++++++++
 tools/python/xen/xend/XendConfig.py     |   11 -
 tools/python/xen/xend/XendDevices.py    |    3 
 tools/python/xen/xend/XendDomainInfo.py |   93 ++++++++++++-
 tools/python/xen/xend/server/vscsiif.py |  228 ++++++++++++++++++++++++++++++++
 tools/python/xen/xm/create.py           |   94 +++++++++++++
 tools/python/xen/xm/main.py             |  101 ++++++++++++++
 14 files changed, 775 insertions(+), 8 deletions(-)

diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/examples/vscsi
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/examples/vscsi      Thu Jul 03 13:39:06 2008 +0100
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (c) 2007, FUJITSU Limited
+# Based on the block scripts code.
+#
+
+dir=$(dirname "$0")
+. "$dir/xen-hotplug-common.sh"
+
+findCommand "$@"
+
+case "$command" in
+       add)
+               success
+               ;;
+       remove)
+               # TODO
+               exit 0
+               ;;
+esac
+
+exit 0
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/examples/xen-backend.agent
--- a/tools/examples/xen-backend.agent  Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/examples/xen-backend.agent  Thu Jul 03 13:39:06 2008 +0100
@@ -19,6 +19,9 @@ case "$XENBUS_TYPE" in
   vif)
     [ -n "$script" ] && $script "$ACTION"
     ;;
+  vscsi)
+    /etc/xen/scripts/vscsi "$ACTION"
+    ;;
 esac
 
 case "$ACTION" in
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/examples/xen-backend.rules
--- a/tools/examples/xen-backend.rules  Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/examples/xen-backend.rules  Thu Jul 03 13:39:06 2008 +0100
@@ -3,6 +3,7 @@ SUBSYSTEM=="xen-backend", KERNEL=="vtpm*
 SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script} 
online"
 SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="offline", 
RUN+="$env{script} offline"
+SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", ACTION=="remove", 
RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
 KERNEL=="evtchn", NAME="xen/%k"
 KERNEL=="blktap[0-9]*", NAME="xen/%k"
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/examples/xmexample.hvm
--- a/tools/examples/xmexample.hvm      Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/examples/xmexample.hvm      Thu Jul 03 13:39:06 2008 +0100
@@ -282,3 +282,26 @@ serial='pty'
 #  '0' -> the bit must be '0'
 #  'x' -> we don't care (do not check)
 #  's' -> the bit must be the same as on the host that started this VM
+
+
+#-----------------------------------------------------------------------------
+#   Configure PVSCSI devices:
+#
+#vscsi=[ 'PDEV, VDEV' ]
+#
+#   PDEV   gives physical SCSI device to be attached to specified guest
+#          domain by one of the following identifier format.
+#          - XX:XX:XX:XX (4-tuples with decimal notation which shows
+#                          "host:channel:target:lun")
+#          - /dev/sdxx or sdx
+#          - /dev/stxx or stx
+#          - /dev/sgxx or sgx
+#          - result of 'scsi_id -gu -s'.
+#            ex. # scsi_id -gu -s /block/sdb
+#                  36000b5d0006a0000006a0257004c0000
+#
+#   VDEV   gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as 
+#          which the specified guest domain recognize.
+#
+
+#vscsi = [ '/dev/sdx, 0:0:0:0' ]
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/examples/xmexample.vti
--- a/tools/examples/xmexample.vti      Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/examples/xmexample.vti      Thu Jul 03 13:39:06 2008 +0100
@@ -161,3 +161,25 @@ serial='pty'
 #    'windows' - All Windows variants (Windows Server 2003/2008)
 #
 #guest_os_type='default'
+
+#-----------------------------------------------------------------------------
+#   Configure PVSCSI devices:
+#
+#vscsi=[ 'PDEV, VDEV' ]
+#
+#   PDEV   gives physical SCSI device to be attached to specified guest
+#          domain by one of the following identifier format.
+#          - XX:XX:XX:XX (4-tuples with decimal notation which shows
+#                          "host:channel:target:lun")
+#          - /dev/sdxx or sdx
+#          - /dev/stxx or stx
+#          - /dev/sgxx or sgx
+#          - result of 'scsi_id -gu -s'.
+#            ex. # scsi_id -gu -s /block/sdb
+#                  36000b5d0006a0000006a0257004c0000
+#
+#   VDEV   gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as 
+#          which the specified guest domain recognize.
+#
+
+#vscsi = [ '/dev/sdx, 0:0:0:0' ]
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/examples/xmexample1
--- a/tools/examples/xmexample1 Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/examples/xmexample1 Thu Jul 03 13:39:06 2008 +0100
@@ -185,4 +185,27 @@ extra = "4"
 #on_reboot   = 'restart'
 #on_crash    = 'restart'
 
-#============================================================================
+#-----------------------------------------------------------------------------
+#   Configure PVSCSI devices:
+#
+#vscsi=[ 'PDEV, VDEV' ]
+#
+#   PDEV   gives physical SCSI device to be attached to specified guest
+#          domain by one of the following identifier format.
+#          - XX:XX:XX:XX (4-tuples with decimal notation which shows
+#                          "host:channel:target:lun")
+#          - /dev/sdxx or sdx
+#          - /dev/stxx or stx
+#          - /dev/sgxx or sgx
+#          - result of 'scsi_id -gu -s'.
+#            ex. # scsi_id -gu -s /block/sdb
+#                  36000b5d0006a0000006a0257004c0000
+#
+#   VDEV   gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as 
+#          which the specified guest domain recognize.
+#
+
+#vscsi = [ '/dev/sdx, 0:0:0:0' ]
+
+#============================================================================
+
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/examples/xmexample2
--- a/tools/examples/xmexample2 Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/examples/xmexample2 Thu Jul 03 13:39:06 2008 +0100
@@ -221,4 +221,26 @@ extra = "4 VMID=%d usr=/dev/sda6" % vmid
 #on_reboot   = 'restart'
 #on_crash    = 'restart'
 
-#============================================================================
+#-----------------------------------------------------------------------------
+#   Configure PVSCSI devices:
+#
+#vscsi=[ 'PDEV, VDEV' ]
+#
+#   PDEV   gives physical SCSI device to be attached to specified guest
+#          domain by one of the following identifier format.
+#          - XX:XX:XX:XX (4-tuples with decimal notation which shows
+#                          "host:channel:target:lun")
+#          - /dev/sdxx or sdx
+#          - /dev/stxx or stx
+#          - /dev/sgxx or sgx
+#          - result of 'scsi_id -gu -s'.
+#            ex. # scsi_id -gu -s /block/sdb
+#                  36000b5d0006a0000006a0257004c0000
+#
+#   VDEV   gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as 
+#          which the specified guest domain recognize.
+#
+
+#vscsi = [ '/dev/sdx, 0:0:0:0' ]
+
+#============================================================================
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/python/xen/util/vscsi_util.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/util/vscsi_util.py       Thu Jul 03 13:39:06 2008 +0100
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+#  -*- mode: python; -*-
+
+#============================================================================
+# 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 (C) 2008 FUJITSU Limited
+#                     Based on the blkif.py
+#============================================================================
+
+
+"""Support for VSCSI Devices.
+"""
+import os
+import sys
+import re
+import string
+
+def _vscsi_hctl_block(name, scsi_devices):
+    """ block-device name is convert into hctl. (e.g., '/dev/sda',
+    '0:0:0:0')"""
+    try:
+        search = re.compile(r'' + name + '$', re.DOTALL)
+    except Exception, e:
+        raise VmError("vscsi: invalid expression. " + str(e))
+    chk = 0
+    for hctl, block, sg, scsi_id in scsi_devices:
+        if search.match(hctl):
+            chk = 1
+            break
+
+    if chk:
+        return (hctl, block)
+    else:
+        return (None, None)
+
+
+def _vscsi_block_scsiid_to_hctl(phyname, scsi_devices):
+    """ block-device name is convert into hctl. (e.g., '/dev/sda',
+    '0:0:0:0')"""
+    
+    if re.match('/dev/sd[a-z]+([1-9]|1[0-5])?$', phyname):
+        # sd driver
+        name = re.sub('(^/dev/)|([1-9]|1[0-5])?$', '', phyname)
+    elif re.match('/dev/sg[0-9]+$', phyname):
+        # sg driver
+        name = re.sub('^/dev/', '', phyname)
+    elif re.match('/dev/st[0-9]+$', phyname):
+        # st driver
+        name = re.sub('^/dev/', '', phyname)
+    else:
+        # scsi_id -gu
+        name = phyname
+
+    chk = 0
+    for hctl, block, sg, scsi_id in scsi_devices:
+        if block == name:
+            chk = 1
+            break
+        elif sg == name:
+            chk = 1
+            break
+        elif scsi_id == name:
+            chk = 1
+            break
+
+    if chk:
+        return (hctl, block)
+    else:
+        return (None, None)
+
+
+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):
+        for hctl in dirnames:
+            paths = os.path.join(dirpath, hctl)
+            block = "-"
+            for f in os.listdir(paths):
+                if re.match('^block', f):
+                    os.chdir(os.path.join(paths, f))
+                    block = os.path.basename(os.getcwd())
+                elif re.match('^tape', f):
+                    os.chdir(os.path.join(paths, f))
+                    block = os.path.basename(os.getcwd())
+                elif re.match('^scsi_changer', f):
+                    os.chdir(os.path.join(paths, f))
+                    block = os.path.basename(os.getcwd())
+                elif re.match('^onstream_tape', f):
+                    os.chdir(os.path.join(paths, f))
+                    block = os.path.basename(os.getcwd())
+
+                if re.match('^scsi_generic', f):
+                    os.chdir(os.path.join(paths, f))
+                    sg = os.path.basename(os.getcwd())
+                    lines = os.popen('/sbin/scsi_id -gu -s 
/class/scsi_generic/' + sg).read().split()
+                    if len(lines) == 0:
+                        scsi_id = '-'
+                    else:
+                        scsi_id = lines[0]
+
+            devices.append([hctl, block, sg, scsi_id])
+
+    return devices
+
+
+def vscsi_search_hctl_and_block(device):
+
+    scsi_devices = vscsi_get_scsidevices()
+
+    tmp = device.split(':')
+    if len(tmp) == 4:
+        (hctl, block) = _vscsi_hctl_block(device, scsi_devices)
+    else:
+        (hctl, block) = _vscsi_block_scsiid_to_hctl(device, scsi_devices)
+
+    return (hctl, block)
+
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py       Thu Jul 03 13:39:06 2008 +0100
@@ -1216,7 +1216,7 @@ class XendConfig(dict):
             dev_type = sxp.name(config)
             dev_info = {}
 
-            if dev_type == 'pci':
+            if dev_type == 'pci' or dev_type == 'vscsi':
                 pci_devs_uuid = sxp.child_value(config, 'uuid',
                                                 uuid.createString())
 
@@ -1625,7 +1625,7 @@ class XendConfig(dict):
 
             dev_type, dev_info = self['devices'][dev_uuid]
 
-            if dev_type == 'pci': # Special case for pci
+            if dev_type == 'pci' or dev_type == 'vscsi': # Special case for pci
                 pci_dict = self.pci_convert_sxp_to_dict(config)
                 pci_devs = pci_dict['devs']
 
@@ -1739,8 +1739,11 @@ class XendConfig(dict):
         ordered_refs = self.ordered_device_refs(target = target)
         for dev_uuid in ordered_refs:
             dev_type, dev_info = target['devices'][dev_uuid]
-            if dev_type == 'pci': # special case for pci devices
-                sxpr = ['pci', ['uuid', dev_info['uuid']]]
+            if dev_type == 'pci' or dev_type == 'vscsi': # special case for 
pci devices
+                if dev_type == 'pci':
+                    sxpr = ['pci', ['uuid', dev_info['uuid']]]
+                elif dev_type == 'vscsi':
+                    sxpr = ['vscsi', ['uuid', dev_info['uuid']]]
                 for pci_dev_info in dev_info['devs']:
                     pci_dev_sxpr = ['dev']
                     for opt, val in pci_dev_info.items():
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/python/xen/xend/XendDevices.py
--- a/tools/python/xen/xend/XendDevices.py      Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/python/xen/xend/XendDevices.py      Thu Jul 03 13:39:06 2008 +0100
@@ -19,7 +19,7 @@
 # A collection of DevControllers 
 #
 
-from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif
+from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, 
vscsiif
 from xen.xend.server.BlktapController import BlktapController
 from xen.xend.server.ConsoleController import ConsoleController
 
@@ -45,6 +45,7 @@ class XendDevices:
         'vfb': vfbif.VfbifController,
         'vkbd': vfbif.VkbdifController,
         'console': ConsoleController,
+        'vscsi': vscsiif.VSCSIController,
     }
 
     #@classmethod
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Jul 03 13:39:06 2008 +0100
@@ -750,6 +750,52 @@ class XendDomainInfo:
 
         return True
 
+    def vscsi_device_configure(self, dev_sxp):
+        """Configure an existing vscsi device.
+            quoted pci funciton
+        """
+        dev_class = sxp.name(dev_sxp)
+        if dev_class != 'vscsi':
+            return False
+
+        dev_config = self.pci_convert_sxp_to_dict(dev_sxp)
+        dev = dev_config['devs'][0]
+        req_devid = sxp.child_value(dev_sxp, 'devid')
+        req_devid = int(req_devid)
+        existing_dev_info = self._getDeviceInfo_vscsi(req_devid, dev['v-dev'])
+        state = sxp.child_value(dev_sxp, 'state')
+
+        if state == 'Initialising':
+            # new create
+            # If request devid does not exist, create and exit.
+            if existing_dev_info is None:
+                self.device_create(dev_sxp)
+                return True
+            elif existing_dev_info == "exists":
+                raise XendError("The virtual device %s is already defined" % 
dev['v-dev'])
+
+        elif state == 'Closing':
+            if existing_dev_info is None:
+                raise XendError("Cannot detach vscsi device does not exist")
+
+        # use DevController.reconfigureDevice to change device config
+        dev_control = self.getDeviceController(dev_class)
+        dev_uuid = dev_control.reconfigureDevice(req_devid, dev_config)
+        dev_control.waitForDevice_reconfigure(req_devid)
+        num_devs = dev_control.cleanupDevice(req_devid)
+
+        # update XendConfig with new device info
+        if dev_uuid:
+            new_dev_sxp = dev_control.configuration(req_devid)
+            self.info.device_update(dev_uuid, new_dev_sxp)
+
+        # If there is no device left, destroy vscsi and remove config.
+        if num_devs == 0:
+            self.destroyDevice('vscsi', req_devid)
+            del self.info['devices'][dev_uuid]
+
+        return True
+
     def device_configure(self, dev_sxp, devid = None):
         """Configure an existing device.
         
@@ -767,6 +813,9 @@ class XendDomainInfo:
 
         if dev_class == 'pci':
             return self.pci_device_configure(dev_sxp)
+
+        if dev_class == 'vscsi':
+            return self.vscsi_device_configure(dev_sxp)
 
         for opt_val in dev_sxp[1:]:
             try:
@@ -940,6 +989,25 @@ class XendDomainInfo:
             if dev_type != 'pci':
                 continue
             return dev_info
+        return None
+
+    def _getDeviceInfo_vscsi(self, devid, vdev):
+        devid = int(devid)
+        for dev_type, dev_info in self.info.all_devices_sxpr():
+            if dev_type != 'vscsi':
+                continue
+            existing_dev_uuid = sxp.child_value(dev_info, 'uuid')
+            existing_conf = self.info['devices'][existing_dev_uuid][1]
+            existing_dev = existing_conf['devs'][0]
+            existing_devid = int(existing_dev['devid'])
+            existing_vdev = existing_dev['v-dev']
+
+            if vdev == existing_vdev:
+                return "exists"
+
+            if devid == existing_devid:
+                return dev_info
+
         return None
 
     def setMemoryTarget(self, target):
@@ -1811,10 +1879,12 @@ class XendDomainInfo:
         if self.image:
             self.image.prepareEnvironment()
 
+        vscsi_uuidlist = {}
+        vscsi_devidlist = []
         ordered_refs = self.info.ordered_device_refs()
         for dev_uuid in ordered_refs:
             devclass, config = self.info['devices'][dev_uuid]
-            if devclass in XendDevices.valid_devices():
+            if devclass in XendDevices.valid_devices() and devclass != 'vscsi':
                 log.info("createDevice: %s : %s" % (devclass, 
scrub_password(config)))
                 dev_uuid = config.get('uuid')
                 devid = self._createDevice(devclass, config)
@@ -1822,6 +1892,27 @@ class XendDomainInfo:
                 # store devid in XendConfig for caching reasons
                 if dev_uuid in self.info['devices']:
                     self.info['devices'][dev_uuid][1]['devid'] = devid
+
+            elif devclass == 'vscsi':
+                vscsi_config = config.get('devs', [])[0]
+                devid = vscsi_config.get('devid', '')
+                dev_uuid = config.get('uuid')
+                vscsi_uuidlist[devid] = dev_uuid
+                vscsi_devidlist.append(devid)
+
+        #It is necessary to sorted it for /dev/sdxx in guest. 
+        if len(vscsi_uuidlist) > 0:
+            vscsi_devidlist.sort()
+            for vscsiid in vscsi_devidlist:
+                dev_uuid = vscsi_uuidlist[vscsiid]
+                devclass, config = self.info['devices'][dev_uuid]
+                log.info("createDevice: %s : %s" % (devclass, 
scrub_password(config)))
+                dev_uuid = config.get('uuid')
+                devid = self._createDevice(devclass, config)
+                # store devid in XendConfig for caching reasons
+                if dev_uuid in self.info['devices']:
+                    self.info['devices'][dev_uuid][1]['devid'] = devid
+
 
         if self.image:
             self.image.createDeviceModel()
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/python/xen/xend/server/vscsiif.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/server/vscsiif.py   Thu Jul 03 13:39:06 2008 +0100
@@ -0,0 +1,228 @@
+#============================================================================
+# 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 (C) 2007 FUJITSU Limited
+#                     Based on the blkif.py
+#============================================================================
+
+
+"""Support for VSCSI Devices.
+"""
+import re
+import string
+
+import types
+
+from xen.xend import sxp
+from xen.xend.XendError import VmError
+from xen.xend.XendLogging import log
+
+from xen.xend.server.DevController import DevController, xenbusState
+from xen.xend.xenstore.xstransact import xstransact
+
+class VSCSIController(DevController):
+    """VSCSI Devices.
+    """
+    def __init__(self, vm):
+        """Create a VSCSI Devices.
+        """
+        DevController.__init__(self, vm)
+
+
+    def sxprs(self):
+        """@see DevController.sxprs"""
+        devslist = []
+        for devid in self.deviceIDs():
+            vscsi_devs = self.readBackendList(devid, "vscsi-devs")
+            vscsipath = "vscsi-devs/"
+            devs = []
+            vscsi_config = []
+            for dev in vscsi_devs:
+                devpath = vscsipath + dev
+                backstate = self.readBackend(devid, devpath + '/state')
+                pdev = self.readBackend(devid, devpath + '/p-dev')
+                pdevname = self.readBackend(devid, devpath + '/p-devname')
+                vdev = self.readBackend(devid, devpath + '/v-dev')
+                localdevid = self.readBackend(devid, devpath + '/devid')
+                frontstate = self.readFrontend(devid, devpath + '/state')
+                devs.append(['dev', \
+                                    ['state', backstate], \
+                                    ['devid', localdevid], \
+                                    ['p-dev', pdev], \
+                                    ['p-devname', pdevname], \
+                                    ['v-dev', vdev], \
+                                    ['frontstate', frontstate] ])
+
+            vscsi_config.append(['devs', devs])
+            state = self.readFrontend(devid, 'state')
+            vscsi_config.append(['state', state])
+            backid = self.readFrontend(devid, 'backend-id')
+            vscsi_config.append(['backend-id', backid])
+            backpath = self.readFrontend(devid, 'backend')
+            vscsi_config.append(['backend', backpath])
+
+            devslist.append([devid, vscsi_config])
+
+        return devslist
+
+
+    def getDeviceDetails(self, config):
+        """@see DevController.getDeviceDetails"""
+        back = {}
+        vscsipath = "vscsi-devs/"
+        for vscsi_config in config.get('devs', []):
+            localdevid = self.allocateDeviceID()
+            # vscsi-devs/dev-0
+            devpath = vscsipath + 'dev-%i' % localdevid
+            back[devpath] = ""
+            pdev = vscsi_config.get('p-dev', '')
+            back[devpath + '/p-dev'] = pdev
+            pdevname = vscsi_config.get('p-devname', '')
+            back[devpath + '/p-devname'] = pdevname
+            vdev = vscsi_config.get('v-dev', '')
+            back[devpath + '/v-dev'] = vdev
+            state = vscsi_config.get('state', '')
+            back[devpath + '/state'] = str(xenbusState[state])
+            devid = vscsi_config.get('devid', '')
+            back[devpath + '/devid'] = str(devid)
+
+        back['uuid'] = config.get('uuid','')
+        devid = int(devid)
+        return (devid, back, {})
+
+
+    def readBackendList(self, devid, *args):
+        frontpath = self.frontendPath(devid)
+        backpath = xstransact.Read(frontpath + "/backend")
+        if backpath:
+            paths = map(lambda x: backpath + "/" + x, args)
+            return xstransact.List(*paths)
+
+
+    def getDeviceConfiguration(self, devid, transaction = None):
+        config = DevController.getDeviceConfiguration(self, devid, transaction)
+
+        vscsi_devs = []
+
+        devs = self.readBackendList(devid, "vscsi-devs")
+        vscsipath = "vscsi-devs/"
+        for dev in devs:
+            devpath = vscsipath + dev
+            pdev = self.readBackend(devid, devpath + '/p-dev')
+            pdevname = self.readBackend(devid, devpath + '/p-devname')
+            vdev = self.readBackend(devid, devpath + '/v-dev')
+            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 }
+            vscsi_devs.append(dev_dict)
+
+        config['devs'] = vscsi_devs
+        config['uuid'] = self.readBackend(devid, 'uuid')
+        return config
+
+
+    def configuration(self, devid, transaction = None):
+        """Returns SXPR for devices on domain.
+        @note: we treat this dict especially to convert to
+        SXP because it is not a straight dict of strings."""
+        
+        configDict = self.getDeviceConfiguration(devid, transaction)
+        sxpr = [self.deviceClass]
+
+        # remove devs
+        devs = configDict.pop('devs', [])
+        
+        for dev in devs:
+            dev_sxpr = ['dev']
+            for dev_item in dev.items():
+                dev_sxpr.append(list(dev_item))
+            sxpr.append(dev_sxpr)
+        
+        for key, val in configDict.items():
+            if type(val) == type(list()):
+                for v in val:
+                    sxpr.append([key, v])
+            else:
+                sxpr.append([key, val])
+
+        return sxpr
+
+
+    def reconfigureDevice(self, _, config):
+        """@see DevController.reconfigureDevice"""
+        (devid, back, front) = self.getDeviceDetails(config)
+        devid = int(devid)
+        vscsi_config = config['devs'][0]
+        states = config.get('states', [])
+        uuid = self.readBackend(devid, 'uuid')
+        if states[0] == 'Initialising':
+            back['uuid'] = uuid
+            self.writeBackend(devid, back)
+
+        elif states[0] == 'Closing':
+            found = False
+            devs = self.readBackendList(devid, "vscsi-devs")
+            vscsipath = "vscsi-devs/"
+            vdev = vscsi_config.get('v-dev', '')
+
+            for dev in devs:
+                devpath = vscsipath + dev
+                old_vdev = self.readBackend(devid, devpath + '/v-dev')
+                if vdev == old_vdev:
+                    found = True
+                    self.writeBackend(devid, devpath + '/state', \
+                                    str(xenbusState['Closing']))
+                    break
+
+            if not found:
+                raise VmError("Device %s not connected" % vdev)
+
+        else:
+            raise XendError('Error configuring device invalid state %s'
+                                % state)
+
+        self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring']))
+        return self.readBackend(devid, 'uuid')
+
+
+    def cleanupDevice(self, devid):
+        devs = self.readBackendList(devid, "vscsi-devs")
+        vscsipath = "vscsi-devs/"
+        new_num_devs = 0
+        
+        for dev in devs:
+            new_num_devs = new_num_devs + 1
+            devpath = vscsipath + dev
+            devstate = self.readBackend(devid, devpath + '/state')
+
+            if str(xenbusState['Closed']) == devstate:
+                self.removeBackend(devid, devpath)
+                frontpath = self.frontendPath(devid)
+                xstransact.Remove(frontpath + '/' + devpath)
+                new_num_devs = new_num_devs - 1
+
+            frontpath = self.frontendPath(devid)
+            front_devstate = xstransact.Read(frontpath + '/' + devpath)
+            if front_devstate is not None:
+                if str(xenbusState['Closed']) == front_devstate:
+                    self.removeBackend(devid, devpath)
+                    xstransact.Remove(frontpath + '/' + devpath)
+                    new_num_devs = new_num_devs - 1
+
+        return new_num_devs
+
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/python/xen/xm/create.py     Thu Jul 03 13:39:06 2008 +0100
@@ -33,6 +33,7 @@ import xen.xend.XendClient
 import xen.xend.XendClient
 from xen.xend.XendBootloader import bootloader
 from xen.util import blkif
+from xen.util import vscsi_util
 import xen.util.xsm.xsm as security
 from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
 
@@ -306,6 +307,11 @@ gopts.var('pci', val='BUS:DEV.FUNC',
           use="""Add a PCI device to a domain, using given params (in hex).
          For example 'pci=c0:02.1'.
          The option may be repeated to add more than one pci device.""")
+
+gopts.var('vscsi', val='PDEV,VDEV[,DOM]',
+          fn=append_value, default=[],
+          use="""Add a SCSI device to a domain. The physical device is PDEV,
+          which is exported to the domain as VDEV(X:X:X:X).""")
 
 gopts.var('ioports', val='FROM[-TO]',
           fn=append_value, default=[],
@@ -637,6 +643,73 @@ def configure_pci(config_devs, vals):
     if len(config_pci)>0:
         config_pci.insert(0, 'pci')
         config_devs.append(['device', config_pci])
+
+def vscsi_convert_sxp_to_dict(dev_sxp):
+    dev_dict = {}
+    for opt_val in dev_sxp[1:]:
+        try:
+            opt, val = opt_val
+            dev_dict[opt] = val
+        except TypeError:
+            pass
+    return dev_dict
+
+def vscsi_lookup_devid(devlist, req_devid):
+    if len(devlist) == 0:
+        return 0
+    else:
+        for devid, backend in devlist:
+            if devid == req_devid:
+                return 1
+        return 0
+
+def configure_vscsis(config_devs, vals):
+    """Create the config for vscsis (virtual scsi devices).
+    """
+    devidlist = []
+    config_scsi = []
+    if len(vals.vscsi) == 0:
+        return 0
+
+    scsi_devices = vscsi_util.vscsi_get_scsidevices()
+    for (p_dev, v_dev, backend) in vals.vscsi:
+        tmp = p_dev.split(':')
+        if len(tmp) == 4:
+            (p_hctl, block) = vscsi_util._vscsi_hctl_block(p_dev, scsi_devices)
+        else:
+            (p_hctl, block) = vscsi_util._vscsi_block_scsiid_to_hctl(p_dev, 
scsi_devices)
+
+        if p_hctl == None:
+            raise ValueError("Cannot find device \"%s\"" % p_dev)
+
+        for config in config_scsi:
+            dev = vscsi_convert_sxp_to_dict(config)
+            if dev['v-dev'] == v_dev:
+                raise ValueError('The virtual device "%s" is already defined' 
% v_dev)
+
+        v_hctl = v_dev.split(':')
+        devid = int(v_hctl[0])
+        config_scsi.append(['dev', \
+                        ['state', 'Initialising'], \
+                        ['devid', devid], \
+                        ['p-dev', p_hctl], \
+                        ['p-devname', block], \
+                        ['v-dev', v_dev] ])
+
+        if vscsi_lookup_devid(devidlist, devid) == 0:
+            devidlist.append([devid, backend])
+
+    for devid, backend in devidlist:
+        tmp = []
+        for config in config_scsi:
+            dev = vscsi_convert_sxp_to_dict(config)
+            if dev['devid'] == devid:
+                tmp.append(config)
+
+        tmp.insert(0, 'vscsi')
+        if backend:
+            tmp.append(['backend', backend])
+        config_devs.append(['device', tmp])
 
 def configure_ioports(config_devs, vals):
     """Create the config for legacy i/o ranges.
@@ -829,6 +902,7 @@ def make_config(vals):
     config_devs = []
     configure_disks(config_devs, vals)
     configure_pci(config_devs, vals)
+    configure_vscsis(config_devs, vals)
     configure_ioports(config_devs, vals)
     configure_irq(config_devs, vals)
     configure_vifs(config_devs, vals)
@@ -895,6 +969,25 @@ def preprocess_pci(vals):
             except IndexError:
                 err('Error in PCI slot syntax "%s"'%(pci_dev_str))
     vals.pci = pci
+
+def preprocess_vscsi(vals):
+    if not vals.vscsi: return
+    scsi = []
+    for scsi_str in vals.vscsi:
+        d = scsi_str.split(',')
+        n = len(d)
+        if n == 2:
+            tmp = d[1].split(':')
+            if len(tmp) != 4:
+                err('vscsi syntax error "%s"' % d[1])
+            else:
+                d.append(None)
+        elif n == 3:
+            pass
+        else:
+            err('vscsi syntax error "%s"' % scsi_str)
+        scsi.append(d)
+    vals.vscsi = scsi
 
 def preprocess_ioports(vals):
     if not vals.ioports: return
@@ -1075,6 +1168,7 @@ def preprocess(vals):
 def preprocess(vals):
     preprocess_disk(vals)
     preprocess_pci(vals)
+    preprocess_vscsi(vals)
     preprocess_ioports(vals)
     preprocess_ip(vals)
     preprocess_nfs(vals)
diff -r d90c5e8d4ac2 -r 6ae87b27ccea tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Thu Jul 03 11:32:10 2008 +0100
+++ b/tools/python/xen/xm/main.py       Thu Jul 03 13:39:06 2008 +0100
@@ -37,6 +37,7 @@ from select import select
 from select import select
 import xml.dom.minidom
 from xen.util.blkif import blkdev_name_to_number
+from xen.util import vscsi_util
 
 import warnings
 warnings.filterwarnings('ignore', category=FutureWarning)
@@ -182,6 +183,12 @@ SUBCOMMAND_HELP = {
                         'Remove a domain\'s pass-through pci device.'),
     'pci-list'      :  ('<Domain>',
                         'List pass-through pci devices for a domain.'),
+    'scsi-attach'  :  ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
+                        'Attach a new SCSI device.'),
+    'scsi-detach'  :  ('<Domain> <VirtDevice>',
+                        'Detach a specified SCSI device.'),
+    'scsi-list'    :  ('<Domain> [--long]',
+                        'List all SCSI devices currently attached.'),
 
     # security
 
@@ -348,6 +355,9 @@ device_commands = [
     "pci-attach",
     "pci-detach",
     "pci-list",
+    "scsi-attach",
+    "scsi-detach",
+    "scsi-list",
     ]
 
 vnet_commands = [
@@ -2106,6 +2116,40 @@ def xm_pci_list(args):
             hdr = 1
         print ( fmt_str % x )
 
+def vscsi_convert_sxp_to_dict(dev_sxp):
+    dev_dict = {}
+    for opt_val in dev_sxp[1:]:
+        try:
+            opt, val = opt_val
+            dev_dict[opt] = val
+        except TypeError:
+            pass
+    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')
+
+    if use_long:
+        map(PrettyPrint.prettyprint, devs)
+    else:
+        hdr = 0
+        for x in devs:
+            if hdr == 0:
+                print "%-3s %-3s %-5s  %-10s %-5s %-10s %-4s" \
+                        % ('Idx', 'BE', 'state', 'phy-hctl', 'phy', 
'vir-hctl', 'devstate')
+                hdr = 1
+            ni = parse_dev_info(x[1])
+            ni['idx'] = int(x[0])
+            for dev in x[1][0][1]:
+                mi = vscsi_convert_sxp_to_dict(dev)
+                print "%(idx)-3d %(backend-id)-3d %(state)-5d " % ni,
+                print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s 
%(frontstate)-4s" % mi
+
 def parse_block_configuration(args):
     dom = args[0]
 
@@ -2285,6 +2329,38 @@ def xm_pci_attach(args):
     (dom, pci) = parse_pci_configuration(args, 'Initialising')
     server.xend.domain.device_configure(dom, pci)
 
+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)
+
 def detach(args, deviceClass):
     rm_cfg = True
     dom = args[0]
@@ -2353,6 +2429,27 @@ def xm_pci_detach(args):
     (dom, pci) = parse_pci_configuration(args, 'Closing')
     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)
 
 def xm_vnet_list(args):
     xenapi_unsupported()
@@ -2548,6 +2645,10 @@ commands = {
     "pci-attach": xm_pci_attach,
     "pci-detach": xm_pci_detach,
     "pci-list": xm_pci_list,
+    # vscsi
+    "scsi-attach": xm_scsi_attach,
+    "scsi-detach": xm_scsi_detach,
+    "scsi-list": xm_scsi_list,
     }
 
 ## The commands supported by a separate argument parser in xend.xm.

_______________________________________________
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®.