4901 lines
229 KiB
Python
4901 lines
229 KiB
Python
# Copyright 2014 Mirantis Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""Test of Share Manager for Manila."""
|
|
import datetime
|
|
import random
|
|
|
|
import ddt
|
|
import mock
|
|
from oslo_concurrency import lockutils
|
|
from oslo_serialization import jsonutils
|
|
from oslo_utils import importutils
|
|
from oslo_utils import timeutils
|
|
import six
|
|
|
|
from manila.common import constants
|
|
from manila import context
|
|
from manila.data import rpcapi as data_rpc
|
|
from manila import db
|
|
from manila.db.sqlalchemy import models
|
|
from manila import exception
|
|
from manila import quota
|
|
from manila.share import access as share_access
|
|
from manila.share import drivers_private_data
|
|
from manila.share import manager
|
|
from manila.share import migration as migration_api
|
|
from manila.share import rpcapi
|
|
from manila.share import share_types
|
|
from manila import test
|
|
from manila.tests.api import fakes as test_fakes
|
|
from manila.tests import db_utils
|
|
from manila.tests import fake_share as fakes
|
|
from manila.tests import fake_utils
|
|
from manila.tests import utils as test_utils
|
|
from manila import utils
|
|
|
|
|
|
def fake_replica(**kwargs):
|
|
return fakes.fake_replica(for_manager=True, **kwargs)
|
|
|
|
|
|
class LockedOperationsTestCase(test.TestCase):
|
|
|
|
class FakeManager(object):
|
|
|
|
@manager.locked_share_replica_operation
|
|
def fake_replica_operation(self, context, replica, share_id=None):
|
|
pass
|
|
|
|
def setUp(self):
|
|
super(self.__class__, self).setUp()
|
|
self.manager = self.FakeManager()
|
|
self.fake_context = test_fakes.FakeRequestContext
|
|
self.lock_call = self.mock_object(
|
|
utils, 'synchronized', mock.Mock(return_value=lambda f: f))
|
|
|
|
@ddt.data({'id': 'FAKE_REPLICA_ID'}, 'FAKE_REPLICA_ID')
|
|
@ddt.unpack
|
|
def test_locked_share_replica_operation(self, **replica):
|
|
|
|
self.manager.fake_replica_operation(self.fake_context, replica,
|
|
share_id='FAKE_SHARE_ID')
|
|
|
|
self.assertTrue(self.lock_call.called)
|
|
|
|
|
|
@ddt.ddt
|
|
class ShareManagerTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(ShareManagerTestCase, self).setUp()
|
|
self.flags(share_driver='manila.tests.fake_driver.FakeShareDriver')
|
|
# Define class directly, because this test suite dedicated
|
|
# to specific manager.
|
|
self.share_manager = importutils.import_object(
|
|
"manila.share.manager.ShareManager")
|
|
self.mock_object(self.share_manager.driver, 'do_setup')
|
|
self.mock_object(self.share_manager.driver, 'check_for_setup_error')
|
|
self.context = context.get_admin_context()
|
|
self.share_manager.driver.initialized = True
|
|
mock.patch.object(
|
|
lockutils, 'lock', fake_utils.get_fake_lock_context())
|
|
self.synchronized_lock_decorator_call = self.mock_object(
|
|
utils, 'synchronized', mock.Mock(return_value=lambda f: f))
|
|
|
|
def test_share_manager_instance(self):
|
|
fake_service_name = "fake_service"
|
|
import_mock = mock.Mock()
|
|
self.mock_object(importutils, "import_object", import_mock)
|
|
private_data_mock = mock.Mock()
|
|
self.mock_object(drivers_private_data, "DriverPrivateData",
|
|
private_data_mock)
|
|
self.mock_object(manager.ShareManager, '_init_hook_drivers')
|
|
|
|
share_manager = manager.ShareManager(service_name=fake_service_name)
|
|
|
|
private_data_mock.assert_called_once_with(
|
|
context=mock.ANY,
|
|
backend_host=share_manager.host,
|
|
config_group=fake_service_name
|
|
)
|
|
self.assertTrue(import_mock.called)
|
|
self.assertTrue(manager.ShareManager._init_hook_drivers.called)
|
|
|
|
def test__init_hook_drivers(self):
|
|
fake_service_name = "fake_service"
|
|
import_mock = mock.Mock()
|
|
self.mock_object(importutils, "import_object", import_mock)
|
|
self.mock_object(drivers_private_data, "DriverPrivateData")
|
|
share_manager = manager.ShareManager(service_name=fake_service_name)
|
|
share_manager.configuration.safe_get = mock.Mock(
|
|
return_value=["Foo", "Bar"])
|
|
self.assertEqual(0, len(share_manager.hooks))
|
|
import_mock.reset()
|
|
|
|
share_manager._init_hook_drivers()
|
|
|
|
self.assertEqual(
|
|
len(share_manager.configuration.safe_get.return_value),
|
|
len(share_manager.hooks))
|
|
import_mock.assert_has_calls([
|
|
mock.call(
|
|
hook,
|
|
configuration=share_manager.configuration,
|
|
host=share_manager.host
|
|
) for hook in share_manager.configuration.safe_get.return_value
|
|
], any_order=True)
|
|
|
|
def test__execute_periodic_hook(self):
|
|
share_instances_mock = mock.Mock()
|
|
hook_data_mock = mock.Mock()
|
|
self.mock_object(
|
|
self.share_manager.db,
|
|
"share_instances_get_all_by_host",
|
|
share_instances_mock)
|
|
self.mock_object(
|
|
self.share_manager.driver,
|
|
"get_periodic_hook_data",
|
|
hook_data_mock)
|
|
self.share_manager.hooks = [mock.Mock(return_value=i) for i in (0, 1)]
|
|
|
|
self.share_manager._execute_periodic_hook(self.context)
|
|
|
|
share_instances_mock.assert_called_once_with(
|
|
context=self.context, host=self.share_manager.host)
|
|
hook_data_mock.assert_called_once_with(
|
|
context=self.context,
|
|
share_instances=share_instances_mock.return_value)
|
|
for mock_hook in self.share_manager.hooks:
|
|
mock_hook.execute_periodic_hook.assert_called_once_with(
|
|
context=self.context,
|
|
periodic_hook_data=hook_data_mock.return_value)
|
|
|
|
def test_init_host_with_no_shares(self):
|
|
self.mock_object(self.share_manager.db,
|
|
'share_instances_get_all_by_host',
|
|
mock.Mock(return_value=[]))
|
|
|
|
self.share_manager.init_host()
|
|
|
|
self.assertTrue(self.share_manager.driver.initialized)
|
|
self.share_manager.db.share_instances_get_all_by_host.\
|
|
assert_called_once_with(utils.IsAMatcher(context.RequestContext),
|
|
self.share_manager.host)
|
|
self.share_manager.driver.do_setup.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext))
|
|
self.share_manager.driver.check_for_setup_error.\
|
|
assert_called_once_with()
|
|
|
|
@ddt.data(
|
|
"migration_get_driver_info",
|
|
"migration_get_info",
|
|
"migration_cancel",
|
|
"migration_get_progress",
|
|
"migration_complete",
|
|
"migration_start",
|
|
"create_share_instance",
|
|
"manage_share",
|
|
"unmanage_share",
|
|
"delete_share_instance",
|
|
"delete_free_share_servers",
|
|
"create_snapshot",
|
|
"delete_snapshot",
|
|
"allow_access",
|
|
"deny_access",
|
|
"_report_driver_status",
|
|
"_execute_periodic_hook",
|
|
"publish_service_capabilities",
|
|
"delete_share_server",
|
|
"extend_share",
|
|
"shrink_share",
|
|
"create_consistency_group",
|
|
"delete_consistency_group",
|
|
"create_cgsnapshot",
|
|
"delete_cgsnapshot",
|
|
"create_share_replica",
|
|
"delete_share_replica",
|
|
"promote_share_replica",
|
|
"periodic_share_replica_update",
|
|
"update_share_replica",
|
|
"create_replicated_snapshot",
|
|
"delete_replicated_snapshot",
|
|
"periodic_share_replica_snapshot_update",
|
|
)
|
|
def test_call_driver_when_its_init_failed(self, method_name):
|
|
self.mock_object(self.share_manager.driver, 'do_setup',
|
|
mock.Mock(side_effect=Exception()))
|
|
self.share_manager.init_host()
|
|
|
|
self.assertRaises(
|
|
exception.DriverNotInitialized,
|
|
getattr(self.share_manager, method_name),
|
|
'foo', 'bar', 'quuz'
|
|
)
|
|
|
|
@ddt.data("do_setup", "check_for_setup_error")
|
|
def test_init_host_with_driver_failure(self, method_name):
|
|
self.mock_object(self.share_manager.driver, method_name,
|
|
mock.Mock(side_effect=Exception()))
|
|
self.mock_object(manager.LOG, 'exception')
|
|
self.share_manager.driver.initialized = False
|
|
|
|
self.share_manager.init_host()
|
|
|
|
manager.LOG.exception.assert_called_once_with(
|
|
mock.ANY, {'name': self.share_manager.driver.__class__.__name__,
|
|
'host': self.share_manager.host,
|
|
'exc': mock.ANY})
|
|
self.assertFalse(self.share_manager.driver.initialized)
|
|
|
|
def _setup_init_mocks(self, setup_access_rules=True):
|
|
instances = [
|
|
db_utils.create_share(id='fake_id_1',
|
|
status=constants.STATUS_AVAILABLE,
|
|
display_name='fake_name_1').instance,
|
|
db_utils.create_share(id='fake_id_2',
|
|
status=constants.STATUS_ERROR,
|
|
display_name='fake_name_2').instance,
|
|
db_utils.create_share(id='fake_id_3',
|
|
status=constants.STATUS_AVAILABLE,
|
|
display_name='fake_name_3').instance,
|
|
db_utils.create_share(
|
|
id='fake_id_4',
|
|
status=constants.STATUS_AVAILABLE,
|
|
task_state=constants.TASK_STATE_MIGRATION_IN_PROGRESS,
|
|
display_name='fake_name_4').instance,
|
|
db_utils.create_share(id='fake_id_5',
|
|
status=constants.STATUS_AVAILABLE,
|
|
display_name='fake_name_5').instance,
|
|
]
|
|
|
|
instances[4]['access_rules_status'] = constants.STATUS_OUT_OF_SYNC
|
|
|
|
if not setup_access_rules:
|
|
return instances
|
|
|
|
rules = [
|
|
db_utils.create_access(share_id='fake_id_1'),
|
|
db_utils.create_access(share_id='fake_id_3'),
|
|
]
|
|
|
|
return instances, rules
|
|
|
|
def test_init_host_with_shares_and_rules(self):
|
|
|
|
# initialization of test data
|
|
def raise_share_access_exists(*args, **kwargs):
|
|
raise exception.ShareAccessExists(
|
|
access_type='fake_access_type', access='fake_access')
|
|
|
|
instances, rules = self._setup_init_mocks()
|
|
fake_export_locations = ['fake/path/1', 'fake/path']
|
|
share_server = 'fake_share_server_type_does_not_matter'
|
|
self.mock_object(self.share_manager.db,
|
|
'share_instances_get_all_by_host',
|
|
mock.Mock(return_value=instances))
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(side_effect=[instances[0], instances[2],
|
|
instances[4]]))
|
|
self.mock_object(self.share_manager.db,
|
|
'share_export_locations_update')
|
|
self.mock_object(self.share_manager.driver, 'ensure_share',
|
|
mock.Mock(return_value=fake_export_locations))
|
|
self.mock_object(self.share_manager, '_ensure_share_instance_has_pool')
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=share_server))
|
|
self.mock_object(self.share_manager, 'publish_service_capabilities',
|
|
mock.Mock())
|
|
self.mock_object(self.share_manager.db,
|
|
'share_access_get_all_for_share',
|
|
mock.Mock(return_value=rules))
|
|
self.mock_object(
|
|
self.share_manager.access_helper,
|
|
'update_access_rules',
|
|
mock.Mock(side_effect=raise_share_access_exists)
|
|
)
|
|
|
|
# call of 'init_host' method
|
|
self.share_manager.init_host()
|
|
|
|
# verification of call
|
|
self.share_manager.db.share_instances_get_all_by_host.\
|
|
assert_called_once_with(utils.IsAMatcher(context.RequestContext),
|
|
self.share_manager.host)
|
|
exports_update = self.share_manager.db.share_export_locations_update
|
|
exports_update.assert_has_calls([
|
|
mock.call(mock.ANY, instances[0]['id'], fake_export_locations),
|
|
mock.call(mock.ANY, instances[2]['id'], fake_export_locations)
|
|
])
|
|
self.share_manager.driver.do_setup.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext))
|
|
self.share_manager.driver.check_for_setup_error.\
|
|
assert_called_once_with()
|
|
self.share_manager._ensure_share_instance_has_pool.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0]),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2]),
|
|
])
|
|
self.share_manager._get_share_server.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0]),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2]),
|
|
])
|
|
self.share_manager.driver.ensure_share.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0],
|
|
share_server=share_server),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2],
|
|
share_server=share_server),
|
|
])
|
|
self.share_manager.publish_service_capabilities.\
|
|
assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext))
|
|
self.share_manager.access_helper.update_access_rules.assert_has_calls([
|
|
mock.call(mock.ANY, instances[4]['id'], share_server=share_server),
|
|
])
|
|
|
|
def test_init_host_with_exception_on_ensure_share(self):
|
|
def raise_exception(*args, **kwargs):
|
|
raise exception.ManilaException(message="Fake raise")
|
|
|
|
instances = self._setup_init_mocks(setup_access_rules=False)
|
|
share_server = 'fake_share_server_type_does_not_matter'
|
|
self.mock_object(self.share_manager.db,
|
|
'share_instances_get_all_by_host',
|
|
mock.Mock(return_value=instances))
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(side_effect=[instances[0], instances[2],
|
|
instances[3]]))
|
|
self.mock_object(self.share_manager.driver, 'ensure_share',
|
|
mock.Mock(side_effect=raise_exception))
|
|
self.mock_object(self.share_manager, '_ensure_share_instance_has_pool')
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=share_server))
|
|
self.mock_object(self.share_manager, 'publish_service_capabilities')
|
|
self.mock_object(manager.LOG, 'error')
|
|
self.mock_object(manager.LOG, 'info')
|
|
|
|
# call of 'init_host' method
|
|
self.share_manager.init_host()
|
|
|
|
# verification of call
|
|
self.share_manager.db.share_instances_get_all_by_host.\
|
|
assert_called_once_with(utils.IsAMatcher(context.RequestContext),
|
|
self.share_manager.host)
|
|
self.share_manager.driver.do_setup.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext))
|
|
self.share_manager.driver.check_for_setup_error.assert_called_with()
|
|
self.share_manager._ensure_share_instance_has_pool.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0]),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2]),
|
|
])
|
|
self.share_manager._get_share_server.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0]),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2]),
|
|
])
|
|
self.share_manager.driver.ensure_share.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0],
|
|
share_server=share_server),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2],
|
|
share_server=share_server),
|
|
])
|
|
self.share_manager.publish_service_capabilities.\
|
|
assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext))
|
|
manager.LOG.info.assert_any_call(
|
|
mock.ANY,
|
|
{'task': constants.TASK_STATE_MIGRATION_IN_PROGRESS,
|
|
'id': instances[3]['id']},
|
|
)
|
|
manager.LOG.info.assert_any_call(
|
|
mock.ANY,
|
|
{'id': instances[1]['id'], 'status': instances[1]['status']},
|
|
)
|
|
|
|
def test_init_host_with_exception_on_update_access_rules(self):
|
|
def raise_exception(*args, **kwargs):
|
|
raise exception.ManilaException(message="Fake raise")
|
|
|
|
instances, rules = self._setup_init_mocks()
|
|
share_server = 'fake_share_server_type_does_not_matter'
|
|
smanager = self.share_manager
|
|
self.mock_object(smanager.db, 'share_instances_get_all_by_host',
|
|
mock.Mock(return_value=instances))
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(side_effect=[instances[0], instances[2],
|
|
instances[4]]))
|
|
self.mock_object(self.share_manager.driver, 'ensure_share',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(smanager, '_ensure_share_instance_has_pool')
|
|
self.mock_object(smanager, '_get_share_server',
|
|
mock.Mock(return_value=share_server))
|
|
self.mock_object(smanager, 'publish_service_capabilities')
|
|
self.mock_object(manager.LOG, 'error')
|
|
self.mock_object(manager.LOG, 'info')
|
|
self.mock_object(smanager.db, 'share_access_get_all_for_share',
|
|
mock.Mock(return_value=rules))
|
|
self.mock_object(smanager.access_helper, 'update_access_rules',
|
|
mock.Mock(side_effect=raise_exception))
|
|
|
|
# call of 'init_host' method
|
|
smanager.init_host()
|
|
|
|
# verification of call
|
|
smanager.db.share_instances_get_all_by_host.\
|
|
assert_called_once_with(utils.IsAMatcher(context.RequestContext),
|
|
smanager.host)
|
|
smanager.driver.do_setup.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext))
|
|
smanager.driver.check_for_setup_error.assert_called_with()
|
|
smanager._ensure_share_instance_has_pool.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0]),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2]),
|
|
])
|
|
smanager._get_share_server.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0]),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2]),
|
|
])
|
|
smanager.driver.ensure_share.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[0],
|
|
share_server=share_server),
|
|
mock.call(utils.IsAMatcher(context.RequestContext), instances[2],
|
|
share_server=share_server),
|
|
])
|
|
self.share_manager.publish_service_capabilities.\
|
|
assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext))
|
|
manager.LOG.info.assert_any_call(
|
|
mock.ANY,
|
|
{'task': constants.TASK_STATE_MIGRATION_IN_PROGRESS,
|
|
'id': instances[3]['id']},
|
|
)
|
|
manager.LOG.info.assert_any_call(
|
|
mock.ANY,
|
|
{'id': instances[1]['id'], 'status': instances[1]['status']},
|
|
)
|
|
smanager.access_helper.update_access_rules.assert_has_calls([
|
|
mock.call(utils.IsAMatcher(context.RequestContext),
|
|
instances[4]['id'], share_server=share_server),
|
|
])
|
|
manager.LOG.error.assert_has_calls([
|
|
mock.call(mock.ANY, mock.ANY),
|
|
])
|
|
|
|
def test_create_share_instance_from_snapshot_with_server(self):
|
|
"""Test share can be created from snapshot if server exists."""
|
|
network = db_utils.create_share_network()
|
|
server = db_utils.create_share_server(
|
|
share_network_id=network['id'], host='fake_host',
|
|
backend_details=dict(fake='fake'))
|
|
parent_share = db_utils.create_share(share_network_id='net-id',
|
|
share_server_id=server['id'])
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
snapshot = db_utils.create_snapshot(share_id=parent_share['id'])
|
|
snapshot_id = snapshot['id']
|
|
|
|
self.share_manager.create_share_instance(
|
|
self.context, share.instance['id'], snapshot_id=snapshot_id)
|
|
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
|
share_id).id)
|
|
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(constants.STATUS_AVAILABLE, shr['status'])
|
|
self.assertEqual(server['id'], shr['instance']['share_server_id'])
|
|
|
|
def test_create_share_instance_from_snapshot_with_server_not_found(self):
|
|
"""Test creation from snapshot fails if server not found."""
|
|
parent_share = db_utils.create_share(share_network_id='net-id',
|
|
share_server_id='fake-id')
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
snapshot = db_utils.create_snapshot(share_id=parent_share['id'])
|
|
snapshot_id = snapshot['id']
|
|
|
|
self.assertRaises(exception.ShareServerNotFound,
|
|
self.share_manager.create_share_instance,
|
|
self.context,
|
|
share.instance['id'],
|
|
snapshot_id=snapshot_id
|
|
)
|
|
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(constants.STATUS_ERROR, shr['status'])
|
|
|
|
def test_create_share_instance_from_snapshot(self):
|
|
"""Test share can be created from snapshot."""
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
snapshot = db_utils.create_snapshot(share_id=share_id)
|
|
snapshot_id = snapshot['id']
|
|
|
|
self.share_manager.create_share_instance(
|
|
self.context, share.instance['id'], snapshot_id=snapshot_id)
|
|
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
|
share_id).id)
|
|
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(constants.STATUS_AVAILABLE, shr['status'])
|
|
self.assertTrue(len(shr['export_location']) > 0)
|
|
self.assertEqual(2, len(shr['export_locations']))
|
|
|
|
def test_create_share_instance_for_share_with_replication_support(self):
|
|
"""Test update call is made to update replica_state."""
|
|
share = db_utils.create_share(replication_type='writable')
|
|
share_id = share['id']
|
|
|
|
self.share_manager.create_share_instance(self.context,
|
|
share.instance['id'])
|
|
|
|
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
|
share_id).id)
|
|
|
|
shr = db.share_get(self.context, share_id)
|
|
shr_instance = db.share_instance_get(self.context,
|
|
share.instance['id'])
|
|
|
|
self.assertEqual(constants.STATUS_AVAILABLE, shr['status'],)
|
|
self.assertEqual(constants.REPLICA_STATE_ACTIVE,
|
|
shr_instance['replica_state'])
|
|
|
|
@ddt.data([], None)
|
|
def test_create_share_replica_no_active_replicas(self, active_replicas):
|
|
replica = fake_replica()
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=active_replicas))
|
|
self.mock_object(
|
|
db, 'share_replica_get', mock.Mock(return_value=replica))
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_driver_replica_call = self.mock_object(
|
|
self.share_manager.driver, 'create_replica')
|
|
|
|
self.assertRaises(exception.ReplicationException,
|
|
self.share_manager.create_share_replica,
|
|
self.context, replica)
|
|
mock_replica_update_call.assert_called_once_with(
|
|
mock.ANY, replica['id'], {'status': constants.STATUS_ERROR,
|
|
'replica_state': constants.STATUS_ERROR})
|
|
self.assertFalse(mock_driver_replica_call.called)
|
|
|
|
def test_create_share_replica_with_share_network_id_and_not_dhss(self):
|
|
replica = fake_replica()
|
|
manager.CONF.set_default('driver_handles_share_servers', False)
|
|
self.mock_object(db, 'share_access_get_all_for_share',
|
|
mock.Mock(return_value=[]))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=fake_replica(id='fake2')))
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_driver_replica_call = self.mock_object(
|
|
self.share_manager.driver, 'create_replica')
|
|
|
|
self.assertRaises(exception.InvalidDriverMode,
|
|
self.share_manager.create_share_replica,
|
|
self.context, replica)
|
|
mock_replica_update_call.assert_called_once_with(
|
|
mock.ANY, replica['id'], {'status': constants.STATUS_ERROR,
|
|
'replica_state': constants.STATUS_ERROR})
|
|
self.assertFalse(mock_driver_replica_call.called)
|
|
|
|
def test_create_share_replica_with_share_server_exception(self):
|
|
replica = fake_replica()
|
|
manager.CONF.set_default('driver_handles_share_servers', True)
|
|
self.mock_object(db, 'share_instance_access_copy',
|
|
mock.Mock(return_value=[]))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=fake_replica(id='fake2')))
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_driver_replica_call = self.mock_object(
|
|
self.share_manager.driver, 'create_replica')
|
|
|
|
self.assertRaises(exception.NotFound,
|
|
self.share_manager.create_share_replica,
|
|
self.context, replica)
|
|
mock_replica_update_call.assert_called_once_with(
|
|
mock.ANY, replica['id'], {'status': constants.STATUS_ERROR,
|
|
'replica_state': constants.STATUS_ERROR})
|
|
self.assertFalse(mock_driver_replica_call.called)
|
|
|
|
def test_create_share_replica_driver_error_on_creation(self):
|
|
fake_access_rules = [{'id': '1'}, {'id': '2'}, {'id': '3'}]
|
|
replica = fake_replica(share_network_id='')
|
|
replica_2 = fake_replica(id='fake2')
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_instance_access_copy',
|
|
mock.Mock(return_value=fake_access_rules))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=replica_2))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, replica_2]))
|
|
self.mock_object(self.share_manager,
|
|
'_provide_share_server_for_share',
|
|
mock.Mock(return_value=('FAKE_SERVER', replica)))
|
|
self.mock_object(self.share_manager,
|
|
'_get_replica_snapshots_for_snapshot',
|
|
mock.Mock(return_value=[]))
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_export_locs_update_call = self.mock_object(
|
|
db, 'share_export_locations_update')
|
|
mock_log_error = self.mock_object(manager.LOG, 'error')
|
|
mock_log_info = self.mock_object(manager.LOG, 'info')
|
|
self.mock_object(db, 'share_instance_access_get',
|
|
mock.Mock(return_value=fake_access_rules[0]))
|
|
mock_share_replica_access_update = self.mock_object(
|
|
db, 'share_instance_update_access_status')
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
|
|
driver_call = self.mock_object(
|
|
self.share_manager.driver, 'create_replica',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.create_share_replica,
|
|
self.context, replica)
|
|
mock_replica_update_call.assert_called_once_with(
|
|
mock.ANY, replica['id'], {'status': constants.STATUS_ERROR,
|
|
'replica_state': constants.STATUS_ERROR})
|
|
self.assertEqual(1, mock_share_replica_access_update.call_count)
|
|
self.assertFalse(mock_export_locs_update_call.called)
|
|
self.assertTrue(mock_log_error.called)
|
|
self.assertFalse(mock_log_info.called)
|
|
self.assertTrue(driver_call.called)
|
|
|
|
def test_create_share_replica_invalid_locations_state(self):
|
|
driver_retval = {
|
|
'export_locations': 'FAKE_EXPORT_LOC',
|
|
}
|
|
replica = fake_replica(share_network='')
|
|
replica_2 = fake_replica(id='fake2')
|
|
fake_access_rules = [{'id': '1'}, {'id': '2'}]
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=replica_2))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, replica_2]))
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_instance_access_copy',
|
|
mock.Mock(return_value=fake_access_rules))
|
|
self.mock_object(self.share_manager,
|
|
'_provide_share_server_for_share',
|
|
mock.Mock(return_value=('FAKE_SERVER', replica)))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager,
|
|
'_get_replica_snapshots_for_snapshot',
|
|
mock.Mock(return_value=[]))
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_export_locs_update_call = self.mock_object(
|
|
db, 'share_export_locations_update')
|
|
mock_log_info = self.mock_object(manager.LOG, 'info')
|
|
mock_log_warning = self.mock_object(manager.LOG, 'warning')
|
|
mock_log_error = self.mock_object(manager.LOG, 'error')
|
|
driver_call = self.mock_object(
|
|
self.share_manager.driver, 'create_replica',
|
|
mock.Mock(return_value=driver_retval))
|
|
self.mock_object(db, 'share_instance_access_get',
|
|
mock.Mock(return_value=fake_access_rules[0]))
|
|
mock_share_replica_access_update = self.mock_object(
|
|
db, 'share_instance_update_access_status')
|
|
|
|
self.share_manager.create_share_replica(self.context, replica)
|
|
|
|
self.assertFalse(mock_replica_update_call.called)
|
|
self.assertEqual(1, mock_share_replica_access_update.call_count)
|
|
self.assertFalse(mock_export_locs_update_call.called)
|
|
self.assertTrue(mock_log_info.called)
|
|
self.assertTrue(mock_log_warning.called)
|
|
self.assertFalse(mock_log_error.called)
|
|
self.assertTrue(driver_call.called)
|
|
call_args = driver_call.call_args_list[0][0]
|
|
replica_list_arg = call_args[1]
|
|
r_ids = [r['id'] for r in replica_list_arg]
|
|
for r in (replica, replica_2):
|
|
self.assertIn(r['id'], r_ids)
|
|
self.assertEqual(2, len(r_ids))
|
|
|
|
def test_create_share_replica_no_availability_zone(self):
|
|
replica = fake_replica(
|
|
availability_zone=None, share_network='',
|
|
replica_state=constants.REPLICA_STATE_OUT_OF_SYNC)
|
|
replica_2 = fake_replica(id='fake2')
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, replica_2]))
|
|
manager.CONF.set_default('storage_availability_zone', 'fake_az')
|
|
fake_access_rules = [{'id': '1'}, {'id': '2'}, {'id': '3'}]
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_instance_access_copy',
|
|
mock.Mock(return_value=fake_access_rules))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=replica_2))
|
|
self.mock_object(self.share_manager,
|
|
'_provide_share_server_for_share',
|
|
mock.Mock(return_value=('FAKE_SERVER', replica)))
|
|
self.mock_object(self.share_manager,
|
|
'_get_replica_snapshots_for_snapshot',
|
|
mock.Mock(return_value=[]))
|
|
mock_replica_update_call = self.mock_object(
|
|
db, 'share_replica_update', mock.Mock(return_value=replica))
|
|
mock_calls = [
|
|
mock.call(mock.ANY, replica['id'],
|
|
{'availability_zone': 'fake_az'}, with_share_data=True),
|
|
mock.call(mock.ANY, replica['id'],
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'replica_state': constants.REPLICA_STATE_OUT_OF_SYNC}),
|
|
]
|
|
mock_export_locs_update_call = self.mock_object(
|
|
db, 'share_export_locations_update')
|
|
mock_log_info = self.mock_object(manager.LOG, 'info')
|
|
mock_log_warning = self.mock_object(manager.LOG, 'warning')
|
|
mock_log_error = self.mock_object(manager.LOG, 'warning')
|
|
self.mock_object(db, 'share_instance_access_get',
|
|
mock.Mock(return_value=fake_access_rules[0]))
|
|
mock_share_replica_access_update = self.mock_object(
|
|
self.share_manager, '_update_share_replica_access_rules_state')
|
|
driver_call = self.mock_object(
|
|
self.share_manager.driver, 'create_replica',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(self.share_manager, '_get_share_server', mock.Mock())
|
|
|
|
self.share_manager.create_share_replica(self.context, replica)
|
|
|
|
mock_replica_update_call.assert_has_calls(mock_calls, any_order=False)
|
|
mock_share_replica_access_update.assert_called_once_with(
|
|
mock.ANY, replica['id'], replica['access_rules_status'])
|
|
self.assertTrue(mock_export_locs_update_call.called)
|
|
self.assertTrue(mock_log_info.called)
|
|
self.assertFalse(mock_log_warning.called)
|
|
self.assertFalse(mock_log_error.called)
|
|
self.assertTrue(driver_call.called)
|
|
|
|
@ddt.data(True, False)
|
|
def test_create_share_replica(self, has_snapshots):
|
|
replica = fake_replica(
|
|
share_network='', replica_state=constants.REPLICA_STATE_IN_SYNC)
|
|
replica_2 = fake_replica(id='fake2')
|
|
snapshots = ([fakes.fake_snapshot(create_instance=True)]
|
|
if has_snapshots else [])
|
|
snapshot_instances = [
|
|
fakes.fake_snapshot_instance(share_instance_id=replica['id']),
|
|
fakes.fake_snapshot_instance(share_instance_id='fake2'),
|
|
]
|
|
fake_access_rules = [{'id': '1'}, {'id': '2'}, {'id': '3'}]
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_instance_access_copy',
|
|
mock.Mock(return_value=fake_access_rules))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=replica_2))
|
|
self.mock_object(self.share_manager,
|
|
'_provide_share_server_for_share',
|
|
mock.Mock(return_value=('FAKE_SERVER', replica)))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, replica_2]))
|
|
self.mock_object(db, 'share_snapshot_get_all_for_share', mock.Mock(
|
|
return_value=snapshots))
|
|
mock_instance_get_call = self.mock_object(
|
|
db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_export_locs_update_call = self.mock_object(
|
|
db, 'share_export_locations_update')
|
|
mock_log_info = self.mock_object(manager.LOG, 'info')
|
|
mock_log_warning = self.mock_object(manager.LOG, 'warning')
|
|
mock_log_error = self.mock_object(manager.LOG, 'warning')
|
|
self.mock_object(db, 'share_instance_access_get',
|
|
mock.Mock(return_value=fake_access_rules[0]))
|
|
mock_share_replica_access_update = self.mock_object(
|
|
db, 'share_instance_update_access_status')
|
|
driver_call = self.mock_object(
|
|
self.share_manager.driver, 'create_replica',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
|
|
self.share_manager.create_share_replica(self.context, replica)
|
|
|
|
mock_replica_update_call.assert_called_once_with(
|
|
mock.ANY, replica['id'],
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'replica_state': constants.REPLICA_STATE_IN_SYNC})
|
|
self.assertEqual(1, mock_share_replica_access_update.call_count)
|
|
self.assertTrue(mock_export_locs_update_call.called)
|
|
self.assertTrue(mock_log_info.called)
|
|
self.assertFalse(mock_log_warning.called)
|
|
self.assertFalse(mock_log_error.called)
|
|
self.assertTrue(driver_call.called)
|
|
call_args = driver_call.call_args_list[0][0]
|
|
replica_list_arg = call_args[1]
|
|
snapshot_list_arg = call_args[4]
|
|
r_ids = [r['id'] for r in replica_list_arg]
|
|
for r in (replica, replica_2):
|
|
self.assertIn(r['id'], r_ids)
|
|
self.assertEqual(2, len(r_ids))
|
|
if has_snapshots:
|
|
for snapshot_dict in snapshot_list_arg:
|
|
self.assertTrue('active_replica_snapshot' in snapshot_dict)
|
|
self.assertTrue('share_replica_snapshot' in snapshot_dict)
|
|
else:
|
|
self.assertFalse(mock_instance_get_call.called)
|
|
|
|
def test_delete_share_replica_access_rules_exception(self):
|
|
replica = fake_replica()
|
|
replica_2 = fake_replica(id='fake_2')
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, replica_2]))
|
|
active_replica = fake_replica(
|
|
id='Current_active_replica',
|
|
replica_state=constants.REPLICA_STATE_ACTIVE)
|
|
mock_exception_log = self.mock_object(manager.LOG, 'exception')
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=active_replica))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(self.share_manager.access_helper,
|
|
'update_access_rules')
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_replica_delete_call = self.mock_object(db, 'share_replica_delete')
|
|
mock_drv_delete_replica_call = self.mock_object(
|
|
self.share_manager.driver, 'delete_replica')
|
|
self.mock_object(
|
|
self.share_manager.access_helper, 'update_access_rules',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.delete_share_replica,
|
|
self.context, replica['id'],
|
|
share_id=replica['share_id'])
|
|
mock_replica_update_call.assert_called_once_with(
|
|
mock.ANY, replica['id'], {'status': constants.STATUS_ERROR})
|
|
self.assertFalse(mock_drv_delete_replica_call.called)
|
|
self.assertFalse(mock_replica_delete_call.called)
|
|
self.assertFalse(mock_exception_log.called)
|
|
|
|
def test_delete_share_replica_drv_misbehavior_ignored_with_the_force(self):
|
|
replica = fake_replica()
|
|
active_replica = fake_replica(id='Current_active_replica')
|
|
mock_exception_log = self.mock_object(manager.LOG, 'exception')
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, active_replica]))
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=active_replica))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager.access_helper,
|
|
'update_access_rules')
|
|
self.mock_object(
|
|
db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=[]))
|
|
mock_snap_instance_delete = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_replica_delete_call = self.mock_object(db, 'share_replica_delete')
|
|
mock_drv_delete_replica_call = self.mock_object(
|
|
self.share_manager.driver, 'delete_replica',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
self.mock_object(
|
|
self.share_manager.access_helper, 'update_access_rules')
|
|
|
|
self.share_manager.delete_share_replica(
|
|
self.context, replica['id'], share_id=replica['share_id'],
|
|
force=True)
|
|
|
|
self.assertFalse(mock_replica_update_call.called)
|
|
self.assertTrue(mock_replica_delete_call.called)
|
|
self.assertEqual(1, mock_exception_log.call_count)
|
|
self.assertTrue(mock_drv_delete_replica_call.called)
|
|
self.assertFalse(mock_snap_instance_delete.called)
|
|
|
|
def test_delete_share_replica_driver_exception(self):
|
|
replica = fake_replica()
|
|
active_replica = fake_replica(id='Current_active_replica')
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, active_replica]))
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=active_replica))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
mock_snapshot_get_call = self.mock_object(
|
|
db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=[]))
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_replica_delete_call = self.mock_object(db, 'share_replica_delete')
|
|
self.mock_object(
|
|
self.share_manager.access_helper, 'update_access_rules')
|
|
mock_drv_delete_replica_call = self.mock_object(
|
|
self.share_manager.driver, 'delete_replica',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.delete_share_replica,
|
|
self.context, replica['id'],
|
|
share_id=replica['share_id'])
|
|
self.assertTrue(mock_replica_update_call.called)
|
|
self.assertFalse(mock_replica_delete_call.called)
|
|
self.assertTrue(mock_drv_delete_replica_call.called)
|
|
self.assertTrue(mock_snapshot_get_call.called)
|
|
|
|
def test_delete_share_replica_both_exceptions_ignored_with_the_force(self):
|
|
replica = fake_replica()
|
|
active_replica = fake_replica(id='Current_active_replica')
|
|
snapshots = [
|
|
fakes.fake_snapshot(share_id=replica['id'],
|
|
status=constants.STATUS_AVAILABLE),
|
|
fakes.fake_snapshot(share_id=replica['id'],
|
|
id='test_creating_to_err',
|
|
status=constants.STATUS_CREATING)
|
|
]
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, active_replica]))
|
|
mock_exception_log = self.mock_object(manager.LOG, 'exception')
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=active_replica))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(
|
|
db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshots))
|
|
mock_snapshot_instance_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_replica_delete_call = self.mock_object(db, 'share_replica_delete')
|
|
self.mock_object(
|
|
self.share_manager.access_helper, 'update_access_rules',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
mock_drv_delete_replica_call = self.mock_object(
|
|
self.share_manager.driver, 'delete_replica',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
|
|
self.share_manager.delete_share_replica(
|
|
self.context, replica['id'], share_id=replica['share_id'],
|
|
force=True)
|
|
|
|
mock_replica_update_call.assert_called_once_with(
|
|
mock.ANY, replica['id'], {'status': constants.STATUS_ERROR})
|
|
self.assertTrue(mock_replica_delete_call.called)
|
|
self.assertEqual(2, mock_exception_log.call_count)
|
|
self.assertTrue(mock_drv_delete_replica_call.called)
|
|
self.assertEqual(2, mock_snapshot_instance_delete_call.call_count)
|
|
|
|
def test_delete_share_replica(self):
|
|
replica = fake_replica()
|
|
active_replica = fake_replica(id='current_active_replica')
|
|
snapshots = [
|
|
fakes.fake_snapshot(share_id=replica['share_id'],
|
|
status=constants.STATUS_AVAILABLE),
|
|
fakes.fake_snapshot(share_id=replica['share_id'],
|
|
id='test_creating_to_err',
|
|
status=constants.STATUS_CREATING)
|
|
]
|
|
self.mock_object(
|
|
db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshots))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, active_replica]))
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=active_replica))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
mock_info_log = self.mock_object(manager.LOG, 'info')
|
|
mock_snapshot_instance_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
mock_replica_update_call = self.mock_object(db, 'share_replica_update')
|
|
mock_replica_delete_call = self.mock_object(db, 'share_replica_delete')
|
|
self.mock_object(
|
|
self.share_manager.access_helper, 'update_access_rules')
|
|
mock_drv_delete_replica_call = self.mock_object(
|
|
self.share_manager.driver, 'delete_replica')
|
|
|
|
self.share_manager.delete_share_replica(self.context, replica)
|
|
|
|
self.assertFalse(mock_replica_update_call.called)
|
|
self.assertTrue(mock_replica_delete_call.called)
|
|
self.assertTrue(mock_info_log.called)
|
|
self.assertTrue(mock_drv_delete_replica_call.called)
|
|
self.assertEqual(2, mock_snapshot_instance_delete_call.call_count)
|
|
|
|
def test_promote_share_replica_no_active_replica(self):
|
|
replica = fake_replica()
|
|
replica_list = [replica]
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_replicas_get_available_active_replica',
|
|
mock.Mock(return_value=replica_list))
|
|
mock_info_log = self.mock_object(manager.LOG, 'info')
|
|
mock_driver_call = self.mock_object(self.share_manager.driver,
|
|
'promote_replica')
|
|
mock_replica_update = self.mock_object(db, 'share_replica_update')
|
|
expected_update_call = mock.call(
|
|
mock.ANY, replica['id'], {'status': constants.STATUS_AVAILABLE})
|
|
|
|
self.assertRaises(exception.ReplicationException,
|
|
self.share_manager.promote_share_replica,
|
|
self.context, replica)
|
|
self.assertFalse(mock_info_log.called)
|
|
self.assertFalse(mock_driver_call.called)
|
|
mock_replica_update.assert_has_calls([expected_update_call])
|
|
|
|
def test_promote_share_replica_driver_exception(self):
|
|
replica = fake_replica()
|
|
active_replica = fake_replica(
|
|
id='current_active_replica',
|
|
replica_state=constants.REPLICA_STATE_ACTIVE)
|
|
replica_list = [replica, active_replica]
|
|
self.mock_object(db, 'share_access_get_all_for_share',
|
|
mock.Mock(return_value=[]))
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replica_list))
|
|
self.mock_object(self.share_manager.driver, 'promote_replica',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
mock_info_log = self.mock_object(manager.LOG, 'info')
|
|
mock_replica_update = self.mock_object(db, 'share_replica_update')
|
|
expected_update_calls = [mock.call(
|
|
mock.ANY, r['id'], {'status': constants.STATUS_ERROR})
|
|
for r in(replica, active_replica)]
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.promote_share_replica,
|
|
self.context, replica)
|
|
mock_replica_update.assert_has_calls(expected_update_calls)
|
|
self.assertFalse(mock_info_log.called)
|
|
|
|
@ddt.data([], None)
|
|
def test_promote_share_replica_driver_update_nothing_has_snaps(self,
|
|
retval):
|
|
replica = fake_replica()
|
|
active_replica = fake_replica(
|
|
id='current_active_replica',
|
|
replica_state=constants.REPLICA_STATE_ACTIVE)
|
|
snapshots_instances = [
|
|
fakes.fake_snapshot(create_instance=True,
|
|
share_id=replica['share_id'],
|
|
status=constants.STATUS_AVAILABLE),
|
|
fakes.fake_snapshot(create_instance=True,
|
|
share_id=replica['share_id'],
|
|
id='test_creating_to_err',
|
|
status=constants.STATUS_CREATING)
|
|
]
|
|
replica_list = [replica, active_replica]
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_access_get_all_for_share',
|
|
mock.Mock(return_value=[]))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replica_list))
|
|
self.mock_object(
|
|
db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshots_instances))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'promote_replica',
|
|
mock.Mock(return_value=retval))
|
|
mock_snap_instance_update = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
mock_info_log = self.mock_object(manager.LOG, 'info')
|
|
mock_export_locs_update = self.mock_object(
|
|
db, 'share_export_locations_update')
|
|
mock_replica_update = self.mock_object(db, 'share_replica_update')
|
|
call_1 = mock.call(mock.ANY, replica['id'],
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'replica_state': constants.REPLICA_STATE_ACTIVE})
|
|
call_2 = mock.call(
|
|
mock.ANY, 'current_active_replica',
|
|
{'replica_state': constants.REPLICA_STATE_OUT_OF_SYNC})
|
|
expected_update_calls = [call_1, call_2]
|
|
|
|
self.share_manager.promote_share_replica(self.context, replica)
|
|
|
|
self.assertFalse(mock_export_locs_update.called)
|
|
mock_replica_update.assert_has_calls(expected_update_calls,
|
|
any_order=True)
|
|
mock_snap_instance_update.assert_called_once_with(
|
|
mock.ANY, 'test_creating_to_err',
|
|
{'status': constants.STATUS_ERROR})
|
|
self.assertEqual(2, mock_info_log.call_count)
|
|
|
|
def test_promote_share_replica_driver_updates_replica_list(self):
|
|
replica = fake_replica()
|
|
active_replica = fake_replica(
|
|
id='current_active_replica',
|
|
replica_state=constants.REPLICA_STATE_ACTIVE)
|
|
replica_list = [replica, active_replica, fake_replica(id=3)]
|
|
updated_replica_list = [
|
|
{
|
|
'id': replica['id'],
|
|
'export_locations': ['TEST1', 'TEST2'],
|
|
'replica_state': constants.REPLICA_STATE_ACTIVE,
|
|
},
|
|
{
|
|
'id': 'current_active_replica',
|
|
'export_locations': 'junk_return_value',
|
|
'replica_state': constants.REPLICA_STATE_IN_SYNC,
|
|
},
|
|
{
|
|
'id': 'other_replica',
|
|
'export_locations': ['TEST1', 'TEST2'],
|
|
},
|
|
]
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(
|
|
db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=[]))
|
|
self.mock_object(db, 'share_access_get_all_for_share',
|
|
mock.Mock(return_value=[]))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replica_list))
|
|
mock_snap_instance_update = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
self.mock_object(
|
|
self.share_manager.driver, 'promote_replica',
|
|
mock.Mock(return_value=updated_replica_list))
|
|
mock_info_log = self.mock_object(manager.LOG, 'info')
|
|
mock_export_locs_update = self.mock_object(
|
|
db, 'share_export_locations_update')
|
|
mock_replica_update = self.mock_object(db, 'share_replica_update')
|
|
reset_replication_change_call = mock.call(
|
|
mock.ANY, replica['id'], {'replica_state': constants.STATUS_ACTIVE,
|
|
'status': constants.STATUS_AVAILABLE})
|
|
|
|
self.share_manager.promote_share_replica(self.context, replica)
|
|
|
|
self.assertEqual(2, mock_export_locs_update.call_count)
|
|
self.assertEqual(2, mock_replica_update.call_count)
|
|
self.assertTrue(
|
|
reset_replication_change_call in mock_replica_update.mock_calls)
|
|
self.assertTrue(mock_info_log.called)
|
|
self.assertFalse(mock_snap_instance_update.called)
|
|
|
|
@ddt.data('openstack1@watson#_pool0', 'openstack1@newton#_pool0')
|
|
def test_periodic_share_replica_update(self, host):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
replicas = [
|
|
fake_replica(host='openstack1@watson#pool4'),
|
|
fake_replica(host='openstack1@watson#pool5'),
|
|
fake_replica(host='openstack1@newton#pool5'),
|
|
fake_replica(host='openstack1@newton#pool5'),
|
|
|
|
]
|
|
self.mock_object(self.share_manager.db, 'share_replicas_get_all',
|
|
mock.Mock(return_value=replicas))
|
|
mock_update_method = self.mock_object(
|
|
self.share_manager, '_share_replica_update')
|
|
|
|
self.share_manager.host = host
|
|
|
|
self.share_manager.periodic_share_replica_update(self.context)
|
|
|
|
self.assertEqual(2, mock_update_method.call_count)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
|
|
@ddt.data(constants.REPLICA_STATE_IN_SYNC,
|
|
constants.REPLICA_STATE_OUT_OF_SYNC)
|
|
def test__share_replica_update_driver_exception(self, replica_state):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
replica = fake_replica(replica_state=replica_state)
|
|
active_replica = fake_replica(
|
|
replica_state=constants.REPLICA_STATE_ACTIVE)
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, active_replica]))
|
|
self.mock_object(self.share_manager.db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(return_value='fake_share_server'))
|
|
self.mock_object(self.share_manager.driver, 'update_replica_state',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
mock_db_update_call = self.mock_object(
|
|
self.share_manager.db, 'share_replica_update')
|
|
|
|
self.share_manager._share_replica_update(
|
|
self.context, replica, share_id=replica['share_id'])
|
|
|
|
mock_db_update_call.assert_called_once_with(
|
|
self.context, replica['id'],
|
|
{'replica_state': constants.STATUS_ERROR,
|
|
'status': constants.STATUS_ERROR}
|
|
)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
|
|
def test__share_replica_update_driver_exception_ignored(self):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
replica = fake_replica(replica_state=constants.STATUS_ERROR)
|
|
active_replica = fake_replica(replica_state=constants.STATUS_ACTIVE)
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, active_replica]))
|
|
self.mock_object(self.share_manager.db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(return_value='fake_share_server'))
|
|
self.share_manager.host = replica['host']
|
|
self.mock_object(self.share_manager.driver, 'update_replica_state',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
mock_db_update_call = self.mock_object(
|
|
self.share_manager.db, 'share_replica_update')
|
|
|
|
self.share_manager._share_replica_update(
|
|
self.context, replica, share_id=replica['share_id'])
|
|
|
|
mock_db_update_call.assert_called_once_with(
|
|
self.context, replica['id'],
|
|
{'replica_state': constants.STATUS_ERROR,
|
|
'status': constants.STATUS_ERROR}
|
|
)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
|
|
@ddt.data({'status': constants.STATUS_AVAILABLE,
|
|
'replica_state': constants.REPLICA_STATE_ACTIVE, },
|
|
{'status': constants.STATUS_DELETING,
|
|
'replica_state': constants.REPLICA_STATE_IN_SYNC, },
|
|
{'status': constants.STATUS_CREATING,
|
|
'replica_state': constants.REPLICA_STATE_OUT_OF_SYNC, },
|
|
{'status': constants.STATUS_MANAGING,
|
|
'replica_state': constants.REPLICA_STATE_OUT_OF_SYNC, },
|
|
{'status': constants.STATUS_UNMANAGING,
|
|
'replica_state': constants.REPLICA_STATE_ACTIVE, },
|
|
{'status': constants.STATUS_EXTENDING,
|
|
'replica_state': constants.REPLICA_STATE_IN_SYNC, },
|
|
{'status': constants.STATUS_SHRINKING,
|
|
'replica_state': constants.REPLICA_STATE_IN_SYNC, })
|
|
def test__share_replica_update_unqualified_replica(self, state):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
mock_warning_log = self.mock_object(manager.LOG, 'warning')
|
|
mock_driver_call = self.mock_object(
|
|
self.share_manager.driver, 'update_replica_state')
|
|
mock_db_update_call = self.mock_object(
|
|
self.share_manager.db, 'share_replica_update')
|
|
replica = fake_replica(**state)
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(return_value='fake_share_server'))
|
|
self.mock_object(db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
|
|
self.share_manager._share_replica_update(self.context, replica,
|
|
share_id=replica['share_id'])
|
|
|
|
self.assertFalse(mock_debug_log.called)
|
|
self.assertFalse(mock_warning_log.called)
|
|
self.assertFalse(mock_driver_call.called)
|
|
self.assertFalse(mock_db_update_call.called)
|
|
|
|
@ddt.data(None, constants.REPLICA_STATE_IN_SYNC,
|
|
constants.REPLICA_STATE_OUT_OF_SYNC,
|
|
constants.REPLICA_STATE_ACTIVE,
|
|
constants.STATUS_ERROR)
|
|
def test__share_replica_update(self, retval):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
mock_warning_log = self.mock_object(manager.LOG, 'warning')
|
|
replica_states = [constants.REPLICA_STATE_IN_SYNC,
|
|
constants.REPLICA_STATE_OUT_OF_SYNC]
|
|
replica = fake_replica(replica_state=random.choice(replica_states),
|
|
share_server='fake_share_server')
|
|
active_replica = fake_replica(
|
|
id='fake2', replica_state=constants.STATUS_ACTIVE)
|
|
snapshots = [fakes.fake_snapshot(
|
|
create_instance=True, aggregate_status=constants.STATUS_AVAILABLE)]
|
|
snapshot_instances = [
|
|
fakes.fake_snapshot_instance(share_instance_id=replica['id']),
|
|
fakes.fake_snapshot_instance(share_instance_id='fake2'),
|
|
]
|
|
del replica['availability_zone']
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica, active_replica]))
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(return_value='fake_share_server'))
|
|
mock_db_update_calls = []
|
|
self.mock_object(self.share_manager.db, 'share_replica_get',
|
|
mock.Mock(return_value=replica))
|
|
mock_driver_call = self.mock_object(
|
|
self.share_manager.driver, 'update_replica_state',
|
|
mock.Mock(return_value=retval))
|
|
mock_db_update_call = self.mock_object(
|
|
self.share_manager.db, 'share_replica_update')
|
|
self.mock_object(db, 'share_snapshot_get_all_for_share',
|
|
mock.Mock(return_value=snapshots))
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
|
|
self.share_manager._share_replica_update(
|
|
self.context, replica, share_id=replica['share_id'])
|
|
|
|
if retval == constants.REPLICA_STATE_ACTIVE:
|
|
self.assertEqual(1, mock_warning_log.call_count)
|
|
elif retval:
|
|
self.assertEqual(0, mock_warning_log.call_count)
|
|
self.assertTrue(mock_driver_call.called)
|
|
snapshot_list_arg = mock_driver_call.call_args[0][4]
|
|
self.assertTrue('active_replica_snapshot' in snapshot_list_arg[0])
|
|
self.assertTrue('share_replica_snapshot' in snapshot_list_arg[0])
|
|
mock_db_update_call.assert_has_calls(mock_db_update_calls)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
|
|
def test_update_share_replica_replica_not_found(self):
|
|
replica = fake_replica()
|
|
self.mock_object(
|
|
self.share_manager.db, 'share_replica_get', mock.Mock(
|
|
side_effect=exception.ShareReplicaNotFound(replica_id='fake')))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
driver_call = self.mock_object(
|
|
self.share_manager, '_share_replica_update')
|
|
|
|
self.assertRaises(
|
|
exception.ShareReplicaNotFound,
|
|
self.share_manager.update_share_replica,
|
|
self.context, replica, share_id=replica['share_id'])
|
|
|
|
self.assertFalse(driver_call.called)
|
|
|
|
def test_update_share_replica_replica(self):
|
|
replica_update_call = self.mock_object(
|
|
self.share_manager, '_share_replica_update')
|
|
self.mock_object(self.share_manager.db, 'share_replica_get')
|
|
|
|
retval = self.share_manager.update_share_replica(
|
|
self.context, 'fake_replica_id', share_id='fake_share_id')
|
|
|
|
self.assertIsNone(retval)
|
|
self.assertTrue(replica_update_call.called)
|
|
|
|
def _get_snapshot_instance_dict(self, snapshot_instance, share):
|
|
expected_snapshot_instance_dict = {
|
|
'status': constants.STATUS_CREATING,
|
|
'share_id': share['id'],
|
|
'share_name': snapshot_instance['share_name'],
|
|
'deleted': snapshot_instance['deleted'],
|
|
'share': share,
|
|
'updated_at': snapshot_instance['updated_at'],
|
|
'snapshot_id': snapshot_instance['snapshot_id'],
|
|
'id': snapshot_instance['id'],
|
|
'name': snapshot_instance['name'],
|
|
'created_at': snapshot_instance['created_at'],
|
|
'share_instance_id': snapshot_instance['share_instance_id'],
|
|
'progress': snapshot_instance['progress'],
|
|
'deleted_at': snapshot_instance['deleted_at'],
|
|
'provider_location': snapshot_instance['provider_location'],
|
|
}
|
|
return expected_snapshot_instance_dict
|
|
|
|
def test_create_snapshot_driver_exception(self):
|
|
|
|
def _raise_not_found(self, *args, **kwargs):
|
|
raise exception.NotFound()
|
|
|
|
share_id = 'FAKE_SHARE_ID'
|
|
share = fakes.fake_share(id=share_id, instance={'id': 'fake_id'})
|
|
snapshot_instance = fakes.fake_snapshot_instance(
|
|
share_id=share_id, share=share, name='fake_snapshot')
|
|
snapshot = fakes.fake_snapshot(
|
|
share_id=share_id, share=share, instance=snapshot_instance,
|
|
project_id=self.context.project_id)
|
|
snapshot_id = snapshot['id']
|
|
self.mock_object(self.share_manager.driver, "create_snapshot",
|
|
mock.Mock(side_effect=_raise_not_found))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
db_update = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_update')
|
|
expected_snapshot_instance_dict = self._get_snapshot_instance_dict(
|
|
snapshot_instance, share)
|
|
|
|
self.assertRaises(exception.NotFound,
|
|
self.share_manager.create_snapshot,
|
|
self.context, share_id, snapshot_id)
|
|
db_update.assert_called_once_with(self.context,
|
|
snapshot_instance['id'],
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
self.share_manager.driver.create_snapshot.assert_called_once_with(
|
|
self.context, expected_snapshot_instance_dict, share_server=None)
|
|
|
|
def test_create_snapshot(self):
|
|
share_id = 'FAKE_SHARE_ID'
|
|
share = fakes.fake_share(id=share_id, instance={'id': 'fake_id'})
|
|
snapshot_instance = fakes.fake_snapshot_instance(
|
|
share_id=share_id, share=share, name='fake_snapshot')
|
|
snapshot = fakes.fake_snapshot(
|
|
share_id=share_id, share=share, instance=snapshot_instance)
|
|
snapshot_id = snapshot['id']
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
expected_update_calls = [
|
|
mock.call(self.context, snapshot_instance['id'],
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'progress': '100%'})
|
|
]
|
|
|
|
expected_snapshot_instance_dict = self._get_snapshot_instance_dict(
|
|
snapshot_instance, share)
|
|
self.mock_object(self.share_manager.driver, 'create_snapshot',
|
|
mock.Mock(return_value=None))
|
|
db_update = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_update')
|
|
|
|
return_value = self.share_manager.create_snapshot(
|
|
self.context, share_id, snapshot_id)
|
|
|
|
self.assertIsNone(return_value)
|
|
self.share_manager.driver.create_snapshot.assert_called_once_with(
|
|
self.context, expected_snapshot_instance_dict, share_server=None)
|
|
db_update.assert_has_calls(expected_update_calls, any_order=True)
|
|
|
|
@ddt.data(exception.ShareSnapshotIsBusy(snapshot_name='fake_name'),
|
|
exception.NotFound())
|
|
def test_delete_snapshot_driver_exception(self, exc):
|
|
|
|
share_id = 'FAKE_SHARE_ID'
|
|
share = fakes.fake_share(id=share_id, instance={'id': 'fake_id'})
|
|
snapshot_instance = fakes.fake_snapshot_instance(
|
|
share_id=share_id, share=share, name='fake_snapshot')
|
|
snapshot = fakes.fake_snapshot(
|
|
share_id=share_id, share=share, instance=snapshot_instance,
|
|
project_id=self.context.project_id)
|
|
snapshot_id = snapshot['id']
|
|
self.mock_object(self.share_manager.driver, "delete_snapshot",
|
|
mock.Mock(side_effect=exc))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
self.mock_object(
|
|
self.share_manager.db, 'share_get', mock.Mock(return_value=share))
|
|
db_update = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_update')
|
|
db_destroy_call = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_delete')
|
|
expected_snapshot_instance_dict = self._get_snapshot_instance_dict(
|
|
snapshot_instance, share)
|
|
mock_exception_log = self.mock_object(manager.LOG, 'exception')
|
|
self.assertRaises(type(exc), self.share_manager.delete_snapshot,
|
|
self.context, snapshot_id)
|
|
db_update.assert_called_once_with(
|
|
mock.ANY, snapshot_instance['id'],
|
|
{'status': constants.STATUS_ERROR_DELETING})
|
|
self.share_manager.driver.delete_snapshot.assert_called_once_with(
|
|
mock.ANY, expected_snapshot_instance_dict,
|
|
share_server=None)
|
|
self.assertFalse(db_destroy_call.called)
|
|
self.assertFalse(mock_exception_log.called)
|
|
|
|
@ddt.data(True, False)
|
|
def test_delete_snapshot_with_quota_error(self, quota_error):
|
|
|
|
share_id = 'FAKE_SHARE_ID'
|
|
share = fakes.fake_share(id=share_id, instance={'id': 'fake_id'})
|
|
snapshot_instance = fakes.fake_snapshot_instance(
|
|
share_id=share_id, share=share, name='fake_snapshot')
|
|
snapshot = fakes.fake_snapshot(
|
|
share_id=share_id, share=share, instance=snapshot_instance,
|
|
project_id=self.context.project_id, size=1)
|
|
snapshot_id = snapshot['id']
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(self.share_manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
mock_exception_log = self.mock_object(manager.LOG, 'exception')
|
|
expected_exc_count = 1 if quota_error else 0
|
|
|
|
expected_snapshot_instance_dict = self._get_snapshot_instance_dict(
|
|
snapshot_instance, share)
|
|
|
|
self.mock_object(self.share_manager.driver, 'delete_snapshot')
|
|
db_update_call = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_update')
|
|
snapshot_destroy_call = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_delete')
|
|
side_effect = exception.QuotaError(code=500) if quota_error else None
|
|
self.mock_object(quota.QUOTAS, 'reserve',
|
|
mock.Mock(side_effect=side_effect))
|
|
quota_commit_call = self.mock_object(quota.QUOTAS, 'commit')
|
|
|
|
retval = self.share_manager.delete_snapshot(
|
|
self.context, snapshot_id)
|
|
|
|
self.assertIsNone(retval)
|
|
self.share_manager.driver.delete_snapshot.assert_called_once_with(
|
|
mock.ANY, expected_snapshot_instance_dict, share_server=None)
|
|
self.assertFalse(db_update_call.called)
|
|
self.assertTrue(snapshot_destroy_call.called)
|
|
self.assertTrue(manager.QUOTAS.reserve.called)
|
|
quota.QUOTAS.reserve.assert_called_once_with(
|
|
mock.ANY, project_id=self.context.project_id, snapshots=-1,
|
|
snapshot_gigabytes=-snapshot['size'], user_id=snapshot['user_id'])
|
|
self.assertEqual(not quota_error, quota_commit_call.called)
|
|
self.assertEqual(quota_error, mock_exception_log.called)
|
|
self.assertEqual(expected_exc_count, mock_exception_log.call_count)
|
|
|
|
@ddt.data(exception.ShareSnapshotIsBusy, exception.ManilaException)
|
|
def test_delete_snapshot_ignore_exceptions_with_the_force(self, exc):
|
|
|
|
def _raise_quota_error():
|
|
raise exception.QuotaError(code='500')
|
|
|
|
share_id = 'FAKE_SHARE_ID'
|
|
share = fakes.fake_share(id=share_id, instance={'id': 'fake_id'})
|
|
snapshot_instance = fakes.fake_snapshot_instance(
|
|
share_id=share_id, share=share, name='fake_snapshot')
|
|
snapshot = fakes.fake_snapshot(
|
|
share_id=share_id, share=share, instance=snapshot_instance,
|
|
project_id=self.context.project_id, size=1)
|
|
snapshot_id = snapshot['id']
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(self.share_manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
mock_exception_log = self.mock_object(manager.LOG, 'exception')
|
|
self.mock_object(self.share_manager.driver, 'delete_snapshot',
|
|
mock.Mock(side_effect=exc))
|
|
db_update_call = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_update')
|
|
snapshot_destroy_call = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_delete')
|
|
self.mock_object(quota.QUOTAS, 'reserve',
|
|
mock.Mock(side_effect=_raise_quota_error))
|
|
quota_commit_call = self.mock_object(quota.QUOTAS, 'commit')
|
|
|
|
retval = self.share_manager.delete_snapshot(
|
|
self.context, snapshot_id, force=True)
|
|
|
|
self.assertIsNone(retval)
|
|
self.assertEqual(2, mock_exception_log.call_count)
|
|
snapshot_destroy_call.assert_called_once_with(
|
|
mock.ANY, snapshot_instance['id'])
|
|
self.assertFalse(quota_commit_call.called)
|
|
self.assertFalse(db_update_call.called)
|
|
|
|
def test_create_share_instance_with_share_network_dhss_false(self):
|
|
manager.CONF.set_default('driver_handles_share_servers', False)
|
|
self.mock_object(
|
|
self.share_manager.driver.configuration, 'safe_get',
|
|
mock.Mock(return_value=False))
|
|
share_network_id = 'fake_sn'
|
|
share_instance = db_utils.create_share(
|
|
share_network_id=share_network_id).instance
|
|
self.mock_object(
|
|
self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(return_value=share_instance))
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
|
|
self.assertRaisesRegex(
|
|
exception.ManilaException,
|
|
'.*%s.*' % share_instance['id'],
|
|
self.share_manager.create_share_instance, self.context,
|
|
share_instance['id'])
|
|
self.share_manager.db.share_instance_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
share_instance['id'],
|
|
with_share_data=True
|
|
)
|
|
self.share_manager.db.share_instance_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), share_instance['id'],
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
def test_create_share_instance_with_share_network_server_not_exists(self):
|
|
"""Test share can be created without share server."""
|
|
|
|
share_net = db_utils.create_share_network()
|
|
share = db_utils.create_share(share_network_id=share_net['id'])
|
|
|
|
share_id = share['id']
|
|
|
|
def fake_setup_server(context, share_network, *args, **kwargs):
|
|
return db_utils.create_share_server(
|
|
share_network_id=share_network['id'],
|
|
host='fake_host')
|
|
|
|
self.mock_object(manager.LOG, 'info')
|
|
self.share_manager.driver.create_share = mock.Mock(
|
|
return_value='fake_location')
|
|
self.share_manager._setup_server = fake_setup_server
|
|
self.share_manager.create_share_instance(self.context,
|
|
share.instance['id'])
|
|
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
|
share_id).id)
|
|
manager.LOG.info.assert_called_with(mock.ANY, share.instance['id'])
|
|
|
|
def test_create_share_instance_with_share_network_server_fail(self):
|
|
fake_share = db_utils.create_share(share_network_id='fake_sn_id',
|
|
size=1)
|
|
fake_server = {
|
|
'id': 'fake_srv_id',
|
|
'status': constants.STATUS_CREATING,
|
|
}
|
|
self.mock_object(db, 'share_server_create',
|
|
mock.Mock(return_value=fake_server))
|
|
self.mock_object(db, 'share_instance_update',
|
|
mock.Mock(return_value=fake_share.instance))
|
|
self.mock_object(db, 'share_instance_get',
|
|
mock.Mock(return_value=fake_share.instance))
|
|
self.mock_object(manager.LOG, 'error')
|
|
|
|
def raise_share_server_not_found(*args, **kwargs):
|
|
raise exception.ShareServerNotFound(
|
|
share_server_id=fake_server['id'])
|
|
|
|
def raise_manila_exception(*args, **kwargs):
|
|
raise exception.ManilaException()
|
|
|
|
self.mock_object(db,
|
|
'share_server_get_all_by_host_and_share_net_valid',
|
|
mock.Mock(side_effect=raise_share_server_not_found))
|
|
self.mock_object(self.share_manager, '_setup_server',
|
|
mock.Mock(side_effect=raise_manila_exception))
|
|
|
|
self.assertRaises(
|
|
exception.ManilaException,
|
|
self.share_manager.create_share_instance,
|
|
self.context,
|
|
fake_share.instance['id'],
|
|
)
|
|
db.share_server_get_all_by_host_and_share_net_valid.\
|
|
assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
self.share_manager.host,
|
|
fake_share['share_network_id'],
|
|
)
|
|
db.share_server_create.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), mock.ANY)
|
|
db.share_instance_update.assert_has_calls([
|
|
mock.call(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
fake_share.instance['id'],
|
|
{'status': constants.STATUS_ERROR},
|
|
)
|
|
])
|
|
self.share_manager._setup_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), fake_server)
|
|
manager.LOG.error.assert_called_with(mock.ANY,
|
|
fake_share.instance['id'])
|
|
|
|
def test_create_share_instance_with_share_network_not_found(self):
|
|
"""Test creation fails if share network not found."""
|
|
|
|
self.mock_object(manager.LOG, 'error')
|
|
|
|
share = db_utils.create_share(share_network_id='fake-net-id')
|
|
share_id = share['id']
|
|
self.assertRaises(
|
|
exception.ShareNetworkNotFound,
|
|
self.share_manager.create_share_instance,
|
|
self.context,
|
|
share.instance['id']
|
|
)
|
|
manager.LOG.error.assert_called_with(mock.ANY, share.instance['id'])
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(constants.STATUS_ERROR, shr['status'])
|
|
|
|
def test_create_share_instance_with_share_network_server_exists(self):
|
|
"""Test share can be created with existing share server."""
|
|
share_net = db_utils.create_share_network()
|
|
share = db_utils.create_share(share_network_id=share_net['id'])
|
|
share_srv = db_utils.create_share_server(
|
|
share_network_id=share_net['id'], host=self.share_manager.host)
|
|
|
|
share_id = share['id']
|
|
|
|
self.mock_object(manager.LOG, 'info')
|
|
driver_mock = mock.Mock()
|
|
driver_mock.create_share.return_value = "fake_location"
|
|
driver_mock.choose_share_server_compatible_with_share.return_value = (
|
|
share_srv
|
|
)
|
|
self.share_manager.driver = driver_mock
|
|
self.share_manager.create_share_instance(self.context,
|
|
share.instance['id'])
|
|
self.assertFalse(self.share_manager.driver.setup_network.called)
|
|
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
|
share_id).id)
|
|
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(shr['status'], constants.STATUS_AVAILABLE)
|
|
self.assertEqual(shr['share_server_id'], share_srv['id'])
|
|
self.assertTrue(len(shr['export_location']) > 0)
|
|
self.assertEqual(1, len(shr['export_locations']))
|
|
manager.LOG.info.assert_called_with(mock.ANY, share.instance['id'])
|
|
|
|
@ddt.data('export_location', 'export_locations')
|
|
def test_create_share_instance_with_error_in_driver(self, details_key):
|
|
"""Test db updates if share creation fails in driver."""
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
some_data = 'fake_location'
|
|
self.share_manager.driver = mock.Mock()
|
|
e = exception.ManilaException(detail_data={details_key: some_data})
|
|
self.share_manager.driver.create_share.side_effect = e
|
|
self.assertRaises(
|
|
exception.ManilaException,
|
|
self.share_manager.create_share_instance,
|
|
self.context,
|
|
share.instance['id']
|
|
)
|
|
self.assertTrue(self.share_manager.driver.create_share.called)
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(some_data, shr['export_location'])
|
|
|
|
def test_create_share_instance_with_server_created(self):
|
|
"""Test share can be created and share server is created."""
|
|
share_net = db_utils.create_share_network()
|
|
share = db_utils.create_share(share_network_id=share_net['id'])
|
|
db_utils.create_share_server(
|
|
share_network_id=share_net['id'], host=self.share_manager.host,
|
|
status=constants.STATUS_ERROR)
|
|
share_id = share['id']
|
|
fake_server = {
|
|
'id': 'fake_srv_id',
|
|
'status': constants.STATUS_CREATING,
|
|
}
|
|
self.mock_object(db, 'share_server_create',
|
|
mock.Mock(return_value=fake_server))
|
|
self.mock_object(self.share_manager, '_setup_server',
|
|
mock.Mock(return_value=fake_server))
|
|
|
|
self.share_manager.create_share_instance(self.context,
|
|
share.instance['id'])
|
|
|
|
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
|
share_id).id)
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(constants.STATUS_AVAILABLE, shr['status'])
|
|
self.assertEqual('fake_srv_id', shr['share_server_id'])
|
|
db.share_server_create.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), mock.ANY)
|
|
self.share_manager._setup_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), fake_server)
|
|
|
|
def test_create_share_instance_update_replica_state(self):
|
|
share_net = db_utils.create_share_network()
|
|
share = db_utils.create_share(share_network_id=share_net['id'],
|
|
replication_type='dr')
|
|
db_utils.create_share_server(
|
|
share_network_id=share_net['id'], host=self.share_manager.host,
|
|
status=constants.STATUS_ERROR)
|
|
share_id = share['id']
|
|
fake_server = {
|
|
'id': 'fake_srv_id',
|
|
'status': constants.STATUS_CREATING,
|
|
}
|
|
self.mock_object(db, 'share_server_create',
|
|
mock.Mock(return_value=fake_server))
|
|
self.mock_object(self.share_manager, '_setup_server',
|
|
mock.Mock(return_value=fake_server))
|
|
|
|
self.share_manager.create_share_instance(self.context,
|
|
share.instance['id'])
|
|
|
|
self.assertEqual(share_id, db.share_get(context.get_admin_context(),
|
|
share_id).id)
|
|
shr = db.share_get(self.context, share_id)
|
|
shr_instances = db.share_instances_get_all_by_share(
|
|
self.context, shr['id'])
|
|
self.assertEqual(1, len(shr_instances))
|
|
self.assertEqual(constants.STATUS_AVAILABLE, shr['status'])
|
|
self.assertEqual(
|
|
constants.REPLICA_STATE_ACTIVE, shr_instances[0]['replica_state'])
|
|
self.assertEqual('fake_srv_id', shr['share_server_id'])
|
|
db.share_server_create.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), mock.ANY)
|
|
self.share_manager._setup_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), fake_server)
|
|
|
|
@ddt.data(True, False)
|
|
def test_create_delete_share_instance_error(self, exception_update_access):
|
|
"""Test share can be created and deleted with error."""
|
|
|
|
def _raise_exception(self, *args, **kwargs):
|
|
raise exception.ManilaException('fake')
|
|
|
|
self.mock_object(self.share_manager.driver, "create_share",
|
|
mock.Mock(side_effect=_raise_exception))
|
|
self.mock_object(self.share_manager.driver, "delete_share",
|
|
mock.Mock(side_effect=_raise_exception))
|
|
if exception_update_access:
|
|
self.mock_object(
|
|
self.share_manager.access_helper, "update_access_rules",
|
|
mock.Mock(side_effect=_raise_exception))
|
|
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.create_share_instance,
|
|
self.context,
|
|
share.instance['id'])
|
|
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(constants.STATUS_ERROR, shr['status'])
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.delete_share_instance,
|
|
self.context,
|
|
share.instance['id'])
|
|
|
|
shr = db.share_get(self.context, share_id)
|
|
self.assertEqual(constants.STATUS_ERROR_DELETING, shr['status'])
|
|
self.share_manager.driver.create_share.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
utils.IsAMatcher(models.ShareInstance),
|
|
share_server=None)
|
|
if not exception_update_access:
|
|
self.share_manager.driver.delete_share.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
utils.IsAMatcher(models.ShareInstance),
|
|
share_server=None)
|
|
|
|
def test_create_share_instance_update_availability_zone(self):
|
|
share = db_utils.create_share(availability_zone=None)
|
|
share_id = share['id']
|
|
|
|
self.share_manager.create_share_instance(
|
|
self.context, share.instance['id'])
|
|
|
|
actual_share = db.share_get(context.get_admin_context(), share_id)
|
|
self.assertIsNotNone(actual_share.availability_zone)
|
|
self.assertEqual(manager.CONF.storage_availability_zone,
|
|
actual_share.availability_zone)
|
|
|
|
def test_provide_share_server_for_share_incompatible_servers(self):
|
|
fake_exception = exception.ManilaException("fake")
|
|
fake_share_server = {'id': 'fake'}
|
|
share = db_utils.create_share()
|
|
|
|
self.mock_object(db,
|
|
'share_server_get_all_by_host_and_share_net_valid',
|
|
mock.Mock(return_value=[fake_share_server]))
|
|
self.mock_object(
|
|
self.share_manager.driver,
|
|
"choose_share_server_compatible_with_share",
|
|
mock.Mock(side_effect=fake_exception)
|
|
)
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager._provide_share_server_for_share,
|
|
self.context, "fake_id", share.instance)
|
|
driver_mock = self.share_manager.driver
|
|
driver_method_mock = (
|
|
driver_mock.choose_share_server_compatible_with_share
|
|
)
|
|
driver_method_mock.assert_called_once_with(
|
|
self.context, [fake_share_server], share.instance, snapshot=None,
|
|
consistency_group=None)
|
|
|
|
def test_provide_share_server_for_share_invalid_arguments(self):
|
|
self.assertRaises(ValueError,
|
|
self.share_manager._provide_share_server_for_share,
|
|
self.context, None, None)
|
|
|
|
def test_provide_share_server_for_share_parent_ss_not_found(self):
|
|
fake_parent_id = "fake_server_id"
|
|
fake_exception = exception.ShareServerNotFound("fake")
|
|
share = db_utils.create_share()
|
|
fake_snapshot = {
|
|
'share': {
|
|
'instance': {
|
|
'share_server_id': fake_parent_id
|
|
}
|
|
}
|
|
}
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(side_effect=fake_exception))
|
|
|
|
self.assertRaises(exception.ShareServerNotFound,
|
|
self.share_manager._provide_share_server_for_share,
|
|
self.context, "fake_id", share.instance,
|
|
snapshot=fake_snapshot)
|
|
|
|
db.share_server_get.assert_called_once_with(
|
|
self.context, fake_parent_id)
|
|
|
|
def test_provide_share_server_for_share_parent_ss_invalid(self):
|
|
fake_parent_id = "fake_server_id"
|
|
share = db_utils.create_share()
|
|
fake_snapshot = {
|
|
'share': {
|
|
'instance': {
|
|
'share_server_id': fake_parent_id
|
|
}
|
|
}
|
|
}
|
|
fake_parent_share_server = {'status': 'fake'}
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(return_value=fake_parent_share_server))
|
|
|
|
self.assertRaises(exception.InvalidShareServer,
|
|
self.share_manager._provide_share_server_for_share,
|
|
self.context, "fake_id", share.instance,
|
|
snapshot=fake_snapshot)
|
|
|
|
db.share_server_get.assert_called_once_with(
|
|
self.context, fake_parent_id)
|
|
|
|
def test_provide_share_server_for_cg_incompatible_servers(self):
|
|
fake_exception = exception.ManilaException("fake")
|
|
fake_share_server = {'id': 'fake'}
|
|
cg = db_utils.create_consistency_group()
|
|
|
|
self.mock_object(db,
|
|
'share_server_get_all_by_host_and_share_net_valid',
|
|
mock.Mock(return_value=[fake_share_server]))
|
|
self.mock_object(
|
|
self.share_manager.driver,
|
|
"choose_share_server_compatible_with_cg",
|
|
mock.Mock(side_effect=fake_exception)
|
|
)
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager._provide_share_server_for_cg,
|
|
self.context, "fake_id", cg)
|
|
driver_mock = self.share_manager.driver
|
|
driver_method_mock = (
|
|
driver_mock.choose_share_server_compatible_with_cg
|
|
)
|
|
driver_method_mock.assert_called_once_with(
|
|
self.context, [fake_share_server], cg, cgsnapshot=None)
|
|
|
|
def test_provide_share_server_for_cg_invalid_arguments(self):
|
|
self.assertRaises(exception.InvalidInput,
|
|
self.share_manager._provide_share_server_for_cg,
|
|
self.context, None, None)
|
|
|
|
def test_manage_share_invalid_driver(self):
|
|
self.mock_object(self.share_manager, 'driver', mock.Mock())
|
|
self.share_manager.driver.driver_handles_share_servers = True
|
|
self.mock_object(share_types,
|
|
'get_share_type_extra_specs',
|
|
mock.Mock(return_value='False'))
|
|
self.mock_object(self.share_manager.db, 'share_update', mock.Mock())
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
|
|
self.assertRaises(
|
|
exception.InvalidDriverMode,
|
|
self.share_manager.manage_share, self.context, share_id, {})
|
|
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), share_id,
|
|
{'status': constants.STATUS_MANAGE_ERROR, 'size': 1})
|
|
|
|
def test_manage_share_invalid_share_type(self):
|
|
self.mock_object(self.share_manager, 'driver', mock.Mock())
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
self.mock_object(share_types,
|
|
'get_share_type_extra_specs',
|
|
mock.Mock(return_value='True'))
|
|
self.mock_object(self.share_manager.db, 'share_update', mock.Mock())
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
|
|
self.assertRaises(
|
|
exception.ManageExistingShareTypeMismatch,
|
|
self.share_manager.manage_share, self.context, share_id, {})
|
|
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), share_id,
|
|
{'status': constants.STATUS_MANAGE_ERROR, 'size': 1})
|
|
|
|
def test_manage_share_driver_exception(self):
|
|
CustomException = type('CustomException', (Exception,), dict())
|
|
self.mock_object(self.share_manager, 'driver', mock.Mock())
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
self.mock_object(self.share_manager.driver,
|
|
'manage_existing',
|
|
mock.Mock(side_effect=CustomException))
|
|
self.mock_object(share_types,
|
|
'get_share_type_extra_specs',
|
|
mock.Mock(return_value='False'))
|
|
self.mock_object(self.share_manager.db, 'share_update', mock.Mock())
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
driver_options = {'fake': 'fake'}
|
|
|
|
self.assertRaises(
|
|
CustomException,
|
|
self.share_manager.manage_share,
|
|
self.context, share_id, driver_options)
|
|
|
|
self.share_manager.driver.manage_existing.\
|
|
assert_called_once_with(mock.ANY, driver_options)
|
|
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), share_id,
|
|
{'status': constants.STATUS_MANAGE_ERROR, 'size': 1})
|
|
|
|
def test_manage_share_invalid_size(self):
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
self.mock_object(share_types,
|
|
'get_share_type_extra_specs',
|
|
mock.Mock(return_value='False'))
|
|
self.mock_object(self.share_manager.driver,
|
|
"manage_existing",
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager.db, 'share_update', mock.Mock())
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
driver_options = {'fake': 'fake'}
|
|
|
|
self.assertRaises(
|
|
exception.InvalidShare,
|
|
self.share_manager.manage_share,
|
|
self.context, share_id, driver_options)
|
|
|
|
self.share_manager.driver.manage_existing.\
|
|
assert_called_once_with(mock.ANY, driver_options)
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), share_id,
|
|
{'status': constants.STATUS_MANAGE_ERROR, 'size': 1})
|
|
|
|
def test_manage_share_quota_error(self):
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
self.mock_object(share_types,
|
|
'get_share_type_extra_specs',
|
|
mock.Mock(return_value='False'))
|
|
self.mock_object(self.share_manager.driver,
|
|
"manage_existing",
|
|
mock.Mock(return_value={'size': 3}))
|
|
self.mock_object(quota.QUOTAS, 'reserve',
|
|
mock.Mock(side_effect=exception.QuotaError))
|
|
self.mock_object(self.share_manager.db, 'share_update', mock.Mock())
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
driver_options = {'fake': 'fake'}
|
|
|
|
self.assertRaises(
|
|
exception.QuotaError,
|
|
self.share_manager.manage_share,
|
|
self.context, share_id, driver_options)
|
|
|
|
self.share_manager.driver.manage_existing.\
|
|
assert_called_once_with(mock.ANY, driver_options)
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
mock.ANY, share_id,
|
|
{'status': constants.STATUS_MANAGE_ERROR, 'size': 1})
|
|
|
|
@ddt.data(
|
|
{'size': 1, 'replication_type': None},
|
|
{'size': 2, 'name': 'fake', 'replication_type': 'dr'},
|
|
{'size': 3, 'export_locations': ['foo', 'bar', 'quuz'],
|
|
'replication_type': 'writable'},
|
|
)
|
|
def test_manage_share_valid_share(self, driver_data):
|
|
replication_type = driver_data.pop('replication_type')
|
|
export_locations = driver_data.get('export_locations')
|
|
self.mock_object(self.share_manager.db, 'share_update', mock.Mock())
|
|
self.mock_object(self.share_manager, 'driver', mock.Mock())
|
|
self.mock_object(quota.QUOTAS, 'reserve', mock.Mock())
|
|
self.mock_object(
|
|
self.share_manager.db,
|
|
'share_export_locations_update',
|
|
mock.Mock(side_effect=(
|
|
self.share_manager.db.share_export_locations_update)))
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
self.mock_object(share_types,
|
|
'get_share_type_extra_specs',
|
|
mock.Mock(return_value='False'))
|
|
self.mock_object(self.share_manager.driver,
|
|
"manage_existing",
|
|
mock.Mock(return_value=driver_data))
|
|
share = db_utils.create_share(replication_type=replication_type)
|
|
share_id = share['id']
|
|
driver_options = {'fake': 'fake'}
|
|
|
|
self.share_manager.manage_share(self.context, share_id, driver_options)
|
|
|
|
self.share_manager.driver.manage_existing.\
|
|
assert_called_once_with(mock.ANY, driver_options)
|
|
if export_locations:
|
|
self.share_manager.db.share_export_locations_update.\
|
|
assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
share.instance['id'], export_locations, delete=True)
|
|
else:
|
|
self.assertFalse(
|
|
self.share_manager.db.share_export_locations_update.called)
|
|
valid_share_data = {
|
|
'status': constants.STATUS_AVAILABLE, 'launched_at': mock.ANY}
|
|
if replication_type:
|
|
valid_share_data['replica_state'] = constants.REPLICA_STATE_ACTIVE
|
|
valid_share_data.update(driver_data)
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
share_id, valid_share_data)
|
|
|
|
def test_update_quota_usages_new(self):
|
|
self.mock_object(self.share_manager.db, 'quota_usage_get',
|
|
mock.Mock(return_value={'in_use': 1}))
|
|
self.mock_object(self.share_manager.db, 'quota_usage_update')
|
|
project_id = 'fake_project_id'
|
|
resource_name = 'fake'
|
|
usage = 1
|
|
|
|
self.share_manager._update_quota_usages(
|
|
self.context, project_id, {resource_name: usage})
|
|
|
|
self.share_manager.db.quota_usage_get.assert_called_once_with(
|
|
mock.ANY, project_id, resource_name, mock.ANY)
|
|
self.share_manager.db.quota_usage_update.assert_called_once_with(
|
|
mock.ANY, project_id, mock.ANY, resource_name, in_use=2)
|
|
|
|
def test_update_quota_usages_update(self):
|
|
project_id = 'fake_project_id'
|
|
resource_name = 'fake'
|
|
usage = 1
|
|
side_effect = exception.QuotaUsageNotFound(project_id=project_id)
|
|
self.mock_object(
|
|
self.share_manager.db,
|
|
'quota_usage_get',
|
|
mock.Mock(side_effect=side_effect))
|
|
self.mock_object(self.share_manager.db, 'quota_usage_create')
|
|
|
|
self.share_manager._update_quota_usages(
|
|
self.context, project_id, {resource_name: usage})
|
|
|
|
self.share_manager.db.quota_usage_get.assert_called_once_with(
|
|
mock.ANY, project_id, resource_name, mock.ANY)
|
|
self.share_manager.db.quota_usage_create.assert_called_once_with(
|
|
mock.ANY, project_id, mock.ANY, resource_name, usage)
|
|
|
|
def _setup_unmanage_mocks(self, mock_driver=True, mock_unmanage=None):
|
|
if mock_driver:
|
|
self.mock_object(self.share_manager, 'driver')
|
|
|
|
if mock_unmanage:
|
|
self.mock_object(self.share_manager.driver, "unmanage",
|
|
mock_unmanage)
|
|
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
self.mock_object(self.share_manager.db, 'share_instance_delete')
|
|
|
|
@ddt.data(True, False)
|
|
def test_unmanage_share_invalid_driver(self, driver_handles_share_servers):
|
|
self._setup_unmanage_mocks()
|
|
self.share_manager.driver.driver_handles_share_servers = (
|
|
driver_handles_share_servers
|
|
)
|
|
share_net = db_utils.create_share_network()
|
|
share_srv = db_utils.create_share_server(
|
|
share_network_id=share_net['id'], host=self.share_manager.host)
|
|
share = db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id=share_srv['id'])
|
|
|
|
self.share_manager.unmanage_share(self.context, share['id'])
|
|
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
mock.ANY, share['id'], {'status': constants.STATUS_UNMANAGE_ERROR})
|
|
|
|
def test_unmanage_share_invalid_share(self):
|
|
unmanage = mock.Mock(side_effect=exception.InvalidShare(reason="fake"))
|
|
self._setup_unmanage_mocks(mock_driver=False, mock_unmanage=unmanage)
|
|
share = db_utils.create_share()
|
|
|
|
self.share_manager.unmanage_share(self.context, share['id'])
|
|
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
mock.ANY, share['id'], {'status': constants.STATUS_UNMANAGE_ERROR})
|
|
|
|
def test_unmanage_share_valid_share(self):
|
|
manager.CONF.set_default('driver_handles_share_servers', False)
|
|
self._setup_unmanage_mocks(mock_driver=False,
|
|
mock_unmanage=mock.Mock())
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
share_instance_id = share.instance['id']
|
|
|
|
self.share_manager.unmanage_share(self.context, share_id)
|
|
|
|
self.share_manager.driver.unmanage.\
|
|
assert_called_once_with(mock.ANY)
|
|
self.share_manager.db.share_instance_delete.assert_called_once_with(
|
|
mock.ANY, share_instance_id)
|
|
|
|
def test_unmanage_share_valid_share_with_quota_error(self):
|
|
manager.CONF.set_default('driver_handles_share_servers', False)
|
|
self._setup_unmanage_mocks(mock_driver=False,
|
|
mock_unmanage=mock.Mock())
|
|
self.mock_object(quota.QUOTAS, 'reserve',
|
|
mock.Mock(side_effect=Exception()))
|
|
share = db_utils.create_share()
|
|
share_instance_id = share.instance['id']
|
|
|
|
self.share_manager.unmanage_share(self.context, share['id'])
|
|
|
|
self.share_manager.driver.unmanage.\
|
|
assert_called_once_with(mock.ANY)
|
|
self.share_manager.db.share_instance_delete.assert_called_once_with(
|
|
mock.ANY, share_instance_id)
|
|
|
|
def test_unmanage_share_remove_access_rules_error(self):
|
|
manager.CONF.set_default('driver_handles_share_servers', False)
|
|
manager.CONF.unmanage_remove_access_rules = True
|
|
self._setup_unmanage_mocks(mock_driver=False,
|
|
mock_unmanage=mock.Mock())
|
|
self.mock_object(
|
|
self.share_manager.access_helper,
|
|
'update_access_rules',
|
|
mock.Mock(side_effect=Exception())
|
|
)
|
|
self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(return_value=[]))
|
|
share = db_utils.create_share()
|
|
|
|
self.share_manager.unmanage_share(self.context, share['id'])
|
|
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
mock.ANY, share['id'], {'status': constants.STATUS_UNMANAGE_ERROR})
|
|
|
|
def test_unmanage_share_valid_share_remove_access_rules(self):
|
|
manager.CONF.set_default('driver_handles_share_servers', False)
|
|
manager.CONF.unmanage_remove_access_rules = True
|
|
self._setup_unmanage_mocks(mock_driver=False,
|
|
mock_unmanage=mock.Mock())
|
|
smanager = self.share_manager
|
|
self.mock_object(smanager.access_helper, 'update_access_rules')
|
|
self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(return_value=[]))
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
share_instance_id = share.instance['id']
|
|
|
|
smanager.unmanage_share(self.context, share_id)
|
|
|
|
smanager.driver.unmanage.assert_called_once_with(mock.ANY)
|
|
smanager.access_helper.update_access_rules.assert_called_once_with(
|
|
mock.ANY, mock.ANY, delete_rules='all', share_server=None
|
|
)
|
|
smanager.db.share_instance_delete.assert_called_once_with(
|
|
mock.ANY, share_instance_id)
|
|
|
|
def test_delete_share_instance_share_server_not_found(self):
|
|
share_net = db_utils.create_share_network()
|
|
share = db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id='fake-id')
|
|
|
|
self.assertRaises(
|
|
exception.ShareServerNotFound,
|
|
self.share_manager.delete_share_instance,
|
|
self.context,
|
|
share.instance['id']
|
|
)
|
|
|
|
@ddt.data(True, False)
|
|
def test_delete_share_instance_last_on_srv_with_sec_service(
|
|
self, with_details):
|
|
share_net = db_utils.create_share_network()
|
|
sec_service = db_utils.create_security_service(
|
|
share_network_id=share_net['id'])
|
|
backend_details = dict(
|
|
security_service_ldap=jsonutils.dumps(sec_service))
|
|
if with_details:
|
|
share_srv = db_utils.create_share_server(
|
|
share_network_id=share_net['id'],
|
|
host=self.share_manager.host,
|
|
backend_details=backend_details)
|
|
else:
|
|
share_srv = db_utils.create_share_server(
|
|
share_network_id=share_net['id'],
|
|
host=self.share_manager.host)
|
|
db.share_server_backend_details_set(
|
|
context.get_admin_context(), share_srv['id'], backend_details)
|
|
share = db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id=share_srv['id'])
|
|
self.share_manager.driver = mock.Mock()
|
|
manager.CONF.delete_share_server_with_last_share = True
|
|
|
|
self.share_manager.delete_share_instance(self.context,
|
|
share.instance['id'])
|
|
|
|
self.share_manager.driver.teardown_server.assert_called_once_with(
|
|
server_details=backend_details,
|
|
security_services=[jsonutils.loads(
|
|
backend_details['security_service_ldap'])])
|
|
|
|
@ddt.data({'force': True, 'side_effect': 'update_access'},
|
|
{'force': True, 'side_effect': 'delete_share'},
|
|
{'force': False, 'side_effect': None})
|
|
@ddt.unpack
|
|
def test_delete_share_instance_last_on_server(self, force, side_effect):
|
|
share_net = db_utils.create_share_network()
|
|
share_srv = db_utils.create_share_server(
|
|
share_network_id=share_net['id'],
|
|
host=self.share_manager.host
|
|
)
|
|
share = db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id=share_srv['id'])
|
|
|
|
self.share_manager.driver = mock.Mock()
|
|
if side_effect == 'update_access':
|
|
self.mock_object(
|
|
self.share_manager.access_helper, 'update_access_rules',
|
|
mock.Mock(side_effect=Exception('fake')))
|
|
if side_effect == 'delete_share':
|
|
self.mock_object(self.share_manager.driver, 'delete_share',
|
|
mock.Mock(side_effect=Exception('fake')))
|
|
self.mock_object(manager.LOG, 'error')
|
|
manager.CONF.delete_share_server_with_last_share = True
|
|
self.share_manager.delete_share_instance(
|
|
self.context, share.instance['id'], force=force)
|
|
self.share_manager.driver.teardown_server.assert_called_once_with(
|
|
server_details=share_srv.get('backend_details'),
|
|
security_services=[])
|
|
self.assertEqual(force, manager.LOG.error.called)
|
|
|
|
def test_delete_share_instance_last_on_server_deletion_disabled(self):
|
|
share_net = db_utils.create_share_network()
|
|
share_srv = db_utils.create_share_server(
|
|
share_network_id=share_net['id'],
|
|
host=self.share_manager.host
|
|
)
|
|
share = db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id=share_srv['id'])
|
|
|
|
manager.CONF.delete_share_server_with_last_share = False
|
|
self.share_manager.driver = mock.Mock()
|
|
self.share_manager.delete_share_instance(self.context,
|
|
share.instance['id'])
|
|
self.assertFalse(self.share_manager.driver.teardown_network.called)
|
|
|
|
def test_delete_share_instance_not_last_on_server(self):
|
|
share_net = db_utils.create_share_network()
|
|
share_srv = db_utils.create_share_server(
|
|
share_network_id=share_net['id'],
|
|
host=self.share_manager.host
|
|
)
|
|
share = db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id=share_srv['id'])
|
|
db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id=share_srv['id'])
|
|
|
|
manager.CONF.delete_share_server_with_last_share = True
|
|
self.share_manager.driver = mock.Mock()
|
|
self.share_manager.delete_share_instance(self.context,
|
|
share.instance['id'])
|
|
self.assertFalse(self.share_manager.driver.teardown_network.called)
|
|
|
|
@ddt.data('update_access', 'delete_share')
|
|
def test_delete_share_instance_not_found(self, side_effect):
|
|
share_net = db_utils.create_share_network()
|
|
share_srv = db_utils.create_share_server(
|
|
share_network_id=share_net['id'],
|
|
host=self.share_manager.host)
|
|
share = db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id=share_srv['id'])
|
|
access = db_utils.create_access(share_id=share['id'])
|
|
db_utils.create_share(share_network_id=share_net['id'],
|
|
share_server_id=share_srv['id'])
|
|
|
|
manager.CONF.delete_share_server_with_last_share = False
|
|
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(return_value=share_srv))
|
|
self.mock_object(db, 'share_instance_get',
|
|
mock.Mock(return_value=share.instance))
|
|
self.mock_object(db, 'share_access_get_all_for_instance',
|
|
mock.Mock(return_value=[access]))
|
|
self.share_manager.driver = mock.Mock()
|
|
self.share_manager.access_helper.driver = mock.Mock()
|
|
if side_effect == 'update_access':
|
|
self.mock_object(
|
|
self.share_manager.access_helper.driver, 'update_access',
|
|
mock.Mock(side_effect=exception.ShareResourceNotFound(
|
|
share_id=share['id'])))
|
|
if side_effect == 'delete_share':
|
|
self.mock_object(
|
|
self.share_manager.driver, 'delete_share',
|
|
mock.Mock(side_effect=exception.ShareResourceNotFound(
|
|
share_id=share['id'])))
|
|
self.mock_object(
|
|
self.share_manager.access_helper, '_check_needs_refresh',
|
|
mock.Mock(return_value=False)
|
|
)
|
|
|
|
self.mock_object(manager.LOG, 'warning')
|
|
|
|
self.share_manager.delete_share_instance(self.context,
|
|
share.instance['id'])
|
|
self.assertFalse(self.share_manager.driver.teardown_network.called)
|
|
|
|
(self.share_manager.access_helper.driver.update_access.
|
|
assert_called_once_with(utils.IsAMatcher(
|
|
context.RequestContext), share.instance, [], add_rules=[],
|
|
delete_rules=[access], share_server=share_srv))
|
|
|
|
self.assertTrue(manager.LOG.warning.called)
|
|
|
|
def test_allow_deny_access(self):
|
|
"""Test access rules to share can be created and deleted."""
|
|
self.mock_object(share_access.LOG, 'info')
|
|
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
share_instance = db_utils.create_share_instance(
|
|
share_id=share_id,
|
|
access_rules_status=constants.STATUS_OUT_OF_SYNC)
|
|
share_instance_id = share_instance['id']
|
|
access = db_utils.create_access(share_id=share_id,
|
|
share_instance_id=share_instance_id)
|
|
access_id = access['id']
|
|
|
|
self.share_manager.allow_access(self.context, share_instance_id,
|
|
[access_id])
|
|
self.assertEqual('active', db.share_instance_get(
|
|
self.context, share_instance_id).access_rules_status)
|
|
|
|
share_access.LOG.info.assert_called_with(mock.ANY,
|
|
share_instance_id)
|
|
share_access.LOG.info.reset_mock()
|
|
|
|
self.share_manager.deny_access(self.context, share_instance_id,
|
|
[access_id])
|
|
|
|
share_access.LOG.info.assert_called_with(mock.ANY,
|
|
share_instance_id)
|
|
share_access.LOG.info.reset_mock()
|
|
|
|
def test_allow_deny_access_error(self):
|
|
"""Test access rules to share can be created and deleted with error."""
|
|
|
|
def _fake_allow_access(self, *args, **kwargs):
|
|
raise exception.NotFound()
|
|
|
|
def _fake_deny_access(self, *args, **kwargs):
|
|
raise exception.NotFound()
|
|
|
|
self.mock_object(self.share_manager.access_helper.driver,
|
|
"allow_access", _fake_allow_access)
|
|
self.mock_object(self.share_manager.access_helper.driver,
|
|
"deny_access", _fake_deny_access)
|
|
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
share_instance = db_utils.create_share_instance(
|
|
share_id=share_id,
|
|
access_rules_status=constants.STATUS_OUT_OF_SYNC)
|
|
share_instance_id = share_instance['id']
|
|
access = db_utils.create_access(share_id=share_id,
|
|
share_instance_id=share_instance_id)
|
|
access_id = access['id']
|
|
|
|
def validate(method):
|
|
self.assertRaises(exception.ManilaException, method, self.context,
|
|
share_instance_id, [access_id])
|
|
|
|
inst = db.share_instance_get(self.context, share_instance_id)
|
|
self.assertEqual(constants.STATUS_ERROR,
|
|
inst['access_rules_status'])
|
|
|
|
validate(self.share_manager.allow_access)
|
|
validate(self.share_manager.deny_access)
|
|
|
|
def test_setup_server(self):
|
|
# Setup required test data
|
|
share_server = {
|
|
'id': 'fake_id',
|
|
'share_network_id': 'fake_sn_id',
|
|
}
|
|
metadata = {'fake_metadata_key': 'fake_metadata_value'}
|
|
share_network = {'id': 'fake_sn_id'}
|
|
network_info = {'security_services': []}
|
|
for ss_type in constants.SECURITY_SERVICES_ALLOWED_TYPES:
|
|
network_info['security_services'].append({
|
|
'name': 'fake_name' + ss_type,
|
|
'domain': 'fake_domain' + ss_type,
|
|
'server': 'fake_server' + ss_type,
|
|
'dns_ip': 'fake_dns_ip' + ss_type,
|
|
'user': 'fake_user' + ss_type,
|
|
'type': ss_type,
|
|
'password': 'fake_password' + ss_type,
|
|
})
|
|
sec_services = network_info['security_services']
|
|
server_info = {'fake_server_info_key': 'fake_server_info_value'}
|
|
network_info['network_type'] = 'fake_network_type'
|
|
|
|
# mock required stuff
|
|
self.mock_object(self.share_manager.db, 'share_network_get',
|
|
mock.Mock(return_value=share_network))
|
|
self.mock_object(self.share_manager.driver, 'allocate_network')
|
|
self.mock_object(self.share_manager, '_form_server_setup_info',
|
|
mock.Mock(return_value=network_info))
|
|
self.mock_object(self.share_manager, '_validate_segmentation_id')
|
|
self.mock_object(self.share_manager.driver, 'setup_server',
|
|
mock.Mock(return_value=server_info))
|
|
self.mock_object(self.share_manager.db,
|
|
'share_server_backend_details_set')
|
|
self.mock_object(self.share_manager.db, 'share_server_update',
|
|
mock.Mock(return_value=share_server))
|
|
|
|
# execute method _setup_server
|
|
result = self.share_manager._setup_server(
|
|
self.context, share_server, metadata=metadata)
|
|
|
|
# verify results
|
|
self.assertEqual(share_server, result)
|
|
self.share_manager.db.share_network_get.assert_has_calls([
|
|
mock.call(self.context, share_server['share_network_id']),
|
|
mock.call(self.context, share_server['share_network_id']),
|
|
])
|
|
self.share_manager.driver.allocate_network.assert_called_once_with(
|
|
self.context, share_server, share_network)
|
|
self.share_manager._form_server_setup_info.assert_called_once_with(
|
|
self.context, share_server, share_network)
|
|
self.share_manager._validate_segmentation_id.assert_called_once_with(
|
|
network_info)
|
|
self.share_manager.driver.setup_server.assert_called_once_with(
|
|
network_info, metadata=metadata)
|
|
self.share_manager.db.share_server_backend_details_set.\
|
|
assert_has_calls([
|
|
mock.call(self.context, share_server['id'],
|
|
{'security_service_' + sec_services[0]['type']:
|
|
jsonutils.dumps(sec_services[0])}),
|
|
mock.call(self.context, share_server['id'],
|
|
{'security_service_' + sec_services[1]['type']:
|
|
jsonutils.dumps(sec_services[1])}),
|
|
mock.call(self.context, share_server['id'],
|
|
{'security_service_' + sec_services[2]['type']:
|
|
jsonutils.dumps(sec_services[2])}),
|
|
mock.call(self.context, share_server['id'], server_info),
|
|
])
|
|
self.share_manager.db.share_server_update.assert_called_once_with(
|
|
self.context, share_server['id'],
|
|
{'status': constants.STATUS_ACTIVE})
|
|
|
|
def test_setup_server_server_info_not_present(self):
|
|
# Setup required test data
|
|
share_server = {
|
|
'id': 'fake_id',
|
|
'share_network_id': 'fake_sn_id',
|
|
}
|
|
metadata = {'fake_metadata_key': 'fake_metadata_value'}
|
|
share_network = {'id': 'fake_sn_id'}
|
|
network_info = {
|
|
'fake_network_info_key': 'fake_network_info_value',
|
|
'security_services': [],
|
|
'network_type': 'fake_network_type',
|
|
}
|
|
server_info = {}
|
|
|
|
# mock required stuff
|
|
self.mock_object(self.share_manager.db, 'share_network_get',
|
|
mock.Mock(return_value=share_network))
|
|
self.mock_object(self.share_manager, '_form_server_setup_info',
|
|
mock.Mock(return_value=network_info))
|
|
self.mock_object(self.share_manager.driver, 'setup_server',
|
|
mock.Mock(return_value=server_info))
|
|
self.mock_object(self.share_manager.db, 'share_server_update',
|
|
mock.Mock(return_value=share_server))
|
|
self.mock_object(self.share_manager.driver, 'allocate_network')
|
|
|
|
# execute method _setup_server
|
|
result = self.share_manager._setup_server(
|
|
self.context, share_server, metadata=metadata)
|
|
|
|
# verify results
|
|
self.assertEqual(share_server, result)
|
|
self.share_manager.db.share_network_get.assert_has_calls([
|
|
mock.call(self.context, share_server['share_network_id']),
|
|
mock.call(self.context, share_server['share_network_id'])])
|
|
self.share_manager._form_server_setup_info.assert_called_once_with(
|
|
self.context, share_server, share_network)
|
|
self.share_manager.driver.setup_server.assert_called_once_with(
|
|
network_info, metadata=metadata)
|
|
self.share_manager.db.share_server_update.assert_called_once_with(
|
|
self.context, share_server['id'],
|
|
{'status': constants.STATUS_ACTIVE})
|
|
self.share_manager.driver.allocate_network.assert_called_once_with(
|
|
self.context, share_server, share_network)
|
|
|
|
def setup_server_raise_exception(self, detail_data_proper):
|
|
# Setup required test data
|
|
share_server = {
|
|
'id': 'fake_id',
|
|
'share_network_id': 'fake_sn_id',
|
|
}
|
|
server_info = {'details_key': 'value'}
|
|
share_network = {'id': 'fake_sn_id'}
|
|
network_info = {
|
|
'fake_network_info_key': 'fake_network_info_value',
|
|
'security_services': [],
|
|
'network_type': 'fake_network_type',
|
|
}
|
|
if detail_data_proper:
|
|
detail_data = {'server_details': server_info}
|
|
self.mock_object(self.share_manager.db,
|
|
'share_server_backend_details_set')
|
|
else:
|
|
detail_data = 'not dictionary detail data'
|
|
|
|
# Mock required parameters
|
|
self.mock_object(self.share_manager.db, 'share_network_get',
|
|
mock.Mock(return_value=share_network))
|
|
self.mock_object(self.share_manager.db, 'share_server_update')
|
|
for m in ['deallocate_network', 'allocate_network']:
|
|
self.mock_object(self.share_manager.driver, m)
|
|
self.mock_object(self.share_manager, '_form_server_setup_info',
|
|
mock.Mock(return_value=network_info))
|
|
self.mock_object(self.share_manager.db,
|
|
'share_server_backend_details_set')
|
|
self.mock_object(self.share_manager.driver, 'setup_server',
|
|
mock.Mock(side_effect=exception.ManilaException(
|
|
detail_data=detail_data)))
|
|
|
|
# execute method _setup_server
|
|
self.assertRaises(
|
|
exception.ManilaException,
|
|
self.share_manager._setup_server,
|
|
self.context,
|
|
share_server,
|
|
)
|
|
|
|
# verify results
|
|
if detail_data_proper:
|
|
self.share_manager.db.share_server_backend_details_set.\
|
|
assert_called_once_with(
|
|
self.context, share_server['id'], server_info)
|
|
self.share_manager._form_server_setup_info.assert_called_once_with(
|
|
self.context, share_server, share_network)
|
|
self.share_manager.db.share_server_update.assert_called_once_with(
|
|
self.context, share_server['id'],
|
|
{'status': constants.STATUS_ERROR})
|
|
self.share_manager.db.share_network_get.assert_has_calls([
|
|
mock.call(self.context, share_server['share_network_id']),
|
|
mock.call(self.context, share_server['share_network_id'])])
|
|
self.share_manager.driver.allocate_network.assert_has_calls([
|
|
mock.call(self.context, share_server, share_network)])
|
|
self.share_manager.driver.deallocate_network.assert_has_calls([
|
|
mock.call(self.context, share_server['id'])])
|
|
|
|
def test_setup_server_incorrect_detail_data(self):
|
|
self.setup_server_raise_exception(detail_data_proper=False)
|
|
|
|
def test_setup_server_exception_in_driver(self):
|
|
self.setup_server_raise_exception(detail_data_proper=True)
|
|
|
|
@ddt.data({},
|
|
{'detail_data': 'fake'},
|
|
{'detail_data': {'server_details': 'fake'}},
|
|
{'detail_data': {'server_details': {'fake': 'fake'}}},
|
|
{'detail_data': {
|
|
'server_details': {'fake': 'fake', 'fake2': 'fake2'}}},)
|
|
def test_setup_server_exception_in_cleanup_after_error(self, data):
|
|
|
|
def get_server_details_from_data(data):
|
|
d = data.get('detail_data')
|
|
if not isinstance(d, dict):
|
|
return {}
|
|
d = d.get('server_details')
|
|
if not isinstance(d, dict):
|
|
return {}
|
|
return d
|
|
|
|
share_server = {'id': 'fake', 'share_network_id': 'fake'}
|
|
details = get_server_details_from_data(data)
|
|
|
|
exc_mock = mock.Mock(side_effect=exception.ManilaException(**data))
|
|
details_mock = mock.Mock(side_effect=exception.ManilaException())
|
|
self.mock_object(self.share_manager.db, 'share_network_get', exc_mock)
|
|
self.mock_object(self.share_manager.db,
|
|
'share_server_backend_details_set', details_mock)
|
|
self.mock_object(self.share_manager.db, 'share_server_update')
|
|
self.mock_object(self.share_manager.driver, 'deallocate_network')
|
|
self.mock_object(manager.LOG, 'debug')
|
|
self.mock_object(manager.LOG, 'warning')
|
|
|
|
self.assertRaises(
|
|
exception.ManilaException,
|
|
self.share_manager._setup_server,
|
|
self.context,
|
|
share_server,
|
|
)
|
|
|
|
self.assertTrue(self.share_manager.db.share_network_get.called)
|
|
if details:
|
|
self.assertEqual(len(details), details_mock.call_count)
|
|
expected = [mock.call(mock.ANY, share_server['id'], {k: v})
|
|
for k, v in details.items()]
|
|
self.assertEqual(expected, details_mock.call_args_list)
|
|
self.share_manager.db.share_server_update.assert_called_once_with(
|
|
self.context,
|
|
share_server['id'],
|
|
{'status': constants.STATUS_ERROR})
|
|
self.share_manager.driver.deallocate_network.assert_called_once_with(
|
|
self.context, share_server['id']
|
|
)
|
|
self.assertFalse(manager.LOG.warning.called)
|
|
if get_server_details_from_data(data):
|
|
self.assertTrue(manager.LOG.debug.called)
|
|
|
|
def test_ensure_share_instance_has_pool_with_only_host(self):
|
|
fake_share = {
|
|
'status': constants.STATUS_AVAILABLE, 'host': 'host1', 'id': 1}
|
|
host = self.share_manager._ensure_share_instance_has_pool(
|
|
context.get_admin_context(), fake_share)
|
|
self.assertIsNone(host)
|
|
|
|
def test_ensure_share_instance_has_pool_with_full_pool_name(self):
|
|
fake_share = {'host': 'host1#pool0', 'id': 1,
|
|
'status': constants.STATUS_AVAILABLE}
|
|
fake_share_expected_value = 'pool0'
|
|
host = self.share_manager._ensure_share_instance_has_pool(
|
|
context.get_admin_context(), fake_share)
|
|
self.assertEqual(fake_share_expected_value, host)
|
|
|
|
def test_ensure_share_instance_has_pool_unable_to_fetch_share(self):
|
|
fake_share = {'host': 'host@backend', 'id': 1,
|
|
'status': constants.STATUS_AVAILABLE}
|
|
with mock.patch.object(self.share_manager.driver, 'get_pool',
|
|
side_effect=Exception):
|
|
with mock.patch.object(manager, 'LOG') as mock_LOG:
|
|
self.share_manager._ensure_share_instance_has_pool(
|
|
context.get_admin_context(), fake_share)
|
|
self.assertEqual(1, mock_LOG.error.call_count)
|
|
|
|
def test__form_server_setup_info(self):
|
|
def fake_network_allocations_get_for_share_server(*args, **kwargs):
|
|
if kwargs.get('label') != 'admin':
|
|
return ['foo', 'bar']
|
|
return ['admin-foo', 'admin-bar']
|
|
|
|
self.mock_object(
|
|
self.share_manager.db, 'network_allocations_get_for_share_server',
|
|
mock.Mock(
|
|
side_effect=fake_network_allocations_get_for_share_server))
|
|
fake_share_server = dict(
|
|
id='fake_share_server_id', backend_details=dict(foo='bar'))
|
|
fake_share_network = dict(
|
|
segmentation_id='fake_segmentation_id',
|
|
cidr='fake_cidr',
|
|
neutron_net_id='fake_neutron_net_id',
|
|
neutron_subnet_id='fake_neutron_subnet_id',
|
|
nova_net_id='fake_nova_net_id',
|
|
security_services='fake_security_services',
|
|
network_type='fake_network_type')
|
|
expected = dict(
|
|
server_id=fake_share_server['id'],
|
|
segmentation_id=fake_share_network['segmentation_id'],
|
|
cidr=fake_share_network['cidr'],
|
|
neutron_net_id=fake_share_network['neutron_net_id'],
|
|
neutron_subnet_id=fake_share_network['neutron_subnet_id'],
|
|
nova_net_id=fake_share_network['nova_net_id'],
|
|
security_services=fake_share_network['security_services'],
|
|
network_allocations=(
|
|
fake_network_allocations_get_for_share_server()),
|
|
admin_network_allocations=(
|
|
fake_network_allocations_get_for_share_server(label='admin')),
|
|
backend_details=fake_share_server['backend_details'],
|
|
network_type=fake_share_network['network_type'])
|
|
|
|
network_info = self.share_manager._form_server_setup_info(
|
|
self.context, fake_share_server, fake_share_network)
|
|
|
|
self.assertEqual(expected, network_info)
|
|
self.share_manager.db.network_allocations_get_for_share_server.\
|
|
assert_has_calls([
|
|
mock.call(self.context, fake_share_server['id'], label='user'),
|
|
mock.call(self.context, fake_share_server['id'], label='admin')
|
|
])
|
|
|
|
@ddt.data(
|
|
{'network_info': {'network_type': 'vlan', 'segmentation_id': '100'}},
|
|
{'network_info': {'network_type': 'vlan', 'segmentation_id': '1'}},
|
|
{'network_info': {'network_type': 'vlan', 'segmentation_id': '4094'}},
|
|
{'network_info': {'network_type': 'vxlan', 'segmentation_id': '100'}},
|
|
{'network_info': {'network_type': 'vxlan', 'segmentation_id': '1'}},
|
|
{'network_info': {'network_type': 'vxlan',
|
|
'segmentation_id': '16777215'}},
|
|
{'network_info': {'network_type': 'gre', 'segmentation_id': '100'}},
|
|
{'network_info': {'network_type': 'gre', 'segmentation_id': '1'}},
|
|
{'network_info': {'network_type': 'gre',
|
|
'segmentation_id': '4294967295'}},
|
|
{'network_info': {'network_type': 'flat', 'segmentation_id': None}},
|
|
{'network_info': {'network_type': 'flat', 'segmentation_id': 0}},
|
|
{'network_info': {'network_type': None, 'segmentation_id': None}},
|
|
{'network_info': {'network_type': None, 'segmentation_id': 0}})
|
|
@ddt.unpack
|
|
def test_validate_segmentation_id_with_valid_values(self, network_info):
|
|
self.share_manager._validate_segmentation_id(network_info)
|
|
|
|
@ddt.data(
|
|
{'network_info': {'network_type': 'vlan', 'segmentation_id': None}},
|
|
{'network_info': {'network_type': 'vlan', 'segmentation_id': -1}},
|
|
{'network_info': {'network_type': 'vlan', 'segmentation_id': 0}},
|
|
{'network_info': {'network_type': 'vlan', 'segmentation_id': '4095'}},
|
|
{'network_info': {'network_type': 'vxlan', 'segmentation_id': None}},
|
|
{'network_info': {'network_type': 'vxlan', 'segmentation_id': 0}},
|
|
{'network_info': {'network_type': 'vxlan',
|
|
'segmentation_id': '16777216'}},
|
|
{'network_info': {'network_type': 'gre', 'segmentation_id': None}},
|
|
{'network_info': {'network_type': 'gre', 'segmentation_id': 0}},
|
|
{'network_info': {'network_type': 'gre',
|
|
'segmentation_id': '4294967296'}},
|
|
{'network_info': {'network_type': 'flat', 'segmentation_id': '1000'}},
|
|
{'network_info': {'network_type': None, 'segmentation_id': '1000'}})
|
|
@ddt.unpack
|
|
def test_validate_segmentation_id_with_invalid_values(self, network_info):
|
|
self.assertRaises(exception.NetworkBadConfigurationException,
|
|
self.share_manager._validate_segmentation_id,
|
|
network_info)
|
|
|
|
@ddt.data(10, 36, 60)
|
|
def test_verify_server_cleanup_interval_valid_cases(self, val):
|
|
data = dict(DEFAULT=dict(unused_share_server_cleanup_interval=val))
|
|
with test_utils.create_temp_config_with_opts(data):
|
|
manager.ShareManager()
|
|
|
|
@mock.patch.object(db, 'share_server_get_all_unused_deletable',
|
|
mock.Mock())
|
|
@mock.patch.object(manager.ShareManager, 'delete_share_server',
|
|
mock.Mock())
|
|
def test_delete_free_share_servers_cleanup_disabled(self):
|
|
data = dict(DEFAULT=dict(automatic_share_server_cleanup=False))
|
|
with test_utils.create_temp_config_with_opts(data):
|
|
share_manager = manager.ShareManager()
|
|
share_manager.driver.initialized = True
|
|
share_manager.delete_free_share_servers(self.context)
|
|
self.assertFalse(db.share_server_get_all_unused_deletable.called)
|
|
|
|
@mock.patch.object(db, 'share_server_get_all_unused_deletable',
|
|
mock.Mock())
|
|
@mock.patch.object(manager.ShareManager, 'delete_share_server',
|
|
mock.Mock())
|
|
def test_delete_free_share_servers_driver_handles_ss_disabled(self):
|
|
data = dict(DEFAULT=dict(driver_handles_share_servers=False))
|
|
with test_utils.create_temp_config_with_opts(data):
|
|
share_manager = manager.ShareManager()
|
|
share_manager.driver.initialized = True
|
|
share_manager.delete_free_share_servers(self.context)
|
|
self.assertFalse(db.share_server_get_all_unused_deletable.called)
|
|
self.assertFalse(share_manager.delete_share_server.called)
|
|
|
|
@mock.patch.object(db, 'share_server_get_all_unused_deletable',
|
|
mock.Mock(return_value=['server1', ]))
|
|
@mock.patch.object(manager.ShareManager, 'delete_share_server',
|
|
mock.Mock())
|
|
@mock.patch.object(timeutils, 'utcnow', mock.Mock(
|
|
return_value=datetime.timedelta(minutes=20)))
|
|
def test_delete_free_share_servers(self):
|
|
self.share_manager.delete_free_share_servers(self.context)
|
|
db.share_server_get_all_unused_deletable.assert_called_once_with(
|
|
self.context,
|
|
self.share_manager.host,
|
|
datetime.timedelta(minutes=10))
|
|
self.share_manager.delete_share_server.assert_called_once_with(
|
|
self.context,
|
|
'server1')
|
|
timeutils.utcnow.assert_called_once_with()
|
|
|
|
def test_extend_share_invalid(self):
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
reservations = {}
|
|
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
self.mock_object(quota.QUOTAS, 'rollback')
|
|
self.mock_object(self.share_manager.driver, 'extend_share',
|
|
mock.Mock(side_effect=Exception('fake')))
|
|
|
|
self.assertRaises(
|
|
exception.ShareExtendingError,
|
|
self.share_manager.extend_share, self.context, share_id, 123, {})
|
|
|
|
quota.QUOTAS.rollback.assert_called_once_with(
|
|
mock.ANY,
|
|
reservations,
|
|
project_id=six.text_type(share['project_id']),
|
|
user_id=six.text_type(share['user_id'])
|
|
)
|
|
|
|
def test_extend_share(self):
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
new_size = 123
|
|
shr_update = {
|
|
'size': int(new_size),
|
|
'status': constants.STATUS_AVAILABLE.lower()
|
|
}
|
|
reservations = {}
|
|
fake_share_server = 'fake'
|
|
|
|
manager = self.share_manager
|
|
self.mock_object(manager, 'driver')
|
|
self.mock_object(manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(manager.db, 'share_update',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(quota.QUOTAS, 'commit')
|
|
self.mock_object(manager.driver, 'extend_share')
|
|
self.mock_object(manager, '_get_share_server',
|
|
mock.Mock(return_value=fake_share_server))
|
|
|
|
self.share_manager.extend_share(self.context, share_id,
|
|
new_size, reservations)
|
|
|
|
self.assertTrue(manager._get_share_server.called)
|
|
manager.driver.extend_share.assert_called_once_with(
|
|
utils.IsAMatcher(models.ShareInstance),
|
|
new_size, share_server=fake_share_server
|
|
)
|
|
quota.QUOTAS.commit.assert_called_once_with(
|
|
mock.ANY, reservations, project_id=share['project_id'],
|
|
user_id=share['user_id'])
|
|
manager.db.share_update.assert_called_once_with(
|
|
mock.ANY, share_id, shr_update
|
|
)
|
|
|
|
def test_shrink_share_quota_error(self):
|
|
size = 5
|
|
new_size = 1
|
|
share = db_utils.create_share(size=size)
|
|
share_id = share['id']
|
|
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
self.mock_object(quota.QUOTAS, 'reserve',
|
|
mock.Mock(side_effect=Exception('fake')))
|
|
|
|
self.assertRaises(
|
|
exception.ShareShrinkingError,
|
|
self.share_manager.shrink_share, self.context, share_id, new_size)
|
|
|
|
quota.QUOTAS.reserve.assert_called_with(
|
|
mock.ANY,
|
|
project_id=six.text_type(share['project_id']),
|
|
user_id=six.text_type(share['user_id']),
|
|
gigabytes=new_size - size
|
|
)
|
|
self.assertTrue(self.share_manager.db.share_update.called)
|
|
|
|
@ddt.data({'exc': exception.InvalidShare('fake'),
|
|
'status': constants.STATUS_SHRINKING_ERROR},
|
|
{'exc': exception.ShareShrinkingPossibleDataLoss("fake"),
|
|
'status': constants.STATUS_SHRINKING_POSSIBLE_DATA_LOSS_ERROR})
|
|
@ddt.unpack
|
|
def test_shrink_share_invalid(self, exc, status):
|
|
share = db_utils.create_share()
|
|
new_size = 1
|
|
share_id = share['id']
|
|
size_decrease = int(share['size']) - new_size
|
|
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
self.mock_object(self.share_manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(quota.QUOTAS, 'reserve')
|
|
self.mock_object(quota.QUOTAS, 'rollback')
|
|
self.mock_object(self.share_manager.driver, 'shrink_share',
|
|
mock.Mock(side_effect=exc))
|
|
|
|
self.assertRaises(
|
|
exception.ShareShrinkingError,
|
|
self.share_manager.shrink_share, self.context, share_id, new_size)
|
|
|
|
self.share_manager.driver.shrink_share.assert_called_once_with(
|
|
utils.IsAMatcher(models.ShareInstance),
|
|
new_size, share_server=None
|
|
)
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
mock.ANY, share_id, {'status': status}
|
|
)
|
|
quota.QUOTAS.reserve.assert_called_once_with(
|
|
mock.ANY, gigabytes=-size_decrease, project_id=share['project_id'],
|
|
user_id=share['user_id']
|
|
)
|
|
quota.QUOTAS.rollback.assert_called_once_with(
|
|
mock.ANY, mock.ANY, project_id=share['project_id'],
|
|
user_id=share['user_id']
|
|
)
|
|
self.assertTrue(self.share_manager.db.share_get.called)
|
|
|
|
def test_shrink_share(self):
|
|
share = db_utils.create_share()
|
|
share_id = share['id']
|
|
new_size = 123
|
|
shr_update = {
|
|
'size': int(new_size),
|
|
'status': constants.STATUS_AVAILABLE
|
|
}
|
|
fake_share_server = 'fake'
|
|
size_decrease = int(share['size']) - new_size
|
|
|
|
manager = self.share_manager
|
|
self.mock_object(manager, 'driver')
|
|
self.mock_object(manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(manager.db, 'share_update',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(quota.QUOTAS, 'commit')
|
|
self.mock_object(quota.QUOTAS, 'reserve')
|
|
self.mock_object(manager.driver, 'shrink_share')
|
|
self.mock_object(manager, '_get_share_server',
|
|
mock.Mock(return_value=fake_share_server))
|
|
|
|
self.share_manager.shrink_share(self.context, share_id, new_size)
|
|
|
|
self.assertTrue(manager._get_share_server.called)
|
|
manager.driver.shrink_share.assert_called_once_with(
|
|
utils.IsAMatcher(models.ShareInstance),
|
|
new_size, share_server=fake_share_server
|
|
)
|
|
|
|
quota.QUOTAS.reserve.assert_called_once_with(
|
|
mock.ANY, gigabytes=-size_decrease, project_id=share['project_id'],
|
|
user_id=share['user_id']
|
|
)
|
|
quota.QUOTAS.commit.assert_called_once_with(
|
|
mock.ANY, mock.ANY, project_id=share['project_id'],
|
|
user_id=share['user_id']
|
|
)
|
|
manager.db.share_update.assert_called_once_with(
|
|
mock.ANY, share_id, shr_update
|
|
)
|
|
|
|
def test_report_driver_status_driver_handles_ss_false(self):
|
|
fake_stats = {'field': 'val'}
|
|
fake_pool = {'name': 'pool1'}
|
|
self.share_manager.last_capabilities = {'field': 'old_val'}
|
|
|
|
self.mock_object(self.share_manager, 'driver', mock.Mock())
|
|
driver = self.share_manager.driver
|
|
|
|
driver.get_share_stats = mock.Mock(return_value=fake_stats)
|
|
self.mock_object(db, 'share_server_get_all_by_host', mock.Mock())
|
|
driver.driver_handles_share_servers = False
|
|
driver.get_share_server_pools = mock.Mock(return_value=fake_pool)
|
|
|
|
self.share_manager._report_driver_status(self.context)
|
|
|
|
driver.get_share_stats.assert_called_once_with(
|
|
refresh=True)
|
|
self.assertFalse(db.share_server_get_all_by_host.called)
|
|
self.assertFalse(driver.get_share_server_pools.called)
|
|
self.assertEqual(fake_stats, self.share_manager.last_capabilities)
|
|
|
|
def test_report_driver_status_driver_handles_ss(self):
|
|
fake_stats = {'field': 'val'}
|
|
fake_ss = {'id': '1234'}
|
|
fake_pool = {'name': 'pool1'}
|
|
|
|
self.mock_object(self.share_manager, 'driver', mock.Mock())
|
|
driver = self.share_manager.driver
|
|
|
|
driver.get_share_stats = mock.Mock(return_value=fake_stats)
|
|
self.mock_object(db, 'share_server_get_all_by_host', mock.Mock(
|
|
return_value=[fake_ss]))
|
|
driver.driver_handles_share_servers = True
|
|
driver.get_share_server_pools = mock.Mock(return_value=fake_pool)
|
|
|
|
self.share_manager._report_driver_status(self.context)
|
|
|
|
driver.get_share_stats.assert_called_once_with(refresh=True)
|
|
db.share_server_get_all_by_host.assert_called_once_with(
|
|
self.context,
|
|
self.share_manager.host)
|
|
driver.get_share_server_pools.assert_called_once_with(fake_ss)
|
|
expected_stats = {
|
|
'field': 'val',
|
|
'server_pools_mapping': {
|
|
'1234': fake_pool},
|
|
}
|
|
self.assertEqual(expected_stats, self.share_manager.last_capabilities)
|
|
|
|
def test_report_driver_status_empty_share_stats(self):
|
|
old_capabilities = {'field': 'old_val'}
|
|
fake_pool = {'name': 'pool1'}
|
|
self.share_manager.last_capabilities = old_capabilities
|
|
|
|
self.mock_object(self.share_manager, 'driver', mock.Mock())
|
|
driver = self.share_manager.driver
|
|
|
|
driver.get_share_stats = mock.Mock(return_value={})
|
|
self.mock_object(db, 'share_server_get_all_by_host', mock.Mock())
|
|
driver.driver_handles_share_servers = True
|
|
driver.get_share_server_pools = mock.Mock(return_value=fake_pool)
|
|
|
|
self.share_manager._report_driver_status(self.context)
|
|
|
|
driver.get_share_stats.assert_called_once_with(refresh=True)
|
|
self.assertFalse(db.share_server_get_all_by_host.called)
|
|
self.assertFalse(driver.get_share_server_pools.called)
|
|
self.assertEqual(old_capabilities,
|
|
self.share_manager.last_capabilities)
|
|
|
|
def test_create_consistency_group(self):
|
|
fake_cg = {'id': 'fake_id'}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group',
|
|
mock.Mock(return_value=None))
|
|
|
|
self.share_manager.create_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
|
|
def test_create_cg_with_share_network_driver_not_handles_servers(self):
|
|
manager.CONF.set_default('driver_handles_share_servers', False)
|
|
self.mock_object(
|
|
self.share_manager.driver.configuration, 'safe_get',
|
|
mock.Mock(return_value=False))
|
|
cg_id = 'fake_cg_id'
|
|
share_network_id = 'fake_sn'
|
|
fake_cg = {'id': 'fake_id', 'share_network_id': share_network_id}
|
|
self.mock_object(
|
|
self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update')
|
|
|
|
self.assertRaises(
|
|
exception.ManilaException,
|
|
self.share_manager.create_consistency_group, self.context, cg_id)
|
|
|
|
self.share_manager.db.consistency_group_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), cg_id)
|
|
self.share_manager.db.consistency_group_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), cg_id,
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
def test_create_cg_with_share_network_driver_handles_servers(self):
|
|
manager.CONF.set_default('driver_handles_share_servers', True)
|
|
self.mock_object(
|
|
self.share_manager.driver.configuration, 'safe_get',
|
|
mock.Mock(return_value=True))
|
|
share_network_id = 'fake_sn'
|
|
fake_cg = {'id': 'fake_id', 'share_network_id': share_network_id,
|
|
'host': "fake_host"}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager, '_provide_share_server_for_cg',
|
|
mock.Mock(return_value=({}, fake_cg)))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group',
|
|
mock.Mock(return_value=None))
|
|
|
|
self.share_manager.create_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
|
|
def test_create_consistency_group_with_update(self):
|
|
fake_cg = {'id': 'fake_id'}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group',
|
|
mock.Mock(return_value={'foo': 'bar'}))
|
|
|
|
self.share_manager.create_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_any_call(mock.ANY, 'fake_id', {'foo': 'bar'})
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_any_call(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
|
|
def test_create_consistency_group_with_error(self):
|
|
fake_cg = {'id': 'fake_id'}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group',
|
|
mock.Mock(side_effect=exception.Error))
|
|
|
|
self.assertRaises(exception.Error,
|
|
self.share_manager.create_consistency_group,
|
|
self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
def test_create_consistency_group_from_cgsnapshot(self):
|
|
fake_cg = {'id': 'fake_id', 'source_cgsnapshot_id': 'fake_snap_id',
|
|
'shares': [], 'share_server_id': 'fake_ss_id'}
|
|
fake_ss = {'id': 'fake_ss_id', 'share_network_id': 'fake_sn'}
|
|
fake_snap = {'id': 'fake_snap_id', 'cgsnapshot_members': [],
|
|
'consistency_group': {'share_server_id': fake_ss['id']}}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(
|
|
return_value=fake_ss))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group_from_cgsnapshot',
|
|
mock.Mock(return_value=(None, None)))
|
|
|
|
self.share_manager.create_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
self.share_manager.db.share_server_get(mock.ANY, 'fake_ss_id')
|
|
self.share_manager.driver.create_consistency_group_from_cgsnapshot.\
|
|
assert_called_once_with(
|
|
mock.ANY, fake_cg, fake_snap, share_server=fake_ss)
|
|
|
|
def test_create_cg_cgsnapshot_share_network_driver_not_handles_servers(
|
|
self):
|
|
manager.CONF.set_default('driver_handles_share_servers', False)
|
|
self.mock_object(
|
|
self.share_manager.driver.configuration, 'safe_get',
|
|
mock.Mock(return_value=False))
|
|
cg_id = 'fake_cg_id'
|
|
share_network_id = 'fake_sn'
|
|
fake_cg = {'id': 'fake_id', 'source_cgsnapshot_id': 'fake_snap_id',
|
|
'shares': [], 'share_network_id': share_network_id,
|
|
'host': "fake_host"}
|
|
self.mock_object(
|
|
self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
fake_snap = {'id': 'fake_snap_id', 'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update')
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.create_consistency_group,
|
|
self.context, cg_id)
|
|
|
|
self.share_manager.db.consistency_group_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), cg_id)
|
|
self.share_manager.db.consistency_group_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), cg_id,
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
def test_create_cg_from_cgsnapshot_share_network_driver_handles_servers(
|
|
self):
|
|
manager.CONF.set_default('driver_handles_share_servers', True)
|
|
self.mock_object(self.share_manager.driver.configuration, 'safe_get',
|
|
mock.Mock(return_value=True))
|
|
share_network_id = 'fake_sn'
|
|
fake_cg = {'id': 'fake_id', 'source_cgsnapshot_id': 'fake_snap_id',
|
|
'shares': [], 'share_network_id': share_network_id}
|
|
fake_snap = {'id': 'fake_snap_id', 'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager, '_provide_share_server_for_cg',
|
|
mock.Mock(return_value=({}, fake_cg)))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group_from_cgsnapshot',
|
|
mock.Mock(return_value=(None, None)))
|
|
|
|
self.share_manager.create_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
|
|
def test_create_consistency_group_from_cgsnapshot_with_update(self):
|
|
fake_cg = {'id': 'fake_id', 'source_cgsnapshot_id': 'fake_snap_id',
|
|
'shares': []}
|
|
fake_snap = {'id': 'fake_snap_id', 'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group_from_cgsnapshot',
|
|
mock.Mock(return_value=({'foo': 'bar'}, None)))
|
|
|
|
self.share_manager.create_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_any_call(mock.ANY, 'fake_id', {'foo': 'bar'})
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_any_call(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
|
|
def test_create_consistency_group_from_cgsnapshot_with_share_update(self):
|
|
fake_share = {'id': 'fake_share_id'}
|
|
fake_export_locations = ['my_export_location']
|
|
fake_cg = {'id': 'fake_id', 'source_cgsnapshot_id': 'fake_snap_id',
|
|
'shares': [fake_share]}
|
|
fake_snap = {'id': 'fake_snap_id', 'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update')
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
self.mock_object(self.share_manager.db,
|
|
'share_export_locations_update')
|
|
fake_share_update_list = [{'id': fake_share['id'],
|
|
'foo': 'bar',
|
|
'export_locations': fake_export_locations}]
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group_from_cgsnapshot',
|
|
mock.Mock(
|
|
return_value=(None, fake_share_update_list)))
|
|
|
|
self.share_manager.create_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.share_instance_update.\
|
|
assert_any_call(mock.ANY, 'fake_share_id', {'foo': 'bar'})
|
|
self.share_manager.db.share_export_locations_update.\
|
|
assert_any_call(mock.ANY, 'fake_share_id', fake_export_locations)
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_any_call(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
|
|
def test_create_consistency_group_from_cgsnapshot_with_error(self):
|
|
fake_cg = {'id': 'fake_id', 'source_cgsnapshot_id': 'fake_snap_id',
|
|
'shares': []}
|
|
fake_snap = {'id': 'fake_snap_id', 'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db,
|
|
'share_instances_get_all_by_consistency_group_id',
|
|
mock.Mock(return_value=[]))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group_from_cgsnapshot',
|
|
mock.Mock(side_effect=exception.Error))
|
|
|
|
self.assertRaises(exception.Error,
|
|
self.share_manager.create_consistency_group,
|
|
self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
def test_create_consistency_group_from_cgsnapshot_with_share_error(self):
|
|
fake_share = {'id': 'fake_share_id'}
|
|
fake_cg = {'id': 'fake_id', 'source_cgsnapshot_id': 'fake_snap_id',
|
|
'shares': [fake_share]}
|
|
fake_snap = {'id': 'fake_snap_id', 'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db,
|
|
'share_instances_get_all_by_consistency_group_id',
|
|
mock.Mock(return_value=[fake_share]))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update')
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_consistency_group_from_cgsnapshot',
|
|
mock.Mock(side_effect=exception.Error))
|
|
|
|
self.assertRaises(exception.Error,
|
|
self.share_manager.create_consistency_group,
|
|
self.context, "fake_id")
|
|
|
|
self.share_manager.db.share_instance_update.\
|
|
assert_any_call(mock.ANY, 'fake_share_id',
|
|
{'status': constants.STATUS_ERROR})
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
def test_delete_consistency_group(self):
|
|
fake_cg = {'id': 'fake_id'}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_destroy',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'delete_consistency_group',
|
|
mock.Mock(return_value=None))
|
|
|
|
self.share_manager.delete_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_destroy.\
|
|
assert_called_once_with(mock.ANY, 'fake_id')
|
|
|
|
def test_delete_consistency_group_with_update(self):
|
|
fake_cg = {'id': 'fake_id'}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_destroy',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'delete_consistency_group',
|
|
mock.Mock(return_value={'foo': 'bar'}))
|
|
|
|
self.share_manager.delete_consistency_group(self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id', {'foo': 'bar'})
|
|
self.share_manager.db.consistency_group_destroy.\
|
|
assert_called_once_with(mock.ANY, 'fake_id')
|
|
|
|
def test_delete_consistency_group_with_error(self):
|
|
fake_cg = {'id': 'fake_id'}
|
|
self.mock_object(self.share_manager.db, 'consistency_group_get',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.db, 'consistency_group_update',
|
|
mock.Mock(return_value=fake_cg))
|
|
self.mock_object(self.share_manager.driver,
|
|
'delete_consistency_group',
|
|
mock.Mock(side_effect=exception.Error))
|
|
|
|
self.assertRaises(exception.Error,
|
|
self.share_manager.delete_consistency_group,
|
|
self.context, "fake_id")
|
|
|
|
self.share_manager.db.consistency_group_update.\
|
|
assert_called_once_with(mock.ANY, 'fake_id',
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
def test_create_cgsnapshot(self):
|
|
fake_snap = {'id': 'fake_snap_id', 'consistency_group': {},
|
|
'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_update',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_cgsnapshot',
|
|
mock.Mock(return_value=(None, None)))
|
|
|
|
self.share_manager.create_cgsnapshot(self.context, fake_snap['id'])
|
|
|
|
self.share_manager.db.cgsnapshot_update.\
|
|
assert_called_once_with(mock.ANY, fake_snap['id'],
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
|
|
def test_create_cgsnapshot_with_update(self):
|
|
fake_snap = {'id': 'fake_snap_id', 'consistency_group': {},
|
|
'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_update',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_cgsnapshot',
|
|
mock.Mock(return_value=({'foo': 'bar'}, None)))
|
|
|
|
self.share_manager.create_cgsnapshot(self.context, fake_snap['id'])
|
|
|
|
self.share_manager.db.cgsnapshot_update.\
|
|
assert_any_call(mock.ANY, 'fake_snap_id', {'foo': 'bar'})
|
|
self.share_manager.db.cgsnapshot_update.assert_any_call(
|
|
mock.ANY, fake_snap['id'],
|
|
{'status': constants.STATUS_AVAILABLE, 'created_at': mock.ANY})
|
|
|
|
def test_create_cgsnapshot_with_member_update(self):
|
|
fake_member = {
|
|
'id': 'fake_member_id',
|
|
'share_instance_id': 'blah',
|
|
}
|
|
fake_member_update = {
|
|
'id': 'fake_member_id',
|
|
'foo': 'bar'
|
|
}
|
|
fake_snap = {'id': 'fake_snap_id', 'consistency_group': {},
|
|
'cgsnapshot_members': [fake_member]}
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_update',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_member_update')
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(return_value={'id': 'blah'}))
|
|
self.mock_object(self.share_manager.driver, 'create_cgsnapshot',
|
|
mock.Mock(return_value=(None, [fake_member_update])))
|
|
|
|
self.share_manager.create_cgsnapshot(self.context, fake_snap['id'])
|
|
|
|
self.share_manager.db.cgsnapshot_update.assert_any_call(
|
|
mock.ANY, fake_snap['id'],
|
|
{'cgsnapshot_members': [fake_member_update]})
|
|
self.share_manager.db.cgsnapshot_update.\
|
|
assert_any_call(mock.ANY, fake_snap['id'],
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'created_at': mock.ANY})
|
|
self.assertTrue(self.share_manager.db.cgsnapshot_member_update.called)
|
|
|
|
def test_create_cgsnapshot_with_error(self):
|
|
fake_snap = {'id': 'fake_snap_id', 'consistency_group': {},
|
|
'cgsnapshot_members': []}
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_get',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.db, 'cgsnapshot_update',
|
|
mock.Mock(return_value=fake_snap))
|
|
self.mock_object(self.share_manager.driver,
|
|
'create_cgsnapshot',
|
|
mock.Mock(side_effect=exception.Error))
|
|
|
|
self.assertRaises(exception.Error,
|
|
self.share_manager.create_cgsnapshot,
|
|
self.context, fake_snap['id'])
|
|
|
|
self.share_manager.db.cgsnapshot_update.\
|
|
assert_called_once_with(mock.ANY, fake_snap['id'],
|
|
{'status': constants.STATUS_ERROR})
|
|
|
|
def test_migration_get_info(self):
|
|
share_instance = {'share_server_id': 'fake_server_id'}
|
|
share_instance_id = 'fake_id'
|
|
share_server = 'fake_share_server'
|
|
migration_info = 'fake_info'
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(return_value=share_instance))
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(return_value=share_server))
|
|
self.mock_object(self.share_manager.driver, 'migration_get_info',
|
|
mock.Mock(return_value=migration_info))
|
|
|
|
# run
|
|
result = self.share_manager.migration_get_info(
|
|
self.context, share_instance_id)
|
|
|
|
# asserts
|
|
self.assertEqual(migration_info, result)
|
|
|
|
self.share_manager.db.share_instance_get.assert_called_once_with(
|
|
self.context, share_instance_id, with_share_data=True)
|
|
|
|
self.share_manager.driver.migration_get_info.assert_called_once_with(
|
|
self.context, share_instance, share_server)
|
|
|
|
def test_migration_get_driver_info(self):
|
|
share_instance = {'share_server_id': 'fake_server_id'}
|
|
share_instance_id = 'fake-id'
|
|
share_server = 'fake-share-server'
|
|
migration_info = 'fake_info'
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(return_value=share_instance))
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(return_value=share_server))
|
|
self.mock_object(self.share_manager.driver,
|
|
'migration_get_driver_info',
|
|
mock.Mock(return_value=migration_info))
|
|
|
|
result = self.share_manager.migration_get_driver_info(
|
|
self.context, share_instance_id)
|
|
|
|
# asserts
|
|
self.assertEqual(migration_info, result)
|
|
|
|
self.share_manager.db.share_instance_get.assert_called_once_with(
|
|
self.context, share_instance_id, with_share_data=True)
|
|
|
|
self.share_manager.driver.migration_get_driver_info.\
|
|
assert_called_once_with(self.context, share_instance, share_server)
|
|
|
|
@ddt.data({'return_value': (True, 'fake_model_update'), 'notify': True},
|
|
{'return_value': (False, 'fake_model_update'), 'notify': True},
|
|
{'return_value': (True, 'fake_model_update'), 'notify': False},
|
|
{'return_value': (False, 'fake_model_update'), 'notify': False})
|
|
@ddt.unpack
|
|
def test_migration_start(self, return_value, notify):
|
|
|
|
server = 'fake_share_server'
|
|
instance = db_utils.create_share_instance(
|
|
share_id='fake_id',
|
|
status=constants.STATUS_AVAILABLE,
|
|
share_server_id='fake_server_id')
|
|
share = db_utils.create_share(id='fake_id', instances=[instance])
|
|
host = {'host': 'fake_host'}
|
|
driver_migration_info = 'driver_fake_info'
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(return_value=instance))
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(return_value=server))
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
self.mock_object(rpcapi.ShareAPI, 'migration_get_driver_info',
|
|
mock.Mock(return_value=driver_migration_info))
|
|
self.mock_object(self.share_manager.driver, 'migration_start',
|
|
mock.Mock(return_value=return_value))
|
|
if not return_value[0]:
|
|
self.mock_object(self.share_manager, '_migration_start_generic')
|
|
|
|
# run
|
|
self.share_manager.migration_start(
|
|
self.context, 'fake_id', host, False, notify)
|
|
|
|
# asserts
|
|
self.share_manager.db.share_get.assert_called_once_with(
|
|
self.context, share['id'])
|
|
self.share_manager.db.share_instance_get.assert_called_once_with(
|
|
self.context, instance['id'], with_share_data=True)
|
|
self.share_manager.db.share_server_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
instance['share_server_id'])
|
|
|
|
share_update_calls = [
|
|
mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_IN_PROGRESS}),
|
|
mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': (
|
|
constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS)})
|
|
]
|
|
share_instance_update_calls = [
|
|
mock.call(self.context, instance['id'],
|
|
{'status': constants.STATUS_MIGRATING}),
|
|
mock.call(self.context, instance['id'], 'fake_model_update')
|
|
]
|
|
|
|
if not notify and return_value[0]:
|
|
share_update_calls.append(mock.call(
|
|
self.context, share['id'],
|
|
{'task_state':
|
|
constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE}))
|
|
elif notify and return_value[0]:
|
|
share_update_calls.append(mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_SUCCESS}))
|
|
share_instance_update_calls.append(mock.call(
|
|
self.context, instance['id'],
|
|
{'status': constants.STATUS_AVAILABLE,
|
|
'host': host['host']}))
|
|
elif not return_value[0]:
|
|
share_update_calls.append(mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_IN_PROGRESS}))
|
|
|
|
self.share_manager.db.share_update.assert_has_calls(share_update_calls)
|
|
self.share_manager.db.share_instance_update.assert_has_calls(
|
|
share_instance_update_calls)
|
|
rpcapi.ShareAPI.migration_get_driver_info.assert_called_once_with(
|
|
self.context, instance)
|
|
self.share_manager.driver.migration_start.assert_called_once_with(
|
|
self.context, instance, server, host, driver_migration_info,
|
|
notify)
|
|
|
|
def test_migration_start_exception(self):
|
|
|
|
server = 'fake_share_server'
|
|
instance = db_utils.create_share_instance(
|
|
share_id='fake_id',
|
|
status=constants.STATUS_AVAILABLE,
|
|
share_server_id='fake_server_id')
|
|
share = db_utils.create_share(id='fake_id', instances=[instance])
|
|
host = 'fake_host'
|
|
driver_migration_info = 'driver_fake_info'
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(return_value=instance))
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(return_value=server))
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
self.mock_object(rpcapi.ShareAPI, 'migration_get_driver_info',
|
|
mock.Mock(return_value=driver_migration_info))
|
|
|
|
self.mock_object(self.share_manager.driver, 'migration_start',
|
|
mock.Mock(side_effect=Exception('fake')))
|
|
self.mock_object(self.share_manager, '_migration_start_generic',
|
|
mock.Mock(side_effect=Exception('fake')))
|
|
self.mock_object(manager.LOG, 'exception')
|
|
|
|
# run
|
|
self.assertRaises(exception.ShareMigrationFailed,
|
|
self.share_manager.migration_start,
|
|
self.context, 'fake_id', host, False, False)
|
|
|
|
# asserts
|
|
self.share_manager.db.share_get.assert_called_once_with(
|
|
self.context, share['id'])
|
|
self.share_manager.db.share_instance_get.assert_called_once_with(
|
|
self.context, instance['id'], with_share_data=True)
|
|
self.share_manager.db.share_server_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
instance['share_server_id'])
|
|
|
|
share_update_calls = [
|
|
mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_IN_PROGRESS}),
|
|
mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': (
|
|
constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS)}),
|
|
mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_IN_PROGRESS}),
|
|
mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_ERROR})
|
|
]
|
|
share_instance_update_calls = [
|
|
mock.call(self.context, instance['id'],
|
|
{'status': constants.STATUS_MIGRATING}),
|
|
mock.call(self.context, instance['id'],
|
|
{'status': constants.STATUS_AVAILABLE})
|
|
]
|
|
(self.share_manager._migration_start_generic.
|
|
assert_called_once_with(self.context, share, instance, host,
|
|
False))
|
|
self.assertTrue(manager.LOG.exception.called)
|
|
|
|
self.share_manager.db.share_update.assert_has_calls(share_update_calls)
|
|
self.share_manager.db.share_instance_update.assert_has_calls(
|
|
share_instance_update_calls)
|
|
rpcapi.ShareAPI.migration_get_driver_info.assert_called_once_with(
|
|
self.context, instance)
|
|
self.share_manager.driver.migration_start.assert_called_once_with(
|
|
self.context, instance, server, host, driver_migration_info, False)
|
|
|
|
@ddt.data(None, Exception('fake'))
|
|
def test__migration_start_generic(self, exc):
|
|
instance = db_utils.create_share_instance(
|
|
share_id='fake_id',
|
|
status=constants.STATUS_AVAILABLE,
|
|
share_server_id='fake_server_id')
|
|
new_instance = db_utils.create_share_instance(
|
|
share_id='new_fake_id',
|
|
status=constants.STATUS_AVAILABLE)
|
|
share = db_utils.create_share(id='fake_id', instances=[instance])
|
|
server = 'share_server'
|
|
src_migration_info = 'src_fake_info'
|
|
dest_migration_info = 'dest_fake_info'
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(return_value=server))
|
|
self.mock_object(self.share_manager.db, 'share_instance_update',
|
|
mock.Mock(return_value=server))
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'change_to_read_only')
|
|
if exc is None:
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'create_instance_and_wait',
|
|
mock.Mock(return_value=new_instance))
|
|
self.mock_object(self.share_manager.driver, 'migration_get_info',
|
|
mock.Mock(return_value=src_migration_info))
|
|
self.mock_object(rpcapi.ShareAPI, 'migration_get_info',
|
|
mock.Mock(return_value=dest_migration_info))
|
|
self.mock_object(data_rpc.DataAPI, 'migration_start',
|
|
mock.Mock(side_effect=Exception('fake')))
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'cleanup_new_instance')
|
|
else:
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'create_instance_and_wait',
|
|
mock.Mock(side_effect=exc))
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'cleanup_access_rules')
|
|
|
|
# run
|
|
self.assertRaises(
|
|
exception.ShareMigrationFailed,
|
|
self.share_manager._migration_start_generic,
|
|
self.context, share, instance, 'fake_host', False)
|
|
|
|
# asserts
|
|
self.share_manager.db.share_server_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
instance['share_server_id'])
|
|
|
|
migration_api.ShareMigrationHelper.change_to_read_only.\
|
|
assert_called_once_with(instance, server, True,
|
|
self.share_manager.driver)
|
|
migration_api.ShareMigrationHelper.create_instance_and_wait.\
|
|
assert_called_once_with(share, instance, 'fake_host')
|
|
migration_api.ShareMigrationHelper.\
|
|
cleanup_access_rules.assert_called_once_with(
|
|
instance, server, self.share_manager.driver)
|
|
if exc is None:
|
|
self.share_manager.db.share_instance_update.\
|
|
assert_called_once_with(
|
|
self.context, new_instance['id'],
|
|
{'status': constants.STATUS_MIGRATING_TO})
|
|
self.share_manager.driver.migration_get_info.\
|
|
assert_called_once_with(self.context, instance, server)
|
|
rpcapi.ShareAPI.migration_get_info.assert_called_once_with(
|
|
self.context, new_instance)
|
|
data_rpc.DataAPI.migration_start.assert_called_once_with(
|
|
self.context, share['id'], ['lost+found'], instance['id'],
|
|
new_instance['id'], src_migration_info, dest_migration_info,
|
|
False)
|
|
migration_api.ShareMigrationHelper.\
|
|
cleanup_new_instance.assert_called_once_with(new_instance)
|
|
|
|
@ddt.data('fake_model_update', Exception('fake'))
|
|
def test_migration_complete_driver(self, exc):
|
|
server = 'fake_server'
|
|
model_update = 'fake_model_update'
|
|
instance = db_utils.create_share_instance(
|
|
share_id='fake_id',
|
|
status=constants.STATUS_AVAILABLE,
|
|
share_server_id='fake_server_id')
|
|
share = db_utils.create_share(
|
|
id='fake_id',
|
|
instances=[instance],
|
|
task_state=constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE)
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(return_value=instance))
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(return_value=server))
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
if isinstance(exc, Exception):
|
|
self.mock_object(self.share_manager.driver, 'migration_complete',
|
|
mock.Mock(side_effect=exc))
|
|
else:
|
|
self.mock_object(self.share_manager.driver, 'migration_complete',
|
|
mock.Mock(return_value=exc))
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
self.mock_object(rpcapi.ShareAPI, 'migration_get_driver_info',
|
|
mock.Mock(return_value='fake_info'))
|
|
self.mock_object(manager.LOG, 'exception')
|
|
|
|
# run
|
|
if isinstance(exc, Exception):
|
|
self.assertRaises(
|
|
exception.ShareMigrationFailed,
|
|
self.share_manager.migration_complete,
|
|
self.context, 'fake_id', 'fake_ins_id', 'new_fake_ins_id')
|
|
else:
|
|
self.share_manager.migration_complete(
|
|
self.context, 'fake_id', 'fake_ins_id', 'new_fake_ins_id')
|
|
|
|
# asserts
|
|
self.share_manager.db.share_get.assert_called_once_with(
|
|
self.context, share['id'])
|
|
self.share_manager.db.share_instance_get.assert_called_once_with(
|
|
self.context, instance['id'], with_share_data=True)
|
|
self.share_manager.db.share_server_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), 'fake_server_id')
|
|
self.share_manager.driver.migration_complete.assert_called_once_with(
|
|
self.context, instance, server, 'fake_info')
|
|
rpcapi.ShareAPI.migration_get_driver_info.assert_called_once_with(
|
|
self.context, instance)
|
|
if isinstance(exc, Exception):
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_ERROR})
|
|
self.assertTrue(manager.LOG.exception.called)
|
|
else:
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_SUCCESS})
|
|
self.share_manager.db.share_instance_update.\
|
|
assert_called_once_with(self.context, instance['id'],
|
|
model_update)
|
|
|
|
@ddt.data(None, Exception('fake'))
|
|
def test_migration_complete_generic(self, exc):
|
|
share = db_utils.create_share(
|
|
id='fake_id',
|
|
task_state=constants.TASK_STATE_DATA_COPYING_COMPLETED)
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_get',
|
|
mock.Mock(return_value=share))
|
|
self.mock_object(self.share_manager, '_migration_complete',
|
|
mock.Mock(side_effect=exc))
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
self.mock_object(manager.LOG, 'exception')
|
|
|
|
# run
|
|
if exc:
|
|
self.assertRaises(
|
|
exception.ShareMigrationFailed,
|
|
self.share_manager.migration_complete,
|
|
self.context, 'fake_id', 'fake_ins_id', 'new_fake_ins_id')
|
|
else:
|
|
self.share_manager.migration_complete(
|
|
self.context, 'fake_id', 'fake_ins_id', 'new_fake_ins_id')
|
|
|
|
# asserts
|
|
self.share_manager.db.share_get.assert_called_once_with(
|
|
self.context, share['id'])
|
|
self.share_manager._migration_complete.assert_called_once_with(
|
|
self.context, share, 'fake_ins_id', 'new_fake_ins_id')
|
|
if exc:
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_ERROR})
|
|
self.share_manager.db.share_instance_update.\
|
|
assert_called_once_with(
|
|
self.context, 'fake_ins_id',
|
|
{'status': constants.STATUS_AVAILABLE})
|
|
self.assertTrue(manager.LOG.exception.called)
|
|
|
|
@ddt.data(constants.TASK_STATE_DATA_COPYING_ERROR,
|
|
constants.TASK_STATE_DATA_COPYING_CANCELLED,
|
|
constants.TASK_STATE_DATA_COPYING_COMPLETED,
|
|
'other')
|
|
def test__migration_complete_status(self, status):
|
|
|
|
instance = db_utils.create_share_instance(
|
|
share_id='fake_id',
|
|
share_server_id='fake_server_id')
|
|
new_instance = db_utils.create_share_instance(share_id='fake_id')
|
|
share = db_utils.create_share(id='fake_id', task_state=status)
|
|
server = 'fake_server'
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(side_effect=[instance, new_instance]))
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(return_value=server))
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'cleanup_new_instance')
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'cleanup_access_rules')
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
if status == constants.TASK_STATE_DATA_COPYING_COMPLETED:
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'apply_new_access_rules',
|
|
mock.Mock(side_effect=Exception('fake')))
|
|
self.mock_object(manager.LOG, 'exception')
|
|
|
|
# run
|
|
if status == constants.TASK_STATE_DATA_COPYING_CANCELLED:
|
|
self.share_manager._migration_complete(
|
|
self.context, share, instance['id'], new_instance['id'])
|
|
else:
|
|
self.assertRaises(
|
|
exception.ShareMigrationFailed,
|
|
self.share_manager._migration_complete, self.context, share,
|
|
instance['id'], new_instance['id'])
|
|
|
|
# asserts
|
|
self.share_manager.db.share_instance_get.assert_has_calls([
|
|
mock.call(self.context, instance['id'], with_share_data=True),
|
|
mock.call(self.context, new_instance['id'], with_share_data=True)
|
|
])
|
|
self.share_manager.db.share_server_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), 'fake_server_id')
|
|
|
|
if status != 'other':
|
|
migration_api.ShareMigrationHelper.cleanup_new_instance.\
|
|
assert_called_once_with(new_instance)
|
|
migration_api.ShareMigrationHelper.cleanup_access_rules.\
|
|
assert_called_once_with(instance, server,
|
|
self.share_manager.driver)
|
|
if status == constants.TASK_STATE_MIGRATION_CANCELLED:
|
|
self.share_manager.db.share_instance_update.\
|
|
assert_called_once_with(self.context, instance['id'],
|
|
{'status': constants.STATUS_AVAILABLE})
|
|
self.share_manager.db.share_update.assert_called_once_with(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_CANCELLED})
|
|
if status == constants.TASK_STATE_DATA_COPYING_COMPLETED:
|
|
migration_api.ShareMigrationHelper.apply_new_access_rules.\
|
|
assert_called_once_with(new_instance)
|
|
self.assertTrue(manager.LOG.exception.called)
|
|
|
|
def test__migration_complete(self):
|
|
|
|
instance = db_utils.create_share_instance(
|
|
share_id='fake_id',
|
|
share_server_id='fake_server_id')
|
|
new_instance = db_utils.create_share_instance(share_id='fake_id')
|
|
share = db_utils.create_share(
|
|
id='fake_id',
|
|
task_state=constants.TASK_STATE_DATA_COPYING_COMPLETED)
|
|
server = 'fake_server'
|
|
|
|
# mocks
|
|
self.mock_object(self.share_manager.db, 'share_instance_get',
|
|
mock.Mock(side_effect=[instance, new_instance]))
|
|
self.mock_object(self.share_manager.db, 'share_server_get',
|
|
mock.Mock(return_value=server))
|
|
self.mock_object(self.share_manager.db, 'share_instance_update')
|
|
self.mock_object(self.share_manager.db, 'share_update')
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'delete_instance_and_wait')
|
|
self.mock_object(migration_api.ShareMigrationHelper,
|
|
'apply_new_access_rules')
|
|
|
|
# run
|
|
self.share_manager._migration_complete(
|
|
self.context, share, instance['id'], new_instance['id'])
|
|
|
|
# asserts
|
|
self.share_manager.db.share_instance_get.assert_has_calls([
|
|
mock.call(self.context, instance['id'], with_share_data=True),
|
|
mock.call(self.context, new_instance['id'], with_share_data=True)
|
|
])
|
|
self.share_manager.db.share_server_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), 'fake_server_id')
|
|
|
|
self.share_manager.db.share_instance_update.assert_has_calls([
|
|
mock.call(self.context, new_instance['id'],
|
|
{'status': constants.STATUS_AVAILABLE}),
|
|
mock.call(self.context, instance['id'],
|
|
{'status': constants.STATUS_INACTIVE})
|
|
])
|
|
self.share_manager.db.share_update.assert_has_calls([
|
|
mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_COMPLETING}),
|
|
mock.call(
|
|
self.context, share['id'],
|
|
{'task_state': constants.TASK_STATE_MIGRATION_SUCCESS}),
|
|
])
|
|
migration_api.ShareMigrationHelper.apply_new_access_rules.\
|
|
assert_called_once_with(new_instance)
|
|
migration_api.ShareMigrationHelper.delete_instance_and_wait.\
|
|
assert_called_once_with(instance)
|
|
|
|
def test_migration_cancel(self):
|
|
|
|
server = db_utils.create_share_server()
|
|
share = db_utils.create_share(
|
|
task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
|
|
share_server_id=server['id'])
|
|
|
|
self.mock_object(db, 'share_get', mock.Mock(return_value=share))
|
|
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(return_value=server))
|
|
|
|
self.mock_object(rpcapi.ShareAPI, 'migration_get_driver_info',
|
|
mock.Mock(return_value='migration_info'))
|
|
|
|
self.mock_object(self.share_manager.driver, 'migration_cancel')
|
|
|
|
self.share_manager.migration_cancel(self.context, share)
|
|
|
|
rpcapi.ShareAPI.migration_get_driver_info.assert_called_once_with(
|
|
self.context, share.instance)
|
|
|
|
self.share_manager.driver.migration_cancel.assert_called_once_with(
|
|
self.context, share.instance, server, 'migration_info')
|
|
|
|
def test_migration_cancel_invalid(self):
|
|
|
|
share = db_utils.create_share()
|
|
|
|
self.mock_object(db, 'share_get', mock.Mock(return_value=share))
|
|
|
|
self.assertRaises(
|
|
exception.InvalidShare, self.share_manager.migration_cancel,
|
|
self.context, share)
|
|
|
|
def test_migration_get_progress(self):
|
|
|
|
server = db_utils.create_share_server()
|
|
share = db_utils.create_share(
|
|
task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
|
|
share_server_id=server['id'])
|
|
|
|
expected = 'fake_progress'
|
|
|
|
self.mock_object(db, 'share_get', mock.Mock(return_value=share))
|
|
|
|
self.mock_object(db, 'share_server_get',
|
|
mock.Mock(return_value=server))
|
|
|
|
self.mock_object(rpcapi.ShareAPI, 'migration_get_driver_info',
|
|
mock.Mock(return_value='migration_info'))
|
|
|
|
self.mock_object(self.share_manager.driver, 'migration_get_progress',
|
|
mock.Mock(return_value=expected))
|
|
|
|
result = self.share_manager.migration_get_progress(self.context, share)
|
|
|
|
self.assertEqual(expected, result)
|
|
|
|
rpcapi.ShareAPI.migration_get_driver_info.assert_called_once_with(
|
|
self.context, share.instance)
|
|
|
|
self.share_manager.driver.migration_get_progress.\
|
|
assert_called_once_with(
|
|
self.context, share.instance, server, 'migration_info')
|
|
|
|
def test_migration_get_progress_invalid(self):
|
|
|
|
share = db_utils.create_share()
|
|
|
|
self.mock_object(db, 'share_get', mock.Mock(return_value=share))
|
|
|
|
self.assertRaises(
|
|
exception.InvalidShare, self.share_manager.migration_get_progress,
|
|
self.context, share)
|
|
|
|
def test_manage_snapshot_invalid_driver_mode(self):
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = True
|
|
share = db_utils.create_share()
|
|
snapshot = db_utils.create_snapshot(share_id=share['id'])
|
|
driver_options = {'fake': 'fake'}
|
|
|
|
self.assertRaises(
|
|
exception.InvalidDriverMode,
|
|
self.share_manager.manage_snapshot, self.context,
|
|
snapshot['id'], driver_options)
|
|
|
|
def test_manage_snapshot_invalid_snapshot(self):
|
|
fake_share_server = 'fake_share_server'
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
mock_get_share_server = self.mock_object(
|
|
self.share_manager,
|
|
'_get_share_server',
|
|
mock.Mock(return_value=fake_share_server))
|
|
share = db_utils.create_share()
|
|
snapshot = db_utils.create_snapshot(share_id=share['id'])
|
|
driver_options = {'fake': 'fake'}
|
|
mock_get = self.mock_object(self.share_manager.db,
|
|
'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
|
|
self.assertRaises(
|
|
exception.InvalidShareSnapshot,
|
|
self.share_manager.manage_snapshot, self.context,
|
|
snapshot['id'], driver_options)
|
|
|
|
mock_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['id'])
|
|
mock_get_share_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['share'])
|
|
|
|
def test_manage_snapshot_driver_exception(self):
|
|
CustomException = type('CustomException', (Exception,), {})
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
mock_manage = self.mock_object(self.share_manager.driver,
|
|
'manage_existing_snapshot',
|
|
mock.Mock(side_effect=CustomException))
|
|
mock_get_share_server = self.mock_object(self.share_manager,
|
|
'_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
share = db_utils.create_share()
|
|
snapshot = db_utils.create_snapshot(share_id=share['id'])
|
|
driver_options = {}
|
|
mock_get = self.mock_object(self.share_manager.db,
|
|
'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
|
|
self.assertRaises(
|
|
CustomException,
|
|
self.share_manager.manage_snapshot,
|
|
self.context, snapshot['id'], driver_options)
|
|
|
|
mock_manage.assert_called_once_with(mock.ANY, driver_options)
|
|
mock_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['id'])
|
|
mock_get_share_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['share'])
|
|
|
|
@ddt.data(
|
|
{'size': 1},
|
|
{'size': 2, 'name': 'fake'},
|
|
{'size': 3})
|
|
def test_manage_snapshot_valid_snapshot(self, driver_data):
|
|
mock_get_share_server = self.mock_object(self.share_manager,
|
|
'_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_update')
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.mock_object(quota.QUOTAS, 'reserve', mock.Mock())
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
mock_manage = self.mock_object(
|
|
self.share_manager.driver,
|
|
"manage_existing_snapshot",
|
|
mock.Mock(return_value=driver_data))
|
|
size = driver_data['size']
|
|
share = db_utils.create_share(size=size)
|
|
snapshot = db_utils.create_snapshot(share_id=share['id'], size=size)
|
|
snapshot_id = snapshot['id']
|
|
driver_options = {}
|
|
mock_get = self.mock_object(self.share_manager.db,
|
|
'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
|
|
self.share_manager.manage_snapshot(self.context, snapshot_id,
|
|
driver_options)
|
|
|
|
mock_manage.assert_called_once_with(mock.ANY, driver_options)
|
|
valid_snapshot_data = {
|
|
'status': constants.STATUS_AVAILABLE}
|
|
valid_snapshot_data.update(driver_data)
|
|
self.share_manager.db.share_snapshot_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
snapshot_id, valid_snapshot_data)
|
|
mock_get_share_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['share'])
|
|
mock_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot_id)
|
|
|
|
def test_unmanage_snapshot_invalid_driver_mode(self):
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = True
|
|
share = db_utils.create_share()
|
|
snapshot = db_utils.create_snapshot(share_id=share['id'])
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_update')
|
|
|
|
ret = self.share_manager.unmanage_snapshot(self.context,
|
|
snapshot['id'])
|
|
self.assertIsNone(ret)
|
|
self.share_manager.db.share_snapshot_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
snapshot['id'],
|
|
{'status': constants.STATUS_UNMANAGE_ERROR})
|
|
|
|
def test_unmanage_snapshot_invalid_snapshot(self):
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
mock_get_share_server = self.mock_object(
|
|
self.share_manager,
|
|
'_get_share_server',
|
|
mock.Mock(return_value='fake_share_server'))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_update')
|
|
share = db_utils.create_share()
|
|
snapshot = db_utils.create_snapshot(share_id=share['id'])
|
|
mock_get = self.mock_object(self.share_manager.db,
|
|
'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
|
|
ret = self.share_manager.unmanage_snapshot(self.context,
|
|
snapshot['id'])
|
|
|
|
self.assertIsNone(ret)
|
|
self.share_manager.db.share_snapshot_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext),
|
|
snapshot['id'],
|
|
{'status': constants.STATUS_UNMANAGE_ERROR})
|
|
mock_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['id'])
|
|
mock_get_share_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['share'])
|
|
|
|
def test_unmanage_snapshot_invalid_share(self):
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
mock_unmanage = mock.Mock(
|
|
side_effect=exception.UnmanageInvalidShareSnapshot(reason="fake"))
|
|
self.mock_object(self.share_manager.driver, "unmanage_snapshot",
|
|
mock_unmanage)
|
|
mock_get_share_server = self.mock_object(
|
|
self.share_manager,
|
|
'_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager.db, 'share_snapshot_update')
|
|
share = db_utils.create_share()
|
|
snapshot = db_utils.create_snapshot(share_id=share['id'])
|
|
mock_get = self.mock_object(self.share_manager.db,
|
|
'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
|
|
self.share_manager.unmanage_snapshot(self.context, snapshot['id'])
|
|
|
|
self.share_manager.db.share_snapshot_update.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['id'],
|
|
{'status': constants.STATUS_UNMANAGE_ERROR})
|
|
self.share_manager.driver.unmanage_snapshot.assert_called_once_with(
|
|
mock.ANY)
|
|
mock_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['id'])
|
|
mock_get_share_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['share'])
|
|
|
|
@ddt.data(False, True)
|
|
def test_unmanage_snapshot_valid_snapshot(self, quota_error):
|
|
if quota_error:
|
|
self.mock_object(quota.QUOTAS, 'reserve', mock.Mock(
|
|
side_effect=exception.ManilaException(message='error')))
|
|
mock_log_warning = self.mock_object(manager.LOG, 'warning')
|
|
self.mock_object(self.share_manager, 'driver')
|
|
self.share_manager.driver.driver_handles_share_servers = False
|
|
self.mock_object(self.share_manager.driver, "unmanage_snapshot")
|
|
mock_get_share_server = self.mock_object(
|
|
self.share_manager,
|
|
'_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
mock_snapshot_instance_destroy_call = self.mock_object(
|
|
self.share_manager.db, 'share_snapshot_instance_delete')
|
|
share = db_utils.create_share()
|
|
snapshot = db_utils.create_snapshot(share_id=share['id'])
|
|
mock_get = self.mock_object(self.share_manager.db,
|
|
'share_snapshot_get',
|
|
mock.Mock(return_value=snapshot))
|
|
|
|
self.share_manager.unmanage_snapshot(self.context, snapshot['id'])
|
|
|
|
self.share_manager.driver.unmanage_snapshot.assert_called_once_with(
|
|
mock.ANY)
|
|
mock_snapshot_instance_destroy_call.assert_called_once_with(
|
|
mock.ANY, snapshot['instance']['id'])
|
|
mock_get.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['id'])
|
|
mock_get_share_server.assert_called_once_with(
|
|
utils.IsAMatcher(context.RequestContext), snapshot['share'])
|
|
if quota_error:
|
|
self.assertTrue(mock_log_warning.called)
|
|
|
|
def _setup_crud_replicated_snapshot_data(self):
|
|
snapshot = fakes.fake_snapshot(create_instance=True)
|
|
snapshot_instance = fakes.fake_snapshot_instance(
|
|
base_snapshot=snapshot)
|
|
snapshot_instances = [snapshot['instance'], snapshot_instance]
|
|
replicas = [fake_replica(), fake_replica()]
|
|
return snapshot, snapshot_instances, replicas
|
|
|
|
def test_create_replicated_snapshot_driver_exception(self):
|
|
snapshot, snapshot_instances, replicas = (
|
|
self._setup_crud_replicated_snapshot_data()
|
|
)
|
|
self.mock_object(
|
|
db, 'share_snapshot_get', mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replicas))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'create_replicated_snapshot',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.create_replicated_snapshot,
|
|
self.context, snapshot['id'], share_id='fake_share')
|
|
mock_db_update_call.assert_has_calls([
|
|
mock.call(
|
|
self.context, snapshot['instance']['id'],
|
|
{'status': constants.STATUS_ERROR}),
|
|
mock.call(
|
|
self.context, snapshot_instances[1]['id'],
|
|
{'status': constants.STATUS_ERROR}),
|
|
])
|
|
|
|
@ddt.data(None, [])
|
|
def test_create_replicated_snapshot_driver_updates_nothing(self, retval):
|
|
snapshot, snapshot_instances, replicas = (
|
|
self._setup_crud_replicated_snapshot_data()
|
|
)
|
|
self.mock_object(
|
|
db, 'share_snapshot_get', mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replicas))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'create_replicated_snapshot',
|
|
mock.Mock(return_value=retval))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
|
|
return_value = self.share_manager.create_replicated_snapshot(
|
|
self.context, snapshot['id'], share_id='fake_share')
|
|
|
|
self.assertIsNone(return_value)
|
|
self.assertFalse(mock_db_update_call.called)
|
|
|
|
def test_create_replicated_snapshot_driver_updates_snapshot(self):
|
|
snapshot, snapshot_instances, replicas = (
|
|
self._setup_crud_replicated_snapshot_data()
|
|
)
|
|
snapshot_dict = {
|
|
'status': constants.STATUS_AVAILABLE,
|
|
'provider_location': 'spinners_end',
|
|
'progress': '100%',
|
|
'id': snapshot['instance']['id'],
|
|
}
|
|
self.mock_object(
|
|
db, 'share_snapshot_get', mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replicas))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'create_replicated_snapshot',
|
|
mock.Mock(return_value=[snapshot_dict]))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
|
|
return_value = self.share_manager.create_replicated_snapshot(
|
|
self.context, snapshot['id'], share_id='fake_share')
|
|
|
|
self.assertIsNone(return_value)
|
|
mock_db_update_call.assert_called_once_with(
|
|
self.context, snapshot['instance']['id'], snapshot_dict)
|
|
|
|
def delete_replicated_snapshot_driver_exception(self):
|
|
snapshot, snapshot_instances, replicas = (
|
|
self._setup_crud_replicated_snapshot_data()
|
|
)
|
|
self.mock_object(
|
|
db, 'share_snapshot_get', mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replicas))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'delete_replicated_snapshot',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
|
|
self.assertRaises(exception.ManilaException,
|
|
self.share_manager.delete_replicated_snapshot,
|
|
self.context, snapshot['id'], share_id='fake_share')
|
|
mock_db_update_call.assert_has_calls([
|
|
mock.call(
|
|
self.context, snapshot['instance']['id'],
|
|
{'status': constants.STATUS_ERROR_DELETING}),
|
|
mock.call(
|
|
self.context, snapshot_instances[1]['id'],
|
|
{'status': constants.STATUS_ERROR_DELETING}),
|
|
])
|
|
self.assertFalse(mock_db_delete_call.called)
|
|
|
|
def delete_replicated_snapshot_driver_exception_ignored_with_force(self):
|
|
snapshot, snapshot_instances, replicas = (
|
|
self._setup_crud_replicated_snapshot_data()
|
|
)
|
|
self.mock_object(
|
|
db, 'share_snapshot_get', mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replicas))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'delete_replicated_snapshot',
|
|
mock.Mock(side_effect=exception.ManilaException))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
|
|
retval = self.share_manager.delete_replicated_snapshot(
|
|
self.context, snapshot['id'], share_id='fake_share')
|
|
|
|
self.assertIsNone(retval)
|
|
mock_db_delete_call.assert_has_calls([
|
|
mock.call(
|
|
self.context, snapshot['instance']['id']),
|
|
mock.call(
|
|
self.context, snapshot_instances[1]['id']),
|
|
])
|
|
self.assertFalse(mock_db_update_call.called)
|
|
|
|
@ddt.data(None, [])
|
|
def delete_replicated_snapshot_driver_updates_nothing(self, retval):
|
|
snapshot, snapshot_instances, replicas = (
|
|
self._setup_crud_replicated_snapshot_data()
|
|
)
|
|
self.mock_object(
|
|
db, 'share_snapshot_get', mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replicas))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'delete_replicated_snapshot',
|
|
mock.Mock(return_value=retval))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
|
|
return_value = self.share_manager.delete_replicated_snapshot(
|
|
self.context, snapshot['id'], share_id='fake_share')
|
|
|
|
self.assertIsNone(return_value)
|
|
self.assertFalse(mock_db_delete_call.called)
|
|
self.assertFalse(mock_db_update_call.called)
|
|
|
|
def delete_replicated_snapshot_driver_deletes_snapshots(self):
|
|
snapshot, snapshot_instances, replicas = (
|
|
self._setup_crud_replicated_snapshot_data()
|
|
)
|
|
retval = [{
|
|
'status': constants.STATUS_DELETED,
|
|
'id': snapshot['instance']['id'],
|
|
}]
|
|
self.mock_object(
|
|
db, 'share_snapshot_get', mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replicas))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'delete_replicated_snapshot',
|
|
mock.Mock(return_value=retval))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
|
|
return_value = self.share_manager.delete_replicated_snapshot(
|
|
self.context, snapshot['id'], share_id='fake_share')
|
|
|
|
self.assertIsNone(return_value)
|
|
mock_db_delete_call.assert_called_once_with(
|
|
self.context, snapshot['instance']['id'])
|
|
self.assertFalse(mock_db_update_call.called)
|
|
|
|
@ddt.data(True, False)
|
|
def delete_replicated_snapshot_drv_del_and_updates_snapshots(self, force):
|
|
snapshot, snapshot_instances, replicas = (
|
|
self._setup_crud_replicated_snapshot_data()
|
|
)
|
|
updated_instance_details = {
|
|
'status': constants.STATUS_ERROR,
|
|
'id': snapshot_instances[1]['id'],
|
|
'provider_location': 'azkaban',
|
|
}
|
|
retval = [
|
|
{
|
|
'status': constants.STATUS_DELETED,
|
|
'id': snapshot['instance']['id'],
|
|
},
|
|
]
|
|
retval.append(updated_instance_details)
|
|
self.mock_object(
|
|
db, 'share_snapshot_get', mock.Mock(return_value=snapshot))
|
|
self.mock_object(self.share_manager, '_get_share_server')
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=replicas))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'delete_replicated_snapshot',
|
|
mock.Mock(return_value=retval))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
|
|
return_value = self.share_manager.delete_replicated_snapshot(
|
|
self.context, snapshot['id'], share_id='fake_share', force=force)
|
|
|
|
self.assertIsNone(return_value)
|
|
if force:
|
|
self.assertTrue(2, mock_db_delete_call.call_count)
|
|
self.assertFalse(mock_db_update_call.called)
|
|
else:
|
|
mock_db_delete_call.assert_called_once_with(
|
|
self.context, snapshot['instance']['id'])
|
|
mock_db_update_call.assert_called_once_with(
|
|
self.context, snapshot_instances[1]['id'],
|
|
updated_instance_details)
|
|
|
|
def test_periodic_share_replica_snapshot_update(self):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
replicas = 3 * [
|
|
fake_replica(host='malfoy@manor#_pool0',
|
|
replica_state=constants.REPLICA_STATE_IN_SYNC)
|
|
]
|
|
replicas.append(fake_replica(replica_state=constants.STATUS_ACTIVE))
|
|
snapshot = fakes.fake_snapshot(create_instance=True,
|
|
status=constants.STATUS_DELETING)
|
|
snapshot_instances = 3 * [
|
|
fakes.fake_snapshot_instance(base_snapshot=snapshot)
|
|
]
|
|
self.mock_object(
|
|
db, 'share_replicas_get_all', mock.Mock(return_value=replicas))
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(return_value=snapshot_instances))
|
|
mock_snapshot_update_call = self.mock_object(
|
|
self.share_manager, '_update_replica_snapshot')
|
|
|
|
retval = self.share_manager.periodic_share_replica_snapshot_update(
|
|
self.context)
|
|
|
|
self.assertIsNone(retval)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
self.assertEqual(0, mock_snapshot_update_call.call_count)
|
|
|
|
@ddt.data(True, False)
|
|
def test_periodic_share_replica_snapshot_update_nothing_to_update(
|
|
self, has_instances):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
replicas = 3 * [
|
|
fake_replica(host='malfoy@manor#_pool0',
|
|
replica_state=constants.REPLICA_STATE_IN_SYNC)
|
|
]
|
|
replicas.append(fake_replica(replica_state=constants.STATUS_ACTIVE))
|
|
snapshot = fakes.fake_snapshot(create_instance=True,
|
|
status=constants.STATUS_DELETING)
|
|
snapshot_instances = 3 * [
|
|
fakes.fake_snapshot_instance(base_snapshot=snapshot)
|
|
]
|
|
self.mock_object(db, 'share_replicas_get_all',
|
|
mock.Mock(side_effect=[[], replicas]))
|
|
self.mock_object(db, 'share_snapshot_instance_get_all_with_filters',
|
|
mock.Mock(side_effect=[snapshot_instances, []]))
|
|
mock_snapshot_update_call = self.mock_object(
|
|
self.share_manager, '_update_replica_snapshot')
|
|
|
|
retval = self.share_manager.periodic_share_replica_snapshot_update(
|
|
self.context)
|
|
|
|
self.assertIsNone(retval)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
self.assertEqual(0, mock_snapshot_update_call.call_count)
|
|
|
|
def test__update_replica_snapshot_replica_deleted_from_database(self):
|
|
replica_not_found = exception.ShareReplicaNotFound(replica_id='xyzzy')
|
|
self.mock_object(db, 'share_replica_get', mock.Mock(
|
|
side_effect=replica_not_found))
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
mock_driver_update_call = self.mock_object(
|
|
self.share_manager.driver, 'update_replicated_snapshot')
|
|
snaphot_instance = fakes.fake_snapshot_instance()
|
|
|
|
retval = self.share_manager._update_replica_snapshot(
|
|
self.context, snaphot_instance)
|
|
|
|
self.assertIsNone(retval)
|
|
mock_db_delete_call.assert_called_once_with(
|
|
self.context, snaphot_instance['id'])
|
|
self.assertFalse(mock_driver_update_call.called)
|
|
self.assertFalse(mock_db_update_call.called)
|
|
|
|
def test__update_replica_snapshot_both_deleted_from_database(self):
|
|
replica_not_found = exception.ShareReplicaNotFound(replica_id='xyzzy')
|
|
instance_not_found = exception.ShareSnapshotInstanceNotFound(
|
|
instance_id='spoon!')
|
|
self.mock_object(db, 'share_replica_get', mock.Mock(
|
|
side_effect=replica_not_found))
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete', mock.Mock(
|
|
side_effect=instance_not_found))
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
mock_driver_update_call = self.mock_object(
|
|
self.share_manager.driver, 'update_replicated_snapshot')
|
|
snapshot_instance = fakes.fake_snapshot_instance()
|
|
|
|
retval = self.share_manager._update_replica_snapshot(
|
|
self.context, snapshot_instance)
|
|
|
|
self.assertIsNone(retval)
|
|
mock_db_delete_call.assert_called_once_with(
|
|
self.context, snapshot_instance['id'])
|
|
self.assertFalse(mock_driver_update_call.called)
|
|
self.assertFalse(mock_db_update_call.called)
|
|
|
|
def test__update_replica_snapshot_driver_raises_Not_Found_exception(self):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
replica = fake_replica()
|
|
snapshot_instance = fakes.fake_snapshot_instance(
|
|
status=constants.STATUS_DELETING)
|
|
self.mock_object(
|
|
db, 'share_replica_get', mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica]))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(
|
|
self.share_manager.driver, 'update_replicated_snapshot',
|
|
mock.Mock(
|
|
side_effect=exception.SnapshotResourceNotFound(name='abc')))
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
|
|
retval = self.share_manager._update_replica_snapshot(
|
|
self.context, snapshot_instance, replica_snapshots=None)
|
|
|
|
self.assertIsNone(retval)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
mock_db_delete_call.assert_called_once_with(
|
|
self.context, snapshot_instance['id'])
|
|
self.assertFalse(mock_db_update_call.called)
|
|
|
|
@ddt.data(exception.NotFound, exception.ManilaException)
|
|
def test__update_replica_snapshot_driver_raises_other_exception(self, exc):
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
mock_info_log = self.mock_object(manager.LOG, 'info')
|
|
mock_exception_log = self.mock_object(manager.LOG, 'exception')
|
|
replica = fake_replica()
|
|
snapshot_instance = fakes.fake_snapshot_instance(
|
|
status=constants.STATUS_CREATING)
|
|
self.mock_object(
|
|
db, 'share_replica_get', mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica]))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager.driver,
|
|
'update_replicated_snapshot',
|
|
mock.Mock(side_effect=exc))
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
|
|
retval = self.share_manager._update_replica_snapshot(
|
|
self.context, snapshot_instance)
|
|
|
|
self.assertIsNone(retval)
|
|
self.assertEqual(1, mock_exception_log.call_count)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
self.assertFalse(mock_info_log.called)
|
|
mock_db_update_call.assert_called_once_with(
|
|
self.context, snapshot_instance['id'], {'status': 'error'})
|
|
self.assertFalse(mock_db_delete_call.called)
|
|
|
|
@ddt.data(True, False)
|
|
def test__update_replica_snapshot_driver_updates_replica(self, update):
|
|
replica = fake_replica()
|
|
snapshot_instance = fakes.fake_snapshot_instance()
|
|
driver_update = {}
|
|
if update:
|
|
driver_update = {
|
|
'id': snapshot_instance['id'],
|
|
'provider_location': 'knockturn_alley',
|
|
'status': constants.STATUS_AVAILABLE,
|
|
}
|
|
mock_debug_log = self.mock_object(manager.LOG, 'debug')
|
|
mock_info_log = self.mock_object(manager.LOG, 'info')
|
|
self.mock_object(
|
|
db, 'share_replica_get', mock.Mock(return_value=replica))
|
|
self.mock_object(db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(db, 'share_snapshot_instance_get',
|
|
mock.Mock(return_value=snapshot_instance))
|
|
self.mock_object(db, 'share_replicas_get_all_by_share',
|
|
mock.Mock(return_value=[replica]))
|
|
self.mock_object(self.share_manager, '_get_share_server',
|
|
mock.Mock(return_value=None))
|
|
self.mock_object(self.share_manager.driver,
|
|
'update_replicated_snapshot',
|
|
mock.Mock(return_value=driver_update))
|
|
mock_db_delete_call = self.mock_object(
|
|
db, 'share_snapshot_instance_delete')
|
|
mock_db_update_call = self.mock_object(
|
|
db, 'share_snapshot_instance_update')
|
|
|
|
retval = self.share_manager._update_replica_snapshot(
|
|
self.context, snapshot_instance, replica_snapshots=None)
|
|
|
|
driver_update['progress'] = '100%'
|
|
self.assertIsNone(retval)
|
|
self.assertEqual(1, mock_debug_log.call_count)
|
|
self.assertFalse(mock_info_log.called)
|
|
if update:
|
|
mock_db_update_call.assert_called_once_with(
|
|
self.context, snapshot_instance['id'], driver_update)
|
|
else:
|
|
self.assertFalse(mock_db_update_call.called)
|
|
self.assertFalse(mock_db_delete_call.called)
|
|
|
|
|
|
@ddt.ddt
|
|
class HookWrapperTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(HookWrapperTestCase, self).setUp()
|
|
self.configuration = mock.Mock()
|
|
self.configuration.safe_get.return_value = True
|
|
|
|
@manager.add_hooks
|
|
def _fake_wrapped_method(self, some_arg, some_kwarg):
|
|
return "foo"
|
|
|
|
def test_hooks_enabled(self):
|
|
self.hooks = [mock.Mock(return_value=i) for i in range(2)]
|
|
|
|
result = self._fake_wrapped_method(
|
|
"some_arg", some_kwarg="some_kwarg_value")
|
|
|
|
self.assertEqual("foo", result)
|
|
for i, mock_hook in enumerate(self.hooks):
|
|
mock_hook.execute_pre_hook.assert_called_once_with(
|
|
"some_arg",
|
|
func_name="_fake_wrapped_method",
|
|
some_kwarg="some_kwarg_value")
|
|
mock_hook.execute_post_hook.assert_called_once_with(
|
|
"some_arg",
|
|
func_name="_fake_wrapped_method",
|
|
driver_action_results="foo",
|
|
pre_hook_data=self.hooks[i].execute_pre_hook.return_value,
|
|
some_kwarg="some_kwarg_value")
|
|
|
|
def test_hooks_disabled(self):
|
|
self.hooks = []
|
|
|
|
result = self._fake_wrapped_method(
|
|
"some_arg", some_kwarg="some_kwarg_value")
|
|
|
|
self.assertEqual("foo", result)
|
|
for mock_hook in self.hooks:
|
|
self.assertFalse(mock_hook.execute_pre_hook.called)
|
|
self.assertFalse(mock_hook.execute_post_hook.called)
|