# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1224147018 -3600
# Node ID 9404bcb6d32e2a3873289254a42b0dbf6663a41c
# Parent 22c89412fc8c0b7d47b73b7d67f0ef88b07b935e
Enhance XenAPI for pvSCSI
Basically, I implemented XenAPI for pvSCSI according to the patch of
XenAPI document which I sent before. However, I renamed the class
name of virtual SCSI devices to "DSCSI".
Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
---
tools/python/xen/util/pci.py | 21 ---
tools/python/xen/util/utils.py | 26 ++++
tools/python/xen/util/vscsi_util.py | 113 +++++++++++++++++
tools/python/xen/xend/XendAPI.py | 20 ++-
tools/python/xen/xend/XendConfig.py | 201 ++++++++++++++++++++++++++------
tools/python/xen/xend/XendDSCSI.py | 174 +++++++++++++++++++++++++++
tools/python/xen/xend/XendDomainInfo.py | 110 ++++++++++++++++-
tools/python/xen/xend/XendNode.py | 39 ++++++
tools/python/xen/xend/XendPSCSI.py | 143 ++++++++++++++++++++++
tools/python/xen/xend/server/vscsiif.py | 18 +-
tools/python/xen/xm/create.dtd | 5
tools/python/xen/xm/main.py | 140 ++++++++++++++--------
tools/python/xen/xm/xenapi_create.py | 59 +++++++++
13 files changed, 947 insertions(+), 122 deletions(-)
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/util/pci.py
--- a/tools/python/xen/util/pci.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/util/pci.py Thu Oct 16 09:50:18 2008 +0100
@@ -12,8 +12,8 @@ import types
import types
import struct
import time
-
-PROC_MNT_PATH = '/proc/mounts'
+from xen.util import utils
+
PROC_PCI_PATH = '/proc/bus/pci/devices'
PROC_PCI_NUM_RESOURCES = 7
@@ -97,9 +97,6 @@ MSIX_SIZE_MASK = 0x7ff
# Global variable to store information from lspci
lspci_info = None
-# Global variable to store the sysfs mount point
-sysfs_mnt_point = None
-
#Calculate PAGE_SHIFT: number of bits to shift an address to get the page
number
PAGE_SIZE = resource.getpagesize()
PAGE_SHIFT = 0
@@ -141,20 +138,8 @@ def parse_pci_name(pci_name_string):
def find_sysfs_mnt():
- global sysfs_mnt_point
- if not sysfs_mnt_point is None:
- return sysfs_mnt_point
-
try:
- mounts_file = open(PROC_MNT_PATH,'r')
-
- for line in mounts_file:
- sline = line.split()
- if len(sline)<3:
- continue
- if sline[2]=='sysfs':
- sysfs_mnt_point= sline[1]
- return sysfs_mnt_point
+ return utils.find_sysfs_mount()
except IOError, (errno, strerr):
raise PciDeviceParseError(('Failed to locate sysfs mount: %s: %s (%d)'%
(PROC_PCI_PATH, strerr, errno)))
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/util/utils.py
--- a/tools/python/xen/util/utils.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/util/utils.py Thu Oct 16 09:50:18 2008 +0100
@@ -48,3 +48,29 @@ def daemonize(prog, args, stdin_tmpfile=
os.waitpid(pid, 0)
return daemon_pid
+# Global variable to store the sysfs mount point
+sysfs_mount_point = None
+
+PROC_MOUNTS_PATH = '/proc/mounts'
+
+def find_sysfs_mount():
+ global sysfs_mount_point
+
+ if not sysfs_mount_point is None:
+ return sysfs_mount_point
+
+ try:
+ mounts_file = open(PROC_MOUNTS_PATH, 'r')
+
+ for line in mounts_file:
+ sline = line.split()
+ if len(sline) < 3:
+ continue
+ if sline[2] == 'sysfs':
+ sysfs_mount_point= sline[1]
+ return sysfs_mount_point
+ except IOError, (errno, strerr):
+ raise
+
+ return None
+
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/util/vscsi_util.py
--- a/tools/python/xen/util/vscsi_util.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/util/vscsi_util.py Thu Oct 16 09:50:18 2008 +0100
@@ -23,9 +23,18 @@
"""Support for VSCSI Devices.
"""
import os
+import os.path
import sys
import re
import string
+from xen.util import utils
+
+SYSFS_SCSI_PATH = "/bus/scsi/devices"
+SYSFS_SCSI_DEV_VENDOR_PATH = '/vendor'
+SYSFS_SCSI_DEV_MODEL_PATH = '/model'
+SYSFS_SCSI_DEV_TYPEID_PATH = '/type'
+SYSFS_SCSI_DEV_REVISION_PATH = '/rev'
+SYSFS_SCSI_DEV_SCSILEVEL_PATH = '/scsi_level'
def _vscsi_hctl_block(name, scsi_devices):
""" block-device name is convert into hctl. (e.g., '/dev/sda',
@@ -84,10 +93,10 @@ def vscsi_get_scsidevices():
def vscsi_get_scsidevices():
""" get all scsi devices"""
- SERCH_SCSI_PATH = "/sys/bus/scsi/devices"
devices = []
-
- for dirpath, dirnames, files in os.walk(SERCH_SCSI_PATH):
+ sysfs_mnt = utils.find_sysfs_mount()
+
+ for dirpath, dirnames, files in os.walk(sysfs_mnt + SYSFS_SCSI_PATH):
for hctl in dirnames:
paths = os.path.join(dirpath, hctl)
block = "-"
@@ -131,3 +140,101 @@ def vscsi_search_hctl_and_block(device):
return (hctl, block)
+
+def get_scsi_vendor(pHCTL):
+ try:
+ sysfs_mnt = utils.find_sysfs_mount()
+ sysfs_scsi_dev_path = \
+ os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+ scsi_vendor = \
+ os.popen('cat ' + sysfs_scsi_dev_path + \
+ SYSFS_SCSI_DEV_VENDOR_PATH).read()
+ return scsi_vendor.splitlines()[0]
+ except:
+ return None
+
+def get_scsi_model(pHCTL):
+ try:
+ sysfs_mnt = utils.find_sysfs_mount()
+ sysfs_scsi_dev_path = \
+ os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+ scsi_model = \
+ os.popen('cat ' + sysfs_scsi_dev_path + \
+ SYSFS_SCSI_DEV_MODEL_PATH).read()
+ return scsi_model.splitlines()[0]
+ except:
+ return None
+
+def get_scsi_typeid(pHCTL):
+ try:
+ sysfs_mnt = utils.find_sysfs_mount()
+ sysfs_scsi_dev_path = \
+ os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+ scsi_typeid = \
+ os.popen('cat ' + sysfs_scsi_dev_path + \
+ SYSFS_SCSI_DEV_TYPEID_PATH).read()
+ return int(scsi_typeid.splitlines()[0])
+ except:
+ return None
+
+def get_scsi_revision(pHCTL):
+ try:
+ sysfs_mnt = utils.find_sysfs_mount()
+ sysfs_scsi_dev_path = \
+ os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+ scsi_revision = \
+ os.popen('cat ' + sysfs_scsi_dev_path + \
+ SYSFS_SCSI_DEV_REVISION_PATH).read()
+ return scsi_revision.splitlines()[0]
+ except:
+ return None
+
+def get_scsi_scsilevel(pHCTL):
+ try:
+ sysfs_mnt = utils.find_sysfs_mount()
+ sysfs_scsi_dev_path = \
+ os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL)
+ scsi_scsilevel = \
+ os.popen('cat ' + sysfs_scsi_dev_path + \
+ SYSFS_SCSI_DEV_SCSILEVEL_PATH).read()
+ return int(scsi_scsilevel.splitlines()[0])
+ except:
+ return None
+
+def get_all_scsi_devices():
+
+ scsi_devs = []
+
+ for scsi_info in vscsi_get_scsidevices():
+ scsi_dev = {
+ 'physical_HCTL': scsi_info[0],
+ 'dev_name': None,
+ 'sg_name': scsi_info[2],
+ 'scsi_id': None
+ }
+ if scsi_info[1] != '-':
+ scsi_dev['dev_name'] = scsi_info[1]
+ if scsi_info[3] != '-':
+ scsi_dev['scsi_id'] = scsi_info[3]
+
+ scsi_dev['vendor_name'] = \
+ get_scsi_vendor(scsi_dev['physical_HCTL'])
+ scsi_dev['model'] = \
+ get_scsi_model(scsi_dev['physical_HCTL'])
+ scsi_dev['type_id'] = \
+ get_scsi_typeid(scsi_dev['physical_HCTL'])
+ scsi_dev['revision'] = \
+ get_scsi_revision(scsi_dev['physical_HCTL'])
+ scsi_dev['scsi_level'] = \
+ get_scsi_scsilevel(scsi_dev['physical_HCTL'])
+
+ try:
+ lsscsi_info = os.popen('lsscsi ' +
scsi_dev['physical_HCTL']).read().split()
+ scsi_dev['type'] = lsscsi_info[1]
+ except:
+ scsi_dev['type'] = None
+
+ scsi_devs.append(scsi_dev)
+
+ return scsi_devs
+
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xend/XendAPI.py Thu Oct 16 09:50:18 2008 +0100
@@ -42,6 +42,8 @@ from XendPBD import XendPBD
from XendPBD import XendPBD
from XendPPCI import XendPPCI
from XendDPCI import XendDPCI
+from XendPSCSI import XendPSCSI
+from XendDSCSI import XendDSCSI
from XendXSPolicy import XendXSPolicy, XendACMPolicy
from XendAPIConstants import *
@@ -480,7 +482,9 @@ classes = {
'PBD' : valid_object("PBD"),
'PIF_metrics' : valid_object("PIF_metrics"),
'PPCI' : valid_object("PPCI"),
- 'DPCI' : valid_object("DPCI")
+ 'DPCI' : valid_object("DPCI"),
+ 'PSCSI' : valid_object("PSCSI"),
+ 'DSCSI' : valid_object("DSCSI")
}
autoplug_classes = {
@@ -491,6 +495,8 @@ autoplug_classes = {
'PIF_metrics' : XendPIFMetrics,
'PPCI' : XendPPCI,
'DPCI' : XendDPCI,
+ 'PSCSI' : XendPSCSI,
+ 'DSCSI' : XendDSCSI,
'XSPolicy' : XendXSPolicy,
'ACMPolicy' : XendACMPolicy,
}
@@ -881,6 +887,7 @@ class XendAPI(object):
'PBDs',
'PIFs',
'PPCIs',
+ 'PSCSIs',
'host_CPUs',
'cpu_configuration',
'metrics',
@@ -961,6 +968,8 @@ class XendAPI(object):
return xen_api_success(XendNode.instance().get_PIF_refs())
def host_get_PPCIs(self, session, ref):
return xen_api_success(XendNode.instance().get_PPCI_refs())
+ def host_get_PSCSIs(self, session, ref):
+ return xen_api_success(XendNode.instance().get_PSCSI_refs())
def host_get_host_CPUs(self, session, host_ref):
return xen_api_success(XendNode.instance().get_host_cpu_refs())
def host_get_metrics(self, _, ref):
@@ -1037,7 +1046,8 @@ class XendAPI(object):
'logging': {},
'PIFs': XendPIF.get_all(),
'PBDs': XendPBD.get_all(),
- 'PPCIs': XendPPCI.get_all()}
+ 'PPCIs': XendPPCI.get_all(),
+ 'PSCSIs': XendPSCSI.get_all()}
return xen_api_success(record)
# class methods
@@ -1158,6 +1168,7 @@ class XendAPI(object):
'VBDs',
'VTPMs',
'DPCIs',
+ 'DSCSIs',
'tools_version',
'domid',
'is_control_domain',
@@ -1304,6 +1315,10 @@ class XendAPI(object):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_success(dom.get_dpcis())
+ def VM_get_DSCSIs(self, session, vm_ref):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ return xen_api_success(dom.get_dscsis())
+
def VM_get_tools_version(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return dom.get_tools_version()
@@ -1684,6 +1699,7 @@ class XendAPI(object):
'VBDs': xeninfo.get_vbds(),
'VTPMs': xeninfo.get_vtpms(),
'DPCIs': xeninfo.get_dpcis(),
+ 'DSCSIs': xeninfo.get_dscsis(),
'PV_bootloader': xeninfo.info.get('PV_bootloader'),
'PV_kernel': xeninfo.info.get('PV_kernel'),
'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py Thu Oct 16 09:50:18 2008 +0100
@@ -26,6 +26,8 @@ from xen.xend import XendAPIStore
from xen.xend import XendAPIStore
from xen.xend.XendPPCI import XendPPCI
from xen.xend.XendDPCI import XendDPCI
+from xen.xend.XendPSCSI import XendPSCSI
+from xen.xend.XendDSCSI import XendDSCSI
from xen.xend.XendError import VmError
from xen.xend.XendDevices import XendDevices
from xen.xend.PrettyPrint import prettyprintstring
@@ -782,8 +784,8 @@ class XendConfig(dict):
log.debug('_sxp_to_xapi(%s)' % scrub_password(sxp_cfg))
# _parse_sxp() below will call device_add() and construct devices.
- # Some devices (currently only pci) may require VM's uuid, so
- # setup self['uuid'] beforehand.
+ # Some devices may require VM's uuid, so setup self['uuid']
+ # beforehand.
self['uuid'] = sxp.child_value(sxp_cfg, 'uuid', uuid.createString())
cfg = self._parse_sxp(sxp_cfg)
@@ -1222,29 +1224,28 @@ class XendConfig(dict):
dev_type = sxp.name(config)
dev_info = {}
- if dev_type == 'pci' or dev_type == 'vscsi':
+ if dev_type == 'pci':
pci_devs_uuid = sxp.child_value(config, 'uuid',
uuid.createString())
pci_dict = self.pci_convert_sxp_to_dict(config)
pci_devs = pci_dict['devs']
- if dev_type != 'vscsi':
- # create XenAPI DPCI objects.
- for pci_dev in pci_devs:
- dpci_uuid = pci_dev.get('uuid')
- ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'],
- pci_dev['bus'],
- pci_dev['slot'],
- pci_dev['func'])
- if ppci_uuid is None:
- continue
- dpci_record = {
- 'VM': self['uuid'],
- 'PPCI': ppci_uuid,
- 'hotplug_slot': pci_dev.get('vslot', 0)
- }
- XendDPCI(dpci_uuid, dpci_record)
+ # create XenAPI DPCI objects.
+ for pci_dev in pci_devs:
+ dpci_uuid = pci_dev.get('uuid')
+ ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'],
+ pci_dev['bus'],
+ pci_dev['slot'],
+ pci_dev['func'])
+ if ppci_uuid is None:
+ continue
+ dpci_record = {
+ 'VM': self['uuid'],
+ 'PPCI': ppci_uuid,
+ 'hotplug_slot': pci_dev.get('vslot', 0)
+ }
+ XendDPCI(dpci_uuid, dpci_record)
target['devices'][pci_devs_uuid] = (dev_type,
{'devs': pci_devs,
@@ -1253,6 +1254,30 @@ class XendConfig(dict):
log.debug("XendConfig: reading device: %s" % pci_devs)
return pci_devs_uuid
+
+ if dev_type == 'vscsi':
+ vscsi_devs_uuid = sxp.child_value(config, 'uuid',
+ uuid.createString())
+ vscsi_dict = self.vscsi_convert_sxp_to_dict(config)
+ vscsi_devs = vscsi_dict['devs']
+
+ # create XenAPI DSCSI objects.
+ for vscsi_dev in vscsi_devs:
+ dscsi_uuid = vscsi_dev.get('uuid')
+ pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev'])
+ if pscsi_uuid is None:
+ continue
+ dscsi_record = {
+ 'VM': self['uuid'],
+ 'PSCSI': pscsi_uuid,
+ 'virtual_HCTL': vscsi_dev.get('v-dev')
+ }
+ XendDSCSI(dscsi_uuid, dscsi_record)
+
+ target['devices'][vscsi_devs_uuid] = \
+ (dev_type, {'devs': vscsi_devs, 'uuid': vscsi_devs_uuid} )
+ log.debug("XendConfig: reading device: %s" % vscsi_devs)
+ return vscsi_devs_uuid
for opt_val in config[1:]:
try:
@@ -1559,6 +1584,86 @@ class XendConfig(dict):
return dev_config
+ def vscsi_convert_sxp_to_dict(self, dev_sxp):
+ """Convert vscsi device sxp to dict
+ @param dev_sxp: device configuration
+ @type dev_sxp: SXP object (parsed config)
+ @return: dev_config
+ @rtype: dictionary
+ """
+ # Parsing the device SXP's. In most cases, the SXP looks
+ # like this:
+ #
+ # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]]
+ #
+ # However, for SCSI devices it looks like this:
+ #
+ # [device,
+ # [vscsi,
+ # [dev,
+ # [devid, 0], [p-devname, sdb], [p-dev, 1:0:0:1],
+ # [v-dev, 0:0:0:0], [state, Initialising]
+ # ],
+ # [dev,
+ # [devid, 0], [p-devname, sdc], [p-dev, 1:0:0:2],
+ # [v-dev, 0:0:0:1], [satet, Initialising]
+ # ]
+ # ],
+ # [vscsi,
+ # [dev,
+ # [devid, 1], [p-devname, sdg], [p-dev, 2:0:0:0],
+ # [v-dev, 1:0:0:0], [state, Initialising]
+ # ],
+ # [dev,
+ # [devid, 1], [p-devname, sdh], [p-dev, 2:0:0:1],
+ # [v-dev, 1:0:0:1], [satet, Initialising]
+ # ]
+ # ]
+ # ]
+ #
+ # It seems the reasoning for this difference is because
+ # vscsiif.py needs all the SCSI device configurations with
+ # same host number at the same time when creating the devices.
+
+ # For SCSI device hotplug support, the SXP of SCSI devices is
+ # extendend like this:
+ #
+ # [device,
+ # [vscsi,
+ # [dev,
+ # [devid, 0], [p-devname, sdd], [p-dev, 1:0:0:3],
+ # [v-dev, 0:0:0:2], [state, Initialising]
+ # ]
+ # ]
+ # ]
+ #
+ # state 'Initialising' indicates that the device is being attached,
+ # while state 'Closing' indicates that the device is being detached.
+ #
+ # The Dict looks like this:
+ #
+ # { devs: [ {devid: 0, p-devname: sdd, p-dev: 1:0:0:3,
+ # v-dev: 0:0:0:2, state: Initialising} ] }
+
+ dev_config = {}
+
+ vscsi_devs = []
+ for vscsi_dev in sxp.children(dev_sxp, 'dev'):
+ vscsi_dev_info = {}
+ for opt_val in vscsi_dev[1:]:
+ try:
+ opt, val = opt_val
+ vscsi_dev_info[opt] = val
+ except TypeError:
+ pass
+ # append uuid for each vscsi device.
+ vscsi_uuid = vscsi_dev_info.get('uuid', uuid.createString())
+ vscsi_dev_info['uuid'] = vscsi_uuid
+ vscsi_devs.append(vscsi_dev_info)
+ dev_config['devs'] = vscsi_devs
+
+ return dev_config
+
def console_add(self, protocol, location, other_config = {}):
dev_uuid = uuid.createString()
if protocol == 'vt100':
@@ -1632,7 +1737,7 @@ class XendConfig(dict):
dev_type, dev_info = self['devices'][dev_uuid]
- if dev_type == 'pci' or dev_type == 'vscsi': # Special case for pci
+ if dev_type == 'pci': # Special case for pci
pci_dict = self.pci_convert_sxp_to_dict(config)
pci_devs = pci_dict['devs']
@@ -1640,26 +1745,50 @@ class XendConfig(dict):
for dpci_uuid in XendDPCI.get_by_VM(self['uuid']):
XendAPIStore.deregister(dpci_uuid, "DPCI")
- if dev_type != 'vscsi':
- # create XenAPI DPCI objects.
- for pci_dev in pci_devs:
- dpci_uuid = pci_dev.get('uuid')
- ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'],
- pci_dev['bus'],
- pci_dev['slot'],
- pci_dev['func'])
- if ppci_uuid is None:
- continue
- dpci_record = {
- 'VM': self['uuid'],
- 'PPCI': ppci_uuid,
- 'hotplug_slot': pci_dev.get('vslot', 0)
- }
- XendDPCI(dpci_uuid, dpci_record)
+ # create XenAPI DPCI objects.
+ for pci_dev in pci_devs:
+ dpci_uuid = pci_dev.get('uuid')
+ ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'],
+ pci_dev['bus'],
+ pci_dev['slot'],
+ pci_dev['func'])
+ if ppci_uuid is None:
+ continue
+ dpci_record = {
+ 'VM': self['uuid'],
+ 'PPCI': ppci_uuid,
+ 'hotplug_slot': pci_dev.get('vslot', 0)
+ }
+ XendDPCI(dpci_uuid, dpci_record)
self['devices'][dev_uuid] = (dev_type,
{'devs': pci_devs,
'uuid': dev_uuid})
+ return True
+
+ if dev_type == 'vscsi': # Special case for vscsi
+ vscsi_dict = self.vscsi_convert_sxp_to_dict(config)
+ vscsi_devs = vscsi_dict['devs']
+
+ # destroy existing XenAPI DSCSI objects
+ for dscsi_uuid in XendDSCSI.get_by_VM(self['uuid']):
+ XendAPIStore.deregister(dscsi_uuid, "DSCSI")
+
+ # create XenAPI DSCSI objects.
+ for vscsi_dev in vscsi_devs:
+ dscsi_uuid = vscsi_dev.get('uuid')
+ pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev'])
+ if pscsi_uuid is None:
+ continue
+ dscsi_record = {
+ 'VM': self['uuid'],
+ 'PSCSI': pscsi_uuid,
+ 'virtual_HCTL': vscsi_dev.get('v-dev')
+ }
+ XendDSCSI(dscsi_uuid, dscsi_record)
+
+ self['devices'][dev_uuid] = \
+ (dev_type, {'devs': vscsi_devs, 'uuid': dev_uuid} )
return True
for opt_val in config[1:]:
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xend/XendDSCSI.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/XendDSCSI.py Thu Oct 16 09:50:18 2008 +0100
@@ -0,0 +1,174 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright FUJITSU LIMITED 2008
+# Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
+#============================================================================
+
+from xen.xend.XendBase import XendBase
+from xen.xend.XendPSCSI import XendPSCSI
+from xen.xend import XendAPIStore
+from xen.xend import sxp
+from xen.xend import uuid as genuuid
+
+import XendDomain, XendNode
+
+from XendError import *
+from XendTask import XendTask
+from XendLogging import log
+
+class XendDSCSI(XendBase):
+ """Representation of a half-virtualized SCSI device."""
+
+ def getClass(self):
+ return "DSCSI"
+
+ def getAttrRO(self):
+ attrRO = ['VM',
+ 'PSCSI',
+ 'virtual_host',
+ 'virtual_channel',
+ 'virtual_target',
+ 'virtual_lun',
+ 'virtual_HCTL',
+ 'runtime_properties']
+ return XendBase.getAttrRO() + attrRO
+
+ def getAttrRW(self):
+ attrRW = []
+ return XendBase.getAttrRW() + attrRW
+
+ def getAttrInst(self):
+ attrInst = ['VM',
+ 'PSCSI',
+ 'virtual_HCTL']
+ return XendBase.getAttrInst() + attrInst
+
+ def getMethods(self):
+ methods = ['destroy']
+ return XendBase.getMethods() + methods
+
+ def getFuncs(self):
+ funcs = ['create']
+ return XendBase.getFuncs() + funcs
+
+ getClass = classmethod(getClass)
+ getAttrRO = classmethod(getAttrRO)
+ getAttrRW = classmethod(getAttrRW)
+ getAttrInst = classmethod(getAttrInst)
+ getMethods = classmethod(getMethods)
+ getFuncs = classmethod(getFuncs)
+
+ def create(self, dscsi_struct):
+
+ # Check if VM is valid
+ xendom = XendDomain.instance()
+ if not xendom.is_valid_vm(dscsi_struct['VM']):
+ raise InvalidHandleError('VM', dscsi_struct['VM'])
+ dom = xendom.get_vm_by_uuid(dscsi_struct['VM'])
+
+ # Check if PSCSI is valid
+ xennode = XendNode.instance()
+ pscsi_uuid = xennode.get_pscsi_by_uuid(dscsi_struct['PSCSI'])
+ if not pscsi_uuid:
+ raise InvalidHandleError('PSCSI', dscsi_struct['PSCSI'])
+
+ # Assign PSCSI to VM
+ try:
+ dscsi_ref = XendTask.log_progress(0, 100, \
+ dom.create_dscsi, \
+ dscsi_struct)
+ except XendError, e:
+ log.exception("Error in create_dscsi")
+ raise
+
+ return dscsi_ref
+
+ create = classmethod(create)
+
+ def get_by_VM(cls, VM_ref):
+ result = []
+ for dscsi in XendAPIStore.get_all("DSCSI"):
+ if dscsi.get_VM() == VM_ref:
+ result.append(dscsi.get_uuid())
+ return result
+
+ get_by_VM = classmethod(get_by_VM)
+
+ def __init__(self, uuid, record):
+ XendBase.__init__(self, uuid, record)
+ v_hctl = self.virtual_HCTL.split(':')
+ self.virtual_host = int(v_hctl[0])
+ self.virtual_channel = int(v_hctl[1])
+ self.virtual_target = int(v_hctl[2])
+ self.virtual_lun = int(v_hctl[3])
+
+ def get_VM(self):
+ return self.VM
+
+ def get_PSCSI(self):
+ return self.PSCSI
+
+ def get_virtual_host(self):
+ return self.virtual_host
+
+ def get_virtual_channel(self):
+ return self.virtual_channel
+
+ def get_virtual_target(self):
+ return self.virtual_target
+
+ def get_virtual_lun(self):
+ return self.virtual_lun
+
+ def get_virtual_HCTL(self):
+ return self.virtual_HCTL
+
+ def get_runtime_properties(self):
+ xendom = XendDomain.instance()
+ dominfo = xendom.get_vm_by_uuid(self.VM)
+
+ try:
+ device_dict = {}
+ for device_sxp in dominfo.getDeviceSxprs('vscsi'):
+ target_dev = None
+ for dev in device_sxp[1][0][1]:
+ vdev = sxp.child_value(dev, 'v-dev')
+ if vdev == self.virtual_HCTL:
+ target_dev = dev
+ break
+ if target_dev is None:
+ continue
+
+ dev_dict = {}
+ for info in target_dev[1:]:
+ dev_dict[info[0]] = info[1]
+ device_dict['dev'] = dev_dict
+ for info in device_sxp[1][1:]:
+ device_dict[info[0]] = info[1]
+
+ return device_dict
+ except Exception, exn:
+ log.exception(exn)
+ return {}
+
+ def destroy(self):
+ xendom = XendDomain.instance()
+ dom = xendom.get_vm_by_uuid(self.get_VM())
+ if not dom:
+ raise InvalidHandleError("VM", self.get_VM())
+ XendTask.log_progress(0, 100, \
+ dom.destroy_dscsi, \
+ self.get_uuid())
+
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu Oct 16 09:50:18 2008 +0100
@@ -55,9 +55,11 @@ from xen.xend.XendAPIConstants import *
from xen.xend.XendVMMetrics import XendVMMetrics
+from xen.xend import XendAPIStore
from xen.xend.XendPPCI import XendPPCI
from xen.xend.XendDPCI import XendDPCI
-from xen.xend import XendAPIStore
+from xen.xend.XendPSCSI import XendPSCSI
+from xen.xend.XendDSCSI import XendDSCSI
MIGRATE_TIMEOUT = 30.0
BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
@@ -663,6 +665,9 @@ class XendDomainInfo:
if dev_type == 'pci':
for dev in dev_config_dict['devs']:
XendAPIStore.deregister(dev['uuid'], 'DPCI')
+ if dev_type == 'vscsi':
+ for dev in dev_config_dict['devs']:
+ XendAPIStore.deregister(dev['uuid'], 'DSCSI')
elif dev_type == 'tap':
self.info['vbd_refs'].remove(dev_uuid)
else:
@@ -786,12 +791,11 @@ class XendDomainInfo:
if dev_class != 'vscsi':
return False
- dev_config = self.info.pci_convert_sxp_to_dict(dev_sxp)
+ dev_config = self.info.vscsi_convert_sxp_to_dict(dev_sxp)
dev = dev_config['devs'][0]
- req_devid = sxp.child_value(dev_sxp, 'devid')
- req_devid = int(req_devid)
+ req_devid = int(dev['devid'])
existing_dev_info = self._getDeviceInfo_vscsi(req_devid, dev['v-dev'])
- state = sxp.child_value(dev_sxp, 'state')
+ state = dev['state']
if state == 'Initialising':
# new create
@@ -3237,6 +3241,9 @@ class XendDomainInfo:
def get_dpcis(self):
return XendDPCI.get_by_VM(self.info.get('uuid'))
+ def get_dscsis(self):
+ return XendDSCSI.get_by_VM(self.info.get('uuid'))
+
def create_vbd(self, xenapi_vbd, vdi_image_path):
"""Create a VBD using a VDI from XendStorageRepository.
@@ -3416,6 +3423,60 @@ class XendDomainInfo:
raise XendError('Failed to create device')
return dpci_uuid
+
+ def create_dscsi(self, xenapi_dscsi):
+ """Create scsi device from the passed struct in Xen API format.
+
+ @param xenapi_dscsi: DSCSI struct from Xen API
+ @rtype: string
+ @return: UUID
+ """
+
+ dscsi_uuid = uuid.createString()
+
+ # Convert xenapi to sxp
+ pscsi = XendAPIStore.get(xenapi_dscsi.get('PSCSI'), 'PSCSI')
+ devid = int(xenapi_dscsi.get('virtual_HCTL').split(':')[0])
+ target_vscsi_sxp = \
+ ['vscsi',
+ ['dev',
+ ['devid', devid],
+ ['p-devname', pscsi.get_dev_name()],
+ ['p-dev', pscsi.get_physical_HCTL()],
+ ['v-dev', xenapi_dscsi.get('virtual_HCTL')],
+ ['state', 'Initialising'],
+ ['uuid', dscsi_uuid]
+ ]
+ ]
+
+ if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
+
+ cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid, None)
+
+ if cur_vscsi_sxp is None:
+ dev_uuid = self.info.device_add('vscsi', cfg_sxp =
target_vscsi_sxp)
+ if not dev_uuid:
+ raise XendError('Failed to create device')
+
+ else:
+ new_vscsi_sxp = ['vscsi']
+ for existing_dev in sxp.children(cur_vscsi_sxp, 'dev'):
+ new_vscsi_sxp.append(existing_dev)
+ new_vscsi_sxp.append(sxp.child0(target_vscsi_sxp, 'dev'))
+
+ dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid')
+ self.info.device_update(dev_uuid, new_vscsi_sxp)
+
+ xen.xend.XendDomain.instance().managed_config_save(self)
+
+ else:
+ try:
+ self.device_configure(target_vscsi_sxp)
+
+ except Exception, exn:
+ raise XendError('Failed to create device')
+
+ return dscsi_uuid
def destroy_device_by_uuid(self, dev_type, dev_uuid):
@@ -3484,6 +3545,41 @@ class XendDomainInfo:
except Exception, exn:
raise XendError('Failed to destroy device')
+ def destroy_dscsi(self, dev_uuid):
+ dscsi = XendAPIStore.get(dev_uuid, 'DSCSI')
+ devid = dscsi.get_virtual_host()
+ vHCTL = dscsi.get_virtual_HCTL()
+ cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid, None)
+ dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid')
+
+ target_dev = None
+ new_vscsi_sxp = ['vscsi']
+ for dev in sxp.children(cur_vscsi_sxp, 'dev'):
+ if vHCTL == sxp.child_value(dev, 'v-dev'):
+ target_dev = dev
+ else:
+ new_vscsi_sxp.append(dev)
+
+ if target_dev is None:
+ raise XendError('Failed to destroy device')
+
+ target_dev.append(['state', 'Closing'])
+ target_vscsi_sxp = ['vscsi', target_dev]
+
+ if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
+
+ self.info.device_update(dev_uuid, new_vscsi_sxp)
+ if len(sxp.children(new_vscsi_sxp, 'dev')) == 0:
+ del self.info['devices'][dev_uuid]
+ xen.xend.XendDomain.instance().managed_config_save(self)
+
+ else:
+ try:
+ self.device_configure(target_vscsi_sxp)
+
+ except Exception, exn:
+ raise XendError('Failed to destroy device')
+
def destroy_xapi_instances(self):
"""Destroy Xen-API instances stored in XendAPIStore.
"""
@@ -3508,6 +3604,10 @@ class XendDomainInfo:
for dpci_uuid in XendDPCI.get_by_VM(self.info.get('uuid')):
XendAPIStore.deregister(dpci_uuid, "DPCI")
+ # Destroy DSCSI instances.
+ for dscsi_uuid in XendDSCSI.get_by_VM(self.info.get('uuid')):
+ XendAPIStore.deregister(dscsi_uuid, "DSCSI")
+
def has_device(self, dev_class, dev_uuid):
return (dev_uuid in self.info['%s_refs' % dev_class.lower()])
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xend/XendNode.py Thu Oct 16 09:50:18 2008 +0100
@@ -22,6 +22,7 @@ import xen.lowlevel.xc
from xen.util import Brctl
from xen.util import pci as PciUtil
+from xen.util import vscsi_util
from xen.xend import XendAPIStore
from xen.xend import osdep
@@ -38,7 +39,8 @@ from XendStateStore import XendStateStor
from XendStateStore import XendStateStore
from XendMonitor import XendMonitor
from XendPPCI import XendPPCI
-
+from XendPSCSI import XendPSCSI
+
class XendNode:
"""XendNode - Represents a Domain 0 Host."""
@@ -53,6 +55,7 @@ class XendNode:
* network
* Storage Repository
* PPCI
+ * PSCSI
"""
self.xc = xen.lowlevel.xc.xc()
@@ -269,6 +272,24 @@ class XendNode:
XendPPCI(ppci_uuid, ppci_record)
+ # Initialise PSCSIs
+ saved_pscsis = self.state_store.load_state('pscsi')
+ saved_pscsi_table = {}
+ if saved_pscsis:
+ for pscsi_uuid, pscsi_record in saved_pscsis.items():
+ try:
+ saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid
+ except KeyError:
+ pass
+
+ for pscsi_record in vscsi_util.get_all_scsi_devices():
+ if pscsi_record['scsi_id']:
+ # If saved uuid exists, use it. Otherwise create one.
+ pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'],
+ uuid.createString())
+ XendPSCSI(pscsi_uuid, pscsi_record)
+
+
## def network_destroy(self, net_uuid):
## del self.networks[net_uuid]
## self.save_networks()
@@ -317,6 +338,15 @@ class XendNode:
def get_ppci_by_uuid(self, ppci_uuid):
if ppci_uuid in self.get_PPCI_refs():
return ppci_uuid
+ return None
+
+
+ def get_PSCSI_refs(self):
+ return XendPSCSI.get_all()
+
+ def get_pscsi_by_uuid(self, pscsi_uuid):
+ if pscsi_uuid in self.get_PSCSI_refs():
+ return pscsi_uuid
return None
@@ -333,6 +363,7 @@ class XendNode:
self.save_PBDs()
self.save_SRs()
self.save_PPCIs()
+ self.save_PSCSIs()
def save_PIFs(self):
pif_records = dict([(pif_uuid, XendAPIStore.get(
@@ -362,6 +393,12 @@ class XendNode:
ppci_uuid, "PPCI").get_record())
for ppci_uuid in XendPPCI.get_all()])
self.state_store.save_state('ppci', ppci_records)
+
+ def save_PSCSIs(self):
+ pscsi_records = dict([(pscsi_uuid, XendAPIStore.get(
+ pscsi_uuid, "PSCSI").get_record())
+ for pscsi_uuid in XendPSCSI.get_all()])
+ self.state_store.save_state('pscsi', pscsi_records)
def shutdown(self):
return 0
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xend/XendPSCSI.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/XendPSCSI.py Thu Oct 16 09:50:18 2008 +0100
@@ -0,0 +1,143 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright FUJITSU LIMITED 2008
+# Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
+#============================================================================
+
+from xen.xend.XendBase import XendBase
+from xen.xend.XendBase import XendAPIStore
+from xen.xend import uuid as genuuid
+
+class XendPSCSI(XendBase):
+ """Representation of a physical SCSI device."""
+
+ def getClass(self):
+ return "PSCSI"
+
+ def getAttrRO(self):
+ attrRO = ['host',
+ 'physical_host',
+ 'physical_channel',
+ 'physical_target',
+ 'physical_lun',
+ 'physical_HCTL',
+ 'vendor_name',
+ 'model',
+ 'type_id',
+ 'type',
+ 'dev_name',
+ 'sg_name',
+ 'revision',
+ 'scsi_id',
+ 'scsi_level']
+ return XendBase.getAttrRO() + attrRO
+
+ def getAttrRW(self):
+ attrRW = []
+ return XendBase.getAttrRW() + attrRW
+
+ def getAttrInst(self):
+ attrInst = []
+ return XendBase.getAttrInst() + attrInst
+
+ def getMethods(self):
+ methods = []
+ return XendBase.getMethods() + methods
+
+ def getFuncs(self):
+ funcs = []
+ return XendBase.getFuncs() + funcs
+
+ getClass = classmethod(getClass)
+ getAttrRO = classmethod(getAttrRO)
+ getAttrRW = classmethod(getAttrRW)
+ getAttrInst = classmethod(getAttrInst)
+ getMethods = classmethod(getMethods)
+ getFuncs = classmethod(getFuncs)
+
+ def get_by_HCTL(self, physical_HCTL):
+ for pscsi in XendAPIStore.get_all("PSCSI"):
+ if pscsi.get_physical_HCTL() == physical_HCTL:
+ return pscsi.get_uuid()
+ return None
+
+ get_by_HCTL = classmethod(get_by_HCTL)
+
+ def __init__(self, uuid, record):
+ self.physical_HCTL = record['physical_HCTL']
+ self.vendor_name = record['vendor_name']
+ self.model = record['model']
+ self.type_id = record['type_id']
+ self.type = record['type']
+ self.dev_name = record['dev_name']
+ self.sg_name = record['sg_name']
+ self.revision = record['revision']
+ self.scsi_id = record['scsi_id']
+ self.scsi_level = record['scsi_level']
+
+ p_hctl = self.physical_HCTL.split(':')
+ self.physical_host = int(p_hctl[0])
+ self.physical_channel = int(p_hctl[1])
+ self.physical_target = int(p_hctl[2])
+ self.physical_lun = int(p_hctl[3])
+
+ XendBase.__init__(self, uuid, record)
+
+ def get_host(self):
+ from xen.xend import XendNode
+ return XendNode.instance().get_uuid()
+
+ def get_physical_host(self):
+ return self.physical_host
+
+ def get_physical_channel(self):
+ return self.physical_channel
+
+ def get_physical_target(self):
+ return self.physical_target
+
+ def get_physical_lun(self):
+ return self.physical_lun
+
+ def get_physical_HCTL(self):
+ return self.physical_HCTL
+
+ def get_vendor_name(self):
+ return self.vendor_name
+
+ def get_model(self):
+ return self.model
+
+ def get_type_id(self):
+ return self.type_id
+
+ def get_type(self):
+ return self.type
+
+ def get_dev_name(self):
+ return self.dev_name
+
+ def get_sg_name(self):
+ return self.sg_name
+
+ def get_revision(self):
+ return self.revision
+
+ def get_scsi_id(self):
+ return self.scsi_id
+
+ def get_scsi_level(self):
+ return self.scsi_level
+
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xend/server/vscsiif.py
--- a/tools/python/xen/xend/server/vscsiif.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xend/server/vscsiif.py Thu Oct 16 09:50:18 2008 +0100
@@ -125,10 +125,10 @@ class VSCSIController(DevController):
state = self.readBackend(devid, devpath + '/state')
localdevid = self.readBackend(devid, devpath + '/devid')
dev_dict = {'p-dev': pdev,
- 'p-devname': pdevname,
- 'v-dev': pdevname,
- 'state': state,
- 'devid': localdevid }
+ 'p-devname': pdevname,
+ 'v-dev': vdev,
+ 'state': state,
+ 'devid': localdevid }
vscsi_devs.append(dev_dict)
config['devs'] = vscsi_devs
@@ -168,17 +168,17 @@ class VSCSIController(DevController):
(devid, back, front) = self.getDeviceDetails(config)
devid = int(devid)
vscsi_config = config['devs'][0]
- states = config.get('states', [])
+ state = vscsi_config.get('state', '')
driver_state = self.readBackend(devid, 'state')
if str(xenbusState['Connected']) != driver_state:
raise VmError("Driver status is not connected")
uuid = self.readBackend(devid, 'uuid')
- if states[0] == 'Initialising':
+ if state == 'Initialising':
back['uuid'] = uuid
self.writeBackend(devid, back)
- elif states[0] == 'Closing':
+ elif state == 'Closing':
found = False
devs = self.readBackendList(devid, "vscsi-devs")
vscsipath = "vscsi-devs/"
@@ -197,8 +197,8 @@ class VSCSIController(DevController):
raise VmError("Device %s not connected" % vdev)
else:
- raise XendError('Error configuring device invalid state %s'
- % state)
+ raise XendError("Error configuring device invalid "
+ "state '%s'" % state)
self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring']))
return self.readBackend(devid, 'uuid')
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xm/create.dtd
--- a/tools/python/xen/xm/create.dtd Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xm/create.dtd Thu Oct 16 09:50:18 2008 +0100
@@ -40,6 +40,7 @@
vif*,
vtpm*,
pci*,
+ vscsi*,
console*,
platform*,
vcpu_param*,
@@ -87,6 +88,10 @@
slot CDATA #REQUIRED
func CDATA #REQUIRED
vslt CDATA #IMPLIED>
+
+<!ELEMENT vscsi EMPTY>
+<!ATTLIST vscsi p-dev CDATA #REQUIRED
+ v-dev CDATA #REQUIRED>
<!ELEMENT console (other_config*)>
<!ATTLIST console protocol (vt100|rfb|rdp) #REQUIRED>
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xm/main.py Thu Oct 16 09:50:18 2008 +0100
@@ -2235,12 +2235,34 @@ def vscsi_convert_sxp_to_dict(dev_sxp):
return dev_dict
def xm_scsi_list(args):
- xenapi_unsupported()
(use_long, params) = arg_check_for_resource_list(args, "scsi-list")
dom = params[0]
- devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
+ devs = []
+ if serverType == SERVER_XEN_API:
+
+ dscsi_refs = server.xenapi.VM.get_DSCSIs(get_single_vm(dom))
+ dscsi_properties = \
+ map(server.xenapi.DSCSI.get_runtime_properties, dscsi_refs)
+ dscsi_dict = {}
+ for dscsi_property in dscsi_properties:
+ devid = int(dscsi_property['dev']['devid'])
+ try:
+ dscsi_sxp = dscsi_dict[devid]
+ except:
+ dscsi_sxp = [['devs', []]]
+ for key, value in dscsi_property.items():
+ if key != 'dev':
+ dscsi_sxp.append([key, value])
+ dev_sxp = ['dev']
+ dev_sxp.extend(map2sxp(dscsi_property['dev']))
+ dscsi_sxp[0][1].append(dev_sxp)
+ dscsi_dict[devid] = dscsi_sxp
+ devs = map2sxp(dscsi_dict)
+
+ else:
+ devs = server.xend.domain.getDeviceSxprs(dom, 'vscsi')
if use_long:
map(PrettyPrint.prettyprint, devs)
@@ -2464,37 +2486,60 @@ def xm_pci_attach(args):
else:
server.xend.domain.device_configure(dom, pci)
+def parse_scsi_configuration(p_scsi, v_hctl, state):
+ v = v_hctl.split(':')
+ if len(v) != 4:
+ raise OptionError("Invalid argument: %s" % v_hctl)
+
+ if p_scsi is not None:
+ (p_hctl, block) = vscsi_util.vscsi_search_hctl_and_block(p_scsi)
+ if p_hctl == None:
+ raise OptionError("Cannot find device '%s'" % p_scsi)
+ else:
+ p_hctl = ''
+ block = ''
+
+ scsi = ['vscsi']
+ scsi.append(['dev', \
+ ['state', state], \
+ ['devid', int(v[0])], \
+ ['p-dev', p_hctl], \
+ ['p-devname', block], \
+ ['v-dev', v_hctl] \
+ ])
+
+ return scsi
+
def xm_scsi_attach(args):
- xenapi_unsupported()
-
arg_check(args, 'scsi-attach', 3, 4)
- p_devname = args[1]
- v_dev = args[2]
-
- v_hctl = v_dev.split(':')
- if len(v_hctl) != 4:
- raise OptionError("Invalid argument: %s" % v_dev)
-
- (p_hctl, block) = vscsi_util.vscsi_search_hctl_and_block(p_devname)
-
- if p_hctl == None:
- raise OptionError("Cannot find device \"%s\"" % p_devname)
-
dom = args[0]
- vscsi = ['vscsi']
- vscsi.append(['dev', \
- ['state', 'Initialising'], \
- ['devid', v_hctl[0]], \
- ['p-dev', p_hctl], \
- ['p-devname', block], \
- ['v-dev', v_dev] ])
-
- if len(args) == 4:
- vscsi.append(['backend', args[3]])
-
- vscsi.append(['state', 'Initialising'])
- vscsi.append(['devid', v_hctl[0]])
- server.xend.domain.device_configure(dom, vscsi)
+ p_scsi = args[1]
+ v_hctl = args[2]
+ scsi = parse_scsi_configuration(p_scsi, v_hctl, 'Initialising')
+
+ if serverType == SERVER_XEN_API:
+
+ scsi_dev = sxp.children(scsi, 'dev')[0]
+ p_hctl = sxp.child_value(scsi_dev, 'p-dev')
+ target_ref = None
+ for pscsi_ref in server.xenapi.PSCSI.get_all():
+ if p_hctl == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
+ target_ref = pscsi_ref
+ break
+ if target_ref is None:
+ raise OptionError("Cannot find device '%s'" % p_scsi)
+
+ dscsi_record = {
+ "VM": get_single_vm(dom),
+ "PSCSI": target_ref,
+ "virtual_HCTL": v_hctl
+ }
+ server.xenapi.DSCSI.create(dscsi_record)
+
+ else:
+ if len(args) == 4:
+ scsi.append(['backend', args[3]])
+ server.xend.domain.device_configure(dom, scsi)
def detach(args, deviceClass):
rm_cfg = True
@@ -2587,26 +2632,25 @@ def xm_pci_detach(args):
server.xend.domain.device_configure(dom, pci)
def xm_scsi_detach(args):
- xenapi_unsupported()
arg_check(args, 'scsi-detach', 2)
-
- v_dev = args[1]
- v_hctl = v_dev.split(':')
- if len(v_hctl) != 4:
- raise OptionError("Invalid argument: %s" % v_dev)
-
dom = args[0]
- vscsi = ['vscsi']
- vscsi.append(['dev', \
- ['state', 'Closing'], \
- ['devid', v_hctl[0]], \
- ['p-dev', ''], \
- ['p-devname', ''], \
- ['v-dev', v_dev] ])
-
- vscsi.append(['state', 'Closing'])
- vscsi.append(['devid', v_hctl[0]])
- server.xend.domain.device_configure(dom, vscsi)
+ v_hctl = args[1]
+ scsi = parse_scsi_configuration(None, v_hctl, 'Closing')
+
+ if serverType == SERVER_XEN_API:
+
+ target_ref = None
+ for dscsi_ref in server.xenapi.VM.get_DSCSIs(get_single_vm(dom)):
+ if v_hctl == server.xenapi.DSCSI.get_virtual_HCTL(dscsi_ref):
+ target_ref = dscsi_ref
+ break
+ if target_ref is None:
+ raise OptionError("Device %s not assigned" % v_hctl)
+
+ server.xenapi.DSCSI.destroy(target_ref)
+
+ else:
+ server.xend.domain.device_configure(dom, scsi)
def xm_vnet_list(args):
xenapi_unsupported()
diff -r 22c89412fc8c -r 9404bcb6d32e tools/python/xen/xm/xenapi_create.py
--- a/tools/python/xen/xm/xenapi_create.py Wed Oct 15 15:58:09 2008 +0100
+++ b/tools/python/xen/xm/xenapi_create.py Thu Oct 16 09:50:18 2008 +0100
@@ -375,6 +375,12 @@ class xenapi_create:
self.create_pcis(vm_ref, pcis)
+ # Now create scsis
+
+ scsis = vm.getElementsByTagName("vscsi")
+
+ self.create_scsis(vm_ref, scsis)
+
return vm_ref
except:
server.xenapi.VM.destroy(vm_ref)
@@ -532,6 +538,33 @@ class xenapi_create:
return server.xenapi.DPCI.create(dpci_record)
+ def create_scsis(self, vm_ref, scsis):
+ log(DEBUG, "create_scsis")
+ return map(lambda scsi: self.create_scsi(vm_ref, scsi), scsis)
+
+ def create_scsi(self, vm_ref, scsi):
+ log(DEBUG, "create_scsi")
+
+ target_ref = None
+ for pscsi_ref in server.xenapi.PSCSI.get_all():
+ if scsi.attributes["p-dev"].value ==
server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
+ target_ref = pscsi_ref
+ break
+ if target_ref is None:
+ log(DEBUG, "create_scsi: scsi device not found")
+ return None
+
+ dscsi_record = {
+ "VM":
+ vm_ref,
+ "PSCSI":
+ target_ref,
+ "virtual_HCTL":
+ scsi.attributes["v-dev"].value
+ }
+
+ return server.xenapi.DSCSI.create(dscsi_record)
+
def get_child_by_name(exp, childname, default = None):
try:
return [child for child in sxp.children(exp)
@@ -562,6 +595,9 @@ class sxp2xml:
pcis_sxp = map(lambda x: x[1], [device for device in devices
if device[1][0] == "pci"])
+
+ scsis_sxp = map(lambda x: x[1], [device for device in devices
+ if device[1][0] == "vscsi"])
# Create XML Document
@@ -704,6 +740,12 @@ class sxp2xml:
map(vm.appendChild, pcis)
+ # And now the scsis
+
+ scsis = self.extract_scsis(scsis_sxp, document)
+
+ map(vm.appendChild, scsis)
+
# Last but not least the consoles...
consoles = self.extract_consoles(image, document)
@@ -893,6 +935,23 @@ class sxp2xml:
pcis.append(pci)
return pcis
+
+ def extract_scsis(self, scsis_sxp, document):
+
+ scsis = []
+
+ for scsi_sxp in scsis_sxp:
+ for dev_sxp in sxp.children(scsi_sxp, "dev"):
+ scsi = document.createElement("vscsi")
+
+ scsi.attributes["p-dev"] \
+ = get_child_by_name(dev_sxp, "p-dev")
+ scsi.attributes["v-dev"] \
+ = get_child_by_name(dev_sxp, "v-dev")
+
+ scsis.append(scsi)
+
+ return scsis
def mk_other_config(self, key, value, document):
other_config = document.createElement("other_config")
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|