summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorWalter A. Boring IV <walter.boring@hp.com>2013-01-17 16:36:22 -0800
committerWalter A. Boring IV <walter.boring@hp.com>2013-02-18 18:15:40 -0800
commit052859fbdb10f7f796512ef4f9a3d6e87fd3f87f (patch)
tree41f05d0df45d05d91852a0086d86c156729f2937 /nova/tests
parent7106ba954e8fab3d81429413003203398aebe2ac (diff)
Fibre channel block storage support (nova changes)
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
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/fake_libvirt_utils.py54
-rw-r--r--nova/tests/test_libvirt.py6
-rw-r--r--nova/tests/test_libvirt_volume.py79
3 files changed, 138 insertions, 1 deletions
diff --git a/nova/tests/fake_libvirt_utils.py b/nova/tests/fake_libvirt_utils.py
index 285a4b7e3..caa5e72d1 100644
--- a/nova/tests/fake_libvirt_utils.py
+++ b/nova/tests/fake_libvirt_utils.py
@@ -34,6 +34,60 @@ def get_iscsi_initiator():
return "fake.initiator.iqn"
+def get_fc_hbas():
+ return [{'ClassDevice': 'host1',
+ 'ClassDevicePath': '/sys/devices/pci0000:00/0000:00:03.0'
+ '/0000:05:00.2/host1/fc_host/host1',
+ 'dev_loss_tmo': '30',
+ 'fabric_name': '0x1000000533f55566',
+ 'issue_lip': '<store method only>',
+ 'max_npiv_vports': '255',
+ 'maxframe_size': '2048 bytes',
+ 'node_name': '0x200010604b019419',
+ 'npiv_vports_inuse': '0',
+ 'port_id': '0x680409',
+ 'port_name': '0x100010604b019419',
+ 'port_state': 'Online',
+ 'port_type': 'NPort (fabric via point-to-point)',
+ 'speed': '10 Gbit',
+ 'supported_classes': 'Class 3',
+ 'supported_speeds': '10 Gbit',
+ 'symbolic_name': 'Emulex 554M FV4.0.493.0 DV8.3.27',
+ 'tgtid_bind_type': 'wwpn (World Wide Port Name)',
+ 'uevent': None,
+ 'vport_create': '<store method only>',
+ 'vport_delete': '<store method only>'}]
+
+
+def get_fc_hbas_info():
+ hbas = get_fc_hbas()
+ info = [{'port_name': hbas[0]['port_name'].replace('0x', ''),
+ 'node_name': hbas[0]['node_name'].replace('0x', ''),
+ 'host_device': hbas[0]['ClassDevice'],
+ 'device_path': hbas[0]['ClassDevicePath']}]
+ return info
+
+
+def get_fc_wwpns():
+ hbas = get_fc_hbas()
+ wwpns = []
+ for hba in hbas:
+ wwpn = hba['port_name'].replace('0x', '')
+ wwpns.append(wwpn)
+
+ return wwpns
+
+
+def get_fc_wwnns():
+ hbas = get_fc_hbas()
+ wwnns = []
+ for hba in hbas:
+ wwnn = hba['node_name'].replace('0x', '')
+ wwnns.append(wwnn)
+
+ return wwnns
+
+
def create_image(disk_format, path, size):
pass
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 6cff3f567..2c5b07428 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -338,6 +338,8 @@ class LibvirtConnTestCase(test.TestCase):
initiator = 'fake.initiator.iqn'
ip = 'fakeip'
host = 'fakehost'
+ wwpns = ['100010604b019419']
+ wwnns = ['200010604b019419']
self.flags(my_ip=ip)
self.flags(host=host)
@@ -345,7 +347,9 @@ class LibvirtConnTestCase(test.TestCase):
expected = {
'ip': ip,
'initiator': initiator,
- 'host': host
+ 'host': host,
+ 'wwpns': wwpns,
+ 'wwnns': wwnns
}
volume = {
'id': 'fake'
diff --git a/nova/tests/test_libvirt_volume.py b/nova/tests/test_libvirt_volume.py
index 1d157ba34..fa71782ee 100644
--- a/nova/tests/test_libvirt_volume.py
+++ b/nova/tests/test_libvirt_volume.py
@@ -17,10 +17,14 @@
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
@@ -467,3 +471,78 @@ class LibvirtVolumeTestCase(test.TestCase):
('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)