[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |