masakari/masakari/tests/unit/objects/test_hosts.py

307 lines
12 KiB
Python

# Copyright 2016 NTT DATA
# 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 copy
from unittest import mock
from oslo_utils import timeutils
from masakari.api import utils as api_utils
from masakari import db
from masakari import exception
from masakari.objects import fields
from masakari.objects import host
from masakari.objects import segment
from masakari.tests.unit.objects import test_objects
from masakari.tests import uuidsentinel
NOW = timeutils.utcnow().replace(microsecond=0)
fake_segment_dict = {
'name': 'fake_segment',
'recovery_method': 'auto',
'description': 'fake',
'service_type': 'CINDER',
'id': 123,
'uuid': uuidsentinel.fake_segment,
'created_at': NOW,
'updated_at': None,
'deleted_at': None,
'deleted': False
}
def _fake_host(**kwargs):
fake_host = {
'created_at': NOW,
'updated_at': None,
'deleted_at': None,
'deleted': False,
'id': 123,
'uuid': uuidsentinel.fake_host,
'name': 'fake-host',
'reserved': False,
'on_maintenance': False,
'control_attributes': 'fake_control_attributes',
'type': 'SSH',
'failover_segment': fake_segment_dict,
'failover_segment_id': uuidsentinel.fake_segment,
}
fake_host.update(kwargs)
return fake_host
fake_host = _fake_host()
class TestHostObject(test_objects._LocalTest):
def _compare_segment_and_host_data(self, obj):
self.compare_obj(obj.failover_segment, fake_segment_dict)
self.assertEqual(obj.name, fake_host.get('name'))
self.assertEqual(obj.reserved, fake_host.get('reserved'))
self.assertEqual(obj.on_maintenance, fake_host.get('on_maintenance'))
self.assertEqual(obj.type, fake_host.get('type'))
self.assertEqual(obj.control_attributes, fake_host.get('control_attri'
'butes'))
self.assertEqual(obj.id, 123)
def _test_query(self, db_method, obj_method, *args, **kwargs):
with mock.patch.object(db, db_method) as mock_db:
db_exception = kwargs.pop('db_exception', None)
if db_exception:
mock_db.side_effect = db_exception
else:
mock_db.return_value = fake_host
obj = getattr(host.Host, obj_method)(self.context, *args, **kwargs)
if db_exception:
self.assertIsNone(obj)
self._compare_segment_and_host_data(obj)
def test_get_by_id(self):
self._test_query('host_get_by_id', 'get_by_id', 123)
def test_get_by_uuid(self):
self._test_query('host_get_by_uuid', 'get_by_uuid',
uuidsentinel.fake_segment)
def test_get_by_name(self):
self._test_query('host_get_by_name', 'get_by_name',
'fake-host')
def _host_create_attributes(self):
host_obj = host.Host(context=self.context)
host_obj.name = 'foo-host'
host_obj.failover_segment_id = uuidsentinel.fake_segment
host_obj.type = 'fake-type'
host_obj.reserved = False
host_obj.on_maintenance = False
host_obj.control_attributes = 'fake_attributes'
host_obj.uuid = uuidsentinel.fake_host
return host_obj
@mock.patch.object(api_utils, 'notify_about_host_api')
@mock.patch.object(db, 'host_create')
def test_create(self, mock_db_create, mock_notify_about_host_api):
mock_db_create.return_value = fake_host
host_obj = self._host_create_attributes()
host_obj.create()
self._compare_segment_and_host_data(host_obj)
mock_db_create.assert_called_once_with(self.context, {
'failover_segment_id': uuidsentinel.fake_segment,
'on_maintenance': False, 'uuid': uuidsentinel.fake_host,
'reserved': False, 'name': u'foo-host',
'control_attributes': u'fake_attributes',
'type': u'fake-type'})
action = fields.EventNotificationAction.HOST_CREATE
phase_start = fields.EventNotificationPhase.START
phase_end = fields.EventNotificationPhase.END
notify_calls = [
mock.call(self.context, host_obj, action=action,
phase=phase_start),
mock.call(self.context, host_obj, action=action,
phase=phase_end)]
mock_notify_about_host_api.assert_has_calls(notify_calls)
@mock.patch.object(api_utils, 'notify_about_host_api')
@mock.patch.object(db, 'host_create')
def test_recreate_fails(self, mock_host_create,
mock_notify_about_host_api):
mock_host_create.return_value = fake_host
host_obj = self._host_create_attributes()
host_obj.create()
self.assertRaises(exception.ObjectActionError, host_obj.create)
action = fields.EventNotificationAction.HOST_CREATE
phase_start = fields.EventNotificationPhase.START
phase_end = fields.EventNotificationPhase.END
notify_calls = [
mock.call(self.context, host_obj, action=action,
phase=phase_start),
mock.call(self.context, host_obj, action=action,
phase=phase_end)]
mock_notify_about_host_api.assert_has_calls(notify_calls)
mock_host_create.assert_called_once_with(self.context, {
'uuid': uuidsentinel.fake_host, 'name': 'foo-host',
'failover_segment_id': uuidsentinel.fake_segment,
'type': 'fake-type', 'reserved': False, 'on_maintenance': False,
'control_attributes': 'fake_attributes'})
@mock.patch.object(api_utils, 'notify_about_host_api')
@mock.patch.object(db, 'host_delete')
def test_destroy(self, mock_host_destroy, mock_notify_about_host_api):
host_obj = self._host_create_attributes()
host_obj.id = 123
host_obj.destroy()
mock_host_destroy.assert_called_once_with(
self.context, uuidsentinel.fake_host)
action = fields.EventNotificationAction.HOST_DELETE
phase_start = fields.EventNotificationPhase.START
phase_end = fields.EventNotificationPhase.END
notify_calls = [
mock.call(self.context, host_obj, action=action,
phase=phase_start),
mock.call(self.context, host_obj, action=action,
phase=phase_end)]
mock_notify_about_host_api.assert_has_calls(notify_calls)
@mock.patch.object(api_utils, 'notify_about_host_api')
@mock.patch.object(db, 'host_delete')
def test_destroy_host_not_found(self, mock_host_destroy,
mock_notify_about_host_api):
mock_host_destroy.side_effect = exception.HostNotFound(id=123)
host_obj = self._host_create_attributes()
host_obj.id = 123
self.assertRaises(exception.HostNotFound, host_obj.destroy)
action = fields.EventNotificationAction.HOST_DELETE
phase_start = fields.EventNotificationPhase.START
notify_calls = [
mock.call(self.context, host_obj, action=action,
phase=phase_start)]
mock_notify_about_host_api.assert_has_calls(notify_calls)
@mock.patch.object(db, 'host_get_all_by_filters')
def test_get_host_by_filters(self, mock_api_get):
fake_host2 = copy.deepcopy(fake_host)
fake_host2['name'] = 'fake_host22'
mock_api_get.return_value = [fake_host2, fake_host]
filters = {'reserved': False}
host_result = host.HostList.get_all(self.context, filters=filters)
self.assertEqual(2, len(host_result))
mock_api_get.assert_called_once_with(self.context, filters={
'reserved': False
}, limit=None, marker=None, sort_dirs=None, sort_keys=None)
@mock.patch.object(db, 'host_get_all_by_filters')
def test_get_limit_and_marker_invalid_marker(self, mock_api_get):
host_name = 'fake-host'
mock_api_get.side_effect = exception.MarkerNotFound(marker=host_name)
self.assertRaises(exception.MarkerNotFound,
host.HostList.get_all,
self.context, limit=5, marker=host_name)
@mock.patch.object(api_utils, 'notify_about_host_api')
@mock.patch.object(db, 'host_update')
def test_save(self, mock_host_update, mock_notify_about_host_api):
mock_host_update.return_value = fake_host
host_obj = self._host_create_attributes()
host_obj.id = 123
host_obj.save()
self._compare_segment_and_host_data(host_obj)
(mock_host_update.
assert_called_once_with(self.context, uuidsentinel.fake_host,
{'control_attributes': u'fake_attributes',
'type': u'fake-type',
'failover_segment_id':
uuidsentinel.fake_segment,
'name': u'foo-host',
'uuid': uuidsentinel.fake_host,
'reserved': False, 'on_maintenance': False
}))
action = fields.EventNotificationAction.HOST_UPDATE
phase_start = fields.EventNotificationPhase.START
phase_end = fields.EventNotificationPhase.END
notify_calls = [
mock.call(self.context, host_obj, action=action,
phase=phase_start),
mock.call(self.context, host_obj, action=action,
phase=phase_end)]
mock_notify_about_host_api.assert_has_calls(notify_calls)
@mock.patch.object(db, 'host_update')
def test_save_lazy_attribute_changed(self, mock_host_update):
mock_host_update.return_value = fake_host
host_obj = self._host_create_attributes()
host_obj.failover_segment = (segment.
FailoverSegment(context=self.context))
host_obj.id = 123
self.assertRaises(exception.ObjectActionError, host_obj.save)
@mock.patch.object(api_utils, 'notify_about_host_api')
@mock.patch.object(db, 'host_update')
def test_save_host_already_exists(self, mock_host_update,
mock_notify_about_host_api):
mock_host_update.side_effect = exception.HostExists(name="foo-host")
host_object = host.Host(context=self.context)
host_object.name = "foo-host"
host_object.id = 123
host_object.uuid = uuidsentinel.fake_host
self.assertRaises(exception.HostExists, host_object.save)
action = fields.EventNotificationAction.HOST_UPDATE
phase_start = fields.EventNotificationPhase.START
notify_calls = [
mock.call(self.context, host_object, action=action,
phase=phase_start)]
mock_notify_about_host_api.assert_has_calls(notify_calls)
@mock.patch.object(api_utils, 'notify_about_host_api')
@mock.patch.object(db, 'host_update')
def test_save_host_not_found(self, mock_host_update,
mock_notify_about_host_api):
mock_host_update.side_effect = exception.HostNotFound(id="foo-host")
host_object = host.Host(context=self.context)
host_object.name = "foo-host"
host_object.id = 123
host_object.uuid = uuidsentinel.fake_host
self.assertRaises(exception.HostNotFound, host_object.save)
action = fields.EventNotificationAction.HOST_UPDATE
phase_start = fields.EventNotificationPhase.START
notify_calls = [
mock.call(self.context, host_object, action=action,
phase=phase_start)]
mock_notify_about_host_api.assert_has_calls(notify_calls)