# Copyright (c) 2014 NetApp, Inc. # All Rights Reserved. # # 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 # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import hashlib import mock from manila import context from manila.share import configuration from manila.share.drivers.netapp import api as naapi from manila.share.drivers.netapp import cluster_mode as driver from manila import test class NetAppClusteredDrvTestCase(test.TestCase): """Tests for NetApp cmode driver. """ def setUp(self): super(NetAppClusteredDrvTestCase, self).setUp() self._context = context.get_admin_context() self._db = mock.Mock() driver.driver.NetAppApiClient = mock.Mock() self.driver = driver.NetAppClusteredShareDriver( self._db, configuration=configuration.Configuration(None)) self.driver._client = mock.Mock() self.driver._client.send_request = mock.Mock() self._vserver_client = mock.Mock() self._vserver_client.send_request = mock.Mock() driver.driver.NetAppApiClient = mock.Mock( return_value=self._vserver_client) self.share = {'id': 'fake_uuid', 'project_id': 'fake_tenant_id', 'name': 'fake_name', 'size': 1, 'share_proto': 'fake', 'share_network_id': 'fake_net_id', 'network_info': { 'network_allocations': [ {'ip_address': 'ip'} ] } } self.snapshot = {'id': 'fake_snapshot_uuid', 'project_id': 'fake_tenant_id', 'share_id': 'fake_share_id', 'share': self.share } self.security_service = {'id': 'fake_id', 'domain': 'FAKE', 'server': 'fake_server', 'sid': 'fake_sid', 'password': 'fake_password'} self.helper = mock.Mock() self.driver._helpers = {'FAKE': self.helper} self.driver._licenses = ['fake'] def test_create_vserver(self): res = naapi.NaElement('fake') res.add_new_child('aggregate-name', 'aggr') self.driver.configuration.netapp_root_volume_aggregate = 'root' fake_aggrs = mock.Mock() fake_aggrs.get_child_by_name.return_value = fake_aggrs fake_aggrs.get_children.return_value = [res] self.driver._client.send_request = mock.Mock(return_value=fake_aggrs) vserver_create_args = { 'vserver-name': 'os_fake_net_id', 'root-volume-security-style': 'unix', 'root-volume-aggregate': 'root', 'root-volume': 'root', 'name-server-switch': { 'nsswitch': 'file' } } vserver_modify_args = { 'aggr-list': [ {'aggr-name': 'aggr'} ], 'vserver-name': 'os_fake_net_id'} self.driver._create_vserver('os_fake_net_id') self.driver._client.send_request.assert_has_calls([ mock.call('vserver-create', vserver_create_args), mock.call('aggr-get-iter'), mock.call('vserver-modify', vserver_modify_args), ] ) def test_get_network_allocations_number(self): res = mock.Mock() res.get_child_content.return_value = '5' self.driver._client.send_request = mock.Mock(return_value=res) self.assertEqual(self.driver.get_network_allocations_number(), 5) def test_delete_vserver(self): self.driver._delete_vserver('fake', self._vserver_client) self._vserver_client.send_request.assert_has_calls([ mock.call('volume-offline', {'name': 'root'}), mock.call('volume-destroy', {'name': 'root'}) ]) self.driver._client.send_request.assert_called_once_with( 'vserver-destroy', {'vserver-name': 'fake'}) def test_create_net_iface(self): self.driver._create_net_iface('1.1.1.1', '255.255.255.0', '200', 'node', 'port', 'vserver-name', 'all_id') vlan_args = { 'vlan-info': { 'parent-interface': 'port', 'node': 'node', 'vlanid': '200'} } interface_args = { 'address': '1.1.1.1', 'administrative-status': 'up', 'data-protocols': [ {'data-protocol': 'nfs'}, {'data-protocol': 'cifs'} ], 'home-node': 'node', 'home-port': 'port-200', 'netmask': '255.255.255.0', 'interface-name': 'os_all_id', 'role': 'data', 'vserver': 'vserver-name', } self.driver._client.send_request.assert_has_calls([ mock.call('net-vlan-create', vlan_args), mock.call('net-interface-create', interface_args), ]) def test_enable_nfs(self): self.driver._enable_nfs(self._vserver_client) export_args = { 'client-match': '0.0.0.0/0', 'policy-name': 'default', 'ro-rule': { 'security-flavor': 'any' }, 'rw-rule': { 'security-flavor': 'any' } } self._vserver_client.send_request.assert_has_calls( [mock.call('nfs-enable'), mock.call('nfs-service-modify', {'is-nfsv40-enabled': 'true'}), mock.call('export-rule-create', export_args)] ) def test_configure_ldap(self): conf_name = hashlib.md5('fake_id').hexdigest() client_args = { 'ldap-client-config': conf_name, 'servers': { 'ip-address': 'fake_server' }, 'tcp-port': '389', 'schema': 'RFC-2307', 'bind-password': 'fake_password' } config_args = {'client-config': conf_name, 'client-enabled': 'true'} self.driver._configure_ldap(self.security_service, self._vserver_client) self._vserver_client.send_request.assert_has_calls([ mock.call('ldap-client-create', client_args), mock.call('ldap-config-create', config_args)]) def test_configure_kerberos(self): kerberos_args = {'admin-server-ip': 'fake_server', 'admin-server-port': '749', 'clock-skew': '5', 'comment': '', 'config-name': 'fake_id', 'kdc-ip': 'fake_server', 'kdc-port': '88', 'kdc-vendor': 'other', 'password-server-ip': 'fake_server', 'password-server-port': '464', 'realm': 'FAKE'} spn = 'nfs/fake-vserver.FAKE@FAKE' kerberos_modify_args = {'admin-password': 'fake_password', 'admin-user-name': 'fake_sid', 'interface-name': 'fake_lif', 'is-kerberos-enabled': 'true', 'service-principal-name': spn } self.driver._get_lifs = mock.Mock(return_value=['fake_lif']) self.driver._configure_dns = mock.Mock(return_value=['fake_lif']) self.driver._configure_kerberos('fake_vserver', self.security_service, self._vserver_client) self.driver._client.send_request.assert_called_once_with( 'kerberos-realm-create', kerberos_args) self._vserver_client.send_request.assert_called_once_with( 'kerberos-config-modify', kerberos_modify_args) def test_configure_active_directory(self): self.driver._configure_dns = mock.Mock() self.driver._configure_active_directory(self.security_service, self._vserver_client) args = {'admin-username': 'fake_sid', 'admin-password': 'fake_password', 'force-account-overwrite': 'true', 'cifs-server': 'fake_server', 'domain': 'FAKE'} self._vserver_client.send_request.assert_called_with( 'cifs-server-create', args) def test_allocate_container(self): root = naapi.NaElement('root') attributes = naapi.NaElement('attributes') vserver_info = naapi.NaElement('vserver-info') vserver_aggr_info_list = naapi.NaElement('vserver-aggr-info-list') for i in range(1, 4): vserver_aggr_info_list.add_node_with_children('aggr-attributes', **{'aggr-name': 'fake%s' % i, 'aggr-availsize': '%s' % i}) vserver_info.add_child_elem(vserver_aggr_info_list) attributes.add_child_elem(vserver_info) root.add_child_elem(attributes) root.add_new_child('attributes', None) self._vserver_client.send_request = mock.Mock(return_value=root) self.driver._allocate_container(self.share, 'vserver', self._vserver_client) args = {'containing-aggr-name': 'fake3', 'size': '1g', 'volume': 'share_fake_uuid', 'junction-path': '/share_fake_uuid' } self._vserver_client.send_request.assert_called_with( 'volume-create', args) def test_allocate_container_from_snapshot(self): self.driver._allocate_container_from_snapshot(self.share, self.snapshot, 'vserver', self._vserver_client) args = {'volume': 'share_fake_uuid', 'parent-volume': 'share_fake_share_id', 'parent-snapshot': 'share_snapshot_fake_snapshot_uuid', 'junction-path': '/share_fake_uuid'} self._vserver_client.send_request.assert_called_with( 'volume-clone-create', args) def test_deallocate_container(self): self.driver._deallocate_container(self.share, self._vserver_client) self._vserver_client.send_request.assert_has_calls([ mock.call('volume-unmount', {'volume-name': 'share_fake_uuid'}), mock.call('volume-offline', {'name': 'share_fake_uuid'}), mock.call('volume-destroy', {'name': 'share_fake_uuid'}) ]) def test_create_export(self): self.helper.create_share = mock.Mock(return_value="fake-location") export_location = self.driver._create_export( self.share, 'vserver', self._vserver_client) self.helper.create_share.assert_called_once_with( "share_%s" % self.share['id'], 'ip') self.assertEqual(export_location, "fake-location") def test_create_snapshot(self): self.driver.create_snapshot(self._context, self.snapshot) self._vserver_client.send_request.assert_called_once_with( 'snapshot-create', {'volume': 'share_fake_share_id', 'snapshot': 'share_snapshot_fake_snapshot_uuid'}) def test_delete_share(self): resp = mock.Mock() resp.get_child_content.return_value = 1 self._vserver_client.send_request = mock.Mock(return_value=resp) self.driver.delete_share(self._context, self.share) self.helper.delete_share.assert_called_once_with(self.share) def test_allow_access(self): access = "1.2.3.4" self.driver.allow_access(self._context, self.share, access) self.helper.allow_access.assert_called_ince_with(self._context, self.share, access) def test_deny_access(self): access = "1.2.3.4" self.driver.deny_access(self._context, self.share, access) self.helper.deny_access.assert_called_ince_with(self._context, self.share, access) class NetAppNFSHelperTestCase(test.TestCase): """Tests for NetApp 7mode driver. """ def setUp(self): super(NetAppNFSHelperTestCase, self).setUp() self._context = context.get_admin_context() self._db = mock.Mock() self.client = mock.Mock() self.share = {'id': 'fake_uuid', 'tenant_id': 'fake_tenant_id', 'name': 'fake_name', 'size': 1, 'export_location': 'location:/path', 'share_proto': 'fake'} self.helper = driver.NetAppClusteredNFSHelper() self.helper._client = mock.Mock() self.helper._client.send_request = mock.Mock() def test_create_share(self): location = self.helper.create_share('share_name', 'fake-vserver-location') self.helper._client.send_request.assert_called_once_with( 'nfs-exportfs-append-rules-2', mock.ANY) self.assertEqual(location, 'fake-vserver-location:/share_name') def test_delete_share(self): self.helper.delete_share(self.share) self.helper._client.send_request.assert_called_once_with( 'nfs-exportfs-delete-rules', mock.ANY) def test_allow_access(self): access = {'access_to': '1.2.3.4', 'access_type': 'ip'} root = naapi.NaElement('root') rules = naapi.NaElement('rules') root.add_child_elem(rules) self.helper._client.send_request = mock.Mock(return_value=root) self.helper.allow_access(self._context, self.share, access) self.helper._client.send_request.assert_has_calls([ mock.call('nfs-exportfs-list-rules-2', mock.ANY), mock.call('nfs-exportfs-append-rules-2', mock.ANY) ]) def test_deny_access(self): access = {'access_to': '1.2.3.4', 'access_type': 'ip'} root = naapi.NaElement('root') rules = naapi.NaElement('rules') root.add_child_elem(rules) self.helper._client.send_request = mock.Mock(return_value=root) self.helper.allow_access(self._context, self.share, access) self.helper._client.send_request.assert_has_calls([ mock.call('nfs-exportfs-list-rules-2', mock.ANY), mock.call('nfs-exportfs-append-rules-2', mock.ANY) ]) class NetAppCIFSHelperTestCase(test.TestCase): """Tests for NetApp 7mode driver. """ def setUp(self): super(NetAppCIFSHelperTestCase, self).setUp() self._context = context.get_admin_context() self._db = mock.Mock() self.share = {'id': 'fake_uuid', 'tenant_id': 'fake_tenant_id', 'name': 'fake_name', 'size': 1, 'export_location': 'location:/path', 'share_proto': 'fake'} self.helper = driver.NetAppClusteredCIFSHelper() self.helper._client = mock.Mock() self.helper._client.send_request = mock.Mock() def test_create_share(self): self.helper.create_share('fake_name', '1.1.1.1') self.helper._client.send_request.assert_has_calls([ mock.call('cifs-share-create', {'path': '/fake_name', 'share-name': 'fake_name'}), mock.call('cifs-share-access-control-delete', {'user-or-group': 'Everyone', 'share': 'fake_name'}) ]) def test_delete_share(self): self.share['export_location'] = "nfs://host/fake_name" self.helper.delete_share(self.share) self.helper._client.send_request.assert_called_with( 'cifs-share-delete', {'share-name': 'fake_name'}) def test_allow_access(self): self.helper._allow_access_for('fake_name', 'fake_share') self.helper._client.send_request.assert_called_with( 'cifs-share-access-control-create', {'permission': 'full_control', 'share': 'fake_share', 'user-or-group': 'fake_name'})