diff --git a/doc/source/admin/emc_unity_driver.rst b/doc/source/admin/emc_unity_driver.rst index 1369228e78..c186fa3a10 100644 --- a/doc/source/admin/emc_unity_driver.rst +++ b/doc/source/admin/emc_unity_driver.rst @@ -35,7 +35,7 @@ Requirements ------------ - Unity OE 4.0.1 or higher. -- StorOps 0.2.17 or higher is installed on Manila node. +- StorOps 0.5.7 or higher is installed on Manila node. - Following licenses are activated on Unity: * CIFS/SMB Support @@ -138,6 +138,31 @@ for the Unity driver. Restart of :term:`manila-share` service is needed for the configuration changes to take effect. +IPv6 support +------------ + +IPv6 support for Unity driver is introduced in Queens release. The feature is divided +into two parts: + +1. The driver is able to manage share or snapshot in the Neutron IPv6 network. +2. The driver is able to connect Unity management interface using its IPv6 address. + +Pre-Configurations for IPv6 support +=================================== + +The following parameters need to be configured in `/etc/manila/manila.conf` +for the Unity driver: + + network_plugin_ipv6_enabled = True + +- `network_plugin_ipv6_enabled` indicates IPv6 is enabled. + +If you want to connect Unity using IPv6 address, you should configure IPv6 address +by `/net/if/mgmt` uemcli command, `mgmtInterfaceSettings` RESTful api or the system +settings of Unity GUI for Unity and specify the address in `/etc/manila/manila.conf`: + + emc_nas_server = + Restrictions ------------ diff --git a/doc/source/admin/share_back_ends_feature_support_mapping.rst b/doc/source/admin/share_back_ends_feature_support_mapping.rst index c3c2e507b9..1aae9b9a3f 100644 --- a/doc/source/admin/share_back_ends_feature_support_mapping.rst +++ b/doc/source/admin/share_back_ends_feature_support_mapping.rst @@ -108,7 +108,7 @@ Mapping of share drivers and share access rules support +----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+ | EMC VNX | NFS (J) | NFS (Q) | CIFS (J) | \- | \- | NFS (L) | NFS (Q) | CIFS (L) | \- | \- | +----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+ -| EMC Unity | NFS (N) | \- | CIFS (N) | \- | \- | NFS (N) | \- | CIFS (N) | \- | \- | +| EMC Unity | NFS (N) | NFS (Q) | CIFS (N) | \- | \- | NFS (N) | NFS (Q) | CIFS (N) | \- | \- | +----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+ | EMC Isilon | NFS,CIFS (K) | \- | CIFS (M) | \- | \- | NFS (M) | \- | CIFS (M) | \- | \- | +----------------------------------------+--------------+--------------+----------------+------------+--------------+--------------+--------------+----------------+------------+------------+ @@ -232,7 +232,7 @@ More information: :ref:`capabilities_and_extra_specs` +----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+ | EMC VNX | J | \- | \- | \- | \- | L | \- | J | \- | \- | P | Q | +----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+ -| EMC Unity | N | \- | \- | \- | N | \- | \- | N | \- | \- | P | \- | +| EMC Unity | N | \- | \- | \- | N | \- | \- | N | \- | \- | P | Q | +----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+ | EMC Isilon | \- | K | \- | \- | \- | L | \- | K | \- | \- | P | \- | +----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+--------------------+--------------+--------------+ diff --git a/manila/share/drivers/dell_emc/driver.py b/manila/share/drivers/dell_emc/driver.py index 46d684e225..d0ec05db72 100644 --- a/manila/share/drivers/dell_emc/driver.py +++ b/manila/share/drivers/dell_emc/driver.py @@ -77,6 +77,7 @@ class EMCShareDriver(driver.ShareDriver): configuration=self.configuration) super(EMCShareDriver, self).__init__( self.plugin.driver_handles_share_servers, *args, **kwargs) + self.ipv6_implemented = self.plugin.ipv6_implemented if hasattr(self.plugin, 'ipv6_implemented'): self.ipv6_implemented = self.plugin.ipv6_implemented diff --git a/manila/share/drivers/dell_emc/plugins/unity/client.py b/manila/share/drivers/dell_emc/plugins/unity/client.py index 159c7d6ac7..753d9a4aa5 100644 --- a/manila/share/drivers/dell_emc/plugins/unity/client.py +++ b/manila/share/drivers/dell_emc/plugins/unity/client.py @@ -26,6 +26,7 @@ if storops: from manila.common import constants as const from manila import exception from manila.i18n import _ +from manila.share.drivers.dell_emc.common.enas import utils as enas_utils from manila.share.drivers.dell_emc.plugins.unity import utils LOG = log.getLogger(__name__) @@ -171,11 +172,12 @@ class UnityClient(object): @staticmethod def create_interface(nas_server, ip_addr, netmask, gateway, port_id, - vlan_id=None): + vlan_id=None, prefix_length=None): try: nas_server.create_file_interface(port_id, ip_addr, netmask=netmask, + v6_prefix_length=prefix_length, gateway=gateway, vlan_id=vlan_id) except storops_ex.UnityIpAddressUsedError: @@ -262,6 +264,7 @@ class UnityClient(object): def nfs_allow_access(self, share_name, host_ip, access_level): share = self.system.get_nfs_share(name=share_name) + host_ip = enas_utils.convert_ipv6_format_if_needed(host_ip) if access_level == const.ACCESS_LEVEL_RW: share.allow_read_write_access(host_ip, force_create_host=True) share.allow_root_access(host_ip, force_create_host=True) diff --git a/manila/share/drivers/dell_emc/plugins/unity/connection.py b/manila/share/drivers/dell_emc/plugins/unity/connection.py index 1b187384e2..727b7d1982 100644 --- a/manila/share/drivers/dell_emc/plugins/unity/connection.py +++ b/manila/share/drivers/dell_emc/plugins/unity/connection.py @@ -19,6 +19,7 @@ from oslo_config import cfg from oslo_log import log from oslo_utils import excutils from oslo_utils import importutils +from oslo_utils import netutils storops = importutils.try_import('storops') if storops: @@ -35,7 +36,7 @@ from manila.share.drivers.dell_emc.plugins.unity import utils as unity_utils from manila.share import utils as share_utils from manila import utils -VERSION = "3.0.0" +VERSION = "4.0.0" LOG = log.getLogger(__name__) SUPPORTED_NETWORK_TYPES = (None, 'flat', 'vlan') @@ -83,6 +84,7 @@ class UnityStorageConnection(driver.StorageConnection): self.reserved_percentage = None self.max_over_subscription_ratio = None self.port_ids_conf = None + self.ipv6_implemented = True # props from super class. self.driver_handles_share_servers = True @@ -475,17 +477,20 @@ class UnityStorageConnection(driver.StorageConnection): return network def _create_network_interface(self, nas_server, network, port_id): - ip_addr = network['ip_address'] - netmask = utils.cidr_to_netmask(network['cidr']) - gateway = network['gateway'] - vlan_id = network['segmentation_id'] + kargs = {'ip_addr': network['ip_address'], + 'gateway': network['gateway'], + 'vlan_id': network['segmentation_id'], + 'port_id': port_id} + + if netutils.is_valid_ipv6_cidr(kargs['ip_addr']): + kargs['netmask'] = None + kargs['prefix_length'] = str(utils.cidr_to_prefixlen( + network['cidr'])) + else: + kargs['netmask'] = utils.cidr_to_netmask(network['cidr']) + # Create the interfaces on NAS server - self.client.create_interface(nas_server, - ip_addr, - netmask, - gateway, - port_id=port_id, - vlan_id=vlan_id) + self.client.create_interface(nas_server, **kargs) def _choose_sp(self, sp_ports_map): sp = None @@ -508,7 +513,7 @@ class UnityStorageConnection(driver.StorageConnection): def _get_cifs_location(file_interfaces, share_name): return [ {'path': r'\\%(interface)s\%(share_name)s' % { - 'interface': interface.ip_address, + 'interface': enas_utils.export_unc_path(interface.ip_address), 'share_name': share_name} } for interface in file_interfaces @@ -551,7 +556,8 @@ class UnityStorageConnection(driver.StorageConnection): def _get_nfs_location(file_interfaces, share_name): return [ {'path': '%(interface)s:/%(share_name)s' % { - 'interface': interface.ip_address, + 'interface': enas_utils.convert_ipv6_format_if_needed( + interface.ip_address), 'share_name': share_name} } for interface in file_interfaces diff --git a/manila/tests/share/drivers/dell_emc/plugins/unity/mocked_manila.yaml b/manila/tests/share/drivers/dell_emc/plugins/unity/mocked_manila.yaml index 0662b1ffd7..6e823a26b0 100644 --- a/manila/tests/share/drivers/dell_emc/plugins/unity/mocked_manila.yaml +++ b/manila/tests/share/drivers/dell_emc/plugins/unity/mocked_manila.yaml @@ -45,6 +45,17 @@ network_allocations_vxlan: network_type: vxlan mtu: 1500 +network_allocations_ipv6: + _type: 'network_allocations' + _properties: &network_allocations_ipv6_prop + - id: '04ac4c27-9cf7-4406-809c-13edc93e9844' + ip_address: '2001:db8:0:1:f816:3eff:fe76:35c4' + cidr: '2001:db8:0:1:f816:3eff:fe76:35c4/64' + segmentation_id: 170 + gateway: '2001:db8:0:1::1' + network_type: vlan + mtu: 1500 + active_directory: _type: 'security_service' _properties: &active_directory_prop @@ -97,6 +108,13 @@ network_info__vxlan: network_type: 'vxlan' network_allocations: *network_allocations_vxlan_prop +network_info__ipv6: + _type: 'network_info' + _properties: &network_info__ipv6_prop + <<: *network_info_flat_prop + network_allocations: *network_allocations_ipv6_prop + segmentation_id: 170 + network_info__active_directory: _type: 'network_info' _properties: diff --git a/manila/tests/share/drivers/dell_emc/plugins/unity/mocked_unity.yaml b/manila/tests/share/drivers/dell_emc/plugins/unity/mocked_unity.yaml index fa25c145ab..69ef556409 100644 --- a/manila/tests/share/drivers/dell_emc/plugins/unity/mocked_unity.yaml +++ b/manila/tests/share/drivers/dell_emc/plugins/unity/mocked_unity.yaml @@ -27,6 +27,13 @@ interface_2: &interface_2 _properties: ip_address: 'fake_ip_addr_2' +interface_ipv6: &interface_ipv6 + _properties: + ip_addr: '2001:db8:0:1:f816:3eff:fe76:35c4' + gateway: '2001:db8:0:1::1' + prefix_length: '64' + vlan_id: '201' + nas_server: &nas_server _properties: &nas_server_prop name: '78fd845f-8e7d-487f-bfde-051d83e78103' @@ -34,6 +41,13 @@ nas_server: &nas_server current_sp: *sp_a home_sp: *sp_a +nas_server_ipv6: &nas_server_ipv6 + _properties: &nas_server_ipv6_prop + name: 'af1eef2f-be66-4df1-8f25-9720f087da05' + file_interface: [*interface_ipv6] + current_sp: *sp_a + home_sp: *sp_a + filesystem_base: &filesystem_base _properties: &filesystem_base_prop name: 'fake_filesystem_name' @@ -1082,3 +1096,9 @@ test_get_file_ports: unity: _methods: get_file_port: [*port_1, *port_internal_port, *down_port, *la_port] + +test_create_file_interface_ipv6: + file_interface: *interface_ipv6 + nas_server: + _methods: + create_file_interface: diff --git a/manila/tests/share/drivers/dell_emc/plugins/unity/test_client.py b/manila/tests/share/drivers/dell_emc/plugins/unity/test_client.py index 088afd5bac..3603db1569 100644 --- a/manila/tests/share/drivers/dell_emc/plugins/unity/test_client.py +++ b/manila/tests/share/drivers/dell_emc/plugins/unity/test_client.py @@ -14,6 +14,7 @@ # under the License. import ddt +import mock from oslo_utils import units from manila import exception @@ -207,3 +208,26 @@ class TestClient(test.TestCase): def test_get_tenant_for_vlan_already_has_interfaces(self, client): tenant = client.get_tenant('tenant', 3) self.assertEqual('tenant_1', tenant.id) + + @res_mock.mock_client_input + @res_mock.patch_client + def test_create_file_interface_ipv6(self, client, mocked_input): + mock_nas_server = mock.Mock() + mock_nas_server.create_file_interface = mock.Mock(return_value=None) + mock_file_interface = mocked_input['file_interface'] + mock_port_id = mock.Mock() + client.create_interface(mock_nas_server, + mock_file_interface.ip_addr, + netmask=None, + gateway=mock_file_interface.gateway, + port_id=mock_port_id, + vlan_id=mock_file_interface.vlan_id, + prefix_length=mock_file_interface.prefix_length + ) + mock_nas_server.create_file_interface.assert_called_once_with( + mock_port_id, + mock_file_interface.ip_addr, + netmask=None, + v6_prefix_length=mock_file_interface.prefix_length, + gateway=mock_file_interface.gateway, + vlan_id=mock_file_interface.vlan_id) diff --git a/manila/tests/share/drivers/dell_emc/plugins/unity/test_connection.py b/manila/tests/share/drivers/dell_emc/plugins/unity/test_connection.py index 64e1be4c4b..a94b21b00f 100644 --- a/manila/tests/share/drivers/dell_emc/plugins/unity/test_connection.py +++ b/manila/tests/share/drivers/dell_emc/plugins/unity/test_connection.py @@ -15,6 +15,7 @@ import copy import ddt +import mock from oslo_utils import units import six @@ -613,3 +614,42 @@ class TestConnection(test.TestCase): self.assertRaises(exception.InvalidShareAccessLevel, connection.allow_access, None, share, rw_access) + + @res_mock.patch_connection + def test__create_network_interface_ipv6(self, connection): + connection.client.create_interface = mock.Mock(return_value=None) + nas_server = mock.Mock() + network = {'ip_address': '2001:db8:0:1:f816:3eff:fe76:35c4', + 'cidr': '2001:db8:0:1:f816:3eff:fe76:35c4/64', + 'gateway': '2001:db8:0:1::1', + 'segmentation_id': '201'} + port_id = mock.Mock() + connection._create_network_interface(nas_server, network, port_id) + + expected = {'ip_addr': '2001:db8:0:1:f816:3eff:fe76:35c4', + 'netmask': None, + 'gateway': '2001:db8:0:1::1', + 'port_id': port_id, + 'vlan_id': '201', + 'prefix_length': '64'} + connection.client.create_interface.assert_called_once_with(nas_server, + **expected) + + @res_mock.patch_connection + def test__create_network_interface_ipv4(self, connection): + connection.client.create_interface = mock.Mock(return_value=None) + nas_server = mock.Mock() + network = {'ip_address': '192.168.1.10', + 'cidr': '192.168.1.10/24', + 'gateway': '192.168.1.1', + 'segmentation_id': '201'} + port_id = mock.Mock() + connection._create_network_interface(nas_server, network, port_id) + + expected = {'ip_addr': '192.168.1.10', + 'netmask': '255.255.255.0', + 'gateway': '192.168.1.1', + 'port_id': port_id, + 'vlan_id': '201'} + connection.client.create_interface.assert_called_once_with(nas_server, + **expected) diff --git a/manila/tests/share/drivers/dell_emc/test_driver.py b/manila/tests/share/drivers/dell_emc/test_driver.py index 1a259d7cb4..0faecb72f7 100644 --- a/manila/tests/share/drivers/dell_emc/test_driver.py +++ b/manila/tests/share/drivers/dell_emc/test_driver.py @@ -24,6 +24,7 @@ from manila import test class FakeConnection(base.StorageConnection): def __init__(self, *args, **kwargs): + self.ipv6_implemented = True pass @property diff --git a/releasenotes/notes/unity-manila-ipv6-support-dd9bcf23064baceb.yaml b/releasenotes/notes/unity-manila-ipv6-support-dd9bcf23064baceb.yaml new file mode 100644 index 0000000000..62eb46d54f --- /dev/null +++ b/releasenotes/notes/unity-manila-ipv6-support-dd9bcf23064baceb.yaml @@ -0,0 +1,3 @@ +--- +features: + - IPv6 support for Dell EMC Unity Manila driver.