GPFS and other file based drivers require a LocalConnector to support
volume connection and migration operations.
Modify brick/initiator/connector.py to add LocalConnector class.
Modify test_brick_connector.py to extend test_factory to include LocalConnector
class.
Modify test_gpfs.py to include new migrate_volume test.
Modify test_utils.py to extend test_brick_get_connector to include LocalConnector
class.
Closes-Bug: #
1218052
Change-Id: I259fae339c2df7ae304a91c80c27d135762041f5
execute=execute,
driver=driver,
root_helper=root_helper)
+
+ elif protocol == "LOCAL":
+ return LocalConnector(execute=execute,
+ driver=driver,
+ root_helper=root_helper)
else:
msg = (_("Invalid InitiatorConnector protocol "
"specified %(protocol)s") %
def disconnect_volume(self, connection_properties, device_info):
"""No need to do anything to disconnect a volume in a filesystem."""
+
+
+class LocalConnector(InitiatorConnector):
+ """"Connector class to attach/detach File System backed volumes."""
+
+ def __init__(self, root_helper, driver=None, execute=putils.execute,
+ *args, **kwargs):
+ super(LocalConnector, self).__init__(root_helper,
+ driver,
+ execute,
+ *args,
+ **kwargs)
+
+ def connect_volume(self, connection_properties):
+ """Connect to a volume.
+
+ connection_properties must include:
+ device_path - path to the volume to be connected
+ """
+ if 'device_path' not in connection_properties:
+ msg = (_("Invalid connection_properties specified "
+ "no device_path attribute"))
+ raise ValueError(msg)
+
+ device_info = {'type': 'local',
+ 'path': connection_properties['device_path']}
+ return device_info
+
+ def disconnect_volume(self, connection_properties, device_info):
+ """Disconnect a volume from the local host."""
pass
obj = connector.InitiatorConnector.factory('glusterfs', None)
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_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.assertTrue(dev_info['type'] == 'local')
+ self.assertTrue(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)
self.volume.delete_volume(self.context, volume_id)
self.assertFalse(os.path.exists(path))
+ def test_migrate_volume(self):
+ """Test volume migration done by driver."""
+ loc = 'GPFSDriver:cindertest:openstack'
+ cap = {'location_info': loc}
+ host = {'host': 'foo', 'capabilities': cap}
+ volume = test_utils.create_volume(self.context, host=CONF.host)
+ self.driver.create_volume(volume)
+ self.driver.migrate_volume(self.context, volume, host)
+ self.driver.delete_volume(volume)
+
def _create_snapshot(self, volume_id, size='0'):
"""Create a snapshot object."""
snap = {}
driver=None,
root_helper=root_helper)
+ self.mox.StubOutClassWithMocks(connector, 'LocalConnector')
+ connector.LocalConnector(execute=putils.execute,
+ driver=None,
+ root_helper=root_helper)
+
self.mox.ReplayAll()
utils.brick_get_connector('iscsi')
utils.brick_get_connector('fibre_channel')
utils.brick_get_connector('aoe')
+ utils.brick_get_connector('local')
self.mox.VerifyAll()