]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Segment LUN clones in NetApp iSCSI
authorAndrew Kerr <andrew.kerr@netapp.com>
Mon, 24 Feb 2014 21:25:20 +0000 (16:25 -0500)
committerAndrew Kerr <andrew.kerr@netapp.com>
Wed, 26 Feb 2014 15:57:35 +0000 (10:57 -0500)
The NetApp ZAPI for clone_create and clone_start has a maximum size.
This fix breaks the lun into consumable sizes for the ZAPI.

Change-Id: Id4d0872c6099b7cfc73d806d772a3ae051a76b70
Closes-Bug: 1284182

cinder/tests/test_netapp.py
cinder/volume/drivers/netapp/iscsi.py

index bad9fc85f7a98e85140bc5d9d7ec1f396d251fc3..682c061bbb34c16dce81aea69a093276326b3d63 100644 (file)
@@ -340,6 +340,12 @@ class FakeDirectCMODEServerHandler(FakeHTTPRequestHandler):
                 body = """<results status="passed"><lun-id-assigned>1
                 </lun-id-assigned>
                 </results>"""
+        elif 'lun-get-geometry' == api:
+                body = """<results status="passed"><bytes-per-sector>256
+                </bytes-per-sector><cylinders>512</cylinders><max-resize-size>
+                3221225472</max-resize-size><sectors-per-track>512
+                </sectors-per-track><size>2147483648</size>
+                <tracks-per-cylinder>256</tracks-per-cylinder></results>"""
         elif 'iscsi-service-get-iter' == api:
                 body = """<results status="passed"><attributes-list>
                 <iscsi-service-info>
@@ -636,6 +642,18 @@ class NetAppDirectCmodeISCSIDriverTestCase(test.TestCase):
         self.driver.delete_snapshot(self.snapshot)
         self.driver.delete_volume(self.volume)
 
+    def test_extend_vol_same_size(self):
+        self.driver.create_volume(self.volume)
+        self.driver.extend_volume(self.volume, self.volume['size'])
+
+    def test_extend_vol_direct_resize(self):
+        self.driver.create_volume(self.volume)
+        self.driver.extend_volume(self.volume, 3)
+
+    def test_extend_vol_sub_lun_clone(self):
+        self.driver.create_volume(self.volume)
+        self.driver.extend_volume(self.volume, 4)
+
 
 class NetAppDriverNegativeTestCase(test.TestCase):
     """Test case for NetAppDriver"""
index a8710ce2c8534f56815b20120fed5158ff653158..65bfb92395b011cb707100b8fadfccadae5addd8 100644 (file)
@@ -21,6 +21,7 @@ storage systems with installed iSCSI licenses.
 """
 
 import copy
+import math
 import sys
 import time
 import uuid
@@ -526,7 +527,7 @@ class NetAppDirectISCSIDriver(driver.ISCSIDriver):
         return lun
 
     def _clone_lun(self, name, new_name, space_reserved='true',
-                   start_block=0, end_block=0, block_count=0):
+                   src_block=0, dest_block=0, block_count=0):
         """Clone LUN with the given name to the new name."""
         raise NotImplementedError()
 
@@ -962,7 +963,7 @@ class NetAppDirectCmodeISCSIDriver(NetAppDirectISCSIDriver):
         return igroup_list
 
     def _clone_lun(self, name, new_name, space_reserved='true',
-                   start_block=0, end_block=0, block_count=0):
+                   src_block=0, dest_block=0, block_count=0):
         """Clone LUN with the given handle to the new name."""
         metadata = self._get_lun_attr(name, 'metadata')
         volume = metadata['Volume']
@@ -972,19 +973,31 @@ class NetAppDirectCmodeISCSIDriver(NetAppDirectISCSIDriver):
                 'destination-path': new_name, 'space-reserve': space_reserved})
         if block_count > 0:
             block_ranges = NaElement("block-ranges")
-            block_range = NaElement.create_node_with_children(
-                'block-range',
-                **{'source-block-number': str(start_block),
-                   'destination-block-number': str(end_block),
-                   'block-count': str(block_count)})
-            block_ranges.add_child_elem(block_range)
+            # zAPI can only handle 2^24 block ranges
+            bc_limit = 2 ** 24  # 8GB
+            segments = int(math.ceil(float(block_count) / float(bc_limit)))
+            bc = block_count
+            for segment in range(0, segments):
+                if bc > bc_limit:
+                    block_count = bc_limit
+                    bc -= bc_limit
+                else:
+                    block_count = bc
+                block_range = NaElement.create_node_with_children(
+                    'block-range',
+                    **{'source-block-number': str(src_block),
+                       'destination-block-number': str(dest_block),
+                       'block-count': str(block_count)})
+                block_ranges.add_child_elem(block_range)
+                src_block = int(src_block) + int(block_count)
+                dest_block = int(dest_block) + int(block_count)
             clone_create.add_child_elem(block_ranges)
         self.client.invoke_successfully(clone_create, True)
         LOG.debug(_("Cloned LUN with new name %s") % new_name)
         lun = self._get_lun_by_args(vserver=self.vserver, path='/vol/%s/%s'
                                     % (volume, new_name))
         if len(lun) == 0:
-            msg = _("No clonned lun named %s found on the filer")
+            msg = _("No cloned lun named %s found on the filer")
             raise exception.VolumeBackendAPIException(data=msg % (new_name))
         clone_meta = self._create_lun_meta(lun[0])
         self._add_lun_to_table(NetAppLun('%s:%s' % (clone_meta['Vserver'],
@@ -1313,7 +1326,7 @@ class NetAppDirect7modeISCSIDriver(NetAppDirectISCSIDriver):
         return (igroup, lun_id)
 
     def _clone_lun(self, name, new_name, space_reserved='true',
-                   start_block=0, end_block=0, block_count=0):
+                   src_block=0, dest_block=0, block_count=0):
         """Clone LUN with the given handle to the new name."""
         metadata = self._get_lun_attr(name, 'metadata')
         path = metadata['Path']
@@ -1325,12 +1338,24 @@ class NetAppDirect7modeISCSIDriver(NetAppDirectISCSIDriver):
                               'no-snap': 'true'})
         if block_count > 0:
             block_ranges = NaElement("block-ranges")
-            block_range = NaElement.create_node_with_children(
-                'block-range',
-                **{'source-block-number': str(start_block),
-                    'destination-block-number': str(end_block),
-                    'block-count': str(block_count)})
-            block_ranges.add_child_elem(block_range)
+            # zAPI can only handle 2^24 block ranges
+            bc_limit = 2 ** 24  # 8GB
+            segments = int(math.ceil(float(block_count) / float(bc_limit)))
+            bc = block_count
+            for segment in range(0, segments):
+                if bc > bc_limit:
+                    block_count = bc_limit
+                    bc -= bc_limit
+                else:
+                    block_count = bc
+                block_range = NaElement.create_node_with_children(
+                    'block-range',
+                    **{'source-block-number': str(src_block),
+                        'destination-block-number': str(dest_block),
+                        'block-count': str(block_count)})
+                block_ranges.add_child_elem(block_range)
+                src_block = int(src_block) + int(block_count)
+                dest_block = int(dest_block) + int(block_count)
             clone_start.add_child_elem(block_ranges)
         result = self.client.invoke_successfully(clone_start, True)
         clone_id_el = result.get_child_by_name('clone-id')