"Fossies" - the Fresh Open Source Software Archive

Member "manila-11.0.1/manila/tests/share/test_api.py" (1 Feb 2021, 247265 Bytes) of package /linux/misc/openstack/manila-11.0.1.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_api.py": 11.0.0_vs_11.0.1.

    1 # Copyright 2012 NetApp.  All rights reserved.
    2 # Copyright (c) 2015 Tom Barron.  All rights reserved.
    3 #
    4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    5 #    not use this file except in compliance with the License. You may obtain
    6 #    a copy of the License at
    7 #
    8 #         http://www.apache.org/licenses/LICENSE-2.0
    9 #
   10 #    Unless required by applicable law or agreed to in writing, software
   11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   13 #    License for the specific language governing permissions and limitations
   14 #    under the License.
   15 """Unit tests for the Share API module."""
   16 
   17 import copy
   18 import datetime
   19 from unittest import mock
   20 
   21 
   22 import ddt
   23 from oslo_config import cfg
   24 from oslo_utils import timeutils
   25 from oslo_utils import uuidutils
   26 
   27 from manila.common import constants
   28 from manila import context
   29 from manila.data import rpcapi as data_rpc
   30 from manila import db as db_api
   31 from manila.db.sqlalchemy import models
   32 from manila import exception
   33 from manila import policy
   34 from manila import quota
   35 from manila import share
   36 from manila.share import api as share_api
   37 from manila.share import share_types
   38 from manila import test
   39 from manila.tests import db_utils
   40 from manila.tests import fake_share as fakes
   41 from manila.tests import utils as test_utils
   42 from manila import utils
   43 
   44 CONF = cfg.CONF
   45 
   46 
   47 _FAKE_LIST_OF_ALL_SHARES = [
   48     {
   49         'name': 'foo',
   50         'description': 'ds',
   51         'status': constants.STATUS_AVAILABLE,
   52         'project_id': 'fake_pid_1',
   53         'share_server_id': 'fake_server_1',
   54     },
   55     {
   56         'name': 'bar',
   57         'status': constants.STATUS_ERROR,
   58         'project_id': 'fake_pid_2',
   59         'share_server_id': 'fake_server_2',
   60     },
   61     {
   62         'name': 'foo1',
   63         'description': 'ds1',
   64         'status': constants.STATUS_AVAILABLE,
   65         'project_id': 'fake_pid_2',
   66         'share_server_id': 'fake_server_3',
   67     },
   68     {
   69         'name': 'bar',
   70         'status': constants.STATUS_ERROR,
   71         'project_id': 'fake_pid_2',
   72         'share_server_id': 'fake_server_3',
   73     },
   74 ]
   75 
   76 
   77 _FAKE_LIST_OF_ALL_SNAPSHOTS = [
   78     {
   79         'name': 'foo',
   80         'status': constants.STATUS_AVAILABLE,
   81         'project_id': 'fake_pid_1',
   82         'share_id': 'fake_server_1',
   83     },
   84     {
   85         'name': 'bar',
   86         'status': constants.STATUS_ERROR,
   87         'project_id': 'fake_pid_2',
   88         'share_id': 'fake_server_2',
   89     },
   90     {
   91         'name': 'foo',
   92         'status': constants.STATUS_AVAILABLE,
   93         'project_id': 'fake_pid_2',
   94         'share_id': 'fake_share_id_3',
   95     },
   96     {
   97         'name': 'bar',
   98         'status': constants.STATUS_ERROR,
   99         'project_id': 'fake_pid_2',
  100         'share_id': 'fake_share_id_3',
  101     },
  102 ]
  103 
  104 
  105 @ddt.ddt
  106 class ShareAPITestCase(test.TestCase):
  107 
  108     def setUp(self):
  109         super(ShareAPITestCase, self).setUp()
  110         self.context = context.get_admin_context()
  111         self.scheduler_rpcapi = mock.Mock()
  112         self.share_rpcapi = mock.Mock()
  113         self.api = share.API()
  114         self.mock_object(self.api, 'scheduler_rpcapi', self.scheduler_rpcapi)
  115         self.mock_object(self.api, 'share_rpcapi', self.share_rpcapi)
  116         self.mock_object(quota.QUOTAS, 'reserve',
  117                          lambda *args, **kwargs: None)
  118 
  119         self.dt_utc = datetime.datetime.utcnow()
  120         self.mock_object(timeutils, 'utcnow',
  121                          mock.Mock(return_value=self.dt_utc))
  122         self.mock_object(share_api.policy, 'check_policy')
  123 
  124     def _setup_create_mocks(self, protocol='nfs', **kwargs):
  125         share = db_utils.create_share(
  126             user_id=self.context.user_id,
  127             project_id=self.context.project_id,
  128             share_type_id=kwargs.pop('share_type_id', 'fake'),
  129             **kwargs
  130         )
  131         share_data = {
  132             'share_proto': protocol,
  133             'size': 1,
  134             'display_name': 'fakename',
  135             'display_description': 'fakedesc',
  136             'availability_zone': 'fakeaz'
  137         }
  138 
  139         self.mock_object(db_api, 'share_create', mock.Mock(return_value=share))
  140         self.mock_object(self.api, 'create_instance')
  141 
  142         return share, share_data
  143 
  144     def _setup_create_instance_mocks(self):
  145         host = 'fake'
  146         share_type_id = "fake_share_type"
  147         share = db_utils.create_share(
  148             user_id=self.context.user_id,
  149             project_id=self.context.project_id,
  150             create_share_instance=False,
  151         )
  152         share_instance = db_utils.create_share_instance(
  153             share_id=share['id'],
  154             share_type_id=share_type_id)
  155         share_type = {'fake': 'fake'}
  156         self.mock_object(db_api, 'share_instance_create',
  157                          mock.Mock(return_value=share_instance))
  158         self.mock_object(db_api, 'share_type_get',
  159                          mock.Mock(return_value=share_type))
  160         az_mock = mock.Mock()
  161         type(az_mock.return_value).id = mock.PropertyMock(
  162             return_value='fake_id')
  163         self.mock_object(db_api, 'availability_zone_get', az_mock)
  164         self.mock_object(self.api.share_rpcapi, 'create_share_instance')
  165         self.mock_object(self.api.scheduler_rpcapi, 'create_share_instance')
  166 
  167         return host, share, share_instance
  168 
  169     def _setup_create_from_snapshot_mocks(self, use_scheduler=True, host=None):
  170         CONF.set_default("use_scheduler_creating_share_from_snapshot",
  171                          use_scheduler)
  172 
  173         share_type = fakes.fake_share_type()
  174 
  175         original_share = db_utils.create_share(
  176             user_id=self.context.user_id,
  177             project_id=self.context.project_id,
  178             status=constants.STATUS_AVAILABLE,
  179             host=host if host else 'fake',
  180             size=1,
  181             share_type_id=share_type['id'],
  182         )
  183         snapshot = db_utils.create_snapshot(
  184             share_id=original_share['id'],
  185             status=constants.STATUS_AVAILABLE,
  186             size=1
  187         )
  188 
  189         share, share_data = self._setup_create_mocks(
  190             snapshot_id=snapshot['id'], share_type_id=share_type['id'])
  191         request_spec = {
  192             'share_properties': share.to_dict(),
  193             'share_proto': share['share_proto'],
  194             'share_id': share['id'],
  195             'share_type': None,
  196             'snapshot_id': share['snapshot_id'],
  197         }
  198 
  199         self.mock_object(quota.QUOTAS, 'reserve',
  200                          mock.Mock(return_value='reservation'))
  201         self.mock_object(quota.QUOTAS, 'commit')
  202         self.mock_object(
  203             share_types, 'get_share_type', mock.Mock(return_value=share_type))
  204 
  205         return snapshot, share, share_data, request_spec
  206 
  207     def _setup_delete_mocks(self, status, snapshots=None, **kwargs):
  208         if snapshots is None:
  209             snapshots = []
  210         share = db_utils.create_share(status=status, **kwargs)
  211         self.mock_object(db_api, 'share_delete')
  212         self.mock_object(db_api, 'share_server_update')
  213         self.mock_object(db_api, 'share_snapshot_get_all_for_share',
  214                          mock.Mock(return_value=snapshots))
  215         self.mock_object(self.api, 'delete_instance')
  216         return share
  217 
  218     def _setup_delete_share_instance_mocks(self, **kwargs):
  219         share = db_utils.create_share(**kwargs)
  220 
  221         self.mock_object(db_api, 'share_instance_update',
  222                          mock.Mock(return_value=share.instance))
  223         self.mock_object(self.api.share_rpcapi, 'delete_share_instance')
  224         self.mock_object(db_api, 'share_server_update')
  225 
  226         return share.instance
  227 
  228     def test_get_all_admin_no_filters(self):
  229         self.mock_object(db_api, 'share_get_all_by_project',
  230                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0]))
  231         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True)
  232         shares = self.api.get_all(ctx)
  233         share_api.policy.check_policy.assert_called_once_with(
  234             ctx, 'share', 'get_all')
  235         db_api.share_get_all_by_project.assert_called_once_with(
  236             ctx, sort_dir='desc', sort_key='created_at',
  237             project_id='fake_pid_1', filters={}, is_public=False
  238         )
  239         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0], shares)
  240 
  241     def test_get_all_admin_filter_by_all_tenants(self):
  242         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True)
  243         self.mock_object(db_api, 'share_get_all',
  244                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES))
  245         shares = self.api.get_all(ctx, {'all_tenants': 1})
  246         share_api.policy.check_policy.assert_called_once_with(
  247             ctx, 'share', 'get_all')
  248         db_api.share_get_all.assert_called_once_with(
  249             ctx, sort_dir='desc', sort_key='created_at', filters={})
  250         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES, shares)
  251 
  252     def test_get_all_admin_filter_by_all_tenants_with_blank(self):
  253         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True)
  254         self.mock_object(db_api, 'share_get_all',
  255                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES))
  256         shares = self.api.get_all(ctx, {'all_tenants': ''})
  257         share_api.policy.check_policy.assert_called_once_with(
  258             ctx, 'share', 'get_all')
  259         db_api.share_get_all.assert_called_once_with(
  260             ctx, sort_dir='desc', sort_key='created_at', filters={})
  261         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES, shares)
  262 
  263     def test_get_all_admin_filter_by_all_tenants_with_false(self):
  264         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True)
  265         self.mock_object(db_api, 'share_get_all_by_project',
  266                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0]))
  267         shares = self.api.get_all(ctx, {'all_tenants': 'false'})
  268         share_api.policy.check_policy.assert_called_once_with(
  269             ctx, 'share', 'get_all')
  270         db_api.share_get_all_by_project.assert_called_once_with(
  271             ctx, sort_dir='desc', sort_key='created_at',
  272             project_id='fake_pid_1', filters={}, is_public=False
  273         )
  274         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0], shares)
  275 
  276     def test_get_all_admin_filter_by_all_tenants_with_invaild_value(self):
  277         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True)
  278         self.mock_object(db_api, 'share_get_all')
  279         self.assertRaises(
  280             exception.InvalidInput,
  281             self.api.get_all, ctx, {'all_tenants': 'wonk'})
  282 
  283     @ddt.data(
  284         ({'share_server_id': 'fake_share_server'}, 'list_by_share_server_id'),
  285         ({'host': 'fake_host'}, 'list_by_host'),
  286     )
  287     @ddt.unpack
  288     def test_get_all_by_non_admin_using_admin_filter(self, filters, policy):
  289 
  290         def fake_policy_checker(*args, **kwargs):
  291             if policy == args[2] and not args[0].is_admin:
  292                 raise exception.NotAuthorized
  293 
  294         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
  295         self.mock_object(
  296             share_api.policy, 'check_policy',
  297             mock.Mock(side_effect=fake_policy_checker))
  298 
  299         self.assertRaises(
  300             exception.NotAuthorized,
  301             self.api.get_all, ctx, filters)
  302 
  303         share_api.policy.check_policy.assert_has_calls([
  304             mock.call(ctx, 'share', 'get_all'),
  305             mock.call(ctx, 'share', policy),
  306         ])
  307 
  308     def test_get_all_admin_filter_by_share_server_and_all_tenants(self):
  309         # NOTE(vponomaryov): if share_server_id provided, 'all_tenants' opt
  310         #                    should not make any influence.
  311         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=True)
  312         self.mock_object(db_api, 'share_get_all_by_share_server',
  313                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[2:]))
  314         self.mock_object(db_api, 'share_get_all')
  315         self.mock_object(db_api, 'share_get_all_by_project')
  316         shares = self.api.get_all(
  317             ctx, {'share_server_id': 'fake_server_3', 'all_tenants': 1})
  318         share_api.policy.check_policy.assert_has_calls([
  319             mock.call(ctx, 'share', 'get_all'),
  320             mock.call(ctx, 'share', 'list_by_share_server_id'),
  321         ])
  322         db_api.share_get_all_by_share_server.assert_called_once_with(
  323             ctx, 'fake_server_3', sort_dir='desc', sort_key='created_at',
  324             filters={},
  325         )
  326         db_api.share_get_all_by_project.assert_has_calls([])
  327         db_api.share_get_all.assert_has_calls([])
  328         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[2:], shares)
  329 
  330     def test_get_all_admin_filter_by_name(self):
  331         ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True)
  332         self.mock_object(db_api, 'share_get_all_by_project',
  333                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1:]))
  334         shares = self.api.get_all(ctx, {'name': 'bar'})
  335         share_api.policy.check_policy.assert_has_calls([
  336             mock.call(ctx, 'share', 'get_all'),
  337         ])
  338         db_api.share_get_all_by_project.assert_called_once_with(
  339             ctx, sort_dir='desc', sort_key='created_at',
  340             project_id='fake_pid_2', filters={}, is_public=False
  341         )
  342         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1::2], shares)
  343 
  344     @ddt.data(({'name': 'fo'}, 0), ({'description': 'd'}, 0),
  345               ({'name': 'foo', 'description': 'd'}, 0),
  346               ({'name': 'foo'}, 1), ({'description': 'ds'}, 1),
  347               ({'name~': 'foo', 'description~': 'ds'}, 2),
  348               ({'name': 'foo', 'description~': 'ds'}, 1),
  349               ({'name~': 'foo', 'description': 'ds'}, 1))
  350     @ddt.unpack
  351     def test_get_all_admin_filter_by_name_and_description(
  352             self, search_opts, get_share_number):
  353         ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True)
  354         self.mock_object(db_api, 'share_get_all_by_project',
  355                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES))
  356         shares = self.api.get_all(ctx, search_opts)
  357         share_api.policy.check_policy.assert_has_calls([
  358             mock.call(ctx, 'share', 'get_all'),
  359         ])
  360         db_api.share_get_all_by_project.assert_called_once_with(
  361             ctx, sort_dir='desc', sort_key='created_at',
  362             project_id='fake_pid_2',
  363             filters={}, is_public=False
  364         )
  365         self.assertEqual(get_share_number, len(shares))
  366         if get_share_number == 2:
  367             self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0::2], shares)
  368         elif get_share_number == 1:
  369             self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[:1], shares)
  370 
  371     @ddt.data('id', 'path')
  372     def test_get_all_admin_filter_by_export_location(self, type):
  373         ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True)
  374         self.mock_object(db_api, 'share_get_all_by_project',
  375                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1:]))
  376         shares = self.api.get_all(ctx, {'export_location_' + type: 'test'})
  377         share_api.policy.check_policy.assert_has_calls([
  378             mock.call(ctx, 'share', 'get_all'),
  379         ])
  380         db_api.share_get_all_by_project.assert_called_once_with(
  381             ctx, sort_dir='desc', sort_key='created_at',
  382             project_id='fake_pid_2',
  383             filters={'export_location_' + type: 'test'}, is_public=False
  384         )
  385         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1:], shares)
  386 
  387     def test_get_all_admin_filter_by_name_and_all_tenants(self):
  388         ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True)
  389         self.mock_object(db_api, 'share_get_all',
  390                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES))
  391         shares = self.api.get_all(ctx, {'name': 'foo', 'all_tenants': 1})
  392         share_api.policy.check_policy.assert_has_calls([
  393             mock.call(ctx, 'share', 'get_all'),
  394         ])
  395         db_api.share_get_all.assert_called_once_with(
  396             ctx, sort_dir='desc', sort_key='created_at', filters={})
  397         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[:1], shares)
  398 
  399     def test_get_all_admin_filter_by_status(self):
  400         ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True)
  401         expected_filter = {'status': constants.STATUS_AVAILABLE}
  402         self.mock_object(
  403             db_api, 'share_get_all_by_project',
  404             mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0::2]))
  405 
  406         shares = self.api.get_all(ctx, {'status': constants.STATUS_AVAILABLE})
  407         share_api.policy.check_policy.assert_has_calls([
  408             mock.call(ctx, 'share', 'get_all'),
  409         ])
  410         db_api.share_get_all_by_project.assert_called_once_with(
  411             ctx, sort_dir='desc', sort_key='created_at',
  412             project_id='fake_pid_2', filters=expected_filter, is_public=False
  413         )
  414         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0::2], shares)
  415 
  416     def test_get_all_admin_filter_by_status_and_all_tenants(self):
  417         ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=True)
  418         self.mock_object(
  419             db_api, 'share_get_all',
  420             mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1::2]))
  421         expected_filter = {'status': constants.STATUS_ERROR}
  422         shares = self.api.get_all(
  423             ctx, {'status': constants.STATUS_ERROR, 'all_tenants': 1})
  424         share_api.policy.check_policy.assert_has_calls([
  425             mock.call(ctx, 'share', 'get_all'),
  426         ])
  427         db_api.share_get_all.assert_called_once_with(
  428             ctx, sort_dir='desc', sort_key='created_at',
  429             filters=expected_filter)
  430         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1::2], shares)
  431 
  432     def test_get_all_non_admin_filter_by_all_tenants(self):
  433         # Expected share list only by project of non-admin user
  434         ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=False)
  435         self.mock_object(db_api, 'share_get_all_by_project',
  436                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1:]))
  437         shares = self.api.get_all(ctx, {'all_tenants': 1})
  438         share_api.policy.check_policy.assert_has_calls([
  439             mock.call(ctx, 'share', 'get_all'),
  440         ])
  441         db_api.share_get_all_by_project.assert_called_once_with(
  442             ctx, sort_dir='desc', sort_key='created_at',
  443             project_id='fake_pid_2', filters={}, is_public=False
  444         )
  445         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1:], shares)
  446 
  447     def test_get_all_non_admin_with_name_and_status_filters(self):
  448         ctx = context.RequestContext('fake_uid', 'fake_pid_2', is_admin=False)
  449         self.mock_object(db_api, 'share_get_all_by_project',
  450                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[1:]))
  451         shares = self.api.get_all(
  452             ctx, {'name': 'bar', 'status': constants.STATUS_ERROR})
  453         share_api.policy.check_policy.assert_has_calls([
  454             mock.call(ctx, 'share', 'get_all'),
  455         ])
  456         expected_filter_1 = {'status': constants.STATUS_ERROR}
  457         expected_filter_2 = {'status': constants.STATUS_AVAILABLE}
  458 
  459         db_api.share_get_all_by_project.assert_called_once_with(
  460             ctx, sort_dir='desc', sort_key='created_at',
  461             project_id='fake_pid_2', filters=expected_filter_1, is_public=False
  462         )
  463 
  464         # two items expected, one filtered
  465         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1::2], shares)
  466 
  467         # one item expected, two filtered
  468         shares = self.api.get_all(
  469             ctx, {'name': 'foo1', 'status': constants.STATUS_AVAILABLE})
  470         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[2::4], shares)
  471         share_api.policy.check_policy.assert_has_calls([
  472             mock.call(ctx, 'share', 'get_all'),
  473             mock.call(ctx, 'share', 'get_all'),
  474         ])
  475         db_api.share_get_all_by_project.assert_has_calls([
  476             mock.call(
  477                 ctx, sort_dir='desc', sort_key='created_at',
  478                 project_id='fake_pid_2', filters=expected_filter_1,
  479                 is_public=False),
  480             mock.call(
  481                 ctx, sort_dir='desc', sort_key='created_at',
  482                 project_id='fake_pid_2', filters=expected_filter_2,
  483                 is_public=False),
  484         ])
  485 
  486     @ddt.data('True', 'true', '1', 'yes', 'y', 'on', 't', True)
  487     def test_get_all_non_admin_public(self, is_public):
  488         ctx = context.RequestContext('fake_uid', 'fake_pid_2',
  489                                      is_admin=False)
  490         self.mock_object(db_api, 'share_get_all_by_project', mock.Mock(
  491             return_value=_FAKE_LIST_OF_ALL_SHARES[1:]))
  492         shares = self.api.get_all(ctx, {'is_public': is_public})
  493         share_api.policy.check_policy.assert_has_calls([
  494             mock.call(ctx, 'share', 'get_all'),
  495         ])
  496         db_api.share_get_all_by_project.assert_called_once_with(
  497             ctx, sort_dir='desc', sort_key='created_at',
  498             project_id='fake_pid_2', filters={}, is_public=True
  499         )
  500         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1:], shares)
  501 
  502     @ddt.data('False', 'false', '0', 'no', 'n', 'off', 'f', False)
  503     def test_get_all_non_admin_not_public(self, is_public):
  504         ctx = context.RequestContext('fake_uid', 'fake_pid_2',
  505                                      is_admin=False)
  506         self.mock_object(db_api, 'share_get_all_by_project', mock.Mock(
  507             return_value=_FAKE_LIST_OF_ALL_SHARES[1:]))
  508         shares = self.api.get_all(ctx, {'is_public': is_public})
  509         share_api.policy.check_policy.assert_has_calls([
  510             mock.call(ctx, 'share', 'get_all'),
  511         ])
  512         db_api.share_get_all_by_project.assert_called_once_with(
  513             ctx, sort_dir='desc', sort_key='created_at',
  514             project_id='fake_pid_2', filters={}, is_public=False
  515         )
  516         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[1:], shares)
  517 
  518     @ddt.data('truefoo', 'bartrue')
  519     def test_get_all_invalid_public_value(self, is_public):
  520         ctx = context.RequestContext('fake_uid', 'fake_pid_2',
  521                                      is_admin=False)
  522         self.assertRaises(ValueError, self.api.get_all,
  523                           ctx, {'is_public': is_public})
  524         share_api.policy.check_policy.assert_has_calls([
  525             mock.call(ctx, 'share', 'get_all'),
  526         ])
  527 
  528     def test_get_all_with_sorting_valid(self):
  529         self.mock_object(db_api, 'share_get_all_by_project',
  530                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0]))
  531         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
  532         shares = self.api.get_all(ctx, sort_key='status', sort_dir='asc')
  533         share_api.policy.check_policy.assert_called_once_with(
  534             ctx, 'share', 'get_all')
  535         db_api.share_get_all_by_project.assert_called_once_with(
  536             ctx, sort_dir='asc', sort_key='status',
  537             project_id='fake_pid_1', filters={}, is_public=False
  538         )
  539         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0], shares)
  540 
  541     def test_get_all_sort_key_invalid(self):
  542         self.mock_object(db_api, 'share_get_all_by_project',
  543                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0]))
  544         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
  545         self.assertRaises(
  546             exception.InvalidInput,
  547             self.api.get_all,
  548             ctx,
  549             sort_key=1,
  550         )
  551         share_api.policy.check_policy.assert_called_once_with(
  552             ctx, 'share', 'get_all')
  553 
  554     def test_get_all_sort_dir_invalid(self):
  555         self.mock_object(db_api, 'share_get_all_by_project',
  556                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0]))
  557         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
  558         self.assertRaises(
  559             exception.InvalidInput,
  560             self.api.get_all,
  561             ctx,
  562             sort_dir=1,
  563         )
  564         share_api.policy.check_policy.assert_called_once_with(
  565             ctx, 'share', 'get_all')
  566 
  567     def _get_all_filter_metadata_or_extra_specs_valid(self, key):
  568         self.mock_object(db_api, 'share_get_all_by_project',
  569                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0]))
  570         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
  571         search_opts = {key: {'foo1': 'bar1', 'foo2': 'bar2'}}
  572         shares = self.api.get_all(ctx, search_opts=search_opts.copy())
  573         if key == 'extra_specs':
  574             share_api.policy.check_policy.assert_has_calls([
  575                 mock.call(ctx, 'share', 'get_all'),
  576                 mock.call(ctx, 'share_types_extra_spec', 'index'),
  577             ])
  578         else:
  579             share_api.policy.check_policy.assert_called_once_with(
  580                 ctx, 'share', 'get_all')
  581         db_api.share_get_all_by_project.assert_called_once_with(
  582             ctx, sort_dir='desc', sort_key='created_at',
  583             project_id='fake_pid_1', filters=search_opts, is_public=False)
  584         self.assertEqual(_FAKE_LIST_OF_ALL_SHARES[0], shares)
  585 
  586     def test_get_all_filter_by_metadata(self):
  587         self._get_all_filter_metadata_or_extra_specs_valid(key='metadata')
  588 
  589     def test_get_all_filter_by_extra_specs(self):
  590         self._get_all_filter_metadata_or_extra_specs_valid(key='extra_specs')
  591 
  592     def _get_all_filter_metadata_or_extra_specs_invalid(self, key):
  593         self.mock_object(db_api, 'share_get_all_by_project',
  594                          mock.Mock(return_value=_FAKE_LIST_OF_ALL_SHARES[0]))
  595         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
  596         search_opts = {key: "{'foo': 'bar'}"}
  597         self.assertRaises(exception.InvalidInput, self.api.get_all, ctx,
  598                           search_opts=search_opts)
  599         if key == 'extra_specs':
  600             share_api.policy.check_policy.assert_has_calls([
  601                 mock.call(ctx, 'share', 'get_all'),
  602                 mock.call(ctx, 'share_types_extra_spec', 'index'),
  603             ])
  604         else:
  605             share_api.policy.check_policy.assert_called_once_with(
  606                 ctx, 'share', 'get_all')
  607 
  608     def test_get_all_filter_by_invalid_metadata(self):
  609         self._get_all_filter_metadata_or_extra_specs_invalid(key='metadata')
  610 
  611     def test_get_all_filter_by_invalid_extra_specs(self):
  612         self._get_all_filter_metadata_or_extra_specs_invalid(key='extra_specs')
  613 
  614     @ddt.data(True, False)
  615     def test_create_public_and_private_share(self, is_public):
  616         share, share_data = self._setup_create_mocks(is_public=is_public)
  617         az = share_data.pop('availability_zone')
  618 
  619         self.api.create(
  620             self.context,
  621             share_data['share_proto'],
  622             share_data['size'],
  623             share_data['display_name'],
  624             share_data['display_description'],
  625             availability_zone=az
  626         )
  627 
  628         share['status'] = constants.STATUS_CREATING
  629         share['host'] = None
  630 
  631         self.assertSubDictMatch(share_data,
  632                                 db_api.share_create.call_args[0][1])
  633 
  634     @ddt.data(
  635         {},
  636         {
  637             constants.ExtraSpecs.SNAPSHOT_SUPPORT: True,
  638         },
  639         {
  640             constants.ExtraSpecs.SNAPSHOT_SUPPORT: False,
  641             constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: False,
  642         },
  643         {
  644             constants.ExtraSpecs.SNAPSHOT_SUPPORT: True,
  645             constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: False,
  646         },
  647         {
  648             constants.ExtraSpecs.SNAPSHOT_SUPPORT: True,
  649             constants.ExtraSpecs.CREATE_SHARE_FROM_SNAPSHOT_SUPPORT: True,
  650         }
  651     )
  652     def test_create_default_snapshot_semantics(self, extra_specs):
  653         share, share_data = self._setup_create_mocks(is_public=False)
  654         az = share_data.pop('availability_zone')
  655         share_type = fakes.fake_share_type(extra_specs=extra_specs)
  656 
  657         self.api.create(
  658             self.context,
  659             share_data['share_proto'],
  660             share_data['size'],
  661             share_data['display_name'],
  662             share_data['display_description'],
  663             availability_zone=az,
  664             share_type=share_type
  665         )
  666 
  667         share['status'] = constants.STATUS_CREATING
  668         share['host'] = None
  669 
  670         share_data.update(extra_specs)
  671         if extra_specs.get('snapshot_support') is None:
  672             share_data['snapshot_support'] = False
  673         if extra_specs.get('create_share_from_snapshot_support') is None:
  674             share_data['create_share_from_snapshot_support'] = False
  675 
  676         self.assertSubDictMatch(share_data,
  677                                 db_api.share_create.call_args[0][1])
  678 
  679     @ddt.data(*constants.SUPPORTED_SHARE_PROTOCOLS)
  680     def test_create_share_valid_protocol(self, proto):
  681         share, share_data = self._setup_create_mocks(protocol=proto)
  682         az = share_data.pop('availability_zone')
  683 
  684         all_protos = ','.join(
  685             proto for proto in constants.SUPPORTED_SHARE_PROTOCOLS)
  686         data = dict(DEFAULT=dict(enabled_share_protocols=all_protos))
  687         with test_utils.create_temp_config_with_opts(data):
  688             self.api.create(
  689                 self.context, proto, share_data['size'],
  690                 share_data['display_name'],
  691                 share_data['display_description'],
  692                 availability_zone=az)
  693 
  694         share['status'] = constants.STATUS_CREATING
  695         share['host'] = None
  696 
  697         self.assertSubDictMatch(share_data,
  698                                 db_api.share_create.call_args[0][1])
  699 
  700     @ddt.data(
  701         {'get_all_azs_return': [], 'subnet_by_az_side_effect': []},
  702         {'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'}],
  703          'subnet_by_az_side_effect': [None]},
  704         {'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'}],
  705          'subnet_by_az_side_effect': ['fake_sns_1']},
  706         {'get_all_azs_return': [{'name': 'az1', 'id': 'az_id_1'},
  707                                 {'name': 'az2', 'id': 'az_id_2'}],
  708          'subnet_by_az_side_effect': [None, 'fake_sns_2']}
  709     )
  710     @ddt.unpack
  711     def test__get_all_availability_zones_with_subnets(
  712             self, get_all_azs_return, subnet_by_az_side_effect):
  713         fake_share_network_id = 'fake_sn_id'
  714         self.mock_object(db_api, 'availability_zone_get_all',
  715                          mock.Mock(return_value=get_all_azs_return))
  716         self.mock_object(db_api,
  717                          'share_network_subnet_get_by_availability_zone_id',
  718                          mock.Mock(side_effect=subnet_by_az_side_effect))
  719         expected_az_names = []
  720         expected_get_az_calls = []
  721         for index, value in enumerate(get_all_azs_return):
  722             expected_get_az_calls.append(mock.call(
  723                 self.context, share_network_id=fake_share_network_id,
  724                 availability_zone_id=value['id']))
  725             if subnet_by_az_side_effect[index] is not None:
  726                 expected_az_names.append(value['name'])
  727 
  728         get_all_subnets = self.api._get_all_availability_zones_with_subnets
  729         compatible_azs = get_all_subnets(self.context, fake_share_network_id)
  730 
  731         db_api.availability_zone_get_all.assert_called_once_with(
  732             self.context)
  733         db_get_azs_with_subnet = (
  734             db_api.share_network_subnet_get_by_availability_zone_id)
  735         db_get_azs_with_subnet.assert_has_calls(expected_get_az_calls)
  736 
  737         self.assertEqual(expected_az_names, compatible_azs)
  738 
  739     @ddt.data(
  740         {'availability_zones': None, 'azs_with_subnet': ['fake_az_1']},
  741         {'availability_zones': ['fake_az_2'],
  742          'azs_with_subnet': ['fake_az_2']},
  743         {'availability_zones': ['fake_az_1', 'faze_az_2', 'fake_az_3'],
  744          'azs_with_subnet': ['fake_az_3']}
  745     )
  746     @ddt.unpack
  747     def test_create_share_with_subnets(self, availability_zones,
  748                                        azs_with_subnet):
  749         share, share_data = self._setup_create_mocks()
  750         reservation = 'fake'
  751         self.mock_object(quota.QUOTAS, 'reserve',
  752                          mock.Mock(return_value=reservation))
  753         self.mock_object(self.api, '_get_all_availability_zones_with_subnets',
  754                          mock.Mock(return_value=azs_with_subnet))
  755         self.mock_object(quota.QUOTAS, 'commit')
  756         self.mock_object(self.api, 'create_instance')
  757         self.mock_object(db_api, 'share_get')
  758         fake_share_network_id = 'fake_sn_id'
  759 
  760         if availability_zones:
  761             expected_azs = (
  762                 [az for az in availability_zones if az in azs_with_subnet])
  763         else:
  764             expected_azs = azs_with_subnet
  765 
  766         self.api.create(
  767             self.context,
  768             share_data['share_proto'],
  769             share_data['size'],
  770             share_data['display_name'],
  771             share_data['display_description'],
  772             share_network_id=fake_share_network_id,
  773             availability_zones=availability_zones)
  774         share['status'] = constants.STATUS_CREATING
  775         share['host'] = None
  776 
  777         quota.QUOTAS.reserve.assert_called_once()
  778         get_all_azs_sns = self.api._get_all_availability_zones_with_subnets
  779         get_all_azs_sns.assert_called_once_with(
  780             self.context, fake_share_network_id)
  781         quota.QUOTAS.commit.assert_called_once()
  782         self.api.create_instance.assert_called_once_with(
  783             self.context, share, share_network_id=fake_share_network_id,
  784             host=None, availability_zone=None, share_group=None,
  785             share_group_snapshot_member=None, share_type_id=None,
  786             availability_zones=expected_azs, snapshot_host=None
  787         )
  788         db_api.share_get.assert_called_once()
  789 
  790     @ddt.data(
  791         {'availability_zones': None, 'azs_with_subnet': []},
  792         {'availability_zones': ['fake_az_1'],
  793          'azs_with_subnet': ['fake_az_2']}
  794     )
  795     @ddt.unpack
  796     def test_create_share_with_subnets_invalid_azs(self, availability_zones,
  797                                                    azs_with_subnet):
  798         share, share_data = self._setup_create_mocks()
  799         reservation = 'fake'
  800         self.mock_object(quota.QUOTAS, 'reserve',
  801                          mock.Mock(return_value=reservation))
  802         self.mock_object(self.api, '_get_all_availability_zones_with_subnets',
  803                          mock.Mock(return_value=azs_with_subnet))
  804         self.mock_object(quota.QUOTAS, 'commit')
  805         self.mock_object(self.api, 'create_instance')
  806         self.mock_object(db_api, 'share_get')
  807         fake_share_network_id = 'fake_sn_id'
  808 
  809         self.assertRaises(
  810             exception.InvalidInput,
  811             self.api.create,
  812             self.context, share_data['share_proto'], share_data['size'],
  813             share_data['display_name'], share_data['display_description'],
  814             share_network_id=fake_share_network_id,
  815             availability_zones=availability_zones)
  816 
  817         quota.QUOTAS.reserve.assert_called_once()
  818         get_all_azs_sns = self.api._get_all_availability_zones_with_subnets
  819         get_all_azs_sns.assert_called_once_with(
  820             self.context, fake_share_network_id)
  821 
  822     @ddt.data(
  823         None, '', 'fake', 'nfsfake', 'cifsfake', 'glusterfsfake', 'hdfsfake')
  824     def test_create_share_invalid_protocol(self, proto):
  825         share, share_data = self._setup_create_mocks(protocol=proto)
  826 
  827         all_protos = ','.join(
  828             proto for proto in constants.SUPPORTED_SHARE_PROTOCOLS)
  829         data = dict(DEFAULT=dict(enabled_share_protocols=all_protos))
  830         with test_utils.create_temp_config_with_opts(data):
  831             self.assertRaises(
  832                 exception.InvalidInput,
  833                 self.api.create,
  834                 self.context, proto, share_data['size'],
  835                 share_data['display_name'],
  836                 share_data['display_description'])
  837 
  838     @ddt.data({'overs': {'gigabytes': 'fake'},
  839                'expected_exception': exception.ShareSizeExceedsAvailableQuota},
  840               {'overs': {'shares': 'fake'},
  841                'expected_exception': exception.ShareLimitExceeded})
  842     @ddt.unpack
  843     def test_create_share_over_quota(self, overs, expected_exception):
  844         share, share_data = self._setup_create_mocks()
  845 
  846         usages = {'gigabytes': {'reserved': 5, 'in_use': 5},
  847                   'shares': {'reserved': 10, 'in_use': 10}}
  848         quotas = {'gigabytes': 5, 'shares': 10}
  849         exc = exception.OverQuota(overs=overs, usages=usages, quotas=quotas)
  850         self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc))
  851 
  852         self.assertRaises(
  853             expected_exception,
  854             self.api.create,
  855             self.context,
  856             share_data['share_proto'],
  857             share_data['size'],
  858             share_data['display_name'],
  859             share_data['display_description']
  860         )
  861         quota.QUOTAS.reserve.assert_called_once_with(
  862             self.context, share_type_id=None,
  863             shares=1, gigabytes=share_data['size'])
  864 
  865     @ddt.data(exception.QuotaError, exception.InvalidShare)
  866     def test_create_share_error_on_quota_commit(self, expected_exception):
  867         share, share_data = self._setup_create_mocks()
  868         reservation = 'fake'
  869         self.mock_object(quota.QUOTAS, 'reserve',
  870                          mock.Mock(return_value=reservation))
  871         self.mock_object(quota.QUOTAS, 'commit',
  872                          mock.Mock(side_effect=expected_exception('fake')))
  873         self.mock_object(quota.QUOTAS, 'rollback')
  874         self.mock_object(db_api, 'share_delete')
  875 
  876         self.assertRaises(
  877             expected_exception,
  878             self.api.create,
  879             self.context,
  880             share_data['share_proto'],
  881             share_data['size'],
  882             share_data['display_name'],
  883             share_data['display_description']
  884         )
  885 
  886         quota.QUOTAS.rollback.assert_called_once_with(
  887             self.context, reservation, share_type_id=None)
  888         db_api.share_delete.assert_called_once_with(self.context, share['id'])
  889 
  890     def test_create_share_instance_with_host_and_az(self):
  891         host, share, share_instance = self._setup_create_instance_mocks()
  892 
  893         self.api.create_instance(self.context, share, host=host,
  894                                  availability_zone='fake',
  895                                  share_type_id='fake_share_type')
  896 
  897         db_api.share_instance_create.assert_called_once_with(
  898             self.context, share['id'],
  899             {
  900                 'share_network_id': None,
  901                 'status': constants.STATUS_CREATING,
  902                 'scheduled_at': self.dt_utc,
  903                 'host': host,
  904                 'availability_zone_id': 'fake_id',
  905                 'share_type_id': 'fake_share_type',
  906                 'cast_rules_to_readonly': False,
  907             }
  908         )
  909         db_api.share_type_get.assert_called_once_with(
  910             self.context, share_instance['share_type_id'])
  911         self.api.share_rpcapi.create_share_instance.assert_called_once_with(
  912             self.context,
  913             share_instance,
  914             host,
  915             request_spec=mock.ANY,
  916             filter_properties={},
  917             snapshot_id=share['snapshot_id'],
  918         )
  919         self.assertFalse(
  920             self.api.scheduler_rpcapi.create_share_instance.called)
  921 
  922     def test_create_share_instance_without_host(self):
  923         _, share, share_instance = self._setup_create_instance_mocks()
  924 
  925         self.api.create_instance(self.context, share)
  926 
  927         (self.api.scheduler_rpcapi.create_share_instance.
  928             assert_called_once_with(
  929                 self.context, request_spec=mock.ANY, filter_properties={}))
  930         self.assertFalse(self.api.share_rpcapi.create_share_instance.called)
  931 
  932     def test_create_share_instance_from_snapshot(self):
  933         snapshot, share, _, _ = self._setup_create_from_snapshot_mocks()
  934 
  935         request_spec, share_instance = (
  936             self.api.create_share_instance_and_get_request_spec(
  937                 self.context, share)
  938         )
  939 
  940         self.assertIsNotNone(share_instance)
  941         self.assertEqual(share['id'],
  942                          request_spec['share_instance_properties']['share_id'])
  943         self.assertEqual(share['snapshot_id'], request_spec['snapshot_id'])
  944 
  945         self.assertFalse(
  946             self.api.share_rpcapi.create_share_instance_and_get_request_spec
  947                 .called)
  948 
  949     def test_create_instance_share_group_snapshot_member(self):
  950         fake_req_spec = {
  951             'share_properties': 'fake_share_properties',
  952             'share_instance_properties': 'fake_share_instance_properties',
  953         }
  954         share = fakes.fake_share()
  955         member_info = {
  956             'host': 'host',
  957             'share_network_id': 'share_network_id',
  958             'share_server_id': 'share_server_id',
  959         }
  960 
  961         fake_instance = fakes.fake_share_instance(
  962             share_id=share['id'], **member_info)
  963         sg_snap_member = {'share_instance': fake_instance}
  964         self.mock_policy_check = self.mock_object(
  965             policy, 'check_policy', mock.Mock(return_value=True))
  966         mock_share_rpcapi_call = self.mock_object(self.share_rpcapi,
  967                                                   'create_share_instance')
  968         mock_scheduler_rpcapi_call = self.mock_object(self.scheduler_rpcapi,
  969                                                       'create_share_instance')
  970         mock_db_share_instance_update = self.mock_object(
  971             db_api, 'share_instance_update')
  972         self.mock_object(
  973             share_api.API, 'create_share_instance_and_get_request_spec',
  974             mock.Mock(return_value=(fake_req_spec, fake_instance)))
  975 
  976         retval = self.api.create_instance(
  977             self.context, fakes.fake_share(),
  978             share_group_snapshot_member=sg_snap_member)
  979 
  980         self.assertIsNone(retval)
  981         mock_db_share_instance_update.assert_called_once_with(
  982             self.context, fake_instance['id'], member_info)
  983         self.assertFalse(mock_scheduler_rpcapi_call.called)
  984         self.assertFalse(mock_share_rpcapi_call.called)
  985 
  986     def test_get_share_attributes_from_share_type(self):
  987 
  988         share_type = {
  989             'extra_specs': {
  990                 'snapshot_support': True,
  991                 'create_share_from_snapshot_support': False,
  992                 'revert_to_snapshot_support': False,
  993                 'mount_snapshot_support': False,
  994                 'replication_type': 'dr',
  995             }
  996         }
  997 
  998         result = self.api.get_share_attributes_from_share_type(share_type)
  999 
 1000         self.assertEqual(share_type['extra_specs'], result)
 1001 
 1002     @ddt.data({}, {'extra_specs': {}}, None)
 1003     def test_get_share_attributes_from_share_type_defaults(self, share_type):
 1004 
 1005         result = self.api.get_share_attributes_from_share_type(share_type)
 1006 
 1007         expected = {
 1008             'snapshot_support': False,
 1009             'create_share_from_snapshot_support': False,
 1010             'revert_to_snapshot_support': False,
 1011             'mount_snapshot_support': False,
 1012             'replication_type': None,
 1013         }
 1014         self.assertEqual(expected, result)
 1015 
 1016     @ddt.data({'extra_specs': {'snapshot_support': 'fake'}},
 1017               {'extra_specs': {'create_share_from_snapshot_support': 'fake'}})
 1018     def test_get_share_attributes_from_share_type_invalid(self, share_type):
 1019 
 1020         self.assertRaises(exception.InvalidExtraSpec,
 1021                           self.api.get_share_attributes_from_share_type,
 1022                           share_type)
 1023 
 1024     @ddt.data(
 1025         {'replication_type': 'dr', 'dhss': False, 'share_server_id': None},
 1026         {'replication_type': 'readable', 'dhss': False,
 1027          'share_server_id': None},
 1028         {'replication_type': None, 'dhss': False, 'share_server_id': None},
 1029         {'replication_type': None, 'dhss': True, 'share_server_id': 'fake'}
 1030     )
 1031     @ddt.unpack
 1032     def test_manage_new(self, replication_type, dhss, share_server_id):
 1033         share_data = {
 1034             'host': 'fake',
 1035             'export_location_path': 'fake',
 1036             'share_proto': 'fake',
 1037             'share_type_id': 'fake',
 1038         }
 1039         if dhss:
 1040             share_data['share_server_id'] = share_server_id
 1041         driver_options = {}
 1042         date = datetime.datetime(1, 1, 1, 1, 1, 1)
 1043         timeutils.utcnow.return_value = date
 1044         fake_subnet = db_utils.create_share_network_subnet(
 1045             share_network_id='fake')
 1046         share_server = db_utils.create_share_server(
 1047             status=constants.STATUS_ACTIVE, id=share_server_id,
 1048             share_network_subnet_id=fake_subnet['id'])
 1049         fake_share_data = {
 1050             'id': 'fakeid',
 1051             'status': constants.STATUS_CREATING,
 1052         }
 1053         fake_type = {
 1054             'id': 'fake_type_id',
 1055             'extra_specs': {
 1056                 'snapshot_support': False,
 1057                 'replication_type': replication_type,
 1058                 'create_share_from_snapshot_support': False,
 1059                 'revert_to_snapshot_support': False,
 1060                 'mount_snapshot_support': False,
 1061                 'driver_handles_share_servers': dhss,
 1062             },
 1063         }
 1064 
 1065         share = db_api.share_create(self.context, fake_share_data)
 1066 
 1067         self.mock_object(self.scheduler_rpcapi, 'manage_share')
 1068         self.mock_object(db_api, 'share_create',
 1069                          mock.Mock(return_value=share))
 1070         self.mock_object(db_api, 'share_export_locations_update')
 1071         self.mock_object(db_api, 'share_get',
 1072                          mock.Mock(return_value=share))
 1073         self.mock_object(share_types, 'get_share_type',
 1074                          mock.Mock(return_value=fake_type))
 1075         self.mock_object(db_api, 'share_server_get',
 1076                          mock.Mock(return_value=share_server))
 1077         self.mock_object(db_api, 'share_network_subnet_get',
 1078                          mock.Mock(return_value=fake_subnet))
 1079         self.mock_object(db_api, 'share_instances_get_all',
 1080                          mock.Mock(return_value=[]))
 1081 
 1082         self.api.manage(self.context, copy.deepcopy(share_data),
 1083                         driver_options)
 1084 
 1085         share_data.update({
 1086             'user_id': self.context.user_id,
 1087             'project_id': self.context.project_id,
 1088             'status': constants.STATUS_MANAGING,
 1089             'scheduled_at': date,
 1090             'snapshot_support': fake_type['extra_specs']['snapshot_support'],
 1091             'create_share_from_snapshot_support':
 1092                 fake_type['extra_specs']['create_share_from_snapshot_support'],
 1093             'revert_to_snapshot_support':
 1094                 fake_type['extra_specs']['revert_to_snapshot_support'],
 1095             'mount_snapshot_support':
 1096                 fake_type['extra_specs']['mount_snapshot_support'],
 1097             'replication_type': replication_type,
 1098         })
 1099 
 1100         expected_request_spec = self._get_request_spec_dict(
 1101             share, fake_type, size=0, share_proto=share_data['share_proto'],
 1102             host=share_data['host'])
 1103 
 1104         if dhss:
 1105             share_data.update({
 1106                 'share_network_id': fake_subnet['share_network_id']})
 1107         export_location = share_data.pop('export_location_path')
 1108         filters = {'export_location_path': export_location,
 1109                    'host': share_data['host']
 1110                    }
 1111         if share_server_id:
 1112             filters['share_server_id'] = share_server_id
 1113         db_api.share_instances_get_all.assert_called_once_with(
 1114             self.context, filters=filters)
 1115         db_api.share_create.assert_called_once_with(self.context, share_data)
 1116         db_api.share_get.assert_called_once_with(self.context, share['id'])
 1117         db_api.share_export_locations_update.assert_called_once_with(
 1118             self.context, share.instance['id'], export_location)
 1119         self.scheduler_rpcapi.manage_share.assert_called_once_with(
 1120             self.context, share['id'], driver_options, expected_request_spec)
 1121         if dhss:
 1122             db_api.share_server_get.assert_called_once_with(
 1123                 self.context, share_data['share_server_id'])
 1124             db_api.share_network_subnet_get.assert_called_once_with(
 1125                 self.context, share_server['share_network_subnet_id'])
 1126 
 1127     @ddt.data((True, exception.InvalidInput, True),
 1128               (True, exception.InvalidInput, False),
 1129               (False, exception.InvalidInput, True),
 1130               (True, exception.InvalidInput, True))
 1131     @ddt.unpack
 1132     def test_manage_new_dhss_true_and_false(self, dhss, exception_type,
 1133                                             has_share_server_id):
 1134         share_data = {
 1135             'host': 'fake',
 1136             'export_location_path': 'fake',
 1137             'share_proto': 'fake',
 1138             'share_type_id': 'fake',
 1139         }
 1140         if has_share_server_id:
 1141             share_data['share_server_id'] = 'fake'
 1142 
 1143         driver_options = {}
 1144         date = datetime.datetime(1, 1, 1, 1, 1, 1)
 1145         timeutils.utcnow.return_value = date
 1146         fake_type = {
 1147             'id': 'fake_type_id',
 1148             'extra_specs': {
 1149                 'snapshot_support': False,
 1150                 'create_share_from_snapshot_support': False,
 1151                 'revert_to_snapshot_support': False,
 1152                 'mount_snapshot_support': False,
 1153                 'driver_handles_share_servers': dhss,
 1154             },
 1155         }
 1156 
 1157         self.mock_object(share_types, 'get_share_type',
 1158                          mock.Mock(return_value=fake_type))
 1159         self.mock_object(db_api, 'share_instances_get_all',
 1160                          mock.Mock(return_value=[]))
 1161 
 1162         self.assertRaises(exception_type,
 1163                           self.api.manage,
 1164                           self.context,
 1165                           share_data=share_data,
 1166                           driver_options=driver_options
 1167                           )
 1168         share_types.get_share_type.assert_called_once_with(
 1169             self.context, share_data['share_type_id']
 1170         )
 1171         filters = {'export_location_path': share_data['export_location_path'],
 1172                    'host': share_data['host']
 1173                    }
 1174         if has_share_server_id:
 1175             filters['share_server_id'] = 'fake'
 1176         db_api.share_instances_get_all.assert_called_once_with(
 1177             self.context, filters=filters)
 1178 
 1179     def test_manage_new_share_server_not_found(self):
 1180         share_data = {
 1181             'host': 'fake',
 1182             'export_location_path': 'fake',
 1183             'share_proto': 'fake',
 1184             'share_type_id': 'fake',
 1185             'share_server_id': 'fake'
 1186 
 1187         }
 1188         driver_options = {}
 1189         date = datetime.datetime(1, 1, 1, 1, 1, 1)
 1190         timeutils.utcnow.return_value = date
 1191 
 1192         fake_type = {
 1193             'id': 'fake_type_id',
 1194             'extra_specs': {
 1195                 'snapshot_support': False,
 1196                 'replication_type': 'dr',
 1197                 'create_share_from_snapshot_support': False,
 1198                 'revert_to_snapshot_support': False,
 1199                 'mount_snapshot_support': False,
 1200                 'driver_handles_share_servers': True,
 1201             },
 1202         }
 1203 
 1204         self.mock_object(share_types, 'get_share_type',
 1205                          mock.Mock(return_value=fake_type))
 1206         self.mock_object(db_api, 'share_instances_get_all',
 1207                          mock.Mock(return_value=[]))
 1208 
 1209         self.assertRaises(exception.InvalidInput,
 1210                           self.api.manage,
 1211                           self.context,
 1212                           share_data=share_data,
 1213                           driver_options=driver_options
 1214                           )
 1215         share_types.get_share_type.assert_called_once_with(
 1216             self.context, share_data['share_type_id']
 1217         )
 1218         db_api.share_instances_get_all.assert_called_once_with(
 1219             self.context, filters={
 1220                 'export_location_path': share_data['export_location_path'],
 1221                 'host': share_data['host'],
 1222                 'share_server_id': share_data['share_server_id']
 1223             }
 1224         )
 1225 
 1226     def test_manage_new_share_server_not_active(self):
 1227         share_data = {
 1228             'host': 'fake',
 1229             'export_location_path': 'fake',
 1230             'share_proto': 'fake',
 1231             'share_type_id': 'fake',
 1232             'share_server_id': 'fake'
 1233 
 1234         }
 1235         fake_share_data = {
 1236             'id': 'fakeid',
 1237             'status': constants.STATUS_ERROR,
 1238         }
 1239         driver_options = {}
 1240         date = datetime.datetime(1, 1, 1, 1, 1, 1)
 1241         timeutils.utcnow.return_value = date
 1242 
 1243         fake_type = {
 1244             'id': 'fake_type_id',
 1245             'extra_specs': {
 1246                 'snapshot_support': False,
 1247                 'replication_type': 'dr',
 1248                 'create_share_from_snapshot_support': False,
 1249                 'revert_to_snapshot_support': False,
 1250                 'mount_snapshot_support': False,
 1251                 'driver_handles_share_servers': True,
 1252             },
 1253         }
 1254 
 1255         share = db_api.share_create(self.context, fake_share_data)
 1256 
 1257         self.mock_object(share_types, 'get_share_type',
 1258                          mock.Mock(return_value=fake_type))
 1259         self.mock_object(db_api, 'share_instances_get_all',
 1260                          mock.Mock(return_value=[]))
 1261         self.mock_object(db_api, 'share_server_get',
 1262                          mock.Mock(return_value=share))
 1263 
 1264         self.assertRaises(exception.InvalidShareServer,
 1265                           self.api.manage,
 1266                           self.context,
 1267                           share_data=share_data,
 1268                           driver_options=driver_options
 1269                           )
 1270         share_types.get_share_type.assert_called_once_with(
 1271             self.context, share_data['share_type_id']
 1272         )
 1273         db_api.share_instances_get_all.assert_called_once_with(
 1274             self.context, filters={
 1275                 'export_location_path': share_data['export_location_path'],
 1276                 'host': share_data['host'],
 1277                 'share_server_id': share_data['share_server_id']
 1278             }
 1279         )
 1280         db_api.share_server_get.assert_called_once_with(
 1281             self.context, share_data['share_server_id']
 1282         )
 1283 
 1284     @ddt.data(constants.STATUS_MANAGE_ERROR, constants.STATUS_AVAILABLE)
 1285     def test_manage_duplicate(self, status):
 1286         share_data = {
 1287             'host': 'fake',
 1288             'export_location_path': 'fake',
 1289             'share_proto': 'fake',
 1290             'share_type_id': 'fake',
 1291         }
 1292         driver_options = {}
 1293         fake_type = {
 1294             'id': 'fake_type_id',
 1295             'extra_specs': {
 1296                 'snapshot_support': False,
 1297                 'create_share_from_snapshot_support': False,
 1298                 'driver_handles_share_servers': False,
 1299             },
 1300         }
 1301         already_managed = [{'id': 'fake', 'status': status}]
 1302         self.mock_object(db_api, 'share_instances_get_all',
 1303                          mock.Mock(return_value=already_managed))
 1304         self.mock_object(share_types, 'get_share_type',
 1305                          mock.Mock(return_value=fake_type))
 1306         self.assertRaises(exception.InvalidShare, self.api.manage,
 1307                           self.context, share_data, driver_options)
 1308 
 1309     def _get_request_spec_dict(self, share, share_type, **kwargs):
 1310 
 1311         if share is None:
 1312             share = {'instance': {}}
 1313 
 1314         share_instance = share['instance']
 1315 
 1316         share_properties = {
 1317             'size': kwargs.get('size', share.get('size')),
 1318             'user_id': kwargs.get('user_id', share.get('user_id')),
 1319             'project_id': kwargs.get('project_id', share.get('project_id')),
 1320             'snapshot_support': kwargs.get(
 1321                 'snapshot_support',
 1322                 share_type['extra_specs']['snapshot_support']),
 1323             'create_share_from_snapshot_support': kwargs.get(
 1324                 'create_share_from_snapshot_support',
 1325                 share_type['extra_specs'].get(
 1326                     'create_share_from_snapshot_support')),
 1327             'revert_to_snapshot_support': kwargs.get(
 1328                 'revert_to_snapshot_support',
 1329                 share_type['extra_specs'].get('revert_to_snapshot_support')),
 1330             'mount_snapshot_support': kwargs.get(
 1331                 'mount_snapshot_support',
 1332                 share_type['extra_specs'].get('mount_snapshot_support')),
 1333             'share_proto': kwargs.get('share_proto', share.get('share_proto')),
 1334             'share_type_id': share_type['id'],
 1335             'is_public': kwargs.get('is_public', share.get('is_public')),
 1336             'share_group_id': kwargs.get(
 1337                 'share_group_id', share.get('share_group_id')),
 1338             'source_share_group_snapshot_member_id': kwargs.get(
 1339                 'source_share_group_snapshot_member_id',
 1340                 share.get('source_share_group_snapshot_member_id')),
 1341             'snapshot_id': kwargs.get('snapshot_id', share.get('snapshot_id')),
 1342         }
 1343         share_instance_properties = {
 1344             'availability_zone_id': kwargs.get(
 1345                 'availability_zone_id',
 1346                 share_instance.get('availability_zone_id')),
 1347             'share_network_id': kwargs.get(
 1348                 'share_network_id', share_instance.get('share_network_id')),
 1349             'share_server_id': kwargs.get(
 1350                 'share_server_id', share_instance.get('share_server_id')),
 1351             'share_id': kwargs.get('share_id', share_instance.get('share_id')),
 1352             'host': kwargs.get('host', share_instance.get('host')),
 1353             'status': kwargs.get('status', share_instance.get('status')),
 1354         }
 1355 
 1356         request_spec = {
 1357             'share_properties': share_properties,
 1358             'share_instance_properties': share_instance_properties,
 1359             'share_type': share_type,
 1360             'share_id': share.get('id'),
 1361         }
 1362         return request_spec
 1363 
 1364     def test_unmanage(self):
 1365 
 1366         share = db_utils.create_share(
 1367             id='fakeid',
 1368             host='fake',
 1369             size='1',
 1370             status=constants.STATUS_AVAILABLE,
 1371             user_id=self.context.user_id,
 1372             project_id=self.context.project_id,
 1373             task_state=None)
 1374 
 1375         self.mock_object(db_api, 'share_update', mock.Mock())
 1376 
 1377         self.api.unmanage(self.context, share)
 1378 
 1379         self.share_rpcapi.unmanage_share.assert_called_once_with(
 1380             self.context, mock.ANY)
 1381         db_api.share_update.assert_called_once_with(
 1382             mock.ANY, share['id'], mock.ANY)
 1383 
 1384     def test_unmanage_task_state_busy(self):
 1385 
 1386         share = db_utils.create_share(
 1387             id='fakeid',
 1388             host='fake',
 1389             size='1',
 1390             status=constants.STATUS_AVAILABLE,
 1391             user_id=self.context.user_id,
 1392             project_id=self.context.project_id,
 1393             task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS)
 1394 
 1395         self.assertRaises(exception.ShareBusyException, self.api.unmanage,
 1396                           self.context, share)
 1397 
 1398     @mock.patch.object(quota.QUOTAS, 'reserve',
 1399                        mock.Mock(return_value='reservation'))
 1400     @mock.patch.object(quota.QUOTAS, 'commit', mock.Mock())
 1401     def test_create_snapshot(self):
 1402         snapshot = db_utils.create_snapshot(
 1403             with_share=True, status=constants.STATUS_CREATING, size=1)
 1404         share = snapshot['share']
 1405 
 1406         fake_name = 'fakename'
 1407         fake_desc = 'fakedesc'
 1408         options = {
 1409             'share_id': share['id'],
 1410             'user_id': self.context.user_id,
 1411             'project_id': self.context.project_id,
 1412             'status': constants.STATUS_CREATING,
 1413             'progress': '0%',
 1414             'share_size': share['size'],
 1415             'size': 1,
 1416             'display_name': fake_name,
 1417             'display_description': fake_desc,
 1418             'share_proto': share['share_proto'],
 1419         }
 1420         with mock.patch.object(db_api, 'share_snapshot_create',
 1421                                mock.Mock(return_value=snapshot)):
 1422             self.api.create_snapshot(self.context, share, fake_name,
 1423                                      fake_desc)
 1424             share_api.policy.check_policy.assert_called_once_with(
 1425                 self.context, 'share', 'create_snapshot', share)
 1426             quota.QUOTAS.reserve.assert_called_once_with(
 1427                 self.context, share_type_id=None,
 1428                 snapshot_gigabytes=1, snapshots=1)
 1429             quota.QUOTAS.commit.assert_called_once_with(
 1430                 self.context, 'reservation', share_type_id=None)
 1431             db_api.share_snapshot_create.assert_called_once_with(
 1432                 self.context, options)
 1433 
 1434     def test_create_snapshot_space_quota_exceeded(self):
 1435 
 1436         share = fakes.fake_share(
 1437             id=uuidutils.generate_uuid(), size=1, project_id='fake_project',
 1438             user_id='fake_user', has_replicas=False, status='available')
 1439         usages = {'snapshot_gigabytes': {'reserved': 10, 'in_use': 0}}
 1440         quotas = {'snapshot_gigabytes': 10}
 1441         side_effect = exception.OverQuota(
 1442             overs='snapshot_gigabytes', usages=usages, quotas=quotas)
 1443         self.mock_object(
 1444             quota.QUOTAS, 'reserve', mock.Mock(side_effect=side_effect))
 1445         mock_snap_create = self.mock_object(db_api, 'share_snapshot_create')
 1446 
 1447         self.assertRaises(exception.SnapshotSizeExceedsAvailableQuota,
 1448                           self.api.create_snapshot,
 1449                           self.context,
 1450                           share,
 1451                           'fake_name',
 1452                           'fake_description')
 1453         mock_snap_create.assert_not_called()
 1454 
 1455     def test_create_snapshot_count_quota_exceeded(self):
 1456 
 1457         share = fakes.fake_share(
 1458             id=uuidutils.generate_uuid(), size=1, project_id='fake_project',
 1459             user_id='fake_user', has_replicas=False, status='available')
 1460         usages = {'snapshots': {'reserved': 10, 'in_use': 0}}
 1461         quotas = {'snapshots': 10}
 1462         side_effect = exception.OverQuota(
 1463             overs='snapshots', usages=usages, quotas=quotas)
 1464         self.mock_object(
 1465             quota.QUOTAS, 'reserve', mock.Mock(side_effect=side_effect))
 1466         mock_snap_create = self.mock_object(db_api, 'share_snapshot_create')
 1467 
 1468         self.assertRaises(exception.SnapshotLimitExceeded,
 1469                           self.api.create_snapshot,
 1470                           self.context,
 1471                           share,
 1472                           'fake_name',
 1473                           'fake_description')
 1474         mock_snap_create.assert_not_called()
 1475 
 1476     def test_manage_snapshot_share_not_found(self):
 1477         snapshot = fakes.fake_snapshot(share_id='fake_share',
 1478                                        as_primitive=True)
 1479         mock_share_get_call = self.mock_object(
 1480             db_api, 'share_get', mock.Mock(side_effect=exception.NotFound))
 1481         mock_db_snapshot_call = self.mock_object(
 1482             db_api, 'share_snapshot_get_all_for_share')
 1483 
 1484         self.assertRaises(exception.ShareNotFound,
 1485                           self.api.manage_snapshot,
 1486                           self.context,
 1487                           snapshot,
 1488                           {})
 1489         self.assertFalse(mock_db_snapshot_call.called)
 1490         mock_share_get_call.assert_called_once_with(
 1491             self.context, snapshot['share_id'])
 1492 
 1493     def test_manage_snapshot_share_has_replicas(self):
 1494         share_ref = fakes.fake_share(
 1495             has_replicas=True, status=constants.STATUS_AVAILABLE)
 1496         self.mock_object(
 1497             db_api, 'share_get', mock.Mock(return_value=share_ref))
 1498         snapshot = fakes.fake_snapshot(create_instance=True, as_primitive=True)
 1499         mock_db_snapshot_get_all_for_share_call = self.mock_object(
 1500             db_api, 'share_snapshot_get_all_for_share')
 1501 
 1502         self.assertRaises(exception.InvalidShare,
 1503                           self.api.manage_snapshot,
 1504                           context,
 1505                           snapshot,
 1506                           {})
 1507         self.assertFalse(mock_db_snapshot_get_all_for_share_call.called)
 1508 
 1509     def test_manage_snapshot_already_managed(self):
 1510         share_ref = fakes.fake_share(
 1511             has_replicas=False, status=constants.STATUS_AVAILABLE)
 1512         snapshot = fakes.fake_snapshot(create_instance=True, as_primitive=True)
 1513         self.mock_object(
 1514             db_api, 'share_get', mock.Mock(return_value=share_ref))
 1515         mock_db_snapshot_call = self.mock_object(
 1516             db_api, 'share_snapshot_get_all_for_share', mock.Mock(
 1517                 return_value=[snapshot]))
 1518         mock_db_snapshot_create_call = self.mock_object(
 1519             db_api, 'share_snapshot_create')
 1520 
 1521         self.assertRaises(exception.ManageInvalidShareSnapshot,
 1522                           self.api.manage_snapshot,
 1523                           self.context,
 1524                           snapshot,
 1525                           {})
 1526         mock_db_snapshot_call.assert_called_once_with(
 1527             self.context, snapshot['share_id'])
 1528         self.assertFalse(mock_db_snapshot_create_call.called)
 1529 
 1530     def test_manage_snapshot(self):
 1531         share_ref = fakes.fake_share(
 1532             has_replicas=False, status=constants.STATUS_AVAILABLE,
 1533             host='fake_host')
 1534         existing_snapshot = fakes.fake_snapshot(
 1535             create_instance=True, share_id=share_ref['id'])
 1536         self.mock_object(db_api, 'share_snapshot_get_all_for_share',
 1537                          mock.Mock(return_value=[existing_snapshot]))
 1538         snapshot_data = {
 1539             'share_id': share_ref['id'],
 1540             'provider_location': 'someproviderlocation',
 1541         }
 1542         expected_snapshot_data = {
 1543             'user_id': self.context.user_id,
 1544             'project_id': self.context.project_id,
 1545             'status': constants.STATUS_MANAGING,
 1546             'share_size': share_ref['size'],
 1547             'progress': '0%',
 1548             'share_proto': share_ref['share_proto'],
 1549         }
 1550         expected_snapshot_data.update(**snapshot_data)
 1551         snapshot = fakes.fake_snapshot(
 1552             create_instance=True, **expected_snapshot_data)
 1553         self.mock_object(
 1554             db_api, 'share_get', mock.Mock(return_value=share_ref))
 1555         mock_db_snapshot_create_call = self.mock_object(
 1556             db_api, 'share_snapshot_create', mock.Mock(return_value=snapshot))
 1557         mock_rpc_call = self.mock_object(self.share_rpcapi, 'manage_snapshot',
 1558                                          mock.Mock(return_value=snapshot))
 1559 
 1560         new_snap = self.api.manage_snapshot(
 1561             self.context, snapshot_data, {})
 1562 
 1563         self.assertEqual(new_snap, snapshot)
 1564         mock_db_snapshot_create_call.assert_called_once_with(
 1565             self.context, expected_snapshot_data)
 1566         mock_rpc_call.assert_called_once_with(
 1567             self.context, snapshot, share_ref['host'], {})
 1568 
 1569     def test_manage_share_server(self):
 1570         """Tests manage share server"""
 1571         host = 'fake_host'
 1572         fake_share_network = {
 1573             'id': 'fake_net_id'
 1574         }
 1575         fake_share_net_subnet = {
 1576             'id': 'fake_subnet_id',
 1577             'share_network_id': fake_share_network['id']
 1578         }
 1579         identifier = 'fake_identifier'
 1580         values = {
 1581             'host': host,
 1582             'share_network_subnet_id': fake_share_net_subnet['id'],
 1583             'status': constants.STATUS_MANAGING,
 1584             'is_auto_deletable': False,
 1585             'identifier': identifier,
 1586         }
 1587 
 1588         server_managing = {
 1589             'id': 'fake_server_id',
 1590             'status': constants.STATUS_MANAGING,
 1591             'host': host,
 1592             'share_network_subnet_id': fake_share_net_subnet['id'],
 1593             'is_auto_deletable': False,
 1594             'identifier': identifier,
 1595         }
 1596 
 1597         mock_share_server_search = self.mock_object(
 1598             db_api, 'share_server_search_by_identifier',
 1599             mock.Mock(side_effect=exception.ShareServerNotFound('fake')))
 1600 
 1601         mock_share_server_get = self.mock_object(
 1602             db_api, 'share_server_get',
 1603             mock.Mock(
 1604                 return_value=server_managing)
 1605         )
 1606         mock_share_server_create = self.mock_object(
 1607             db_api, 'share_server_create',
 1608             mock.Mock(return_value=server_managing)
 1609         )
 1610         result = self.api.manage_share_server(
 1611             self.context, 'fake_identifier', host, fake_share_net_subnet,
 1612             {'opt1': 'val1', 'opt2': 'val2'}
 1613         )
 1614 
 1615         mock_share_server_create.assert_called_once_with(
 1616             self.context, values)
 1617 
 1618         mock_share_server_get.assert_called_once_with(
 1619             self.context, 'fake_server_id')
 1620 
 1621         mock_share_server_search.assert_called_once_with(
 1622             self.context, 'fake_identifier')
 1623 
 1624         result_dict = {
 1625             'host': result['host'],
 1626             'share_network_subnet_id': result['share_network_subnet_id'],
 1627             'status': result['status'],
 1628             'is_auto_deletable': result['is_auto_deletable'],
 1629             'identifier': result['identifier'],
 1630         }
 1631         self.assertEqual(values, result_dict)
 1632 
 1633     def test_manage_share_server_invalid(self):
 1634 
 1635         server = {'identifier': 'fake_server'}
 1636 
 1637         mock_share_server_search = self.mock_object(
 1638             db_api, 'share_server_search_by_identifier',
 1639             mock.Mock(return_value=[server]))
 1640 
 1641         self.assertRaises(
 1642             exception.InvalidInput, self.api.manage_share_server,
 1643             self.context, 'invalid_identifier', 'fake_host', 'fake_share_net',
 1644             {})
 1645 
 1646         mock_share_server_search.assert_called_once_with(
 1647             self.context, 'invalid_identifier')
 1648 
 1649     def test_unmanage_snapshot(self):
 1650         fake_host = 'fake_host'
 1651         snapshot_data = {
 1652             'status': constants.STATUS_UNMANAGING,
 1653             'terminated_at': timeutils.utcnow(),
 1654         }
 1655         snapshot = fakes.fake_snapshot(
 1656             create_instance=True, share_instance_id='id2', **snapshot_data)
 1657         mock_db_snap_update_call = self.mock_object(
 1658             db_api, 'share_snapshot_update', mock.Mock(return_value=snapshot))
 1659         mock_rpc_call = self.mock_object(
 1660             self.share_rpcapi, 'unmanage_snapshot')
 1661 
 1662         retval = self.api.unmanage_snapshot(
 1663             self.context, snapshot, fake_host)
 1664 
 1665         self.assertIsNone(retval)
 1666         mock_db_snap_update_call.assert_called_once_with(
 1667             self.context, snapshot['id'], snapshot_data)
 1668         mock_rpc_call.assert_called_once_with(
 1669             self.context, snapshot, fake_host)
 1670 
 1671     def test_unmanage_share_server(self):
 1672         shr1 = {}
 1673         share_server = db_utils.create_share_server(**shr1)
 1674         update_data = {'status': constants.STATUS_UNMANAGING,
 1675                        'terminated_at': timeutils.utcnow()}
 1676 
 1677         mock_share_instances_get_all = self.mock_object(
 1678             db_api, 'share_instances_get_all_by_share_server',
 1679             mock.Mock(return_value={}))
 1680         mock_share_group_get_all = self.mock_object(
 1681             db_api, 'share_group_get_all_by_share_server',
 1682             mock.Mock(return_value={}))
 1683         mock_share_server_update = self.mock_object(
 1684             db_api, 'share_server_update',
 1685             mock.Mock(return_value=share_server))
 1686 
 1687         mock_rpc = self.mock_object(
 1688             self.api.share_rpcapi, 'unmanage_share_server')
 1689 
 1690         self.api.unmanage_share_server(self.context, share_server, True)
 1691 
 1692         mock_share_instances_get_all.assert_called_once_with(
 1693             self.context, share_server['id']
 1694         )
 1695         mock_share_group_get_all.assert_called_once_with(
 1696             self.context, share_server['id']
 1697         )
 1698         mock_share_server_update.assert_called_once_with(
 1699             self.context, share_server['id'], update_data
 1700         )
 1701 
 1702         mock_rpc.assert_called_once_with(
 1703             self.context, share_server, force=True)
 1704 
 1705     def test_unmanage_share_server_in_use(self):
 1706         fake_share = db_utils.create_share()
 1707         fake_share_server = db_utils.create_share_server()
 1708 
 1709         fake_share_instance = db_utils.create_share_instance(
 1710             share_id=fake_share['id'])
 1711         share_instance_get_all_mock = self.mock_object(
 1712             db_api, 'share_instances_get_all_by_share_server',
 1713             mock.Mock(return_value=fake_share_instance)
 1714         )
 1715 
 1716         self.assertRaises(exception.ShareServerInUse,
 1717                           self.api.unmanage_share_server,
 1718                           self.context,
 1719                           fake_share_server, True)
 1720         share_instance_get_all_mock.assert_called_once_with(
 1721             self.context, fake_share_server['id']
 1722         )
 1723 
 1724     def test_unmanage_share_server_in_use_share_groups(self):
 1725         fake_share_server = db_utils.create_share_server()
 1726         fake_share_groups = db_utils.create_share_group()
 1727 
 1728         share_instance_get_all_mock = self.mock_object(
 1729             db_api, 'share_instances_get_all_by_share_server',
 1730             mock.Mock(return_value={})
 1731         )
 1732         group_get_all_mock = self.mock_object(
 1733             db_api, 'share_group_get_all_by_share_server',
 1734             mock.Mock(return_value=fake_share_groups)
 1735         )
 1736 
 1737         self.assertRaises(exception.ShareServerInUse,
 1738                           self.api.unmanage_share_server,
 1739                           self.context,
 1740                           fake_share_server, True)
 1741         share_instance_get_all_mock.assert_called_once_with(
 1742             self.context, fake_share_server['id']
 1743         )
 1744         group_get_all_mock.assert_called_once_with(
 1745             self.context, fake_share_server['id']
 1746         )
 1747 
 1748     @ddt.data(True, False)
 1749     def test_revert_to_snapshot(self, has_replicas):
 1750 
 1751         share = fakes.fake_share(id=uuidutils.generate_uuid(),
 1752                                  has_replicas=has_replicas)
 1753         self.mock_object(db_api, 'share_get', mock.Mock(return_value=share))
 1754         mock_handle_revert_to_snapshot_quotas = self.mock_object(
 1755             self.api, '_handle_revert_to_snapshot_quotas',
 1756             mock.Mock(return_value='fake_reservations'))
 1757         mock_revert_to_replicated_snapshot = self.mock_object(
 1758             self.api, '_revert_to_replicated_snapshot')
 1759         mock_revert_to_snapshot = self.mock_object(
 1760             self.api, '_revert_to_snapshot')
 1761         snapshot = fakes.fake_snapshot(share_id=share['id'])
 1762 
 1763         self.api.revert_to_snapshot(self.context, share, snapshot)
 1764 
 1765         mock_handle_revert_to_snapshot_quotas.assert_called_once_with(
 1766             self.context, share, snapshot)
 1767         if not has_replicas:
 1768             self.assertFalse(mock_revert_to_replicated_snapshot.called)
 1769             mock_revert_to_snapshot.assert_called_once_with(
 1770                 self.context, share, snapshot, 'fake_reservations')
 1771         else:
 1772             mock_revert_to_replicated_snapshot.assert_called_once_with(
 1773                 self.context, share, snapshot, 'fake_reservations')
 1774             self.assertFalse(mock_revert_to_snapshot.called)
 1775 
 1776     @ddt.data(None, 'fake_reservations')
 1777     def test_revert_to_snapshot_exception(self, reservations):
 1778 
 1779         share = fakes.fake_share(id=uuidutils.generate_uuid(),
 1780                                  has_replicas=False)
 1781         self.mock_object(db_api, 'share_get', mock.Mock(return_value=share))
 1782         self.mock_object(
 1783             self.api, '_handle_revert_to_snapshot_quotas',
 1784             mock.Mock(return_value=reservations))
 1785         side_effect = exception.ReplicationException(reason='error')
 1786         self.mock_object(
 1787             self.api, '_revert_to_snapshot',
 1788             mock.Mock(side_effect=side_effect))
 1789         mock_quotas_rollback = self.mock_object(quota.QUOTAS, 'rollback')
 1790         snapshot = fakes.fake_snapshot(share_id=share['id'])
 1791 
 1792         self.assertRaises(exception.ReplicationException,
 1793                           self.api.revert_to_snapshot,
 1794                           self.context,
 1795                           share,
 1796                           snapshot)
 1797 
 1798         if reservations is not None:
 1799             mock_quotas_rollback.assert_called_once_with(
 1800                 self.context, reservations,
 1801                 share_type_id=share['instance']['share_type_id'])
 1802         else:
 1803             self.assertFalse(mock_quotas_rollback.called)
 1804 
 1805     def test_handle_revert_to_snapshot_quotas(self):
 1806 
 1807         share = fakes.fake_share(
 1808             id=uuidutils.generate_uuid(), size=1, project_id='fake_project',
 1809             user_id='fake_user', has_replicas=False)
 1810         snapshot = fakes.fake_snapshot(
 1811             id=uuidutils.generate_uuid(), share_id=share['id'], size=1)
 1812         mock_quotas_reserve = self.mock_object(quota.QUOTAS, 'reserve')
 1813 
 1814         result = self.api._handle_revert_to_snapshot_quotas(
 1815             self.context, share, snapshot)
 1816 
 1817         self.assertIsNone(result)
 1818         self.assertFalse(mock_quotas_reserve.called)
 1819 
 1820     def test_handle_revert_to_snapshot_quotas_different_size(self):
 1821 
 1822         share = fakes.fake_share(
 1823             id=uuidutils.generate_uuid(), size=1, project_id='fake_project',
 1824             user_id='fake_user', has_replicas=False)
 1825         snapshot = fakes.fake_snapshot(
 1826             id=uuidutils.generate_uuid(), share_id=share['id'], size=2)
 1827         mock_quotas_reserve = self.mock_object(
 1828             quota.QUOTAS, 'reserve',
 1829             mock.Mock(return_value='fake_reservations'))
 1830 
 1831         result = self.api._handle_revert_to_snapshot_quotas(
 1832             self.context, share, snapshot)
 1833 
 1834         self.assertEqual('fake_reservations', result)
 1835         mock_quotas_reserve.assert_called_once_with(
 1836             self.context, project_id='fake_project', gigabytes=1,
 1837             share_type_id=share['instance']['share_type_id'],
 1838             user_id='fake_user')
 1839 
 1840     def test_handle_revert_to_snapshot_quotas_quota_exceeded(self):
 1841 
 1842         share = fakes.fake_share(
 1843             id=uuidutils.generate_uuid(), size=1, project_id='fake_project',
 1844             user_id='fake_user', has_replicas=False)
 1845         snapshot = fakes.fake_snapshot(
 1846             id=uuidutils.generate_uuid(), share_id=share['id'], size=2)
 1847         usages = {'gigabytes': {'reserved': 10, 'in_use': 0}}
 1848         quotas = {'gigabytes': 10}
 1849         side_effect = exception.OverQuota(
 1850             overs='fake', usages=usages, quotas=quotas)
 1851         self.mock_object(
 1852             quota.QUOTAS, 'reserve', mock.Mock(side_effect=side_effect))
 1853 
 1854         self.assertRaises(exception.ShareSizeExceedsAvailableQuota,
 1855                           self.api._handle_revert_to_snapshot_quotas,
 1856                           self.context,
 1857                           share,
 1858                           snapshot)
 1859 
 1860     def test__revert_to_snapshot(self):
 1861 
 1862         share = fakes.fake_share(
 1863             id=uuidutils.generate_uuid(), size=1, project_id='fake_project',
 1864             user_id='fake_user', has_replicas=False)
 1865         snapshot = fakes.fake_snapshot(
 1866             id=uuidutils.generate_uuid(), share_id=share['id'], size=2)
 1867         mock_share_update = self.mock_object(db_api, 'share_update')
 1868         mock_share_snapshot_update = self.mock_object(
 1869             db_api, 'share_snapshot_update')
 1870         mock_revert_rpc_call = self.mock_object(
 1871             self.share_rpcapi, 'revert_to_snapshot')
 1872 
 1873         self.api._revert_to_snapshot(
 1874             self.context, share, snapshot, 'fake_reservations')
 1875 
 1876         mock_share_update.assert_called_once_with(
 1877             self.context, share['id'], {'status': constants.STATUS_REVERTING})
 1878         mock_share_snapshot_update.assert_called_once_with(
 1879             self.context, snapshot['id'],
 1880             {'status': constants.STATUS_RESTORING})
 1881         mock_revert_rpc_call.assert_called_once_with(
 1882             self.context, share, snapshot, share['instance']['host'],
 1883             'fake_reservations')
 1884 
 1885     def test_revert_to_replicated_snapshot(self):
 1886 
 1887         share = fakes.fake_share(
 1888             has_replicas=True, status=constants.STATUS_AVAILABLE)
 1889         snapshot = fakes.fake_snapshot(share_instance_id='id1')
 1890         snapshot_instance = fakes.fake_snapshot_instance(
 1891             base_snapshot=snapshot, id='sid1')
 1892         replicas = [
 1893             fakes.fake_replica(
 1894                 id='rid1', replica_state=constants.REPLICA_STATE_ACTIVE),
 1895             fakes.fake_replica(
 1896                 id='rid2', replica_state=constants.REPLICA_STATE_IN_SYNC),
 1897         ]
 1898         self.mock_object(
 1899             db_api, 'share_replicas_get_available_active_replica',
 1900             mock.Mock(return_value=replicas[0]))
 1901         self.mock_object(
 1902             db_api, 'share_snapshot_instance_get_all_with_filters',
 1903             mock.Mock(return_value=[snapshot_instance]))
 1904         mock_share_replica_update = self.mock_object(
 1905             db_api, 'share_replica_update')
 1906         mock_share_snapshot_instance_update = self.mock_object(
 1907             db_api, 'share_snapshot_instance_update')
 1908         mock_revert_rpc_call = self.mock_object(
 1909             self.share_rpcapi, 'revert_to_snapshot')
 1910 
 1911         self.api._revert_to_replicated_snapshot(
 1912             self.context, share, snapshot, 'fake_reservations')
 1913 
 1914         mock_share_replica_update.assert_called_once_with(
 1915             self.context, 'rid1', {'status': constants.STATUS_REVERTING})
 1916         mock_share_snapshot_instance_update.assert_called_once_with(
 1917             self.context, 'sid1', {'status': constants.STATUS_RESTORING})
 1918         mock_revert_rpc_call.assert_called_once_with(
 1919             self.context, share, snapshot, replicas[0]['host'],
 1920             'fake_reservations')
 1921 
 1922     def test_revert_to_replicated_snapshot_no_active_replica(self):
 1923 
 1924         share = fakes.fake_share(
 1925             has_replicas=True, status=constants.STATUS_AVAILABLE)
 1926         snapshot = fakes.fake_snapshot(share_instance_id='id1')
 1927         self.mock_object(
 1928             db_api, 'share_replicas_get_available_active_replica',
 1929             mock.Mock(return_value=None))
 1930 
 1931         self.assertRaises(exception.ReplicationException,
 1932                           self.api._revert_to_replicated_snapshot,
 1933                           self.context,
 1934                           share,
 1935                           snapshot,
 1936                           'fake_reservations')
 1937 
 1938     def test_revert_to_replicated_snapshot_no_snapshot_instance(self):
 1939 
 1940         share = fakes.fake_share(
 1941             has_replicas=True, status=constants.STATUS_AVAILABLE)
 1942         snapshot = fakes.fake_snapshot(share_instance_id='id1')
 1943         replicas = [
 1944             fakes.fake_replica(
 1945                 id='rid1', replica_state=constants.REPLICA_STATE_ACTIVE),
 1946             fakes.fake_replica(
 1947                 id='rid2', replica_state=constants.REPLICA_STATE_IN_SYNC),
 1948         ]
 1949         self.mock_object(
 1950             db_api, 'share_replicas_get_available_active_replica',
 1951             mock.Mock(return_value=replicas[0]))
 1952         self.mock_object(
 1953             db_api, 'share_snapshot_instance_get_all_with_filters',
 1954             mock.Mock(return_value=[None]))
 1955 
 1956         self.assertRaises(exception.ReplicationException,
 1957                           self.api._revert_to_replicated_snapshot,
 1958                           self.context,
 1959                           share,
 1960                           snapshot,
 1961                           'fake_reservations')
 1962 
 1963     def test_create_snapshot_for_replicated_share(self):
 1964         share = fakes.fake_share(
 1965             has_replicas=True, status=constants.STATUS_AVAILABLE)
 1966         snapshot = fakes.fake_snapshot(
 1967             create_instance=True, share_instance_id='id2')
 1968         replicas = [
 1969             fakes.fake_replica(
 1970                 id='id1', replica_state=constants.REPLICA_STATE_ACTIVE),
 1971             fakes.fake_replica(
 1972                 id='id2', replica_state=constants.REPLICA_STATE_IN_SYNC)
 1973         ]
 1974         self.mock_object(share_api.policy, 'check_policy')
 1975         self.mock_object(quota.QUOTAS, 'reserve',
 1976                          mock.Mock(return_value='reservation'))
 1977         self.mock_object(
 1978             db_api, 'share_snapshot_create', mock.Mock(return_value=snapshot))
 1979         self.mock_object(db_api, 'share_replicas_get_all_by_share',
 1980                          mock.Mock(return_value=replicas))
 1981         self.mock_object(
 1982             db_api, 'share_snapshot_get', mock.Mock(return_value=snapshot))
 1983         self.mock_object(quota.QUOTAS, 'commit')
 1984         mock_instance_create_call = self.mock_object(
 1985             db_api, 'share_snapshot_instance_create')
 1986         mock_snapshot_rpc_call = self.mock_object(
 1987             self.share_rpcapi, 'create_snapshot')
 1988         mock_replicated_snapshot_rpc_call = self.mock_object(
 1989             self.share_rpcapi, 'create_replicated_snapshot')
 1990         snapshot_instance_args = {
 1991             'status': constants.STATUS_CREATING,
 1992             'progress': '0%',
 1993             'share_instance_id': 'id1',
 1994         }
 1995 
 1996         retval = self.api.create_snapshot(
 1997             self.context, share, 'fake_name', 'fake_description')
 1998 
 1999         self.assertEqual(snapshot['id'], retval['id'])
 2000         mock_instance_create_call.assert_called_once_with(
 2001             self.context, snapshot['id'], snapshot_instance_args)
 2002         self.assertFalse(mock_snapshot_rpc_call.called)
 2003         self.assertTrue(mock_replicated_snapshot_rpc_call.called)
 2004 
 2005     @mock.patch.object(db_api, 'share_instances_get_all_by_share_server',
 2006                        mock.Mock(return_value=[]))
 2007     @mock.patch.object(db_api, 'share_group_get_all_by_share_server',
 2008                        mock.Mock(return_value=[]))
 2009     def test_delete_share_server_no_dependent_shares(self):
 2010         server = {'id': 'fake_share_server_id'}
 2011         server_returned = {
 2012             'id': 'fake_share_server_id',
 2013         }
 2014         self.mock_object(db_api, 'share_server_update',
 2015                          mock.Mock(return_value=server_returned))
 2016         self.api.delete_share_server(self.context, server)
 2017         db_api.share_instances_get_all_by_share_server.assert_called_once_with(
 2018             self.context, server['id'])
 2019         (db_api.share_group_get_all_by_share_server.
 2020             assert_called_once_with(self.context, server['id']))
 2021         self.share_rpcapi.delete_share_server.assert_called_once_with(
 2022             self.context, server_returned)
 2023 
 2024     @mock.patch.object(db_api, 'share_instances_get_all_by_share_server',
 2025                        mock.Mock(return_value=['fake_share', ]))
 2026     @mock.patch.object(db_api, 'share_group_get_all_by_share_server',
 2027                        mock.Mock(return_value=[]))
 2028     def test_delete_share_server_dependent_share_exists(self):
 2029         server = {'id': 'fake_share_server_id'}
 2030         self.assertRaises(exception.ShareServerInUse,
 2031                           self.api.delete_share_server,
 2032                           self.context,
 2033                           server)
 2034         db_api.share_instances_get_all_by_share_server.assert_called_once_with(
 2035             self.context, server['id'])
 2036 
 2037     @mock.patch.object(db_api, 'share_instances_get_all_by_share_server',
 2038                        mock.Mock(return_value=[]))
 2039     @mock.patch.object(db_api, 'share_group_get_all_by_share_server',
 2040                        mock.Mock(return_value=['fake_group', ]))
 2041     def test_delete_share_server_dependent_group_exists(self):
 2042         server = {'id': 'fake_share_server_id'}
 2043         self.assertRaises(exception.ShareServerInUse,
 2044                           self.api.delete_share_server,
 2045                           self.context,
 2046                           server)
 2047 
 2048         db_api.share_instances_get_all_by_share_server.assert_called_once_with(
 2049             self.context, server['id'])
 2050         (db_api.share_group_get_all_by_share_server.
 2051             assert_called_once_with(self.context, server['id']))
 2052 
 2053     @mock.patch.object(db_api, 'share_snapshot_instance_update', mock.Mock())
 2054     def test_delete_snapshot(self):
 2055         snapshot = db_utils.create_snapshot(
 2056             with_share=True, status=constants.STATUS_AVAILABLE)
 2057         share = snapshot['share']
 2058 
 2059         with mock.patch.object(db_api, 'share_get',
 2060                                mock.Mock(return_value=share)):
 2061             self.api.delete_snapshot(self.context, snapshot)
 2062             self.share_rpcapi.delete_snapshot.assert_called_once_with(
 2063                 self.context, snapshot, share['host'], force=False)
 2064             share_api.policy.check_policy.assert_called_once_with(
 2065                 self.context, 'share', 'delete_snapshot', snapshot)
 2066             db_api.share_snapshot_instance_update.assert_called_once_with(
 2067                 self.context,
 2068                 snapshot['instance']['id'],
 2069                 {'status': constants.STATUS_DELETING})
 2070             db_api.share_get.assert_called_once_with(
 2071                 self.context, snapshot['share_id'])
 2072 
 2073     def test_delete_snapshot_wrong_status(self):
 2074         snapshot = db_utils.create_snapshot(
 2075             with_share=True, status=constants.STATUS_CREATING)
 2076 
 2077         self.assertRaises(exception.InvalidShareSnapshot,
 2078                           self.api.delete_snapshot,
 2079                           self.context,
 2080                           snapshot)
 2081         share_api.policy.check_policy.assert_called_once_with(
 2082             self.context, 'share', 'delete_snapshot', snapshot)
 2083 
 2084     @ddt.data(constants.STATUS_MANAGING, constants.STATUS_ERROR_DELETING,
 2085               constants.STATUS_CREATING, constants.STATUS_AVAILABLE)
 2086     def test_delete_snapshot_force_delete(self, status):
 2087         share = fakes.fake_share(id=uuidutils.generate_uuid(),
 2088                                  has_replicas=False)
 2089         snapshot = fakes.fake_snapshot(aggregate_status=status, share=share)
 2090         snapshot_instance = fakes.fake_snapshot_instance(
 2091             base_snapshot=snapshot)
 2092         self.mock_object(db_api, 'share_get', mock.Mock(return_value=share))
 2093         self.mock_object(
 2094             db_api, 'share_snapshot_instance_get_all_with_filters',
 2095             mock.Mock(return_value=[snapshot_instance]))
 2096         mock_instance_update_call = self.mock_object(
 2097             db_api, 'share_snapshot_instance_update')
 2098         mock_rpc_call = self.mock_object(self.share_rpcapi, 'delete_snapshot')
 2099 
 2100         retval = self.api.delete_snapshot(self.context, snapshot, force=True)
 2101 
 2102         self.assertIsNone(retval)
 2103         mock_instance_update_call.assert_called_once_with(
 2104             self.context, snapshot_instance['id'],
 2105             {'status': constants.STATUS_DELETING})
 2106         mock_rpc_call.assert_called_once_with(
 2107             self.context, snapshot, share['instance']['host'], force=True)
 2108 
 2109     @ddt.data(True, False)
 2110     def test_delete_snapshot_replicated_snapshot(self, force):
 2111         share = fakes.fake_share(has_replicas=True)
 2112         snapshot = fakes.fake_snapshot(
 2113             create_instance=True, share_id=share['id'],
 2114             status=constants.STATUS_ERROR)
 2115         snapshot_instance = fakes.fake_snapshot_instance(
 2116             base_snapshot=snapshot)
 2117         expected_update_calls = [
 2118             mock.call(self.context, x, {'status': constants.STATUS_DELETING})
 2119             for x in (snapshot['instance']['id'], snapshot_instance['id'])
 2120         ]
 2121         self.mock_object(db_api, 'share_get', mock.Mock(return_value=share))
 2122         self.mock_object(
 2123             db_api, 'share_snapshot_instance_get_all_with_filters',
 2124             mock.Mock(return_value=[snapshot['instance'], snapshot_instance]))
 2125         mock_db_update_call = self.mock_object(
 2126             db_api, 'share_snapshot_instance_update')
 2127         mock_snapshot_rpc_call = self.mock_object(
 2128             self.share_rpcapi, 'delete_snapshot')
 2129         mock_replicated_snapshot_rpc_call = self.mock_object(
 2130             self.share_rpcapi, 'delete_replicated_snapshot')
 2131 
 2132         retval = self.api.delete_snapshot(self.context, snapshot, force=force)
 2133 
 2134         self.assertIsNone(retval)
 2135         self.assertEqual(2, mock_db_update_call.call_count)
 2136         mock_db_update_call.assert_has_calls(expected_update_calls)
 2137         mock_replicated_snapshot_rpc_call.assert_called_once_with(
 2138             self.context, snapshot, share['instance']['host'],
 2139             share_id=share['id'], force=force)
 2140         self.assertFalse(mock_snapshot_rpc_call.called)
 2141 
 2142     def test_create_snapshot_if_share_not_available(self):
 2143         share = db_utils.create_share(status=constants.STATUS_ERROR)
 2144         self.assertRaises(exception.InvalidShare,
 2145                           self.api.create_snapshot,
 2146                           self.context,
 2147                           share,
 2148                           'fakename',
 2149                           'fakedesc')
 2150         share_api.policy.check_policy.assert_called_once_with(
 2151             self.context, 'share', 'create_snapshot', share)
 2152 
 2153     def test_create_snapshot_invalid_task_state(self):
 2154         share = db_utils.create_share(
 2155             status=constants.STATUS_AVAILABLE,
 2156             task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS)
 2157         self.assertRaises(exception.ShareBusyException,
 2158                           self.api.create_snapshot,
 2159                           self.context,
 2160                           share,
 2161                           'fakename',
 2162                           'fakedesc')
 2163         share_api.policy.check_policy.assert_called_once_with(
 2164             self.context, 'share', 'create_snapshot', share)
 2165 
 2166     @ddt.data({'use_scheduler': False, 'valid_host': 'fake',
 2167                'az': None},
 2168               {'use_scheduler': True, 'valid_host': None,
 2169                'az': None},
 2170               {'use_scheduler': True, 'valid_host': None,
 2171                'az': "fakeaz2"})
 2172     @ddt.unpack
 2173     def test_create_from_snapshot(self, use_scheduler, valid_host, az):
 2174         snapshot, share, share_data, request_spec = (
 2175             self._setup_create_from_snapshot_mocks(
 2176                 use_scheduler=use_scheduler, host=valid_host)
 2177         )
 2178         share_type = fakes.fake_share_type()
 2179 
 2180         mock_get_share_type_call = self.mock_object(
 2181             share_types, 'get_share_type', mock.Mock(return_value=share_type))
 2182 
 2183         az = snapshot['share']['availability_zone'] if not az else az
 2184         self.api.create(
 2185             self.context,
 2186             share_data['share_proto'],
 2187             None,  # NOTE(u_glide): Get share size from snapshot
 2188             share_data['display_name'],
 2189             share_data['display_description'],
 2190             snapshot_id=snapshot['id'],
 2191             availability_zone=az,
 2192         )
 2193 
 2194         share_data.pop('availability_zone')
 2195 
 2196         mock_get_share_type_call.assert_called_once_with(
 2197             self.context, share['share_type_id'])
 2198         self.assertSubDictMatch(share_data,
 2199                                 db_api.share_create.call_args[0][1])
 2200         self.api.create_instance.assert_called_once_with(
 2201             self.context, share, share_network_id=share['share_network_id'],
 2202             host=valid_host, share_type_id=share_type['id'],
 2203             availability_zone=az,
 2204             share_group=None, share_group_snapshot_member=None,
 2205             availability_zones=None,
 2206             snapshot_host=snapshot['share']['instance']['host'])
 2207         share_api.policy.check_policy.assert_called_once_with(
 2208             self.context, 'share_snapshot', 'get_snapshot')
 2209         quota.QUOTAS.reserve.assert_called_once_with(
 2210             self.context, share_type_id=share_type['id'],
 2211             gigabytes=1, shares=1)
 2212         quota.QUOTAS.commit.assert_called_once_with(
 2213             self.context, 'reservation', share_type_id=share_type['id'])
 2214 
 2215     def test_create_share_share_type_contains_replication_type(self):
 2216         extra_specs = {'replication_type': constants.REPLICATION_TYPE_READABLE}
 2217         share_type = db_utils.create_share_type(extra_specs=extra_specs)
 2218         share_type = db_api.share_type_get(self.context, share_type['id'])
 2219         share, share_data = self._setup_create_mocks(
 2220             share_type_id=share_type['id'])
 2221         az = share_data.pop('availability_zone')
 2222 
 2223         self.mock_object(quota.QUOTAS, 'reserve',
 2224                          mock.Mock(return_value='reservation'))
 2225         self.mock_object(quota.QUOTAS, 'commit')
 2226 
 2227         self.api.create(
 2228             self.context,
 2229             share_data['share_proto'],
 2230             share_data['size'],
 2231             share_data['display_name'],
 2232             share_data['display_description'],
 2233             availability_zone=az,
 2234             share_type=share_type
 2235         )
 2236         quota.QUOTAS.reserve.assert_called_once_with(
 2237             self.context, share_type_id=share_type['id'],
 2238             gigabytes=1, shares=1, share_replicas=1, replica_gigabytes=1)
 2239         quota.QUOTAS.commit.assert_called_once_with(
 2240             self.context, 'reservation', share_type_id=share_type['id']
 2241         )
 2242 
 2243     def test_create_from_snapshot_az_different_from_source(self):
 2244         snapshot, share, share_data, request_spec = (
 2245             self._setup_create_from_snapshot_mocks(use_scheduler=False)
 2246         )
 2247 
 2248         self.assertRaises(exception.InvalidInput, self.api.create,
 2249                           self.context, share_data['share_proto'],
 2250                           share_data['size'],
 2251                           share_data['display_name'],
 2252                           share_data['display_description'],
 2253                           snapshot_id=snapshot['id'],
 2254                           availability_zone='fake_different_az')
 2255 
 2256     def test_create_from_snapshot_with_different_share_type(self):
 2257         snapshot, share, share_data, request_spec = (
 2258             self._setup_create_from_snapshot_mocks()
 2259         )
 2260 
 2261         share_type = {'id': 'super_fake_share_type'}
 2262 
 2263         self.assertRaises(exception.InvalidInput, self.api.create,
 2264                           self.context, share_data['share_proto'],
 2265                           share_data['size'],
 2266                           share_data['display_name'],
 2267                           share_data['display_description'],
 2268                           snapshot_id=snapshot['id'],
 2269                           availability_zone=share_data['availability_zone'],
 2270                           share_type=share_type)
 2271 
 2272     def test_get_snapshot(self):
 2273         fake_get_snap = {'fake_key': 'fake_val'}
 2274         with mock.patch.object(db_api, 'share_snapshot_get',
 2275                                mock.Mock(return_value=fake_get_snap)):
 2276             rule = self.api.get_snapshot(self.context, 'fakeid')
 2277             self.assertEqual(fake_get_snap, rule)
 2278             share_api.policy.check_policy.assert_called_once_with(
 2279                 self.context, 'share_snapshot', 'get_snapshot')
 2280             db_api.share_snapshot_get.assert_called_once_with(
 2281                 self.context, 'fakeid')
 2282 
 2283     def test_create_from_snapshot_not_available(self):
 2284         snapshot = db_utils.create_snapshot(
 2285             with_share=True, status=constants.STATUS_ERROR)
 2286         self.assertRaises(exception.InvalidShareSnapshot, self.api.create,
 2287                           self.context, 'nfs', '1', 'fakename',
 2288                           'fakedesc', snapshot_id=snapshot['id'],
 2289                           availability_zone='fakeaz')
 2290 
 2291     def test_create_from_snapshot_larger_size(self):
 2292         snapshot = db_utils.create_snapshot(
 2293             size=100, status=constants.STATUS_AVAILABLE, with_share=True)
 2294         self.assertRaises(exception.InvalidInput, self.api.create,
 2295                           self.context, 'nfs', 1, 'fakename', 'fakedesc',
 2296                           availability_zone='fakeaz',
 2297                           snapshot_id=snapshot['id'])
 2298 
 2299     def test_create_share_wrong_size_0(self):
 2300         self.assertRaises(exception.InvalidInput, self.api.create,
 2301                           self.context, 'nfs', 0, 'fakename', 'fakedesc',
 2302                           availability_zone='fakeaz')
 2303 
 2304     def test_create_share_wrong_size_some(self):
 2305         self.assertRaises(exception.InvalidInput, self.api.create,
 2306                           self.context, 'nfs', 'some', 'fakename',
 2307                           'fakedesc', availability_zone='fakeaz')
 2308 
 2309     @ddt.data(constants.STATUS_AVAILABLE, constants.STATUS_ERROR)
 2310     def test_delete(self, status):
 2311         share = self._setup_delete_mocks(status)
 2312 
 2313         self.api.delete(self.context, share)
 2314 
 2315         self.api.delete_instance.assert_called_once_with(
 2316             utils.IsAMatcher(context.RequestContext),
 2317             utils.IsAMatcher(models.ShareInstance), force=False
 2318         )
 2319         db_api.share_snapshot_get_all_for_share.assert_called_once_with(
 2320             utils.IsAMatcher(context.RequestContext), share['id'])
 2321 
 2322     def test_delete_quota_with_different_user(self):
 2323         share = self._setup_delete_mocks(constants.STATUS_AVAILABLE)
 2324         diff_user_context = context.RequestContext(
 2325             user_id='fake2',
 2326             project_id='fake',
 2327             is_admin=False
 2328         )
 2329 
 2330         self.api.delete(diff_user_context, share)
 2331 
 2332     def test_delete_wrong_status(self):
 2333         share = fakes.fake_share(status='wrongstatus')
 2334         self.mock_object(db_api, 'share_get', mock.Mock(return_value=share))
 2335         self.assertRaises(exception.InvalidShare, self.api.delete,
 2336                           self.context, share)
 2337 
 2338     def test_delete_share_has_replicas(self):
 2339         share = self._setup_delete_mocks(constants.STATUS_AVAILABLE,
 2340                                          replication_type='writable')
 2341         db_utils.create_share_replica(share_id=share['id'],
 2342                                       replica_state='in_sync')
 2343         db_utils.create_share_replica(share_id=share['id'],
 2344                                       replica_state='out_of_sync')
 2345 
 2346         self.assertRaises(exception.Conflict, self.api.delete,
 2347                           self.context, share)
 2348 
 2349     @mock.patch.object(db_api, 'count_share_group_snapshot_members_in_share',
 2350                        mock.Mock(return_value=2))
 2351     def test_delete_dependent_share_group_snapshot_members(self):
 2352         share_server_id = 'fake-ss-id'
 2353         share = self._setup_delete_mocks(constants.STATUS_AVAILABLE,
 2354                                          share_server_id)
 2355 
 2356         self.assertRaises(exception.InvalidShare, self.api.delete,
 2357                           self.context, share)
 2358 
 2359     @mock.patch.object(db_api, 'share_instance_delete', mock.Mock())
 2360     def test_delete_no_host(self):
 2361         share = self._setup_delete_mocks(constants.STATUS_AVAILABLE, host=None)
 2362 
 2363         self.api.delete(self.context, share)
 2364         db_api.share_instance_delete.assert_called_once_with(
 2365             utils.IsAMatcher(context.RequestContext), share.instance['id'],
 2366             need_to_update_usages=True)
 2367 
 2368     def test_delete_share_with_snapshots(self):
 2369         share = self._setup_delete_mocks(constants.STATUS_AVAILABLE,
 2370                                          snapshots=['fake'])
 2371 
 2372         self.assertRaises(
 2373             exception.InvalidShare,
 2374             self.api.delete,
 2375             self.context,
 2376             share
 2377         )
 2378 
 2379     def test_delete_share_invalid_task_state(self):
 2380         share = db_utils.create_share(
 2381             status=constants.STATUS_AVAILABLE,
 2382             task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS)
 2383 
 2384         self.assertRaises(exception.ShareBusyException,
 2385                           self.api.delete,
 2386                           self.context, share)
 2387 
 2388     def test_delete_share_quota_error(self):
 2389         share = self._setup_delete_mocks(constants.STATUS_AVAILABLE)
 2390         self.mock_object(quota.QUOTAS, 'reserve',
 2391                          mock.Mock(side_effect=exception.QuotaError('fake')))
 2392 
 2393         self.api.delete(self.context, share)
 2394 
 2395     @ddt.data({'status': constants.STATUS_AVAILABLE, 'force': False},
 2396               {'status': constants.STATUS_ERROR, 'force': True})
 2397     @ddt.unpack
 2398     def test_delete_share_instance(self, status, force):
 2399         instance = self._setup_delete_share_instance_mocks(
 2400             status=status, share_server_id='fake')
 2401 
 2402         self.api.delete_instance(self.context, instance, force=force)
 2403 
 2404         db_api.share_instance_update.assert_called_once_with(
 2405             self.context,
 2406             instance['id'],
 2407             {'status': constants.STATUS_DELETING,
 2408              'terminated_at': self.dt_utc}
 2409         )
 2410         self.api.share_rpcapi.delete_share_instance.assert_called_once_with(
 2411             self.context, instance, force=force
 2412         )
 2413         db_api.share_server_update(
 2414             self.context,
 2415             instance['share_server_id'],
 2416             {'updated_at': self.dt_utc}
 2417         )
 2418 
 2419     def test_delete_share_instance_invalid_status(self):
 2420         instance = self._setup_delete_share_instance_mocks(
 2421             status=constants.STATUS_CREATING, share_server_id='fake')
 2422 
 2423         self.assertRaises(
 2424             exception.InvalidShareInstance,
 2425             self.api.delete_instance,
 2426             self.context,
 2427             instance
 2428         )
 2429 
 2430     def test_get(self):
 2431         share = db_utils.create_share()
 2432         with mock.patch.object(db_api, 'share_get',
 2433                                mock.Mock(return_value=share)):
 2434             result = self.api.get(self.context, 'fakeid')
 2435             self.assertEqual(share, result)
 2436             share_api.policy.check_policy.assert_called_once_with(
 2437                 self.context, 'share', 'get', share)
 2438             db_api.share_get.assert_called_once_with(
 2439                 self.context, 'fakeid')
 2440 
 2441     @mock.patch.object(db_api, 'share_snapshot_get_all_by_project',
 2442                        mock.Mock())
 2443     def test_get_all_snapshots_admin_not_all_tenants(self):
 2444         ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=True)
 2445         self.api.get_all_snapshots(ctx)
 2446         share_api.policy.check_policy.assert_called_once_with(
 2447             ctx, 'share_snapshot', 'get_all_snapshots')
 2448         db_api.share_snapshot_get_all_by_project.assert_called_once_with(
 2449             ctx, 'fakepid', sort_dir='desc', sort_key='share_id', filters={})
 2450 
 2451     @mock.patch.object(db_api, 'share_snapshot_get_all', mock.Mock())
 2452     def test_get_all_snapshots_admin_all_tenants(self):
 2453         self.api.get_all_snapshots(self.context,
 2454                                    search_opts={'all_tenants': 1})
 2455         share_api.policy.check_policy.assert_called_once_with(
 2456             self.context, 'share_snapshot', 'get_all_snapshots')
 2457         db_api.share_snapshot_get_all.assert_called_once_with(
 2458             self.context, sort_dir='desc', sort_key='share_id', filters={})
 2459 
 2460     @mock.patch.object(db_api, 'share_snapshot_get_all_by_project',
 2461                        mock.Mock())
 2462     def test_get_all_snapshots_not_admin(self):
 2463         ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=False)
 2464         self.api.get_all_snapshots(ctx)
 2465         share_api.policy.check_policy.assert_called_once_with(
 2466             ctx, 'share_snapshot', 'get_all_snapshots')
 2467         db_api.share_snapshot_get_all_by_project.assert_called_once_with(
 2468             ctx, 'fakepid', sort_dir='desc', sort_key='share_id', filters={})
 2469 
 2470     def test_get_all_snapshots_not_admin_search_opts(self):
 2471         search_opts = {'size': 'fakesize'}
 2472         fake_objs = [{'name': 'fakename1'}, search_opts]
 2473         ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=False)
 2474         self.mock_object(db_api, 'share_snapshot_get_all_by_project',
 2475                          mock.Mock(return_value=fake_objs))
 2476 
 2477         result = self.api.get_all_snapshots(ctx, search_opts)
 2478 
 2479         self.assertEqual([search_opts], result)
 2480         share_api.policy.check_policy.assert_called_once_with(
 2481             ctx, 'share_snapshot', 'get_all_snapshots')
 2482         db_api.share_snapshot_get_all_by_project.assert_called_once_with(
 2483             ctx, 'fakepid', sort_dir='desc', sort_key='share_id',
 2484             filters=search_opts)
 2485 
 2486     @ddt.data(({'name': 'fo'}, 0), ({'description': 'd'}, 0),
 2487               ({'name': 'foo', 'description': 'd'}, 0),
 2488               ({'name': 'foo'}, 1), ({'description': 'ds'}, 1),
 2489               ({'name~': 'foo', 'description~': 'ds'}, 2),
 2490               ({'name': 'foo', 'description~': 'ds'}, 1),
 2491               ({'name~': 'foo', 'description': 'ds'}, 1))
 2492     @ddt.unpack
 2493     def test_get_all_snapshots_filter_by_name_and_description(
 2494             self, search_opts, get_snapshot_number):
 2495         fake_objs = [{'name': 'fo2', 'description': 'd2'},
 2496                      {'name': 'foo', 'description': 'ds'},
 2497                      {'name': 'foo1', 'description': 'ds1'}]
 2498         ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=False)
 2499         self.mock_object(db_api, 'share_snapshot_get_all_by_project',
 2500                          mock.Mock(return_value=fake_objs))
 2501 
 2502         result = self.api.get_all_snapshots(ctx, search_opts)
 2503 
 2504         self.assertEqual(get_snapshot_number, len(result))
 2505         if get_snapshot_number == 2:
 2506             self.assertEqual(fake_objs[1:], result)
 2507         elif get_snapshot_number == 1:
 2508             self.assertEqual(fake_objs[1:2], result)
 2509 
 2510         share_api.policy.check_policy.assert_called_once_with(
 2511             ctx, 'share_snapshot', 'get_all_snapshots')
 2512         db_api.share_snapshot_get_all_by_project.assert_called_once_with(
 2513             ctx, 'fakepid', sort_dir='desc', sort_key='share_id',
 2514             filters=search_opts)
 2515 
 2516     def test_get_all_snapshots_with_sorting_valid(self):
 2517         self.mock_object(
 2518             db_api, 'share_snapshot_get_all_by_project',
 2519             mock.Mock(return_value=_FAKE_LIST_OF_ALL_SNAPSHOTS[0]))
 2520         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
 2521         snapshots = self.api.get_all_snapshots(
 2522             ctx, sort_key='status', sort_dir='asc')
 2523         share_api.policy.check_policy.assert_called_once_with(
 2524             ctx, 'share_snapshot', 'get_all_snapshots')
 2525         db_api.share_snapshot_get_all_by_project.assert_called_once_with(
 2526             ctx, 'fake_pid_1', sort_dir='asc', sort_key='status', filters={})
 2527         self.assertEqual(_FAKE_LIST_OF_ALL_SNAPSHOTS[0], snapshots)
 2528 
 2529     def test_get_all_snapshots_sort_key_invalid(self):
 2530         self.mock_object(
 2531             db_api, 'share_snapshot_get_all_by_project',
 2532             mock.Mock(return_value=_FAKE_LIST_OF_ALL_SNAPSHOTS[0]))
 2533         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
 2534         self.assertRaises(
 2535             exception.InvalidInput,
 2536             self.api.get_all_snapshots,
 2537             ctx,
 2538             sort_key=1,
 2539         )
 2540         share_api.policy.check_policy.assert_called_once_with(
 2541             ctx, 'share_snapshot', 'get_all_snapshots')
 2542 
 2543     def test_get_all_snapshots_sort_dir_invalid(self):
 2544         self.mock_object(
 2545             db_api, 'share_snapshot_get_all_by_project',
 2546             mock.Mock(return_value=_FAKE_LIST_OF_ALL_SNAPSHOTS[0]))
 2547         ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
 2548         self.assertRaises(
 2549             exception.InvalidInput,
 2550             self.api.get_all_snapshots,
 2551             ctx,
 2552             sort_dir=1,
 2553         )
 2554         share_api.policy.check_policy.assert_called_once_with(
 2555             ctx, 'share_snapshot', 'get_all_snapshots')
 2556 
 2557     def test_allow_access_rule_already_exists(self):
 2558         share = db_utils.create_share(status=constants.STATUS_AVAILABLE)
 2559         fake_access = db_utils.create_access(share_id=share['id'])
 2560         self.mock_object(self.api.db, 'share_access_create')
 2561 
 2562         self.assertRaises(
 2563             exception.ShareAccessExists, self.api.allow_access,
 2564             self.context, share, fake_access['access_type'],
 2565             fake_access['access_to'], fake_access['access_level'])
 2566         self.assertFalse(self.api.db.share_access_create.called)
 2567 
 2568     def test_allow_access_invalid_access_level(self):
 2569         share = db_utils.create_share(status=constants.STATUS_AVAILABLE)
 2570         self.mock_object(self.api.db, 'share_access_create')
 2571 
 2572         self.assertRaises(
 2573             exception.InvalidShareAccess, self.api.allow_access,
 2574             self.context, share, 'user', 'alice', access_level='execute')
 2575         self.assertFalse(self.api.db.share_access_create.called)
 2576 
 2577     @ddt.data({'host': None},
 2578               {'status': constants.STATUS_ERROR_DELETING,
 2579                'access_rules_status': constants.STATUS_ACTIVE},
 2580               {'host': None, 'access_rules_status': constants.STATUS_ERROR},
 2581               {'access_rules_status': constants.STATUS_ERROR})
 2582     def test_allow_access_invalid_instance(self, params):
 2583         share = db_utils.create_share(host='fake')
 2584         db_utils.create_share_instance(share_id=share['id'])
 2585         db_utils.create_share_instance(share_id=share['id'], **params)
 2586         self.mock_object(self.api.db, 'share_access_create')
 2587 
 2588         self.assertRaises(exception.InvalidShare, self.api.allow_access,
 2589                           self.context, share, 'ip', '10.0.0.1')
 2590         self.assertFalse(self.api.db.share_access_create.called)
 2591 
 2592     @ddt.data(*(constants.ACCESS_LEVELS + (None,)))
 2593     def test_allow_access(self, level):
 2594         share = db_utils.create_share(status=constants.STATUS_AVAILABLE)
 2595         values = {
 2596             'share_id': share['id'],
 2597             'access_type': 'fake_access_type',
 2598             'access_to': 'fake_access_to',
 2599             'access_level': level,
 2600             'metadata': None,
 2601         }
 2602         fake_access = copy.deepcopy(values)
 2603         fake_access.update({
 2604             'id': 'fake_access_id',
 2605             'state': constants.STATUS_ACTIVE,
 2606             'deleted': 'fake_deleted',
 2607             'deleted_at': 'fake_deleted_at',
 2608             'instance_mappings': ['foo', 'bar'],
 2609         })
 2610         self.mock_object(db_api, 'share_get',
 2611                          mock.Mock(return_value=share))
 2612         self.mock_object(db_api, 'share_access_create',
 2613                          mock.Mock(return_value=fake_access))
 2614         self.mock_object(db_api, 'share_access_get',
 2615                          mock.Mock(return_value=fake_access))
 2616         self.mock_object(db_api, 'share_access_get_all_by_type_and_access',
 2617                          mock.Mock(return_value=[]))
 2618         self.mock_object(self.api, 'allow_access_to_instance')
 2619 
 2620         access = self.api.allow_access(
 2621             self.context, share, fake_access['access_type'],
 2622             fake_access['access_to'], level)
 2623 
 2624         self.assertEqual(fake_access, access)
 2625         db_api.share_access_create.assert_called_once_with(
 2626             self.context, values)
 2627         self.api.allow_access_to_instance.assert_called_once_with(
 2628             self.context, share.instance)
 2629 
 2630     def test_allow_access_to_instance(self):
 2631         share = db_utils.create_share(host='fake')
 2632         rpc_method = self.mock_object(self.api.share_rpcapi, 'update_access')
 2633 
 2634         self.api.allow_access_to_instance(self.context, share.instance)
 2635 
 2636         rpc_method.assert_called_once_with(self.context, share.instance)
 2637 
 2638     @ddt.data({'host': None},
 2639               {'status': constants.STATUS_ERROR_DELETING,
 2640                'access_rules_status': constants.STATUS_ACTIVE},
 2641               {'host': None, 'access_rules_status': constants.STATUS_ERROR},
 2642               {'access_rules_status': constants.STATUS_ERROR})
 2643     def test_deny_access_invalid_instance(self, params):
 2644         share = db_utils.create_share(host='fake')
 2645         db_utils.create_share_instance(share_id=share['id'])
 2646         db_utils.create_share_instance(share_id=share['id'], **params)
 2647         access_rule = db_utils.create_access(share_id=share['id'])
 2648         self.mock_object(self.api, 'deny_access_to_instance')
 2649 
 2650         self.assertRaises(exception.InvalidShare, self.api.deny_access,
 2651                           self.context, share, access_rule)
 2652         self.assertFalse(self.api.deny_access_to_instance.called)
 2653 
 2654     def test_deny_access(self):
 2655         share = db_utils.create_share(
 2656             host='fake', status=constants.STATUS_AVAILABLE,
 2657             access_rules_status=constants.STATUS_ACTIVE)
 2658         access_rule = db_utils.create_access(share_id=share['id'])
 2659         self.mock_object(self.api, 'deny_access_to_instance')
 2660 
 2661         retval = self.api.deny_access(self.context, share, access_rule)
 2662 
 2663         self.assertIsNone(retval)
 2664         self.api.deny_access_to_instance.assert_called_once_with(
 2665             self.context, share.instance, access_rule)
 2666 
 2667     def test_deny_access_to_instance(self):
 2668         share = db_utils.create_share(host='fake')
 2669         share_instance = db_utils.create_share_instance(
 2670             share_id=share['id'], host='fake')
 2671         access = db_utils.create_access(share_id=share['id'])
 2672         rpc_method = self.mock_object(self.api.share_rpcapi, 'update_access')
 2673         self.mock_object(db_api, 'share_instance_access_get',
 2674                          mock.Mock(return_value=access.instance_mappings[0]))
 2675         mock_share_instance_rules_status_update = self.mock_object(
 2676             self.api.access_helper,
 2677             'get_and_update_share_instance_access_rules_status')
 2678         mock_access_rule_state_update = self.mock_object(
 2679             self.api.access_helper,
 2680             'get_and_update_share_instance_access_rule')
 2681 
 2682         self.api.deny_access_to_instance(self.context, share_instance, access)
 2683 
 2684         rpc_method.assert_called_once_with(self.context, share_instance)
 2685         mock_access_rule_state_update.assert_called_once_with(
 2686             self.context, access['id'],
 2687             updates={'state': constants.ACCESS_STATE_QUEUED_TO_DENY},
 2688             share_instance_id=share_instance['id'])
 2689         expected_conditional_change = {
 2690             constants.STATUS_ACTIVE: constants.SHARE_INSTANCE_RULES_SYNCING,
 2691         }
 2692         mock_share_instance_rules_status_update.assert_called_once_with(
 2693             self.context, share_instance_id=share_instance['id'],
 2694             conditionally_change=expected_conditional_change)
 2695 
 2696     def test_access_get(self):
 2697         with mock.patch.object(db_api, 'share_access_get',
 2698                                mock.Mock(return_value='fake')):
 2699             rule = self.api.access_get(self.context, 'fakeid')
 2700             self.assertEqual('fake', rule)
 2701             db_api.share_access_get.assert_called_once_with(
 2702                 self.context, 'fakeid')
 2703 
 2704     def test_access_get_all(self):
 2705         share = db_utils.create_share(id='fakeid')
 2706 
 2707         values = {
 2708             'fakeacc0id': {
 2709                 'id': 'fakeacc0id',
 2710                 'access_type': 'fakeacctype',
 2711                 'access_to': 'fakeaccto',
 2712                 'access_level': 'rw',
 2713                 'share_id': share['id'],
 2714             },
 2715             'fakeacc1id': {
 2716                 'id': 'fakeacc1id',
 2717                 'access_type': 'fakeacctype',
 2718                 'access_to': 'fakeaccto',
 2719                 'access_level': 'rw',
 2720                 'share_id': share['id'],
 2721             },
 2722         }
 2723         rules = [
 2724             db_utils.create_access(**values['fakeacc0id']),
 2725             db_utils.create_access(**values['fakeacc1id']),
 2726         ]
 2727 
 2728         # add state property
 2729         values['fakeacc0id']['state'] = constants.STATUS_ACTIVE
 2730         values['fakeacc1id']['state'] = constants.STATUS_ACTIVE
 2731 
 2732         self.mock_object(db_api, 'share_access_get_all_for_share',
 2733                          mock.Mock(return_value=rules))
 2734         actual = self.api.access_get_all(self.context, share)
 2735 
 2736         self.assertEqual(rules, actual)
 2737         share_api.policy.check_policy.assert_called_once_with(
 2738             self.context, 'share', 'access_get_all')
 2739         db_api.share_access_get_all_for_share.assert_called_once_with(
 2740             self.context, 'fakeid', filters=None)
 2741 
 2742     def test_share_metadata_get(self):
 2743         metadata = {'a': 'b', 'c': 'd'}
 2744         share_id = uuidutils.generate_uuid()
 2745         db_api.share_create(self.context,
 2746                             {'id': share_id, 'metadata': metadata})
 2747         self.assertEqual(metadata,
 2748                          db_api.share_metadata_get(self.context, share_id))
 2749 
 2750     def test_share_metadata_update(self):
 2751         metadata1 = {'a': '1', 'c': '2'}
 2752         metadata2 = {'a': '3', 'd': '5'}
 2753         should_be = {'a': '3', 'c': '2', 'd': '5'}
 2754         share_id = uuidutils.generate_uuid()
 2755         db_api.share_create(self.context,
 2756                             {'id': share_id, 'metadata': metadata1})
 2757         db_api.share_metadata_update(self.context, share_id, metadata2, False)
 2758         self.assertEqual(should_be,
 2759                          db_api.share_metadata_get(self.context, share_id))
 2760 
 2761     def test_share_metadata_update_delete(self):
 2762         metadata1 = {'a': '1', 'c': '2'}
 2763         metadata2 = {'a': '3', 'd': '4'}
 2764         should_be = metadata2
 2765         share_id = uuidutils.generate_uuid()
 2766         db_api.share_create(self.context,
 2767                             {'id': share_id, 'metadata': metadata1})
 2768         db_api.share_metadata_update(self.context, share_id, metadata2, True)
 2769         self.assertEqual(should_be,
 2770                          db_api.share_metadata_get(self.context, share_id))
 2771 
 2772     def test_extend_invalid_status(self):
 2773         invalid_status = 'fake'
 2774         share = db_utils.create_share(status=invalid_status)
 2775         new_size = 123
 2776 
 2777         self.assertRaises(exception.InvalidShare,
 2778                           self.api.extend, self.context, share, new_size)
 2779 
 2780     def test_extend_invalid_task_state(self):
 2781         share = db_utils.create_share(
 2782             status=constants.STATUS_AVAILABLE,
 2783             task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS)
 2784         new_size = 123
 2785 
 2786         self.assertRaises(exception.ShareBusyException,
 2787                           self.api.extend, self.context, share, new_size)
 2788 
 2789     def test_extend_invalid_size(self):
 2790         share = db_utils.create_share(status=constants.STATUS_AVAILABLE,
 2791                                       size=200)
 2792         new_size = 123
 2793 
 2794         self.assertRaises(exception.InvalidInput,
 2795                           self.api.extend, self.context, share, new_size)
 2796 
 2797     def _setup_extend_mocks(self, supports_replication):
 2798         replica_list = []
 2799         if supports_replication:
 2800             replica_list.append({'id': 'fake_replica_id'})
 2801             replica_list.append({'id': 'fake_replica_id_2'})
 2802         self.mock_object(db_api, 'share_replicas_get_all_by_share',
 2803                          mock.Mock(return_value=replica_list))
 2804 
 2805     @ddt.data(
 2806         (False, 'gigabytes', exception.ShareSizeExceedsAvailableQuota),
 2807         (True, 'replica_gigabytes',
 2808          exception.ShareReplicaSizeExceedsAvailableQuota)
 2809     )
 2810     @ddt.unpack
 2811     def test_extend_quota_error(self, supports_replication, quota_key,
 2812                                 expected_exception):
 2813         self._setup_extend_mocks(supports_replication)
 2814         share = db_utils.create_share(status=constants.STATUS_AVAILABLE,
 2815                                       size=100)
 2816         new_size = 123
 2817         replica_amount = len(
 2818             db_api.share_replicas_get_all_by_share.return_value)
 2819         value_to_be_extended = new_size - share['size']
 2820         usages = {quota_key: {'reserved': 11, 'in_use': 12}}
 2821         quotas = {quota_key: 13}
 2822         overs = {quota_key: new_size}
 2823         exc = exception.OverQuota(usages=usages, quotas=quotas, overs=overs)
 2824         expected_deltas = {
 2825             'project_id': share['project_id'],
 2826             'gigabytes': value_to_be_extended,
 2827             'user_id': share['user_id'],
 2828             'share_type_id': share['instance']['share_type_id']
 2829         }
 2830         if supports_replication:
 2831             expected_deltas.update(
 2832                 {'replica_gigabytes': value_to_be_extended * replica_amount})
 2833         self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc))
 2834 
 2835         self.assertRaises(expected_exception,
 2836                           self.api.extend, self.context, share, new_size)
 2837         quota.QUOTAS.reserve.assert_called_once_with(
 2838             mock.ANY, **expected_deltas
 2839         )
 2840 
 2841     def test_extend_quota_user(self):
 2842         self._setup_extend_mocks(False)
 2843         share = db_utils.create_share(status=constants.STATUS_AVAILABLE,
 2844                                       size=100)
 2845         diff_user_context = context.RequestContext(
 2846             user_id='fake2',
 2847             project_id='fake',
 2848             is_admin=False
 2849         )
 2850         new_size = 123
 2851         size_increase = int(new_size) - share['size']
 2852         self.mock_object(quota.QUOTAS, 'reserve')
 2853 
 2854         self.api.extend(diff_user_context, share, new_size)
 2855 
 2856         quota.QUOTAS.reserve.assert_called_once_with(
 2857             diff_user_context,
 2858             project_id=share['project_id'],
 2859             gigabytes=size_increase,
 2860             share_type_id=None,
 2861             user_id=share['user_id']
 2862         )
 2863 
 2864     @ddt.data(True, False)
 2865     def test_extend_valid(self, supports_replication):
 2866         self._setup_extend_mocks(supports_replication)
 2867         share = db_utils.create_share(status=constants.STATUS_AVAILABLE,
 2868                                       size=100)
 2869         new_size = 123
 2870         size_increase = int(new_size) - share['size']
 2871         replica_amount = len(
 2872             db_api.share_replicas_get_all_by_share.return_value)
 2873 
 2874         expected_deltas = {
 2875             'project_id': share['project_id'],
 2876             'gigabytes': size_increase,
 2877             'user_id': share['user_id'],
 2878             'share_type_id': share['instance']['share_type_id']
 2879         }
 2880         if supports_replication:
 2881             new_replica_size = size_increase * replica_amount
 2882             expected_deltas.update({'replica_gigabytes': new_replica_size})
 2883         self.mock_object(self.api, 'update')
 2884         self.mock_object(self.api.share_rpcapi, 'extend_share')
 2885         self.mock_object(quota.QUOTAS, 'reserve')
 2886 
 2887         self.api.extend(self.context, share, new_size)
 2888 
 2889         self.api.update.assert_called_once_with(
 2890             self.context, share, {'status': constants.STATUS_EXTENDING})
 2891         self.api.share_rpcapi.extend_share.assert_called_once_with(
 2892             self.context, share, new_size, mock.ANY
 2893         )
 2894         quota.QUOTAS.reserve.assert_called_once_with(
 2895             self.context, **expected_deltas)
 2896 
 2897     def test_shrink_invalid_status(self):
 2898         invalid_status = 'fake'
 2899         share = db_utils.create_share(status=invalid_status)
 2900 
 2901         self.assertRaises(exception.InvalidShare,
 2902                           self.api.shrink, self.context, share, 123)
 2903 
 2904     def test_shrink_invalid_task_state(self):
 2905         share = db_utils.create_share(
 2906             status=constants.STATUS_AVAILABLE,
 2907             task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS)
 2908 
 2909         self.assertRaises(exception.ShareBusyException,
 2910                           self.api.shrink, self.context, share, 123)
 2911 
 2912     @ddt.data(300, 0, -1)
 2913     def test_shrink_invalid_size(self, new_size):
 2914         share = db_utils.create_share(status=constants.STATUS_AVAILABLE,
 2915                                       size=200)
 2916 
 2917         self.assertRaises(exception.InvalidInput,
 2918                           self.api.shrink, self.context, share, new_size)
 2919 
 2920     @ddt.data(constants.STATUS_AVAILABLE,
 2921               constants.STATUS_SHRINKING_POSSIBLE_DATA_LOSS_ERROR)
 2922     def test_shrink_valid(self, share_status):
 2923         share = db_utils.create_share(status=share_status, size=100)
 2924         new_size = 50
 2925         self.mock_object(self.api, 'update')
 2926         self.mock_object(self.api.share_rpcapi, 'shrink_share')
 2927 
 2928         self.api.shrink(self.context, share, new_size)
 2929 
 2930         self.api.update.assert_called_once_with(
 2931             self.context, share, {'status': constants.STATUS_SHRINKING})
 2932         self.api.share_rpcapi.shrink_share.assert_called_once_with(
 2933             self.context, share, new_size
 2934         )
 2935 
 2936     def test_snapshot_allow_access(self):
 2937         access_to = '1.1.1.1'
 2938         access_type = 'ip'
 2939         share = db_utils.create_share()
 2940         snapshot = db_utils.create_snapshot(share_id=share['id'],
 2941                                             status=constants.STATUS_AVAILABLE)
 2942         access = db_utils.create_snapshot_access(
 2943             share_snapshot_id=snapshot['id'])
 2944         values = {'share_snapshot_id': snapshot['id'],
 2945                   'access_type': access_type,
 2946                   'access_to': access_to}
 2947 
 2948         existing_access_check = self.mock_object(
 2949             db_api, 'share_snapshot_check_for_existing_access',
 2950             mock.Mock(return_value=False))
 2951         access_create = self.mock_object(
 2952             db_api, 'share_snapshot_access_create',
 2953             mock.Mock(return_value=access))
 2954         self.mock_object(self.api.share_rpcapi, 'snapshot_update_access')
 2955 
 2956         out = self.api.snapshot_allow_access(self.context, snapshot,
 2957                                              access_type, access_to)
 2958 
 2959         self.assertEqual(access, out)
 2960         existing_access_check.assert_called_once_with(
 2961             utils.IsAMatcher(context.RequestContext), snapshot['id'],
 2962             access_type, access_to)
 2963         access_create.assert_called_once_with(
 2964             utils.IsAMatcher(context.RequestContext), values)
 2965 
 2966     def test_snapshot_allow_access_instance_exception(self):
 2967         access_to = '1.1.1.1'
 2968         access_type = 'ip'
 2969         share = db_utils.create_share()
 2970         snapshot = db_utils.create_snapshot(share_id=share['id'])
 2971         existing_access_check = self.mock_object(
 2972             db_api, 'share_snapshot_check_for_existing_access',
 2973             mock.Mock(return_value=False))
 2974 
 2975         self.assertRaises(exception.InvalidShareSnapshotInstance,
 2976                           self.api.snapshot_allow_access, self.context,
 2977                           snapshot, access_type, access_to)
 2978 
 2979         existing_access_check.assert_called_once_with(
 2980             utils.IsAMatcher(context.RequestContext), snapshot['id'],
 2981             access_type, access_to)
 2982 
 2983     def test_snapshot_allow_access_access_exists_exception(self):
 2984         access_to = '1.1.1.1'
 2985         access_type = 'ip'
 2986         share = db_utils.create_share()
 2987         snapshot = db_utils.create_snapshot(share_id=share['id'])
 2988         db_utils.create_snapshot_access(
 2989             share_snapshot_id=snapshot['id'], access_to=access_to,
 2990             access_type=access_type)
 2991 
 2992         existing_access_check = self.mock_object(
 2993             db_api, 'share_snapshot_check_for_existing_access',
 2994             mock.Mock(return_value=True))
 2995 
 2996         self.assertRaises(exception.ShareSnapshotAccessExists,
 2997                           self.api.snapshot_allow_access, self.context,
 2998                           snapshot, access_type, access_to)
 2999 
 3000         existing_access_check.assert_called_once_with(
 3001             utils.IsAMatcher(context.RequestContext), snapshot['id'],
 3002             access_type, access_to)
 3003 
 3004     def test_snapshot_deny_access(self):
 3005         share = db_utils.create_share()
 3006         snapshot = db_utils.create_snapshot(share_id=share['id'],
 3007                                             status=constants.STATUS_AVAILABLE)
 3008         access = db_utils.create_snapshot_access(
 3009             share_snapshot_id=snapshot['id'])
 3010         mapping = {'id': 'fake_id',
 3011                    'state': constants.STATUS_ACTIVE,
 3012                    'access_id': access['id']}
 3013 
 3014         access_get = self.mock_object(
 3015             db_api, 'share_snapshot_instance_access_get',
 3016             mock.Mock(return_value=mapping))
 3017         access_update_state = self.mock_object(
 3018             db_api, 'share_snapshot_instance_access_update')
 3019         update_access = self.mock_object(self.api.share_rpcapi,
 3020                                          'snapshot_update_access')
 3021 
 3022         self.api.snapshot_deny_access(self.context, snapshot, access)
 3023 
 3024         access_get.assert_called_once_with(
 3025             utils.IsAMatcher(context.RequestContext), access['id'],
 3026             snapshot['instance']['id'])
 3027         access_update_state.assert_called_once_with(
 3028             utils.IsAMatcher(context.RequestContext), access['id'],
 3029             snapshot.instance['id'],
 3030             {'state': constants.ACCESS_STATE_QUEUED_TO_DENY})
 3031         update_access.assert_called_once_with(
 3032             utils.IsAMatcher(context.RequestContext), snapshot['instance'])
 3033 
 3034     def test_snapshot_deny_access_exception(self):
 3035         share = db_utils.create_share()
 3036         snapshot = db_utils.create_snapshot(share_id=share['id'])
 3037         access = db_utils.create_snapshot_access(
 3038             share_snapshot_id=snapshot['id'])
 3039 
 3040         self.assertRaises(exception.InvalidShareSnapshotInstance,
 3041                           self.api.snapshot_deny_access, self.context,
 3042                           snapshot, access)
 3043 
 3044     def test_snapshot_access_get_all(self):
 3045         share = db_utils.create_share()
 3046         snapshot = db_utils.create_snapshot(share_id=share['id'])
 3047         access = []
 3048         access.append(db_utils.create_snapshot_access(
 3049             share_snapshot_id=snapshot['id']))
 3050 
 3051         self.mock_object(
 3052             db_api, 'share_snapshot_access_get_all_for_share_snapshot',
 3053             mock.Mock(return_value=access))
 3054 
 3055         out = self.api.snapshot_access_get_all(self.context, snapshot)
 3056 
 3057         self.assertEqual(access, out)
 3058 
 3059     def test_snapshot_access_get(self):
 3060         share = db_utils.create_share()
 3061         snapshot = db_utils.create_snapshot(share_id=share['id'])
 3062         access = db_utils.create_snapshot_access(
 3063             share_snapshot_id=snapshot['id'])
 3064 
 3065         self.mock_object(
 3066             db_api, 'share_snapshot_access_get',
 3067             mock.Mock(return_value=access))
 3068 
 3069         out = self.api.snapshot_access_get(self.context, access['id'])
 3070 
 3071         self.assertEqual(access, out)
 3072 
 3073     def test_snapshot_export_locations_get(self):
 3074         share = db_utils.create_share()
 3075         snapshot = db_utils.create_snapshot(share_id=share['id'])
 3076 
 3077         self.mock_object(
 3078             db_api, 'share_snapshot_export_locations_get',
 3079             mock.Mock(return_value=''))
 3080 
 3081         out = self.api.snapshot_export_locations_get(self.context, snapshot)
 3082 
 3083         self.assertEqual('', out)
 3084 
 3085     def test_snapshot_export_location_get(self):
 3086         fake_el = '/fake_export_location'
 3087 
 3088         self.mock_object(
 3089             db_api, 'share_snapshot_instance_export_location_get',
 3090             mock.Mock(return_value=fake_el))
 3091 
 3092         out = self.api.snapshot_export_location_get(self.context, 'fake_id')
 3093 
 3094         self.assertEqual(fake_el, out)
 3095 
 3096     @ddt.data({'share_type': True, 'share_net': True, 'dhss': True},
 3097               {'share_type': False, 'share_net': True, 'dhss': True},
 3098               {'share_type': False, 'share_net': False, 'dhss': True},
 3099               {'share_type': True, 'share_net': False, 'dhss': False},
 3100               {'share_type': False, 'share_net': False, 'dhss': False})
 3101     @ddt.unpack
 3102     def test_migration_start(self, share_type, share_net, dhss):
 3103         host = 'fake2@backend#pool'
 3104         service = {'availability_zone_id': 'fake_az_id',
 3105                    'availability_zone': {'name': 'fake_az1'}}
 3106         share_network = None
 3107         share_network_id = None
 3108         if share_net:
 3109             share_network = db_utils.create_share_network(id='fake_net_id')
 3110             share_network_id = share_network['id']
 3111 
 3112         fake_type = {
 3113             'id': 'fake_type_id',
 3114             'extra_specs': {
 3115                 'snapshot_support': False,
 3116                 'create_share_from_snapshot_support': False,
 3117                 'revert_to_snapshot_support': False,
 3118                 'mount_snapshot_support': False,
 3119                 'driver_handles_share_servers': dhss,
 3120             },
 3121         }
 3122 
 3123         if share_type:
 3124             fake_type_2 = {
 3125                 'id': 'fake_type_2_id',
 3126                 'extra_specs': {
 3127                     'snapshot_support': False,
 3128                     'create_share_from_snapshot_support': False,
 3129                     'revert_to_snapshot_support': False,
 3130                     'mount_snapshot_support': False,
 3131                     'driver_handles_share_servers': dhss,
 3132                     'availability_zones': 'fake_az1,fake_az2',
 3133                 },
 3134             }
 3135         else:
 3136             fake_type_2 = fake_type
 3137 
 3138         share = db_utils.create_share(
 3139             status=constants.STATUS_AVAILABLE,
 3140             host='fake@backend#pool', share_type_id=fake_type['id'],
 3141             share_network_id=share_network_id)
 3142 
 3143         request_spec = self._get_request_spec_dict(
 3144             share, fake_type_2, size=0, availability_zone_id='fake_az_id',
 3145             share_network_id=share_network_id)
 3146 
 3147         self.mock_object(self.scheduler_rpcapi, 'migrate_share_to_host')
 3148         self.mock_object(share_types, 'get_share_type',
 3149                          mock.Mock(return_value=fake_type))
 3150         self.mock_object(utils, 'validate_service_host')
 3151         self.mock_object(db_api, 'share_instance_update')
 3152         self.mock_object(db_api, 'share_update')
 3153         self.mock_object(db_api, 'service_get_by_args',
 3154                          mock.Mock(return_value=service))
 3155 
 3156         if share_type:
 3157             self.api.migration_start(self.context, share, host, False, True,
 3158                                      True, True, True, share_network,
 3159                                      fake_type_2)
 3160         else:
 3161             self.api.migration_start(self.context, share, host, False, True,
 3162                                      True, True, True, share_network, None)
 3163 
 3164         self.scheduler_rpcapi.migrate_share_to_host.assert_called_once_with(
 3165             self.context, share['id'], host, False, True, True, True, True,
 3166             share_network_id, fake_type_2['id'], request_spec)
 3167         if not share_type:
 3168             share_types.get_share_type.assert_called_once_with(
 3169                 self.context, fake_type['id'])
 3170         utils.validate_service_host.assert_called_once_with(
 3171             self.context, 'fake2@backend')
 3172         db_api.service_get_by_args.assert_called_once_with(
 3173             self.context, 'fake2@backend', 'manila-share')
 3174         db_api.share_update.assert_called_once_with(
 3175             self.context, share['id'],
 3176             {'task_state': constants.TASK_STATE_MIGRATION_STARTING})
 3177         db_api.share_instance_update.assert_called_once_with(
 3178             self.context, share.instance['id'],
 3179             {'status': constants.STATUS_MIGRATING})
 3180 
 3181     def test_migration_start_destination_az_unsupported(self):
 3182         host = 'fake2@backend#pool'
 3183         host_without_pool = host.split('#')[0]
 3184         service = {'availability_zone_id': 'fake_az_id',
 3185                    'availability_zone': {'name': 'fake_az3'}}
 3186         share_network = db_utils.create_share_network(id='fake_net_id')
 3187         share_network_id = share_network['id']
 3188         existing_share_type = {
 3189             'id': '4b5b0920-a294-401b-bb7d-c55b425e1cad',
 3190             'name': 'fake_type_1',
 3191             'extra_specs': {
 3192                 'snapshot_support': False,
 3193                 'create_share_from_snapshot_support': False,
 3194                 'revert_to_snapshot_support': False,
 3195                 'mount_snapshot_support': False,
 3196                 'driver_handles_share_servers': 'true',
 3197                 'availability_zones': 'fake_az3'
 3198             },
 3199         }
 3200         new_share_type = {
 3201             'id': 'fa844ae2-494d-4da9-95e7-37ac6a26f635',
 3202             'name': 'fake_type_2',
 3203             'extra_specs': {
 3204                 'snapshot_support': False,
 3205                 'create_share_from_snapshot_support': False,
 3206                 'revert_to_snapshot_support': False,
 3207                 'mount_snapshot_support': False,
 3208                 'driver_handles_share_servers': 'true',
 3209                 'availability_zones': 'fake_az1,fake_az2',
 3210             },
 3211         }
 3212         share = db_utils.create_share(
 3213             status=constants.STATUS_AVAILABLE,
 3214             host='fake@backend#pool', share_type_id=existing_share_type['id'],
 3215             share_network_id=share_network_id)
 3216         self.mock_object(self.api, '_get_request_spec_dict')
 3217         self.mock_object(self.scheduler_rpcapi, 'migrate_share_to_host')
 3218         self.mock_object(share_types, 'get_share_type')
 3219         self.mock_object(utils, 'validate_service_host')
 3220         self.mock_object(db_api, 'share_instance_update')
 3221         self.mock_object(db_api, 'share_update')
 3222         self.mock_object(db_api, 'service_get_by_args',
 3223                          mock.Mock(return_value=service))
 3224 
 3225         self.assertRaises(exception.InvalidShare,
 3226                           self.api.migration_start,
 3227                           self.context, share, host, False, True, True,
 3228                           True, False, new_share_network=share_network,
 3229                           new_share_type=new_share_type)
 3230         utils.validate_service_host.assert_called_once_with(
 3231             self.context, host_without_pool)
 3232         share_types.get_share_type.assert_not_called()
 3233         db_api.share_update.assert_not_called()
 3234         db_api.service_get_by_args.assert_called_once_with(
 3235             self.context, host_without_pool, 'manila-share')
 3236         self.api._get_request_spec_dict.assert_not_called()
 3237         db_api.share_instance_update.assert_not_called()
 3238         self.scheduler_rpcapi.migrate_share_to_host.assert_not_called()
 3239 
 3240     @ddt.data({'force_host_assisted': True, 'writable': True,
 3241                'preserve_metadata': False, 'preserve_snapshots': False,
 3242                'nondisruptive': False},
 3243               {'force_host_assisted': True, 'writable': False,
 3244                'preserve_metadata': True, 'preserve_snapshots': False,
 3245                'nondisruptive': False},
 3246               {'force_host_assisted': True, 'writable': False,
 3247                'preserve_metadata': False, 'preserve_snapshots': True,
 3248                'nondisruptive': False},
 3249               {'force_host_assisted': True, 'writable': False,
 3250                'preserve_metadata': False, 'preserve_snapshots': False,
 3251                'nondisruptive': True})
 3252     @ddt.unpack
 3253     def test_migration_start_invalid_host_and_driver_assisted_params(
 3254             self, force_host_assisted, writable, preserve_metadata,
 3255             preserve_snapshots, nondisruptive):
 3256 
 3257         self.assertRaises(
 3258             exception.InvalidInput, self.api.migration_start, self.context,
 3259             'some_share', 'some_host', force_host_assisted, preserve_metadata,
 3260             writable, preserve_snapshots, nondisruptive)
 3261 
 3262     @ddt.data(True, False)
 3263     def test_migration_start_invalid_share_network_type_combo(self, dhss):
 3264         host = 'fake2@backend#pool'
 3265         share_network = None
 3266         if not dhss:
 3267             share_network = db_utils.create_share_network(id='fake_net_id')
 3268 
 3269         fake_type = {
 3270             'id': 'fake_type_id',
 3271             'extra_specs': {
 3272                 'snapshot_support': False,
 3273                 'driver_handles_share_servers': not dhss,
 3274             },
 3275         }
 3276 
 3277         fake_type_2 = {
 3278             'id': 'fake_type_2_id',
 3279             'extra_specs': {
 3280                 'snapshot_support': False,
 3281                 'driver_handles_share_servers': dhss,
 3282             },
 3283         }
 3284 
 3285         share = db_utils.create_share(
 3286             status=constants.STATUS_AVAILABLE,
 3287             host='fake@backend#pool', share_type_id=fake_type['id'])
 3288 
 3289         self.mock_object(utils, 'validate_service_host')
 3290 
 3291         self.assertRaises(
 3292             exception.InvalidInput, self.api.migration_start, self.context,
 3293             share, host, False, True, True, True, True, share_network,
 3294             fake_type_2)
 3295 
 3296         utils.validate_service_host.assert_called_once_with(
 3297             self.context, 'fake2@backend')
 3298 
 3299     def test_migration_start_status_unavailable(self):
 3300         host = 'fake2@backend#pool'
 3301         share = db_utils.create_share(
 3302             status=constants.STATUS_ERROR)
 3303 
 3304         self.assertRaises(exception.InvalidShare, self.api.migration_start,
 3305                           self.context, share, host, False, True, True, True,
 3306                           True)
 3307 
 3308     def test_migration_start_access_rules_status_error(self):
 3309         host = 'fake2@backend#pool'
 3310         instance = db_utils.create_share_instance(
 3311             share_id='fake_share_id',
 3312             access_rules_status=constants.STATUS_ERROR,
 3313             status=constants.STATUS_AVAILABLE)
 3314         share = db_utils.create_share(
 3315             id='fake_share_id',
 3316             instances=[instance])
 3317 
 3318         self.assertRaises(exception.InvalidShare, self.api.migration_start,
 3319                           self.context, share, host, False, True, True, True,
 3320                           True)
 3321 
 3322     def test_migration_start_task_state_invalid(self):
 3323         host = 'fake2@backend#pool'
 3324         share = db_utils.create_share(
 3325             status=constants.STATUS_AVAILABLE,
 3326             task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS)
 3327 
 3328         self.assertRaises(exception.ShareBusyException,
 3329                           self.api.migration_start,
 3330                           self.context, share, host, False, True, True, True,
 3331                           True)
 3332 
 3333     def test_migration_start_host_assisted_with_snapshots(self):
 3334         host = 'fake2@backend#pool'
 3335         share = db_utils.create_share(
 3336             host='fake@backend#pool', status=constants.STATUS_AVAILABLE)
 3337         self.mock_object(db_api, 'share_snapshot_get_all_for_share',
 3338                          mock.Mock(return_value=True))
 3339 
 3340         self.assertRaises(exception.Conflict, self.api.migration_start,
 3341                           self.context, share, host, True, False, False, False,
 3342                           False)
 3343 
 3344     def test_migration_start_with_snapshots(self):
 3345         host = 'fake2@backend#pool'
 3346 
 3347         fake_type = {
 3348             'id': 'fake_type_id',
 3349             'extra_specs': {
 3350                 'snapshot_support': True,
 3351                 'driver_handles_share_servers': False,
 3352             },
 3353         }
 3354 
 3355         service = {'availability_zone_id': 'fake_az_id',
 3356                    'availability_zone': {'name': 'fake_az'}}
 3357         self.mock_object(db_api, 'service_get_by_args',
 3358                          mock.Mock(return_value=service))
 3359         self.mock_object(utils, 'validate_service_host')
 3360         self.mock_object(share_types, 'get_share_type',
 3361                          mock.Mock(return_value=fake_type))
 3362 
 3363         share = db_utils.create_share(
 3364             host='fake@backend#pool', status=constants.STATUS_AVAILABLE,
 3365             share_type_id=fake_type['id'])
 3366 
 3367         request_spec = self._get_request_spec_dict(
 3368             share, fake_type, availability_zone_id='fake_az_id')
 3369 
 3370         self.api.migration_start(self.context, share, host, False, True, True,
 3371                                  True, True)
 3372 
 3373         self.scheduler_rpcapi.migrate_share_to_host.assert_called_once_with(
 3374             self.context, share['id'], host, False, True, True, True, True,
 3375             None, 'fake_type_id', request_spec)
 3376 
 3377     def test_migration_start_has_replicas(self):
 3378         host = 'fake2@backend#pool'
 3379         share = db_utils.create_share(
 3380             host='fake@backend#pool', status=constants.STATUS_AVAILABLE,
 3381             replication_type='dr')
 3382         for i in range(1, 4):
 3383             db_utils.create_share_replica(
 3384                 share_id=share['id'], replica_state='in_sync')
 3385         self.mock_object(db_api, 'share_snapshot_get_all_for_share',
 3386                          mock.Mock(return_value=True))
 3387         mock_log = self.mock_object(share_api, 'LOG')
 3388         mock_snapshot_get_call = self.mock_object(
 3389             db_api, 'share_snapshot_get_all_for_share')
 3390         # Share was updated after adding replicas, grabbing it again.
 3391         share = db_api.share_get(self.context, share['id'])
 3392 
 3393         self.assertRaises(exception.Conflict, self.api.migration_start,
 3394                           self.context, share, host, False, True, True, True,
 3395                           True)
 3396         self.assertTrue(mock_log.error.called)
 3397         self.assertFalse(mock_snapshot_get_call.called)
 3398 
 3399     def test_migration_start_is_member_of_group(self):
 3400         group = db_utils.create_share_group()
 3401         share = db_utils.create_share(
 3402             host='fake@backend#pool', status=constants.STATUS_AVAILABLE,
 3403             share_group_id=group['id'])
 3404         mock_log = self.mock_object(share_api, 'LOG')
 3405 
 3406         self.assertRaises(exception.InvalidShare, self.api.migration_start,
 3407                           self.context, share, 'fake_host', False, True, True,
 3408                           True, True)
 3409         self.assertTrue(mock_log.error.called)
 3410 
 3411     def test_migration_start_invalid_host(self):
 3412         host = 'fake@backend#pool'
 3413         share = db_utils.create_share(
 3414             host='fake2@backend', status=constants.STATUS_AVAILABLE)
 3415 
 3416         self.mock_object(db_api, 'share_snapshot_get_all_for_share',
 3417                          mock.Mock(return_value=False))
 3418 
 3419         self.assertRaises(exception.ServiceNotFound,
 3420                           self.api.migration_start,
 3421                           self.context, share, host, False, True, True, True,
 3422                           True)
 3423 
 3424     @ddt.data({'dhss': True, 'new_share_network_id': 'fake_net_id',
 3425                'new_share_type_id': 'fake_type_id'},
 3426               {'dhss': False, 'new_share_network_id': None,
 3427                'new_share_type_id': 'fake_type_id'},
 3428               {'dhss': True, 'new_share_network_id': 'fake_net_id',
 3429                'new_share_type_id': None})
 3430     @ddt. unpack
 3431     def test_migration_start_same_data_as_source(
 3432             self, dhss, new_share_network_id, new_share_type_id):
 3433         host = 'fake@backend#pool'
 3434 
 3435         fake_type_src = {
 3436             'id': 'fake_type_id',
 3437             'extra_specs': {
 3438                 'snapshot_support': True,
 3439                 'driver_handles_share_servers': True,
 3440             },
 3441         }
 3442 
 3443         new_share_type_param = None
 3444         if new_share_type_id:
 3445             new_share_type_param = {
 3446                 'id': new_share_type_id,
 3447                 'extra_specs': {
 3448                     'snapshot_support': True,
 3449                     'driver_handles_share_servers': dhss,
 3450                 },
 3451             }
 3452 
 3453         new_share_net_param = None
 3454         if new_share_network_id:
 3455             new_share_net_param = db_utils.create_share_network(
 3456                 id=new_share_network_id)
 3457 
 3458         share = db_utils.create_share(
 3459             host='fake@backend#pool', status=constants.STATUS_AVAILABLE,
 3460             share_type_id=fake_type_src['id'],
 3461             share_network_id=new_share_network_id)
 3462 
 3463         self.mock_object(utils, 'validate_service_host')
 3464         self.mock_object(db_api, 'share_update')
 3465         self.mock_object(share_types, 'get_share_type',
 3466                          mock.Mock(return_value=fake_type_src))
 3467 
 3468         result = self.api.migration_start(
 3469             self.context, share, host, False, True, True, True, True,
 3470             new_share_net_param, new_share_type_param)
 3471 
 3472         self.assertEqual(200, result)
 3473 
 3474         db_api.share_update.assert_called_once_with(
 3475             self.context, share['id'],
 3476             {'task_state': constants.TASK_STATE_MIGRATION_SUCCESS})
 3477 
 3478     @ddt.data({}, {'replication_type': None})
 3479     def test_create_share_replica_invalid_share_type(self, attributes):
 3480         share = fakes.fake_share(id='FAKE_SHARE_ID', **attributes)
 3481         mock_request_spec_call = self.mock_object(
 3482             self.api, 'create_share_instance_and_get_request_spec')
 3483         mock_db_update_call = self.mock_object(db_api, 'share_replica_update')
 3484         mock_scheduler_rpcapi_call = self.mock_object(
 3485             self.api.scheduler_rpcapi, 'create_share_replica')
 3486 
 3487         self.assertRaises(exception.InvalidShare,
 3488                           self.api.create_share_replica,
 3489                           self.context, share)
 3490         self.assertFalse(mock_request_spec_call.called)
 3491         self.assertFalse(mock_db_update_call.called)
 3492         self.assertFalse(mock_scheduler_rpcapi_call.called)
 3493 
 3494     def test_create_share_replica_busy_share(self):
 3495         share = fakes.fake_share(
 3496             id='FAKE_SHARE_ID',
 3497             task_state='doing_something_real_important',
 3498             is_busy=True,
 3499             replication_type='dr')
 3500         mock_request_spec_call = self.mock_object(
 3501             self.api, 'create_share_instance_and_get_request_spec')
 3502         mock_db_update_call = self.mock_object(db_api, 'share_replica_update')
 3503         mock_scheduler_rpcapi_call = self.mock_object(
 3504             self.api.scheduler_rpcapi, 'create_share_replica')
 3505 
 3506         self.assertRaises(exception.ShareBusyException,
 3507                           self.api.create_share_replica,
 3508                           self.context, share)
 3509         self.assertFalse(mock_request_spec_call.called)
 3510         self.assertFalse(mock_db_update_call.called)
 3511         self.assertFalse(mock_scheduler_rpcapi_call.called)
 3512 
 3513     @ddt.data(None, [])
 3514     def test_create_share_replica_no_active_replica(self, active_replicas):
 3515         share = fakes.fake_share(
 3516             id='FAKE_SHARE_ID', replication_type='dr')
 3517         mock_request_spec_call = self.mock_object(
 3518             self.api, 'create_share_instance_and_get_request_spec')
 3519         mock_db_update_call = self.mock_object(db_api, 'share_replica_update')
 3520         mock_scheduler_rpcapi_call = self.mock_object(
 3521             self.api.scheduler_rpcapi, 'create_share_replica')
 3522         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 3523                          mock.Mock(return_value=active_replicas))
 3524 
 3525         self.assertRaises(exception.ReplicationException,
 3526                           self.api.create_share_replica,
 3527                           self.context, share)
 3528         self.assertFalse(mock_request_spec_call.called)
 3529         self.assertFalse(mock_db_update_call.called)
 3530         self.assertFalse(mock_scheduler_rpcapi_call.called)
 3531 
 3532     @ddt.data(None, 'fake-share-type')
 3533     def test_create_share_replica_type_doesnt_support_AZ(self, st_name):
 3534         share_type = fakes.fake_share_type(
 3535             name=st_name,
 3536             extra_specs={'availability_zones': 'zone 1,zone 3'})
 3537         share = fakes.fake_share(
 3538             id='FAKE_SHARE_ID', replication_type='dr',
 3539             availability_zone='zone 2')
 3540         share['instance'].update({
 3541             'share_type': share_type,
 3542             'share_type_id': '359b9851-2bd5-4404-89a9-5cd22bbc5fb9',
 3543         })
 3544         mock_request_spec_call = self.mock_object(
 3545             self.api, 'create_share_instance_and_get_request_spec')
 3546         mock_db_update_call = self.mock_object(db_api, 'share_replica_update')
 3547         mock_scheduler_rpcapi_call = self.mock_object(
 3548             self.api.scheduler_rpcapi, 'create_share_replica')
 3549         self.mock_object(share_types, 'get_share_type',
 3550                          mock.Mock(return_value=share_type))
 3551         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 3552                          mock.Mock(return_value=mock.Mock(
 3553                              return_value={'host': 'fake_ar_host'})))
 3554 
 3555         self.assertRaises(exception.InvalidShare,
 3556                           self.api.create_share_replica,
 3557                           self.context, share, availability_zone='zone 2')
 3558         share_types.get_share_type.assert_called_once_with(
 3559             self.context, '359b9851-2bd5-4404-89a9-5cd22bbc5fb9')
 3560         self.assertFalse(mock_request_spec_call.called)
 3561         self.assertFalse(mock_db_update_call.called)
 3562         self.assertFalse(mock_scheduler_rpcapi_call.called)
 3563 
 3564     def test_create_share_replica_subnet_not_found(self):
 3565         request_spec = fakes.fake_replica_request_spec()
 3566         replica = request_spec['share_instance_properties']
 3567         extra_specs = {
 3568             'availability_zones': 'FAKE_AZ,FAKE_AZ2',
 3569             'replication_type': constants.REPLICATION_TYPE_DR
 3570         }
 3571         share_type = db_utils.create_share_type(extra_specs=extra_specs)
 3572         share_type = db_api.share_type_get(self.context, share_type['id'])
 3573         az_name = 'FAKE_AZ'
 3574         share = db_utils.create_share(
 3575             id=replica['share_id'], replication_type='dr')
 3576         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 3577                          mock.Mock(return_value=mock.Mock(
 3578                              return_value={'host': 'fake_ar_host'})))
 3579         self.mock_object(share_types, 'get_share_type',
 3580                          mock.Mock(return_value=share_type))
 3581         self.mock_object(db_api, 'availability_zone_get')
 3582         self.mock_object(db_api,
 3583                          'share_network_subnet_get_by_availability_zone_id',
 3584                          mock.Mock(return_value=None))
 3585 
 3586         self.assertRaises(exception.InvalidShare,
 3587                           self.api.create_share_replica,
 3588                           self.context,
 3589                           share,
 3590                           availability_zone=az_name,
 3591                           share_network_id='fake_id')
 3592         (db_api.share_replicas_get_available_active_replica
 3593             .assert_called_once_with(self.context, share['id']))
 3594         self.assertTrue(share_types.get_share_type.called)
 3595         db_api.availability_zone_get.assert_called_once_with(
 3596             self.context, az_name)
 3597         self.assertTrue(
 3598             db_api.share_network_subnet_get_by_availability_zone_id.called)
 3599 
 3600     def test_create_share_replica_az_not_found(self):
 3601         request_spec = fakes.fake_replica_request_spec()
 3602         replica = request_spec['share_instance_properties']
 3603         extra_specs = {
 3604             'availability_zones': 'FAKE_AZ,FAKE_AZ2',
 3605             'replication_type': constants.REPLICATION_TYPE_DR
 3606         }
 3607         share_type = db_utils.create_share_type(extra_specs=extra_specs)
 3608         share_type = db_api.share_type_get(self.context, share_type['id'])
 3609         az_name = 'FAKE_AZ'
 3610         share = db_utils.create_share(
 3611             id=replica['share_id'], replication_type='dr')
 3612         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 3613                          mock.Mock(return_value=mock.Mock(
 3614                              return_value={'host': 'fake_ar_host'})))
 3615         self.mock_object(share_types, 'get_share_type',
 3616                          mock.Mock(return_value=share_type))
 3617         side_effect = exception.AvailabilityZoneNotFound(id=az_name)
 3618         self.mock_object(db_api, 'availability_zone_get',
 3619                          mock.Mock(side_effect=side_effect))
 3620 
 3621         self.assertRaises(exception.InvalidInput,
 3622                           self.api.create_share_replica,
 3623                           self.context,
 3624                           share,
 3625                           availability_zone=az_name,
 3626                           share_network_id='fake_id')
 3627         (db_api.share_replicas_get_available_active_replica
 3628             .assert_called_once_with(self.context, share['id']))
 3629         self.assertTrue(share_types.get_share_type.called)
 3630         db_api.availability_zone_get.assert_called_once_with(
 3631             self.context, az_name)
 3632 
 3633     @ddt.data(
 3634         {'availability_zones': '', 'azs_with_subnet': ['fake_az_1']},
 3635         {'availability_zones': 'fake_az_1,fake_az_2',
 3636          'azs_with_subnet': ['fake_az_2']}
 3637     )
 3638     @ddt.unpack
 3639     def test_create_share_replica_azs_with_subnets(self, availability_zones,
 3640                                                    azs_with_subnet):
 3641         request_spec = fakes.fake_replica_request_spec()
 3642         replica = request_spec['share_instance_properties']
 3643         share_network_id = 'fake_share_network_id'
 3644         extra_specs = {
 3645             'availability_zones': availability_zones,
 3646             'replication_type': constants.REPLICATION_TYPE_DR
 3647         }
 3648         share_type = db_utils.create_share_type(extra_specs=extra_specs)
 3649         share_type = db_api.share_type_get(self.context, share_type['id'])
 3650         share = db_utils.create_share(
 3651             id=replica['share_id'], replication_type='dr',
 3652             share_type_id=share_type['id'])
 3653         cast_rules_to_readonly = (
 3654             share['replication_type'] == constants.REPLICATION_TYPE_READABLE)
 3655         fake_replica = fakes.fake_replica(id=replica['id'])
 3656         fake_request_spec = fakes.fake_replica_request_spec()
 3657 
 3658         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 3659                          mock.Mock(return_value={'host': 'fake_ar_host'}))
 3660         self.mock_object(share_types, 'get_share_type',
 3661                          mock.Mock(return_value=share_type))
 3662         mock_get_all_az_subnet = self.mock_object(
 3663             self.api, '_get_all_availability_zones_with_subnets',
 3664             mock.Mock(return_value=azs_with_subnet))
 3665 
 3666         if availability_zones == '':
 3667             expected_azs = azs_with_subnet
 3668         else:
 3669             availability_zones = [
 3670                 t for t in availability_zones.split(',') if availability_zones]
 3671             expected_azs = (
 3672                 [az for az in availability_zones if az in azs_with_subnet])
 3673 
 3674         self.mock_object(
 3675             self.api, 'create_share_instance_and_get_request_spec',
 3676             mock.Mock(return_value=(fake_request_spec, fake_replica)))
 3677         self.mock_object(db_api, 'share_replica_update')
 3678         mock_snapshot_get_all_call = self.mock_object(
 3679             db_api, 'share_snapshot_get_all_for_share',
 3680             mock.Mock(return_value=[]))
 3681         mock_sched_rpcapi_call = self.mock_object(
 3682             self.api.scheduler_rpcapi, 'create_share_replica')
 3683 
 3684         self.api.create_share_replica(
 3685             self.context, share, share_network_id=share_network_id)
 3686 
 3687         (db_api.share_replicas_get_available_active_replica
 3688             .assert_called_once_with(self.context, share['id']))
 3689         self.assertTrue(share_types.get_share_type.called)
 3690         mock_get_all_az_subnet.assert_called_once_with(
 3691             self.context, share_network_id
 3692         )
 3693         (self.api.create_share_instance_and_get_request_spec.
 3694          assert_called_once_with(
 3695              self.context, share, availability_zone=None,
 3696              share_network_id=share_network_id, share_type_id=share_type['id'],
 3697              availability_zones=expected_azs,
 3698              cast_rules_to_readonly=cast_rules_to_readonly))
 3699         db_api.share_replica_update.assert_called_once()
 3700         mock_snapshot_get_all_call.assert_called_once()
 3701         mock_sched_rpcapi_call.assert_called_once()
 3702 
 3703     @ddt.data(
 3704         {'availability_zones': '', 'azs_with_subnet': []},
 3705         {'availability_zones': 'fake_az_1,fake_az_2',
 3706          'azs_with_subnet': ['fake_az_3']}
 3707     )
 3708     @ddt.unpack
 3709     def test_create_share_replica_azs_with_subnets_invalid_input(
 3710             self, availability_zones, azs_with_subnet):
 3711         request_spec = fakes.fake_replica_request_spec()
 3712         replica = request_spec['share_instance_properties']
 3713         share_network_id = 'fake_share_network_id'
 3714         extra_specs = {
 3715             'availability_zones': availability_zones,
 3716             'replication_type': constants.REPLICATION_TYPE_DR
 3717         }
 3718         share_type = db_utils.create_share_type(extra_specs=extra_specs)
 3719         share_type = db_api.share_type_get(self.context, share_type['id'])
 3720         share = db_utils.create_share(
 3721             id=replica['share_id'], replication_type='dr',
 3722             share_type_id=share_type['id'])
 3723 
 3724         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 3725                          mock.Mock(return_value={'host': 'fake_ar_host'}))
 3726         self.mock_object(share_types, 'get_share_type',
 3727                          mock.Mock(return_value=share_type))
 3728         mock_get_all_az_subnet = self.mock_object(
 3729             self.api, '_get_all_availability_zones_with_subnets',
 3730             mock.Mock(return_value=azs_with_subnet))
 3731 
 3732         self.assertRaises(
 3733             exception.InvalidInput,
 3734             self.api.create_share_replica,
 3735             self.context, share, share_network_id=share_network_id)
 3736 
 3737         (db_api.share_replicas_get_available_active_replica
 3738          .assert_called_once_with(self.context, share['id']))
 3739         self.assertTrue(share_types.get_share_type.called)
 3740         mock_get_all_az_subnet.assert_called_once_with(
 3741             self.context, share_network_id
 3742         )
 3743 
 3744     @ddt.data({'has_snapshots': True,
 3745                'extra_specs': {
 3746                    'replication_type': constants.REPLICATION_TYPE_DR,
 3747                },
 3748                'share_network_id': None},
 3749               {'has_snapshots': False,
 3750                'extra_specs': {
 3751                    'availability_zones': 'FAKE_AZ,FAKE_AZ2',
 3752                    'replication_type': constants.REPLICATION_TYPE_DR,
 3753                },
 3754                'share_network_id': None},
 3755               {'has_snapshots': True,
 3756                'extra_specs': {
 3757                    'availability_zones': 'FAKE_AZ,FAKE_AZ2',
 3758                    'replication_type': constants.REPLICATION_TYPE_READABLE,
 3759                },
 3760                'share_network_id': None},
 3761               {'has_snapshots': False,
 3762                'extra_specs': {
 3763                    'replication_type': constants.REPLICATION_TYPE_READABLE,
 3764                },
 3765                'share_network_id': 'fake_sn_id'})
 3766     @ddt.unpack
 3767     def test_create_share_replica(self, has_snapshots, extra_specs,
 3768                                   share_network_id):
 3769         request_spec = fakes.fake_replica_request_spec()
 3770         replication_type = extra_specs['replication_type']
 3771         replica = request_spec['share_instance_properties']
 3772         share_type = db_utils.create_share_type(extra_specs=extra_specs)
 3773         share_type = db_api.share_type_get(self.context, share_type['id'])
 3774         share = db_utils.create_share(
 3775             id=replica['share_id'], replication_type=replication_type,
 3776             share_type_id=share_type['id'])
 3777         snapshots = (
 3778             [fakes.fake_snapshot(), fakes.fake_snapshot()]
 3779             if has_snapshots else []
 3780         )
 3781         cast_rules_to_readonly = (
 3782             replication_type == constants.REPLICATION_TYPE_READABLE)
 3783 
 3784         fake_replica = fakes.fake_replica(id=replica['id'])
 3785         fake_request_spec = fakes.fake_replica_request_spec()
 3786         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 3787                          mock.Mock(return_value={'host': 'fake_ar_host'}))
 3788         self.mock_object(share_types, 'get_share_type',
 3789                          mock.Mock(return_value=share_type))
 3790         self.mock_object(db_api, 'availability_zone_get')
 3791         self.mock_object(db_api,
 3792                          'share_network_subnet_get_by_availability_zone_id')
 3793         self.mock_object(
 3794             share_api.API, 'create_share_instance_and_get_request_spec',
 3795             mock.Mock(return_value=(fake_request_spec, fake_replica)))
 3796         self.mock_object(db_api, 'share_replica_update')
 3797         mock_sched_rpcapi_call = self.mock_object(
 3798             self.api.scheduler_rpcapi, 'create_share_replica')
 3799         mock_snapshot_get_all_call = self.mock_object(
 3800             db_api, 'share_snapshot_get_all_for_share',
 3801             mock.Mock(return_value=snapshots))
 3802         mock_snapshot_instance_create_call = self.mock_object(
 3803             db_api, 'share_snapshot_instance_create')
 3804         expected_snap_instance_create_call_count = 2 if has_snapshots else 0
 3805 
 3806         result = self.api.create_share_replica(
 3807             self.context, share, availability_zone='FAKE_AZ',
 3808             share_network_id=share_network_id)
 3809 
 3810         self.assertTrue(mock_sched_rpcapi_call.called)
 3811         self.assertEqual(replica, result)
 3812         share_types.get_share_type.assert_called_once_with(
 3813             self.context, share_type['id'])
 3814         mock_snapshot_get_all_call.assert_called_once_with(
 3815             self.context, fake_replica['share_id'])
 3816         self.assertEqual(expected_snap_instance_create_call_count,
 3817                          mock_snapshot_instance_create_call.call_count)
 3818         expected_azs = extra_specs.get('availability_zones', '')
 3819         expected_azs = expected_azs.split(',') if expected_azs else []
 3820         (share_api.API.create_share_instance_and_get_request_spec.
 3821          assert_called_once_with(
 3822              self.context, share, availability_zone='FAKE_AZ',
 3823              share_network_id=share_network_id, share_type_id=share_type['id'],
 3824              availability_zones=expected_azs,
 3825              cast_rules_to_readonly=cast_rules_to_readonly))
 3826 
 3827     def test_delete_last_active_replica(self):
 3828         fake_replica = fakes.fake_replica(
 3829             share_id='FAKE_SHARE_ID',
 3830             replica_state=constants.REPLICA_STATE_ACTIVE)
 3831         self.mock_object(db_api, 'share_replicas_get_all_by_share',
 3832                          mock.Mock(return_value=[fake_replica]))
 3833         mock_log = self.mock_object(share_api.LOG, 'info')
 3834 
 3835         self.assertRaises(
 3836             exception.ReplicationException, self.api.delete_share_replica,
 3837             self.context, fake_replica)
 3838         self.assertFalse(mock_log.called)
 3839 
 3840     @ddt.data(True, False)
 3841     def test_delete_share_replica_no_host(self, has_snapshots):
 3842         snapshots = [{'id': 'xyz'}, {'id': 'abc'}, {'id': 'pqr'}]
 3843         snapshots = snapshots if has_snapshots else []
 3844         replica = fakes.fake_replica('FAKE_ID', host='')
 3845         mock_sched_rpcapi_call = self.mock_object(
 3846             self.share_rpcapi, 'delete_share_replica')
 3847         mock_db_replica_delete_call = self.mock_object(
 3848             db_api, 'share_replica_delete')
 3849         mock_db_update_call = self.mock_object(db_api, 'share_replica_update')
 3850         mock_snapshot_get_call = self.mock_object(
 3851             db_api, 'share_snapshot_instance_get_all_with_filters',
 3852             mock.Mock(return_value=snapshots))
 3853         mock_snapshot_instance_delete_call = self.mock_object(
 3854             db_api, 'share_snapshot_instance_delete')
 3855 
 3856         self.api.delete_share_replica(self.context, replica)
 3857 
 3858         self.assertFalse(mock_sched_rpcapi_call.called)
 3859         mock_db_replica_delete_call.assert_called_once_with(
 3860             self.context, replica['id'])
 3861         mock_db_update_call.assert_called_once_with(
 3862             self.context, replica['id'],
 3863             {'status': constants.STATUS_DELETING, 'terminated_at': mock.ANY})
 3864         mock_snapshot_get_call.assert_called_once_with(
 3865             self.context, {'share_instance_ids': replica['id']})
 3866         self.assertEqual(
 3867             len(snapshots), mock_snapshot_instance_delete_call.call_count)
 3868 
 3869     @ddt.data(True, False)
 3870     def test_delete_share_replica(self, force):
 3871         replica = fakes.fake_replica('FAKE_ID', host='HOSTA@BackendB#PoolC')
 3872         mock_sched_rpcapi_call = self.mock_object(
 3873             self.share_rpcapi, 'delete_share_replica')
 3874         mock_db_update_call = self.mock_object(db_api, 'share_replica_update')
 3875 
 3876         self.api.delete_share_replica(self.context, replica, force=force)
 3877 
 3878         mock_sched_rpcapi_call.assert_called_once_with(
 3879             self.context, replica, force=force)
 3880         mock_db_update_call.assert_called_once_with(
 3881             self.context, replica['id'],
 3882             {'status': constants.STATUS_DELETING,
 3883              'terminated_at': mock.ANY})
 3884 
 3885     @ddt.data(constants.STATUS_CREATING, constants.STATUS_DELETING,
 3886               constants.STATUS_ERROR, constants.STATUS_EXTENDING,
 3887               constants.STATUS_REPLICATION_CHANGE, constants.STATUS_MANAGING,
 3888               constants.STATUS_ERROR_DELETING)
 3889     def test_promote_share_replica_non_available_status(self, status):
 3890         replica = fakes.fake_replica(
 3891             status=status, replica_state=constants.REPLICA_STATE_IN_SYNC)
 3892         mock_rpcapi_promote_share_replica_call = self.mock_object(
 3893             self.share_rpcapi, 'promote_share_replica')
 3894 
 3895         self.assertRaises(exception.ReplicationException,
 3896                           self.api.promote_share_replica,
 3897                           self.context,
 3898                           replica)
 3899         self.assertFalse(mock_rpcapi_promote_share_replica_call.called)
 3900 
 3901     @ddt.data(constants.REPLICA_STATE_OUT_OF_SYNC, constants.STATUS_ERROR)
 3902     def test_promote_share_replica_out_of_sync_non_admin(self, replica_state):
 3903         fake_user_context = context.RequestContext(
 3904             user_id=None, project_id=None, is_admin=False,
 3905             read_deleted='no', overwrite=False)
 3906         replica = fakes.fake_replica(
 3907             status=constants.STATUS_AVAILABLE,
 3908             replica_state=replica_state)
 3909         mock_rpcapi_promote_share_replica_call = self.mock_object(
 3910             self.share_rpcapi, 'promote_share_replica')
 3911 
 3912         self.assertRaises(exception.AdminRequired,
 3913                           self.api.promote_share_replica,
 3914                           fake_user_context,
 3915                           replica)
 3916         self.assertFalse(mock_rpcapi_promote_share_replica_call.called)
 3917 
 3918     @ddt.data(constants.REPLICA_STATE_OUT_OF_SYNC, constants.STATUS_ERROR)
 3919     def test_promote_share_replica_admin_authorized(self, replica_state):
 3920         replica = fakes.fake_replica(
 3921             status=constants.STATUS_AVAILABLE,
 3922             replica_state=replica_state, host='HOSTA@BackendB#PoolC')
 3923         self.mock_object(db_api, 'share_replica_get',
 3924                          mock.Mock(return_value=replica))
 3925         mock_rpcapi_promote_share_replica_call = self.mock_object(
 3926             self.share_rpcapi, 'promote_share_replica')
 3927         mock_db_update_call = self.mock_object(db_api, 'share_replica_update')
 3928 
 3929         retval = self.api.promote_share_replica(
 3930             self.context, replica)
 3931 
 3932         self.assertEqual(replica, retval)
 3933         mock_db_update_call.assert_called_once_with(
 3934             self.context, replica['id'],
 3935             {'status': constants.STATUS_REPLICATION_CHANGE})
 3936         mock_rpcapi_promote_share_replica_call.assert_called_once_with(
 3937             self.context, replica)
 3938 
 3939     def test_promote_share_replica(self):
 3940         replica = fakes.fake_replica('FAKE_ID', host='HOSTA@BackendB#PoolC')
 3941         self.mock_object(db_api, 'share_replica_get',
 3942                          mock.Mock(return_value=replica))
 3943         self.mock_object(db_api, 'share_replica_update')
 3944         mock_sched_rpcapi_call = self.mock_object(
 3945             self.share_rpcapi, 'promote_share_replica')
 3946 
 3947         result = self.api.promote_share_replica(self.context, replica)
 3948 
 3949         mock_sched_rpcapi_call.assert_called_once_with(
 3950             self.context, replica)
 3951         self.assertEqual(replica, result)
 3952 
 3953     def test_update_share_replica_no_host(self):
 3954         replica = fakes.fake_replica('FAKE_ID')
 3955         replica['host'] = None
 3956         mock_rpcapi_update_share_replica_call = self.mock_object(
 3957             self.share_rpcapi, 'update_share_replica')
 3958 
 3959         self.assertRaises(exception.InvalidHost,
 3960                           self.api.update_share_replica,
 3961                           self.context,
 3962                           replica)
 3963         self.assertFalse(mock_rpcapi_update_share_replica_call.called)
 3964 
 3965     def test_update_share_replica(self):
 3966         replica = fakes.fake_replica('FAKE_ID', host='HOSTA@BackendB#PoolC')
 3967         mock_rpcapi_update_share_replica_call = self.mock_object(
 3968             self.share_rpcapi, 'update_share_replica')
 3969 
 3970         retval = self.api.update_share_replica(self.context, replica)
 3971 
 3972         self.assertTrue(mock_rpcapi_update_share_replica_call.called)
 3973         self.assertIsNone(retval)
 3974 
 3975     @ddt.data({'overs': {'replica_gigabytes': 'fake'},
 3976                'expected_exception':
 3977                    exception.ShareReplicaSizeExceedsAvailableQuota},
 3978               {'overs': {'share_replicas': 'fake'},
 3979                'expected_exception': exception.ShareReplicasLimitExceeded})
 3980     @ddt.unpack
 3981     def test_create_share_replica_over_quota(self, overs, expected_exception):
 3982         request_spec = fakes.fake_replica_request_spec()
 3983         replica = request_spec['share_instance_properties']
 3984         share = db_utils.create_share(replication_type='dr',
 3985                                       id=replica['share_id'])
 3986         share_type = db_utils.create_share_type()
 3987         share_type = db_api.share_type_get(self.context, share_type['id'])
 3988         usages = {'replica_gigabytes': {'reserved': 5, 'in_use': 5},
 3989                   'share_replicas': {'reserved': 5, 'in_use': 5}}
 3990         quotas = {'share_replicas': 5, 'replica_gigabytes': 5}
 3991         exc = exception.OverQuota(overs=overs, usages=usages, quotas=quotas)
 3992 
 3993         self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(side_effect=exc))
 3994         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 3995                          mock.Mock(return_value={'host': 'fake_ar_host'}))
 3996         self.mock_object(share_types, 'get_share_type',
 3997                          mock.Mock(return_value=share_type))
 3998 
 3999         self.assertRaises(
 4000             expected_exception,
 4001             self.api.create_share_replica,
 4002             self.context,
 4003             share
 4004         )
 4005         quota.QUOTAS.reserve.assert_called_once_with(
 4006             self.context, share_type_id=share_type['id'],
 4007             share_replicas=1, replica_gigabytes=share['size'])
 4008         (db_api.share_replicas_get_available_active_replica
 4009          .assert_called_once_with(self.context, share['id']))
 4010         share_types.get_share_type.assert_called_once_with(
 4011             self.context, share['instance']['share_type_id'])
 4012 
 4013     def test_create_share_replica_error_on_quota_commit(self):
 4014         request_spec = fakes.fake_replica_request_spec()
 4015         replica = request_spec['share_instance_properties']
 4016         share_type = db_utils.create_share_type()
 4017         fake_replica = fakes.fake_replica(id=replica['id'])
 4018         share = db_utils.create_share(replication_type='dr',
 4019                                       id=fake_replica['share_id'],
 4020                                       share_type_id=share_type['id'])
 4021         share_network_id = None
 4022         share_type = db_api.share_type_get(self.context, share_type['id'])
 4023         expected_azs = share_type['extra_specs'].get('availability_zones', '')
 4024         expected_azs = expected_azs.split(',') if expected_azs else []
 4025 
 4026         reservation = 'fake'
 4027         self.mock_object(quota.QUOTAS, 'reserve',
 4028                          mock.Mock(return_value=reservation))
 4029         self.mock_object(quota.QUOTAS, 'commit',
 4030                          mock.Mock(side_effect=exception.QuotaError('fake')))
 4031         self.mock_object(db_api, 'share_replica_delete')
 4032         self.mock_object(quota.QUOTAS, 'rollback')
 4033         self.mock_object(db_api, 'share_replicas_get_available_active_replica',
 4034                          mock.Mock(return_value={'host': 'fake_ar_host'}))
 4035         self.mock_object(share_types, 'get_share_type',
 4036                          mock.Mock(return_value=share_type))
 4037         self.mock_object(
 4038             share_api.API, 'create_share_instance_and_get_request_spec',
 4039             mock.Mock(return_value=(request_spec, fake_replica)))
 4040 
 4041         self.assertRaises(
 4042             exception.QuotaError,
 4043             self.api.create_share_replica,
 4044             self.context,
 4045             share
 4046         )
 4047 
 4048         db_api.share_replica_delete.assert_called_once_with(
 4049             self.context, replica['id'], need_to_update_usages=False)
 4050         quota.QUOTAS.rollback.assert_called_once_with(
 4051             self.context, reservation,
 4052             share_type_id=share['instance']['share_type_id'])
 4053         (db_api.share_replicas_get_available_active_replica.
 4054          assert_called_once_with(self.context, share['id']))
 4055         share_types.get_share_type.assert_called_once_with(
 4056             self.context, share['instance']['share_type_id'])
 4057         (share_api.API.create_share_instance_and_get_request_spec.
 4058          assert_called_once_with(self.context, share, availability_zone=None,
 4059                                  share_network_id=share_network_id,
 4060                                  share_type_id=share_type['id'],
 4061                                  availability_zones=expected_azs,
 4062                                  cast_rules_to_readonly=False))
 4063 
 4064     def test_migration_complete(self):
 4065 
 4066         instance1 = db_utils.create_share_instance(
 4067             share_id='fake_id', status=constants.STATUS_MIGRATING)
 4068         instance2 = db_utils.create_share_instance(
 4069             share_id='fake_id', status=constants.STATUS_MIGRATING_TO)
 4070         share = db_utils.create_share(
 4071             id='fake_id',
 4072             task_state=constants.TASK_STATE_DATA_COPYING_COMPLETED,
 4073             instances=[instance1, instance2])
 4074 
 4075         self.mock_object(db_api, 'share_instance_get',
 4076                          mock.Mock(return_value=instance1))
 4077         self.mock_object(self.api.share_rpcapi, 'migration_complete')
 4078 
 4079         self.api.migration_complete(self.context, share)
 4080 
 4081         self.api.share_rpcapi.migration_complete.assert_called_once_with(
 4082             self.context, instance1, instance2['id'])
 4083 
 4084     @ddt.data(constants.TASK_STATE_DATA_COPYING_STARTING,
 4085               constants.TASK_STATE_MIGRATION_SUCCESS,
 4086               constants.TASK_STATE_DATA_COPYING_IN_PROGRESS,
 4087               constants.TASK_STATE_MIGRATION_ERROR,
 4088               constants.TASK_STATE_MIGRATION_CANCELLED,
 4089               None)
 4090     def test_migration_complete_task_state_invalid(self, task_state):
 4091 
 4092         share = db_utils.create_share(
 4093             id='fake_id',
 4094             task_state=task_state)
 4095 
 4096         self.assertRaises(exception.InvalidShare, self.api.migration_complete,
 4097                           self.context, share)
 4098 
 4099     def test_migration_complete_status_invalid(self):
 4100 
 4101         instance1 = db_utils.create_share_instance(
 4102             share_id='fake_id', status=constants.STATUS_ERROR)
 4103         instance2 = db_utils.create_share_instance(
 4104             share_id='fake_id', status=constants.STATUS_ERROR)
 4105         share = db_utils.create_share(
 4106             id='fake_id',
 4107             task_state=constants.TASK_STATE_DATA_COPYING_COMPLETED,
 4108             instances=[instance1, instance2])
 4109 
 4110         self.assertRaises(exception.ShareMigrationFailed,
 4111                           self.api.migration_complete, self.context,
 4112                           share)
 4113 
 4114     @ddt.data(None, Exception('fake'))
 4115     def test_migration_cancel(self, exc):
 4116 
 4117         share = db_utils.create_share(
 4118             id='fake_id',
 4119             task_state=constants.TASK_STATE_DATA_COPYING_IN_PROGRESS)
 4120         services = ['fake_service']
 4121 
 4122         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True))
 4123         self.mock_object(db_api, 'service_get_all_by_topic',
 4124                          mock.Mock(return_value=services))
 4125         self.mock_object(data_rpc.DataAPI, 'data_copy_cancel',
 4126                          mock.Mock(side_effect=[exc]))
 4127 
 4128         if exc:
 4129             self.assertRaises(
 4130                 exception.ShareMigrationError, self.api.migration_cancel,
 4131                 self.context, share)
 4132         else:
 4133             self.api.migration_cancel(self.context, share)
 4134 
 4135         data_rpc.DataAPI.data_copy_cancel.assert_called_once_with(
 4136             self.context, share['id'])
 4137         db_api.service_get_all_by_topic.assert_called_once_with(
 4138             self.context, 'manila-data')
 4139 
 4140     def test_migration_cancel_service_down(self):
 4141         service = 'fake_service'
 4142         instance1 = db_utils.create_share_instance(
 4143             share_id='fake_id', status=constants.STATUS_MIGRATING)
 4144         instance2 = db_utils.create_share_instance(
 4145             share_id='fake_id', status=constants.STATUS_MIGRATING_TO)
 4146         share = db_utils.create_share(
 4147             id='fake_id',
 4148             task_state=constants.TASK_STATE_DATA_COPYING_IN_PROGRESS,
 4149             instances=[instance1, instance2])
 4150 
 4151         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=False))
 4152         self.mock_object(db_api, 'share_instance_get',
 4153                          mock.Mock(return_value=instance1))
 4154         self.mock_object(db_api, 'service_get_all_by_topic',
 4155                          mock.Mock(return_value=service))
 4156 
 4157         self.assertRaises(exception.InvalidShare,
 4158                           self.api.migration_cancel, self.context, share)
 4159 
 4160     def test_migration_cancel_driver(self):
 4161 
 4162         service = 'fake_service'
 4163         instance1 = db_utils.create_share_instance(
 4164             share_id='fake_id',
 4165             status=constants.STATUS_MIGRATING,
 4166             host='some_host')
 4167         instance2 = db_utils.create_share_instance(
 4168             share_id='fake_id',
 4169             status=constants.STATUS_MIGRATING_TO)
 4170         share = db_utils.create_share(
 4171             id='fake_id',
 4172             task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
 4173             instances=[instance1, instance2])
 4174 
 4175         self.mock_object(db_api, 'share_instance_get',
 4176                          mock.Mock(return_value=instance1))
 4177         self.mock_object(self.api.share_rpcapi, 'migration_cancel')
 4178         self.mock_object(db_api, 'service_get_by_args',
 4179                          mock.Mock(return_value=service))
 4180         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True))
 4181 
 4182         self.api.migration_cancel(self.context, share)
 4183 
 4184         self.api.share_rpcapi.migration_cancel.assert_called_once_with(
 4185             self.context, instance1, instance2['id'])
 4186         db_api.service_get_by_args.assert_called_once_with(
 4187             self.context, instance1['host'], 'manila-share')
 4188 
 4189     @ddt.data(constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
 4190               constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE,
 4191               constants.TASK_STATE_DATA_COPYING_COMPLETED)
 4192     def test_migration_cancel_driver_service_down(self, task_state):
 4193 
 4194         service = 'fake_service'
 4195         instance1 = db_utils.create_share_instance(
 4196             share_id='fake_id',
 4197             status=constants.STATUS_MIGRATING,
 4198             host='some_host')
 4199         instance2 = db_utils.create_share_instance(
 4200             share_id='fake_id',
 4201             status=constants.STATUS_MIGRATING_TO)
 4202         share = db_utils.create_share(
 4203             id='fake_id',
 4204             task_state=task_state,
 4205             instances=[instance1, instance2])
 4206 
 4207         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=False))
 4208         self.mock_object(db_api, 'share_instance_get',
 4209                          mock.Mock(return_value=instance1))
 4210         self.mock_object(db_api, 'service_get_by_args',
 4211                          mock.Mock(return_value=service))
 4212 
 4213         self.assertRaises(exception.InvalidShare,
 4214                           self.api.migration_cancel, self.context, share)
 4215 
 4216     @ddt.data(constants.TASK_STATE_DATA_COPYING_STARTING,
 4217               constants.TASK_STATE_MIGRATION_SUCCESS,
 4218               constants.TASK_STATE_MIGRATION_ERROR,
 4219               constants.TASK_STATE_MIGRATION_CANCELLED,
 4220               None)
 4221     def test_migration_cancel_task_state_invalid(self, task_state):
 4222 
 4223         share = db_utils.create_share(
 4224             id='fake_id',
 4225             task_state=task_state)
 4226 
 4227         self.assertRaises(exception.InvalidShare, self.api.migration_cancel,
 4228                           self.context, share)
 4229 
 4230     @ddt.data({'total_progress': 50}, Exception('fake'))
 4231     def test_migration_get_progress(self, expected):
 4232 
 4233         share = db_utils.create_share(
 4234             id='fake_id',
 4235             task_state=constants.TASK_STATE_DATA_COPYING_IN_PROGRESS)
 4236         services = ['fake_service']
 4237 
 4238         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True))
 4239         self.mock_object(db_api, 'service_get_all_by_topic',
 4240                          mock.Mock(return_value=services))
 4241         self.mock_object(data_rpc.DataAPI, 'data_copy_get_progress',
 4242                          mock.Mock(side_effect=[expected]))
 4243 
 4244         if not isinstance(expected, Exception):
 4245             result = self.api.migration_get_progress(self.context, share)
 4246             self.assertEqual(expected, result)
 4247         else:
 4248             self.assertRaises(
 4249                 exception.ShareMigrationError, self.api.migration_get_progress,
 4250                 self.context, share)
 4251 
 4252         data_rpc.DataAPI.data_copy_get_progress.assert_called_once_with(
 4253             self.context, share['id'])
 4254         db_api.service_get_all_by_topic.assert_called_once_with(
 4255             self.context, 'manila-data')
 4256 
 4257     def test_migration_get_progress_service_down(self):
 4258         instance1 = db_utils.create_share_instance(
 4259             share_id='fake_id', status=constants.STATUS_MIGRATING)
 4260         instance2 = db_utils.create_share_instance(
 4261             share_id='fake_id', status=constants.STATUS_MIGRATING_TO)
 4262         share = db_utils.create_share(
 4263             id='fake_id',
 4264             task_state=constants.TASK_STATE_DATA_COPYING_IN_PROGRESS,
 4265             instances=[instance1, instance2])
 4266         services = ['fake_service']
 4267 
 4268         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=False))
 4269         self.mock_object(db_api, 'service_get_all_by_topic',
 4270                          mock.Mock(return_value=services))
 4271         self.mock_object(db_api, 'share_instance_get',
 4272                          mock.Mock(return_value=instance1))
 4273 
 4274         self.assertRaises(exception.InvalidShare,
 4275                           self.api.migration_get_progress, self.context, share)
 4276 
 4277     def test_migration_get_progress_driver(self):
 4278 
 4279         expected = {'total_progress': 50}
 4280         instance1 = db_utils.create_share_instance(
 4281             share_id='fake_id',
 4282             status=constants.STATUS_MIGRATING,
 4283             host='some_host')
 4284         instance2 = db_utils.create_share_instance(
 4285             share_id='fake_id',
 4286             status=constants.STATUS_MIGRATING_TO)
 4287         share = db_utils.create_share(
 4288             id='fake_id',
 4289             task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
 4290             instances=[instance1, instance2])
 4291         service = 'fake_service'
 4292 
 4293         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True))
 4294         self.mock_object(db_api, 'service_get_by_args',
 4295                          mock.Mock(return_value=service))
 4296         self.mock_object(db_api, 'share_instance_get',
 4297                          mock.Mock(return_value=instance1))
 4298         self.mock_object(self.api.share_rpcapi, 'migration_get_progress',
 4299                          mock.Mock(return_value=expected))
 4300 
 4301         result = self.api.migration_get_progress(self.context, share)
 4302 
 4303         self.assertEqual(expected, result)
 4304 
 4305         self.api.share_rpcapi.migration_get_progress.assert_called_once_with(
 4306             self.context, instance1, instance2['id'])
 4307         db_api.service_get_by_args.assert_called_once_with(
 4308             self.context, instance1['host'], 'manila-share')
 4309 
 4310     def test_migration_get_progress_driver_error(self):
 4311 
 4312         instance1 = db_utils.create_share_instance(
 4313             share_id='fake_id',
 4314             status=constants.STATUS_MIGRATING,
 4315             host='some_host')
 4316         instance2 = db_utils.create_share_instance(
 4317             share_id='fake_id',
 4318             status=constants.STATUS_MIGRATING_TO)
 4319         share = db_utils.create_share(
 4320             id='fake_id',
 4321             task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
 4322             instances=[instance1, instance2])
 4323         service = 'fake_service'
 4324 
 4325         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True))
 4326         self.mock_object(db_api, 'service_get_by_args',
 4327                          mock.Mock(return_value=service))
 4328         self.mock_object(db_api, 'share_instance_get',
 4329                          mock.Mock(return_value=instance1))
 4330         self.mock_object(self.api.share_rpcapi, 'migration_get_progress',
 4331                          mock.Mock(side_effect=Exception('fake')))
 4332 
 4333         self.assertRaises(exception.ShareMigrationError,
 4334                           self.api.migration_get_progress, self.context, share)
 4335 
 4336         self.api.share_rpcapi.migration_get_progress.assert_called_once_with(
 4337             self.context, instance1, instance2['id'])
 4338 
 4339     def test_migration_get_progress_driver_service_down(self):
 4340         service = 'fake_service'
 4341         instance1 = db_utils.create_share_instance(
 4342             share_id='fake_id',
 4343             status=constants.STATUS_MIGRATING,
 4344             host='some_host')
 4345         instance2 = db_utils.create_share_instance(
 4346             share_id='fake_id',
 4347             status=constants.STATUS_MIGRATING_TO)
 4348         share = db_utils.create_share(
 4349             id='fake_id',
 4350             task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
 4351             instances=[instance1, instance2])
 4352 
 4353         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=False))
 4354         self.mock_object(db_api, 'share_instance_get',
 4355                          mock.Mock(return_value=instance1))
 4356         self.mock_object(db_api, 'service_get_by_args',
 4357                          mock.Mock(return_value=service))
 4358 
 4359         self.assertRaises(exception.InvalidShare,
 4360                           self.api.migration_get_progress, self.context, share)
 4361 
 4362     @ddt.data(constants.TASK_STATE_MIGRATION_STARTING,
 4363               constants.TASK_STATE_MIGRATION_DRIVER_STARTING,
 4364               constants.TASK_STATE_DATA_COPYING_STARTING,
 4365               constants.TASK_STATE_MIGRATION_IN_PROGRESS)
 4366     def test_migration_get_progress_task_state_progress_0(self, task_state):
 4367 
 4368         share = db_utils.create_share(
 4369             id='fake_id',
 4370             task_state=task_state)
 4371         expected = {'total_progress': 0}
 4372 
 4373         result = self.api.migration_get_progress(self.context, share)
 4374 
 4375         self.assertEqual(expected, result)
 4376 
 4377     @ddt.data(constants.TASK_STATE_MIGRATION_SUCCESS,
 4378               constants.TASK_STATE_DATA_COPYING_ERROR,
 4379               constants.TASK_STATE_MIGRATION_CANCELLED,
 4380               constants.TASK_STATE_MIGRATION_COMPLETING,
 4381               constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE,
 4382               constants.TASK_STATE_DATA_COPYING_COMPLETED,
 4383               constants.TASK_STATE_DATA_COPYING_COMPLETING,
 4384               constants.TASK_STATE_DATA_COPYING_CANCELLED,
 4385               constants.TASK_STATE_MIGRATION_ERROR)
 4386     def test_migration_get_progress_task_state_progress_100(self, task_state):
 4387 
 4388         share = db_utils.create_share(
 4389             id='fake_id',
 4390             task_state=task_state)
 4391         expected = {'total_progress': 100}
 4392 
 4393         result = self.api.migration_get_progress(self.context, share)
 4394 
 4395         self.assertEqual(expected, result)
 4396 
 4397     def test_migration_get_progress_task_state_None(self):
 4398 
 4399         share = db_utils.create_share(id='fake_id', task_state=None)
 4400 
 4401         self.assertRaises(exception.InvalidShare,
 4402                           self.api.migration_get_progress, self.context, share)
 4403 
 4404     @ddt.data(None, {'invalid_progress': None}, {})
 4405     def test_migration_get_progress_invalid(self, progress):
 4406 
 4407         instance1 = db_utils.create_share_instance(
 4408             share_id='fake_id',
 4409             status=constants.STATUS_MIGRATING,
 4410             host='some_host')
 4411         instance2 = db_utils.create_share_instance(
 4412             share_id='fake_id',
 4413             status=constants.STATUS_MIGRATING_TO)
 4414         share = db_utils.create_share(
 4415             id='fake_id',
 4416             task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
 4417             instances=[instance1, instance2])
 4418         service = 'fake_service'
 4419 
 4420         self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True))
 4421         self.mock_object(db_api, 'service_get_by_args',
 4422                          mock.Mock(return_value=service))
 4423         self.mock_object(db_api, 'share_instance_get',
 4424                          mock.Mock(return_value=instance1))
 4425 
 4426         self.mock_object(self.api.share_rpcapi, 'migration_get_progress',
 4427                          mock.Mock(return_value=progress))
 4428 
 4429         self.assertRaises(exception.InvalidShare,
 4430                           self.api.migration_get_progress, self.context, share)
 4431 
 4432         self.api.share_rpcapi.migration_get_progress.assert_called_once_with(
 4433             self.context, instance1, instance2['id'])
 4434 
 4435     @ddt.data(True, False)
 4436     def test__migration_initial_checks(self, create_share_network):
 4437         type_data = {
 4438             'extra_specs': {
 4439                 'availability_zones': 'fake_az1,fake_az2'
 4440             }
 4441         }
 4442         fake_server_host = 'fake@backend'
 4443         fake_share_server = db_utils.create_share_server(host=fake_server_host)
 4444         share_type = db_utils.create_share_type(**type_data)
 4445         share_type = db_api.share_type_get(self.context, share_type['id'])
 4446         fake_share = db_utils.create_share(
 4447             host='fake@backend#pool', status=constants.STATUS_AVAILABLE,
 4448             share_type_id=share_type['id'])
 4449         fake_az = {
 4450             'id': 'fake_az_id',
 4451             'name': 'fake_az1'
 4452         }
 4453         fake_share_network = (
 4454             db_utils.create_share_network() if create_share_network else None)
 4455         fake_share_network_id = (
 4456             fake_share_network['id']
 4457             if create_share_network else fake_share['share_network_id'])
 4458         fake_subnet = db_utils.create_share_network_subnet(
 4459             availability_zone_id=fake_az['id'])
 4460 
 4461         fake_host = 'test@fake'
 4462         service = {'availability_zone_id': fake_az['id'],
 4463