From e2729946fc4860095eaa37e7bb47eaf692bb586b Mon Sep 17 00:00:00 2001 From: Felipe Rodrigues Date: Wed, 11 Jan 2023 00:49:30 -0300 Subject: [PATCH] [NetApp] Configure VLAN/MTU through subnet metadata The NetApp driver can setup a share server VLAN segmentation and MTU based on the subnet metadata. If the subnet metadata has `set_vlan`, the driver will configure the segmentation following the metadata fields. If the subnet metadata has the `set_mtu` field, the MTU is configured according its value. If share network subnet does not have those metadata fields, the segmentation configuration keeps working as before, that's it, it is set according to the values provided by Manila network plugin. Change-Id: I69731b187527d8d443893dcc94c604688d73e696 --- .../dataontap/cluster_mode/lib_multi_svm.py | 42 ++++++++++++++++ .../cluster_mode/test_lib_multi_svm.py | 48 +++++++++++++++++++ .../share/drivers/netapp/dataontap/fakes.py | 1 + ...re_net_with_metadata-c5d1b5f542967276.yaml | 9 ++++ 4 files changed, 100 insertions(+) create mode 100644 releasenotes/notes/netapp_configure_net_with_metadata-c5d1b5f542967276.yaml diff --git a/manila/share/drivers/netapp/dataontap/cluster_mode/lib_multi_svm.py b/manila/share/drivers/netapp/dataontap/cluster_mode/lib_multi_svm.py index 5ff9087c5d..bb6589c148 100644 --- a/manila/share/drivers/netapp/dataontap/cluster_mode/lib_multi_svm.py +++ b/manila/share/drivers/netapp/dataontap/cluster_mode/lib_multi_svm.py @@ -46,6 +46,8 @@ DEFAULT_MTU = 1500 CLUSTER_IPSPACES = ('Cluster', 'Default') SERVER_MIGRATE_SVM_DR = 'svm_dr' SERVER_MIGRATE_SVM_MIGRATE = 'svm_migrate' +METADATA_VLAN = 'set_vlan' +METADATA_MTU = 'set_mtu' class NetAppCmodeMultiSVMFileStorageLibrary( @@ -143,9 +145,49 @@ class NetAppCmodeMultiSVMFileStorageLibrary( return [aggr_name for aggr_name in aggregate_names if re.match(pattern, aggr_name)] + @na_utils.trace + def _set_network_with_metadata(self, network_info): + """Set the subnet metadata information for network_info object.""" + + for network in network_info: + metadata = network.get('subnet_metadata') + if not metadata: + continue + + metadata_vlan = metadata.get(METADATA_VLAN) + if not metadata_vlan: + continue + + if int(metadata_vlan) > 4094 or int(metadata_vlan) < 1: + msg = _( + 'A segmentation ID %s was specified but is not valid for ' + 'a VLAN network type; the segmentation ID must be an ' + 'integer value in the range of [1,4094]') + raise exception.NetworkBadConfigurationException( + reason=msg % metadata_vlan) + + if metadata.get(METADATA_MTU) is not None: + try: + int(metadata.get(METADATA_MTU)) + except ValueError: + msg = _('Metadata network MTU must be an integer value.') + raise exception.NetworkBadConfigurationException(msg) + + network['network_type'] = 'vlan' + network['segmentation_id'] = metadata_vlan + for allocation in network['network_allocations']: + allocation['network_type'] = 'vlan' + allocation['segmentation_id'] = metadata_vlan + allocation['mtu'] = int(metadata.get(METADATA_MTU) or + allocation['mtu']) + @na_utils.trace def setup_server(self, network_info, metadata=None): """Creates and configures new Vserver.""" + + # only changes network_info if one of networks has metadata set. + self._set_network_with_metadata(network_info) + ports = {} server_id = network_info[0]['server_id'] LOG.debug("Setting up server %s.", server_id) diff --git a/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py b/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py index b27f2b5289..a4e8aeb60d 100644 --- a/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py +++ b/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py @@ -441,6 +441,49 @@ class NetAppFileStorageLibraryTestCase(test.TestCase): self.assertListEqual([], result) + def test__set_network_with_metadata(self): + net_info_1 = copy.deepcopy(fake.NETWORK_INFO) + net_info_2 = copy.deepcopy(fake.NETWORK_INFO) + net_info_2['subnet_metadata'] = {'fake_key': 'fake_value'} + net_info_3 = copy.deepcopy(fake.NETWORK_INFO) + metadata_vlan = 1 + net_info_3['subnet_metadata'] = { + 'set_vlan': metadata_vlan, + 'set_mtu': '1' + } + net_info_4 = copy.deepcopy(fake.NETWORK_INFO) + metadata_vlan = 1 + net_info_4['subnet_metadata'] = { + 'set_vlan': metadata_vlan + } + + net_list = [net_info_1, net_info_2, net_info_3, net_info_4] + self.library._set_network_with_metadata(net_list) + + net_info = copy.deepcopy(fake.NETWORK_INFO) + self.assertEqual(net_info, net_list[0]) + net_info['subnet_metadata'] = {'fake_key': 'fake_value'} + self.assertEqual(net_info, net_list[1]) + self.assertEqual(metadata_vlan, net_list[2]['segmentation_id']) + for allocation in net_list[2]['network_allocations']: + self.assertEqual(metadata_vlan, allocation['segmentation_id']) + self.assertEqual(1, allocation['mtu']) + self.assertEqual(metadata_vlan, net_list[3]['segmentation_id']) + for allocation in net_list[3]['network_allocations']: + self.assertEqual(metadata_vlan, allocation['segmentation_id']) + self.assertEqual(fake.MTU, allocation['mtu']) + + @ddt.data({'set_vlan': '0', 'set_mtu': '1500'}, + {'set_vlan': '1000', 'set_mtu': '1bla'}) + def test__set_network_with_metadata_exception(self, metadata): + net_info = copy.deepcopy(fake.NETWORK_INFO) + net_info['subnet_metadata'] = metadata + + self.assertRaises( + exception.NetworkBadConfigurationException, + self.library._set_network_with_metadata, + [net_info]) + @ddt.data({'nfs_config_support': False}, {'nfs_config_support': True, 'nfs_config': fake.NFS_CONFIG_UDP_MAX}, @@ -472,6 +515,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase): self.library, "_get_nfs_config_provisioning_options", mock.Mock(return_value=nfs_config)) + mock_set_with_meta = self.mock_object( + self.library, '_set_network_with_metadata') result = self.library.setup_server(fake.NETWORK_INFO_LIST, fake.SERVER_METADATA) @@ -480,6 +525,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase): for network_allocation in fake.NETWORK_INFO['network_allocations']: ports[network_allocation['id']] = network_allocation['ip_address'] + mock_set_with_meta.assert_called_once_with(fake.NETWORK_INFO_LIST) self.assertTrue(mock_validate_network_type.called) self.assertTrue(mock_validate_share_network_subnets.called) self.assertTrue(mock_get_vserver_name.called) @@ -524,6 +570,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase): mock_validate_share_network_subnets = self.mock_object( self.library, '_validate_share_network_subnets') + self.mock_object(self.library, '_set_network_with_metadata') self.assertRaises( exception.ManilaException, @@ -555,6 +602,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase): self.mock_object(self.library, '_validate_network_type') self.mock_object(self.library, '_validate_share_network_subnets', mock.Mock(side_effect=invalid_subnet_exception)) + self.mock_object(self.library, '_set_network_with_metadata') self.assertRaises( exception.NetworkBadConfigurationException, diff --git a/manila/tests/share/drivers/netapp/dataontap/fakes.py b/manila/tests/share/drivers/netapp/dataontap/fakes.py index ddca99a3d2..28e097f4d4 100644 --- a/manila/tests/share/drivers/netapp/dataontap/fakes.py +++ b/manila/tests/share/drivers/netapp/dataontap/fakes.py @@ -515,6 +515,7 @@ NETWORK_INFO = { 'neutron_net_id': '4eff22ca-5ad2-454d-a000-aadfd7b40b39', 'neutron_subnet_id': '62bf1c2c-18eb-421b-8983-48a6d39aafe0', 'segmentation_id': '1000', + 'network_type': 'vlan' } NETWORK_INFO_LIST = [NETWORK_INFO] NETWORK_INFO_NETMASK = '255.255.255.0' diff --git a/releasenotes/notes/netapp_configure_net_with_metadata-c5d1b5f542967276.yaml b/releasenotes/notes/netapp_configure_net_with_metadata-c5d1b5f542967276.yaml new file mode 100644 index 0000000000..20449d159c --- /dev/null +++ b/releasenotes/notes/netapp_configure_net_with_metadata-c5d1b5f542967276.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + NetApp driver with DHSS True mode now supports setup the share server + network VLAN segmentation through share network subnet metadata. + To do so, the field `set_vlan` must be informed with VLAN number. + It can set the network MTU passing the metadata field `set_mtu`. If + the subnet metadata contains the `set_vlan` without the `set_mtu` + field the MTU is configured according to network plugin.