# License for the specific language governing permissions and limitations
# under the License.
+from cinder.volume.drivers.netapp.dataontap.client import api as netapp_api
+
VOLUME_ID = 'f10d1a84-9b7b-427e-8fec-63c48b509a56'
LUN_ID = 'ee6b4cc7-477b-4016-aa0c-7127b4e3af86'
LUN_HANDLE = 'fake_lun_handle'
VOLUME_REF = {'name': 'fake_vref_name', 'size': 42}
FILE_LIST = ['file1', 'file2', 'file3']
+
+FAKE_LUN = netapp_api.NaElement.create_node_with_children(
+ 'lun-info',
+ **{'alignment': 'indeterminate',
+ 'block-size': '512',
+ 'comment': '',
+ 'creation-timestamp': '1354536362',
+ 'is-space-alloc-enabled': 'false',
+ 'is-space-reservation-enabled': 'true',
+ 'mapped': 'false',
+ 'multiprotocol-type': 'linux',
+ 'online': 'true',
+ 'path': '/vol/fakeLUN/fakeLUN',
+ 'prefix-size': '0',
+ 'qtree': '',
+ 'read-only': 'false',
+ 'serial-number': '2FfGI$APyN68',
+ 'share-state': 'none',
+ 'size': '20971520',
+ 'size-used': '0',
+ 'staging': 'false',
+ 'suffix-size': '0',
+ 'uuid': 'cec1f3d7-3d41-11e2-9cf4-123478563412',
+ 'volume': 'fakeLUN',
+ 'vserver': 'fake_vserver'})
def test_clone_lun_zero_block_count(self):
"""Test for when clone lun is not passed a block count."""
+ self.library._get_lun_attr = mock.Mock(return_value={
+ 'Volume': 'fakeLUN', 'Path': '/vol/fake/fakeLUN'})
+ self.library.zapi_client = mock.Mock()
+ self.library.zapi_client.get_lun_by_args.return_value = [fake.FAKE_LUN]
+ self.library._add_lun_to_table = mock.Mock()
+
+ self.library._clone_lun('fakeLUN', 'newFakeLUN', 'false')
+
+ self.library.zapi_client.clone_lun.assert_called_once_with(
+ '/vol/fake/fakeLUN', '/vol/fake/newFakeLUN', 'fakeLUN',
+ 'newFakeLUN', 'false', block_count=0, dest_block=0, src_block=0)
- lun = netapp_api.NaElement.create_node_with_children(
- 'lun-info',
- **{'alignment': 'indeterminate',
- 'block-size': '512',
- 'comment': '',
- 'creation-timestamp': '1354536362',
- 'is-space-alloc-enabled': 'false',
- 'is-space-reservation-enabled': 'true',
- 'mapped': 'false',
- 'multiprotocol-type': 'linux',
- 'online': 'true',
- 'path': '/vol/fakeLUN/fakeLUN',
- 'prefix-size': '0',
- 'qtree': '',
- 'read-only': 'false',
- 'serial-number': '2FfGI$APyN68',
- 'share-state': 'none',
- 'size': '20971520',
- 'size-used': '0',
- 'staging': 'false',
- 'suffix-size': '0',
- 'uuid': 'cec1f3d7-3d41-11e2-9cf4-123478563412',
- 'volume': 'fakeLUN',
- 'vserver': 'fake_vserver'})
+ def test_clone_lun_no_space_reservation(self):
+ """Test for when space_reservation is not passed."""
self.library._get_lun_attr = mock.Mock(return_value={
'Volume': 'fakeLUN', 'Path': '/vol/fake/fakeLUN'})
+ self.library.lun_space_reservation = 'false'
self.library.zapi_client = mock.Mock()
- self.library.zapi_client.get_lun_by_args.return_value = [lun]
+ self.library.zapi_client.get_lun_by_args.return_value = [fake.FAKE_LUN]
self.library._add_lun_to_table = mock.Mock()
self.library._clone_lun('fakeLUN', 'newFakeLUN')
self.library.zapi_client.clone_lun.assert_called_once_with(
'/vol/fake/fakeLUN', '/vol/fake/newFakeLUN', 'fakeLUN',
- 'newFakeLUN', 'true', block_count=0, dest_block=0, src_block=0)
+ 'newFakeLUN', 'false', block_count=0, dest_block=0, src_block=0)
def test_clone_lun_qos_supplied(self):
"""Test for qos supplied in clone lun invocation."""
def test_do_setup_san_configured(self, mock_check_flags):
self.library.configuration.netapp_lun_ostype = 'windows'
self.library.configuration.netapp_host_type = 'solaris'
+ self.library.configuration.netapp_lun_space_reservation = 'disabled'
self.library.do_setup(mock.Mock())
self.assertTrue(mock_check_flags.called)
self.assertEqual('windows', self.library.lun_ostype)
def test_do_setup_san_unconfigured(self, mock_check_flags):
self.library.configuration.netapp_lun_ostype = None
self.library.configuration.netapp_host_type = None
+ self.library.configuration.netapp_lun_space_reservation = 'enabled'
self.library.do_setup(mock.Mock())
self.assertTrue(mock_check_flags.called)
self.assertEqual('linux', self.library.lun_ostype)
self.assertEqual('linux', self.library.host_type)
+ def test_do_setup_space_reservation_disabled(self):
+ self.mock_object(na_utils, 'check_flags')
+ self.library.configuration.netapp_lun_ostype = None
+ self.library.configuration.netapp_host_type = None
+ self.library.configuration.netapp_lun_space_reservation = 'disabled'
+
+ self.library.do_setup(mock.Mock())
+
+ self.assertEqual('false', self.library.lun_space_reservation)
+
+ def test_do_setup_space_reservation_enabled(self):
+ self.mock_object(na_utils, 'check_flags')
+ self.library.configuration.netapp_lun_ostype = None
+ self.library.configuration.netapp_host_type = None
+ self.library.configuration.netapp_lun_space_reservation = 'enabled'
+
+ self.library.do_setup(mock.Mock())
+
+ self.assertEqual('true', self.library.lun_space_reservation)
+
def test_get_existing_vol_manage_missing_id_path(self):
self.assertRaises(exception.ManageExistingInvalidReference,
self.library._get_existing_vol_with_manage_ref,
self.mock_object(self.library, 'extend_volume')
self.mock_object(self.library, 'delete_volume')
self.mock_object(self.library, '_mark_qos_policy_group_for_deletion')
+ self.library.lun_space_reservation = 'false'
self.library._clone_source_to_destination(fake.CLONE_SOURCE,
fake.CLONE_DESTINATION)
fake.CLONE_DESTINATION, fake.EXTRA_SPECS)
self.library._clone_lun.assert_called_once_with(
fake.CLONE_SOURCE_NAME, fake.CLONE_DESTINATION_NAME,
- space_reserved='true',
+ space_reserved='false',
qos_policy_group_name=fake.QOS_POLICY_GROUP_NAME)
self.library.extend_volume.assert_called_once_with(
fake.CLONE_DESTINATION, fake.CLONE_DESTINATION_SIZE,
side_effect=Exception))
self.mock_object(self.library, 'delete_volume')
self.mock_object(self.library, '_mark_qos_policy_group_for_deletion')
+ self.library.lun_space_reservation = 'true'
self.assertRaises(exception.VolumeBackendAPIException,
self.library._clone_source_to_destination,
self.library.zapi_client = mock.Mock()
self.library.zapi_client.get_lun_by_args.return_value = [
mock.Mock(spec=netapp_api.NaElement)]
- lun = netapp_api.NaElement.create_node_with_children(
- 'lun-info',
- **{'alignment': 'indeterminate',
- 'block-size': '512',
- 'comment': '',
- 'creation-timestamp': '1354536362',
- 'is-space-alloc-enabled': 'false',
- 'is-space-reservation-enabled': 'true',
- 'mapped': 'false',
- 'multiprotocol-type': 'linux',
- 'online': 'true',
- 'path': '/vol/fakeLUN/lun1',
- 'prefix-size': '0',
- 'qtree': '',
- 'read-only': 'false',
- 'serial-number': '2FfGI$APyN68',
- 'share-state': 'none',
- 'size': '20971520',
- 'size-used': '0',
- 'staging': 'false',
- 'suffix-size': '0',
- 'uuid': 'cec1f3d7-3d41-11e2-9cf4-123478563412',
- 'volume': 'fakeLUN',
- 'vserver': 'fake_vserver'})
+ lun = fake.FAKE_LUN
+ self.library._get_lun_by_args = mock.Mock(return_value=[lun])
+ self.library._add_lun_to_table = mock.Mock()
+ self.library._update_stale_vols = mock.Mock()
+
+ self.library._clone_lun('fakeLUN', 'newFakeLUN', 'false')
+
+ self.library.zapi_client.clone_lun.assert_called_once_with(
+ 'fakeLUN', 'fakeLUN', 'newFakeLUN', 'false', block_count=0,
+ dest_block=0, src_block=0, qos_policy_group_name=None)
+
+ def test_clone_lun_no_space_reservation(self):
+ """Test for when space_reservation is not passed."""
+
+ self.library._get_lun_attr = mock.Mock(return_value={'Volume':
+ 'fakeLUN'})
+ self.library.zapi_client = mock.Mock()
+ self.library.lun_space_reservation = 'false'
+ self.library.zapi_client.get_lun_by_args.return_value = [
+ mock.Mock(spec=netapp_api.NaElement)]
+ lun = fake.FAKE_LUN
self.library._get_lun_by_args = mock.Mock(return_value=[lun])
self.library._add_lun_to_table = mock.Mock()
self.library._update_stale_vols = mock.Mock()
self.library._clone_lun('fakeLUN', 'newFakeLUN')
self.library.zapi_client.clone_lun.assert_called_once_with(
- 'fakeLUN', 'fakeLUN', 'newFakeLUN', 'true', block_count=0,
+ 'fakeLUN', 'fakeLUN', 'newFakeLUN', 'false', block_count=0,
dest_block=0, src_block=0, qos_policy_group_name=None)
def test_get_fc_target_wwpns(self):
return True
return False
- def _clone_lun(self, name, new_name, space_reserved='true',
+ def _clone_lun(self, name, new_name, space_reserved=None,
qos_policy_group_name=None, src_block=0, dest_block=0,
block_count=0):
"""Clone LUN with the given handle to the new name."""
+ if not space_reserved:
+ space_reserved = self.lun_space_reservation
if qos_policy_group_name is not None:
msg = _('Data ONTAP operating in 7-Mode does not support QoS '
'policy groups.')
self.lun_table = {}
self.lun_ostype = None
self.host_type = None
+ self.lun_space_reservation = 'true'
self.lookup_service = fczm_utils.create_lookup_service()
self.app_version = kwargs.get("app_version", "unknown")
or self.DEFAULT_LUN_OS)
self.host_type = (self.configuration.netapp_host_type
or self.DEFAULT_HOST_TYPE)
+ if self.configuration.netapp_lun_space_reservation == 'enabled':
+ self.lun_space_reservation = 'true'
+ else:
+ self.lun_space_reservation = 'false'
def check_for_setup_error(self):
"""Check that the driver is working and can communicate.
size = int(volume['size']) * units.Gi
metadata = {'OsType': self.lun_ostype,
- 'SpaceReserved': 'true',
+ 'SpaceReserved': self.lun_space_reservation,
'Path': '/vol/%s/%s' % (pool_name, lun_name)}
qos_policy_group_info = self._setup_qos_for_volume(volume, extra_specs)
try:
self._clone_lun(source_name, destination_name,
- space_reserved='true',
+ space_reserved=self.lun_space_reservation,
qos_policy_group_name=qos_policy_group_name)
if destination_size != source_size:
return igroup_name, lun_map['lun-id']
return None, None
- def _clone_lun(self, name, new_name, space_reserved='true',
+ def _clone_lun(self, name, new_name, space_reserved=None,
qos_policy_group_name=None, src_block=0, dest_block=0,
block_count=0):
"""Clone LUN with the given handle to the new name."""
+ if not space_reserved:
+ space_reserved = self.lun_space_reservation
metadata = self._get_lun_attr(name, 'metadata')
volume = metadata['Volume']
self.zapi_client.clone_lun(volume, name, new_name, space_reserved,
'to restrict provisioning to the specified controller '
'volumes. Specify the value of this option to be a '
'comma separated list of NetApp controller volume names '
- 'to be used for provisioning.')), ]
+ 'to be used for provisioning.')),
+ cfg.StrOpt('netapp_lun_space_reservation',
+ default='enabled',
+ choices=['enabled', 'disabled'],
+ help=('This option determines if storage space is reserved '
+ 'for LUN allocation. If enabled, LUNs are thick '
+ 'provisioned. If space reservation is disabled, '
+ 'storage space is allocated on demand.')), ]
netapp_cluster_opts = [
cfg.StrOpt('netapp_vserver',