Merge "NetApp cDOT: Add NetApp Volume Encryption support"
This commit is contained in:
@@ -889,6 +889,47 @@ CLONE_SPLIT_STATUS_NO_DATA_RESPONSE = etree.XML("""
|
|||||||
</results>
|
</results>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
VOLUME_GET_ITER_ENCRYPTION_SSC_RESPONSE = etree.XML("""
|
||||||
|
<results status="passed">
|
||||||
|
<attributes-list>
|
||||||
|
<volume-attributes>
|
||||||
|
<encrypt>true</encrypt>
|
||||||
|
<volume-id-attributes>
|
||||||
|
<containing-aggregate-name>%(aggr)s</containing-aggregate-name>
|
||||||
|
<junction-path>/%(volume)s</junction-path>
|
||||||
|
<name>%(volume)s</name>
|
||||||
|
<owning-vserver-name>%(vserver)s</owning-vserver-name>
|
||||||
|
<type>rw</type>
|
||||||
|
</volume-id-attributes>
|
||||||
|
<volume-mirror-attributes>
|
||||||
|
<is-data-protection-mirror>false</is-data-protection-mirror>
|
||||||
|
<is-replica-volume>false</is-replica-volume>
|
||||||
|
</volume-mirror-attributes>
|
||||||
|
<volume-qos-attributes>
|
||||||
|
<policy-group-name>fake_qos_policy_group_name</policy-group-name>
|
||||||
|
</volume-qos-attributes>
|
||||||
|
<volume-space-attributes>
|
||||||
|
<is-space-guarantee-enabled>true</is-space-guarantee-enabled>
|
||||||
|
<space-guarantee>none</space-guarantee>
|
||||||
|
<percentage-snapshot-reserve>5</percentage-snapshot-reserve>
|
||||||
|
<size>12345</size>
|
||||||
|
</volume-space-attributes>
|
||||||
|
<volume-snapshot-attributes>
|
||||||
|
<snapshot-policy>default</snapshot-policy>
|
||||||
|
</volume-snapshot-attributes>
|
||||||
|
<volume-language-attributes>
|
||||||
|
<language-code>en_US</language-code>
|
||||||
|
</volume-language-attributes>
|
||||||
|
</volume-attributes>
|
||||||
|
</attributes-list>
|
||||||
|
<num-records>1</num-records>
|
||||||
|
</results>
|
||||||
|
""" % {
|
||||||
|
'aggr': VOLUME_AGGREGATE_NAMES[0],
|
||||||
|
'volume': VOLUME_NAMES[0],
|
||||||
|
'vserver': VOLUME_VSERVER_NAME,
|
||||||
|
})
|
||||||
|
|
||||||
STORAGE_DISK_GET_ITER_RESPONSE_PAGE_1 = etree.XML("""
|
STORAGE_DISK_GET_ITER_RESPONSE_PAGE_1 = etree.XML("""
|
||||||
<results status="passed">
|
<results status="passed">
|
||||||
<attributes-list>
|
<attributes-list>
|
||||||
|
|||||||
@@ -1940,6 +1940,72 @@ class NetAppCmodeClientTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
|
|
||||||
|
def test_is_flexvol_encrypted(self):
|
||||||
|
|
||||||
|
api_response = netapp_api.NaElement(
|
||||||
|
fake_client.VOLUME_GET_ITER_ENCRYPTION_SSC_RESPONSE)
|
||||||
|
self.client.features.add_feature('FLEXVOL_ENCRYPTION')
|
||||||
|
self.mock_object(self.client,
|
||||||
|
'send_iter_request',
|
||||||
|
return_value=api_response)
|
||||||
|
|
||||||
|
result = self.client.is_flexvol_encrypted(
|
||||||
|
fake_client.VOLUME_NAMES[0], fake_client.VOLUME_VSERVER_NAME)
|
||||||
|
|
||||||
|
volume_get_iter_args = {
|
||||||
|
'query': {
|
||||||
|
'volume-attributes': {
|
||||||
|
'encrypt': 'true',
|
||||||
|
'volume-id-attributes': {
|
||||||
|
'name': fake_client.VOLUME_NAME,
|
||||||
|
'owning-vserver-name': fake_client.VOLUME_VSERVER_NAME,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'desired-attributes': {
|
||||||
|
'volume-attributes': {
|
||||||
|
'encrypt': None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.client.send_iter_request.assert_called_once_with(
|
||||||
|
'volume-get-iter', volume_get_iter_args)
|
||||||
|
|
||||||
|
self.assertTrue(result)
|
||||||
|
|
||||||
|
def test_is_flexvol_encrypted_unsupported_version(self):
|
||||||
|
|
||||||
|
self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=False)
|
||||||
|
result = self.client.is_flexvol_encrypted(
|
||||||
|
fake_client.VOLUME_NAMES[0], fake_client.VOLUME_VSERVER_NAME)
|
||||||
|
|
||||||
|
self.assertFalse(result)
|
||||||
|
|
||||||
|
def test_is_flexvol_encrypted_no_records_found(self):
|
||||||
|
|
||||||
|
api_response = netapp_api.NaElement(
|
||||||
|
fake_client.NO_RECORDS_RESPONSE)
|
||||||
|
self.mock_object(self.client,
|
||||||
|
'send_request',
|
||||||
|
return_value=api_response)
|
||||||
|
|
||||||
|
result = self.client.is_flexvol_encrypted(
|
||||||
|
fake_client.VOLUME_NAMES[0], fake_client.VOLUME_VSERVER_NAME)
|
||||||
|
|
||||||
|
self.assertFalse(result)
|
||||||
|
|
||||||
|
def test_is_flexvol_encrypted_api_error(self):
|
||||||
|
|
||||||
|
self.mock_object(self.client,
|
||||||
|
'send_request',
|
||||||
|
side_effect=self._mock_api_error())
|
||||||
|
|
||||||
|
result = self.client.is_flexvol_encrypted(
|
||||||
|
fake_client.VOLUME_NAMES[0], fake_client.VOLUME_VSERVER_NAME)
|
||||||
|
|
||||||
|
self.assertFalse(result)
|
||||||
|
|
||||||
def test_get_aggregates(self):
|
def test_get_aggregates(self):
|
||||||
|
|
||||||
api_response = netapp_api.NaElement(
|
api_response = netapp_api.NaElement(
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ SSC = {
|
|||||||
'netapp_raid_type': 'raid_dp',
|
'netapp_raid_type': 'raid_dp',
|
||||||
'netapp_disk_type': ['SSD'],
|
'netapp_disk_type': ['SSD'],
|
||||||
'netapp_hybrid_aggregate': 'false',
|
'netapp_hybrid_aggregate': 'false',
|
||||||
|
'netapp_flexvol_encryption': 'true',
|
||||||
'pool_name': 'volume1',
|
'pool_name': 'volume1',
|
||||||
},
|
},
|
||||||
'volume2': {
|
'volume2': {
|
||||||
@@ -54,6 +55,7 @@ SSC = {
|
|||||||
'netapp_raid_type': 'raid_dp',
|
'netapp_raid_type': 'raid_dp',
|
||||||
'netapp_disk_type': ['FCAL', 'SSD'],
|
'netapp_disk_type': ['FCAL', 'SSD'],
|
||||||
'netapp_hybrid_aggregate': 'true',
|
'netapp_hybrid_aggregate': 'true',
|
||||||
|
'netapp_flexvol_encryption': 'false',
|
||||||
'pool_name': 'volume2',
|
'pool_name': 'volume2',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -84,6 +86,15 @@ SSC_DEDUPE_INFO = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSC_ENCRYPTION_INFO = {
|
||||||
|
'volume1': {
|
||||||
|
'netapp_flexvol_encryption': 'true',
|
||||||
|
},
|
||||||
|
'volume2': {
|
||||||
|
'netapp_flexvol_encryption': 'false',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
SSC_MIRROR_INFO = {
|
SSC_MIRROR_INFO = {
|
||||||
'volume1': {
|
'volume1': {
|
||||||
'netapp_mirrored': 'false',
|
'netapp_mirrored': 'false',
|
||||||
@@ -118,6 +129,19 @@ PROVISIONING_OPTS = {
|
|||||||
'size': 20,
|
'size': 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCRYPTED_PROVISIONING_OPTS = {
|
||||||
|
'aggregate': 'fake_aggregate',
|
||||||
|
'thin_provisioned': True,
|
||||||
|
'snapshot_policy': None,
|
||||||
|
'language': 'en_US',
|
||||||
|
'dedupe_enabled': False,
|
||||||
|
'compression_enabled': False,
|
||||||
|
'snapshot_reserve': '12',
|
||||||
|
'volume_type': 'rw',
|
||||||
|
'size': 20,
|
||||||
|
'encrypt': 'true',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_fake_cmode_config(backend_name):
|
def get_fake_cmode_config(backend_name):
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,10 @@ class CapabilitiesLibraryTestCase(test.TestCase):
|
|||||||
self.ssc_library, '_get_ssc_aggregate_info',
|
self.ssc_library, '_get_ssc_aggregate_info',
|
||||||
side_effect=[fake.SSC_AGGREGATE_INFO['volume1'],
|
side_effect=[fake.SSC_AGGREGATE_INFO['volume1'],
|
||||||
fake.SSC_AGGREGATE_INFO['volume2']])
|
fake.SSC_AGGREGATE_INFO['volume2']])
|
||||||
|
mock_get_ssc_encryption_info = self.mock_object(
|
||||||
|
self.ssc_library, '_get_ssc_encryption_info',
|
||||||
|
side_effect=[fake.SSC_ENCRYPTION_INFO['volume1'],
|
||||||
|
fake.SSC_ENCRYPTION_INFO['volume2']])
|
||||||
ordered_ssc = collections.OrderedDict()
|
ordered_ssc = collections.OrderedDict()
|
||||||
ordered_ssc['volume1'] = fake.SSC_VOLUME_MAP['volume1']
|
ordered_ssc['volume1'] = fake.SSC_VOLUME_MAP['volume1']
|
||||||
ordered_ssc['volume2'] = fake.SSC_VOLUME_MAP['volume2']
|
ordered_ssc['volume2'] = fake.SSC_VOLUME_MAP['volume2']
|
||||||
@@ -150,6 +154,8 @@ class CapabilitiesLibraryTestCase(test.TestCase):
|
|||||||
mock.call('volume1'), mock.call('volume2')])
|
mock.call('volume1'), mock.call('volume2')])
|
||||||
mock_get_ssc_aggregate_info.assert_has_calls([
|
mock_get_ssc_aggregate_info.assert_has_calls([
|
||||||
mock.call('aggr1'), mock.call('aggr2')])
|
mock.call('aggr1'), mock.call('aggr2')])
|
||||||
|
mock_get_ssc_encryption_info.assert_has_calls([
|
||||||
|
mock.call('volume1'), mock.call('volume2')])
|
||||||
|
|
||||||
def test__update_for_failover(self):
|
def test__update_for_failover(self):
|
||||||
self.mock_object(self.ssc_library, 'update_ssc')
|
self.mock_object(self.ssc_library, 'update_ssc')
|
||||||
@@ -282,6 +288,22 @@ class CapabilitiesLibraryTestCase(test.TestCase):
|
|||||||
self.zapi_client.get_flexvol_dedupe_info.assert_called_once_with(
|
self.zapi_client.get_flexvol_dedupe_info.assert_called_once_with(
|
||||||
fake_client.VOLUME_NAMES[0])
|
fake_client.VOLUME_NAMES[0])
|
||||||
|
|
||||||
|
def test_get_ssc_encryption_info(self):
|
||||||
|
|
||||||
|
self.mock_object(
|
||||||
|
self.ssc_library.zapi_client, 'is_flexvol_encrypted',
|
||||||
|
return_value=True)
|
||||||
|
|
||||||
|
result = self.ssc_library._get_ssc_encryption_info(
|
||||||
|
fake_client.VOLUME_NAMES[0])
|
||||||
|
|
||||||
|
expected = {
|
||||||
|
'netapp_flexvol_encryption': 'true',
|
||||||
|
}
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
self.zapi_client.is_flexvol_encrypted.assert_called_once_with(
|
||||||
|
fake_client.VOLUME_NAMES[0], fake_client.VOLUME_VSERVER_NAME)
|
||||||
|
|
||||||
@ddt.data(True, False)
|
@ddt.data(True, False)
|
||||||
def test_get_ssc_mirror_info(self, mirrored):
|
def test_get_ssc_mirror_info(self, mirrored):
|
||||||
|
|
||||||
|
|||||||
@@ -543,6 +543,9 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase):
|
|||||||
mock_get_provisioning_opts_call = self.mock_object(
|
mock_get_provisioning_opts_call = self.mock_object(
|
||||||
self.mock_src_client, 'get_provisioning_options_from_flexvol',
|
self.mock_src_client, 'get_provisioning_options_from_flexvol',
|
||||||
return_value=provisioning_opts)
|
return_value=provisioning_opts)
|
||||||
|
mock_is_flexvol_encrypted = self.mock_object(
|
||||||
|
self.mock_src_client, 'is_flexvol_encrypted',
|
||||||
|
return_value=False)
|
||||||
self.mock_object(self.dm_mixin, '_get_replication_aggregate_map',
|
self.mock_object(self.dm_mixin, '_get_replication_aggregate_map',
|
||||||
return_value=aggr_map)
|
return_value=aggr_map)
|
||||||
mock_client_call = self.mock_object(
|
mock_client_call = self.mock_object(
|
||||||
@@ -560,6 +563,45 @@ class NetAppCDOTDataMotionMixinTestCase(test.TestCase):
|
|||||||
mock_client_call.assert_called_once_with(
|
mock_client_call.assert_called_once_with(
|
||||||
self.dest_flexvol_name, 'aggr01', fakes.PROVISIONING_OPTS['size'],
|
self.dest_flexvol_name, 'aggr01', fakes.PROVISIONING_OPTS['size'],
|
||||||
volume_type='dp', **expected_prov_opts)
|
volume_type='dp', **expected_prov_opts)
|
||||||
|
mock_is_flexvol_encrypted.assert_called_once_with(
|
||||||
|
self.src_flexvol_name, self.src_vserver)
|
||||||
|
|
||||||
|
def test_create_encrypted_destination_flexvol(self):
|
||||||
|
aggr_map = {
|
||||||
|
fakes.ENCRYPTED_PROVISIONING_OPTS['aggregate']: 'aggr01',
|
||||||
|
'aggr20': 'aggr02',
|
||||||
|
}
|
||||||
|
provisioning_opts = copy.deepcopy(fakes.ENCRYPTED_PROVISIONING_OPTS)
|
||||||
|
expected_prov_opts = copy.deepcopy(fakes.ENCRYPTED_PROVISIONING_OPTS)
|
||||||
|
expected_prov_opts.pop('volume_type', None)
|
||||||
|
expected_prov_opts.pop('size', None)
|
||||||
|
expected_prov_opts.pop('aggregate', None)
|
||||||
|
mock_get_provisioning_opts_call = self.mock_object(
|
||||||
|
self.mock_src_client, 'get_provisioning_options_from_flexvol',
|
||||||
|
return_value=provisioning_opts)
|
||||||
|
mock_is_flexvol_encrypted = self.mock_object(
|
||||||
|
self.mock_src_client, 'is_flexvol_encrypted',
|
||||||
|
return_value=True)
|
||||||
|
self.mock_object(self.dm_mixin, '_get_replication_aggregate_map',
|
||||||
|
return_value=aggr_map)
|
||||||
|
mock_client_call = self.mock_object(
|
||||||
|
self.mock_dest_client, 'create_flexvol')
|
||||||
|
|
||||||
|
retval = self.dm_mixin.create_destination_flexvol(
|
||||||
|
self.src_backend, self.dest_backend,
|
||||||
|
self.src_flexvol_name, self.dest_flexvol_name)
|
||||||
|
|
||||||
|
self.assertIsNone(retval)
|
||||||
|
mock_get_provisioning_opts_call.assert_called_once_with(
|
||||||
|
self.src_flexvol_name)
|
||||||
|
self.dm_mixin._get_replication_aggregate_map.assert_called_once_with(
|
||||||
|
self.src_backend, self.dest_backend)
|
||||||
|
mock_client_call.assert_called_once_with(
|
||||||
|
self.dest_flexvol_name, 'aggr01',
|
||||||
|
fakes.ENCRYPTED_PROVISIONING_OPTS['size'],
|
||||||
|
volume_type='dp', **expected_prov_opts)
|
||||||
|
mock_is_flexvol_encrypted.assert_called_once_with(
|
||||||
|
self.src_flexvol_name, self.src_vserver)
|
||||||
|
|
||||||
def test_ensure_snapmirrors(self):
|
def test_ensure_snapmirrors(self):
|
||||||
flexvols = ['nvol1', 'nvol2']
|
flexvols = ['nvol1', 'nvol2']
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# Copyright (c) 2014 Clinton Knight. All rights reserved.
|
# Copyright (c) 2014 Clinton Knight. All rights reserved.
|
||||||
# Copyright (c) 2015 Tom Barron. All rights reserved.
|
# Copyright (c) 2015 Tom Barron. All rights reserved.
|
||||||
# Copyright (c) 2016 Mike Rooney. All rights reserved.
|
# Copyright (c) 2016 Mike Rooney. All rights reserved.
|
||||||
|
# Copyright (c) 2017 Jose Porrua. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@@ -60,6 +61,7 @@ class Client(client_base.Client):
|
|||||||
ontapi_1_2x = (1, 20) <= ontapi_version < (1, 30)
|
ontapi_1_2x = (1, 20) <= ontapi_version < (1, 30)
|
||||||
ontapi_1_30 = ontapi_version >= (1, 30)
|
ontapi_1_30 = ontapi_version >= (1, 30)
|
||||||
ontapi_1_100 = ontapi_version >= (1, 100)
|
ontapi_1_100 = ontapi_version >= (1, 100)
|
||||||
|
ontapi_1_1xx = (1, 100) <= ontapi_version < (1, 200)
|
||||||
|
|
||||||
self.features.add_feature('SNAPMIRROR_V2', supported=ontapi_1_20)
|
self.features.add_feature('SNAPMIRROR_V2', supported=ontapi_1_20)
|
||||||
self.features.add_feature('USER_CAPABILITY_LIST',
|
self.features.add_feature('USER_CAPABILITY_LIST',
|
||||||
@@ -73,6 +75,7 @@ class Client(client_base.Client):
|
|||||||
supported=ontapi_1_30)
|
supported=ontapi_1_30)
|
||||||
self.features.add_feature('BACKUP_CLONE_PARAM', supported=ontapi_1_100)
|
self.features.add_feature('BACKUP_CLONE_PARAM', supported=ontapi_1_100)
|
||||||
self.features.add_feature('CLUSTER_PEER_POLICY', supported=ontapi_1_30)
|
self.features.add_feature('CLUSTER_PEER_POLICY', supported=ontapi_1_30)
|
||||||
|
self.features.add_feature('FLEXVOL_ENCRYPTION', supported=ontapi_1_1xx)
|
||||||
|
|
||||||
def _invoke_vserver_api(self, na_element, vserver):
|
def _invoke_vserver_api(self, na_element, vserver):
|
||||||
server = copy.copy(self.connection)
|
server = copy.copy(self.connection)
|
||||||
@@ -1163,6 +1166,41 @@ class Client(client_base.Client):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def is_flexvol_encrypted(self, flexvol_name, vserver_name):
|
||||||
|
"""Check if a flexvol is encrypted."""
|
||||||
|
|
||||||
|
if not self.features.FLEXVOL_ENCRYPTION:
|
||||||
|
return False
|
||||||
|
|
||||||
|
api_args = {
|
||||||
|
'query': {
|
||||||
|
'volume-attributes': {
|
||||||
|
'encrypt': 'true',
|
||||||
|
'volume-id-attributes': {
|
||||||
|
'name': flexvol_name,
|
||||||
|
'owning-vserver-name': vserver_name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'desired-attributes': {
|
||||||
|
'volume-attributes': {
|
||||||
|
'encrypt': None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.send_iter_request('volume-get-iter', api_args)
|
||||||
|
except netapp_api.NaApiError:
|
||||||
|
msg = _LE('Failed to get Encryption info for volume %s.')
|
||||||
|
LOG.exception(msg, flexvol_name)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self._has_records(result):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def create_flexvol(self, flexvol_name, aggregate_name, size_gb,
|
def create_flexvol(self, flexvol_name, aggregate_name, size_gb,
|
||||||
space_guarantee_type=None, snapshot_policy=None,
|
space_guarantee_type=None, snapshot_policy=None,
|
||||||
language=None, dedupe_enabled=False,
|
language=None, dedupe_enabled=False,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# Copyright (c) 2016 Clinton Knight. All rights reserved.
|
# Copyright (c) 2016 Clinton Knight. All rights reserved.
|
||||||
|
# Copyright (c) 2017 Jose Porrua. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@@ -44,7 +45,9 @@ SSC_API_MAP = {
|
|||||||
'netapp_dedup',
|
'netapp_dedup',
|
||||||
'netapp_compression',
|
'netapp_compression',
|
||||||
],
|
],
|
||||||
('volume', 'show', 'volume-get-iter'): [],
|
('volume', 'show', 'volume-get-iter'): [
|
||||||
|
'netapp_flexvol_encryption',
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -129,6 +132,7 @@ class CapabilitiesLibrary(object):
|
|||||||
ssc_volume.update(self._get_ssc_flexvol_info(flexvol_name))
|
ssc_volume.update(self._get_ssc_flexvol_info(flexvol_name))
|
||||||
ssc_volume.update(self._get_ssc_dedupe_info(flexvol_name))
|
ssc_volume.update(self._get_ssc_dedupe_info(flexvol_name))
|
||||||
ssc_volume.update(self._get_ssc_mirror_info(flexvol_name))
|
ssc_volume.update(self._get_ssc_mirror_info(flexvol_name))
|
||||||
|
ssc_volume.update(self._get_ssc_encryption_info(flexvol_name))
|
||||||
|
|
||||||
# Get aggregate info
|
# Get aggregate info
|
||||||
aggregate_name = ssc_volume.get('netapp_aggregate')
|
aggregate_name = ssc_volume.get('netapp_aggregate')
|
||||||
@@ -189,6 +193,13 @@ class CapabilitiesLibrary(object):
|
|||||||
'netapp_compression': six.text_type(compression).lower(),
|
'netapp_compression': six.text_type(compression).lower(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _get_ssc_encryption_info(self, flexvol_name):
|
||||||
|
"""Gather flexvol encryption info and recast into SSC-style stats."""
|
||||||
|
encrypted = self.zapi_client.is_flexvol_encrypted(
|
||||||
|
flexvol_name, self.vserver_name)
|
||||||
|
|
||||||
|
return {'netapp_flexvol_encryption': six.text_type(encrypted).lower()}
|
||||||
|
|
||||||
def _get_ssc_mirror_info(self, flexvol_name):
|
def _get_ssc_mirror_info(self, flexvol_name):
|
||||||
"""Gather SnapMirror info and recast into SSC-style volume stats."""
|
"""Gather SnapMirror info and recast into SSC-style volume stats."""
|
||||||
|
|
||||||
|
|||||||
@@ -417,6 +417,12 @@ class DataMotionMixin(object):
|
|||||||
src_flexvol_name)
|
src_flexvol_name)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# If the source is encrypted then the destination needs to be
|
||||||
|
# encrypted too. Using is_flexvol_encrypted because it includes
|
||||||
|
# a simple check to ensure that the NVE feature is supported.
|
||||||
|
if src_client.is_flexvol_encrypted(src_flexvol_name, src_vserver):
|
||||||
|
provisioning_options['encrypt'] = 'true'
|
||||||
|
|
||||||
# Remove size and volume_type
|
# Remove size and volume_type
|
||||||
size = provisioning_options.pop('size', None)
|
size = provisioning_options.pop('size', None)
|
||||||
if not size:
|
if not size:
|
||||||
|
|||||||
Reference in New Issue
Block a user