debuggers.hg
changeset 17997:6ae87b27ccea
pvSCSI: xend changes
Signed-off-by: Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com>
Signed-off-by: Jun Kamada <kama@jp.fujitsu.com>
Signed-off-by: Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com>
Signed-off-by: Jun Kamada <kama@jp.fujitsu.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Thu Jul 03 13:39:06 2008 +0100 (2008-07-03) |
parents | d90c5e8d4ac2 |
children | 1db0b09b290e |
files | tools/examples/vscsi tools/examples/xen-backend.agent tools/examples/xen-backend.rules tools/examples/xmexample.hvm tools/examples/xmexample.vti tools/examples/xmexample1 tools/examples/xmexample2 tools/python/xen/util/vscsi_util.py tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDevices.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/vscsiif.py tools/python/xen/xm/create.py tools/python/xen/xm/main.py |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/examples/vscsi Thu Jul 03 13:39:06 2008 +0100 1.3 @@ -0,0 +1,22 @@ 1.4 +#!/bin/sh 1.5 +# 1.6 +# Copyright (c) 2007, FUJITSU Limited 1.7 +# Based on the block scripts code. 1.8 +# 1.9 + 1.10 +dir=$(dirname "$0") 1.11 +. "$dir/xen-hotplug-common.sh" 1.12 + 1.13 +findCommand "$@" 1.14 + 1.15 +case "$command" in 1.16 + add) 1.17 + success 1.18 + ;; 1.19 + remove) 1.20 + # TODO 1.21 + exit 0 1.22 + ;; 1.23 +esac 1.24 + 1.25 +exit 0
2.1 --- a/tools/examples/xen-backend.agent Thu Jul 03 11:32:10 2008 +0100 2.2 +++ b/tools/examples/xen-backend.agent Thu Jul 03 13:39:06 2008 +0100 2.3 @@ -19,6 +19,9 @@ case "$XENBUS_TYPE" in 2.4 vif) 2.5 [ -n "$script" ] && $script "$ACTION" 2.6 ;; 2.7 + vscsi) 2.8 + /etc/xen/scripts/vscsi "$ACTION" 2.9 + ;; 2.10 esac 2.11 2.12 case "$ACTION" in
3.1 --- a/tools/examples/xen-backend.rules Thu Jul 03 11:32:10 2008 +0100 3.2 +++ b/tools/examples/xen-backend.rules Thu Jul 03 13:39:06 2008 +0100 3.3 @@ -3,6 +3,7 @@ SUBSYSTEM=="xen-backend", KERNEL=="vbd*" 3.4 SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm $env{ACTION}" 3.5 SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script} online" 3.6 SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="offline", RUN+="$env{script} offline" 3.7 +SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi $env{ACTION}" 3.8 SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/etc/xen/scripts/xen-hotplug-cleanup" 3.9 KERNEL=="evtchn", NAME="xen/%k" 3.10 KERNEL=="blktap[0-9]*", NAME="xen/%k"
4.1 --- a/tools/examples/xmexample.hvm Thu Jul 03 11:32:10 2008 +0100 4.2 +++ b/tools/examples/xmexample.hvm Thu Jul 03 13:39:06 2008 +0100 4.3 @@ -282,3 +282,26 @@ serial='pty' 4.4 # '0' -> the bit must be '0' 4.5 # 'x' -> we don't care (do not check) 4.6 # 's' -> the bit must be the same as on the host that started this VM 4.7 + 4.8 + 4.9 +#----------------------------------------------------------------------------- 4.10 +# Configure PVSCSI devices: 4.11 +# 4.12 +#vscsi=[ 'PDEV, VDEV' ] 4.13 +# 4.14 +# PDEV gives physical SCSI device to be attached to specified guest 4.15 +# domain by one of the following identifier format. 4.16 +# - XX:XX:XX:XX (4-tuples with decimal notation which shows 4.17 +# "host:channel:target:lun") 4.18 +# - /dev/sdxx or sdx 4.19 +# - /dev/stxx or stx 4.20 +# - /dev/sgxx or sgx 4.21 +# - result of 'scsi_id -gu -s'. 4.22 +# ex. # scsi_id -gu -s /block/sdb 4.23 +# 36000b5d0006a0000006a0257004c0000 4.24 +# 4.25 +# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as 4.26 +# which the specified guest domain recognize. 4.27 +# 4.28 + 4.29 +#vscsi = [ '/dev/sdx, 0:0:0:0' ]
5.1 --- a/tools/examples/xmexample.vti Thu Jul 03 11:32:10 2008 +0100 5.2 +++ b/tools/examples/xmexample.vti Thu Jul 03 13:39:06 2008 +0100 5.3 @@ -161,3 +161,25 @@ serial='pty' 5.4 # 'windows' - All Windows variants (Windows Server 2003/2008) 5.5 # 5.6 #guest_os_type='default' 5.7 + 5.8 +#----------------------------------------------------------------------------- 5.9 +# Configure PVSCSI devices: 5.10 +# 5.11 +#vscsi=[ 'PDEV, VDEV' ] 5.12 +# 5.13 +# PDEV gives physical SCSI device to be attached to specified guest 5.14 +# domain by one of the following identifier format. 5.15 +# - XX:XX:XX:XX (4-tuples with decimal notation which shows 5.16 +# "host:channel:target:lun") 5.17 +# - /dev/sdxx or sdx 5.18 +# - /dev/stxx or stx 5.19 +# - /dev/sgxx or sgx 5.20 +# - result of 'scsi_id -gu -s'. 5.21 +# ex. # scsi_id -gu -s /block/sdb 5.22 +# 36000b5d0006a0000006a0257004c0000 5.23 +# 5.24 +# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as 5.25 +# which the specified guest domain recognize. 5.26 +# 5.27 + 5.28 +#vscsi = [ '/dev/sdx, 0:0:0:0' ]
6.1 --- a/tools/examples/xmexample1 Thu Jul 03 11:32:10 2008 +0100 6.2 +++ b/tools/examples/xmexample1 Thu Jul 03 13:39:06 2008 +0100 6.3 @@ -185,4 +185,27 @@ extra = "4" 6.4 #on_reboot = 'restart' 6.5 #on_crash = 'restart' 6.6 6.7 +#----------------------------------------------------------------------------- 6.8 +# Configure PVSCSI devices: 6.9 +# 6.10 +#vscsi=[ 'PDEV, VDEV' ] 6.11 +# 6.12 +# PDEV gives physical SCSI device to be attached to specified guest 6.13 +# domain by one of the following identifier format. 6.14 +# - XX:XX:XX:XX (4-tuples with decimal notation which shows 6.15 +# "host:channel:target:lun") 6.16 +# - /dev/sdxx or sdx 6.17 +# - /dev/stxx or stx 6.18 +# - /dev/sgxx or sgx 6.19 +# - result of 'scsi_id -gu -s'. 6.20 +# ex. # scsi_id -gu -s /block/sdb 6.21 +# 36000b5d0006a0000006a0257004c0000 6.22 +# 6.23 +# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as 6.24 +# which the specified guest domain recognize. 6.25 +# 6.26 + 6.27 +#vscsi = [ '/dev/sdx, 0:0:0:0' ] 6.28 + 6.29 #============================================================================ 6.30 +
7.1 --- a/tools/examples/xmexample2 Thu Jul 03 11:32:10 2008 +0100 7.2 +++ b/tools/examples/xmexample2 Thu Jul 03 13:39:06 2008 +0100 7.3 @@ -221,4 +221,26 @@ extra = "4 VMID=%d usr=/dev/sda6" % vmid 7.4 #on_reboot = 'restart' 7.5 #on_crash = 'restart' 7.6 7.7 +#----------------------------------------------------------------------------- 7.8 +# Configure PVSCSI devices: 7.9 +# 7.10 +#vscsi=[ 'PDEV, VDEV' ] 7.11 +# 7.12 +# PDEV gives physical SCSI device to be attached to specified guest 7.13 +# domain by one of the following identifier format. 7.14 +# - XX:XX:XX:XX (4-tuples with decimal notation which shows 7.15 +# "host:channel:target:lun") 7.16 +# - /dev/sdxx or sdx 7.17 +# - /dev/stxx or stx 7.18 +# - /dev/sgxx or sgx 7.19 +# - result of 'scsi_id -gu -s'. 7.20 +# ex. # scsi_id -gu -s /block/sdb 7.21 +# 36000b5d0006a0000006a0257004c0000 7.22 +# 7.23 +# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as 7.24 +# which the specified guest domain recognize. 7.25 +# 7.26 + 7.27 +#vscsi = [ '/dev/sdx, 0:0:0:0' ] 7.28 + 7.29 #============================================================================
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/tools/python/xen/util/vscsi_util.py Thu Jul 03 13:39:06 2008 +0100 8.3 @@ -0,0 +1,133 @@ 8.4 +#!/usr/bin/env python 8.5 +# -*- mode: python; -*- 8.6 + 8.7 +#============================================================================ 8.8 +# This library is free software; you can redistribute it and/or 8.9 +# modify it under the terms of version 2.1 of the GNU Lesser General Public 8.10 +# License as published by the Free Software Foundation. 8.11 +# 8.12 +# This library is distributed in the hope that it will be useful, 8.13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of 8.14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8.15 +# Lesser General Public License for more details. 8.16 +# 8.17 +# You should have received a copy of the GNU Lesser General Public 8.18 +# License along with this library; if not, write to the Free Software 8.19 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 8.20 +#============================================================================ 8.21 +# Copyright (C) 2008 FUJITSU Limited 8.22 +# Based on the blkif.py 8.23 +#============================================================================ 8.24 + 8.25 + 8.26 +"""Support for VSCSI Devices. 8.27 +""" 8.28 +import os 8.29 +import sys 8.30 +import re 8.31 +import string 8.32 + 8.33 +def _vscsi_hctl_block(name, scsi_devices): 8.34 + """ block-device name is convert into hctl. (e.g., '/dev/sda', 8.35 + '0:0:0:0')""" 8.36 + try: 8.37 + search = re.compile(r'' + name + '$', re.DOTALL) 8.38 + except Exception, e: 8.39 + raise VmError("vscsi: invalid expression. " + str(e)) 8.40 + chk = 0 8.41 + for hctl, block, sg, scsi_id in scsi_devices: 8.42 + if search.match(hctl): 8.43 + chk = 1 8.44 + break 8.45 + 8.46 + if chk: 8.47 + return (hctl, block) 8.48 + else: 8.49 + return (None, None) 8.50 + 8.51 + 8.52 +def _vscsi_block_scsiid_to_hctl(phyname, scsi_devices): 8.53 + """ block-device name is convert into hctl. (e.g., '/dev/sda', 8.54 + '0:0:0:0')""" 8.55 + 8.56 + if re.match('/dev/sd[a-z]+([1-9]|1[0-5])?$', phyname): 8.57 + # sd driver 8.58 + name = re.sub('(^/dev/)|([1-9]|1[0-5])?$', '', phyname) 8.59 + elif re.match('/dev/sg[0-9]+$', phyname): 8.60 + # sg driver 8.61 + name = re.sub('^/dev/', '', phyname) 8.62 + elif re.match('/dev/st[0-9]+$', phyname): 8.63 + # st driver 8.64 + name = re.sub('^/dev/', '', phyname) 8.65 + else: 8.66 + # scsi_id -gu 8.67 + name = phyname 8.68 + 8.69 + chk = 0 8.70 + for hctl, block, sg, scsi_id in scsi_devices: 8.71 + if block == name: 8.72 + chk = 1 8.73 + break 8.74 + elif sg == name: 8.75 + chk = 1 8.76 + break 8.77 + elif scsi_id == name: 8.78 + chk = 1 8.79 + break 8.80 + 8.81 + if chk: 8.82 + return (hctl, block) 8.83 + else: 8.84 + return (None, None) 8.85 + 8.86 + 8.87 +def vscsi_get_scsidevices(): 8.88 + """ get all scsi devices""" 8.89 + 8.90 + SERCH_SCSI_PATH = "/sys/bus/scsi/devices" 8.91 + devices = [] 8.92 + 8.93 + for dirpath, dirnames, files in os.walk(SERCH_SCSI_PATH): 8.94 + for hctl in dirnames: 8.95 + paths = os.path.join(dirpath, hctl) 8.96 + block = "-" 8.97 + for f in os.listdir(paths): 8.98 + if re.match('^block', f): 8.99 + os.chdir(os.path.join(paths, f)) 8.100 + block = os.path.basename(os.getcwd()) 8.101 + elif re.match('^tape', f): 8.102 + os.chdir(os.path.join(paths, f)) 8.103 + block = os.path.basename(os.getcwd()) 8.104 + elif re.match('^scsi_changer', f): 8.105 + os.chdir(os.path.join(paths, f)) 8.106 + block = os.path.basename(os.getcwd()) 8.107 + elif re.match('^onstream_tape', f): 8.108 + os.chdir(os.path.join(paths, f)) 8.109 + block = os.path.basename(os.getcwd()) 8.110 + 8.111 + if re.match('^scsi_generic', f): 8.112 + os.chdir(os.path.join(paths, f)) 8.113 + sg = os.path.basename(os.getcwd()) 8.114 + lines = os.popen('/sbin/scsi_id -gu -s /class/scsi_generic/' + sg).read().split() 8.115 + if len(lines) == 0: 8.116 + scsi_id = '-' 8.117 + else: 8.118 + scsi_id = lines[0] 8.119 + 8.120 + devices.append([hctl, block, sg, scsi_id]) 8.121 + 8.122 + return devices 8.123 + 8.124 + 8.125 +def vscsi_search_hctl_and_block(device): 8.126 + 8.127 + scsi_devices = vscsi_get_scsidevices() 8.128 + 8.129 + tmp = device.split(':') 8.130 + if len(tmp) == 4: 8.131 + (hctl, block) = _vscsi_hctl_block(device, scsi_devices) 8.132 + else: 8.133 + (hctl, block) = _vscsi_block_scsiid_to_hctl(device, scsi_devices) 8.134 + 8.135 + return (hctl, block) 8.136 +
9.1 --- a/tools/python/xen/xend/XendConfig.py Thu Jul 03 11:32:10 2008 +0100 9.2 +++ b/tools/python/xen/xend/XendConfig.py Thu Jul 03 13:39:06 2008 +0100 9.3 @@ -1216,7 +1216,7 @@ class XendConfig(dict): 9.4 dev_type = sxp.name(config) 9.5 dev_info = {} 9.6 9.7 - if dev_type == 'pci': 9.8 + if dev_type == 'pci' or dev_type == 'vscsi': 9.9 pci_devs_uuid = sxp.child_value(config, 'uuid', 9.10 uuid.createString()) 9.11 9.12 @@ -1625,7 +1625,7 @@ class XendConfig(dict): 9.13 9.14 dev_type, dev_info = self['devices'][dev_uuid] 9.15 9.16 - if dev_type == 'pci': # Special case for pci 9.17 + if dev_type == 'pci' or dev_type == 'vscsi': # Special case for pci 9.18 pci_dict = self.pci_convert_sxp_to_dict(config) 9.19 pci_devs = pci_dict['devs'] 9.20 9.21 @@ -1739,8 +1739,11 @@ class XendConfig(dict): 9.22 ordered_refs = self.ordered_device_refs(target = target) 9.23 for dev_uuid in ordered_refs: 9.24 dev_type, dev_info = target['devices'][dev_uuid] 9.25 - if dev_type == 'pci': # special case for pci devices 9.26 - sxpr = ['pci', ['uuid', dev_info['uuid']]] 9.27 + if dev_type == 'pci' or dev_type == 'vscsi': # special case for pci devices 9.28 + if dev_type == 'pci': 9.29 + sxpr = ['pci', ['uuid', dev_info['uuid']]] 9.30 + elif dev_type == 'vscsi': 9.31 + sxpr = ['vscsi', ['uuid', dev_info['uuid']]] 9.32 for pci_dev_info in dev_info['devs']: 9.33 pci_dev_sxpr = ['dev'] 9.34 for opt, val in pci_dev_info.items():
10.1 --- a/tools/python/xen/xend/XendDevices.py Thu Jul 03 11:32:10 2008 +0100 10.2 +++ b/tools/python/xen/xend/XendDevices.py Thu Jul 03 13:39:06 2008 +0100 10.3 @@ -19,7 +19,7 @@ 10.4 # A collection of DevControllers 10.5 # 10.6 10.7 -from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif 10.8 +from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, vscsiif 10.9 from xen.xend.server.BlktapController import BlktapController 10.10 from xen.xend.server.ConsoleController import ConsoleController 10.11 10.12 @@ -45,6 +45,7 @@ class XendDevices: 10.13 'vfb': vfbif.VfbifController, 10.14 'vkbd': vfbif.VkbdifController, 10.15 'console': ConsoleController, 10.16 + 'vscsi': vscsiif.VSCSIController, 10.17 } 10.18 10.19 #@classmethod
11.1 --- a/tools/python/xen/xend/XendDomainInfo.py Thu Jul 03 11:32:10 2008 +0100 11.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Jul 03 13:39:06 2008 +0100 11.3 @@ -750,6 +750,52 @@ class XendDomainInfo: 11.4 11.5 return True 11.6 11.7 + def vscsi_device_configure(self, dev_sxp): 11.8 + """Configure an existing vscsi device. 11.9 + quoted pci funciton 11.10 + """ 11.11 + dev_class = sxp.name(dev_sxp) 11.12 + if dev_class != 'vscsi': 11.13 + return False 11.14 + 11.15 + dev_config = self.pci_convert_sxp_to_dict(dev_sxp) 11.16 + dev = dev_config['devs'][0] 11.17 + req_devid = sxp.child_value(dev_sxp, 'devid') 11.18 + req_devid = int(req_devid) 11.19 + existing_dev_info = self._getDeviceInfo_vscsi(req_devid, dev['v-dev']) 11.20 + state = sxp.child_value(dev_sxp, 'state') 11.21 + 11.22 + if state == 'Initialising': 11.23 + # new create 11.24 + # If request devid does not exist, create and exit. 11.25 + if existing_dev_info is None: 11.26 + self.device_create(dev_sxp) 11.27 + return True 11.28 + elif existing_dev_info == "exists": 11.29 + raise XendError("The virtual device %s is already defined" % dev['v-dev']) 11.30 + 11.31 + elif state == 'Closing': 11.32 + if existing_dev_info is None: 11.33 + raise XendError("Cannot detach vscsi device does not exist") 11.34 + 11.35 + # use DevController.reconfigureDevice to change device config 11.36 + dev_control = self.getDeviceController(dev_class) 11.37 + dev_uuid = dev_control.reconfigureDevice(req_devid, dev_config) 11.38 + dev_control.waitForDevice_reconfigure(req_devid) 11.39 + num_devs = dev_control.cleanupDevice(req_devid) 11.40 + 11.41 + # update XendConfig with new device info 11.42 + if dev_uuid: 11.43 + new_dev_sxp = dev_control.configuration(req_devid) 11.44 + self.info.device_update(dev_uuid, new_dev_sxp) 11.45 + 11.46 + # If there is no device left, destroy vscsi and remove config. 11.47 + if num_devs == 0: 11.48 + self.destroyDevice('vscsi', req_devid) 11.49 + del self.info['devices'][dev_uuid] 11.50 + 11.51 + return True 11.52 + 11.53 def device_configure(self, dev_sxp, devid = None): 11.54 """Configure an existing device. 11.55 11.56 @@ -768,6 +814,9 @@ class XendDomainInfo: 11.57 if dev_class == 'pci': 11.58 return self.pci_device_configure(dev_sxp) 11.59 11.60 + if dev_class == 'vscsi': 11.61 + return self.vscsi_device_configure(dev_sxp) 11.62 + 11.63 for opt_val in dev_sxp[1:]: 11.64 try: 11.65 dev_config[opt_val[0]] = opt_val[1] 11.66 @@ -942,6 +991,25 @@ class XendDomainInfo: 11.67 return dev_info 11.68 return None 11.69 11.70 + def _getDeviceInfo_vscsi(self, devid, vdev): 11.71 + devid = int(devid) 11.72 + for dev_type, dev_info in self.info.all_devices_sxpr(): 11.73 + if dev_type != 'vscsi': 11.74 + continue 11.75 + existing_dev_uuid = sxp.child_value(dev_info, 'uuid') 11.76 + existing_conf = self.info['devices'][existing_dev_uuid][1] 11.77 + existing_dev = existing_conf['devs'][0] 11.78 + existing_devid = int(existing_dev['devid']) 11.79 + existing_vdev = existing_dev['v-dev'] 11.80 + 11.81 + if vdev == existing_vdev: 11.82 + return "exists" 11.83 + 11.84 + if devid == existing_devid: 11.85 + return dev_info 11.86 + 11.87 + return None 11.88 + 11.89 def setMemoryTarget(self, target): 11.90 """Set the memory target of this domain. 11.91 @param target: In MiB. 11.92 @@ -1811,10 +1879,12 @@ class XendDomainInfo: 11.93 if self.image: 11.94 self.image.prepareEnvironment() 11.95 11.96 + vscsi_uuidlist = {} 11.97 + vscsi_devidlist = [] 11.98 ordered_refs = self.info.ordered_device_refs() 11.99 for dev_uuid in ordered_refs: 11.100 devclass, config = self.info['devices'][dev_uuid] 11.101 - if devclass in XendDevices.valid_devices(): 11.102 + if devclass in XendDevices.valid_devices() and devclass != 'vscsi': 11.103 log.info("createDevice: %s : %s" % (devclass, scrub_password(config))) 11.104 dev_uuid = config.get('uuid') 11.105 devid = self._createDevice(devclass, config) 11.106 @@ -1823,6 +1893,27 @@ class XendDomainInfo: 11.107 if dev_uuid in self.info['devices']: 11.108 self.info['devices'][dev_uuid][1]['devid'] = devid 11.109 11.110 + elif devclass == 'vscsi': 11.111 + vscsi_config = config.get('devs', [])[0] 11.112 + devid = vscsi_config.get('devid', '') 11.113 + dev_uuid = config.get('uuid') 11.114 + vscsi_uuidlist[devid] = dev_uuid 11.115 + vscsi_devidlist.append(devid) 11.116 + 11.117 + #It is necessary to sorted it for /dev/sdxx in guest. 11.118 + if len(vscsi_uuidlist) > 0: 11.119 + vscsi_devidlist.sort() 11.120 + for vscsiid in vscsi_devidlist: 11.121 + dev_uuid = vscsi_uuidlist[vscsiid] 11.122 + devclass, config = self.info['devices'][dev_uuid] 11.123 + log.info("createDevice: %s : %s" % (devclass, scrub_password(config))) 11.124 + dev_uuid = config.get('uuid') 11.125 + devid = self._createDevice(devclass, config) 11.126 + # store devid in XendConfig for caching reasons 11.127 + if dev_uuid in self.info['devices']: 11.128 + self.info['devices'][dev_uuid][1]['devid'] = devid 11.129 + 11.130 + 11.131 if self.image: 11.132 self.image.createDeviceModel() 11.133
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/tools/python/xen/xend/server/vscsiif.py Thu Jul 03 13:39:06 2008 +0100 12.3 @@ -0,0 +1,228 @@ 12.4 +#============================================================================ 12.5 +# This library is free software; you can redistribute it and/or 12.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public 12.7 +# License as published by the Free Software Foundation. 12.8 +# 12.9 +# This library is distributed in the hope that it will be useful, 12.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of 12.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12.12 +# Lesser General Public License for more details. 12.13 +# 12.14 +# You should have received a copy of the GNU Lesser General Public 12.15 +# License along with this library; if not, write to the Free Software 12.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 12.17 +#============================================================================ 12.18 +# Copyright (C) 2007 FUJITSU Limited 12.19 +# Based on the blkif.py 12.20 +#============================================================================ 12.21 + 12.22 + 12.23 +"""Support for VSCSI Devices. 12.24 +""" 12.25 +import re 12.26 +import string 12.27 + 12.28 +import types 12.29 + 12.30 +from xen.xend import sxp 12.31 +from xen.xend.XendError import VmError 12.32 +from xen.xend.XendLogging import log 12.33 + 12.34 +from xen.xend.server.DevController import DevController, xenbusState 12.35 +from xen.xend.xenstore.xstransact import xstransact 12.36 + 12.37 +class VSCSIController(DevController): 12.38 + """VSCSI Devices. 12.39 + """ 12.40 + def __init__(self, vm): 12.41 + """Create a VSCSI Devices. 12.42 + """ 12.43 + DevController.__init__(self, vm) 12.44 + 12.45 + 12.46 + def sxprs(self): 12.47 + """@see DevController.sxprs""" 12.48 + devslist = [] 12.49 + for devid in self.deviceIDs(): 12.50 + vscsi_devs = self.readBackendList(devid, "vscsi-devs") 12.51 + vscsipath = "vscsi-devs/" 12.52 + devs = [] 12.53 + vscsi_config = [] 12.54 + for dev in vscsi_devs: 12.55 + devpath = vscsipath + dev 12.56 + backstate = self.readBackend(devid, devpath + '/state') 12.57 + pdev = self.readBackend(devid, devpath + '/p-dev') 12.58 + pdevname = self.readBackend(devid, devpath + '/p-devname') 12.59 + vdev = self.readBackend(devid, devpath + '/v-dev') 12.60 + localdevid = self.readBackend(devid, devpath + '/devid') 12.61 + frontstate = self.readFrontend(devid, devpath + '/state') 12.62 + devs.append(['dev', \ 12.63 + ['state', backstate], \ 12.64 + ['devid', localdevid], \ 12.65 + ['p-dev', pdev], \ 12.66 + ['p-devname', pdevname], \ 12.67 + ['v-dev', vdev], \ 12.68 + ['frontstate', frontstate] ]) 12.69 + 12.70 + vscsi_config.append(['devs', devs]) 12.71 + state = self.readFrontend(devid, 'state') 12.72 + vscsi_config.append(['state', state]) 12.73 + backid = self.readFrontend(devid, 'backend-id') 12.74 + vscsi_config.append(['backend-id', backid]) 12.75 + backpath = self.readFrontend(devid, 'backend') 12.76 + vscsi_config.append(['backend', backpath]) 12.77 + 12.78 + devslist.append([devid, vscsi_config]) 12.79 + 12.80 + return devslist 12.81 + 12.82 + 12.83 + def getDeviceDetails(self, config): 12.84 + """@see DevController.getDeviceDetails""" 12.85 + back = {} 12.86 + vscsipath = "vscsi-devs/" 12.87 + for vscsi_config in config.get('devs', []): 12.88 + localdevid = self.allocateDeviceID() 12.89 + # vscsi-devs/dev-0 12.90 + devpath = vscsipath + 'dev-%i' % localdevid 12.91 + back[devpath] = "" 12.92 + pdev = vscsi_config.get('p-dev', '') 12.93 + back[devpath + '/p-dev'] = pdev 12.94 + pdevname = vscsi_config.get('p-devname', '') 12.95 + back[devpath + '/p-devname'] = pdevname 12.96 + vdev = vscsi_config.get('v-dev', '') 12.97 + back[devpath + '/v-dev'] = vdev 12.98 + state = vscsi_config.get('state', '') 12.99 + back[devpath + '/state'] = str(xenbusState[state]) 12.100 + devid = vscsi_config.get('devid', '') 12.101 + back[devpath + '/devid'] = str(devid) 12.102 + 12.103 + back['uuid'] = config.get('uuid','') 12.104 + devid = int(devid) 12.105 + return (devid, back, {}) 12.106 + 12.107 + 12.108 + def readBackendList(self, devid, *args): 12.109 + frontpath = self.frontendPath(devid) 12.110 + backpath = xstransact.Read(frontpath + "/backend") 12.111 + if backpath: 12.112 + paths = map(lambda x: backpath + "/" + x, args) 12.113 + return xstransact.List(*paths) 12.114 + 12.115 + 12.116 + def getDeviceConfiguration(self, devid, transaction = None): 12.117 + config = DevController.getDeviceConfiguration(self, devid, transaction) 12.118 + 12.119 + vscsi_devs = [] 12.120 + 12.121 + devs = self.readBackendList(devid, "vscsi-devs") 12.122 + vscsipath = "vscsi-devs/" 12.123 + for dev in devs: 12.124 + devpath = vscsipath + dev 12.125 + pdev = self.readBackend(devid, devpath + '/p-dev') 12.126 + pdevname = self.readBackend(devid, devpath + '/p-devname') 12.127 + vdev = self.readBackend(devid, devpath + '/v-dev') 12.128 + state = self.readBackend(devid, devpath + '/state') 12.129 + localdevid = self.readBackend(devid, devpath + '/devid') 12.130 + dev_dict = {'p-dev': pdev, 12.131 + 'p-devname': pdevname, 12.132 + 'v-dev': pdevname, 12.133 + 'state': state, 12.134 + 'devid': localdevid } 12.135 + vscsi_devs.append(dev_dict) 12.136 + 12.137 + config['devs'] = vscsi_devs 12.138 + config['uuid'] = self.readBackend(devid, 'uuid') 12.139 + return config 12.140 + 12.141 + 12.142 + def configuration(self, devid, transaction = None): 12.143 + """Returns SXPR for devices on domain. 12.144 + @note: we treat this dict especially to convert to 12.145 + SXP because it is not a straight dict of strings.""" 12.146 + 12.147 + configDict = self.getDeviceConfiguration(devid, transaction) 12.148 + sxpr = [self.deviceClass] 12.149 + 12.150 + # remove devs 12.151 + devs = configDict.pop('devs', []) 12.152 + 12.153 + for dev in devs: 12.154 + dev_sxpr = ['dev'] 12.155 + for dev_item in dev.items(): 12.156 + dev_sxpr.append(list(dev_item)) 12.157 + sxpr.append(dev_sxpr) 12.158 + 12.159 + for key, val in configDict.items(): 12.160 + if type(val) == type(list()): 12.161 + for v in val: 12.162 + sxpr.append([key, v]) 12.163 + else: 12.164 + sxpr.append([key, val]) 12.165 + 12.166 + return sxpr 12.167 + 12.168 + 12.169 + def reconfigureDevice(self, _, config): 12.170 + """@see DevController.reconfigureDevice""" 12.171 + (devid, back, front) = self.getDeviceDetails(config) 12.172 + devid = int(devid) 12.173 + vscsi_config = config['devs'][0] 12.174 + states = config.get('states', []) 12.175 + uuid = self.readBackend(devid, 'uuid') 12.176 + if states[0] == 'Initialising': 12.177 + back['uuid'] = uuid 12.178 + self.writeBackend(devid, back) 12.179 + 12.180 + elif states[0] == 'Closing': 12.181 + found = False 12.182 + devs = self.readBackendList(devid, "vscsi-devs") 12.183 + vscsipath = "vscsi-devs/" 12.184 + vdev = vscsi_config.get('v-dev', '') 12.185 + 12.186 + for dev in devs: 12.187 + devpath = vscsipath + dev 12.188 + old_vdev = self.readBackend(devid, devpath + '/v-dev') 12.189 + if vdev == old_vdev: 12.190 + found = True 12.191 + self.writeBackend(devid, devpath + '/state', \ 12.192 + str(xenbusState['Closing'])) 12.193 + break 12.194 + 12.195 + if not found: 12.196 + raise VmError("Device %s not connected" % vdev) 12.197 + 12.198 + else: 12.199 + raise XendError('Error configuring device invalid state %s' 12.200 + % state) 12.201 + 12.202 + self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring'])) 12.203 + return self.readBackend(devid, 'uuid') 12.204 + 12.205 + 12.206 + def cleanupDevice(self, devid): 12.207 + devs = self.readBackendList(devid, "vscsi-devs") 12.208 + vscsipath = "vscsi-devs/" 12.209 + new_num_devs = 0 12.210 + 12.211 + for dev in devs: 12.212 + new_num_devs = new_num_devs + 1 12.213 + devpath = vscsipath + dev 12.214 + devstate = self.readBackend(devid, devpath + '/state') 12.215 + 12.216 + if str(xenbusState['Closed']) == devstate: 12.217 + self.removeBackend(devid, devpath) 12.218 + frontpath = self.frontendPath(devid) 12.219 + xstransact.Remove(frontpath + '/' + devpath) 12.220 + new_num_devs = new_num_devs - 1 12.221 + 12.222 + frontpath = self.frontendPath(devid) 12.223 + front_devstate = xstransact.Read(frontpath + '/' + devpath) 12.224 + if front_devstate is not None: 12.225 + if str(xenbusState['Closed']) == front_devstate: 12.226 + self.removeBackend(devid, devpath) 12.227 + xstransact.Remove(frontpath + '/' + devpath) 12.228 + new_num_devs = new_num_devs - 1 12.229 + 12.230 + return new_num_devs 12.231 +
13.1 --- a/tools/python/xen/xm/create.py Thu Jul 03 11:32:10 2008 +0100 13.2 +++ b/tools/python/xen/xm/create.py Thu Jul 03 13:39:06 2008 +0100 13.3 @@ -33,6 +33,7 @@ from xen.xend import osdep 13.4 import xen.xend.XendClient 13.5 from xen.xend.XendBootloader import bootloader 13.6 from xen.util import blkif 13.7 +from xen.util import vscsi_util 13.8 import xen.util.xsm.xsm as security 13.9 from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm 13.10 13.11 @@ -307,6 +308,11 @@ gopts.var('pci', val='BUS:DEV.FUNC', 13.12 For example 'pci=c0:02.1'. 13.13 The option may be repeated to add more than one pci device.""") 13.14 13.15 +gopts.var('vscsi', val='PDEV,VDEV[,DOM]', 13.16 + fn=append_value, default=[], 13.17 + use="""Add a SCSI device to a domain. The physical device is PDEV, 13.18 + which is exported to the domain as VDEV(X:X:X:X).""") 13.19 + 13.20 gopts.var('ioports', val='FROM[-TO]', 13.21 fn=append_value, default=[], 13.22 use="""Add a legacy I/O range to a domain, using given params (in hex). 13.23 @@ -638,6 +644,73 @@ def configure_pci(config_devs, vals): 13.24 config_pci.insert(0, 'pci') 13.25 config_devs.append(['device', config_pci]) 13.26 13.27 +def vscsi_convert_sxp_to_dict(dev_sxp): 13.28 + dev_dict = {} 13.29 + for opt_val in dev_sxp[1:]: 13.30 + try: 13.31 + opt, val = opt_val 13.32 + dev_dict[opt] = val 13.33 + except TypeError: 13.34 + pass 13.35 + return dev_dict 13.36 + 13.37 +def vscsi_lookup_devid(devlist, req_devid): 13.38 + if len(devlist) == 0: 13.39 + return 0 13.40 + else: 13.41 + for devid, backend in devlist: 13.42 + if devid == req_devid: 13.43 + return 1 13.44 + return 0 13.45 + 13.46 +def configure_vscsis(config_devs, vals): 13.47 + """Create the config for vscsis (virtual scsi devices). 13.48 + """ 13.49 + devidlist = [] 13.50 + config_scsi = [] 13.51 + if len(vals.vscsi) == 0: 13.52 + return 0 13.53 + 13.54 + scsi_devices = vscsi_util.vscsi_get_scsidevices() 13.55 + for (p_dev, v_dev, backend) in vals.vscsi: 13.56 + tmp = p_dev.split(':') 13.57 + if len(tmp) == 4: 13.58 + (p_hctl, block) = vscsi_util._vscsi_hctl_block(p_dev, scsi_devices) 13.59 + else: 13.60 + (p_hctl, block) = vscsi_util._vscsi_block_scsiid_to_hctl(p_dev, scsi_devices) 13.61 + 13.62 + if p_hctl == None: 13.63 + raise ValueError("Cannot find device \"%s\"" % p_dev) 13.64 + 13.65 + for config in config_scsi: 13.66 + dev = vscsi_convert_sxp_to_dict(config) 13.67 + if dev['v-dev'] == v_dev: 13.68 + raise ValueError('The virtual device "%s" is already defined' % v_dev) 13.69 + 13.70 + v_hctl = v_dev.split(':') 13.71 + devid = int(v_hctl[0]) 13.72 + config_scsi.append(['dev', \ 13.73 + ['state', 'Initialising'], \ 13.74 + ['devid', devid], \ 13.75 + ['p-dev', p_hctl], \ 13.76 + ['p-devname', block], \ 13.77 + ['v-dev', v_dev] ]) 13.78 + 13.79 + if vscsi_lookup_devid(devidlist, devid) == 0: 13.80 + devidlist.append([devid, backend]) 13.81 + 13.82 + for devid, backend in devidlist: 13.83 + tmp = [] 13.84 + for config in config_scsi: 13.85 + dev = vscsi_convert_sxp_to_dict(config) 13.86 + if dev['devid'] == devid: 13.87 + tmp.append(config) 13.88 + 13.89 + tmp.insert(0, 'vscsi') 13.90 + if backend: 13.91 + tmp.append(['backend', backend]) 13.92 + config_devs.append(['device', tmp]) 13.93 + 13.94 def configure_ioports(config_devs, vals): 13.95 """Create the config for legacy i/o ranges. 13.96 """ 13.97 @@ -829,6 +902,7 @@ def make_config(vals): 13.98 config_devs = [] 13.99 configure_disks(config_devs, vals) 13.100 configure_pci(config_devs, vals) 13.101 + configure_vscsis(config_devs, vals) 13.102 configure_ioports(config_devs, vals) 13.103 configure_irq(config_devs, vals) 13.104 configure_vifs(config_devs, vals) 13.105 @@ -896,6 +970,25 @@ def preprocess_pci(vals): 13.106 err('Error in PCI slot syntax "%s"'%(pci_dev_str)) 13.107 vals.pci = pci 13.108 13.109 +def preprocess_vscsi(vals): 13.110 + if not vals.vscsi: return 13.111 + scsi = [] 13.112 + for scsi_str in vals.vscsi: 13.113 + d = scsi_str.split(',') 13.114 + n = len(d) 13.115 + if n == 2: 13.116 + tmp = d[1].split(':') 13.117 + if len(tmp) != 4: 13.118 + err('vscsi syntax error "%s"' % d[1]) 13.119 + else: 13.120 + d.append(None) 13.121 + elif n == 3: 13.122 + pass 13.123 + else: 13.124 + err('vscsi syntax error "%s"' % scsi_str) 13.125 + scsi.append(d) 13.126 + vals.vscsi = scsi 13.127 + 13.128 def preprocess_ioports(vals): 13.129 if not vals.ioports: return 13.130 ioports = [] 13.131 @@ -1075,6 +1168,7 @@ def preprocess_vnc(vals): 13.132 def preprocess(vals): 13.133 preprocess_disk(vals) 13.134 preprocess_pci(vals) 13.135 + preprocess_vscsi(vals) 13.136 preprocess_ioports(vals) 13.137 preprocess_ip(vals) 13.138 preprocess_nfs(vals)
14.1 --- a/tools/python/xen/xm/main.py Thu Jul 03 11:32:10 2008 +0100 14.2 +++ b/tools/python/xen/xm/main.py Thu Jul 03 13:39:06 2008 +0100 14.3 @@ -37,6 +37,7 @@ import datetime 14.4 from select import select 14.5 import xml.dom.minidom 14.6 from xen.util.blkif import blkdev_name_to_number 14.7 +from xen.util import vscsi_util 14.8 14.9 import warnings 14.10 warnings.filterwarnings('ignore', category=FutureWarning) 14.11 @@ -182,6 +183,12 @@ SUBCOMMAND_HELP = { 14.12 'Remove a domain\'s pass-through pci device.'), 14.13 'pci-list' : ('<Domain>', 14.14 'List pass-through pci devices for a domain.'), 14.15 + 'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]', 14.16 + 'Attach a new SCSI device.'), 14.17 + 'scsi-detach' : ('<Domain> <VirtDevice>', 14.18 + 'Detach a specified SCSI device.'), 14.19 + 'scsi-list' : ('<Domain> [--long]', 14.20 + 'List all SCSI devices currently attached.'), 14.21 14.22 # security 14.23 14.24 @@ -348,6 +355,9 @@ device_commands = [ 14.25 "pci-attach", 14.26 "pci-detach", 14.27 "pci-list", 14.28 + "scsi-attach", 14.29 + "scsi-detach", 14.30 + "scsi-list", 14.31 ] 14.32 14.33 vnet_commands = [ 14.34 @@ -2106,6 +2116,40 @@ def xm_pci_list(args): 14.35 hdr = 1 14.36 print ( fmt_str % x ) 14.37 14.38 +def vscsi_convert_sxp_to_dict(dev_sxp): 14.39 + dev_dict = {} 14.40 + for opt_val in dev_sxp[1:]: 14.41 + try: 14.42 + opt, val = opt_val 14.43 + dev_dict[opt] = val 14.44 + except TypeError: 14.45 + pass 14.46 + return dev_dict 14.47 + 14.48 +def xm_scsi_list(args): 14.49 + xenapi_unsupported() 14.50 + (use_long, params) = arg_check_for_resource_list(args, "scsi-list") 14.51 + 14.52 + dom = params[0] 14.53 + 14.54 + devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi') 14.55 + 14.56 + if use_long: 14.57 + map(PrettyPrint.prettyprint, devs) 14.58 + else: 14.59 + hdr = 0 14.60 + for x in devs: 14.61 + if hdr == 0: 14.62 + print "%-3s %-3s %-5s %-10s %-5s %-10s %-4s" \ 14.63 + % ('Idx', 'BE', 'state', 'phy-hctl', 'phy', 'vir-hctl', 'devstate') 14.64 + hdr = 1 14.65 + ni = parse_dev_info(x[1]) 14.66 + ni['idx'] = int(x[0]) 14.67 + for dev in x[1][0][1]: 14.68 + mi = vscsi_convert_sxp_to_dict(dev) 14.69 + print "%(idx)-3d %(backend-id)-3d %(state)-5d " % ni, 14.70 + print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi 14.71 + 14.72 def parse_block_configuration(args): 14.73 dom = args[0] 14.74 14.75 @@ -2285,6 +2329,38 @@ def xm_pci_attach(args): 14.76 (dom, pci) = parse_pci_configuration(args, 'Initialising') 14.77 server.xend.domain.device_configure(dom, pci) 14.78 14.79 +def xm_scsi_attach(args): 14.80 + xenapi_unsupported() 14.81 + 14.82 + arg_check(args, 'scsi-attach', 3, 4) 14.83 + p_devname = args[1] 14.84 + v_dev = args[2] 14.85 + 14.86 + v_hctl = v_dev.split(':') 14.87 + if len(v_hctl) != 4: 14.88 + raise OptionError("Invalid argument: %s" % v_dev) 14.89 + 14.90 + (p_hctl, block) = vscsi_util.vscsi_search_hctl_and_block(p_devname) 14.91 + 14.92 + if p_hctl == None: 14.93 + raise OptionError("Cannot find device \"%s\"" % p_devname) 14.94 + 14.95 + dom = args[0] 14.96 + vscsi = ['vscsi'] 14.97 + vscsi.append(['dev', \ 14.98 + ['state', 'Initialising'], \ 14.99 + ['devid', v_hctl[0]], \ 14.100 + ['p-dev', p_hctl], \ 14.101 + ['p-devname', block], \ 14.102 + ['v-dev', v_dev] ]) 14.103 + 14.104 + if len(args) == 4: 14.105 + vscsi.append(['backend', args[3]]) 14.106 + 14.107 + vscsi.append(['state', 'Initialising']) 14.108 + vscsi.append(['devid', v_hctl[0]]) 14.109 + server.xend.domain.device_configure(dom, vscsi) 14.110 + 14.111 def detach(args, deviceClass): 14.112 rm_cfg = True 14.113 dom = args[0] 14.114 @@ -2353,6 +2429,27 @@ def xm_pci_detach(args): 14.115 (dom, pci) = parse_pci_configuration(args, 'Closing') 14.116 server.xend.domain.device_configure(dom, pci) 14.117 14.118 +def xm_scsi_detach(args): 14.119 + xenapi_unsupported() 14.120 + arg_check(args, 'scsi-detach', 2) 14.121 + 14.122 + v_dev = args[1] 14.123 + v_hctl = v_dev.split(':') 14.124 + if len(v_hctl) != 4: 14.125 + raise OptionError("Invalid argument: %s" % v_dev) 14.126 + 14.127 + dom = args[0] 14.128 + vscsi = ['vscsi'] 14.129 + vscsi.append(['dev', \ 14.130 + ['state', 'Closing'], \ 14.131 + ['devid', v_hctl[0]], \ 14.132 + ['p-dev', ''], \ 14.133 + ['p-devname', ''], \ 14.134 + ['v-dev', v_dev] ]) 14.135 + 14.136 + vscsi.append(['state', 'Closing']) 14.137 + vscsi.append(['devid', v_hctl[0]]) 14.138 + server.xend.domain.device_configure(dom, vscsi) 14.139 14.140 def xm_vnet_list(args): 14.141 xenapi_unsupported() 14.142 @@ -2548,6 +2645,10 @@ commands = { 14.143 "pci-attach": xm_pci_attach, 14.144 "pci-detach": xm_pci_detach, 14.145 "pci-list": xm_pci_list, 14.146 + # vscsi 14.147 + "scsi-attach": xm_scsi_attach, 14.148 + "scsi-detach": xm_scsi_detach, 14.149 + "scsi-list": xm_scsi_list, 14.150 } 14.151 14.152 ## The commands supported by a separate argument parser in xend.xm.