"Fossies" - the Fresh Open Source Software Archive

Member "manila-8.1.4/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py" (19 Nov 2020, 250104 Bytes) of package /linux/misc/openstack/manila-8.1.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_client_cmode.py": 8.1.3_vs_8.1.4.

    1 # Copyright (c) 2014 Alex Meade.  All rights reserved.
    2 # Copyright (c) 2015 Clinton Knight.  All rights reserved.
    3 # Copyright (c) 2015 Tom Barron.  All rights reserved.
    4 #
    5 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    6 #    not use this file except in compliance with the License. You may obtain
    7 #    a copy of the License at
    8 #
    9 #         http://www.apache.org/licenses/LICENSE-2.0
   10 #
   11 #    Unless required by applicable law or agreed to in writing, software
   12 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   13 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   14 #    License for the specific language governing permissions and limitations
   15 #    under the License.
   16 
   17 import copy
   18 import hashlib
   19 import time
   20 
   21 import ddt
   22 import mock
   23 from oslo_log import log
   24 import six
   25 
   26 from manila import exception
   27 from manila.share.drivers.netapp.dataontap.client import api as netapp_api
   28 from manila.share.drivers.netapp.dataontap.client import client_base
   29 from manila.share.drivers.netapp.dataontap.client import client_cmode
   30 from manila import test
   31 from manila.tests.share.drivers.netapp.dataontap.client import fakes as fake
   32 
   33 
   34 @ddt.ddt
   35 class NetAppClientCmodeTestCase(test.TestCase):
   36 
   37     def setUp(self):
   38         super(NetAppClientCmodeTestCase, self).setUp()
   39 
   40         # Mock loggers as themselves to allow logger arg validation
   41         mock_logger = log.getLogger('mock_logger')
   42         self.mock_object(client_cmode.LOG,
   43                          'error',
   44                          mock.Mock(side_effect=mock_logger.error))
   45         self.mock_object(client_cmode.LOG,
   46                          'warning',
   47                          mock.Mock(side_effect=mock_logger.warning))
   48         self.mock_object(client_cmode.LOG,
   49                          'debug',
   50                          mock.Mock(side_effect=mock_logger.debug))
   51 
   52         self.mock_object(client_base.NetAppBaseClient,
   53                          'get_ontapi_version',
   54                          mock.Mock(return_value=(1, 20)))
   55 
   56         self.mock_object(client_base.NetAppBaseClient,
   57                          'get_system_version',
   58                          mock.Mock(return_value={
   59                              'version-tuple': (8, 3, 0),
   60                              'version': fake.VERSION,
   61                          }))
   62 
   63         self.client = client_cmode.NetAppCmodeClient(**fake.CONNECTION_INFO)
   64         self.client.connection = mock.MagicMock()
   65 
   66         self.vserver_client = client_cmode.NetAppCmodeClient(
   67             **fake.CONNECTION_INFO)
   68         self.vserver_client.set_vserver(fake.VSERVER_NAME)
   69         self.vserver_client.connection = mock.MagicMock()
   70 
   71     def _mock_api_error(self, code='fake', message='fake'):
   72         return mock.Mock(side_effect=netapp_api.NaApiError(code=code,
   73                                                            message=message))
   74 
   75     def test_init_features_ontapi_1_21(self):
   76 
   77         self.mock_object(client_base.NetAppBaseClient,
   78                          'get_ontapi_version',
   79                          mock.Mock(return_value=(1, 21)))
   80 
   81         self.client._init_features()
   82 
   83         self.assertFalse(self.client.features.BROADCAST_DOMAINS)
   84         self.assertFalse(self.client.features.IPSPACES)
   85         self.assertFalse(self.client.features.SUBNETS)
   86         self.assertFalse(self.client.features.FLEXVOL_ENCRYPTION)
   87 
   88     @ddt.data((1, 30), (1, 40), (2, 0))
   89     def test_init_features_ontapi_1_30(self, ontapi_version):
   90 
   91         self.mock_object(client_base.NetAppBaseClient,
   92                          'get_ontapi_version',
   93                          mock.Mock(return_value=ontapi_version))
   94 
   95         self.client._init_features()
   96 
   97         self.assertTrue(self.client.features.BROADCAST_DOMAINS)
   98         self.assertTrue(self.client.features.IPSPACES)
   99         self.assertTrue(self.client.features.SUBNETS)
  100 
  101     @ddt.data((1, 110), (2, 0))
  102     def test_init_features_ontap_1_110(self, ontapi_version):
  103 
  104         self.mock_object(client_base.NetAppBaseClient,
  105                          'get_ontapi_version',
  106                          mock.Mock(return_value=ontapi_version))
  107 
  108         self.client._init_features()
  109 
  110         self.assertTrue(self.client.features.BROADCAST_DOMAINS)
  111         self.assertTrue(self.client.features.IPSPACES)
  112         self.assertTrue(self.client.features.SUBNETS)
  113         self.assertTrue(self.client.features.FLEXVOL_ENCRYPTION)
  114 
  115     @ddt.data(((9, 1, 0), fake.VERSION_NO_DARE), ((8, 3, 2), fake.VERSION))
  116     @ddt.unpack
  117     def test_is_nve_supported_unsupported_release_or_platform(self, gen, ver):
  118 
  119         system_version = {'version-tuple': gen, 'version': ver}
  120         self.mock_object(client_base.NetAppBaseClient,
  121                          'get_system_version',
  122                          mock.Mock(return_value=system_version))
  123         self.mock_object(self.client,
  124                          'get_security_key_manager_nve_support',
  125                          mock.Mock(return_value=True))
  126         self.mock_object(self.client,
  127                          'list_cluster_nodes',
  128                          mock.Mock(return_value=fake.NODE_NAMES))
  129 
  130         result = self.client.is_nve_supported()
  131 
  132         self.assertFalse(result)
  133 
  134     def test_is_nve_supported_valid_platform_and_supported_release(self):
  135 
  136         system_version = {
  137             'version-tuple': (9, 1, 0),
  138             'version': fake.VERSION,
  139         }
  140         self.mock_object(client_base.NetAppBaseClient,
  141                          'get_system_version',
  142                          mock.Mock(return_value=system_version))
  143         self.mock_object(self.client,
  144                          'get_security_key_manager_nve_support',
  145                          mock.Mock(return_value=True))
  146         self.mock_object(self.client,
  147                          'list_cluster_nodes',
  148                          mock.Mock(return_value=fake.NODE_NAMES))
  149 
  150         result = self.client.is_nve_supported()
  151         self.assertTrue(result)
  152 
  153     def test_is_nve_supported_key_manager_not_enabled(self):
  154 
  155         system_version = {
  156             'version-tuple': (9, 1, 0),
  157             'version': fake.VERSION,
  158         }
  159         self.mock_object(client_base.NetAppBaseClient,
  160                          'get_system_version',
  161                          mock.Mock(return_value=system_version))
  162         self.mock_object(self.client,
  163                          'get_security_key_manager_nve_support',
  164                          mock.Mock(return_value=False))
  165         self.mock_object(self.client,
  166                          'list_cluster_nodes',
  167                          mock.Mock(return_value=fake.NODE_NAMES))
  168 
  169         result = self.client.is_nve_supported()
  170 
  171         self.assertFalse(result)
  172 
  173     def test_get_security_key_manager_nve_support_enabled(self):
  174         api_response = netapp_api.NaElement(
  175             fake.SECUTITY_KEY_MANAGER_NVE_SUPPORT_RESPONSE_TRUE)
  176         self.mock_object(self.client,
  177                          'send_request',
  178                          mock.Mock(return_value=api_response))
  179 
  180         result = self.client.get_security_key_manager_nve_support(
  181             fake.NODE_NAME)
  182 
  183         self.assertTrue(result)
  184         api_args = {'node': fake.NODE_NAME}
  185         self.client.send_request.assert_has_calls([
  186             mock.call('security-key-manager-volume-encryption-supported',
  187                       api_args)])
  188 
  189     def test_get_security_key_manager_nve_support_disabled(self):
  190         api_response = netapp_api.NaElement(
  191             fake.SECUTITY_KEY_MANAGER_NVE_SUPPORT_RESPONSE_FALSE)
  192         self.mock_object(self.client,
  193                          'send_request',
  194                          mock.Mock(return_value=api_response))
  195 
  196         result = self.client.get_security_key_manager_nve_support(
  197             fake.NODE_NAME)
  198 
  199         self.assertFalse(result)
  200         api_args = {'node': fake.NODE_NAME}
  201         self.client.send_request.assert_has_calls([
  202             mock.call('security-key-manager-volume-encryption-supported',
  203                       api_args)])
  204 
  205     def test_get_security_key_manager_nve_support_disabled_no_license(self):
  206         self.mock_object(self.client,
  207                          'send_request',
  208                          self._mock_api_error())
  209 
  210         result = self.client.get_security_key_manager_nve_support(
  211             fake.NODE_NAME)
  212 
  213         self.assertFalse(result)
  214 
  215         api_args = {'node': fake.NODE_NAME}
  216         self.client.send_request.assert_has_calls([
  217             mock.call('security-key-manager-volume-encryption-supported',
  218                       api_args)])
  219 
  220     @ddt.data((True, True, True), (False, None, False))
  221     @ddt.unpack
  222     def test_send_volume_move_request_success(self, validation_only,
  223                                               encrypt_dst, fv_encryption):
  224         self.mock_object(self.client, 'features',
  225                          mock.Mock(FLEXVOL_ENCRYPTION=fv_encryption))
  226         self.client._send_volume_move_request(fake.ROOT_VOLUME_NAME,
  227                                               fake.NODE_VSERVER_NAME,
  228                                               fake.SHARE_AGGREGATE_NAME,
  229                                               validation_only=validation_only,
  230                                               encrypt_destination=encrypt_dst)
  231 
  232     @ddt.data((True, True, False))
  233     @ddt.unpack
  234     def test_send_volume_move_request_failure(self, validation_only,
  235                                               encrypt_dst, fv_encrypt):
  236         self.mock_object(self.client, 'features',
  237                          mock.Mock(FLEXVOL_ENCRYPTION=fv_encrypt))
  238         self.assertRaises(exception.NetAppException,
  239                           self.client._send_volume_move_request,
  240                           fake.ROOT_VOLUME_NAME,
  241                           fake.NODE_VSERVER_NAME,
  242                           fake.SHARE_AGGREGATE_NAME,
  243                           validation_only=validation_only,
  244                           encrypt_destination=encrypt_dst)
  245 
  246     def test_invoke_vserver_api(self):
  247 
  248         self.client._invoke_vserver_api('fake-api', 'fake_vserver')
  249 
  250         self.client.connection.set_vserver.assert_has_calls(
  251             [mock.call('fake_vserver')])
  252         self.client.connection.invoke_successfully.assert_has_calls(
  253             [mock.call('fake-api', True)])
  254 
  255     def test_has_records(self):
  256         self.assertTrue(self.client._has_records(
  257             netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE)))
  258 
  259     def test_has_records_not_found(self):
  260         self.assertFalse(self.client._has_records(
  261             netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)))
  262 
  263     @ddt.data((fake.VSERVER_GET_ITER_RESPONSE, 1),
  264               (fake.NO_RECORDS_RESPONSE, 0))
  265     @ddt.unpack
  266     def test_get_record_count(self, response, expected):
  267 
  268         api_response = netapp_api.NaElement(response)
  269 
  270         result = self.client._get_record_count(api_response)
  271 
  272         self.assertEqual(expected, result)
  273 
  274     def test_get_records_count_invalid(self):
  275 
  276         api_response = netapp_api.NaElement(
  277             fake.INVALID_GET_ITER_RESPONSE_NO_RECORDS)
  278 
  279         self.assertRaises(exception.NetAppException,
  280                           self.client._get_record_count,
  281                           api_response)
  282 
  283     def test_send_iter_request(self):
  284 
  285         api_responses = [
  286             netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_1),
  287             netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_2),
  288             netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_3),
  289         ]
  290         mock_send_request = self.mock_object(
  291             self.client, 'send_request',
  292             mock.Mock(side_effect=api_responses))
  293 
  294         storage_disk_get_iter_args = {
  295             'desired-attributes': {
  296                 'storage-disk-info': {
  297                     'disk-name': None,
  298                 }
  299             }
  300         }
  301         result = self.client.send_iter_request(
  302             'storage-disk-get-iter', api_args=storage_disk_get_iter_args,
  303             max_page_length=10)
  304 
  305         num_records = result.get_child_content('num-records')
  306         self.assertEqual('28', num_records)
  307         next_tag = result.get_child_content('next-tag')
  308         self.assertEqual('', next_tag)
  309 
  310         args1 = copy.deepcopy(storage_disk_get_iter_args)
  311         args1['max-records'] = 10
  312         args2 = copy.deepcopy(storage_disk_get_iter_args)
  313         args2['max-records'] = 10
  314         args2['tag'] = 'next_tag_1'
  315         args3 = copy.deepcopy(storage_disk_get_iter_args)
  316         args3['max-records'] = 10
  317         args3['tag'] = 'next_tag_2'
  318 
  319         mock_send_request.assert_has_calls([
  320             mock.call('storage-disk-get-iter', args1),
  321             mock.call('storage-disk-get-iter', args2),
  322             mock.call('storage-disk-get-iter', args3),
  323         ])
  324 
  325     def test_send_iter_request_single_page(self):
  326 
  327         api_response = netapp_api.NaElement(
  328             fake.STORAGE_DISK_GET_ITER_RESPONSE)
  329         mock_send_request = self.mock_object(
  330             self.client, 'send_request',
  331             mock.Mock(return_value=api_response))
  332 
  333         storage_disk_get_iter_args = {
  334             'desired-attributes': {
  335                 'storage-disk-info': {
  336                     'disk-name': None,
  337                 }
  338             }
  339         }
  340         result = self.client.send_iter_request(
  341             'storage-disk-get-iter', api_args=storage_disk_get_iter_args,
  342             max_page_length=10)
  343 
  344         num_records = result.get_child_content('num-records')
  345         self.assertEqual('4', num_records)
  346 
  347         args = copy.deepcopy(storage_disk_get_iter_args)
  348         args['max-records'] = 10
  349 
  350         mock_send_request.assert_has_calls([
  351             mock.call('storage-disk-get-iter', args),
  352         ])
  353 
  354     def test_send_iter_request_not_found(self):
  355 
  356         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
  357         mock_send_request = self.mock_object(
  358             self.client, 'send_request',
  359             mock.Mock(return_value=api_response))
  360 
  361         result = self.client.send_iter_request('storage-disk-get-iter')
  362 
  363         num_records = result.get_child_content('num-records')
  364         self.assertEqual('0', num_records)
  365 
  366         args = {'max-records': client_cmode.DEFAULT_MAX_PAGE_LENGTH}
  367 
  368         mock_send_request.assert_has_calls([
  369             mock.call('storage-disk-get-iter', args),
  370         ])
  371 
  372     @ddt.data(fake.INVALID_GET_ITER_RESPONSE_NO_ATTRIBUTES,
  373               fake.INVALID_GET_ITER_RESPONSE_NO_RECORDS)
  374     def test_send_iter_request_invalid(self, fake_response):
  375 
  376         api_response = netapp_api.NaElement(fake_response)
  377         self.mock_object(self.client,
  378                          'send_request',
  379                          mock.Mock(return_value=api_response))
  380 
  381         self.assertRaises(exception.NetAppException,
  382                           self.client.send_iter_request,
  383                           'storage-disk-get-iter')
  384 
  385     def test_set_vserver(self):
  386         self.client.set_vserver(fake.VSERVER_NAME)
  387         self.client.connection.set_vserver.assert_has_calls(
  388             [mock.call('fake_vserver')])
  389 
  390     def test_vserver_exists(self):
  391 
  392         api_response = netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE)
  393         self.mock_object(self.client,
  394                          'send_iter_request',
  395                          mock.Mock(return_value=api_response))
  396 
  397         vserver_get_args = {
  398             'query': {'vserver-info': {'vserver-name': fake.VSERVER_NAME}},
  399             'desired-attributes': {'vserver-info': {'vserver-name': None}}
  400         }
  401 
  402         result = self.client.vserver_exists(fake.VSERVER_NAME)
  403 
  404         self.client.send_iter_request.assert_has_calls([
  405             mock.call('vserver-get-iter', vserver_get_args)])
  406         self.assertTrue(result)
  407 
  408     def test_vserver_exists_not_found(self):
  409 
  410         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
  411         self.mock_object(self.client,
  412                          'send_request',
  413                          mock.Mock(return_value=api_response))
  414 
  415         result = self.client.vserver_exists(fake.VSERVER_NAME)
  416 
  417         self.assertFalse(result)
  418 
  419     def test_create_vserver_no_ipspace(self):
  420 
  421         self.mock_object(self.client, 'send_request')
  422 
  423         vserver_create_args = {
  424             'vserver-name': fake.VSERVER_NAME,
  425             'root-volume-security-style': 'unix',
  426             'root-volume-aggregate': fake.ROOT_VOLUME_AGGREGATE_NAME,
  427             'root-volume': fake.ROOT_VOLUME_NAME,
  428             'name-server-switch': {'nsswitch': 'file'}
  429         }
  430         vserver_modify_args = {
  431             'aggr-list': [{'aggr-name': aggr_name} for aggr_name
  432                           in fake.SHARE_AGGREGATE_NAMES],
  433             'vserver-name': fake.VSERVER_NAME
  434         }
  435 
  436         self.client.create_vserver(fake.VSERVER_NAME,
  437                                    fake.ROOT_VOLUME_AGGREGATE_NAME,
  438                                    fake.ROOT_VOLUME_NAME,
  439                                    fake.SHARE_AGGREGATE_NAMES,
  440                                    None)
  441 
  442         self.client.send_request.assert_has_calls([
  443             mock.call('vserver-create', vserver_create_args),
  444             mock.call('vserver-modify', vserver_modify_args)])
  445 
  446     def test_create_vserver_with_ipspace(self):
  447 
  448         self.client.features.add_feature('IPSPACES')
  449         self.mock_object(self.client, 'send_request')
  450 
  451         vserver_create_args = {
  452             'vserver-name': fake.VSERVER_NAME,
  453             'root-volume-security-style': 'unix',
  454             'root-volume-aggregate': fake.ROOT_VOLUME_AGGREGATE_NAME,
  455             'root-volume': fake.ROOT_VOLUME_NAME,
  456             'name-server-switch': {'nsswitch': 'file'},
  457             'ipspace': fake.IPSPACE_NAME,
  458         }
  459         vserver_modify_args = {
  460             'aggr-list': [{'aggr-name': aggr_name} for aggr_name
  461                           in fake.SHARE_AGGREGATE_NAMES],
  462             'vserver-name': fake.VSERVER_NAME
  463         }
  464 
  465         self.client.create_vserver(fake.VSERVER_NAME,
  466                                    fake.ROOT_VOLUME_AGGREGATE_NAME,
  467                                    fake.ROOT_VOLUME_NAME,
  468                                    fake.SHARE_AGGREGATE_NAMES,
  469                                    fake.IPSPACE_NAME)
  470 
  471         self.client.send_request.assert_has_calls([
  472             mock.call('vserver-create', vserver_create_args),
  473             mock.call('vserver-modify', vserver_modify_args)])
  474 
  475     def test_create_vserver_ipspaces_not_supported(self):
  476 
  477         self.assertRaises(exception.NetAppException,
  478                           self.client.create_vserver,
  479                           fake.VSERVER_NAME,
  480                           fake.ROOT_VOLUME_AGGREGATE_NAME,
  481                           fake.ROOT_VOLUME_NAME,
  482                           fake.SHARE_AGGREGATE_NAMES,
  483                           fake.IPSPACE_NAME)
  484 
  485     def test_get_vserver_root_volume_name(self):
  486 
  487         api_response = netapp_api.NaElement(
  488             fake.VSERVER_GET_ROOT_VOLUME_NAME_RESPONSE)
  489         self.mock_object(self.client,
  490                          'send_iter_request',
  491                          mock.Mock(return_value=api_response))
  492 
  493         vserver_get_args = {
  494             'query': {'vserver-info': {'vserver-name': fake.VSERVER_NAME}},
  495             'desired-attributes': {'vserver-info': {'root-volume': None}}
  496         }
  497 
  498         result = self.client.get_vserver_root_volume_name(fake.VSERVER_NAME)
  499 
  500         self.client.send_iter_request.assert_has_calls([
  501             mock.call('vserver-get-iter', vserver_get_args)])
  502         self.assertEqual(fake.ROOT_VOLUME_NAME, result)
  503 
  504     def test_get_vserver_root_volume_name_not_found(self):
  505 
  506         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
  507         self.mock_object(self.client,
  508                          'send_iter_request',
  509                          mock.Mock(return_value=api_response))
  510 
  511         self.assertRaises(exception.NetAppException,
  512                           self.client.get_vserver_root_volume_name,
  513                           fake.VSERVER_NAME)
  514 
  515     def test_get_vserver_ipspace(self):
  516 
  517         self.client.features.add_feature('IPSPACES')
  518         api_response = netapp_api.NaElement(
  519             fake.VSERVER_GET_IPSPACE_NAME_RESPONSE)
  520         self.mock_object(self.client,
  521                          'send_iter_request',
  522                          mock.Mock(return_value=api_response))
  523 
  524         result = self.client.get_vserver_ipspace(fake.VSERVER_NAME)
  525 
  526         vserver_get_iter_args = {
  527             'query': {
  528                 'vserver-info': {
  529                     'vserver-name': fake.VSERVER_NAME,
  530                 },
  531             },
  532             'desired-attributes': {
  533                 'vserver-info': {
  534                     'ipspace': None,
  535                 },
  536             },
  537         }
  538         self.client.send_iter_request.assert_has_calls([
  539             mock.call('vserver-get-iter', vserver_get_iter_args)])
  540         self.assertEqual(fake.IPSPACE_NAME, result)
  541 
  542     def test_get_vserver_ipspace_not_supported(self):
  543 
  544         result = self.client.get_vserver_ipspace(fake.IPSPACE_NAME)
  545 
  546         self.assertIsNone(result)
  547 
  548     def test_get_vserver_ipspace_not_found(self):
  549 
  550         self.client.features.add_feature('IPSPACES')
  551         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
  552         self.mock_object(self.client,
  553                          'send_iter_request',
  554                          mock.Mock(return_value=api_response))
  555 
  556         self.assertRaises(exception.NetAppException,
  557                           self.client.get_vserver_ipspace,
  558                           fake.IPSPACE_NAME)
  559 
  560     def test_ipspace_has_data_vservers(self):
  561 
  562         self.client.features.add_feature('IPSPACES')
  563         api_response = netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE)
  564         self.mock_object(self.client,
  565                          'send_iter_request',
  566                          mock.Mock(return_value=api_response))
  567 
  568         result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
  569 
  570         vserver_get_iter_args = {
  571             'query': {
  572                 'vserver-info': {
  573                     'ipspace': fake.IPSPACE_NAME,
  574                     'vserver-type': 'data'
  575                 },
  576             },
  577             'desired-attributes': {
  578                 'vserver-info': {
  579                     'vserver-name': None,
  580                 },
  581             },
  582         }
  583         self.client.send_iter_request.assert_has_calls([
  584             mock.call('vserver-get-iter', vserver_get_iter_args)])
  585         self.assertTrue(result)
  586 
  587     def test_ipspace_has_data_vservers_not_supported(self):
  588 
  589         result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
  590 
  591         self.assertFalse(result)
  592 
  593     def test_ipspace_has_data_vservers_not_found(self):
  594 
  595         self.client.features.add_feature('IPSPACES')
  596         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
  597         self.mock_object(self.client,
  598                          'send_request',
  599                          mock.Mock(return_value=api_response))
  600 
  601         result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
  602 
  603         self.assertFalse(result)
  604 
  605     def test_list_vservers(self):
  606 
  607         api_response = netapp_api.NaElement(
  608             fake.VSERVER_DATA_LIST_RESPONSE)
  609         self.mock_object(self.client,
  610                          'send_iter_request',
  611                          mock.Mock(return_value=api_response))
  612 
  613         result = self.client.list_vservers()
  614 
  615         vserver_get_iter_args = {
  616             'query': {
  617                 'vserver-info': {
  618                     'vserver-type': 'data'
  619                 }
  620             },
  621             'desired-attributes': {
  622                 'vserver-info': {
  623                     'vserver-name': None
  624                 }
  625             }
  626         }
  627         self.client.send_iter_request.assert_has_calls([
  628             mock.call('vserver-get-iter', vserver_get_iter_args)])
  629         self.assertListEqual([fake.VSERVER_NAME], result)
  630 
  631     def test_list_vservers_node_type(self):
  632 
  633         api_response = netapp_api.NaElement(
  634             fake.VSERVER_DATA_LIST_RESPONSE)
  635         self.mock_object(self.client,
  636                          'send_iter_request',
  637                          mock.Mock(return_value=api_response))
  638 
  639         result = self.client.list_vservers(vserver_type='node')
  640 
  641         vserver_get_iter_args = {
  642             'query': {
  643                 'vserver-info': {
  644                     'vserver-type': 'node'
  645                 }
  646             },
  647             'desired-attributes': {
  648                 'vserver-info': {
  649                     'vserver-name': None
  650                 }
  651             }
  652         }
  653         self.client.send_iter_request.assert_has_calls([
  654             mock.call('vserver-get-iter', vserver_get_iter_args)])
  655         self.assertListEqual([fake.VSERVER_NAME], result)
  656 
  657     def test_list_vservers_not_found(self):
  658 
  659         api_response = netapp_api.NaElement(
  660             fake.NO_RECORDS_RESPONSE)
  661         self.mock_object(self.client,
  662                          'send_request',
  663                          mock.Mock(return_value=api_response))
  664 
  665         result = self.client.list_vservers(vserver_type='data')
  666 
  667         self.assertListEqual([], result)
  668 
  669     def test_get_vserver_volume_count(self):
  670 
  671         api_response = netapp_api.NaElement(fake.VOLUME_COUNT_RESPONSE)
  672         self.mock_object(self.client,
  673                          'send_iter_request',
  674                          mock.Mock(return_value=api_response))
  675 
  676         result = self.client.get_vserver_volume_count()
  677 
  678         self.assertEqual(2, result)
  679 
  680     def test_delete_vserver_no_volumes(self):
  681 
  682         self.mock_object(self.client,
  683                          'vserver_exists',
  684                          mock.Mock(return_value=True))
  685         self.mock_object(self.client,
  686                          'get_vserver_root_volume_name',
  687                          mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
  688         self.mock_object(self.vserver_client,
  689                          'get_vserver_volume_count',
  690                          mock.Mock(return_value=0))
  691         self.mock_object(self.client, '_terminate_vserver_services')
  692         self.mock_object(self.client, 'send_request')
  693 
  694         self.client.delete_vserver(
  695             fake.VSERVER_NAME,
  696             self.vserver_client,
  697             security_services=[fake.CIFS_SECURITY_SERVICE])
  698 
  699         self.client._terminate_vserver_services.assert_called_with(
  700             fake.VSERVER_NAME, self.vserver_client,
  701             [fake.CIFS_SECURITY_SERVICE])
  702 
  703         vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME}
  704         self.client.send_request.assert_has_calls([
  705             mock.call('vserver-destroy', vserver_destroy_args)])
  706 
  707     def test_delete_vserver_one_volume(self):
  708 
  709         self.mock_object(self.client,
  710                          'vserver_exists',
  711                          mock.Mock(return_value=True))
  712         self.mock_object(self.client,
  713                          'get_vserver_root_volume_name',
  714                          mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
  715         self.mock_object(self.vserver_client,
  716                          'get_vserver_volume_count',
  717                          mock.Mock(return_value=1))
  718         self.mock_object(self.client, 'send_request')
  719         self.mock_object(self.vserver_client, 'offline_volume')
  720         self.mock_object(self.vserver_client, 'delete_volume')
  721 
  722         self.client.delete_vserver(fake.VSERVER_NAME,
  723                                    self.vserver_client)
  724 
  725         self.vserver_client.offline_volume.assert_called_with(
  726             fake.ROOT_VOLUME_NAME)
  727         self.vserver_client.delete_volume.assert_called_with(
  728             fake.ROOT_VOLUME_NAME)
  729 
  730         vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME}
  731         self.client.send_request.assert_has_calls([
  732             mock.call('vserver-destroy', vserver_destroy_args)])
  733 
  734     def test_delete_vserver_one_volume_already_offline(self):
  735 
  736         self.mock_object(self.client,
  737                          'vserver_exists',
  738                          mock.Mock(return_value=True))
  739         self.mock_object(self.client,
  740                          'get_vserver_root_volume_name',
  741                          mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
  742         self.mock_object(self.vserver_client,
  743                          'get_vserver_volume_count',
  744                          mock.Mock(return_value=1))
  745         self.mock_object(self.client, 'send_request')
  746         self.mock_object(self.vserver_client,
  747                          'offline_volume',
  748                          self._mock_api_error(code=netapp_api.EVOLUMEOFFLINE))
  749 
  750         self.mock_object(self.vserver_client, 'delete_volume')
  751 
  752         self.client.delete_vserver(fake.VSERVER_NAME,
  753                                    self.vserver_client)
  754 
  755         self.vserver_client.offline_volume.assert_called_with(
  756             fake.ROOT_VOLUME_NAME)
  757         self.vserver_client.delete_volume.assert_called_with(
  758             fake.ROOT_VOLUME_NAME)
  759 
  760         vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME}
  761         self.client.send_request.assert_has_calls([
  762             mock.call('vserver-destroy', vserver_destroy_args)])
  763         self.assertEqual(1, client_cmode.LOG.error.call_count)
  764 
  765     def test_delete_vserver_one_volume_api_error(self):
  766 
  767         self.mock_object(self.client,
  768                          'vserver_exists',
  769                          mock.Mock(return_value=True))
  770         self.mock_object(self.client,
  771                          'get_vserver_root_volume_name',
  772                          mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
  773         self.mock_object(self.vserver_client,
  774                          'get_vserver_volume_count',
  775                          mock.Mock(return_value=1))
  776         self.mock_object(self.client, 'send_request')
  777         self.mock_object(self.vserver_client,
  778                          'offline_volume',
  779                          self._mock_api_error())
  780         self.mock_object(self.vserver_client, 'delete_volume')
  781 
  782         self.assertRaises(netapp_api.NaApiError,
  783                           self.client.delete_vserver,
  784                           fake.VSERVER_NAME,
  785                           self.vserver_client)
  786 
  787     def test_delete_vserver_multiple_volumes(self):
  788 
  789         self.mock_object(self.client,
  790                          'vserver_exists',
  791                          mock.Mock(return_value=True))
  792         self.mock_object(self.client,
  793                          'get_vserver_root_volume_name',
  794                          mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
  795         self.mock_object(self.vserver_client,
  796                          'get_vserver_volume_count',
  797                          mock.Mock(return_value=2))
  798 
  799         self.assertRaises(exception.NetAppException,
  800                           self.client.delete_vserver,
  801                           fake.VSERVER_NAME,
  802                           self.vserver_client)
  803 
  804     def test_delete_vserver_not_found(self):
  805 
  806         self.mock_object(self.client,
  807                          'vserver_exists',
  808                          mock.Mock(return_value=False))
  809 
  810         self.client.delete_vserver(fake.VSERVER_NAME,
  811                                    self.vserver_client)
  812 
  813         self.assertEqual(1, client_cmode.LOG.error.call_count)
  814 
  815     def test_terminate_vserver_services(self):
  816 
  817         self.mock_object(self.vserver_client, 'send_request')
  818 
  819         self.client._terminate_vserver_services(fake.VSERVER_NAME,
  820                                                 self.vserver_client,
  821                                                 [fake.CIFS_SECURITY_SERVICE])
  822 
  823         cifs_server_delete_args = {
  824             'admin-password': fake.CIFS_SECURITY_SERVICE['password'],
  825             'admin-username': fake.CIFS_SECURITY_SERVICE['user'],
  826         }
  827         self.vserver_client.send_request.assert_has_calls([
  828             mock.call('cifs-server-delete', cifs_server_delete_args)])
  829 
  830     def test_terminate_vserver_services_cifs_not_found(self):
  831 
  832         self.mock_object(self.vserver_client,
  833                          'send_request',
  834                          self._mock_api_error(
  835                              code=netapp_api.EOBJECTNOTFOUND))
  836 
  837         self.client._terminate_vserver_services(fake.VSERVER_NAME,
  838                                                 self.vserver_client,
  839                                                 [fake.CIFS_SECURITY_SERVICE])
  840 
  841         cifs_server_delete_args = {
  842             'admin-password': fake.CIFS_SECURITY_SERVICE['password'],
  843             'admin-username': fake.CIFS_SECURITY_SERVICE['user'],
  844         }
  845         self.vserver_client.send_request.assert_has_calls([
  846             mock.call('cifs-server-delete', cifs_server_delete_args)])
  847         self.assertEqual(1, client_cmode.LOG.error.call_count)
  848 
  849     def test_terminate_vserver_services_api_error(self):
  850 
  851         side_effects = [netapp_api.NaApiError(code='fake'), None]
  852         self.mock_object(self.vserver_client,
  853                          'send_request',
  854                          mock.Mock(side_effect=side_effects))
  855 
  856         self.client._terminate_vserver_services(fake.VSERVER_NAME,
  857                                                 self.vserver_client,
  858                                                 [fake.CIFS_SECURITY_SERVICE])
  859 
  860         cifs_server_delete_args = {
  861             'admin-password': fake.CIFS_SECURITY_SERVICE['password'],
  862             'admin-username': fake.CIFS_SECURITY_SERVICE['user'],
  863         }
  864         self.vserver_client.send_request.assert_has_calls([
  865             mock.call('cifs-server-delete', cifs_server_delete_args),
  866             mock.call('cifs-server-delete')])
  867         self.assertEqual(0, client_cmode.LOG.error.call_count)
  868 
  869     def test_list_cluster_nodes(self):
  870 
  871         api_response = netapp_api.NaElement(
  872             fake.SYSTEM_NODE_GET_ITER_RESPONSE)
  873         self.mock_object(self.client,
  874                          'send_request',
  875                          mock.Mock(return_value=api_response))
  876 
  877         result = self.client.list_cluster_nodes()
  878 
  879         self.assertListEqual([fake.NODE_NAME], result)
  880 
  881     def test_list_cluster_nodes_not_found(self):
  882 
  883         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
  884         self.mock_object(self.client,
  885                          'send_request',
  886                          mock.Mock(return_value=api_response))
  887 
  888         result = self.client.list_cluster_nodes()
  889 
  890         self.assertListEqual([], result)
  891 
  892     def test_list_node_data_ports(self):
  893 
  894         self.mock_object(self.client,
  895                          'get_node_data_ports',
  896                          mock.Mock(return_value=fake.SPEED_SORTED_PORTS))
  897 
  898         result = self.client.list_node_data_ports(fake.NODE_NAME)
  899 
  900         self.assertSequenceEqual(fake.SPEED_SORTED_PORT_NAMES, result)
  901 
  902     def test_get_node_data_ports(self):
  903 
  904         api_response = netapp_api.NaElement(fake.NET_PORT_GET_ITER_RESPONSE)
  905         self.mock_object(self.client,
  906                          'send_iter_request',
  907                          mock.Mock(return_value=api_response))
  908 
  909         result = self.client.get_node_data_ports(fake.NODE_NAME)
  910 
  911         net_port_get_iter_args = {
  912             'query': {
  913                 'net-port-info': {
  914                     'node': fake.NODE_NAME,
  915                     'link-status': 'up',
  916                     'port-type': 'physical|if_group',
  917                     'role': 'data',
  918                 },
  919             },
  920             'desired-attributes': {
  921                 'net-port-info': {
  922                     'port': None,
  923                     'node': None,
  924                     'operational-speed': None,
  925                     'ifgrp-port': None,
  926                 },
  927             },
  928         }
  929 
  930         self.assertSequenceEqual(fake.SPEED_SORTED_PORTS, result)
  931         self.client.send_iter_request.assert_has_calls([
  932             mock.call('net-port-get-iter', net_port_get_iter_args)])
  933 
  934     def test_get_node_data_ports_not_found(self):
  935 
  936         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
  937         self.mock_object(self.client,
  938                          'send_iter_request',
  939                          mock.Mock(return_value=api_response))
  940 
  941         result = self.client.get_node_data_ports(fake.NODE_NAME)
  942 
  943         self.assertSequenceEqual([], result)
  944 
  945     def test_sort_data_ports_by_speed(self):
  946 
  947         result = self.client._sort_data_ports_by_speed(
  948             fake.UNSORTED_PORTS_ALL_SPEEDS)
  949 
  950         self.assertSequenceEqual(fake.SORTED_PORTS_ALL_SPEEDS, result)
  951 
  952     def test_list_root_aggregates(self):
  953 
  954         api_response = netapp_api.NaElement(
  955             fake.AGGR_GET_ITER_ROOT_AGGR_RESPONSE)
  956         self.mock_object(self.client,
  957                          'send_iter_request',
  958                          mock.Mock(return_value=api_response))
  959 
  960         result = self.client.list_root_aggregates()
  961 
  962         aggr_get_iter_args = {
  963             'desired-attributes': {
  964                 'aggr-attributes': {
  965                     'aggregate-name': None,
  966                     'aggr-raid-attributes': {
  967                         'has-local-root': None,
  968                         'has-partner-root': None,
  969                     },
  970                 },
  971             }
  972         }
  973         self.assertSequenceEqual(fake.ROOT_AGGREGATE_NAMES, result)
  974         self.client.send_iter_request.assert_has_calls([
  975             mock.call('aggr-get-iter', aggr_get_iter_args)])
  976 
  977     def test_list_non_root_aggregates(self):
  978 
  979         api_response = netapp_api.NaElement(
  980             fake.AGGR_GET_ITER_NON_ROOT_AGGR_RESPONSE)
  981         self.mock_object(self.client,
  982                          'send_iter_request',
  983                          mock.Mock(return_value=api_response))
  984 
  985         result = self.client.list_non_root_aggregates()
  986 
  987         aggr_get_iter_args = {
  988             'query': {
  989                 'aggr-attributes': {
  990                     'aggr-raid-attributes': {
  991                         'has-local-root': 'false',
  992                         'has-partner-root': 'false',
  993                     }
  994                 },
  995             },
  996             'desired-attributes': {
  997                 'aggr-attributes': {
  998                     'aggregate-name': None,
  999                 },
 1000             },
 1001         }
 1002         self.assertSequenceEqual(fake.SHARE_AGGREGATE_NAMES, result)
 1003         self.client.send_iter_request.assert_has_calls([
 1004             mock.call('aggr-get-iter', aggr_get_iter_args)])
 1005 
 1006     def test_list_aggregates(self):
 1007 
 1008         api_response = netapp_api.NaElement(fake.AGGR_GET_NAMES_RESPONSE)
 1009         self.mock_object(self.client,
 1010                          'send_iter_request',
 1011                          mock.Mock(return_value=api_response))
 1012 
 1013         result = self.client._list_aggregates()
 1014 
 1015         aggr_get_iter_args = {
 1016             'desired-attributes': {
 1017                 'aggr-attributes': {
 1018                     'aggregate-name': None,
 1019                 },
 1020             },
 1021         }
 1022         self.assertSequenceEqual(
 1023             fake.ROOT_AGGREGATE_NAMES + fake.SHARE_AGGREGATE_NAMES, result)
 1024         self.client.send_iter_request.assert_has_calls([
 1025             mock.call('aggr-get-iter', aggr_get_iter_args)])
 1026 
 1027     def test_list_aggregates_not_found(self):
 1028 
 1029         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 1030         self.mock_object(self.client,
 1031                          'send_request',
 1032                          mock.Mock(return_value=api_response))
 1033 
 1034         self.assertRaises(exception.NetAppException,
 1035                           self.client._list_aggregates)
 1036 
 1037     def test_list_vserver_aggregates(self):
 1038 
 1039         self.mock_object(self.vserver_client,
 1040                          'get_vserver_aggregate_capacities',
 1041                          mock.Mock(return_value=fake.VSERVER_AGGREGATES))
 1042 
 1043         result = self.vserver_client.list_vserver_aggregates()
 1044 
 1045         self.assertListEqual(list(fake.VSERVER_AGGREGATES.keys()), result)
 1046 
 1047     def test_list_vserver_aggregates_none_found(self):
 1048 
 1049         self.mock_object(self.vserver_client,
 1050                          'get_vserver_aggregate_capacities',
 1051                          mock.Mock(return_value={}))
 1052 
 1053         result = self.vserver_client.list_vserver_aggregates()
 1054 
 1055         self.assertListEqual([], result)
 1056 
 1057     @ddt.data((True, True), (True, False), (False, True), (False, False))
 1058     @ddt.unpack
 1059     def test_create_network_interface(self, broadcast_domains_supported,
 1060                                       use_vlans):
 1061 
 1062         self.client.features.add_feature('BROADCAST_DOMAINS',
 1063                                          broadcast_domains_supported)
 1064         self.mock_object(self.client, '_ensure_broadcast_domain_for_port')
 1065         self.mock_object(self.client, '_create_vlan')
 1066         self.mock_object(self.client, 'send_request')
 1067 
 1068         lif_create_args = {
 1069             'address': fake.IP_ADDRESS,
 1070             'administrative-status': 'up',
 1071             'data-protocols': [
 1072                 {'data-protocol': 'nfs'},
 1073                 {'data-protocol': 'cifs'}
 1074             ],
 1075             'home-node': fake.NODE_NAME,
 1076             'home-port': fake.VLAN_PORT if use_vlans else fake.PORT,
 1077             'netmask': fake.NETMASK,
 1078             'interface-name': fake.LIF_NAME,
 1079             'role': 'data',
 1080             'vserver': fake.VSERVER_NAME,
 1081         }
 1082         self.client.create_network_interface(fake.IP_ADDRESS,
 1083                                              fake.NETMASK,
 1084                                              fake.VLAN if use_vlans else None,
 1085                                              fake.NODE_NAME,
 1086                                              fake.PORT,
 1087                                              fake.VSERVER_NAME,
 1088                                              fake.LIF_NAME,
 1089                                              fake.IPSPACE_NAME,
 1090                                              fake.MTU)
 1091 
 1092         if use_vlans:
 1093             self.client._create_vlan.assert_called_with(
 1094                 fake.NODE_NAME, fake.PORT, fake.VLAN)
 1095         else:
 1096             self.assertFalse(self.client._create_vlan.called)
 1097 
 1098         if broadcast_domains_supported:
 1099             self.client._ensure_broadcast_domain_for_port.assert_called_with(
 1100                 fake.NODE_NAME, fake.VLAN_PORT if use_vlans else fake.PORT,
 1101                 fake.MTU, ipspace=fake.IPSPACE_NAME)
 1102         else:
 1103             self.assertFalse(
 1104                 self.client._ensure_broadcast_domain_for_port.called)
 1105 
 1106         self.client.send_request.assert_has_calls([
 1107             mock.call('net-interface-create', lif_create_args)])
 1108 
 1109     def test_create_vlan(self):
 1110 
 1111         self.mock_object(self.client, 'send_request')
 1112 
 1113         vlan_create_args = {
 1114             'vlan-info': {
 1115                 'parent-interface': fake.PORT,
 1116                 'node': fake.NODE_NAME,
 1117                 'vlanid': fake.VLAN
 1118             }
 1119         }
 1120         self.client._create_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
 1121 
 1122         self.client.send_request.assert_has_calls([
 1123             mock.call('net-vlan-create', vlan_create_args)])
 1124 
 1125     def test_create_vlan_already_present(self):
 1126 
 1127         self.mock_object(self.client,
 1128                          'send_request',
 1129                          self._mock_api_error(code=netapp_api.EDUPLICATEENTRY))
 1130 
 1131         vlan_create_args = {
 1132             'vlan-info': {
 1133                 'parent-interface': fake.PORT,
 1134                 'node': fake.NODE_NAME,
 1135                 'vlanid': fake.VLAN
 1136             }
 1137         }
 1138         self.client._create_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
 1139 
 1140         self.client.send_request.assert_has_calls([
 1141             mock.call('net-vlan-create', vlan_create_args)])
 1142         self.assertEqual(1, client_cmode.LOG.debug.call_count)
 1143 
 1144     def test_create_vlan_api_error(self):
 1145 
 1146         self.mock_object(self.client, 'send_request', self._mock_api_error())
 1147 
 1148         self.assertRaises(exception.NetAppException,
 1149                           self.client._create_vlan,
 1150                           fake.NODE_NAME,
 1151                           fake.PORT,
 1152                           fake.VLAN)
 1153 
 1154     def test_delete_vlan(self):
 1155 
 1156         self.mock_object(self.client, 'send_request')
 1157 
 1158         vlan_delete_args = {
 1159             'vlan-info': {
 1160                 'parent-interface': fake.PORT,
 1161                 'node': fake.NODE_NAME,
 1162                 'vlanid': fake.VLAN
 1163             }
 1164         }
 1165         self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
 1166 
 1167         self.client.send_request.assert_has_calls([
 1168             mock.call('net-vlan-delete', vlan_delete_args)])
 1169 
 1170     def test_delete_vlan_still_used(self):
 1171 
 1172         self.mock_object(self.client,
 1173                          'send_request',
 1174                          self._mock_api_error(code=netapp_api.EAPIERROR,
 1175                                               message='Port already has a '
 1176                                               'lif bound. '))
 1177 
 1178         vlan_delete_args = {
 1179             'vlan-info': {
 1180                 'parent-interface': fake.PORT,
 1181                 'node': fake.NODE_NAME,
 1182                 'vlanid': fake.VLAN
 1183             }
 1184         }
 1185         self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
 1186 
 1187         self.client.send_request.assert_has_calls([
 1188             mock.call('net-vlan-delete', vlan_delete_args)])
 1189         self.assertEqual(1, client_cmode.LOG.debug.call_count)
 1190 
 1191     def test_delete_vlan_api_error(self):
 1192 
 1193         self.mock_object(self.client, 'send_request', self._mock_api_error())
 1194 
 1195         self.assertRaises(exception.NetAppException,
 1196                           self.client.delete_vlan,
 1197                           fake.NODE_NAME,
 1198                           fake.PORT,
 1199                           fake.VLAN)
 1200 
 1201     @ddt.data(('10.10.10.0/24', '10.10.10.1', False),
 1202               ('fc00::/7', 'fe80::1', False),
 1203               ('0.0.0.0/0', '10.10.10.1', True),
 1204               ('::/0', 'fe80::1', True))
 1205     @ddt.unpack
 1206     def test_create_route(self, subnet, gateway, omit_destination):
 1207         api_response = netapp_api.NaElement(
 1208             fake.NET_ROUTES_CREATE_RESPONSE)
 1209         expected_api_args = {
 1210             'destination': subnet,
 1211             'gateway': gateway,
 1212             'return-record': 'true',
 1213         }
 1214         self.mock_object(
 1215             self.client, 'send_request', mock.Mock(return_value=api_response))
 1216 
 1217         destination = None if omit_destination else subnet
 1218         self.client.create_route(gateway, destination=destination)
 1219 
 1220         self.client.send_request.assert_called_once_with(
 1221             'net-routes-create', expected_api_args)
 1222 
 1223     def test_create_route_duplicate(self):
 1224         self.mock_object(client_cmode.LOG, 'debug')
 1225         expected_api_args = {
 1226             'destination': fake.SUBNET,
 1227             'gateway': fake.GATEWAY,
 1228             'return-record': 'true',
 1229         }
 1230         self.mock_object(
 1231             self.client, 'send_request',
 1232             mock.Mock(side_effect=self._mock_api_error(
 1233                 code=netapp_api.EAPIERROR, message='Duplicate route exists.')))
 1234 
 1235         self.client.create_route(fake.GATEWAY, destination=fake.SUBNET)
 1236 
 1237         self.client.send_request.assert_called_once_with(
 1238             'net-routes-create', expected_api_args)
 1239         self.assertEqual(1, client_cmode.LOG.debug.call_count)
 1240 
 1241     def test_create_route_api_error(self):
 1242         expected_api_args = {
 1243             'destination': fake.SUBNET,
 1244             'gateway': fake.GATEWAY,
 1245             'return-record': 'true',
 1246         }
 1247         self.mock_object(
 1248             self.client, 'send_request',
 1249             mock.Mock(side_effect=self._mock_api_error()))
 1250 
 1251         self.assertRaises(exception.NetAppException,
 1252                           self.client.create_route,
 1253                           fake.GATEWAY, destination=fake.SUBNET)
 1254 
 1255         self.client.send_request.assert_called_once_with(
 1256             'net-routes-create', expected_api_args)
 1257 
 1258     def test_create_route_without_gateway(self):
 1259         self.mock_object(self.client, 'send_request')
 1260         self.client.create_route(None, destination=fake.SUBNET)
 1261         self.assertFalse(self.client.send_request.called)
 1262 
 1263     def test_ensure_broadcast_domain_for_port_domain_match(self):
 1264 
 1265         port_info = {
 1266             'ipspace': fake.IPSPACE_NAME,
 1267             'broadcast-domain': fake.BROADCAST_DOMAIN,
 1268         }
 1269         self.mock_object(self.client,
 1270                          '_get_broadcast_domain_for_port',
 1271                          mock.Mock(return_value=port_info))
 1272         self.mock_object(self.client,
 1273                          '_broadcast_domain_exists',
 1274                          mock.Mock(return_value=True))
 1275         self.mock_object(self.client, '_create_broadcast_domain')
 1276         self.mock_object(self.client, '_modify_broadcast_domain')
 1277         self.mock_object(self.client, '_add_port_to_broadcast_domain')
 1278 
 1279         self.client._ensure_broadcast_domain_for_port(
 1280             fake.NODE_NAME, fake.PORT, fake.MTU, ipspace=fake.IPSPACE_NAME)
 1281 
 1282         self.client._get_broadcast_domain_for_port.assert_called_once_with(
 1283             fake.NODE_NAME, fake.PORT)
 1284         self.client._modify_broadcast_domain.assert_called_once_with(
 1285             fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
 1286         self.assertFalse(self.client._broadcast_domain_exists.called)
 1287         self.assertFalse(self.client._create_broadcast_domain.called)
 1288         self.assertFalse(self.client._add_port_to_broadcast_domain.called)
 1289 
 1290     @ddt.data(fake.IPSPACE_NAME, client_cmode.DEFAULT_IPSPACE)
 1291     def test_ensure_broadcast_domain_for_port_other_domain(self, ipspace):
 1292 
 1293         port_info = {
 1294             'ipspace': ipspace,
 1295             'broadcast-domain': 'other_domain',
 1296         }
 1297         self.mock_object(self.client,
 1298                          '_get_broadcast_domain_for_port',
 1299                          mock.Mock(return_value=port_info))
 1300         self.mock_object(self.client,
 1301                          '_broadcast_domain_exists',
 1302                          mock.Mock(return_value=True))
 1303         self.mock_object(self.client, '_create_broadcast_domain')
 1304         self.mock_object(self.client, '_modify_broadcast_domain')
 1305         self.mock_object(self.client, '_remove_port_from_broadcast_domain')
 1306         self.mock_object(self.client, '_add_port_to_broadcast_domain')
 1307 
 1308         self.client._ensure_broadcast_domain_for_port(
 1309             fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU)
 1310 
 1311         self.client._get_broadcast_domain_for_port.assert_called_once_with(
 1312             fake.NODE_NAME, fake.PORT)
 1313         self.client._remove_port_from_broadcast_domain.assert_called_once_with(
 1314             fake.NODE_NAME, fake.PORT, 'other_domain', ipspace)
 1315         self.client._broadcast_domain_exists.assert_called_once_with(
 1316             fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)
 1317         self.assertFalse(self.client._create_broadcast_domain.called)
 1318         self.client._modify_broadcast_domain.assert_called_once_with(
 1319             fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
 1320         self.client._add_port_to_broadcast_domain.assert_called_once_with(
 1321             fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
 1322             fake.IPSPACE_NAME)
 1323 
 1324     def test_ensure_broadcast_domain_for_port_no_domain(self):
 1325 
 1326         port_info = {
 1327             'ipspace': fake.IPSPACE_NAME,
 1328             'broadcast-domain': None,
 1329         }
 1330         self.mock_object(self.client,
 1331                          '_get_broadcast_domain_for_port',
 1332                          mock.Mock(return_value=port_info))
 1333         self.mock_object(self.client,
 1334                          '_broadcast_domain_exists',
 1335                          mock.Mock(return_value=False))
 1336         self.mock_object(self.client, '_create_broadcast_domain')
 1337         self.mock_object(self.client, '_modify_broadcast_domain')
 1338         self.mock_object(self.client, '_remove_port_from_broadcast_domain')
 1339         self.mock_object(self.client, '_add_port_to_broadcast_domain')
 1340 
 1341         self.client._ensure_broadcast_domain_for_port(
 1342             fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU)
 1343 
 1344         self.client._get_broadcast_domain_for_port.assert_called_once_with(
 1345             fake.NODE_NAME, fake.PORT)
 1346         self.assertFalse(self.client._remove_port_from_broadcast_domain.called)
 1347         self.client._broadcast_domain_exists.assert_called_once_with(
 1348             fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)
 1349         self.client._create_broadcast_domain.assert_called_once_with(
 1350             fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
 1351         self.assertFalse(self.client._modify_broadcast_domain.called)
 1352         self.client._add_port_to_broadcast_domain.assert_called_once_with(
 1353             fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
 1354             fake.IPSPACE_NAME)
 1355 
 1356     def test_get_broadcast_domain_for_port(self):
 1357 
 1358         api_response = netapp_api.NaElement(
 1359             fake.NET_PORT_GET_ITER_BROADCAST_DOMAIN_RESPONSE)
 1360         self.mock_object(self.client,
 1361                          'send_iter_request',
 1362                          mock.Mock(return_value=api_response))
 1363 
 1364         net_port_get_iter_args = {
 1365             'query': {
 1366                 'net-port-info': {
 1367                     'node': fake.NODE_NAME,
 1368                     'port': fake.PORT,
 1369                 },
 1370             },
 1371             'desired-attributes': {
 1372                 'net-port-info': {
 1373                     'broadcast-domain': None,
 1374                     'ipspace': None,
 1375                 },
 1376             },
 1377         }
 1378         result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
 1379                                                             fake.PORT)
 1380 
 1381         expected = {
 1382             'broadcast-domain': fake.BROADCAST_DOMAIN,
 1383             'ipspace': fake.IPSPACE_NAME,
 1384         }
 1385         self.client.send_iter_request.assert_has_calls([
 1386             mock.call('net-port-get-iter', net_port_get_iter_args)])
 1387         self.assertEqual(expected, result)
 1388 
 1389     def test_get_broadcast_domain_for_port_port_not_found(self):
 1390 
 1391         api_response = netapp_api.NaElement(
 1392             fake.NO_RECORDS_RESPONSE)
 1393         self.mock_object(self.client,
 1394                          'send_iter_request',
 1395                          mock.Mock(return_value=api_response))
 1396 
 1397         self.assertRaises(exception.NetAppException,
 1398                           self.client._get_broadcast_domain_for_port,
 1399                           fake.NODE_NAME,
 1400                           fake.PORT)
 1401 
 1402     def test_get_broadcast_domain_for_port_domain_not_found(self):
 1403 
 1404         api_response = netapp_api.NaElement(
 1405             fake.NET_PORT_GET_ITER_BROADCAST_DOMAIN_MISSING_RESPONSE)
 1406         self.mock_object(self.client,
 1407                          'send_iter_request',
 1408                          mock.Mock(return_value=api_response))
 1409 
 1410         result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
 1411                                                             fake.PORT)
 1412 
 1413         expected = {
 1414             'broadcast-domain': None,
 1415             'ipspace': fake.IPSPACE_NAME,
 1416         }
 1417         self.assertEqual(expected, result)
 1418 
 1419     def test_broadcast_domain_exists(self):
 1420 
 1421         api_response = netapp_api.NaElement(
 1422             fake.NET_PORT_BROADCAST_DOMAIN_GET_ITER_RESPONSE)
 1423         self.mock_object(self.client,
 1424                          'send_iter_request',
 1425                          mock.Mock(return_value=api_response))
 1426 
 1427         result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
 1428                                                       fake.IPSPACE_NAME)
 1429 
 1430         net_port_broadcast_domain_get_iter_args = {
 1431             'query': {
 1432                 'net-port-broadcast-domain-info': {
 1433                     'ipspace': fake.IPSPACE_NAME,
 1434                     'broadcast-domain': fake.BROADCAST_DOMAIN,
 1435                 },
 1436             },
 1437             'desired-attributes': {
 1438                 'net-port-broadcast-domain-info': None,
 1439             },
 1440         }
 1441         self.client.send_iter_request.assert_has_calls([
 1442             mock.call('net-port-broadcast-domain-get-iter',
 1443                       net_port_broadcast_domain_get_iter_args)])
 1444         self.assertTrue(result)
 1445 
 1446     def test_broadcast_domain_exists_not_found(self):
 1447 
 1448         api_response = netapp_api.NaElement(
 1449             fake.NO_RECORDS_RESPONSE)
 1450         self.mock_object(self.client,
 1451                          'send_request',
 1452                          mock.Mock(return_value=api_response))
 1453 
 1454         result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
 1455                                                       fake.IPSPACE_NAME)
 1456 
 1457         self.assertFalse(result)
 1458 
 1459     def test_create_broadcast_domain(self):
 1460 
 1461         self.mock_object(self.client, 'send_request')
 1462 
 1463         result = self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN,
 1464                                                       fake.IPSPACE_NAME,
 1465                                                       fake.MTU)
 1466 
 1467         net_port_broadcast_domain_create_args = {
 1468             'ipspace': fake.IPSPACE_NAME,
 1469             'broadcast-domain': fake.BROADCAST_DOMAIN,
 1470             'mtu': fake.MTU,
 1471         }
 1472         self.assertIsNone(result)
 1473         self.client.send_request.assert_has_calls([
 1474             mock.call('net-port-broadcast-domain-create',
 1475                       net_port_broadcast_domain_create_args)])
 1476 
 1477     def test_modify_broadcast_domain(self):
 1478 
 1479         self.mock_object(self.client, 'send_request')
 1480 
 1481         result = self.client._modify_broadcast_domain(fake.BROADCAST_DOMAIN,
 1482                                                       fake.IPSPACE_NAME,
 1483                                                       fake.MTU)
 1484 
 1485         net_port_broadcast_domain_modify_args = {
 1486             'ipspace': fake.IPSPACE_NAME,
 1487             'broadcast-domain': fake.BROADCAST_DOMAIN,
 1488             'mtu': fake.MTU,
 1489         }
 1490         self.assertIsNone(result)
 1491         self.client.send_request.assert_called_once_with(
 1492             'net-port-broadcast-domain-modify',
 1493             net_port_broadcast_domain_modify_args)
 1494 
 1495     def test_delete_broadcast_domain(self):
 1496 
 1497         self.mock_object(self.client, 'send_request')
 1498 
 1499         result = self.client._delete_broadcast_domain(fake.BROADCAST_DOMAIN,
 1500                                                       fake.IPSPACE_NAME)
 1501 
 1502         net_port_broadcast_domain_delete_args = {
 1503             'ipspace': fake.IPSPACE_NAME,
 1504             'broadcast-domain': fake.BROADCAST_DOMAIN,
 1505         }
 1506         self.assertIsNone(result)
 1507         self.client.send_request.assert_has_calls([
 1508             mock.call('net-port-broadcast-domain-destroy',
 1509                       net_port_broadcast_domain_delete_args)])
 1510 
 1511     def test_delete_broadcast_domains_for_ipspace_not_found(self):
 1512 
 1513         self.mock_object(self.client,
 1514                          'get_ipspaces',
 1515                          mock.Mock(return_value=[]))
 1516         self.mock_object(self.client, '_delete_broadcast_domain')
 1517 
 1518         self.client._delete_broadcast_domains_for_ipspace(fake.IPSPACE_NAME)
 1519 
 1520         self.client.get_ipspaces.assert_called_once_with(
 1521             ipspace_name=fake.IPSPACE_NAME)
 1522         self.assertFalse(self.client._delete_broadcast_domain.called)
 1523 
 1524     def test_delete_broadcast_domains_for_ipspace(self):
 1525 
 1526         self.mock_object(self.client,
 1527                          'get_ipspaces',
 1528                          mock.Mock(return_value=fake.IPSPACES))
 1529         self.mock_object(self.client, '_delete_broadcast_domain')
 1530 
 1531         self.client._delete_broadcast_domains_for_ipspace(fake.IPSPACE_NAME)
 1532 
 1533         self.client.get_ipspaces.assert_called_once_with(
 1534             ipspace_name=fake.IPSPACE_NAME)
 1535         self.client._delete_broadcast_domain.assert_called_once_with(
 1536             fake.IPSPACES[0]['broadcast-domains'][0], fake.IPSPACE_NAME)
 1537 
 1538     def test_add_port_to_broadcast_domain(self):
 1539 
 1540         self.mock_object(self.client, 'send_request')
 1541 
 1542         add_port_to_broadcast_domain_args = {
 1543             'ipspace': fake.IPSPACE_NAME,
 1544             'broadcast-domain': fake.BROADCAST_DOMAIN,
 1545             'ports': {
 1546                 'net-qualified-port-name': ':'.join([fake.NODE_NAME,
 1547                                                      fake.VLAN_PORT])
 1548             }
 1549         }
 1550         result = self.client._add_port_to_broadcast_domain(
 1551             fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
 1552             fake.IPSPACE_NAME)
 1553 
 1554         self.assertIsNone(result)
 1555         self.client.send_request.assert_has_calls([
 1556             mock.call('net-port-broadcast-domain-add-ports',
 1557                       add_port_to_broadcast_domain_args)])
 1558 
 1559     def test_add_port_to_broadcast_domain_already_present(self):
 1560 
 1561         self.mock_object(self.client, 'send_request', self._mock_api_error(
 1562             code=netapp_api.
 1563             E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN))
 1564 
 1565         result = self.client._add_port_to_broadcast_domain(
 1566             fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
 1567             fake.IPSPACE_NAME)
 1568 
 1569         self.assertIsNone(result)
 1570 
 1571     def test_add_port_to_broadcast_domain_api_error(self):
 1572 
 1573         self.mock_object(self.client, 'send_request', self._mock_api_error())
 1574 
 1575         self.assertRaises(exception.NetAppException,
 1576                           self.client._add_port_to_broadcast_domain,
 1577                           fake.NODE_NAME,
 1578                           fake.VLAN_PORT,
 1579                           fake.BROADCAST_DOMAIN,
 1580                           fake.IPSPACE_NAME)
 1581 
 1582     def test_remove_port_from_broadcast_domain(self):
 1583 
 1584         self.mock_object(self.client, 'send_request')
 1585 
 1586         result = self.client._remove_port_from_broadcast_domain(
 1587             fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
 1588             fake.IPSPACE_NAME)
 1589 
 1590         net_port_broadcast_domain_remove_ports_args = {
 1591             'ipspace': fake.IPSPACE_NAME,
 1592             'broadcast-domain': fake.BROADCAST_DOMAIN,
 1593             'ports': {
 1594                 'net-qualified-port-name': ':'.join([fake.NODE_NAME,
 1595                                                      fake.VLAN_PORT])
 1596             }
 1597         }
 1598         self.assertIsNone(result)
 1599         self.client.send_request.assert_has_calls([
 1600             mock.call('net-port-broadcast-domain-remove-ports',
 1601                       net_port_broadcast_domain_remove_ports_args)])
 1602 
 1603     def test_network_interface_exists(self):
 1604 
 1605         api_response = netapp_api.NaElement(
 1606             fake.NET_INTERFACE_GET_ONE_RESPONSE)
 1607         self.mock_object(self.client,
 1608                          'send_iter_request',
 1609                          mock.Mock(return_value=api_response))
 1610 
 1611         net_interface_get_args = {
 1612             'query': {
 1613                 'net-interface-info': {
 1614                     'address': fake.IP_ADDRESS,
 1615                     'home-node': fake.NODE_NAME,
 1616                     'home-port': fake.VLAN_PORT,
 1617                     'netmask': fake.NETMASK,
 1618                     'vserver': fake.VSERVER_NAME}
 1619             },
 1620             'desired-attributes': {
 1621                 'net-interface-info': {
 1622                     'interface-name': None,
 1623                 }
 1624             }
 1625         }
 1626         result = self.client.network_interface_exists(
 1627             fake.VSERVER_NAME, fake.NODE_NAME, fake.PORT, fake.IP_ADDRESS,
 1628             fake.NETMASK, fake.VLAN)
 1629 
 1630         self.client.send_iter_request.assert_has_calls([
 1631             mock.call('net-interface-get-iter', net_interface_get_args)])
 1632         self.assertTrue(result)
 1633 
 1634     def test_network_interface_exists_not_found(self):
 1635 
 1636         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 1637         self.mock_object(self.client,
 1638                          'send_iter_request',
 1639                          mock.Mock(return_value=api_response))
 1640 
 1641         net_interface_get_args = {
 1642             'query': {
 1643                 'net-interface-info': {
 1644                     'address': fake.IP_ADDRESS,
 1645                     'home-node': fake.NODE_NAME,
 1646                     'home-port': fake.PORT,
 1647                     'netmask': fake.NETMASK,
 1648                     'vserver': fake.VSERVER_NAME}
 1649             },
 1650             'desired-attributes': {
 1651                 'net-interface-info': {
 1652                     'interface-name': None,
 1653                 }
 1654             }
 1655         }
 1656         result = self.client.network_interface_exists(
 1657             fake.VSERVER_NAME, fake.NODE_NAME, fake.PORT, fake.IP_ADDRESS,
 1658             fake.NETMASK, None)
 1659         self.client.send_iter_request.assert_has_calls([
 1660             mock.call('net-interface-get-iter', net_interface_get_args)])
 1661         self.assertFalse(result)
 1662 
 1663     def test_list_network_interfaces(self):
 1664 
 1665         api_response = netapp_api.NaElement(
 1666             fake.NET_INTERFACE_GET_ITER_RESPONSE)
 1667         self.mock_object(self.client,
 1668                          'send_iter_request',
 1669                          mock.Mock(return_value=api_response))
 1670 
 1671         net_interface_get_args = {
 1672             'desired-attributes': {
 1673                 'net-interface-info': {
 1674                     'interface-name': None,
 1675                 }
 1676             }
 1677         }
 1678 
 1679         result = self.client.list_network_interfaces()
 1680 
 1681         self.client.send_iter_request.assert_has_calls([
 1682             mock.call('net-interface-get-iter', net_interface_get_args)])
 1683         self.assertSequenceEqual(fake.LIF_NAMES, result)
 1684 
 1685     def test_list_network_interfaces_not_found(self):
 1686 
 1687         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 1688         self.mock_object(self.client,
 1689                          'send_request',
 1690                          mock.Mock(return_value=api_response))
 1691 
 1692         result = self.client.list_network_interfaces()
 1693 
 1694         self.assertListEqual([], result)
 1695 
 1696     def test_get_network_interfaces(self):
 1697 
 1698         api_response = netapp_api.NaElement(
 1699             fake.NET_INTERFACE_GET_ITER_RESPONSE)
 1700         self.mock_object(self.client,
 1701                          'send_iter_request',
 1702                          mock.Mock(return_value=api_response))
 1703 
 1704         result = self.client.get_network_interfaces()
 1705 
 1706         self.client.send_iter_request.assert_has_calls([
 1707             mock.call('net-interface-get-iter', None)])
 1708         self.assertSequenceEqual(fake.LIFS, result)
 1709 
 1710     def test_get_network_interfaces_filtered_by_protocol(self):
 1711 
 1712         api_response = netapp_api.NaElement(
 1713             fake.NET_INTERFACE_GET_ITER_RESPONSE_NFS)
 1714         self.mock_object(self.client,
 1715                          'send_iter_request',
 1716                          mock.Mock(return_value=api_response))
 1717 
 1718         result = self.client.get_network_interfaces(protocols=['NFS'])
 1719 
 1720         net_interface_get_args = {
 1721             'query': {
 1722                 'net-interface-info': {
 1723                     'data-protocols': {
 1724                         'data-protocol': 'nfs',
 1725                     }
 1726                 }
 1727             }
 1728         }
 1729 
 1730         self.client.send_iter_request.assert_has_calls([
 1731             mock.call('net-interface-get-iter', net_interface_get_args)])
 1732         self.assertListEqual(fake.NFS_LIFS, result)
 1733 
 1734     def test_get_network_interfaces_not_found(self):
 1735 
 1736         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 1737         self.mock_object(self.client,
 1738                          'send_iter_request',
 1739                          mock.Mock(return_value=api_response))
 1740 
 1741         result = self.client.get_network_interfaces()
 1742 
 1743         self.client.send_iter_request.assert_has_calls([
 1744             mock.call('net-interface-get-iter', None)])
 1745         self.assertListEqual([], result)
 1746 
 1747     def test_get_ipspaces(self):
 1748 
 1749         self.client.features.add_feature('IPSPACES')
 1750         api_response = netapp_api.NaElement(
 1751             fake.NET_IPSPACES_GET_ITER_RESPONSE)
 1752         self.mock_object(self.client,
 1753                          'send_iter_request',
 1754                          mock.Mock(return_value=api_response))
 1755 
 1756         result = self.client.get_ipspaces(ipspace_name=fake.IPSPACE_NAME)
 1757 
 1758         net_ipspaces_get_iter_args = {
 1759             'query': {
 1760                 'net-ipspaces-info': {
 1761                     'ipspace': fake.IPSPACE_NAME,
 1762                 },
 1763             },
 1764         }
 1765         self.client.send_iter_request.assert_has_calls([
 1766             mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
 1767         self.assertEqual(fake.IPSPACES, result)
 1768 
 1769     def test_get_ipspaces_not_found(self):
 1770 
 1771         self.client.features.add_feature('IPSPACES')
 1772         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 1773         self.mock_object(self.client,
 1774                          'send_iter_request',
 1775                          mock.Mock(return_value=api_response))
 1776 
 1777         result = self.client.get_ipspaces()
 1778 
 1779         net_ipspaces_get_iter_args = {}
 1780         self.client.send_iter_request.assert_has_calls([
 1781             mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
 1782         self.assertEqual([], result)
 1783 
 1784     def test_get_ipspaces_not_supported(self):
 1785 
 1786         self.mock_object(self.client, 'send_iter_request')
 1787 
 1788         result = self.client.get_ipspaces()
 1789 
 1790         self.assertFalse(self.client.send_iter_request.called)
 1791         self.assertEqual([], result)
 1792 
 1793     @ddt.data((fake.NET_IPSPACES_GET_ITER_RESPONSE, True),
 1794               (fake.NO_RECORDS_RESPONSE, False))
 1795     @ddt.unpack
 1796     def test_ipspace_exists(self, api_response, expected):
 1797 
 1798         self.client.features.add_feature('IPSPACES')
 1799         api_response = netapp_api.NaElement(api_response)
 1800         self.mock_object(self.client,
 1801                          'send_iter_request',
 1802                          mock.Mock(return_value=api_response))
 1803 
 1804         result = self.client.ipspace_exists(fake.IPSPACE_NAME)
 1805 
 1806         net_ipspaces_get_iter_args = {
 1807             'query': {
 1808                 'net-ipspaces-info': {
 1809                     'ipspace': fake.IPSPACE_NAME,
 1810                 },
 1811             },
 1812             'desired-attributes': {
 1813                 'net-ipspaces-info': {
 1814                     'ipspace': None,
 1815                 },
 1816             },
 1817         }
 1818         self.client.send_iter_request.assert_has_calls([
 1819             mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
 1820         self.assertEqual(expected, result)
 1821 
 1822     def test_ipspace_exists_not_supported(self):
 1823 
 1824         result = self.client.ipspace_exists(fake.IPSPACE_NAME)
 1825 
 1826         self.assertFalse(result)
 1827 
 1828     def test_create_ipspace(self):
 1829 
 1830         self.mock_object(self.client, 'send_request')
 1831 
 1832         self.client.create_ipspace(fake.IPSPACE_NAME)
 1833 
 1834         net_ipspaces_create_args = {'ipspace': fake.IPSPACE_NAME}
 1835         self.client.send_request.assert_has_calls([
 1836             mock.call('net-ipspaces-create', net_ipspaces_create_args)])
 1837 
 1838     def test_delete_ipspace(self):
 1839 
 1840         mock_delete_broadcast_domains_for_ipspace = self.mock_object(
 1841             self.client, '_delete_broadcast_domains_for_ipspace')
 1842         self.mock_object(self.client, 'send_request')
 1843 
 1844         self.client.delete_ipspace(fake.IPSPACE_NAME)
 1845 
 1846         net_ipspaces_destroy_args = {'ipspace': fake.IPSPACE_NAME}
 1847         mock_delete_broadcast_domains_for_ipspace.assert_called_once_with(
 1848             fake.IPSPACE_NAME)
 1849         self.client.send_request.assert_has_calls([
 1850             mock.call('net-ipspaces-destroy', net_ipspaces_destroy_args)])
 1851 
 1852     def test_get_ipspace_name_for_vlan_port(self):
 1853         self.client.features.add_feature('IPSPACES')
 1854         api_response = netapp_api.NaElement(fake.NET_PORT_GET_RESPONSE)
 1855         self.mock_object(self.client,
 1856                          'send_request',
 1857                          mock.Mock(return_value=api_response))
 1858 
 1859         ipspace = self.client.get_ipspace_name_for_vlan_port(
 1860             fake.NODE_NAME, fake.PORT, fake.VLAN)
 1861 
 1862         port = '%(port)s-%(id)s' % {'port': fake.PORT, 'id': fake.VLAN}
 1863         self.client.send_request.assert_called_once_with(
 1864             'net-port-get',
 1865             {'node': fake.NODE_NAME, 'port': port})
 1866         self.assertEqual(fake.IPSPACE_NAME, ipspace)
 1867 
 1868     def test_get_ipspace_name_for_vlan_port_no_ipspace_feature(self):
 1869         self.mock_object(self.client, 'send_request')
 1870 
 1871         ipspace = self.client.get_ipspace_name_for_vlan_port(
 1872             fake.NODE_NAME, fake.PORT, fake.VLAN)
 1873 
 1874         self.client.send_request.assert_not_called()
 1875         self.assertIsNone(ipspace)
 1876 
 1877     def test_get_ipspace_name_for_vlan_port_no_ipspace_found(self):
 1878         self.client.features.add_feature('IPSPACES')
 1879         self.mock_object(
 1880             self.client,
 1881             'send_request',
 1882             self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND))
 1883 
 1884         ipspace = self.client.get_ipspace_name_for_vlan_port(
 1885             fake.NODE_NAME, fake.PORT, fake.VLAN)
 1886 
 1887         self.assertIsNone(ipspace)
 1888 
 1889     def test_get_ipspace_name_for_vlan_port_no_vlan(self):
 1890         self.client.features.add_feature('IPSPACES')
 1891         api_response = netapp_api.NaElement(fake.NET_PORT_GET_RESPONSE_NO_VLAN)
 1892         self.mock_object(self.client,
 1893                          'send_request',
 1894                          mock.Mock(return_value=api_response))
 1895 
 1896         ipspace = self.client.get_ipspace_name_for_vlan_port(
 1897             fake.NODE_NAME, fake.PORT, None)
 1898 
 1899         self.client.send_request.assert_called_once_with(
 1900             'net-port-get',
 1901             {'node': fake.NODE_NAME, 'port': fake.PORT})
 1902         self.assertEqual(fake.IPSPACE_NAME, ipspace)
 1903 
 1904     def test_get_ipspace_name_for_vlan_port_raises_api_error(self):
 1905         self.client.features.add_feature('IPSPACES')
 1906         self.mock_object(self.client,
 1907                          'send_request',
 1908                          mock.Mock(side_effect=self._mock_api_error()))
 1909 
 1910         self.assertRaises(netapp_api.NaApiError,
 1911                           self.client.get_ipspace_name_for_vlan_port,
 1912                           fake.NODE_NAME, fake.VLAN_PORT, None)
 1913 
 1914     def test_add_vserver_to_ipspace(self):
 1915 
 1916         self.mock_object(self.client, 'send_request')
 1917 
 1918         self.client.add_vserver_to_ipspace(fake.IPSPACE_NAME,
 1919                                            fake.VSERVER_NAME)
 1920 
 1921         net_ipspaces_assign_vserver_args = {
 1922             'ipspace': fake.IPSPACE_NAME,
 1923             'vserver': fake.VSERVER_NAME
 1924         }
 1925         self.client.send_request.assert_has_calls([
 1926             mock.call('net-ipspaces-assign-vserver',
 1927                       net_ipspaces_assign_vserver_args)])
 1928 
 1929     def test_get_node_for_aggregate(self):
 1930 
 1931         api_response = netapp_api.NaElement(
 1932             fake.AGGR_GET_NODE_RESPONSE).get_child_by_name(
 1933             'attributes-list').get_children()
 1934         self.mock_object(self.client,
 1935                          '_get_aggregates',
 1936                          mock.Mock(return_value=api_response))
 1937 
 1938         result = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME)
 1939 
 1940         desired_attributes = {
 1941             'aggr-attributes': {
 1942                 'aggregate-name': None,
 1943                 'aggr-ownership-attributes': {
 1944                     'home-name': None,
 1945                 },
 1946             },
 1947         }
 1948 
 1949         self.client._get_aggregates.assert_has_calls([
 1950             mock.call(
 1951                 aggregate_names=[fake.SHARE_AGGREGATE_NAME],
 1952                 desired_attributes=desired_attributes)])
 1953 
 1954         self.assertEqual(fake.NODE_NAME, result)
 1955 
 1956     def test_get_node_for_aggregate_none_requested(self):
 1957 
 1958         result = self.client.get_node_for_aggregate(None)
 1959 
 1960         self.assertIsNone(result)
 1961 
 1962     def test_get_node_for_aggregate_api_not_found(self):
 1963 
 1964         self.mock_object(self.client,
 1965                          'send_iter_request',
 1966                          mock.Mock(side_effect=self._mock_api_error(
 1967                              netapp_api.EAPINOTFOUND)))
 1968 
 1969         result = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME)
 1970 
 1971         self.assertIsNone(result)
 1972 
 1973     def test_get_node_for_aggregate_api_error(self):
 1974 
 1975         self.mock_object(self.client,
 1976                          'send_iter_request',
 1977                          self._mock_api_error())
 1978 
 1979         self.assertRaises(netapp_api.NaApiError,
 1980                           self.client.get_node_for_aggregate,
 1981                           fake.SHARE_AGGREGATE_NAME)
 1982 
 1983     def test_get_node_for_aggregate_not_found(self):
 1984 
 1985         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 1986         self.mock_object(self.client,
 1987                          'send_iter_request',
 1988                          mock.Mock(return_value=api_response))
 1989 
 1990         result = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME)
 1991 
 1992         self.assertIsNone(result)
 1993 
 1994     def test_get_cluster_aggregate_capacities(self):
 1995 
 1996         api_response = netapp_api.NaElement(
 1997             fake.AGGR_GET_SPACE_RESPONSE).get_child_by_name(
 1998             'attributes-list').get_children()
 1999         self.mock_object(self.client,
 2000                          '_get_aggregates',
 2001                          mock.Mock(return_value=api_response))
 2002 
 2003         result = self.client.get_cluster_aggregate_capacities(
 2004             fake.SHARE_AGGREGATE_NAMES)
 2005 
 2006         desired_attributes = {
 2007             'aggr-attributes': {
 2008                 'aggregate-name': None,
 2009                 'aggr-space-attributes': {
 2010                     'size-available': None,
 2011                     'size-total': None,
 2012                     'size-used': None,
 2013                 }
 2014             }
 2015         }
 2016 
 2017         self.client._get_aggregates.assert_has_calls([
 2018             mock.call(
 2019                 aggregate_names=fake.SHARE_AGGREGATE_NAMES,
 2020                 desired_attributes=desired_attributes)])
 2021 
 2022         expected = {
 2023             fake.SHARE_AGGREGATE_NAMES[0]: {
 2024                 'available': 45670400,
 2025                 'total': 943718400,
 2026                 'used': 898048000,
 2027             },
 2028             fake.SHARE_AGGREGATE_NAMES[1]: {
 2029                 'available': 4267659264,
 2030                 'total': 7549747200,
 2031                 'used': 3282087936,
 2032             },
 2033         }
 2034         self.assertDictEqual(expected, result)
 2035 
 2036     def test_get_cluster_aggregate_capacities_not_found(self):
 2037 
 2038         api_response = netapp_api.NaElement('none').get_children()
 2039         self.mock_object(self.client,
 2040                          '_get_aggregates',
 2041                          mock.Mock(return_value=api_response))
 2042 
 2043         result = self.client.get_cluster_aggregate_capacities(
 2044             fake.SHARE_AGGREGATE_NAMES)
 2045 
 2046         self.assertEqual({}, result)
 2047 
 2048     def test_get_cluster_aggregate_capacities_none_requested(self):
 2049 
 2050         result = self.client.get_cluster_aggregate_capacities([])
 2051 
 2052         self.assertEqual({}, result)
 2053 
 2054     def test_get_vserver_aggregate_capacities(self):
 2055 
 2056         api_response = netapp_api.NaElement(fake.VSERVER_GET_RESPONSE)
 2057         self.mock_object(self.vserver_client,
 2058                          'send_request',
 2059                          mock.Mock(return_value=api_response))
 2060 
 2061         result = self.vserver_client.get_vserver_aggregate_capacities()
 2062 
 2063         vserver_args = {
 2064             'desired-attributes': {
 2065                 'vserver-info': {
 2066                     'vserver-name': None,
 2067                     'vserver-aggr-info-list': {
 2068                         'vserver-aggr-info': {
 2069                             'aggr-name': None,
 2070                             'aggr-availsize': None
 2071                         }
 2072                     }
 2073                 }
 2074             }
 2075         }
 2076 
 2077         self.vserver_client.send_request.assert_has_calls([
 2078             mock.call('vserver-get', vserver_args)])
 2079         self.assertDictEqual(fake.VSERVER_AGGREGATES, result)
 2080 
 2081     def test_get_vserver_aggregate_capacities_partial_request(self):
 2082 
 2083         api_response = netapp_api.NaElement(fake.VSERVER_GET_RESPONSE)
 2084         self.mock_object(self.vserver_client,
 2085                          'send_request',
 2086                          mock.Mock(return_value=api_response))
 2087 
 2088         result = self.vserver_client.get_vserver_aggregate_capacities(
 2089             fake.SHARE_AGGREGATE_NAMES[0])
 2090 
 2091         expected = {fake.SHARE_AGGREGATE_NAMES[0]:
 2092                     fake.VSERVER_AGGREGATES[fake.SHARE_AGGREGATE_NAMES[0]]}
 2093         self.assertDictEqual(expected, result)
 2094 
 2095     def test_get_vserver_aggregate_capacities_aggregate_not_found(self):
 2096 
 2097         api_response = netapp_api.NaElement(
 2098             fake.VSERVER_GET_RESPONSE_NO_AGGREGATES)
 2099         self.mock_object(self.vserver_client,
 2100                          'send_request',
 2101                          mock.Mock(return_value=api_response))
 2102 
 2103         result = self.vserver_client.get_vserver_aggregate_capacities()
 2104 
 2105         self.assertDictEqual({}, result)
 2106         self.assertEqual(1, client_cmode.LOG.warning.call_count)
 2107 
 2108     def test_get_vserver_aggregate_capacities_vserver_not_found(self):
 2109 
 2110         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 2111         self.mock_object(self.vserver_client,
 2112                          'send_request',
 2113                          mock.Mock(return_value=api_response))
 2114 
 2115         self.assertRaises(exception.NetAppException,
 2116                           self.vserver_client.get_vserver_aggregate_capacities)
 2117 
 2118     def test_get_vserver_aggregate_capacities_none_requested(self):
 2119 
 2120         result = self.client.get_vserver_aggregate_capacities([])
 2121 
 2122         self.assertEqual({}, result)
 2123 
 2124     def test_get_aggregates(self):
 2125 
 2126         api_response = netapp_api.NaElement(fake.AGGR_GET_ITER_RESPONSE)
 2127         self.mock_object(self.client,
 2128                          'send_iter_request',
 2129                          mock.Mock(return_value=api_response))
 2130 
 2131         result = self.client._get_aggregates()
 2132 
 2133         self.client.send_iter_request.assert_has_calls([
 2134             mock.call('aggr-get-iter', {})])
 2135         self.assertListEqual(
 2136             [aggr.to_string() for aggr in api_response.get_child_by_name(
 2137                 'attributes-list').get_children()],
 2138             [aggr.to_string() for aggr in result])
 2139 
 2140     def test_get_aggregates_with_filters(self):
 2141 
 2142         api_response = netapp_api.NaElement(fake.AGGR_GET_SPACE_RESPONSE)
 2143         self.mock_object(self.client,
 2144                          'send_iter_request',
 2145                          mock.Mock(return_value=api_response))
 2146 
 2147         desired_attributes = {
 2148             'aggr-attributes': {
 2149                 'aggregate-name': None,
 2150                 'aggr-space-attributes': {
 2151                     'size-total': None,
 2152                     'size-available': None,
 2153                 }
 2154             }
 2155         }
 2156 
 2157         result = self.client._get_aggregates(
 2158             aggregate_names=fake.SHARE_AGGREGATE_NAMES,
 2159             desired_attributes=desired_attributes)
 2160 
 2161         aggr_get_iter_args = {
 2162             'query': {
 2163                 'aggr-attributes': {
 2164                     'aggregate-name': '|'.join(fake.SHARE_AGGREGATE_NAMES),
 2165                 }
 2166             },
 2167             'desired-attributes': desired_attributes
 2168         }
 2169 
 2170         self.client.send_iter_request.assert_has_calls([
 2171             mock.call('aggr-get-iter', aggr_get_iter_args)])
 2172         self.assertListEqual(
 2173             [aggr.to_string() for aggr in api_response.get_child_by_name(
 2174                 'attributes-list').get_children()],
 2175             [aggr.to_string() for aggr in result])
 2176 
 2177     def test_get_aggregates_not_found(self):
 2178 
 2179         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 2180         self.mock_object(self.client,
 2181                          'send_iter_request',
 2182                          mock.Mock(return_value=api_response))
 2183 
 2184         result = self.client._get_aggregates()
 2185 
 2186         self.client.send_iter_request.assert_has_calls([
 2187             mock.call('aggr-get-iter', {})])
 2188         self.assertListEqual([], result)
 2189 
 2190     def test_get_performance_instance_uuids(self):
 2191 
 2192         api_response = netapp_api.NaElement(
 2193             fake.PERF_OBJECT_INSTANCE_LIST_INFO_ITER_RESPONSE)
 2194         self.mock_object(self.client,
 2195                          'send_request',
 2196                          mock.Mock(return_value=api_response))
 2197 
 2198         result = self.client.get_performance_instance_uuids(
 2199             'system', fake.NODE_NAME)
 2200 
 2201         expected = [fake.NODE_NAME + ':kernel:system']
 2202         self.assertEqual(expected, result)
 2203 
 2204         perf_object_instance_list_info_iter_args = {
 2205             'objectname': 'system',
 2206             'query': {
 2207                 'instance-info': {
 2208                     'uuid': fake.NODE_NAME + ':*',
 2209                 }
 2210             }
 2211         }
 2212         self.client.send_request.assert_called_once_with(
 2213             'perf-object-instance-list-info-iter',
 2214             perf_object_instance_list_info_iter_args)
 2215 
 2216     def test_get_performance_counter_info(self):
 2217 
 2218         api_response = netapp_api.NaElement(
 2219             fake.PERF_OBJECT_COUNTER_LIST_INFO_WAFL_RESPONSE)
 2220         self.mock_object(self.client,
 2221                          'send_request',
 2222                          mock.Mock(return_value=api_response))
 2223 
 2224         result = self.client.get_performance_counter_info('wafl',
 2225                                                           'cp_phase_times')
 2226 
 2227         expected = {
 2228             'name': 'cp_phase_times',
 2229             'base-counter': 'total_cp_msecs',
 2230             'labels': fake.PERF_OBJECT_COUNTER_TOTAL_CP_MSECS_LABELS,
 2231         }
 2232         self.assertEqual(expected, result)
 2233 
 2234         perf_object_counter_list_info_args = {'objectname': 'wafl'}
 2235         self.client.send_request.assert_called_once_with(
 2236             'perf-object-counter-list-info',
 2237             perf_object_counter_list_info_args)
 2238 
 2239     def test_get_performance_counter_info_not_found(self):
 2240 
 2241         api_response = netapp_api.NaElement(
 2242             fake.PERF_OBJECT_COUNTER_LIST_INFO_WAFL_RESPONSE)
 2243         self.mock_object(self.client,
 2244                          'send_request',
 2245                          mock.Mock(return_value=api_response))
 2246 
 2247         self.assertRaises(exception.NotFound,
 2248                           self.client.get_performance_counter_info,
 2249                           'wafl',
 2250                           'invalid')
 2251 
 2252     def test_get_performance_counters(self):
 2253 
 2254         api_response = netapp_api.NaElement(
 2255             fake.PERF_OBJECT_GET_INSTANCES_SYSTEM_RESPONSE_CMODE)
 2256         self.mock_object(self.client,
 2257                          'send_request',
 2258                          mock.Mock(return_value=api_response))
 2259 
 2260         instance_uuids = [
 2261             fake.NODE_NAMES[0] + ':kernel:system',
 2262             fake.NODE_NAMES[1] + ':kernel:system',
 2263         ]
 2264         counter_names = ['avg_processor_busy']
 2265         result = self.client.get_performance_counters('system',
 2266                                                       instance_uuids,
 2267                                                       counter_names)
 2268 
 2269         expected = [
 2270             {
 2271                 'avg_processor_busy': '5674745133134',
 2272                 'instance-name': 'system',
 2273                 'instance-uuid': instance_uuids[0],
 2274                 'node-name': fake.NODE_NAMES[0],
 2275                 'timestamp': '1453412013',
 2276             }, {
 2277                 'avg_processor_busy': '4077649009234',
 2278                 'instance-name': 'system',
 2279                 'instance-uuid': instance_uuids[1],
 2280                 'node-name': fake.NODE_NAMES[1],
 2281                 'timestamp': '1453412013'
 2282             },
 2283         ]
 2284         self.assertEqual(expected, result)
 2285 
 2286         perf_object_get_instances_args = {
 2287             'objectname': 'system',
 2288             'instance-uuids': [
 2289                 {'instance-uuid': instance_uuid}
 2290                 for instance_uuid in instance_uuids
 2291             ],
 2292             'counters': [
 2293                 {'counter': counter} for counter in counter_names
 2294             ],
 2295         }
 2296         self.client.send_request.assert_called_once_with(
 2297             'perf-object-get-instances', perf_object_get_instances_args)
 2298 
 2299     def test_setup_security_services_ldap(self):
 2300 
 2301         self.mock_object(self.client, 'send_request')
 2302         self.mock_object(self.vserver_client, 'configure_ldap')
 2303 
 2304         self.client.setup_security_services([fake.LDAP_SECURITY_SERVICE],
 2305                                             self.vserver_client,
 2306                                             fake.VSERVER_NAME)
 2307 
 2308         vserver_modify_args = {
 2309             'name-mapping-switch': [
 2310                 {'nmswitch': 'ldap'},
 2311                 {'nmswitch': 'file'},
 2312             ],
 2313             'name-server-switch': [
 2314                 {'nsswitch': 'ldap'},
 2315                 {'nsswitch': 'file'},
 2316             ],
 2317             'vserver-name': fake.VSERVER_NAME
 2318         }
 2319         self.client.send_request.assert_has_calls([
 2320             mock.call('vserver-modify', vserver_modify_args)])
 2321         self.vserver_client.configure_ldap.assert_has_calls([
 2322             mock.call(fake.LDAP_SECURITY_SERVICE)])
 2323 
 2324     def test_setup_security_services_active_directory(self):
 2325 
 2326         self.mock_object(self.client, 'send_request')
 2327         self.mock_object(self.vserver_client, 'configure_active_directory')
 2328 
 2329         self.client.setup_security_services([fake.CIFS_SECURITY_SERVICE],
 2330                                             self.vserver_client,
 2331                                             fake.VSERVER_NAME)
 2332 
 2333         vserver_modify_args = {
 2334             'name-mapping-switch': [
 2335                 {'nmswitch': 'ldap'},
 2336                 {'nmswitch': 'file'},
 2337             ],
 2338             'name-server-switch': [
 2339                 {'nsswitch': 'ldap'},
 2340                 {'nsswitch': 'file'},
 2341             ],
 2342             'vserver-name': fake.VSERVER_NAME
 2343         }
 2344         self.client.send_request.assert_has_calls([
 2345             mock.call('vserver-modify', vserver_modify_args)])
 2346         self.vserver_client.configure_active_directory.assert_has_calls([
 2347             mock.call(fake.CIFS_SECURITY_SERVICE, fake.VSERVER_NAME)])
 2348 
 2349     def test_setup_security_services_kerberos(self):
 2350 
 2351         self.mock_object(self.client, 'send_request')
 2352         self.mock_object(self.client, 'create_kerberos_realm')
 2353         self.mock_object(self.vserver_client, 'configure_kerberos')
 2354 
 2355         self.client.setup_security_services([fake.KERBEROS_SECURITY_SERVICE],
 2356                                             self.vserver_client,
 2357                                             fake.VSERVER_NAME)
 2358 
 2359         vserver_modify_args = {
 2360             'name-mapping-switch': [
 2361                 {'nmswitch': 'ldap'},
 2362                 {'nmswitch': 'file'},
 2363             ],
 2364             'name-server-switch': [
 2365                 {'nsswitch': 'ldap'},
 2366                 {'nsswitch': 'file'},
 2367             ],
 2368             'vserver-name': fake.VSERVER_NAME
 2369         }
 2370         self.client.send_request.assert_has_calls([
 2371             mock.call('vserver-modify', vserver_modify_args)])
 2372         self.client.create_kerberos_realm.assert_has_calls([
 2373             mock.call(fake.KERBEROS_SECURITY_SERVICE)])
 2374         self.vserver_client.configure_kerberos.assert_has_calls([
 2375             mock.call(fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME)])
 2376 
 2377     def test_setup_security_services_invalid(self):
 2378 
 2379         self.mock_object(self.client, 'send_request')
 2380 
 2381         self.assertRaises(exception.NetAppException,
 2382                           self.client.setup_security_services,
 2383                           [fake.INVALID_SECURITY_SERVICE],
 2384                           self.vserver_client,
 2385                           fake.VSERVER_NAME)
 2386 
 2387         vserver_modify_args = {
 2388             'name-mapping-switch': [
 2389                 {'nmswitch': 'ldap'},
 2390                 {'nmswitch': 'file'},
 2391             ],
 2392             'name-server-switch': [
 2393                 {'nsswitch': 'ldap'},
 2394                 {'nsswitch': 'file'},
 2395             ],
 2396             'vserver-name': fake.VSERVER_NAME
 2397         }
 2398         self.client.send_request.assert_has_calls([
 2399             mock.call('vserver-modify', vserver_modify_args)])
 2400 
 2401     def test_enable_nfs(self):
 2402 
 2403         self.mock_object(self.client, 'send_request')
 2404         self.mock_object(self.client, '_enable_nfs_protocols')
 2405         self.mock_object(self.client, '_create_default_nfs_export_rules')
 2406 
 2407         self.client.enable_nfs(fake.NFS_VERSIONS)
 2408 
 2409         self.client.send_request.assert_called_once_with('nfs-enable')
 2410         self.client._enable_nfs_protocols.assert_called_once_with(
 2411             fake.NFS_VERSIONS)
 2412         self.client._create_default_nfs_export_rules.assert_called_once_with()
 2413 
 2414     @ddt.data((True, True, True), (True, False, False), (False, True, True))
 2415     @ddt.unpack
 2416     def test_enable_nfs_protocols(self, v3, v40, v41):
 2417 
 2418         self.mock_object(self.client, 'send_request')
 2419 
 2420         versions = []
 2421         if v3:
 2422             versions.append('nfs3')
 2423         if v40:
 2424             versions.append('nfs4.0')
 2425         if v41:
 2426             versions.append('nfs4.1')
 2427 
 2428         self.client._enable_nfs_protocols(versions)
 2429 
 2430         nfs_service_modify_args = {
 2431             'is-nfsv3-enabled': 'true' if v3 else 'false',
 2432             'is-nfsv40-enabled': 'true' if v40 else 'false',
 2433             'is-nfsv41-enabled': 'true' if v41 else 'false',
 2434         }
 2435         self.client.send_request.assert_called_once_with(
 2436             'nfs-service-modify', nfs_service_modify_args)
 2437 
 2438     def test_create_default_nfs_export_rules(self):
 2439 
 2440         class CopyingMock(mock.Mock):
 2441             def __call__(self, *args, **kwargs):
 2442                 args = copy.deepcopy(args)
 2443                 kwargs = copy.deepcopy(kwargs)
 2444                 return super(CopyingMock, self).__call__(*args, **kwargs)
 2445 
 2446         self.mock_object(self.client, 'send_request', CopyingMock())
 2447 
 2448         self.client._create_default_nfs_export_rules()
 2449 
 2450         export_rule_create_args = {
 2451             'client-match': '0.0.0.0/0',
 2452             'policy-name': 'default',
 2453             'ro-rule': {
 2454                 'security-flavor': 'any'
 2455             },
 2456             'rw-rule': {
 2457                 'security-flavor': 'never'
 2458             }
 2459         }
 2460         export_rule_create_args2 = export_rule_create_args.copy()
 2461         export_rule_create_args2['client-match'] = '::/0'
 2462         self.client.send_request.assert_has_calls([
 2463             mock.call('export-rule-create', export_rule_create_args),
 2464             mock.call('export-rule-create', export_rule_create_args2)])
 2465 
 2466     def test_configure_ldap(self):
 2467 
 2468         self.mock_object(self.client, 'send_request')
 2469 
 2470         self.client.configure_ldap(fake.LDAP_SECURITY_SERVICE)
 2471 
 2472         config_name = hashlib.md5(
 2473             six.b(fake.LDAP_SECURITY_SERVICE['id'])).hexdigest()
 2474 
 2475         ldap_client_create_args = {
 2476             'ldap-client-config': config_name,
 2477             'servers': {'ip-address': fake.LDAP_SECURITY_SERVICE['server']},
 2478             'tcp-port': '389',
 2479             'schema': 'RFC-2307',
 2480             'bind-password': fake.LDAP_SECURITY_SERVICE['password']
 2481         }
 2482         ldap_config_create_args = {
 2483             'client-config': config_name,
 2484             'client-enabled': 'true'
 2485         }
 2486 
 2487         self.client.send_request.assert_has_calls([
 2488             mock.call('ldap-client-create', ldap_client_create_args),
 2489             mock.call('ldap-config-create', ldap_config_create_args)])
 2490 
 2491     def test_configure_active_directory(self):
 2492 
 2493         self.mock_object(self.client, 'send_request')
 2494         self.mock_object(self.client, 'configure_dns')
 2495         self.mock_object(self.client, 'set_preferred_dc')
 2496 
 2497         self.client.configure_active_directory(fake.CIFS_SECURITY_SERVICE,
 2498                                                fake.VSERVER_NAME)
 2499 
 2500         cifs_server = (fake.VSERVER_NAME[0:8] +
 2501                        '-' +
 2502                        fake.VSERVER_NAME[-6:]).replace('_', '-').upper()
 2503 
 2504         cifs_server_create_args = {
 2505             'admin-username': fake.CIFS_SECURITY_SERVICE['user'],
 2506             'admin-password': fake.CIFS_SECURITY_SERVICE['password'],
 2507             'force-account-overwrite': 'true',
 2508             'cifs-server': cifs_server,
 2509             'organizational-unit': fake.CIFS_SECURITY_SERVICE['ou'],
 2510             'domain': fake.CIFS_SECURITY_SERVICE['domain'],
 2511         }
 2512 
 2513         self.client.configure_dns.assert_called_with(
 2514             fake.CIFS_SECURITY_SERVICE)
 2515         self.client.set_preferred_dc.assert_called_with(
 2516             fake.CIFS_SECURITY_SERVICE)
 2517         self.client.send_request.assert_has_calls([
 2518             mock.call('cifs-server-create', cifs_server_create_args)])
 2519 
 2520     def test_configure_active_directory_api_error(self):
 2521 
 2522         self.mock_object(self.client, 'send_request', self._mock_api_error())
 2523         self.mock_object(self.client, 'configure_dns')
 2524 
 2525         self.assertRaises(exception.NetAppException,
 2526                           self.client.configure_active_directory,
 2527                           fake.CIFS_SECURITY_SERVICE,
 2528                           fake.VSERVER_NAME)
 2529 
 2530     def test_create_kerberos_realm(self):
 2531 
 2532         self.mock_object(self.client, 'send_request')
 2533 
 2534         self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE)
 2535 
 2536         kerberos_realm_create_args = {
 2537             'admin-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
 2538             'admin-server-port': '749',
 2539             'clock-skew': '5',
 2540             'comment': '',
 2541             'config-name': fake.KERBEROS_SECURITY_SERVICE['id'],
 2542             'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
 2543             'kdc-port': '88',
 2544             'kdc-vendor': 'other',
 2545             'password-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
 2546             'password-server-port': '464',
 2547             'realm': fake.KERBEROS_SECURITY_SERVICE['domain'].upper()
 2548         }
 2549 
 2550         self.client.send_request.assert_has_calls([
 2551             mock.call('kerberos-realm-create', kerberos_realm_create_args)])
 2552 
 2553     def test_create_kerberos_realm_already_present(self):
 2554 
 2555         self.mock_object(self.client,
 2556                          'send_request',
 2557                          self._mock_api_error(code=netapp_api.EDUPLICATEENTRY))
 2558 
 2559         self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE)
 2560 
 2561         kerberos_realm_create_args = {
 2562             'admin-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
 2563             'admin-server-port': '749',
 2564             'clock-skew': '5',
 2565             'comment': '',
 2566             'config-name': fake.KERBEROS_SECURITY_SERVICE['id'],
 2567             'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
 2568             'kdc-port': '88',
 2569             'kdc-vendor': 'other',
 2570             'password-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
 2571             'password-server-port': '464',
 2572             'realm': fake.KERBEROS_SECURITY_SERVICE['domain'].upper()
 2573         }
 2574 
 2575         self.client.send_request.assert_has_calls([
 2576             mock.call('kerberos-realm-create', kerberos_realm_create_args)])
 2577         self.assertEqual(1, client_cmode.LOG.debug.call_count)
 2578 
 2579     def test_create_kerberos_realm_api_error(self):
 2580 
 2581         self.mock_object(self.client, 'send_request', self._mock_api_error())
 2582 
 2583         self.assertRaises(exception.NetAppException,
 2584                           self.client.create_kerberos_realm,
 2585                           fake.KERBEROS_SECURITY_SERVICE)
 2586 
 2587     def test_configure_kerberos(self):
 2588 
 2589         self.mock_object(self.client, 'send_request')
 2590         self.mock_object(self.client, 'configure_dns')
 2591         self.mock_object(self.client,
 2592                          'list_network_interfaces',
 2593                          mock.Mock(return_value=['lif1', 'lif2']))
 2594 
 2595         self.client.configure_kerberos(
 2596             fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME)
 2597 
 2598         spn = self.client._get_kerberos_service_principal_name(
 2599             fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME)
 2600 
 2601         kerberos_config_modify_args1 = {
 2602             'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'],
 2603             'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'],
 2604             'interface-name': 'lif1',
 2605             'is-kerberos-enabled': 'true',
 2606             'service-principal-name': spn
 2607         }
 2608         kerberos_config_modify_args2 = {
 2609             'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'],
 2610             'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'],
 2611             'interface-name': 'lif2',
 2612             'is-kerberos-enabled': 'true',
 2613             'service-principal-name': spn
 2614         }
 2615 
 2616         self.client.configure_dns.assert_called_with(
 2617             fake.KERBEROS_SECURITY_SERVICE)
 2618         self.client.send_request.assert_has_calls([
 2619             mock.call('kerberos-config-modify',
 2620                       kerberos_config_modify_args1),
 2621             mock.call('kerberos-config-modify',
 2622                       kerberos_config_modify_args2)])
 2623 
 2624     def test_configure_kerberos_no_network_interfaces(self):
 2625 
 2626         self.mock_object(self.client, 'send_request')
 2627         self.mock_object(self.client, 'configure_dns')
 2628         self.mock_object(self.client,
 2629                          'list_network_interfaces',
 2630                          mock.Mock(return_value=[]))
 2631 
 2632         self.assertRaises(exception.NetAppException,
 2633                           self.client.configure_kerberos,
 2634                           fake.KERBEROS_SECURITY_SERVICE,
 2635                           fake.VSERVER_NAME)
 2636 
 2637         self.client.configure_dns.assert_called_with(
 2638             fake.KERBEROS_SECURITY_SERVICE)
 2639 
 2640     def test_get_kerberos_service_principal_name(self):
 2641 
 2642         spn = self.client._get_kerberos_service_principal_name(
 2643             fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME
 2644         )
 2645         self.assertEqual(fake.KERBEROS_SERVICE_PRINCIPAL_NAME, spn)
 2646 
 2647     def test_configure_dns_for_active_directory(self):
 2648 
 2649         self.mock_object(self.client, 'send_request')
 2650 
 2651         self.client.configure_dns(fake.CIFS_SECURITY_SERVICE)
 2652 
 2653         net_dns_create_args = {
 2654             'domains': {'string': fake.CIFS_SECURITY_SERVICE['domain']},
 2655             'name-servers': [{
 2656                 'ip-address': fake.CIFS_SECURITY_SERVICE['dns_ip']
 2657             }],
 2658             'dns-state': 'enabled'
 2659         }
 2660 
 2661         self.client.send_request.assert_has_calls([
 2662             mock.call('net-dns-create', net_dns_create_args)])
 2663 
 2664     def test_configure_dns_multiple_dns_ip(self):
 2665 
 2666         self.mock_object(self.client, 'send_request')
 2667         mock_dns_ips = ['10.0.0.1', '10.0.0.2', '10.0.0.3']
 2668         security_service = fake.CIFS_SECURITY_SERVICE
 2669         security_service['dns_ip'] = ', '.join(mock_dns_ips)
 2670 
 2671         self.client.configure_dns(security_service)
 2672 
 2673         net_dns_create_args = {
 2674             'domains': {'string': security_service['domain']},
 2675             'dns-state': 'enabled',
 2676             'name-servers': [{'ip-address': dns_ip} for dns_ip in mock_dns_ips]
 2677         }
 2678 
 2679         self.client.send_request.assert_has_calls([
 2680             mock.call('net-dns-create', net_dns_create_args)])
 2681 
 2682     def test_configure_dns_for_kerberos(self):
 2683 
 2684         self.mock_object(self.client, 'send_request')
 2685 
 2686         self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE)
 2687 
 2688         net_dns_create_args = {
 2689             'domains': {'string': fake.KERBEROS_SECURITY_SERVICE['domain']},
 2690             'name-servers': [{
 2691                 'ip-address': fake.KERBEROS_SECURITY_SERVICE['dns_ip']
 2692             }],
 2693             'dns-state': 'enabled'
 2694         }
 2695 
 2696         self.client.send_request.assert_has_calls([
 2697             mock.call('net-dns-create', net_dns_create_args)])
 2698 
 2699     def test_configure_dns_already_present(self):
 2700 
 2701         self.mock_object(self.client,
 2702                          'send_request',
 2703                          self._mock_api_error(code=netapp_api.EDUPLICATEENTRY))
 2704 
 2705         self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE)
 2706 
 2707         net_dns_create_args = {
 2708             'domains': {'string': fake.KERBEROS_SECURITY_SERVICE['domain']},
 2709             'name-servers': [{
 2710                 'ip-address': fake.KERBEROS_SECURITY_SERVICE['dns_ip']
 2711             }],
 2712             'dns-state': 'enabled'
 2713         }
 2714 
 2715         self.client.send_request.assert_has_calls([
 2716             mock.call('net-dns-create', net_dns_create_args)])
 2717         self.assertEqual(1, client_cmode.LOG.error.call_count)
 2718 
 2719     def test_configure_dns_api_error(self):
 2720 
 2721         self.mock_object(self.client, 'send_request', self._mock_api_error())
 2722 
 2723         self.assertRaises(exception.NetAppException,
 2724                           self.client.configure_dns,
 2725                           fake.KERBEROS_SECURITY_SERVICE)
 2726 
 2727     @ddt.data(
 2728         {
 2729             'server': '',
 2730             'check_feature': False
 2731         },
 2732         {
 2733             'server': ['10.0.0.2', '10.0.0.3'],
 2734             'check_feature': False
 2735         },
 2736         {
 2737             'server': '10.0.0.1',
 2738             'check_feature': False
 2739         },
 2740         {
 2741             'server': '10.0.0.1',
 2742             'check_feature': True
 2743         }
 2744     )
 2745     @ddt.unpack
 2746     def test_set_preferred_dc(self, server, check_feature):
 2747         if check_feature:
 2748             self.client.features.add_feature('CIFS_DC_ADD_SKIP_CHECK')
 2749 
 2750         self.mock_object(self.client, 'send_request')
 2751         security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
 2752         security_service['server'] = ', '.join(server)
 2753 
 2754         self.client.set_preferred_dc(security_service)
 2755 
 2756         if server is '':
 2757             self.client.send_request.assert_not_called()
 2758         else:
 2759             preferred_dc_add_args = {
 2760                 'domain': fake.CIFS_SECURITY_SERVICE['domain'],
 2761                 'preferred-dc': [{'string': dc_ip} for dc_ip in server]
 2762             }
 2763 
 2764             if check_feature:
 2765                 preferred_dc_add_args['skip-config-validation'] = 'false'
 2766 
 2767             self.client.send_request.assert_has_calls([
 2768                 mock.call('cifs-domain-preferred-dc-add',
 2769                           preferred_dc_add_args)])
 2770 
 2771     def test_set_preferred_dc_api_error(self):
 2772 
 2773         self.mock_object(self.client, 'send_request', self._mock_api_error())
 2774         security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
 2775         security_service['server'] = 'fake_server'
 2776 
 2777         self.assertRaises(exception.NetAppException,
 2778                           self.client.set_preferred_dc,
 2779                           security_service)
 2780 
 2781     def test_create_volume(self):
 2782 
 2783         self.mock_object(self.client, 'send_request')
 2784         self.mock_object(self.client, 'update_volume_efficiency_attributes')
 2785 
 2786         self.client.create_volume(
 2787             fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100)
 2788 
 2789         volume_create_args = {
 2790             'containing-aggr-name': fake.SHARE_AGGREGATE_NAME,
 2791             'size': '100g',
 2792             'volume': fake.SHARE_NAME,
 2793             'volume-type': 'rw',
 2794             'junction-path': '/%s' % fake.SHARE_NAME,
 2795         }
 2796 
 2797         self.client.send_request.assert_called_once_with('volume-create',
 2798                                                          volume_create_args)
 2799 
 2800     @ddt.data(None, fake.QOS_POLICY_GROUP_NAME)
 2801     def test_create_volume_with_extra_specs(self, qos_policy_group_name):
 2802 
 2803         self.mock_object(self.client, 'set_volume_max_files')
 2804         self.mock_object(self.client, 'enable_dedup')
 2805         self.mock_object(self.client, 'enable_compression')
 2806         self.mock_object(self.client, 'send_request')
 2807         self.mock_object(
 2808             self.client,
 2809             'get_volume_efficiency_status',
 2810             mock.Mock(return_value={'dedupe': False, 'compression': False}))
 2811 
 2812         self.client.create_volume(
 2813             fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100,
 2814             thin_provisioned=True, language='en-US',
 2815             snapshot_policy='default', dedup_enabled=True,
 2816             compression_enabled=True, max_files=5000, snapshot_reserve=15,
 2817             qos_policy_group=qos_policy_group_name)
 2818 
 2819         volume_create_args = {
 2820             'containing-aggr-name': fake.SHARE_AGGREGATE_NAME,
 2821             'size': '100g',
 2822             'volume': fake.SHARE_NAME,
 2823             'junction-path': '/%s' % fake.SHARE_NAME,
 2824             'space-reserve': 'none',
 2825             'language-code': 'en-US',
 2826             'volume-type': 'rw',
 2827             'snapshot-policy': 'default',
 2828             'percentage-snapshot-reserve': '15',
 2829         }
 2830 
 2831         if qos_policy_group_name:
 2832             volume_create_args.update(
 2833                 {'qos-policy-group-name': qos_policy_group_name})
 2834 
 2835         self.client.send_request.assert_called_with('volume-create',
 2836                                                     volume_create_args)
 2837         self.client.set_volume_max_files.assert_called_once_with(
 2838             fake.SHARE_NAME, fake.MAX_FILES)
 2839         self.client.enable_dedup.assert_called_once_with(fake.SHARE_NAME)
 2840         self.client.enable_compression.assert_called_once_with(fake.SHARE_NAME)
 2841 
 2842     def test_create_encrypted_volume(self):
 2843 
 2844         self.mock_object(self.client, 'send_request')
 2845         self.mock_object(self.client, 'update_volume_efficiency_attributes')
 2846         self.client.features.add_feature('FLEXVOL_ENCRYPTION')
 2847 
 2848         self.client.create_volume(
 2849             fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100, encrypt=True)
 2850 
 2851         volume_create_args = {
 2852             'containing-aggr-name': fake.SHARE_AGGREGATE_NAME,
 2853             'size': '100g',
 2854             'volume': fake.SHARE_NAME,
 2855             'volume-type': 'rw',
 2856             'junction-path': '/%s' % fake.SHARE_NAME,
 2857             'encrypt': 'true',
 2858         }
 2859 
 2860         self.client.send_request.assert_called_once_with('volume-create',
 2861                                                          volume_create_args)
 2862 
 2863     def test_create_non_encrypted_volume(self):
 2864 
 2865         self.mock_object(self.client, 'send_request')
 2866         self.mock_object(self.client, 'update_volume_efficiency_attributes')
 2867         self.client.features.add_feature('FLEXVOL_ENCRYPTION')
 2868 
 2869         self.client.create_volume(
 2870             fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100, encrypt=False)
 2871 
 2872         volume_create_args = {
 2873             'containing-aggr-name': fake.SHARE_AGGREGATE_NAME,
 2874             'size': '100g',
 2875             'volume': fake.SHARE_NAME,
 2876             'volume-type': 'rw',
 2877             'junction-path': '/%s' % fake.SHARE_NAME,
 2878         }
 2879 
 2880         self.client.send_request.assert_called_once_with('volume-create',
 2881                                                          volume_create_args)
 2882 
 2883     def test_create_encrypted_volume_not_supported(self):
 2884 
 2885         self.assertRaises(exception.NetAppException,
 2886                           self.client.create_volume,
 2887                           fake.SHARE_AGGREGATE_NAME,
 2888                           fake.SHARE_NAME,
 2889                           100,
 2890                           encrypt=True)
 2891 
 2892     def test_is_flexvol_encrypted_unsupported(self):
 2893 
 2894         self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=False)
 2895 
 2896         result = self.client.is_flexvol_encrypted(fake.SHARE_NAME,
 2897                                                   fake.VSERVER_NAME)
 2898 
 2899         self.assertFalse(result)
 2900 
 2901     def test_is_flexvol_encrypted_no_records_found(self):
 2902 
 2903         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 2904         self.mock_object(self.client,
 2905                          'send_iter_request',
 2906                          mock.Mock(return_value=api_response))
 2907 
 2908         result = self.client.is_flexvol_encrypted(fake.SHARE_NAME,
 2909                                                   fake.VSERVER_NAME)
 2910 
 2911         self.assertFalse(result)
 2912 
 2913     def test_is_flexvol_encrypted(self):
 2914 
 2915         self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=True)
 2916         api_response = netapp_api.NaElement(
 2917             fake.GET_VOLUME_FOR_ENCRYPTED_RESPONSE)
 2918         self.mock_object(self.client,
 2919                          'send_iter_request',
 2920                          mock.Mock(return_value=api_response))
 2921 
 2922         result = self.client.is_flexvol_encrypted(fake.SHARE_NAME,
 2923                                                   fake.VSERVER_NAME)
 2924 
 2925         volume_get_iter_args = {
 2926             'query': {
 2927                 'volume-attributes': {
 2928                     'encrypt': 'true',
 2929                     'volume-id-attributes': {
 2930                         'name': fake.SHARE_NAME,
 2931                         'owning-vserver-name': fake.VSERVER_NAME,
 2932                     }
 2933                 }
 2934             },
 2935             'desired-attributes': {
 2936                 'volume-attributes': {
 2937                     'encrypt': None,
 2938                 }
 2939             }
 2940         }
 2941 
 2942         self.client.send_iter_request.assert_called_once_with(
 2943             'volume-get-iter', volume_get_iter_args)
 2944 
 2945         self.assertTrue(result)
 2946 
 2947     def test_is_flexvol_encrypted_8_x_system_version_response(self):
 2948 
 2949         self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=True)
 2950         api_response = netapp_api.NaElement(
 2951             fake.GET_VOLUME_FOR_ENCRYPTED_OLD_SYS_VERSION_RESPONSE)
 2952         self.mock_object(self.client,
 2953                          'send_iter_request',
 2954                          mock.Mock(return_value=api_response))
 2955 
 2956         result = self.client.is_flexvol_encrypted(fake.SHARE_NAME,
 2957                                                   fake.VSERVER_NAME)
 2958 
 2959         volume_get_iter_args = {
 2960             'query': {
 2961                 'volume-attributes': {
 2962                     'encrypt': 'true',
 2963                     'volume-id-attributes': {
 2964                         'name': fake.SHARE_NAME,
 2965                         'owning-vserver-name': fake.VSERVER_NAME,
 2966                     }
 2967                 }
 2968             },
 2969             'desired-attributes': {
 2970                 'volume-attributes': {
 2971                     'encrypt': None,
 2972                 }
 2973             }
 2974         }
 2975 
 2976         self.client.send_iter_request.assert_called_once_with(
 2977             'volume-get-iter', volume_get_iter_args)
 2978 
 2979         self.assertFalse(result)
 2980 
 2981     def test_enable_dedup(self):
 2982 
 2983         self.mock_object(self.client, 'send_request')
 2984 
 2985         self.client.enable_dedup(fake.SHARE_NAME)
 2986 
 2987         sis_enable_args = {'path': '/vol/%s' % fake.SHARE_NAME}
 2988 
 2989         self.client.send_request.assert_called_once_with('sis-enable',
 2990                                                          sis_enable_args)
 2991 
 2992     def test_disable_dedup(self):
 2993 
 2994         self.mock_object(self.client, 'send_request')
 2995 
 2996         self.client.disable_dedup(fake.SHARE_NAME)
 2997 
 2998         sis_disable_args = {'path': '/vol/%s' % fake.SHARE_NAME}
 2999 
 3000         self.client.send_request.assert_called_once_with('sis-disable',
 3001                                                          sis_disable_args)
 3002 
 3003     def test_enable_compression(self):
 3004 
 3005         self.mock_object(self.client, 'send_request')
 3006 
 3007         self.client.enable_compression(fake.SHARE_NAME)
 3008 
 3009         sis_set_config_args = {
 3010             'path': '/vol/%s' % fake.SHARE_NAME,
 3011             'enable-compression': 'true'
 3012         }
 3013 
 3014         self.client.send_request.assert_called_once_with('sis-set-config',
 3015                                                          sis_set_config_args)
 3016 
 3017     def test_disable_compression(self):
 3018 
 3019         self.mock_object(self.client, 'send_request')
 3020 
 3021         self.client.disable_compression(fake.SHARE_NAME)
 3022 
 3023         sis_set_config_args = {
 3024             'path': '/vol/%s' % fake.SHARE_NAME,
 3025             'enable-compression': 'false'
 3026         }
 3027 
 3028         self.client.send_request.assert_called_once_with('sis-set-config',
 3029                                                          sis_set_config_args)
 3030 
 3031     def test_get_volume_efficiency_status(self):
 3032 
 3033         api_response = netapp_api.NaElement(fake.SIS_GET_ITER_RESPONSE)
 3034         self.mock_object(self.client,
 3035                          'send_iter_request',
 3036                          mock.Mock(return_value=api_response))
 3037 
 3038         result = self.client.get_volume_efficiency_status(fake.SHARE_NAME)
 3039 
 3040         sis_get_iter_args = {
 3041             'query': {
 3042                 'sis-status-info': {
 3043                     'path': '/vol/%s' % fake.SHARE_NAME,
 3044                 },
 3045             },
 3046             'desired-attributes': {
 3047                 'sis-status-info': {
 3048                     'state': None,
 3049                     'is-compression-enabled': None,
 3050                 },
 3051             },
 3052         }
 3053         self.client.send_iter_request.assert_has_calls([
 3054             mock.call('sis-get-iter', sis_get_iter_args)])
 3055 
 3056         expected = {'dedupe': True, 'compression': True}
 3057         self.assertDictEqual(expected, result)
 3058 
 3059     def test_get_volume_efficiency_status_not_found(self):
 3060 
 3061         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3062         self.mock_object(self.client,
 3063                          'send_iter_request',
 3064                          mock.Mock(return_value=api_response))
 3065 
 3066         result = self.client.get_volume_efficiency_status(fake.SHARE_NAME)
 3067 
 3068         expected = {'dedupe': False, 'compression': False}
 3069         self.assertDictEqual(expected, result)
 3070 
 3071     def test_set_volume_max_files(self):
 3072 
 3073         self.mock_object(self.client, 'send_request')
 3074 
 3075         self.client.set_volume_max_files(fake.SHARE_NAME, fake.MAX_FILES)
 3076 
 3077         volume_modify_iter_api_args = {
 3078             'query': {
 3079                 'volume-attributes': {
 3080                     'volume-id-attributes': {
 3081                         'name': fake.SHARE_NAME,
 3082                     },
 3083                 },
 3084             },
 3085             'attributes': {
 3086                 'volume-attributes': {
 3087                     'volume-inode-attributes': {
 3088                         'files-total': fake.MAX_FILES,
 3089                     },
 3090                 },
 3091             },
 3092         }
 3093 
 3094         self.client.send_request.assert_called_once_with(
 3095             'volume-modify-iter', volume_modify_iter_api_args)
 3096 
 3097     def test_set_volume_name(self):
 3098 
 3099         self.mock_object(self.client, 'send_request')
 3100 
 3101         self.client.set_volume_name(fake.SHARE_NAME, 'new_name')
 3102 
 3103         volume_rename_api_args = {
 3104             'volume': fake.SHARE_NAME,
 3105             'new-volume-name': 'new_name',
 3106         }
 3107 
 3108         self.client.send_request.assert_called_once_with(
 3109             'volume-rename', volume_rename_api_args)
 3110 
 3111     def test_rename_vserver(self):
 3112 
 3113         vserver_api_args = {
 3114             'vserver-name': fake.VSERVER_NAME,
 3115             'new-name': fake.VSERVER_NAME_2,
 3116         }
 3117         self.mock_object(self.client, 'send_request')
 3118 
 3119         self.client.rename_vserver(fake.VSERVER_NAME, fake.VSERVER_NAME_2)
 3120 
 3121         self.client.send_request.assert_called_once_with(
 3122             'vserver-rename', vserver_api_args
 3123         )
 3124 
 3125     def test_modify_volume_no_optional_args(self):
 3126 
 3127         self.mock_object(self.client, 'send_request')
 3128         mock_update_volume_efficiency_attributes = self.mock_object(
 3129             self.client, 'update_volume_efficiency_attributes')
 3130 
 3131         self.client.modify_volume(fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME)
 3132 
 3133         volume_modify_iter_api_args = {
 3134             'query': {
 3135                 'volume-attributes': {
 3136                     'volume-id-attributes': {
 3137                         'containing-aggregate-name': fake.SHARE_AGGREGATE_NAME,
 3138                         'name': fake.SHARE_NAME,
 3139                     },
 3140                 },
 3141             },
 3142             'attributes': {
 3143                 'volume-attributes': {
 3144                     'volume-inode-attributes': {},
 3145                     'volume-language-attributes': {},
 3146                     'volume-snapshot-attributes': {},
 3147                     'volume-space-attributes': {
 3148                         'space-guarantee': 'volume',
 3149                     },
 3150                 },
 3151             },
 3152         }
 3153 
 3154         self.client.send_request.assert_called_once_with(
 3155             'volume-modify-iter', volume_modify_iter_api_args)
 3156         mock_update_volume_efficiency_attributes.assert_called_once_with(
 3157             fake.SHARE_NAME, False, False)
 3158 
 3159     def test_modify_volume_all_optional_args(self):
 3160 
 3161         self.mock_object(self.client, 'send_request')
 3162         mock_update_volume_efficiency_attributes = self.mock_object(
 3163             self.client, 'update_volume_efficiency_attributes')
 3164 
 3165         self.client.modify_volume(fake.SHARE_AGGREGATE_NAME,
 3166                                   fake.SHARE_NAME,
 3167                                   thin_provisioned=True,
 3168                                   snapshot_policy=fake.SNAPSHOT_POLICY_NAME,
 3169                                   language=fake.LANGUAGE,
 3170                                   dedup_enabled=True,
 3171                                   compression_enabled=False,
 3172                                   max_files=fake.MAX_FILES,
 3173                                   qos_policy_group=fake.QOS_POLICY_GROUP_NAME,
 3174                                   hide_snapdir=True)
 3175 
 3176         volume_modify_iter_api_args = {
 3177             'query': {
 3178                 'volume-attributes': {
 3179                     'volume-id-attributes': {
 3180                         'containing-aggregate-name': fake.SHARE_AGGREGATE_NAME,
 3181                         'name': fake.SHARE_NAME,
 3182                     },
 3183                 },
 3184             },
 3185             'attributes': {
 3186                 'volume-attributes': {
 3187                     'volume-inode-attributes': {
 3188                         'files-total': fake.MAX_FILES,
 3189                     },
 3190                     'volume-language-attributes': {
 3191                         'language': fake.LANGUAGE,
 3192                     },
 3193                     'volume-snapshot-attributes': {
 3194                         'snapshot-policy': fake.SNAPSHOT_POLICY_NAME,
 3195                         'snapdir-access-enabled': 'false'
 3196                     },
 3197                     'volume-space-attributes': {
 3198                         'space-guarantee': 'none',
 3199                     },
 3200                     'volume-qos-attributes': {
 3201                         'policy-group-name': fake.QOS_POLICY_GROUP_NAME,
 3202                     },
 3203 
 3204                 },
 3205             },
 3206         }
 3207 
 3208         self.client.send_request.assert_called_once_with(
 3209             'volume-modify-iter', volume_modify_iter_api_args)
 3210         mock_update_volume_efficiency_attributes.assert_called_once_with(
 3211             fake.SHARE_NAME, True, False)
 3212 
 3213     @ddt.data(
 3214         {'existing': (True, True), 'desired': (True, True)},
 3215         {'existing': (True, True), 'desired': (False, False)},
 3216         {'existing': (True, True), 'desired': (True, False)},
 3217         {'existing': (True, False), 'desired': (True, False)},
 3218         {'existing': (True, False), 'desired': (False, False)},
 3219         {'existing': (True, False), 'desired': (True, True)},
 3220         {'existing': (False, False), 'desired': (False, False)},
 3221         {'existing': (False, False), 'desired': (True, False)},
 3222         {'existing': (False, False), 'desired': (True, True)},
 3223     )
 3224     @ddt.unpack
 3225     def test_update_volume_efficiency_attributes(self, existing, desired):
 3226 
 3227         existing_dedupe = existing[0]
 3228         existing_compression = existing[1]
 3229         desired_dedupe = desired[0]
 3230         desired_compression = desired[1]
 3231 
 3232         self.mock_object(
 3233             self.client,
 3234             'get_volume_efficiency_status',
 3235             mock.Mock(return_value={'dedupe': existing_dedupe,
 3236                                     'compression': existing_compression}))
 3237         mock_enable_compression = self.mock_object(self.client,
 3238                                                    'enable_compression')
 3239         mock_disable_compression = self.mock_object(self.client,
 3240                                                     'disable_compression')
 3241         mock_enable_dedup = self.mock_object(self.client, 'enable_dedup')
 3242         mock_disable_dedup = self.mock_object(self.client, 'disable_dedup')
 3243 
 3244         self.client.update_volume_efficiency_attributes(
 3245             fake.SHARE_NAME, desired_dedupe, desired_compression)
 3246 
 3247         if existing_dedupe == desired_dedupe:
 3248             self.assertFalse(mock_enable_dedup.called)
 3249             self.assertFalse(mock_disable_dedup.called)
 3250         elif existing_dedupe and not desired_dedupe:
 3251             self.assertFalse(mock_enable_dedup.called)
 3252             self.assertTrue(mock_disable_dedup.called)
 3253         elif not existing_dedupe and desired_dedupe:
 3254             self.assertTrue(mock_enable_dedup.called)
 3255             self.assertFalse(mock_disable_dedup.called)
 3256 
 3257         if existing_compression == desired_compression:
 3258             self.assertFalse(mock_enable_compression.called)
 3259             self.assertFalse(mock_disable_compression.called)
 3260         elif existing_compression and not desired_compression:
 3261             self.assertFalse(mock_enable_compression.called)
 3262             self.assertTrue(mock_disable_compression.called)
 3263         elif not existing_compression and desired_compression:
 3264             self.assertTrue(mock_enable_compression.called)
 3265             self.assertFalse(mock_disable_compression.called)
 3266 
 3267     def test_set_volume_size(self):
 3268 
 3269         api_response = netapp_api.NaElement(fake.VOLUME_MODIFY_ITER_RESPONSE)
 3270         self.mock_object(self.client,
 3271                          'send_request',
 3272                          mock.Mock(return_value=api_response))
 3273 
 3274         self.client.set_volume_size(fake.SHARE_NAME, 10)
 3275 
 3276         volume_modify_iter_args = {
 3277             'query': {
 3278                 'volume-attributes': {
 3279                     'volume-id-attributes': {
 3280                         'name': fake.SHARE_NAME
 3281                     }
 3282                 }
 3283             },
 3284             'attributes': {
 3285                 'volume-attributes': {
 3286                     'volume-space-attributes': {
 3287                         'size': 10737418240,
 3288                     },
 3289                 },
 3290             },
 3291         }
 3292         self.client.send_request.assert_has_calls([
 3293             mock.call('volume-modify-iter', volume_modify_iter_args)])
 3294 
 3295     @ddt.data(True, False)
 3296     def test_set_volume_snapdir_access(self, hide_snapdir):
 3297         api_response = netapp_api.NaElement(
 3298             fake.VOLUME_MODIFY_ITER_RESPONSE)
 3299         self.mock_object(self.client,
 3300                          'send_request',
 3301                          mock.Mock(return_value=api_response))
 3302 
 3303         self.client.set_volume_snapdir_access(fake.SHARE_NAME, hide_snapdir)
 3304 
 3305         api_args = {
 3306             'query': {
 3307                 'volume-attributes': {
 3308                     'volume-id-attributes': {
 3309                         'name': fake.SHARE_NAME
 3310                     }
 3311                 }
 3312             },
 3313             'attributes': {
 3314                 'volume-attributes': {
 3315                     'volume-snapshot-attributes': {
 3316                         'snapdir-access-enabled': six.text_type(
 3317                             not hide_snapdir).lower(),
 3318                     },
 3319                 },
 3320             },
 3321         }
 3322         self.client.send_request.assert_called_once_with(
 3323             'volume-modify-iter', api_args)
 3324 
 3325     def test_set_volume_snapdir_access_api_error(self):
 3326 
 3327         api_response = netapp_api.NaElement(
 3328             fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE)
 3329         self.mock_object(self.client,
 3330                          'send_request',
 3331                          mock.Mock(return_value=api_response))
 3332 
 3333         self.assertRaises(netapp_api.NaApiError,
 3334                           self.client.set_volume_size,
 3335                           fake.SHARE_NAME,
 3336                           10)
 3337 
 3338     @ddt.data(True, False)
 3339     def test_set_volume_filesys_size_fixed(self, filesys_size_fixed):
 3340         api_response = netapp_api.NaElement(
 3341             fake.VOLUME_MODIFY_ITER_RESPONSE)
 3342         self.mock_object(self.client,
 3343                          'send_request',
 3344                          mock.Mock(return_value=api_response))
 3345 
 3346         self.client.set_volume_filesys_size_fixed(fake.SHARE_NAME,
 3347                                                   filesys_size_fixed)
 3348 
 3349         api_args = {
 3350             'query': {
 3351                 'volume-attributes': {
 3352                     'volume-id-attributes': {
 3353                         'name': fake.SHARE_NAME
 3354                     }
 3355                 }
 3356             },
 3357             'attributes': {
 3358                 'volume-attributes': {
 3359                     'volume-space-attributes': {
 3360                         'is-filesys-size-fixed': six.text_type(
 3361                             filesys_size_fixed).lower(),
 3362                     },
 3363                 },
 3364             },
 3365         }
 3366         self.client.send_request.assert_called_once_with(
 3367             'volume-modify-iter', api_args)
 3368 
 3369     def test_set_volume_size_api_error(self):
 3370 
 3371         api_response = netapp_api.NaElement(
 3372             fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE)
 3373         self.mock_object(self.client,
 3374                          'send_request',
 3375                          mock.Mock(return_value=api_response))
 3376 
 3377         self.assertRaises(netapp_api.NaApiError,
 3378                           self.client.set_volume_size,
 3379                           fake.SHARE_NAME,
 3380                           10)
 3381 
 3382     @ddt.data(None, 'ntfs')
 3383     def test_set_volume_security_style(self, security_style):
 3384 
 3385         api_response = netapp_api.NaElement(fake.VOLUME_MODIFY_ITER_RESPONSE)
 3386         self.mock_object(self.client,
 3387                          'send_request',
 3388                          mock.Mock(return_value=api_response))
 3389         kwargs = {'security_style': security_style} if security_style else {}
 3390 
 3391         self.client.set_volume_security_style(fake.SHARE_NAME, **kwargs)
 3392 
 3393         volume_modify_iter_args = {
 3394             'query': {
 3395                 'volume-attributes': {
 3396                     'volume-id-attributes': {
 3397                         'name': fake.SHARE_NAME
 3398                     }
 3399                 }
 3400             },
 3401             'attributes': {
 3402                 'volume-attributes': {
 3403                     'volume-security-attributes': {
 3404                         'style': security_style or 'unix',
 3405                     },
 3406                 },
 3407             },
 3408         }
 3409         self.client.send_request.assert_called_once_with(
 3410             'volume-modify-iter', volume_modify_iter_args)
 3411 
 3412     def test_set_volume_security_style_api_error(self):
 3413 
 3414         api_response = netapp_api.NaElement(
 3415             fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE)
 3416         self.mock_object(self.client,
 3417                          'send_request',
 3418                          mock.Mock(return_value=api_response))
 3419 
 3420         self.assertRaises(netapp_api.NaApiError,
 3421                           self.client.set_volume_security_style,
 3422                           fake.SHARE_NAME,
 3423                           'ntfs')
 3424 
 3425     def test_volume_exists(self):
 3426 
 3427         api_response = netapp_api.NaElement(fake.VOLUME_GET_NAME_RESPONSE)
 3428         self.mock_object(self.client,
 3429                          'send_iter_request',
 3430                          mock.Mock(return_value=api_response))
 3431 
 3432         result = self.client.volume_exists(fake.SHARE_NAME)
 3433 
 3434         volume_get_iter_args = {
 3435             'query': {
 3436                 'volume-attributes': {
 3437                     'volume-id-attributes': {
 3438                         'name': fake.SHARE_NAME
 3439                     }
 3440                 }
 3441             },
 3442             'desired-attributes': {
 3443                 'volume-attributes': {
 3444                     'volume-id-attributes': {
 3445                         'name': None
 3446                     }
 3447                 }
 3448             }
 3449         }
 3450 
 3451         self.client.send_iter_request.assert_has_calls([
 3452             mock.call('volume-get-iter', volume_get_iter_args)])
 3453         self.assertTrue(result)
 3454 
 3455     def test_volume_exists_not_found(self):
 3456 
 3457         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3458         self.mock_object(self.client,
 3459                          'send_request',
 3460                          mock.Mock(return_value=api_response))
 3461 
 3462         self.assertFalse(self.client.volume_exists(fake.SHARE_NAME))
 3463 
 3464     def test_snapshot_exists(self):
 3465 
 3466         api_response = netapp_api.NaElement(fake.VOLUME_GET_NAME_RESPONSE)
 3467         self.mock_object(self.client,
 3468                          'send_request',
 3469                          mock.Mock(return_value=api_response))
 3470 
 3471         result = self.client.snapshot_exists(fake.SNAPSHOT_NAME,
 3472                                              fake.SHARE_NAME)
 3473 
 3474         snapshot_get_iter_args = {
 3475             'query': {
 3476                 'snapshot-info': {
 3477                     'name': fake.SNAPSHOT_NAME,
 3478                     'volume': fake.SHARE_NAME,
 3479                 }
 3480             },
 3481             'desired-attributes': {
 3482                 'snapshot-info': {
 3483                     'name': None,
 3484                     'volume': None,
 3485                     'busy': None,
 3486                     'snapshot-owners-list': {
 3487                         'snapshot-owner': None,
 3488                     }
 3489                 }
 3490             }
 3491         }
 3492 
 3493         self.client.send_request.assert_has_calls([
 3494             mock.call('snapshot-get-iter', snapshot_get_iter_args)])
 3495         self.assertTrue(result)
 3496 
 3497     def test_snapshot_exists_not_found(self):
 3498         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3499         self.mock_object(self.client,
 3500                          'send_request',
 3501                          mock.Mock(return_value=api_response))
 3502 
 3503         self.assertFalse(self.client.snapshot_exists(fake.SNAPSHOT_NAME,
 3504                                                      fake.SHARE_NAME))
 3505 
 3506     @ddt.data({
 3507         'api_response_xml': fake.SNAPSHOT_GET_ITER_UNAVAILABLE_RESPONSE,
 3508         'raised_exception': exception.SnapshotUnavailable,
 3509     }, {
 3510         'api_response_xml': fake.SNAPSHOT_GET_ITER_OTHER_ERROR_RESPONSE,
 3511         'raised_exception': exception.NetAppException,
 3512     })
 3513     @ddt.unpack
 3514     def test_snapshot_exists_error(self, api_response_xml, raised_exception):
 3515 
 3516         api_response = netapp_api.NaElement(api_response_xml)
 3517         self.mock_object(self.client,
 3518                          'send_request',
 3519                          mock.Mock(return_value=api_response))
 3520 
 3521         self.assertRaises(raised_exception,
 3522                           self.client.snapshot_exists,
 3523                           fake.SNAPSHOT_NAME,
 3524                           fake.SHARE_NAME)
 3525 
 3526     def test_get_aggregate_for_volume(self):
 3527 
 3528         api_response = netapp_api.NaElement(
 3529             fake.GET_AGGREGATE_FOR_VOLUME_RESPONSE)
 3530         self.mock_object(self.client,
 3531                          'send_iter_request',
 3532                          mock.Mock(return_value=api_response))
 3533 
 3534         result = self.client.get_aggregate_for_volume(fake.SHARE_NAME)
 3535 
 3536         volume_get_iter_args = {
 3537             'query': {
 3538                 'volume-attributes': {
 3539                     'volume-id-attributes': {
 3540                         'name': fake.SHARE_NAME
 3541                     }
 3542                 }
 3543             },
 3544             'desired-attributes': {
 3545                 'volume-attributes': {
 3546                     'volume-id-attributes': {
 3547                         'containing-aggregate-name': None,
 3548                         'name': None
 3549                     }
 3550                 }
 3551             }
 3552         }
 3553 
 3554         self.client.send_iter_request.assert_has_calls([
 3555             mock.call('volume-get-iter', volume_get_iter_args)])
 3556         self.assertEqual(fake.SHARE_AGGREGATE_NAME, result)
 3557 
 3558     def test_get_aggregate_for_volume_not_found(self):
 3559 
 3560         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3561         self.mock_object(self.client,
 3562                          'send_iter_request',
 3563                          mock.Mock(return_value=api_response))
 3564 
 3565         self.assertRaises(exception.NetAppException,
 3566                           self.client.get_aggregate_for_volume,
 3567                           fake.SHARE_NAME)
 3568 
 3569     def test_volume_has_luns(self):
 3570 
 3571         api_response = netapp_api.NaElement(fake.LUN_GET_ITER_RESPONSE)
 3572         self.mock_object(self.client,
 3573                          'send_iter_request',
 3574                          mock.Mock(return_value=api_response))
 3575 
 3576         result = self.client.volume_has_luns(fake.SHARE_NAME)
 3577 
 3578         lun_get_iter_args = {
 3579             'query': {
 3580                 'lun-info': {
 3581                     'volume': fake.SHARE_NAME,
 3582                 },
 3583             },
 3584             'desired-attributes': {
 3585                 'lun-info': {
 3586                     'path': None,
 3587                 },
 3588             },
 3589         }
 3590 
 3591         self.client.send_iter_request.assert_has_calls([
 3592             mock.call('lun-get-iter', lun_get_iter_args)])
 3593         self.assertTrue(result)
 3594 
 3595     def test_volume_has_luns_not_found(self):
 3596 
 3597         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3598         self.mock_object(self.client,
 3599                          'send_request',
 3600                          mock.Mock(return_value=api_response))
 3601 
 3602         result = self.client.volume_has_luns(fake.SHARE_NAME)
 3603 
 3604         self.assertFalse(result)
 3605 
 3606     def test_volume_has_junctioned_volumes(self):
 3607 
 3608         api_response = netapp_api.NaElement(
 3609             fake.VOLUME_GET_ITER_JUNCTIONED_VOLUMES_RESPONSE)
 3610         self.mock_object(self.client,
 3611                          'send_iter_request',
 3612                          mock.Mock(return_value=api_response))
 3613 
 3614         fake_junction_path = '/%s' % fake.SHARE_NAME
 3615         self.mock_object(self.client,
 3616                          'get_volume_junction_path',
 3617                          mock.Mock(return_value=fake_junction_path))
 3618 
 3619         result = self.client.volume_has_junctioned_volumes(fake.SHARE_NAME)
 3620 
 3621         volume_get_iter_args = {
 3622             'query': {
 3623                 'volume-attributes': {
 3624                     'volume-id-attributes': {
 3625                         'junction-path': fake_junction_path + '/*',
 3626                     },
 3627                 },
 3628             },
 3629             'desired-attributes': {
 3630                 'volume-attributes': {
 3631                     'volume-id-attributes': {
 3632                         'name': None,
 3633                     },
 3634                 },
 3635             },
 3636         }
 3637         self.client.send_iter_request.assert_has_calls([
 3638             mock.call('volume-get-iter', volume_get_iter_args)])
 3639         self.assertTrue(result)
 3640 
 3641     def test_volume_has_junctioned_volumes_no_junction_path(self):
 3642 
 3643         self.mock_object(self.client,
 3644                          'get_volume_junction_path',
 3645                          mock.Mock(return_value=''))
 3646 
 3647         result = self.client.volume_has_junctioned_volumes(fake.SHARE_NAME)
 3648 
 3649         self.assertFalse(result)
 3650 
 3651     def test_volume_has_junctioned_volumes_not_found(self):
 3652 
 3653         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3654         self.mock_object(self.client,
 3655                          'send_request',
 3656                          mock.Mock(return_value=api_response))
 3657 
 3658         fake_junction_path = '/%s' % fake.SHARE_NAME
 3659         self.mock_object(self.client,
 3660                          'get_volume_junction_path',
 3661                          mock.Mock(return_value=fake_junction_path))
 3662 
 3663         result = self.client.volume_has_junctioned_volumes(fake.SHARE_NAME)
 3664 
 3665         self.assertFalse(result)
 3666 
 3667     def test_get_volume(self):
 3668 
 3669         api_response = netapp_api.NaElement(
 3670             fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE)
 3671         self.mock_object(self.client,
 3672                          'send_request',
 3673                          mock.Mock(return_value=api_response))
 3674 
 3675         result = self.client.get_volume(fake.SHARE_NAME)
 3676 
 3677         volume_get_iter_args = {
 3678             'query': {
 3679                 'volume-attributes': {
 3680                     'volume-id-attributes': {
 3681                         'name': fake.SHARE_NAME,
 3682                     },
 3683                 },
 3684             },
 3685             'desired-attributes': {
 3686                 'volume-attributes': {
 3687                     'volume-id-attributes': {
 3688                         'containing-aggregate-name': None,
 3689                         'junction-path': None,
 3690                         'name': None,
 3691                         'owning-vserver-name': None,
 3692                         'type': None,
 3693                         'style': None,
 3694                     },
 3695                     'volume-space-attributes': {
 3696                         'size': None,
 3697                     },
 3698                     'volume-qos-attributes': {
 3699                         'policy-group-name': None,
 3700                     },
 3701                 },
 3702             },
 3703         }
 3704 
 3705         expected = {
 3706             'aggregate': fake.SHARE_AGGREGATE_NAME,
 3707             'junction-path': '/%s' % fake.SHARE_NAME,
 3708             'name': fake.SHARE_NAME,
 3709             'type': 'rw',
 3710             'style': 'flex',
 3711             'size': fake.SHARE_SIZE,
 3712             'owning-vserver-name': fake.VSERVER_NAME,
 3713             'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME,
 3714         }
 3715         self.client.send_request.assert_has_calls([
 3716             mock.call('volume-get-iter', volume_get_iter_args)])
 3717         self.assertDictEqual(expected, result)
 3718 
 3719     def test_get_volume_no_qos(self):
 3720         api_response = netapp_api.NaElement(
 3721             fake.VOLUME_GET_ITER_NO_QOS_RESPONSE)
 3722         self.mock_object(self.client,
 3723                          'send_request',
 3724                          mock.Mock(return_value=api_response))
 3725 
 3726         result = self.client.get_volume(fake.SHARE_NAME)
 3727 
 3728         volume_get_iter_args = {
 3729             'query': {
 3730                 'volume-attributes': {
 3731                     'volume-id-attributes': {
 3732                         'name': fake.SHARE_NAME,
 3733                     },
 3734                 },
 3735             },
 3736             'desired-attributes': {
 3737                 'volume-attributes': {
 3738                     'volume-id-attributes': {
 3739                         'containing-aggregate-name': None,
 3740                         'junction-path': None,
 3741                         'name': None,
 3742                         'owning-vserver-name': None,
 3743                         'type': None,
 3744                         'style': None,
 3745                     },
 3746                     'volume-space-attributes': {
 3747                         'size': None,
 3748                     },
 3749                     'volume-qos-attributes': {
 3750                         'policy-group-name': None,
 3751                     },
 3752                 },
 3753             },
 3754         }
 3755 
 3756         expected = {
 3757             'aggregate': fake.SHARE_AGGREGATE_NAME,
 3758             'junction-path': '/%s' % fake.SHARE_NAME,
 3759             'name': fake.SHARE_NAME,
 3760             'type': 'rw',
 3761             'style': 'flex',
 3762             'size': fake.SHARE_SIZE,
 3763             'owning-vserver-name': fake.VSERVER_NAME,
 3764             'qos-policy-group-name': None,
 3765         }
 3766         self.client.send_request.assert_has_calls([
 3767             mock.call('volume-get-iter', volume_get_iter_args)])
 3768         self.assertDictEqual(expected, result)
 3769 
 3770     def test_get_volume_not_found(self):
 3771 
 3772         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3773         self.mock_object(self.client,
 3774                          'send_request',
 3775                          mock.Mock(return_value=api_response))
 3776 
 3777         self.assertRaises(exception.StorageResourceNotFound,
 3778                           self.client.get_volume,
 3779                           fake.SHARE_NAME)
 3780 
 3781     def test_get_volume_not_unique(self):
 3782 
 3783         api_response = netapp_api.NaElement(
 3784             fake.VOLUME_GET_ITER_NOT_UNIQUE_RESPONSE)
 3785         self.mock_object(self.client,
 3786                          'send_request',
 3787                          mock.Mock(return_value=api_response))
 3788 
 3789         self.assertRaises(exception.NetAppException,
 3790                           self.client.get_volume,
 3791                           fake.SHARE_NAME)
 3792 
 3793     def test_get_volume_at_junction_path(self):
 3794 
 3795         api_response = netapp_api.NaElement(
 3796             fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE)
 3797         self.mock_object(self.client,
 3798                          'send_iter_request',
 3799                          mock.Mock(return_value=api_response))
 3800         fake_junction_path = '/%s' % fake.SHARE_NAME
 3801 
 3802         result = self.client.get_volume_at_junction_path(fake_junction_path)
 3803 
 3804         volume_get_iter_args = {
 3805             'query': {
 3806                 'volume-attributes': {
 3807                     'volume-id-attributes': {
 3808                         'junction-path': fake_junction_path,
 3809                     },
 3810                 },
 3811             },
 3812             'desired-attributes': {
 3813                 'volume-attributes': {
 3814                     'volume-id-attributes': {
 3815                         'containing-aggregate-name': None,
 3816                         'junction-path': None,
 3817                         'name': None,
 3818                         'type': None,
 3819                         'style': None,
 3820                     },
 3821                     'volume-space-attributes': {
 3822                         'size': None,
 3823                     }
 3824                 },
 3825             },
 3826         }
 3827         expected = {
 3828             'aggregate': fake.SHARE_AGGREGATE_NAME,
 3829             'junction-path': fake_junction_path,
 3830             'name': fake.SHARE_NAME,
 3831             'type': 'rw',
 3832             'style': 'flex',
 3833             'size': fake.SHARE_SIZE,
 3834         }
 3835         self.client.send_iter_request.assert_has_calls([
 3836             mock.call('volume-get-iter', volume_get_iter_args)])
 3837         self.assertDictEqual(expected, result)
 3838 
 3839     def test_get_volume_at_junction_path_not_specified(self):
 3840 
 3841         result = self.client.get_volume_at_junction_path(None)
 3842 
 3843         self.assertIsNone(result)
 3844 
 3845     def test_get_volume_at_junction_path_not_found(self):
 3846 
 3847         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3848         self.mock_object(self.client,
 3849                          'send_iter_request',
 3850                          mock.Mock(return_value=api_response))
 3851         fake_junction_path = '/%s' % fake.SHARE_NAME
 3852 
 3853         result = self.client.get_volume_at_junction_path(fake_junction_path)
 3854 
 3855         self.assertIsNone(result)
 3856 
 3857     def test_get_volume_to_manage(self):
 3858 
 3859         api_response = netapp_api.NaElement(
 3860             fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE)
 3861         self.mock_object(self.client,
 3862                          'send_iter_request',
 3863                          mock.Mock(return_value=api_response))
 3864 
 3865         result = self.client.get_volume_to_manage(fake.SHARE_AGGREGATE_NAME,
 3866                                                   fake.SHARE_NAME)
 3867 
 3868         volume_get_iter_args = {
 3869             'query': {
 3870                 'volume-attributes': {
 3871                     'volume-id-attributes': {
 3872                         'containing-aggregate-name': fake.SHARE_AGGREGATE_NAME,
 3873                         'name': fake.SHARE_NAME,
 3874                     },
 3875                 },
 3876             },
 3877             'desired-attributes': {
 3878                 'volume-attributes': {
 3879                     'volume-id-attributes': {
 3880                         'containing-aggregate-name': None,
 3881                         'junction-path': None,
 3882                         'name': None,
 3883                         'type': None,
 3884                         'style': None,
 3885                         'owning-vserver-name': None,
 3886                     },
 3887                     'volume-space-attributes': {
 3888                         'size': None,
 3889                     },
 3890                     'volume-qos-attributes': {
 3891                         'policy-group-name': None,
 3892                     },
 3893                 },
 3894             },
 3895         }
 3896         expected = {
 3897             'aggregate': fake.SHARE_AGGREGATE_NAME,
 3898             'junction-path': '/%s' % fake.SHARE_NAME,
 3899             'name': fake.SHARE_NAME,
 3900             'type': 'rw',
 3901             'style': 'flex',
 3902             'size': fake.SHARE_SIZE,
 3903             'owning-vserver-name': fake.VSERVER_NAME,
 3904             'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME,
 3905         }
 3906         self.client.send_iter_request.assert_has_calls([
 3907             mock.call('volume-get-iter', volume_get_iter_args)])
 3908         self.assertDictEqual(expected, result)
 3909 
 3910     def test_get_volume_to_manage_not_found(self):
 3911 
 3912         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 3913         self.mock_object(self.client,
 3914                          'send_iter_request',
 3915                          mock.Mock(return_value=api_response))
 3916 
 3917         result = self.client.get_volume_to_manage(fake.SHARE_AGGREGATE_NAME,
 3918                                                   fake.SHARE_NAME)
 3919 
 3920         self.assertIsNone(result)
 3921 
 3922     @ddt.data(None, fake.QOS_POLICY_GROUP_NAME)
 3923     def test_create_volume_clone(self, qos_policy_group_name):
 3924 
 3925         self.mock_object(self.client, 'send_request')
 3926         self.mock_object(self.client, 'split_volume_clone')
 3927 
 3928         self.client.create_volume_clone(fake.SHARE_NAME,
 3929                                         fake.PARENT_SHARE_NAME,
 3930                                         fake.PARENT_SNAPSHOT_NAME,
 3931                                         qos_policy_group=qos_policy_group_name)
 3932 
 3933         volume_clone_create_args = {
 3934             'volume': fake.SHARE_NAME,
 3935             'parent-volume': fake.PARENT_SHARE_NAME,
 3936             'parent-snapshot': fake.PARENT_SNAPSHOT_NAME,
 3937             'junction-path': '/%s' % fake.SHARE_NAME
 3938         }
 3939 
 3940         if qos_policy_group_name:
 3941             volume_clone_create_args.update(
 3942                 {'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME})
 3943 
 3944         self.client.send_request.assert_has_calls([
 3945             mock.call('volume-clone-create', volume_clone_create_args)])
 3946         self.assertFalse(self.client.split_volume_clone.called)
 3947 
 3948     @ddt.data(True, False)
 3949     def test_create_volume_clone_split(self, split):
 3950 
 3951         self.mock_object(self.client, 'send_request')
 3952         self.mock_object(self.client, 'split_volume_clone')
 3953 
 3954         self.client.create_volume_clone(fake.SHARE_NAME,
 3955                                         fake.PARENT_SHARE_NAME,
 3956                                         fake.PARENT_SNAPSHOT_NAME,
 3957                                         split=split)
 3958 
 3959         volume_clone_create_args = {
 3960             'volume': fake.SHARE_NAME,
 3961             'parent-volume': fake.PARENT_SHARE_NAME,
 3962             'parent-snapshot': fake.PARENT_SNAPSHOT_NAME,
 3963             'junction-path': '/%s' % fake.SHARE_NAME
 3964         }
 3965 
 3966         self.client.send_request.assert_has_calls([
 3967             mock.call('volume-clone-create', volume_clone_create_args)])
 3968         if split:
 3969             self.client.split_volume_clone.assert_called_once_with(
 3970                 fake.SHARE_NAME)
 3971         else:
 3972             self.assertFalse(self.client.split_volume_clone.called)
 3973 
 3974     @ddt.data(None,
 3975               mock.Mock(side_effect=netapp_api.NaApiError(
 3976                   code=netapp_api.EVOL_CLONE_BEING_SPLIT)))
 3977     def test_split_volume_clone(self, side_effect):
 3978 
 3979         self.mock_object(
 3980             self.client, 'send_request',
 3981             mock.Mock(side_effect=side_effect))
 3982 
 3983         self.client.split_volume_clone(fake.SHARE_NAME)
 3984 
 3985         volume_clone_split_args = {'volume': fake.SHARE_NAME}
 3986 
 3987         self.client.send_request.assert_has_calls([
 3988             mock.call('volume-clone-split-start', volume_clone_split_args)])
 3989 
 3990     def test_split_volume_clone_api_error(self):
 3991 
 3992         self.mock_object(self.client,
 3993                          'send_request',
 3994                          mock.Mock(side_effect=self._mock_api_error()))
 3995 
 3996         self.assertRaises(netapp_api.NaApiError,
 3997                           self.client.split_volume_clone,
 3998                           fake.SHARE_NAME)
 3999 
 4000     def test_get_clone_children_for_snapshot(self):
 4001 
 4002         api_response = netapp_api.NaElement(
 4003             fake.VOLUME_GET_ITER_CLONE_CHILDREN_RESPONSE)
 4004         self.mock_object(self.client,
 4005                          'send_iter_request',
 4006                          mock.Mock(return_value=api_response))
 4007 
 4008         result = self.client.get_clone_children_for_snapshot(
 4009             fake.SHARE_NAME, fake.SNAPSHOT_NAME)
 4010 
 4011         volume_get_iter_args = {
 4012             'query': {
 4013                 'volume-attributes': {
 4014                     'volume-clone-attributes': {
 4015                         'volume-clone-parent-attributes': {
 4016                             'name': fake.SHARE_NAME,
 4017                             'snapshot-name': fake.SNAPSHOT_NAME,
 4018                         },
 4019                     },
 4020                 },
 4021             },
 4022             'desired-attributes': {
 4023                 'volume-attributes': {
 4024                     'volume-id-attributes': {
 4025                         'name': None,
 4026                     },
 4027                 },
 4028             },
 4029         }
 4030         self.client.send_iter_request.assert_has_calls([
 4031             mock.call('volume-get-iter', volume_get_iter_args)])
 4032 
 4033         expected = [
 4034             {'name': fake.CLONE_CHILD_1},
 4035             {'name': fake.CLONE_CHILD_2},
 4036         ]
 4037         self.assertEqual(expected, result)
 4038 
 4039     def test_get_clone_children_for_snapshot_not_found(self):
 4040 
 4041         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 4042         self.mock_object(self.client,
 4043                          'send_iter_request',
 4044                          mock.Mock(return_value=api_response))
 4045 
 4046         result = self.client.get_clone_children_for_snapshot(
 4047             fake.SHARE_NAME, fake.SNAPSHOT_NAME)
 4048 
 4049         self.assertEqual([], result)
 4050 
 4051     def test_get_volume_junction_path(self):
 4052 
 4053         api_response = netapp_api.NaElement(
 4054             fake.VOLUME_GET_VOLUME_PATH_RESPONSE)
 4055         self.mock_object(self.client,
 4056                          'send_request',
 4057                          mock.Mock(return_value=api_response))
 4058 
 4059         result = self.client.get_volume_junction_path(fake.SHARE_NAME)
 4060 
 4061         volume_get_volume_path_args = {
 4062             'volume': fake.SHARE_NAME,
 4063             'is-style-cifs': 'false'
 4064         }
 4065 
 4066         self.client.send_request.assert_has_calls([
 4067             mock.call('volume-get-volume-path', volume_get_volume_path_args)])
 4068         self.assertEqual(fake.VOLUME_JUNCTION_PATH, result)
 4069 
 4070     def test_get_volume_junction_path_cifs(self):
 4071 
 4072         api_response = netapp_api.NaElement(
 4073             fake.VOLUME_GET_VOLUME_PATH_CIFS_RESPONSE)
 4074         self.mock_object(self.client,
 4075                          'send_request',
 4076                          mock.Mock(return_value=api_response))
 4077 
 4078         result = self.client.get_volume_junction_path(fake.SHARE_NAME,
 4079                                                       is_style_cifs=True)
 4080 
 4081         volume_get_volume_path_args = {
 4082             'volume': fake.SHARE_NAME,
 4083             'is-style-cifs': 'true'
 4084         }
 4085 
 4086         self.client.send_request.assert_has_calls([
 4087             mock.call('volume-get-volume-path', volume_get_volume_path_args)])
 4088         self.assertEqual(fake.VOLUME_JUNCTION_PATH_CIFS, result)
 4089 
 4090     def test_mount_volume_default_junction_path(self):
 4091 
 4092         self.mock_object(self.client, 'send_request')
 4093 
 4094         self.client.mount_volume(fake.SHARE_NAME)
 4095 
 4096         volume_mount_args = {
 4097             'volume-name': fake.SHARE_NAME,
 4098             'junction-path': '/%s' % fake.SHARE_NAME,
 4099         }
 4100 
 4101         self.client.send_request.assert_has_calls([
 4102             mock.call('volume-mount', volume_mount_args)])
 4103 
 4104     def test_mount_volume(self):
 4105 
 4106         self.mock_object(self.client, 'send_request')
 4107         fake_path = '/fake_path'
 4108 
 4109         self.client.mount_volume(fake.SHARE_NAME, junction_path=fake_path)
 4110 
 4111         volume_mount_args = {
 4112             'volume-name': fake.SHARE_NAME,
 4113             'junction-path': fake_path,
 4114         }
 4115 
 4116         self.client.send_request.assert_has_calls([
 4117             mock.call('volume-mount', volume_mount_args)])
 4118 
 4119     def test_offline_volume(self):
 4120 
 4121         self.mock_object(self.client, 'send_request')
 4122 
 4123         self.client.offline_volume(fake.SHARE_NAME)
 4124 
 4125         volume_offline_args = {'name': fake.SHARE_NAME}
 4126 
 4127         self.client.send_request.assert_has_calls([
 4128             mock.call('volume-offline', volume_offline_args)])
 4129 
 4130     def test_offline_volume_already_offline(self):
 4131 
 4132         self.mock_object(self.client,
 4133                          'send_request',
 4134                          mock.Mock(side_effect=self._mock_api_error(
 4135                              netapp_api.EVOLUMEOFFLINE)))
 4136 
 4137         self.client.offline_volume(fake.SHARE_NAME)
 4138 
 4139         volume_offline_args = {'name': fake.SHARE_NAME}
 4140 
 4141         self.client.send_request.assert_has_calls([
 4142             mock.call('volume-offline', volume_offline_args)])
 4143 
 4144     def test_offline_volume_api_error(self):
 4145 
 4146         self.mock_object(self.client,
 4147                          'send_request',
 4148                          mock.Mock(side_effect=self._mock_api_error()))
 4149 
 4150         self.assertRaises(netapp_api.NaApiError,
 4151                           self.client.offline_volume,
 4152                           fake.SHARE_NAME)
 4153 
 4154     def test__unmount_volume(self):
 4155 
 4156         self.mock_object(self.client, 'send_request')
 4157 
 4158         self.client._unmount_volume(fake.SHARE_NAME)
 4159 
 4160         volume_unmount_args = {
 4161             'volume-name': fake.SHARE_NAME,
 4162             'force': 'false'
 4163         }
 4164 
 4165         self.client.send_request.assert_has_calls([
 4166             mock.call('volume-unmount', volume_unmount_args)])
 4167 
 4168     def test__unmount_volume_force(self):
 4169 
 4170         self.mock_object(self.client, 'send_request')
 4171 
 4172         self.client._unmount_volume(fake.SHARE_NAME, force=True)
 4173 
 4174         volume_unmount_args = {'volume-name': fake.SHARE_NAME, 'force': 'true'}
 4175 
 4176         self.client.send_request.assert_has_calls([
 4177             mock.call('volume-unmount', volume_unmount_args)])
 4178 
 4179     def test__unmount_volume_already_unmounted(self):
 4180 
 4181         self.mock_object(self.client,
 4182                          'send_request',
 4183                          mock.Mock(side_effect=self._mock_api_error(
 4184                              netapp_api.EVOL_NOT_MOUNTED)))
 4185 
 4186         self.client._unmount_volume(fake.SHARE_NAME, force=True)
 4187 
 4188         volume_unmount_args = {'volume-name': fake.SHARE_NAME, 'force': 'true'}
 4189 
 4190         self.client.send_request.assert_has_calls([
 4191             mock.call('volume-unmount', volume_unmount_args)])
 4192 
 4193     def test__unmount_volume_api_error(self):
 4194 
 4195         self.mock_object(self.client,
 4196                          'send_request',
 4197                          mock.Mock(side_effect=self._mock_api_error()))
 4198 
 4199         self.assertRaises(netapp_api.NaApiError,
 4200                           self.client._unmount_volume,
 4201                           fake.SHARE_NAME,
 4202                           force=True)
 4203 
 4204     def test_unmount_volume(self):
 4205 
 4206         self.mock_object(self.client, '_unmount_volume')
 4207 
 4208         self.client.unmount_volume(fake.SHARE_NAME)
 4209 
 4210         self.client._unmount_volume.assert_called_once_with(fake.SHARE_NAME,
 4211                                                             force=False)
 4212         self.assertEqual(1, client_cmode.LOG.debug.call_count)
 4213         self.assertEqual(0, client_cmode.LOG.warning.call_count)
 4214 
 4215     def test_unmount_volume_api_error(self):
 4216 
 4217         self.mock_object(self.client,
 4218                          '_unmount_volume',
 4219                          self._mock_api_error())
 4220 
 4221         self.assertRaises(netapp_api.NaApiError,
 4222                           self.client.unmount_volume,
 4223                           fake.SHARE_NAME)
 4224 
 4225         self.assertEqual(1, self.client._unmount_volume.call_count)
 4226         self.assertEqual(0, client_cmode.LOG.debug.call_count)
 4227         self.assertEqual(0, client_cmode.LOG.warning.call_count)
 4228 
 4229     def test_unmount_volume_with_retries(self):
 4230 
 4231         side_effect = [netapp_api.NaApiError(code=netapp_api.EAPIERROR,
 4232                                              message='...job ID...')] * 5
 4233         side_effect.append(None)
 4234         self.mock_object(self.client,
 4235                          '_unmount_volume',
 4236                          mock.Mock(side_effect=side_effect))
 4237         self.mock_object(time, 'sleep')
 4238 
 4239         self.client.unmount_volume(fake.SHARE_NAME)
 4240 
 4241         self.assertEqual(6, self.client._unmount_volume.call_count)
 4242         self.assertEqual(1, client_cmode.LOG.debug.call_count)
 4243         self.assertEqual(5, client_cmode.LOG.warning.call_count)
 4244 
 4245     def test_unmount_volume_with_max_retries(self):
 4246 
 4247         side_effect = [netapp_api.NaApiError(code=netapp_api.EAPIERROR,
 4248                                              message='...job ID...')] * 30
 4249         self.mock_object(self.client,
 4250                          '_unmount_volume',
 4251                          mock.Mock(side_effect=side_effect))
 4252         self.mock_object(time, 'sleep')
 4253 
 4254         self.assertRaises(exception.NetAppException,
 4255                           self.client.unmount_volume,
 4256                           fake.SHARE_NAME)
 4257 
 4258         self.assertEqual(10, self.client._unmount_volume.call_count)
 4259         self.assertEqual(0, client_cmode.LOG.debug.call_count)
 4260         self.assertEqual(10, client_cmode.LOG.warning.call_count)
 4261 
 4262     def test_delete_volume(self):
 4263 
 4264         self.mock_object(self.client, 'send_request')
 4265 
 4266         self.client.delete_volume(fake.SHARE_NAME)
 4267 
 4268         volume_destroy_args = {'name': fake.SHARE_NAME}
 4269 
 4270         self.client.send_request.assert_has_calls([
 4271             mock.call('volume-destroy', volume_destroy_args)])
 4272 
 4273     def test_create_snapshot(self):
 4274 
 4275         self.mock_object(self.client, 'send_request')
 4276 
 4277         self.client.create_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
 4278 
 4279         snapshot_create_args = {
 4280             'volume': fake.SHARE_NAME,
 4281             'snapshot': fake.SNAPSHOT_NAME
 4282         }
 4283 
 4284         self.client.send_request.assert_has_calls([
 4285             mock.call('snapshot-create', snapshot_create_args)])
 4286 
 4287     @ddt.data({
 4288         'mock_return': fake.SNAPSHOT_GET_ITER_NOT_BUSY_RESPONSE,
 4289         'expected': {
 4290             'access-time': fake.SNAPSHOT_ACCESS_TIME,
 4291             'name': fake.SNAPSHOT_NAME,
 4292             'volume': fake.SHARE_NAME,
 4293             'busy': False,
 4294             'owners': set(),
 4295         }
 4296     }, {
 4297         'mock_return': fake.SNAPSHOT_GET_ITER_BUSY_RESPONSE,
 4298         'expected': {
 4299             'access-time': fake.SNAPSHOT_ACCESS_TIME,
 4300             'name': fake.SNAPSHOT_NAME,
 4301             'volume': fake.SHARE_NAME,
 4302             'busy': True,
 4303             'owners': {'volume clone'},
 4304         }
 4305     })
 4306     @ddt.unpack
 4307     def test_get_snapshot(self, mock_return, expected):
 4308 
 4309         api_response = netapp_api.NaElement(mock_return)
 4310         self.mock_object(self.client,
 4311                          'send_request',
 4312                          mock.Mock(return_value=api_response))
 4313 
 4314         result = self.client.get_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
 4315 
 4316         snapshot_get_iter_args = {
 4317             'query': {
 4318                 'snapshot-info': {
 4319                     'name': fake.SNAPSHOT_NAME,
 4320                     'volume': fake.SHARE_NAME,
 4321                 },
 4322             },
 4323             'desired-attributes': {
 4324                 'snapshot-info': {
 4325                     'access-time': None,
 4326                     'name': None,
 4327                     'volume': None,
 4328                     'busy': None,
 4329                     'snapshot-owners-list': {
 4330                         'snapshot-owner': None,
 4331                     }
 4332                 },
 4333             },
 4334         }
 4335         self.client.send_request.assert_has_calls([
 4336             mock.call('snapshot-get-iter', snapshot_get_iter_args)])
 4337         self.assertDictEqual(expected, result)
 4338 
 4339     @ddt.data({
 4340         'api_response_xml': fake.NO_RECORDS_RESPONSE,
 4341         'raised_exception': exception.SnapshotResourceNotFound,
 4342     }, {
 4343         'api_response_xml': fake.SNAPSHOT_GET_ITER_NOT_UNIQUE_RESPONSE,
 4344         'raised_exception': exception.NetAppException,
 4345     }, {
 4346         'api_response_xml': fake.SNAPSHOT_GET_ITER_UNAVAILABLE_RESPONSE,
 4347         'raised_exception': exception.SnapshotUnavailable,
 4348     }, {
 4349         'api_response_xml': fake.SNAPSHOT_GET_ITER_OTHER_ERROR_RESPONSE,
 4350         'raised_exception': exception.NetAppException,
 4351     })
 4352     @ddt.unpack
 4353     def test_get_snapshot_error(self, api_response_xml, raised_exception):
 4354 
 4355         api_response = netapp_api.NaElement(api_response_xml)
 4356         self.mock_object(self.client,
 4357                          'send_request',
 4358                          mock.Mock(return_value=api_response))
 4359 
 4360         self.assertRaises(raised_exception,
 4361                           self.client.get_snapshot,
 4362                           fake.SHARE_NAME,
 4363                           fake.SNAPSHOT_NAME)
 4364 
 4365     def test_rename_snapshot(self):
 4366 
 4367         self.mock_object(self.client, 'send_request')
 4368 
 4369         self.client.rename_snapshot(fake.SHARE_NAME,
 4370                                     fake.SNAPSHOT_NAME,
 4371                                     'new_snapshot_name')
 4372 
 4373         snapshot_rename_args = {
 4374             'volume': fake.SHARE_NAME,
 4375             'current-name': fake.SNAPSHOT_NAME,
 4376             'new-name': 'new_snapshot_name'
 4377         }
 4378         self.client.send_request.assert_has_calls([
 4379             mock.call('snapshot-rename', snapshot_rename_args)])
 4380 
 4381     def test_restore_snapshot(self):
 4382 
 4383         self.mock_object(self.client, 'send_request')
 4384 
 4385         self.client.restore_snapshot(fake.SHARE_NAME,
 4386                                      fake.SNAPSHOT_NAME)
 4387 
 4388         snapshot_restore_args = {
 4389             'volume': fake.SHARE_NAME,
 4390             'snapshot': fake.SNAPSHOT_NAME,
 4391         }
 4392         self.client.send_request.assert_has_calls([
 4393             mock.call('snapshot-restore-volume', snapshot_restore_args)])
 4394 
 4395     @ddt.data(True, False)
 4396     def test_delete_snapshot(self, ignore_owners):
 4397 
 4398         self.mock_object(self.client, 'send_request')
 4399 
 4400         self.client.delete_snapshot(
 4401             fake.SHARE_NAME, fake.SNAPSHOT_NAME, ignore_owners=ignore_owners)
 4402 
 4403         snapshot_delete_args = {
 4404             'volume': fake.SHARE_NAME,
 4405             'snapshot': fake.SNAPSHOT_NAME,
 4406             'ignore-owners': 'true' if ignore_owners else 'false',
 4407         }
 4408 
 4409         self.client.send_request.assert_has_calls([
 4410             mock.call('snapshot-delete', snapshot_delete_args)])
 4411 
 4412     def test_soft_delete_snapshot(self):
 4413 
 4414         mock_delete_snapshot = self.mock_object(self.client, 'delete_snapshot')
 4415         mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot')
 4416 
 4417         self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
 4418 
 4419         mock_delete_snapshot.assert_called_once_with(
 4420             fake.SHARE_NAME, fake.SNAPSHOT_NAME)
 4421         self.assertFalse(mock_rename_snapshot.called)
 4422 
 4423     def test_soft_delete_snapshot_api_error(self):
 4424 
 4425         mock_delete_snapshot = self.mock_object(
 4426             self.client, 'delete_snapshot', self._mock_api_error())
 4427         mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot')
 4428 
 4429         self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
 4430 
 4431         mock_delete_snapshot.assert_called_once_with(
 4432             fake.SHARE_NAME, fake.SNAPSHOT_NAME)
 4433         mock_rename_snapshot.assert_called_once_with(
 4434             fake.SHARE_NAME, fake.SNAPSHOT_NAME,
 4435             'deleted_manila_' + fake.SNAPSHOT_NAME)
 4436 
 4437     def test_prune_deleted_snapshots(self):
 4438 
 4439         deleted_snapshots_map = {
 4440             'vserver1': [{
 4441                 'name': 'deleted_snap_1',
 4442                 'volume': 'fake_volume_1',
 4443                 'vserver': 'vserver1',
 4444             }],
 4445             'vserver2': [{
 4446                 'name': 'deleted_snap_2',
 4447                 'volume': 'fake_volume_2',
 4448                 'vserver': 'vserver2',
 4449             }],
 4450         }
 4451         mock_get_deleted_snapshots = self.mock_object(
 4452             self.client, '_get_deleted_snapshots',
 4453             mock.Mock(return_value=deleted_snapshots_map))
 4454         mock_delete_snapshot = self.mock_object(
 4455             self.client, 'delete_snapshot',
 4456             mock.Mock(side_effect=[None, netapp_api.NaApiError]))
 4457         self.mock_object(
 4458             copy, 'deepcopy', mock.Mock(return_value=self.client))
 4459 
 4460         self.client.prune_deleted_snapshots()
 4461 
 4462         mock_get_deleted_snapshots.assert_called_once_with()
 4463         mock_delete_snapshot.assert_has_calls([
 4464             mock.call('fake_volume_1', 'deleted_snap_1'),
 4465             mock.call('fake_volume_2', 'deleted_snap_2'),
 4466         ], any_order=True)
 4467 
 4468     def test_get_deleted_snapshots(self):
 4469 
 4470         api_response = netapp_api.NaElement(
 4471             fake.SNAPSHOT_GET_ITER_DELETED_RESPONSE)
 4472         self.mock_object(self.client,
 4473                          'send_iter_request',
 4474                          mock.Mock(return_value=api_response))
 4475 
 4476         result = self.client._get_deleted_snapshots()
 4477 
 4478         snapshot_get_iter_args = {
 4479             'query': {
 4480                 'snapshot-info': {
 4481                     'name': 'deleted_manila_*',
 4482                     'busy': 'false',
 4483                 },
 4484             },
 4485             'desired-attributes': {
 4486                 'snapshot-info': {
 4487                     'name': None,
 4488                     'vserver': None,
 4489                     'volume': None,
 4490                 },
 4491             },
 4492         }
 4493         self.client.send_iter_request.assert_has_calls([
 4494             mock.call('snapshot-get-iter', snapshot_get_iter_args)])
 4495 
 4496         expected = {
 4497             fake.VSERVER_NAME: [{
 4498                 'name': 'deleted_manila_' + fake.SNAPSHOT_NAME,
 4499                 'volume': fake.SHARE_NAME,
 4500                 'vserver': fake.VSERVER_NAME,
 4501             }],
 4502         }
 4503         self.assertDictEqual(expected, result)
 4504 
 4505     def test_create_cg_snapshot(self):
 4506 
 4507         mock_start_cg_snapshot = self.mock_object(
 4508             self.client, '_start_cg_snapshot',
 4509             mock.Mock(return_value=fake.CG_SNAPSHOT_ID))
 4510         mock_commit_cg_snapshot = self.mock_object(
 4511             self.client, '_commit_cg_snapshot')
 4512 
 4513         self.client.create_cg_snapshot([fake.SHARE_NAME, fake.SHARE_NAME_2],
 4514                                        fake.SNAPSHOT_NAME)
 4515 
 4516         mock_start_cg_snapshot.assert_called_once_with(
 4517             [fake.SHARE_NAME, fake.SHARE_NAME_2], fake.SNAPSHOT_NAME)
 4518         mock_commit_cg_snapshot.assert_called_once_with(fake.CG_SNAPSHOT_ID)
 4519 
 4520     def test_create_cg_snapshot_no_id(self):
 4521 
 4522         mock_start_cg_snapshot = self.mock_object(
 4523             self.client, '_start_cg_snapshot', mock.Mock(return_value=None))
 4524         mock_commit_cg_snapshot = self.mock_object(
 4525             self.client, '_commit_cg_snapshot')
 4526 
 4527         self.assertRaises(exception.NetAppException,
 4528                           self.client.create_cg_snapshot,
 4529                           [fake.SHARE_NAME, fake.SHARE_NAME_2],
 4530                           fake.SNAPSHOT_NAME)
 4531 
 4532         mock_start_cg_snapshot.assert_called_once_with(
 4533             [fake.SHARE_NAME, fake.SHARE_NAME_2], fake.SNAPSHOT_NAME)
 4534         self.assertFalse(mock_commit_cg_snapshot.called)
 4535 
 4536     def test_start_cg_snapshot(self):
 4537 
 4538         self.mock_object(self.client, 'send_request')
 4539 
 4540         self.client._start_cg_snapshot([fake.SHARE_NAME, fake.SHARE_NAME_2],
 4541                                        fake.SNAPSHOT_NAME)
 4542 
 4543         cg_start_args = {
 4544             'snapshot': fake.SNAPSHOT_NAME,
 4545             'timeout': 'relaxed',
 4546             'volumes': [
 4547                 {'volume-name': fake.SHARE_NAME},
 4548                 {'volume-name': fake.SHARE_NAME_2},
 4549             ],
 4550         }
 4551 
 4552         self.client.send_request.assert_has_calls([
 4553             mock.call('cg-start', cg_start_args)])
 4554 
 4555     def test_commit_cg_snapshot(self):
 4556 
 4557         self.mock_object(self.client, 'send_request')
 4558 
 4559         self.client._commit_cg_snapshot(fake.CG_SNAPSHOT_ID)
 4560 
 4561         cg_commit_args = {'cg-id': fake.CG_SNAPSHOT_ID}
 4562 
 4563         self.client.send_request.assert_has_calls([
 4564             mock.call('cg-commit', cg_commit_args)])
 4565 
 4566     def test_create_cifs_share(self):
 4567 
 4568         self.mock_object(self.client, 'send_request')
 4569 
 4570         self.client.create_cifs_share(fake.SHARE_NAME)
 4571 
 4572         cifs_share_create_args = {
 4573             'path': '/%s' % fake.SHARE_NAME,
 4574             'share-name': fake.SHARE_NAME
 4575         }
 4576 
 4577         self.client.send_request.assert_has_calls([
 4578             mock.call('cifs-share-create', cifs_share_create_args)])
 4579 
 4580     def test_get_cifs_share_access(self):
 4581 
 4582         api_response = netapp_api.NaElement(
 4583             fake.CIFS_SHARE_ACCESS_CONTROL_GET_ITER)
 4584         self.mock_object(self.client,
 4585                          'send_iter_request',
 4586                          mock.Mock(return_value=api_response))
 4587 
 4588         result = self.client.get_cifs_share_access(fake.SHARE_NAME)
 4589 
 4590         cifs_share_access_control_get_iter_args = {
 4591             'query': {
 4592                 'cifs-share-access-control': {
 4593                     'share': fake.SHARE_NAME,
 4594                 },
 4595             },
 4596             'desired-attributes': {
 4597                 'cifs-share-access-control': {
 4598                     'user-or-group': None,
 4599                     'permission': None,
 4600                 },
 4601             },
 4602         }
 4603         self.client.send_iter_request.assert_has_calls([
 4604             mock.call('cifs-share-access-control-get-iter',
 4605                       cifs_share_access_control_get_iter_args)])
 4606 
 4607         expected = {
 4608             'Administrator': 'full_control',
 4609             'Administrators': 'change',
 4610             'Power Users': 'read',
 4611             'Users': 'no_access',
 4612         }
 4613         self.assertDictEqual(expected, result)
 4614 
 4615     def test_get_cifs_share_access_not_found(self):
 4616 
 4617         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 4618         self.mock_object(self.client,
 4619                          'send_iter_request',
 4620                          mock.Mock(return_value=api_response))
 4621 
 4622         result = self.client.get_cifs_share_access(fake.SHARE_NAME)
 4623 
 4624         self.assertEqual({}, result)
 4625 
 4626     @ddt.data(True, False)
 4627     def test_add_cifs_share_access(self, readonly):
 4628 
 4629         self.mock_object(self.client, 'send_request')
 4630 
 4631         self.client.add_cifs_share_access(fake.SHARE_NAME,
 4632                                           fake.USER_NAME,
 4633                                           readonly)
 4634 
 4635         cifs_share_access_control_create_args = {
 4636             'permission': 'read' if readonly else 'full_control',
 4637             'share': fake.SHARE_NAME,
 4638             'user-or-group': fake.USER_NAME
 4639         }
 4640 
 4641         self.client.send_request.assert_has_calls([
 4642             mock.call(
 4643                 'cifs-share-access-control-create',
 4644                 cifs_share_access_control_create_args)])
 4645 
 4646     @ddt.data(True, False)
 4647     def test_modify_cifs_share_access(self, readonly):
 4648 
 4649         self.mock_object(self.client, 'send_request')
 4650 
 4651         self.client.modify_cifs_share_access(fake.SHARE_NAME,
 4652                                              fake.USER_NAME,
 4653                                              readonly)
 4654 
 4655         cifs_share_access_control_modify_args = {
 4656             'permission': 'read' if readonly else 'full_control',
 4657             'share': fake.SHARE_NAME,
 4658             'user-or-group': fake.USER_NAME
 4659         }
 4660 
 4661         self.client.send_request.assert_has_calls([
 4662             mock.call(
 4663                 'cifs-share-access-control-modify',
 4664                 cifs_share_access_control_modify_args)])
 4665 
 4666     def test_remove_cifs_share_access(self):
 4667 
 4668         self.mock_object(self.client, 'send_request')
 4669 
 4670         self.client.remove_cifs_share_access(fake.SHARE_NAME, fake.USER_NAME)
 4671 
 4672         cifs_share_access_control_delete_args = {
 4673             'user-or-group': fake.USER_NAME,
 4674             'share': fake.SHARE_NAME
 4675         }
 4676 
 4677         self.client.send_request.assert_has_calls([
 4678             mock.call(
 4679                 'cifs-share-access-control-delete',
 4680                 cifs_share_access_control_delete_args)])
 4681 
 4682     def test_remove_cifs_share(self):
 4683 
 4684         self.mock_object(self.client, 'send_request')
 4685 
 4686         self.client.remove_cifs_share(fake.SHARE_NAME)
 4687 
 4688         cifs_share_delete_args = {'share-name': fake.SHARE_NAME}
 4689 
 4690         self.client.send_request.assert_has_calls([
 4691             mock.call('cifs-share-delete', cifs_share_delete_args)])
 4692 
 4693     def test_add_nfs_export_rule(self):
 4694 
 4695         mock_get_nfs_export_rule_indices = self.mock_object(
 4696             self.client, '_get_nfs_export_rule_indices',
 4697             mock.Mock(return_value=[]))
 4698         mock_add_nfs_export_rule = self.mock_object(
 4699             self.client, '_add_nfs_export_rule')
 4700         mock_update_nfs_export_rule = self.mock_object(
 4701             self.client, '_update_nfs_export_rule')
 4702 
 4703         self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
 4704                                         fake.IP_ADDRESS,
 4705                                         False)
 4706 
 4707         mock_get_nfs_export_rule_indices.assert_called_once_with(
 4708             fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
 4709         mock_add_nfs_export_rule.assert_called_once_with(
 4710             fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False)
 4711         self.assertFalse(mock_update_nfs_export_rule.called)
 4712 
 4713     def test_add_nfs_export_rule_single_existing(self):
 4714 
 4715         mock_get_nfs_export_rule_indices = self.mock_object(
 4716             self.client, '_get_nfs_export_rule_indices',
 4717             mock.Mock(return_value=['1']))
 4718         mock_add_nfs_export_rule = self.mock_object(
 4719             self.client, '_add_nfs_export_rule')
 4720         mock_update_nfs_export_rule = self.mock_object(
 4721             self.client, '_update_nfs_export_rule')
 4722         mock_remove_nfs_export_rules = self.mock_object(
 4723             self.client, '_remove_nfs_export_rules')
 4724 
 4725         self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
 4726                                         fake.IP_ADDRESS,
 4727                                         False)
 4728 
 4729         mock_get_nfs_export_rule_indices.assert_called_once_with(
 4730             fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
 4731         self.assertFalse(mock_add_nfs_export_rule.called)
 4732         mock_update_nfs_export_rule.assert_called_once_with(
 4733             fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False, '1')
 4734         mock_remove_nfs_export_rules.assert_called_once_with(
 4735             fake.EXPORT_POLICY_NAME, [])
 4736 
 4737     def test_add_nfs_export_rule_multiple_existing(self):
 4738 
 4739         mock_get_nfs_export_rule_indices = self.mock_object(
 4740             self.client, '_get_nfs_export_rule_indices',
 4741             mock.Mock(return_value=['2', '4', '6']))
 4742         mock_add_nfs_export_rule = self.mock_object(
 4743             self.client, '_add_nfs_export_rule')
 4744         mock_update_nfs_export_rule = self.mock_object(
 4745             self.client, '_update_nfs_export_rule')
 4746         mock_remove_nfs_export_rules = self.mock_object(
 4747             self.client, '_remove_nfs_export_rules')
 4748 
 4749         self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
 4750                                         fake.IP_ADDRESS,
 4751                                         False)
 4752 
 4753         mock_get_nfs_export_rule_indices.assert_called_once_with(
 4754             fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
 4755         self.assertFalse(mock_add_nfs_export_rule.called)
 4756         mock_update_nfs_export_rule.assert_called_once_with(
 4757             fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False, '2')
 4758         mock_remove_nfs_export_rules.assert_called_once_with(
 4759             fake.EXPORT_POLICY_NAME, ['4', '6'])
 4760 
 4761     @ddt.data({'readonly': False, 'rw_security_flavor': 'sys'},
 4762               {'readonly': True, 'rw_security_flavor': 'never'})
 4763     @ddt.unpack
 4764     def test__add_nfs_export_rule(self, readonly, rw_security_flavor):
 4765 
 4766         self.mock_object(self.client, 'send_request')
 4767 
 4768         self.client._add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
 4769                                          fake.IP_ADDRESS,
 4770                                          readonly)
 4771 
 4772         export_rule_create_args = {
 4773             'policy-name': fake.EXPORT_POLICY_NAME,
 4774             'client-match': fake.IP_ADDRESS,
 4775             'ro-rule': {
 4776                 'security-flavor': 'sys',
 4777             },
 4778             'rw-rule': {
 4779                 'security-flavor': rw_security_flavor,
 4780             },
 4781             'super-user-security': {
 4782                 'security-flavor': 'sys',
 4783             },
 4784         }
 4785         self.client.send_request.assert_has_calls(
 4786             [mock.call('export-rule-create', export_rule_create_args)])
 4787 
 4788     @ddt.data({'readonly': False, 'rw_security_flavor': 'sys', 'index': '2'},
 4789               {'readonly': True, 'rw_security_flavor': 'never', 'index': '4'})
 4790     @ddt.unpack
 4791     def test_update_nfs_export_rule(self, readonly, rw_security_flavor, index):
 4792 
 4793         self.mock_object(self.client, 'send_request')
 4794         self.client._update_nfs_export_rule(fake.EXPORT_POLICY_NAME,
 4795                                             fake.IP_ADDRESS,
 4796                                             readonly,
 4797                                             index)
 4798 
 4799         export_rule_modify_args = {
 4800             'policy-name': fake.EXPORT_POLICY_NAME,
 4801             'rule-index': index,
 4802             'client-match': fake.IP_ADDRESS,
 4803             'ro-rule': {
 4804                 'security-flavor': 'sys',
 4805             },
 4806             'rw-rule': {
 4807                 'security-flavor': rw_security_flavor,
 4808             },
 4809             'super-user-security': {
 4810                 'security-flavor': 'sys',
 4811             },
 4812         }
 4813 
 4814         self.client.send_request.assert_has_calls(
 4815             [mock.call('export-rule-modify', export_rule_modify_args)])
 4816 
 4817     def test_get_nfs_export_rule_indices(self):
 4818 
 4819         api_response = netapp_api.NaElement(fake.EXPORT_RULE_GET_ITER_RESPONSE)
 4820         self.mock_object(self.client,
 4821                          'send_iter_request',
 4822                          mock.Mock(return_value=api_response))
 4823 
 4824         result = self.client._get_nfs_export_rule_indices(
 4825             fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
 4826 
 4827         export_rule_get_iter_args = {
 4828             'query': {
 4829                 'export-rule-info': {
 4830                     'policy-name': fake.EXPORT_POLICY_NAME,
 4831                     'client-match': fake.IP_ADDRESS,
 4832                 },
 4833             },
 4834             'desired-attributes': {
 4835                 'export-rule-info': {
 4836                     'vserver-name': None,
 4837                     'policy-name': None,
 4838                     'client-match': None,
 4839                     'rule-index': None,
 4840                 },
 4841             },
 4842         }
 4843         self.assertListEqual(['1', '3'], result)
 4844         self.client.send_iter_request.assert_has_calls([
 4845             mock.call('export-rule-get-iter', export_rule_get_iter_args)])
 4846 
 4847     def test_remove_nfs_export_rule(self):
 4848 
 4849         fake_indices = ['1', '3', '4']
 4850         mock_get_nfs_export_rule_indices = self.mock_object(
 4851             self.client, '_get_nfs_export_rule_indices',
 4852             mock.Mock(return_value=fake_indices))
 4853         mock_remove_nfs_export_rules = self.mock_object(
 4854             self.client, '_remove_nfs_export_rules')
 4855 
 4856         self.client.remove_nfs_export_rule(fake.EXPORT_POLICY_NAME,
 4857                                            fake.IP_ADDRESS)
 4858 
 4859         mock_get_nfs_export_rule_indices.assert_called_once_with(
 4860             fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
 4861         mock_remove_nfs_export_rules.assert_called_once_with(
 4862             fake.EXPORT_POLICY_NAME, fake_indices)
 4863 
 4864     def test_remove_nfs_export_rules(self):
 4865 
 4866         fake_indices = ['1', '3']
 4867         self.mock_object(self.client, 'send_request')
 4868 
 4869         self.client._remove_nfs_export_rules(fake.EXPORT_POLICY_NAME,
 4870                                              fake_indices)
 4871 
 4872         self.client.send_request.assert_has_calls([
 4873             mock.call(
 4874                 'export-rule-destroy',
 4875                 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '1'}),
 4876             mock.call(
 4877                 'export-rule-destroy',
 4878                 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '3'})])
 4879 
 4880     def test_remove_nfs_export_rules_not_found(self):
 4881 
 4882         self.mock_object(self.client,
 4883                          'send_request',
 4884                          self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND))
 4885 
 4886         self.client._remove_nfs_export_rules(fake.EXPORT_POLICY_NAME, ['1'])
 4887 
 4888         self.client.send_request.assert_has_calls([
 4889             mock.call(
 4890                 'export-rule-destroy',
 4891                 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '1'})])
 4892 
 4893     def test_remove_nfs_export_rules_api_error(self):
 4894 
 4895         self.mock_object(self.client, 'send_request', self._mock_api_error())
 4896 
 4897         self.assertRaises(netapp_api.NaApiError,
 4898                           self.client._remove_nfs_export_rules,
 4899                           fake.EXPORT_POLICY_NAME,
 4900                           ['1'])
 4901 
 4902     def test_clear_nfs_export_policy_for_volume(self):
 4903 
 4904         mock_set_nfs_export_policy_for_volume = self.mock_object(
 4905             self.client, 'set_nfs_export_policy_for_volume')
 4906 
 4907         self.client.clear_nfs_export_policy_for_volume(fake.SHARE_NAME)
 4908 
 4909         mock_set_nfs_export_policy_for_volume.assert_called_once_with(
 4910             fake.SHARE_NAME, 'default')
 4911 
 4912     def test_set_nfs_export_policy_for_volume(self):
 4913 
 4914         self.mock_object(self.client, 'send_request')
 4915 
 4916         self.client.set_nfs_export_policy_for_volume(fake.SHARE_NAME,
 4917                                                      fake.EXPORT_POLICY_NAME)
 4918 
 4919         volume_modify_iter_args = {
 4920             'query': {
 4921                 'volume-attributes': {
 4922                     'volume-id-attributes': {
 4923                         'name': fake.SHARE_NAME,
 4924                     },
 4925                 },
 4926             },
 4927             'attributes': {
 4928                 'volume-attributes': {
 4929                     'volume-export-attributes': {
 4930                         'policy': fake.EXPORT_POLICY_NAME,
 4931                     },
 4932                 },
 4933             },
 4934         }
 4935         self.client.send_request.assert_has_calls([
 4936             mock.call('volume-modify-iter', volume_modify_iter_args)])
 4937 
 4938     def test_set_qos_policy_group_for_volume(self):
 4939 
 4940         self.mock_object(self.client, 'send_request')
 4941 
 4942         self.client.set_qos_policy_group_for_volume(fake.SHARE_NAME,
 4943                                                     fake.QOS_POLICY_GROUP_NAME)
 4944 
 4945         volume_modify_iter_args = {
 4946             'query': {
 4947                 'volume-attributes': {
 4948                     'volume-id-attributes': {
 4949                         'name': fake.SHARE_NAME,
 4950                     },
 4951                 },
 4952             },
 4953             'attributes': {
 4954                 'volume-attributes': {
 4955                     'volume-qos-attributes': {
 4956                         'policy-group-name': fake.QOS_POLICY_GROUP_NAME,
 4957                     },
 4958                 },
 4959             },
 4960         }
 4961         self.client.send_request.assert_called_once_with(
 4962             'volume-modify-iter', volume_modify_iter_args)
 4963 
 4964     def test_get_nfs_export_policy_for_volume(self):
 4965 
 4966         api_response = netapp_api.NaElement(
 4967             fake.VOLUME_GET_EXPORT_POLICY_RESPONSE)
 4968         self.mock_object(self.client,
 4969                          'send_iter_request',
 4970                          mock.Mock(return_value=api_response))
 4971 
 4972         result = self.client.get_nfs_export_policy_for_volume(fake.SHARE_NAME)
 4973 
 4974         volume_get_iter_args = {
 4975             'query': {
 4976                 'volume-attributes': {
 4977                     'volume-id-attributes': {
 4978                         'name': fake.SHARE_NAME,
 4979                     },
 4980                 },
 4981             },
 4982             'desired-attributes': {
 4983                 'volume-attributes': {
 4984                     'volume-export-attributes': {
 4985                         'policy': None,
 4986                     },
 4987                 },
 4988             },
 4989         }
 4990         self.assertEqual(fake.EXPORT_POLICY_NAME, result)
 4991         self.client.send_iter_request.assert_has_calls([
 4992             mock.call('volume-get-iter', volume_get_iter_args)])
 4993 
 4994     def test_get_nfs_export_policy_for_volume_not_found(self):
 4995 
 4996         api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
 4997         self.mock_object(self.client,
 4998                          'send_iter_request',
 4999                          mock.Mock(return_value=api_response))
 5000 
 5001         self.assertRaises(exception.NetAppException,
 5002                           self.client.get_nfs_export_policy_for_volume,
 5003                           fake.SHARE_NAME)
 5004 
 5005     def test_create_nfs_export_policy(self):
 5006 
 5007         self.mock_object(self.client, 'send_request')
 5008 
 5009         self.client.create_nfs_export_policy(fake.EXPORT_POLICY_NAME)
 5010 
 5011         export_policy_create_args = {'policy-name': fake.EXPORT_POLICY_NAME}
 5012         self.client.send_request.assert_has_calls([
 5013             mock.call('export-policy-create', export_policy_create_args)])
 5014 
 5015     def test_create_nfs_export_policy_already_present(self):
 5016 
 5017         self.mock_object(self.client,
 5018                          'send_request',
 5019                          self._mock_api_error(code=netapp_api.EDUPLICATEENTRY))
 5020 
 5021         self.client.create_nfs_export_policy(fake.EXPORT_POLICY_NAME)
 5022 
 5023         export_policy_create_args = {'policy-name': fake.EXPORT_POLICY_NAME}
 5024         self.client.send_request.assert_has_calls([
 5025             mock.call('export-policy-create', export_policy_create_args)])
 5026 
 5027     def test_create_nfs_export_policy_api_error(self):
 5028 
 5029         self.mock_object(self.client, 'send_request', self._mock_api_error())
 5030 
 5031         self.assertRaises(netapp_api.NaApiError,
 5032                           self.client.create_nfs_export_policy,
 5033                           fake.EXPORT_POLICY_NAME)
 5034 
 5035     def test_soft_delete_nfs_export_policy(self):
 5036 
 5037         self.mock_object(self.client, 'delete_nfs_export_policy')
 5038         self.mock_object(self.client, 'rename_nfs_export_policy')
 5039 
 5040         self.client.soft_delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
 5041 
 5042         self.client.delete_nfs_export_policy.assert_has_calls([
 5043             mock.call(fake.EXPORT_POLICY_NAME)])
 5044         self.assertFalse(self.client.rename_nfs_export_policy.called)
 5045 
 5046     def test_soft_delete_nfs_export_policy_api_error(self):
 5047 
 5048         self.mock_object(self.client,
 5049                          'delete_nfs_export_policy',
 5050                          self._mock_api_error())
 5051         self.mock_object(self.client, 'rename_nfs_export_policy')
 5052 
 5053         self.client.soft_delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
 5054 
 5055         self.client.delete_nfs_export_policy.assert_has_calls([
 5056             mock.call(fake.EXPORT_POLICY_NAME)])
 5057         self.assertTrue(self.client.rename_nfs_export_policy.called)
 5058 
 5059     def test_delete_nfs_export_policy(self):
 5060 
 5061         self.mock_object(self.client, 'send_request')
 5062 
 5063         self.client.delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
 5064 
 5065         export_policy_destroy_args = {'policy-name': fake.EXPORT_POLICY_NAME}
 5066         self.client.send_request.assert_has_calls([
 5067             mock.call('export-policy-destroy', export_policy_destroy_args)])
 5068 
 5069     def test_delete_nfs_export_policy_not_found(self):
 5070 
 5071         self.mock_object(self.client,
 5072                          'send_request',
 5073                          self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND))
 5074 
 5075         self.client.delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
 5076 
 5077         export_policy_destroy_args = {'policy-name': fake.EXPORT_POLICY_NAME}
 5078         self.client.send_request.assert_has_calls([
 5079             mock.call('export-policy-destroy', export_policy_destroy_args)])
 5080 
 5081     def test_delete_nfs_export_policy_api_error(self):
 5082 
 5083         self.mock_object(self.client, 'send_request', self._mock_api_error())
 5084 
 5085         self.assertRaises(netapp_api.NaApiError,
 5086                           self.client.delete_nfs_export_policy,
 5087                           fake.EXPORT_POLICY_NAME)
 5088 
 5089     def test_rename_nfs_export_policy(self):
 5090 
 5091         self.mock_object(self.client, 'send_request')
 5092 
 5093         self.client.rename_nfs_export_policy(fake.EXPORT_POLICY_NAME,
 5094                                              'new_policy_name')
 5095 
 5096         export_policy_rename_args = {
 5097             'policy-name': fake.EXPORT_POLICY_NAME,
 5098             'new-policy-name': 'new_policy_name'
 5099         }
 5100         self.client.send_request.assert_has_calls([
 5101             mock.call('export-policy-rename', export_policy_rename_args)])
 5102 
 5103     def test_prune_deleted_nfs_export_policies(self):
 5104         # Mock client lest we not be able to see calls on its copy.
 5105         self.mock_object(copy,
 5106                          'deepcopy',
 5107                          mock.Mock(return_value=self.client))
 5108         self.mock_object(self.client,
 5109                          '_get_deleted_nfs_export_policies',
 5110                          mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES))
 5111         self.mock_object(self.client, 'delete_nfs_export_policy')
 5112 
 5113         self.client.prune_deleted_nfs_export_policies()
 5114 
 5115         self.assertTrue(self.client.delete_nfs_export_policy.called)
 5116         self.client.delete_nfs_export_policy.assert_has_calls(
 5117             [mock.call(policy) for policy in
 5118              fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME]])
 5119 
 5120     def test_prune_deleted_nfs_export_policies_api_error(self):
 5121         self.mock_object(copy,
 5122                          'deepcopy',
 5123                          mock.Mock(return_value=self.client))
 5124         self.mock_object(self.client,
 5125                          '_get_deleted_nfs_export_policies',
 5126                          mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES))
 5127         self.mock_object(self.client,
 5128                          'delete_nfs_export_policy',
 5129                          self._mock_api_error())
 5130 
 5131         self.client.prune_deleted_nfs_export_policies()
 5132 
 5133         self.assertTrue(self.client.delete_nfs_export_policy.called)
 5134         self.client.delete_nfs_export_policy.assert_has_calls(
 5135             [mock.call(policy) for policy in
 5136              fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME]])
 5137 
 5138     def test_get_deleted_nfs_export_policies(self):
 5139 
 5140         api_response = netapp_api.NaElement(
 5141             fake.DELETED_EXPORT_POLICY_GET_ITER_RESPONSE)
 5142         self.mock_object(self.client,
 5143                          'send_iter_request',
 5144                          mock.Mock(return_value=api_response))
 5145 
 5146         result = self.client._get_deleted_nfs_export_policies()
 5147 
 5148         export_policy_get_iter_args = {
 5149             'query': {
 5150                 'export-policy-info': {
 5151                     'policy-name': 'deleted_manila_*',
 5152                 },
 5153             },
 5154             'desired-attributes': {
 5155                 'export-policy-info': {
 5156                     'policy-name': None,
 5157                     'vserver': None,
 5158                 },
 5159             },
 5160         }
 5161         self.assertSequenceEqual(fake.DELETED_EXPORT_POLICIES, result)
 5162         self.client.send_iter_request.assert_has_calls([
 5163             mock.call('export-policy-get-iter', export_policy_get_iter_args)])
 5164 
 5165     def test_get_ems_log_destination_vserver(self):
 5166 
 5167         self.mock_object(self.client,
 5168                          'get_ontapi_version',
 5169                          mock.Mock(return_value=(1, 21)))
 5170         mock_list_vservers = self.mock_object(
 5171             self.client,
 5172             'list_vservers',
 5173             mock.Mock(return_value=[fake.ADMIN_VSERVER_NAME]))
 5174 
 5175         result = self.client._get_ems_log_destination_vserver()
 5176 
 5177         mock_list_vservers.assert_called_once_with(vserver_type='admin')
 5178         self.assertEqual(fake.ADMIN_VSERVER_NAME, result)
 5179 
 5180     def test_get_ems_log_destination_vserver_future(self):
 5181 
 5182         self.mock_object(self.client,
 5183                          'get_ontapi_version',
 5184                          mock.Mock(return_value=(2, 0)))
 5185         mock_list_vservers = self.mock_object(
 5186             self.client,
 5187             'list_vservers',
 5188             mock.Mock(return_value=[fake.ADMIN_VSERVER_NAME]))
 5189 
 5190         result = self.client._get_ems_log_destination_vserver()
 5191 
 5192         mock_list_vservers.assert_called_once_with(vserver_type='admin')
 5193         self.assertEqual(fake.ADMIN_VSERVER_NAME, result)
 5194 
 5195     def test_get_ems_log_destination_vserver_legacy(self):
 5196 
 5197         self.mock_object(self.client,
 5198                          'get_ontapi_version',
 5199                          mock.Mock(return_value=(1,</