Segment LUN clones in NetApp iSCSI

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
This commit is contained in:
Andrew Kerr 2014-02-24 16:25:20 -05:00
parent d8cb56a045
commit f0f52a0085
2 changed files with 59 additions and 16 deletions

View 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"""

View 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')