cinder/cinder/tests/brick/test_brick_connector.py

645 lines
28 KiB
Python

# (c) Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# 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.path
import string
import time
from cinder.brick import exception
from cinder.brick.initiator import connector
from cinder.brick.initiator import host_driver
from cinder.i18n import _
from cinder.openstack.common import log as logging
from cinder.openstack.common import loopingcall
from cinder.openstack.common import processutils as putils
from cinder import test
LOG = logging.getLogger(__name__)
class ConnectorTestCase(test.TestCase):
def setUp(self):
super(ConnectorTestCase, self).setUp()
self.cmds = []
def fake_execute(self, *cmd, **kwargs):
self.cmds.append(string.join(cmd))
return "", None
def test_connect_volume(self):
self.connector = connector.InitiatorConnector(None)
self.assertRaises(NotImplementedError,
self.connector.connect_volume, None)
def test_disconnect_volume(self):
self.connector = connector.InitiatorConnector(None)
self.assertRaises(NotImplementedError,
self.connector.disconnect_volume, None, None)
def test_factory(self):
obj = connector.InitiatorConnector.factory('iscsi', None)
self.assertEqual(obj.__class__.__name__, "ISCSIConnector")
obj = connector.InitiatorConnector.factory('fibre_channel', None)
self.assertEqual(obj.__class__.__name__, "FibreChannelConnector")
obj = connector.InitiatorConnector.factory('aoe', None)
self.assertEqual(obj.__class__.__name__, "AoEConnector")
obj = connector.InitiatorConnector.factory(
'nfs', None, nfs_mount_point_base='/mnt/test')
self.assertEqual(obj.__class__.__name__, "RemoteFsConnector")
obj = connector.InitiatorConnector.factory(
'glusterfs', None, glusterfs_mount_point_base='/mnt/test')
self.assertEqual(obj.__class__.__name__, "RemoteFsConnector")
obj = connector.InitiatorConnector.factory('local', None)
self.assertEqual(obj.__class__.__name__, "LocalConnector")
self.assertRaises(ValueError,
connector.InitiatorConnector.factory,
"bogus", None)
def test_check_valid_device_with_wrong_path(self):
self.connector = connector.InitiatorConnector(None)
self.stubs.Set(self.connector,
'_execute', lambda *args, **kwargs: ("", None))
self.assertFalse(self.connector.check_valid_device('/d0v'))
def test_check_valid_device(self):
self.connector = connector.InitiatorConnector(None)
self.stubs.Set(self.connector,
'_execute', lambda *args, **kwargs: ("", ""))
self.assertTrue(self.connector.check_valid_device('/dev'))
def test_check_valid_device_with_cmd_error(self):
def raise_except(*args, **kwargs):
raise putils.ProcessExecutionError
self.connector = connector.InitiatorConnector(None)
self.stubs.Set(self.connector,
'_execute', raise_except)
self.assertFalse(self.connector.check_valid_device('/dev'))
class HostDriverTestCase(test.TestCase):
def setUp(self):
super(HostDriverTestCase, self).setUp()
self.stubs.Set(os.path, 'isdir', lambda x: True)
self.devlist = ['device1', 'device2']
self.stubs.Set(os, 'listdir', lambda x: self.devlist)
def test_host_driver(self):
expected = ['/dev/disk/by-path/' + dev for dev in self.devlist]
driver = host_driver.HostDriver()
actual = driver.get_all_block_devices()
self.assertEqual(expected, actual)
class ISCSIConnectorTestCase(ConnectorTestCase):
def setUp(self):
super(ISCSIConnectorTestCase, self).setUp()
self.connector = connector.ISCSIConnector(
None, execute=self.fake_execute, use_multipath=False)
self.stubs.Set(self.connector._linuxscsi,
'get_name_from_path', lambda x: "/dev/sdb")
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_get_initiator(self):
def initiator_no_file(*args, **kwargs):
raise putils.ProcessExecutionError('No file')
def initiator_get_text(*arg, **kwargs):
text = ('## DO NOT EDIT OR REMOVE THIS FILE!\n'
'## If you remove this file, the iSCSI daemon '
'will not start.\n'
'## If you change the InitiatorName, existing '
'access control lists\n'
'## may reject this initiator. The InitiatorName must '
'be unique\n'
'## for each iSCSI initiator. Do NOT duplicate iSCSI '
'InitiatorNames.\n'
'InitiatorName=iqn.1234-56.foo.bar:01:23456789abc')
return text, None
self.stubs.Set(self.connector, '_execute', initiator_no_file)
initiator = self.connector.get_initiator()
self.assertIsNone(initiator)
self.stubs.Set(self.connector, '_execute', initiator_get_text)
initiator = self.connector.get_initiator()
self.assertEqual(initiator, 'iqn.1234-56.foo.bar:01:23456789abc')
@test.testtools.skipUnless(os.path.exists('/dev/disk/by-path'),
'Test requires /dev/disk/by-path')
def test_connect_volume(self):
self.stubs.Set(os.path, 'exists', lambda x: True)
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)
device = self.connector.connect_volume(connection_info['data'])
dev_str = '/dev/disk/by-path/ip-%s-iscsi-%s-lun-1' % (location, iqn)
self.assertEqual(device['type'], 'block')
self.assertEqual(device['path'], dev_str)
self.connector.disconnect_volume(connection_info['data'], device)
expected_commands = [('iscsiadm -m node -T %s -p %s' %
(iqn, location)),
('iscsiadm -m session'),
('iscsiadm -m node -T %s -p %s --login' %
(iqn, location)),
('iscsiadm -m node -T %s -p %s --op update'
' -n node.startup -v automatic'
% (iqn, location)),
('iscsiadm -m node --rescan'),
('iscsiadm -m session --rescan'),
('blockdev --flushbufs /dev/sdb'),
('tee -a /sys/block/sdb/device/delete'),
('iscsiadm -m node -T %s -p %s --op update'
' -n node.startup -v manual' % (iqn, location)),
('iscsiadm -m node -T %s -p %s --logout' %
(iqn, location)),
('iscsiadm -m node -T %s -p %s --op delete' %
(iqn, location)), ]
LOG.debug("self.cmds = %s" % self.cmds)
LOG.debug("expected = %s" % expected_commands)
self.assertEqual(expected_commands, self.cmds)
def test_connect_volume_with_multipath(self):
location = '10.0.2.15:3260'
name = 'volume-00000001'
iqn = 'iqn.2010-10.org.openstack:%s' % name
vol = {'id': 1, 'name': name}
connection_properties = self.iscsi_connection(vol, location, iqn)
self.connector_with_multipath =\
connector.ISCSIConnector(None, use_multipath=True)
self.stubs.Set(self.connector_with_multipath,
'_run_iscsiadm_bare',
lambda *args, **kwargs: "%s %s" % (location, iqn))
self.stubs.Set(self.connector_with_multipath,
'_get_target_portals_from_iscsiadm_output',
lambda x: [[location, iqn]])
self.stubs.Set(self.connector_with_multipath,
'_connect_to_iscsi_portal',
lambda x: None)
self.stubs.Set(self.connector_with_multipath,
'_rescan_iscsi',
lambda: None)
self.stubs.Set(self.connector_with_multipath,
'_rescan_multipath',
lambda: None)
self.stubs.Set(self.connector_with_multipath,
'_get_multipath_device_name',
lambda x: 'iqn.2010-10.org.openstack:%s' % name)
self.stubs.Set(os.path, 'exists', lambda x: True)
result = self.connector_with_multipath.connect_volume(
connection_properties['data'])
expected_result = {'path': 'iqn.2010-10.org.openstack:volume-00000001',
'type': 'block'}
self.assertEqual(result, expected_result)
def test_connect_volume_with_not_found_device(self):
self.stubs.Set(os.path, 'exists', lambda x: False)
self.stubs.Set(time, 'sleep', lambda x: None)
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)
self.assertRaises(exception.VolumeDeviceNotFound,
self.connector.connect_volume,
connection_info['data'])
def test_get_target_portals_from_iscsiadm_output(self):
connector = self.connector
test_output = '''10.15.84.19:3260 iqn.1992-08.com.netapp:sn.33615311
10.15.85.19:3260 iqn.1992-08.com.netapp:sn.33615311'''
res = connector._get_target_portals_from_iscsiadm_output(test_output)
ip_iqn1 = ['10.15.84.19:3260', 'iqn.1992-08.com.netapp:sn.33615311']
ip_iqn2 = ['10.15.85.19:3260', 'iqn.1992-08.com.netapp:sn.33615311']
expected = [ip_iqn1, ip_iqn2]
self.assertEqual(expected, res)
def test_get_multipath_device_name(self):
self.stubs.Set(os.path, 'realpath', lambda x: None)
multipath_return_string = [('mpath2 (20017380006c00036)'
'dm-7 IBM,2810XIV')]
self.stubs.Set(self.connector, '_run_multipath',
lambda *args, **kwargs: multipath_return_string)
expected = '/dev/mapper/mpath2'
self.assertEqual(expected,
self.connector.
_get_multipath_device_name('/dev/md-1'))
def test_get_iscsi_devices(self):
paths = [('ip-10.0.0.1:3260-iscsi-iqn.2013-01.ro.'
'com.netapp:node.netapp02-lun-0')]
self.stubs.Set(os, 'walk', lambda x: [(['.'], ['by-path'], paths)])
self.assertEqual(self.connector._get_iscsi_devices(), paths)
def test_get_iscsi_devices_with_empty_dir(self):
self.stubs.Set(os, 'walk', lambda x: [])
self.assertEqual(self.connector._get_iscsi_devices(), [])
def test_get_multipath_iqn(self):
paths = [('ip-10.0.0.1:3260-iscsi-iqn.2013-01.ro.'
'com.netapp:node.netapp02-lun-0')]
self.stubs.Set(os.path, 'realpath',
lambda x: '/dev/disk/by-path/%s' % paths[0])
self.stubs.Set(self.connector, '_get_iscsi_devices', lambda: paths)
self.stubs.Set(self.connector, '_get_multipath_device_name',
lambda x: paths[0])
self.assertEqual(self.connector._get_multipath_iqn(paths[0]),
'iqn.2013-01.ro.com.netapp:node.netapp02')
def test_disconnect_volume_multipath_iscsi(self):
result = []
def fake_disconnect_from_iscsi_portal(properties):
result.append(properties)
iqn1 = 'iqn.2013-01.ro.com.netapp:node.netapp01'
iqn2 = 'iqn.2013-01.ro.com.netapp:node.netapp02'
iqns = [iqn1, iqn2]
portal = '10.0.0.1:3260'
dev = ('ip-%s-iscsi-%s-lun-0' % (portal, iqn1))
self.stubs.Set(self.connector,
'_get_target_portals_from_iscsiadm_output',
lambda x: [[portal, iqn1]])
self.stubs.Set(self.connector, '_rescan_iscsi', lambda: None)
self.stubs.Set(self.connector, '_rescan_multipath', lambda: None)
self.stubs.Set(self.connector.driver, 'get_all_block_devices',
lambda: [dev, '/dev/mapper/md-1'])
self.stubs.Set(self.connector, '_get_multipath_device_name',
lambda x: '/dev/mapper/md-3')
self.stubs.Set(self.connector, '_get_multipath_iqn',
lambda x: iqns.pop())
self.stubs.Set(self.connector, '_disconnect_from_iscsi_portal',
fake_disconnect_from_iscsi_portal)
self.stubs.Set(os.path, 'exists', lambda x: True)
fake_property = {'target_portal': portal,
'target_iqn': iqn1}
self.connector._disconnect_volume_multipath_iscsi(fake_property,
'fake/multipath')
# Target in use by other mp devices, don't disconnect
self.assertEqual([], result)
def test_disconnect_volume_multipath_iscsi_without_other_mp_devices(self):
result = []
def fake_disconnect_from_iscsi_portal(properties):
result.append(properties)
portal = '10.0.2.15:3260'
name = 'volume-00000001'
iqn = 'iqn.2010-10.org.openstack:%s' % name
self.stubs.Set(self.connector,
'_get_target_portals_from_iscsiadm_output',
lambda x: [[portal, iqn]])
self.stubs.Set(self.connector, '_rescan_iscsi', lambda: None)
self.stubs.Set(self.connector, '_rescan_multipath', lambda: None)
self.stubs.Set(self.connector.driver, 'get_all_block_devices',
lambda: [])
self.stubs.Set(self.connector, '_disconnect_from_iscsi_portal',
fake_disconnect_from_iscsi_portal)
self.stubs.Set(os.path, 'exists', lambda x: True)
fake_property = {'target_portal': portal,
'target_iqn': iqn}
self.connector._disconnect_volume_multipath_iscsi(fake_property,
'fake/multipath')
# Target not in use by other mp devices, disconnect
self.assertEqual([fake_property], result)
def test_disconnect_volume_multipath_iscsi_with_invalid_symlink(self):
result = []
def fake_disconnect_from_iscsi_portal(properties):
result.append(properties)
portal = '10.0.0.1:3260'
name = 'volume-00000001'
iqn = 'iqn.2010-10.org.openstack:%s' % name
dev = ('ip-%s-iscsi-%s-lun-0' % (portal, iqn))
self.stubs.Set(self.connector,
'_get_target_portals_from_iscsiadm_output',
lambda x: [[portal, iqn]])
self.stubs.Set(self.connector, '_rescan_iscsi', lambda: None)
self.stubs.Set(self.connector, '_rescan_multipath', lambda: None)
self.stubs.Set(self.connector.driver, 'get_all_block_devices',
lambda: [dev, '/dev/mapper/md-1'])
self.stubs.Set(self.connector, '_disconnect_from_iscsi_portal',
fake_disconnect_from_iscsi_portal)
# Simulate a broken symlink by returning False for os.path.exists(dev)
self.stubs.Set(os.path, 'exists', lambda x: False)
fake_property = {'target_portal': portal,
'target_iqn': iqn}
self.connector._disconnect_volume_multipath_iscsi(fake_property,
'fake/multipath')
# Target not in use by other mp devices, disconnect
self.assertEqual([fake_property], result)
class FibreChannelConnectorTestCase(ConnectorTestCase):
def setUp(self):
super(FibreChannelConnectorTestCase, self).setUp()
self.connector = connector.FibreChannelConnector(
None, execute=self.fake_execute, use_multipath=False)
self.assertIsNotNone(self.connector)
self.assertIsNotNone(self.connector._linuxfc)
self.assertIsNotNone(self.connector._linuxscsi)
def fake_get_fc_hbas(self):
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 fake_get_fc_hbas_info(self):
hbas = self.fake_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 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_connect_volume(self):
self.stubs.Set(self.connector._linuxfc, "get_fc_hbas",
self.fake_get_fc_hbas)
self.stubs.Set(self.connector._linuxfc, "get_fc_hbas_info",
self.fake_get_fc_hbas_info)
self.stubs.Set(os.path, 'exists', lambda x: True)
self.stubs.Set(os.path, 'realpath', lambda x: '/dev/sdb')
multipath_devname = '/dev/md-1'
devices = {"device": multipath_devname,
"id": "1234567890",
"devices": [{'device': '/dev/sdb',
'address': '1:0:0:1',
'host': 1, 'channel': 0,
'id': 0, 'lun': 1}]}
self.stubs.Set(self.connector._linuxscsi, 'find_multipath_device',
lambda x: devices)
self.stubs.Set(self.connector._linuxscsi, 'remove_scsi_device',
lambda x: None)
self.stubs.Set(self.connector._linuxscsi, 'get_device_info',
lambda x: devices['devices'][0])
location = '10.0.2.15:3260'
name = 'volume-00000001'
vol = {'id': 1, 'name': name}
# Should work for string, unicode, and list
wwns = ['1234567890123456', unicode('1234567890123456'),
['1234567890123456', '1234567890123457']]
for wwn in wwns:
connection_info = self.fibrechan_connection(vol, location, wwn)
dev_info = self.connector.connect_volume(connection_info['data'])
exp_wwn = wwn[0] if isinstance(wwn, list) else wwn
dev_str = ('/dev/disk/by-path/pci-0000:05:00.2-fc-0x%s-lun-1' %
exp_wwn)
self.assertEqual(dev_info['type'], 'block')
self.assertEqual(dev_info['path'], dev_str)
self.connector.disconnect_volume(connection_info['data'], dev_info)
expected_commands = []
self.assertEqual(expected_commands, self.cmds)
# Should not work for anything other than string, unicode, and list
connection_info = self.fibrechan_connection(vol, location, 123)
self.assertRaises(exception.NoFibreChannelHostsFound,
self.connector.connect_volume,
connection_info['data'])
self.stubs.Set(self.connector._linuxfc, 'get_fc_hbas',
lambda: [])
self.stubs.Set(self.connector._linuxfc, 'get_fc_hbas_info',
lambda: [])
self.assertRaises(exception.NoFibreChannelHostsFound,
self.connector.connect_volume,
connection_info['data'])
class FakeFixedIntervalLoopingCall(object):
def __init__(self, f=None, *args, **kw):
self.args = args
self.kw = kw
self.f = f
self._stop = False
def stop(self):
self._stop = True
def wait(self):
return self
def start(self, interval, initial_delay=None):
while not self._stop:
try:
self.f(*self.args, **self.kw)
except loopingcall.LoopingCallDone:
return self
except Exception:
LOG.exception(_('in fixed duration looping call'))
raise
class AoEConnectorTestCase(ConnectorTestCase):
"""Test cases for AoE initiator class."""
def setUp(self):
super(AoEConnectorTestCase, self).setUp()
self.connector = connector.AoEConnector('sudo')
self.connection_properties = {'target_shelf': 'fake_shelf',
'target_lun': 'fake_lun'}
self.stubs.Set(loopingcall,
'FixedIntervalLoopingCall',
FakeFixedIntervalLoopingCall)
def _mock_path_exists(self, aoe_path, mock_values=None):
mock_values = mock_values or []
self.mox.StubOutWithMock(os.path, 'exists')
for value in mock_values:
os.path.exists(aoe_path).AndReturn(value)
def test_connect_volume(self):
"""Ensure that if path exist aoe-revaliadte was called."""
aoe_device, aoe_path = self.connector._get_aoe_info(
self.connection_properties)
self._mock_path_exists(aoe_path, [True, True])
self.mox.StubOutWithMock(self.connector, '_execute')
self.connector._execute('aoe-revalidate',
aoe_device,
run_as_root=True,
root_helper='sudo',
check_exit_code=0).AndReturn(("", ""))
self.mox.ReplayAll()
self.connector.connect_volume(self.connection_properties)
def test_connect_volume_without_path(self):
"""Ensure that if path doesn't exist aoe-discovery was called."""
aoe_device, aoe_path = self.connector._get_aoe_info(
self.connection_properties)
expected_info = {
'type': 'block',
'device': aoe_device,
'path': aoe_path,
}
self._mock_path_exists(aoe_path, [False, True])
self.mox.StubOutWithMock(self.connector, '_execute')
self.connector._execute('aoe-discover',
run_as_root=True,
root_helper='sudo',
check_exit_code=0).AndReturn(("", ""))
self.mox.ReplayAll()
volume_info = self.connector.connect_volume(
self.connection_properties)
self.assertDictMatch(volume_info, expected_info)
def test_connect_volume_could_not_discover_path(self):
aoe_device, aoe_path = self.connector._get_aoe_info(
self.connection_properties)
number_of_calls = 4
self._mock_path_exists(aoe_path, [False] * (number_of_calls + 1))
self.mox.StubOutWithMock(self.connector, '_execute')
for i in xrange(number_of_calls):
self.connector._execute('aoe-discover',
run_as_root=True,
root_helper='sudo',
check_exit_code=0).AndReturn(("", ""))
self.mox.ReplayAll()
self.assertRaises(exception.VolumeDeviceNotFound,
self.connector.connect_volume,
self.connection_properties)
def test_disconnect_volume(self):
"""Ensure that if path exist aoe-revaliadte was called."""
aoe_device, aoe_path = self.connector._get_aoe_info(
self.connection_properties)
self._mock_path_exists(aoe_path, [True])
self.mox.StubOutWithMock(self.connector, '_execute')
self.connector._execute('aoe-flush',
aoe_device,
run_as_root=True,
root_helper='sudo',
check_exit_code=0).AndReturn(("", ""))
self.mox.ReplayAll()
self.connector.disconnect_volume(self.connection_properties, {})
class RemoteFsConnectorTestCase(ConnectorTestCase):
"""Test cases for Remote FS initiator class."""
TEST_DEV = '172.18.194.100:/var/nfs'
TEST_PATH = '/mnt/test/df0808229363aad55c27da50c38d6328'
def setUp(self):
super(RemoteFsConnectorTestCase, self).setUp()
self.connection_properties = {
'export': self.TEST_DEV,
'name': '9c592d52-ce47-4263-8c21-4ecf3c029cdb'}
self.connector = connector.RemoteFsConnector(
'nfs', root_helper='sudo', nfs_mount_point_base='/mnt/test',
nfs_mount_options='vers=3')
def test_connect_volume(self):
"""Test the basic connect volume case."""
client = self.connector._remotefsclient
self.mox.StubOutWithMock(client, '_execute')
client._execute('mount',
check_exit_code=0).AndReturn(("", ""))
client._execute('mkdir', '-p', self.TEST_PATH,
check_exit_code=0).AndReturn(("", ""))
client._execute('mount', '-t', 'nfs', '-o', 'vers=3',
self.TEST_DEV, self.TEST_PATH,
root_helper='sudo', run_as_root=True,
check_exit_code=0).AndReturn(("", ""))
self.mox.ReplayAll()
self.connector.connect_volume(self.connection_properties)
def test_disconnect_volume(self):
"""Nothing should happen here -- make sure it doesn't blow up."""
self.connector.disconnect_volume(self.connection_properties, {})
class LocalConnectorTestCase(test.TestCase):
def setUp(self):
super(LocalConnectorTestCase, self).setUp()
self.connection_properties = {'name': 'foo',
'device_path': '/tmp/bar'}
def test_connect_volume(self):
self.connector = connector.LocalConnector(None)
cprops = self.connection_properties
dev_info = self.connector.connect_volume(cprops)
self.assertEqual(dev_info['type'], 'local')
self.assertEqual(dev_info['path'], cprops['device_path'])
def test_connect_volume_with_invalid_connection_data(self):
self.connector = connector.LocalConnector(None)
cprops = {}
self.assertRaises(ValueError,
self.connector.connect_volume, cprops)