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] pvSCSI: xend changes

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] pvSCSI: xend changes
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 04 Jul 2008 08:00:13 -0700
Delivery-date: Fri, 04 Jul 2008 08:00:54 -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 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] pvSCSI: xend changes, Xen patchbot-unstable <=