9093275886
rally.plugins.openstack -> rally_openstack - rally_openstack.context -> rally_openstack.contexts rally.plugins.workloads -> rally_openstack/workloads rally.consts -> rally_openstack.consts TODO: fix pep8
431 lines
17 KiB
Python
431 lines
17 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.
|
|
|
|
import mock
|
|
|
|
from rally.common import utils
|
|
from rally_openstack.cleanup import base
|
|
from rally_openstack.cleanup import manager
|
|
from tests.unit import test
|
|
|
|
|
|
BASE = "rally_openstack.cleanup.manager"
|
|
|
|
|
|
class SeekAndDestroyTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(SeekAndDestroyTestCase, self).setUp()
|
|
# clear out the client cache
|
|
manager.SeekAndDestroy.cache = {}
|
|
|
|
def test__get_cached_client(self):
|
|
api_versions = {"cinder": {"version": "1", "service_type": "volume"}}
|
|
|
|
destroyer = manager.SeekAndDestroy(None, None, None,
|
|
api_versions=api_versions)
|
|
cred = mock.Mock()
|
|
user = {"credential": cred}
|
|
|
|
clients = destroyer._get_cached_client(user)
|
|
self.assertIs(cred.clients.return_value, clients)
|
|
cred.clients.assert_called_once_with(api_info=api_versions)
|
|
|
|
self.assertIsNone(destroyer._get_cached_client(None))
|
|
|
|
@mock.patch("%s.LOG" % BASE)
|
|
def test__delete_single_resource(self, mock_log):
|
|
mock_resource = mock.MagicMock(_max_attempts=3, _timeout=10,
|
|
_interval=0.01)
|
|
mock_resource.delete.side_effect = [Exception, Exception, True]
|
|
mock_resource.is_deleted.side_effect = [False, False, True]
|
|
|
|
manager.SeekAndDestroy(None, None, None)._delete_single_resource(
|
|
mock_resource)
|
|
|
|
mock_resource.delete.assert_has_calls([mock.call()] * 3)
|
|
self.assertEqual(3, mock_resource.delete.call_count)
|
|
mock_resource.is_deleted.assert_has_calls([mock.call()] * 3)
|
|
self.assertEqual(3, mock_resource.is_deleted.call_count)
|
|
|
|
# NOTE(boris-42): No logs and no exceptions means no bugs!
|
|
self.assertEqual(0, mock_log.call_count)
|
|
|
|
@mock.patch("%s.LOG" % BASE)
|
|
def test__delete_single_resource_timeout(self, mock_log):
|
|
|
|
mock_resource = mock.MagicMock(_max_attempts=1, _timeout=0.02,
|
|
_interval=0.025)
|
|
|
|
mock_resource.delete.return_value = True
|
|
mock_resource.is_deleted.side_effect = [False, False, True]
|
|
|
|
manager.SeekAndDestroy(None, None, None)._delete_single_resource(
|
|
mock_resource)
|
|
|
|
mock_resource.delete.assert_called_once_with()
|
|
mock_resource.is_deleted.assert_called_once_with()
|
|
|
|
self.assertEqual(1, mock_log.warning.call_count)
|
|
|
|
@mock.patch("%s.LOG" % BASE)
|
|
def test__delete_single_resource_excpetion_in_is_deleted(self, mock_log):
|
|
mock_resource = mock.MagicMock(_max_attempts=3, _timeout=10,
|
|
_interval=0)
|
|
mock_resource.delete.return_value = True
|
|
mock_resource.is_deleted.side_effect = [Exception] * 4
|
|
manager.SeekAndDestroy(None, None, None)._delete_single_resource(
|
|
mock_resource)
|
|
|
|
mock_resource.delete.assert_called_once_with()
|
|
self.assertEqual(4, mock_resource.is_deleted.call_count)
|
|
|
|
self.assertEqual(1, mock_log.warning.call_count)
|
|
self.assertEqual(4, mock_log.exception.call_count)
|
|
|
|
def _manager(self, list_side_effect, **kw):
|
|
mock_mgr = mock.MagicMock()
|
|
mock_mgr().list.side_effect = list_side_effect
|
|
mock_mgr.reset_mock()
|
|
|
|
for k, v in kw.items():
|
|
setattr(mock_mgr, k, v)
|
|
|
|
return mock_mgr
|
|
|
|
@mock.patch("%s.SeekAndDestroy._get_cached_client" % BASE)
|
|
def test__publisher_admin(self, mock__get_cached_client):
|
|
mock_mgr = self._manager([Exception, Exception, [1, 2, 3]],
|
|
_perform_for_admin_only=False)
|
|
admin = mock.MagicMock()
|
|
publish = manager.SeekAndDestroy(mock_mgr, admin, None)._publisher
|
|
|
|
queue = []
|
|
publish(queue)
|
|
mock__get_cached_client.assert_called_once_with(admin)
|
|
mock_mgr.assert_called_once_with(
|
|
admin=mock__get_cached_client.return_value)
|
|
self.assertEqual(queue, [(admin, None, x) for x in range(1, 4)])
|
|
|
|
@mock.patch("%s.SeekAndDestroy._get_cached_client" % BASE)
|
|
def test__publisher_admin_only(self, mock__get_cached_client):
|
|
mock_mgr = self._manager([Exception, Exception, [1, 2, 3]],
|
|
_perform_for_admin_only=True)
|
|
admin = mock.MagicMock()
|
|
publish = manager.SeekAndDestroy(
|
|
mock_mgr, admin, ["u1", "u2"])._publisher
|
|
|
|
queue = []
|
|
publish(queue)
|
|
mock__get_cached_client.assert_called_once_with(admin)
|
|
mock_mgr.assert_called_once_with(
|
|
admin=mock__get_cached_client.return_value)
|
|
self.assertEqual(queue, [(admin, None, x) for x in range(1, 4)])
|
|
|
|
@mock.patch("%s.SeekAndDestroy._get_cached_client" % BASE)
|
|
def test__publisher_user_resource(self, mock__get_cached_client):
|
|
mock_mgr = self._manager([Exception, Exception, [1, 2, 3],
|
|
Exception, Exception, [4, 5]],
|
|
_perform_for_admin_only=False,
|
|
_tenant_resource=True)
|
|
|
|
admin = mock.MagicMock()
|
|
users = [{"tenant_id": 1, "id": 1}, {"tenant_id": 2, "id": 2}]
|
|
publish = manager.SeekAndDestroy(mock_mgr, admin, users)._publisher
|
|
|
|
queue = []
|
|
publish(queue)
|
|
|
|
mock_client = mock__get_cached_client.return_value
|
|
mock_mgr.assert_has_calls([
|
|
mock.call(admin=mock_client, user=mock_client,
|
|
tenant_uuid=users[0]["tenant_id"]),
|
|
mock.call().list(),
|
|
mock.call().list(),
|
|
mock.call().list(),
|
|
mock.call(admin=mock_client, user=mock_client,
|
|
tenant_uuid=users[1]["tenant_id"]),
|
|
mock.call().list(),
|
|
mock.call().list()
|
|
])
|
|
mock__get_cached_client.assert_has_calls([
|
|
mock.call(admin),
|
|
mock.call(users[0]),
|
|
mock.call(users[1])
|
|
])
|
|
expected_queue = [(admin, users[0], x) for x in range(1, 4)]
|
|
expected_queue += [(admin, users[1], x) for x in range(4, 6)]
|
|
self.assertEqual(expected_queue, queue)
|
|
|
|
@mock.patch("%s.LOG" % BASE)
|
|
@mock.patch("%s.SeekAndDestroy._get_cached_client" % BASE)
|
|
def test__gen_publisher_tenant_resource(self, mock__get_cached_client,
|
|
mock_log):
|
|
mock_mgr = self._manager([Exception, [1, 2, 3],
|
|
Exception, Exception, Exception,
|
|
["this shouldn't be in results"]],
|
|
_perform_for_admin_only=False,
|
|
_tenant_resource=True)
|
|
users = [{"tenant_id": 1, "id": 1},
|
|
{"tenant_id": 1, "id": 2},
|
|
{"tenant_id": 2, "id": 3}]
|
|
|
|
publish = manager.SeekAndDestroy(
|
|
mock_mgr, None, users)._publisher
|
|
|
|
queue = []
|
|
publish(queue)
|
|
|
|
mock_client = mock__get_cached_client.return_value
|
|
mock_mgr.assert_has_calls([
|
|
mock.call(admin=mock_client, user=mock_client,
|
|
tenant_uuid=users[0]["tenant_id"]),
|
|
mock.call().list(),
|
|
mock.call().list(),
|
|
mock.call(admin=mock_client, user=mock_client,
|
|
tenant_uuid=users[2]["tenant_id"]),
|
|
mock.call().list(),
|
|
mock.call().list(),
|
|
mock.call().list()
|
|
])
|
|
mock__get_cached_client.assert_has_calls([
|
|
mock.call(None),
|
|
mock.call(users[0]),
|
|
mock.call(users[2])
|
|
])
|
|
self.assertEqual(queue, [(None, users[0], x) for x in range(1, 4)])
|
|
self.assertTrue(mock_log.warning.mock_called)
|
|
self.assertTrue(mock_log.exception.mock_called)
|
|
|
|
@mock.patch("rally.common.utils.name_matches_object")
|
|
@mock.patch("%s.SeekAndDestroy._get_cached_client" % BASE)
|
|
@mock.patch("%s.SeekAndDestroy._delete_single_resource" % BASE)
|
|
def test__consumer(self, mock__delete_single_resource,
|
|
mock__get_cached_client,
|
|
mock_name_matches_object):
|
|
mock_mgr = mock.MagicMock(__name__="Test")
|
|
resource_classes = [mock.Mock()]
|
|
task_id = "task_id"
|
|
mock_name_matches_object.return_value = True
|
|
|
|
consumer = manager.SeekAndDestroy(
|
|
mock_mgr, None, None,
|
|
resource_classes=resource_classes,
|
|
task_id=task_id)._consumer
|
|
|
|
admin = mock.MagicMock()
|
|
user1 = {"id": "a", "tenant_id": "uuid1"}
|
|
cache = {}
|
|
|
|
consumer(cache, (admin, user1, "res"))
|
|
mock_mgr.assert_called_once_with(
|
|
resource="res",
|
|
admin=mock__get_cached_client.return_value,
|
|
user=mock__get_cached_client.return_value,
|
|
tenant_uuid=user1["tenant_id"])
|
|
mock__get_cached_client.assert_has_calls([
|
|
mock.call(admin),
|
|
mock.call(user1)
|
|
])
|
|
mock__delete_single_resource.assert_called_once_with(
|
|
mock_mgr.return_value)
|
|
|
|
mock_mgr.reset_mock()
|
|
mock__get_cached_client.reset_mock()
|
|
mock__delete_single_resource.reset_mock()
|
|
mock_name_matches_object.reset_mock()
|
|
|
|
consumer(cache, (admin, None, "res2"))
|
|
mock_mgr.assert_called_once_with(
|
|
resource="res2",
|
|
admin=mock__get_cached_client.return_value,
|
|
user=mock__get_cached_client.return_value,
|
|
tenant_uuid=None)
|
|
|
|
mock__get_cached_client.assert_has_calls([
|
|
mock.call(admin),
|
|
mock.call(None)
|
|
])
|
|
mock__delete_single_resource.assert_called_once_with(
|
|
mock_mgr.return_value)
|
|
|
|
@mock.patch("rally.common.utils.name_matches_object")
|
|
@mock.patch("%s.SeekAndDestroy._get_cached_client" % BASE)
|
|
@mock.patch("%s.SeekAndDestroy._delete_single_resource" % BASE)
|
|
def test__consumer_with_noname_resource(self, mock__delete_single_resource,
|
|
mock__get_cached_client,
|
|
mock_name_matches_object):
|
|
mock_mgr = mock.MagicMock(__name__="Test")
|
|
mock_mgr.return_value.name.return_value = True
|
|
task_id = "task_id"
|
|
mock_name_matches_object.return_value = False
|
|
|
|
consumer = manager.SeekAndDestroy(mock_mgr, None, None,
|
|
task_id=task_id)._consumer
|
|
|
|
consumer(None, (None, None, "res"))
|
|
self.assertFalse(mock__delete_single_resource.called)
|
|
|
|
mock_mgr.return_value.name.return_value = base.NoName("foo")
|
|
consumer(None, (None, None, "res"))
|
|
mock__delete_single_resource.assert_called_once_with(
|
|
mock_mgr.return_value)
|
|
|
|
@mock.patch("%s.broker.run" % BASE)
|
|
def test_exterminate(self, mock_broker_run):
|
|
manager_cls = mock.MagicMock(_threads=5)
|
|
cleaner = manager.SeekAndDestroy(manager_cls, None, None)
|
|
cleaner._publisher = mock.Mock()
|
|
cleaner._consumer = mock.Mock()
|
|
cleaner.exterminate()
|
|
|
|
mock_broker_run.assert_called_once_with(cleaner._publisher,
|
|
cleaner._consumer,
|
|
consumers_count=5)
|
|
|
|
|
|
class ResourceManagerTestCase(test.TestCase):
|
|
|
|
def _get_res_mock(self, **kw):
|
|
_mock = mock.MagicMock()
|
|
for k, v in kw.items():
|
|
setattr(_mock, k, v)
|
|
return _mock
|
|
|
|
def _list_res_names_helper(self, names, admin_required, mock_iter):
|
|
self.assertEqual(set(names),
|
|
manager.list_resource_names(admin_required))
|
|
mock_iter.assert_called_once_with(base.ResourceManager)
|
|
mock_iter.reset_mock()
|
|
|
|
@mock.patch("%s.discover.itersubclasses" % BASE)
|
|
def test_list_resource_names(self, mock_itersubclasses):
|
|
mock_itersubclasses.return_value = [
|
|
self._get_res_mock(_service="fake", _resource="1",
|
|
_admin_required=True),
|
|
self._get_res_mock(_service="fake", _resource="2",
|
|
_admin_required=False),
|
|
self._get_res_mock(_service="other", _resource="2",
|
|
_admin_required=False)
|
|
]
|
|
|
|
self._list_res_names_helper(
|
|
["fake", "other", "fake.1", "fake.2", "other.2"],
|
|
None, mock_itersubclasses)
|
|
self._list_res_names_helper(
|
|
["fake", "fake.1"],
|
|
True, mock_itersubclasses)
|
|
self._list_res_names_helper(
|
|
["fake", "other", "fake.2", "other.2"],
|
|
False, mock_itersubclasses)
|
|
|
|
@mock.patch("%s.discover.itersubclasses" % BASE)
|
|
def test_find_resource_managers(self, mock_itersubclasses):
|
|
mock_itersubclasses.return_value = [
|
|
self._get_res_mock(_service="fake", _resource="1", _order=1,
|
|
_admin_required=True),
|
|
self._get_res_mock(_service="fake", _resource="2", _order=3,
|
|
_admin_required=False),
|
|
self._get_res_mock(_service="other", _resource="2", _order=2,
|
|
_admin_required=False)
|
|
]
|
|
|
|
self.assertEqual(mock_itersubclasses.return_value[0:2],
|
|
manager.find_resource_managers(names=["fake"]))
|
|
|
|
self.assertEqual(mock_itersubclasses.return_value[0:1],
|
|
manager.find_resource_managers(names=["fake.1"]))
|
|
|
|
self.assertEqual(
|
|
[mock_itersubclasses.return_value[0],
|
|
mock_itersubclasses.return_value[2],
|
|
mock_itersubclasses.return_value[1]],
|
|
manager.find_resource_managers(names=["fake", "other"]))
|
|
|
|
self.assertEqual(mock_itersubclasses.return_value[0:1],
|
|
manager.find_resource_managers(names=["fake"],
|
|
admin_required=True))
|
|
self.assertEqual(mock_itersubclasses.return_value[1:2],
|
|
manager.find_resource_managers(names=["fake"],
|
|
admin_required=False))
|
|
|
|
@mock.patch("rally.common.plugin.discover.itersubclasses")
|
|
@mock.patch("%s.SeekAndDestroy" % BASE)
|
|
@mock.patch("%s.find_resource_managers" % BASE,
|
|
return_value=[mock.MagicMock(), mock.MagicMock()])
|
|
def test_cleanup(self, mock_find_resource_managers, mock_seek_and_destroy,
|
|
mock_itersubclasses):
|
|
class A(utils.RandomNameGeneratorMixin):
|
|
pass
|
|
|
|
class B(object):
|
|
pass
|
|
|
|
mock_itersubclasses.return_value = [A, B]
|
|
|
|
manager.cleanup(names=["a", "b"], admin_required=True,
|
|
admin="admin", users=["user"],
|
|
superclass=A,
|
|
task_id="task_id")
|
|
|
|
mock_find_resource_managers.assert_called_once_with(["a", "b"], True)
|
|
|
|
mock_seek_and_destroy.assert_has_calls([
|
|
mock.call(mock_find_resource_managers.return_value[0], "admin",
|
|
["user"], api_versions=None,
|
|
resource_classes=[A], task_id="task_id"),
|
|
mock.call().exterminate(),
|
|
mock.call(mock_find_resource_managers.return_value[1], "admin",
|
|
["user"], api_versions=None,
|
|
resource_classes=[A], task_id="task_id"),
|
|
mock.call().exterminate()
|
|
])
|
|
|
|
@mock.patch("rally.common.plugin.discover.itersubclasses")
|
|
@mock.patch("%s.SeekAndDestroy" % BASE)
|
|
@mock.patch("%s.find_resource_managers" % BASE,
|
|
return_value=[mock.MagicMock(), mock.MagicMock()])
|
|
def test_cleanup_with_api_versions(self,
|
|
mock_find_resource_managers,
|
|
mock_seek_and_destroy,
|
|
mock_itersubclasses):
|
|
class A(utils.RandomNameGeneratorMixin):
|
|
pass
|
|
|
|
class B(object):
|
|
pass
|
|
|
|
mock_itersubclasses.return_value = [A, B]
|
|
|
|
api_versions = {"cinder": {"version": "1", "service_type": "volume"}}
|
|
manager.cleanup(names=["a", "b"], admin_required=True,
|
|
admin="admin", users=["user"],
|
|
api_versions=api_versions,
|
|
superclass=utils.RandomNameGeneratorMixin,
|
|
task_id="task_id")
|
|
|
|
mock_find_resource_managers.assert_called_once_with(["a", "b"], True)
|
|
|
|
mock_seek_and_destroy.assert_has_calls([
|
|
mock.call(mock_find_resource_managers.return_value[0], "admin",
|
|
["user"], api_versions=api_versions,
|
|
resource_classes=[A], task_id="task_id"),
|
|
mock.call().exterminate(),
|
|
mock.call(mock_find_resource_managers.return_value[1], "admin",
|
|
["user"], api_versions=api_versions,
|
|
resource_classes=[A], task_id="task_id"),
|
|
mock.call().exterminate()
|
|
])
|