]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Allow rexports for targets with Datera
authorMike Perez <thingee@gmail.com>
Thu, 7 May 2015 19:09:45 +0000 (12:09 -0700)
committerMike Perez <thingee@gmail.com>
Thu, 7 May 2015 19:14:13 +0000 (12:14 -0700)
Sometimes due to timing, rexporting a target would fail. This will
verify with Datera if a target already exists, or if it should recreate
an export.

Change-Id: I9c40603cbb525c23e010285bdc66efaaaf4be142
Closes-Bug: #1452838

cinder/tests/unit/volume/drivers/datera.py
cinder/volume/drivers/datera.py

index c780f0fbdfbf459441df4d3595ac1a7927abcd08..cb90de81864b13ae24b2f8d712243544ca6c342e 100644 (file)
@@ -158,10 +158,10 @@ class DateraVolumeTestCase(test.TestCase):
                           self.driver.delete_volume, self.volume)
 
     def test_ensure_export_success(self):
-        self.mock_api.return_value = stub_export
+        self.mock_api.side_effect = self._generate_fake_api_request()
         ctxt = context.get_admin_context()
         expected = {
-            'provider_location': u'172.28.121.10:3260 iqn.2013-05.com.daterain'
+            'provider_location': '172.28.121.10:3260 iqn.2013-05.com.daterain'
                                  'c::01:sn:fc372bc0490b2dbe 0'
         }
         self.assertEqual(expected, self.driver.ensure_export(ctxt,
@@ -173,13 +173,15 @@ class DateraVolumeTestCase(test.TestCase):
         self.assertRaises(exception.DateraAPIException,
                           self.driver.ensure_export, ctxt, self.volume)
 
-    def test_create_export_success(self):
-        self.mock_api.return_value = stub_export
+    def test_create_export_target_does_not_exist_success(self):
+        self.mock_api.side_effect = self._generate_fake_api_request(
+            targets_exist=False)
         ctxt = context.get_admin_context()
         expected = {
-            'provider_location': u'172.28.121.10:3260 iqn.2013-05.com.daterain'
-                                 'c::01:sn:fc372bc0490b2dbe 0'
+            'provider_location': '172.28.121.10:3260 iqn.2013-05.com.daterainc'
+                                 '::01:sn:fc372bc0490b2dbe 0'
         }
+
         self.assertEqual(expected, self.driver.create_export(ctxt,
                                                              self.volume))
 
@@ -305,7 +307,26 @@ class DateraVolumeTestCase(test.TestCase):
         self.assertRaises(exception.NotAuthorized, self.driver._login)
         self.assertEqual(1, self.mock_api.call_count)
 
-stub_export = {
+    def _generate_fake_api_request(self, targets_exist=True):
+        fake_volume = None
+        if not targets_exist:
+            fake_volume = _stub_datera_volume(targets={})
+        else:
+            fake_volume = _stub_datera_volume()
+
+        def _fake_api_request(resource_type, method='get', resource=None,
+                              body=None, action=None, sensitive=False):
+            if resource_type == 'volumes' and action is None:
+                return fake_volume
+            elif resource_type == 'volume' and action == 'export':
+                return stub_create_export
+            elif resource_type == 'export_configs':
+                return stub_get_export
+
+        return _fake_api_request
+
+
+stub_create_export = {
     u'_ipColl': [u'172.28.121.10', u'172.28.120.10'],
     u'acls': {},
     u'activeServers': {u'4594953e-f97f-e111-ad85-001e6738c0f0': u'1'},
@@ -348,6 +369,60 @@ stub_export = {
     u'uuid': u'7071efd7-9f22-4996-8f68-47e9ab19d0fd'
 }
 
+stub_get_export = {
+    "uuid": "744e1bd8-d741-4919-86cd-806037d98c8a",
+    "active_initiators": [],
+    "active_servers": [
+        "472764aa-584b-4c1d-a7b7-e50cf7f5518f"
+    ],
+    "endpoint_addrs": [
+        "172.28.121.10",
+        "172.28.120.10"
+    ],
+    "endpoint_idents": [
+        "iqn.2013-05.com.daterainc::01:sn:fc372bc0490b2dbe"
+    ],
+    "initiators": [],
+    "servers": [
+        "472764aa-584b-4c1d-a7b7-e50cf7f5518f"
+    ],
+    "volumes": [
+        "10305aa4-1343-4363-86fe-f49eb421a48c"
+    ],
+    "type": "iscsi",
+    "creation_type": "system_explicit",
+    "server_allocation": "TS_ALLOC_COMPLETED",
+    "admin_state": "online",
+    "target_allocation": "TS_ALLOC_COMPLETED",
+    "atype": "none",
+    "name": "OS-10305aa4",
+    "targetIds": {
+        "472764aa-584b-4c1d-a7b7-e50cf7f5518f": {
+            "ids": [{
+                "dev": "",
+                "id": ("iqn.2013-05.com.daterainc::01:sn:fc372bc0490b2dbe")
+            }]
+        }
+    }
+}
+
+
+def _stub_datera_volume(*args, **kwargs):
+    return {
+        "status": "available",
+        "name": "test",
+        "num_replicas": "2",
+        "parent": "00000000-0000-0000-0000-000000000000",
+        "size": "1024",
+        "sub_type": "IS_ORIGINAL",
+        "uuid": "10305aa4-1343-4363-86fe-f49eb421a48c",
+        "snapshots": [],
+        "snapshot_configs": [],
+        "targets": [
+            kwargs.get('targets', "744e1bd8-d741-4919-86cd-806037d98c8a"),
+        ]
+    }
+
 
 def _stub_volume(*args, **kwargs):
     uuid = u'c20aba21-6ef6-446b-b374-45733b4883ba'
index c8796e91b27de24da902bbdc8d81c41baeb908d2..654c7c4c04b55f6886f26ec02e16a6adeb54c2d0 100644 (file)
@@ -166,22 +166,31 @@ class DateraDriver(san.SanISCSIDriver):
 
     def _do_export(self, context, volume):
         """Gets the associated account, retrieves CHAP info and updates."""
-        if volume['provider_location']:
-            return {'provider_location': volume['provider_location']}
-
-        export = self._issue_api_request(
-            'volumes', action='export', method='post',
-            body={'ctype': 'TC_BLOCK_ISCSI'}, resource=volume['id'])
-
-        # NOTE(thingee): Refer to the Datera test for a stub of what this looks
-        # like. We're just going to pull the first IP that the Datera cluster
-        # makes available for the portal.
-        iscsi_portal = export['_ipColl'][0] + ':3260'
-        iqn = export['targetIds'].itervalues().next()['ids'][0]['id']
-
-        provider_location = '%s %s %s' % (iscsi_portal, iqn, 0)
-        model_update = {'provider_location': provider_location}
-        return model_update
+        portal = None
+        iqn = None
+        datera_volume = self._issue_api_request('volumes',
+                                                resource=volume['id'])
+        if len(datera_volume['targets']) == 0:
+            export = self._issue_api_request(
+                'volumes', action='export', method='post',
+                body={'ctype': 'TC_BLOCK_ISCSI'}, resource=volume['id'])
+
+            portal = "%s:3260" % export['_ipColl'][0]
+
+            # NOTE(thingee): Refer to the Datera test for a stub of what this
+            # looks like. We're just going to pull the first IP that the Datera
+            # cluster makes available for the portal.
+            iqn = export['targetIds'].itervalues().next()['ids'][0]['id']
+        else:
+            export = self._issue_api_request(
+                'export_configs',
+                resource=datera_volume['targets'][0]
+            )
+            portal = export['endpoint_addrs'][0] + ':3260'
+            iqn = export['endpoint_idents'][0]
+
+        provider_location = '%s %s %s' % (portal, iqn, 0)
+        return {'provider_location': provider_location}
 
     def ensure_export(self, context, volume):
         return self._do_export(context, volume)