
implements blueprint libvirt-fibre-channel These changes constitute the required libvirt changes to support attaching Fibre Channel volumes to a VM. This requires a few new packages to be available on the system sysfsutils -- This is needed to discover the FC HBAs sg3-utils -- this package is needed for scsi device discovery multipath -- This package is needed for multipath support. Typical Fibre Channel arrays support exporting volumes via multiple ports, so multipath support is highly desirable for fault tolerance. If multipath is not installed, the new FibreChannel libvirt volume driver will still work. If multipath is enabled, the new Fibre Channel volume driver detects each of the attached devices for the volume, and properly removes every one of them on detach. In order to use this, the cinder volume driver's initialize_connection will simply return a dictionary with a new driver_volume_type called 'fibrechan'. The target_wwn can be a single entry or a list of wwns that correspond to the list of remote wwn(s) that will export the volume. return {'driver_volume_type': 'fibre_channel', 'data': {'target_lun', 1, 'target_wwn': '1234567890123'}} or return {'driver_volume_type': 'fibre_channel', 'data': {'target_lun', 1, 'target_wwn': ['1234567890123', '0987654321321']}} Change-Id: Ifccc56f960ef434f7cb56a9367e4cad288358440
549 lines
23 KiB
Python
549 lines
23 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
#
|
|
# Copyright 2010 OpenStack LLC
|
|
# Copyright 2012 University Of Minho
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import os
|
|
|
|
from nova import exception
|
|
from nova.openstack.common import cfg
|
|
from nova.storage import linuxscsi
|
|
from nova import test
|
|
from nova.tests import fake_libvirt_utils
|
|
from nova import utils
|
|
from nova.virt import fake
|
|
from nova.virt.libvirt import utils as libvirt_utils
|
|
from nova.virt.libvirt import volume
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
class LibvirtVolumeTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(LibvirtVolumeTestCase, self).setUp()
|
|
self.executes = []
|
|
|
|
def fake_execute(*cmd, **kwargs):
|
|
self.executes.append(cmd)
|
|
return None, None
|
|
|
|
self.stubs.Set(utils, 'execute', fake_execute)
|
|
|
|
class FakeLibvirtDriver(object):
|
|
def __init__(self, hyperv="QEMU"):
|
|
self.hyperv = hyperv
|
|
|
|
def get_hypervisor_type(self):
|
|
return self.hyperv
|
|
|
|
def get_all_block_devices(self):
|
|
return []
|
|
|
|
self.fake_conn = FakeLibvirtDriver(fake.FakeVirtAPI())
|
|
self.connr = {
|
|
'ip': '127.0.0.1',
|
|
'initiator': 'fake_initiator',
|
|
'host': 'fake_host'
|
|
}
|
|
|
|
def test_libvirt_volume_driver_serial(self):
|
|
libvirt_driver = volume.LibvirtVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = {
|
|
'driver_volume_type': 'fake',
|
|
'data': {
|
|
'device_path': '/foo',
|
|
},
|
|
'serial': 'fake_serial',
|
|
}
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'block')
|
|
self.assertEqual(tree.find('./serial').text, 'fake_serial')
|
|
|
|
def iscsi_connection(self, volume, location, iqn):
|
|
return {
|
|
'driver_volume_type': 'iscsi',
|
|
'data': {
|
|
'volume_id': volume['id'],
|
|
'target_portal': location,
|
|
'target_iqn': iqn,
|
|
'target_lun': 1,
|
|
}
|
|
}
|
|
|
|
def test_libvirt_iscsi_driver(self):
|
|
# NOTE(vish) exists is to make driver assume connecting worked
|
|
self.stubs.Set(os.path, 'exists', lambda x: True)
|
|
libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn)
|
|
location = '10.0.2.15:3260'
|
|
name = 'volume-00000001'
|
|
iqn = 'iqn.2010-10.org.openstack:%s' % name
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.iscsi_connection(vol, location, iqn)
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
dev_str = '/dev/disk/by-path/ip-%s-iscsi-%s-lun-1' % (location, iqn)
|
|
self.assertEqual(tree.get('type'), 'block')
|
|
self.assertEqual(tree.find('./source').get('dev'), dev_str)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
expected_commands = [('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location),
|
|
('iscsiadm', '-m', 'session'),
|
|
('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location, '--login'),
|
|
('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location, '--op', 'update',
|
|
'-n', 'node.startup', '-v', 'automatic'),
|
|
('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location, '--op', 'update',
|
|
'-n', 'node.startup', '-v', 'manual'),
|
|
('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location, '--logout'),
|
|
('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location, '--op', 'delete')]
|
|
self.assertEqual(self.executes, expected_commands)
|
|
|
|
def test_libvirt_iscsi_driver_still_in_use(self):
|
|
# NOTE(vish) exists is to make driver assume connecting worked
|
|
self.stubs.Set(os.path, 'exists', lambda x: True)
|
|
libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn)
|
|
location = '10.0.2.15:3260'
|
|
name = 'volume-00000001'
|
|
iqn = 'iqn.2010-10.org.openstack:%s' % name
|
|
devs = ['/dev/disk/by-path/ip-%s-iscsi-%s-lun-1' % (location, iqn)]
|
|
self.stubs.Set(self.fake_conn, 'get_all_block_devices', lambda: devs)
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.iscsi_connection(vol, location, iqn)
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
dev_str = '/dev/disk/by-path/ip-%s-iscsi-%s-lun-1' % (location, iqn)
|
|
self.assertEqual(tree.get('type'), 'block')
|
|
self.assertEqual(tree.find('./source').get('dev'), dev_str)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
expected_commands = [('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location),
|
|
('iscsiadm', '-m', 'session'),
|
|
('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location, '--login'),
|
|
('iscsiadm', '-m', 'node', '-T', iqn,
|
|
'-p', location, '--op', 'update',
|
|
'-n', 'node.startup', '-v', 'automatic')]
|
|
self.assertEqual(self.executes, expected_commands)
|
|
|
|
def sheepdog_connection(self, volume):
|
|
return {
|
|
'driver_volume_type': 'sheepdog',
|
|
'data': {
|
|
'name': volume['name']
|
|
}
|
|
}
|
|
|
|
def test_libvirt_sheepdog_driver(self):
|
|
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.sheepdog_connection(vol)
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'network')
|
|
self.assertEqual(tree.find('./source').get('protocol'), 'sheepdog')
|
|
self.assertEqual(tree.find('./source').get('name'), name)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
def rbd_connection(self, volume):
|
|
return {
|
|
'driver_volume_type': 'rbd',
|
|
'data': {
|
|
'name': '%s/%s' % ('rbd', volume['name']),
|
|
'auth_enabled': CONF.rbd_secret_uuid is not None,
|
|
'auth_username': CONF.rbd_user,
|
|
'secret_type': 'ceph',
|
|
'secret_uuid': CONF.rbd_secret_uuid,
|
|
}
|
|
}
|
|
|
|
def test_libvirt_rbd_driver(self):
|
|
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.rbd_connection(vol)
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'network')
|
|
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
|
|
rbd_name = '%s/%s' % ('rbd', name)
|
|
self.assertEqual(tree.find('./source').get('name'), rbd_name)
|
|
self.assertEqual(tree.find('./source/auth'), None)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
def test_libvirt_rbd_driver_auth_enabled(self):
|
|
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.rbd_connection(vol)
|
|
uuid = '875a8070-d0b9-4949-8b31-104d125c9a64'
|
|
user = 'foo'
|
|
secret_type = 'ceph'
|
|
connection_info['data']['auth_enabled'] = True
|
|
connection_info['data']['auth_username'] = user
|
|
connection_info['data']['secret_type'] = secret_type
|
|
connection_info['data']['secret_uuid'] = uuid
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'network')
|
|
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
|
|
rbd_name = '%s/%s' % ('rbd', name)
|
|
self.assertEqual(tree.find('./source').get('name'), rbd_name)
|
|
self.assertEqual(tree.find('./auth').get('username'), user)
|
|
self.assertEqual(tree.find('./auth/secret').get('type'), secret_type)
|
|
self.assertEqual(tree.find('./auth/secret').get('uuid'), uuid)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
def test_libvirt_rbd_driver_auth_enabled_flags_override(self):
|
|
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.rbd_connection(vol)
|
|
uuid = '875a8070-d0b9-4949-8b31-104d125c9a64'
|
|
user = 'foo'
|
|
secret_type = 'ceph'
|
|
connection_info['data']['auth_enabled'] = True
|
|
connection_info['data']['auth_username'] = user
|
|
connection_info['data']['secret_type'] = secret_type
|
|
connection_info['data']['secret_uuid'] = uuid
|
|
|
|
flags_uuid = '37152720-1785-11e2-a740-af0c1d8b8e4b'
|
|
flags_user = 'bar'
|
|
self.flags(rbd_user=flags_user,
|
|
rbd_secret_uuid=flags_uuid)
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'network')
|
|
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
|
|
rbd_name = '%s/%s' % ('rbd', name)
|
|
self.assertEqual(tree.find('./source').get('name'), rbd_name)
|
|
self.assertEqual(tree.find('./auth').get('username'), flags_user)
|
|
self.assertEqual(tree.find('./auth/secret').get('type'), secret_type)
|
|
self.assertEqual(tree.find('./auth/secret').get('uuid'), flags_uuid)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
def test_libvirt_rbd_driver_auth_disabled(self):
|
|
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.rbd_connection(vol)
|
|
uuid = '875a8070-d0b9-4949-8b31-104d125c9a64'
|
|
user = 'foo'
|
|
secret_type = 'ceph'
|
|
connection_info['data']['auth_enabled'] = False
|
|
connection_info['data']['auth_username'] = user
|
|
connection_info['data']['secret_type'] = secret_type
|
|
connection_info['data']['secret_uuid'] = uuid
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'network')
|
|
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
|
|
rbd_name = '%s/%s' % ('rbd', name)
|
|
self.assertEqual(tree.find('./source').get('name'), rbd_name)
|
|
self.assertEqual(tree.find('./auth'), None)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
def test_libvirt_rbd_driver_auth_disabled_flags_override(self):
|
|
libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.rbd_connection(vol)
|
|
uuid = '875a8070-d0b9-4949-8b31-104d125c9a64'
|
|
user = 'foo'
|
|
secret_type = 'ceph'
|
|
connection_info['data']['auth_enabled'] = False
|
|
connection_info['data']['auth_username'] = user
|
|
connection_info['data']['secret_type'] = secret_type
|
|
connection_info['data']['secret_uuid'] = uuid
|
|
|
|
# NOTE: Supplying the rbd_secret_uuid will enable authentication
|
|
# locally in nova-compute even if not enabled in nova-volume/cinder
|
|
flags_uuid = '37152720-1785-11e2-a740-af0c1d8b8e4b'
|
|
flags_user = 'bar'
|
|
self.flags(rbd_user=flags_user,
|
|
rbd_secret_uuid=flags_uuid)
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'network')
|
|
self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
|
|
rbd_name = '%s/%s' % ('rbd', name)
|
|
self.assertEqual(tree.find('./source').get('name'), rbd_name)
|
|
self.assertEqual(tree.find('./auth').get('username'), flags_user)
|
|
self.assertEqual(tree.find('./auth/secret').get('type'), secret_type)
|
|
self.assertEqual(tree.find('./auth/secret').get('uuid'), flags_uuid)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
def test_libvirt_kvm_volume(self):
|
|
self.stubs.Set(os.path, 'exists', lambda x: True)
|
|
libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
location = '10.0.2.15:3260'
|
|
iqn = 'iqn.2010-10.org.openstack:%s' % name
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.iscsi_connection(vol, location, iqn)
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
dev_str = '/dev/disk/by-path/ip-%s-iscsi-%s-lun-1' % (location, iqn)
|
|
self.assertEqual(tree.get('type'), 'block')
|
|
self.assertEqual(tree.find('./source').get('dev'), dev_str)
|
|
libvirt_driver.disconnect_volume(connection_info, 'vde')
|
|
|
|
def test_libvirt_kvm_volume_with_multipath(self):
|
|
self.flags(libvirt_iscsi_use_multipath=True)
|
|
self.stubs.Set(os.path, 'exists', lambda x: True)
|
|
devs = ['/dev/mapper/sda', '/dev/mapper/sdb']
|
|
self.stubs.Set(self.fake_conn, 'get_all_block_devices', lambda: devs)
|
|
libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn)
|
|
name = 'volume-00000001'
|
|
location = '10.0.2.15:3260'
|
|
iqn = 'iqn.2010-10.org.openstack:%s' % name
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.iscsi_connection(vol, location, iqn)
|
|
mpdev_filepath = '/dev/mapper/foo'
|
|
connection_info['data']['device_path'] = mpdev_filepath
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
target_portals = ['fake_portal1', 'fake_portal2']
|
|
libvirt_driver._get_multipath_device_name = lambda x: mpdev_filepath
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.find('./source').get('dev'), mpdev_filepath)
|
|
libvirt_driver.disconnect_volume(connection_info, 'vde')
|
|
|
|
def test_libvirt_nfs_driver(self):
|
|
# NOTE(vish) exists is to make driver assume connecting worked
|
|
mnt_base = '/mnt'
|
|
self.flags(nfs_mount_point_base=mnt_base)
|
|
|
|
libvirt_driver = volume.LibvirtNFSVolumeDriver(self.fake_conn)
|
|
export_string = '192.168.1.1:/nfs/share1'
|
|
name = 'volume-00001'
|
|
export_mnt_base = os.path.join(mnt_base,
|
|
libvirt_driver.get_hash_str(export_string))
|
|
file_path = os.path.join(export_mnt_base, name)
|
|
|
|
connection_info = {'data': {'export': export_string, 'name': name}}
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'file')
|
|
self.assertEqual(tree.find('./source').get('file'), file_path)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
expected_commands = [
|
|
('stat', export_mnt_base),
|
|
('mount', '-t', 'nfs', export_string, export_mnt_base)]
|
|
self.assertEqual(self.executes, expected_commands)
|
|
|
|
def aoe_connection(self, shelf, lun):
|
|
return {
|
|
'driver_volume_type': 'aoe',
|
|
'data': {
|
|
'target_shelf': shelf,
|
|
'target_lun': lun,
|
|
}
|
|
}
|
|
|
|
def test_libvirt_aoe_driver(self):
|
|
# NOTE(jbr_) exists is to make driver assume connecting worked
|
|
self.stubs.Set(os.path, 'exists', lambda x: True)
|
|
libvirt_driver = volume.LibvirtAOEVolumeDriver(self.fake_conn)
|
|
shelf = '100'
|
|
lun = '1'
|
|
connection_info = self.aoe_connection(shelf, lun)
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
aoedevpath = '/dev/etherd/e%s.%s' % (shelf, lun)
|
|
self.assertEqual(tree.get('type'), 'block')
|
|
self.assertEqual(tree.find('./source').get('dev'), aoedevpath)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
def test_libvirt_glusterfs_driver(self):
|
|
mnt_base = '/mnt'
|
|
self.flags(glusterfs_mount_point_base=mnt_base)
|
|
|
|
libvirt_driver = volume.LibvirtGlusterfsVolumeDriver(self.fake_conn)
|
|
export_string = '192.168.1.1:/volume-00001'
|
|
name = 'volume-00001'
|
|
export_mnt_base = os.path.join(mnt_base,
|
|
libvirt_driver.get_hash_str(export_string))
|
|
file_path = os.path.join(export_mnt_base, name)
|
|
|
|
connection_info = {'data': {'export': export_string, 'name': name}}
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": "vde",
|
|
"type": "disk",
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
self.assertEqual(tree.get('type'), 'file')
|
|
self.assertEqual(tree.find('./source').get('file'), file_path)
|
|
libvirt_driver.disconnect_volume(connection_info, "vde")
|
|
|
|
expected_commands = [
|
|
('stat', export_mnt_base),
|
|
('mount', '-t', 'glusterfs', export_string, export_mnt_base)]
|
|
self.assertEqual(self.executes, expected_commands)
|
|
|
|
def fibrechan_connection(self, volume, location, wwn):
|
|
return {
|
|
'driver_volume_type': 'fibrechan',
|
|
'data': {
|
|
'volume_id': volume['id'],
|
|
'target_portal': location,
|
|
'target_wwn': wwn,
|
|
'target_lun': 1,
|
|
}
|
|
}
|
|
|
|
def test_libvirt_fibrechan_driver(self):
|
|
self.stubs.Set(libvirt_utils, 'get_fc_hbas',
|
|
fake_libvirt_utils.get_fc_hbas)
|
|
self.stubs.Set(libvirt_utils, 'get_fc_hbas_info',
|
|
fake_libvirt_utils.get_fc_hbas_info)
|
|
# NOTE(vish) exists is to make driver assume connecting worked
|
|
self.stubs.Set(os.path, 'exists', lambda x: True)
|
|
self.stubs.Set(os.path, 'realpath', lambda x: '/dev/sdb')
|
|
libvirt_driver = volume.LibvirtFibreChannelVolumeDriver(self.fake_conn)
|
|
multipath_devname = '/dev/md-1'
|
|
devices = {"device": multipath_devname,
|
|
"devices": [{'device': '/dev/sdb',
|
|
'address': '1:0:0:1',
|
|
'host': 1, 'channel': 0,
|
|
'id': 0, 'lun': 1}]}
|
|
self.stubs.Set(linuxscsi, 'find_multipath_device', lambda x: devices)
|
|
self.stubs.Set(linuxscsi, 'remove_device', lambda x: None)
|
|
location = '10.0.2.15:3260'
|
|
name = 'volume-00000001'
|
|
wwn = '1234567890123456'
|
|
vol = {'id': 1, 'name': name}
|
|
connection_info = self.fibrechan_connection(vol, location, wwn)
|
|
mount_device = "vde"
|
|
disk_info = {
|
|
"bus": "virtio",
|
|
"dev": mount_device,
|
|
"type": "disk"
|
|
}
|
|
conf = libvirt_driver.connect_volume(connection_info, disk_info)
|
|
tree = conf.format_dom()
|
|
dev_str = '/dev/disk/by-path/pci-0000:05:00.2-fc-0x%s-lun-1' % wwn
|
|
self.assertEqual(tree.get('type'), 'block')
|
|
self.assertEqual(tree.find('./source').get('dev'), multipath_devname)
|
|
connection_info["data"]["devices"] = devices["devices"]
|
|
libvirt_driver.disconnect_volume(connection_info, mount_device)
|
|
expected_commands = []
|
|
self.assertEqual(self.executes, expected_commands)
|
|
|
|
self.stubs.Set(libvirt_utils, 'get_fc_hbas',
|
|
lambda: [])
|
|
self.stubs.Set(libvirt_utils, 'get_fc_hbas_info',
|
|
lambda: [])
|
|
self.assertRaises(exception.NovaException,
|
|
libvirt_driver.connect_volume,
|
|
connection_info, disk_info)
|
|
|
|
self.stubs.Set(libvirt_utils, 'get_fc_hbas', lambda: [])
|
|
self.stubs.Set(libvirt_utils, 'get_fc_hbas_info', lambda: [])
|
|
self.assertRaises(exception.NovaException,
|
|
libvirt_driver.connect_volume,
|
|
connection_info, disk_info)
|
|
|
|
def test_libvirt_fibrechan_getpci_num(self):
|
|
libvirt_driver = volume.LibvirtFibreChannelVolumeDriver(self.fake_conn)
|
|
hba = {'device_path': "/sys/devices/pci0000:00/0000:00:03.0"
|
|
"/0000:05:00.3/host2/fc_host/host2"}
|
|
pci_num = libvirt_driver._get_pci_num(hba)
|
|
self.assertEqual("0000:05:00.3", pci_num)
|
|
|
|
hba = {'device_path': "/sys/devices/pci0000:00/0000:00:03.0"
|
|
"/0000:05:00.3/0000:06:00.6/host2/fc_host/host2"}
|
|
pci_num = libvirt_driver._get_pci_num(hba)
|
|
self.assertEqual("0000:06:00.6", pci_num)
|