Transform servergroup.create notification

Transform server group create notification to the versioned
notification framework.

Co-Authored-By: Gábor Antal <antal@inf.u-szeged.hu>
Change-Id: I781975293ccef40670cf474dd1d475cb427dba63
Implements: bp versioned-notification-transformation-queens
This commit is contained in:
ShunliZhou 2017-04-06 15:47:15 +08:00
parent ab352afeb2
commit 5537840edf
8 changed files with 195 additions and 1 deletions

View File

@ -0,0 +1,19 @@
{
"priority": "INFO",
"payload": {
"nova_object.version": "1.0",
"nova_object.namespace": "nova",
"nova_object.name": "ServerGroupPayload",
"nova_object.data": {
"uuid": "788608ec-ebdc-45c5-bc7f-e5f24ab92c80",
"name": "test-server-group",
"project_id": "6f70656e737461636b20342065766572",
"user_id": "fake",
"policies": ["anti-affinity"],
"members": [],
"hosts": null
}
},
"event_type": "server_group.create",
"publisher_id": "nova-api:fake-mini"
}

View File

@ -37,6 +37,7 @@ from nova.notifications.objects import base as notification_base
from nova.notifications.objects import exception as notification_exception
from nova.notifications.objects import instance as instance_notification
from nova.notifications.objects import keypair as keypair_notification
from nova.notifications.objects import server_group as sg_notification
from nova import objects
from nova.objects import fields
from nova import rpc
@ -557,6 +558,19 @@ def notify_about_host_update(context, event_suffix, host_payload):
notifier.info(context, 'HostAPI.%s' % event_suffix, host_payload)
def notify_about_server_group_action(context, group, action):
payload = sg_notification.ServerGroupPayload(group)
notification = sg_notification.ServerGroupNotification(
priority=fields.NotificationPriority.INFO,
publisher=notification_base.NotificationPublisher(
host=CONF.host, source=fields.NotificationSource.API),
event_type=notification_base.EventType(
object='server_group',
action=action),
payload=payload)
notification.emit(context)
def refresh_info_cache_for_instance(context, instance):
"""Refresh the info cache for an instance.

View File

@ -0,0 +1,60 @@
# 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 nova.notifications.objects import base
from nova.objects import base as nova_base
from nova.objects import fields
@nova_base.NovaObjectRegistry.register_notification
class ServerGroupPayload(base.NotificationPayloadBase):
SCHEMA = {
'uuid': ('group', 'uuid'),
'name': ('group', 'name'),
'user_id': ('group', 'user_id'),
'project_id': ('group', 'project_id'),
'policies': ('group', 'policies'),
'members': ('group', 'members'),
'hosts': ('group', 'hosts'),
}
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'uuid': fields.UUIDField(),
'name': fields.StringField(nullable=True),
'user_id': fields.StringField(nullable=True),
'project_id': fields.StringField(nullable=True),
'policies': fields.ListOfStringsField(nullable=True),
'members': fields.ListOfStringsField(nullable=True),
'hosts': fields.ListOfStringsField(nullable=True),
}
def __init__(self, group):
super(ServerGroupPayload, self).__init__()
# Note: The group is orphaned here to avoid triggering lazy-loading of
# the group.hosts field.
cgroup = copy.deepcopy(group)
cgroup._context = None
self.populate_schema(group=cgroup)
@base.notification_sample('server_group-create.json')
@nova_base.NovaObjectRegistry.register_notification
class ServerGroupNotification(base.NotificationBase):
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'payload': fields.ObjectField('ServerGroupPayload')
}

View File

@ -417,6 +417,10 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
payload['server_group_id'] = self.uuid
compute_utils.notify_about_server_group_update(self._context,
"create", payload)
compute_utils.notify_about_server_group_action(
context=self._context,
group=self,
action=fields.NotificationAction.CREATE)
@base.remotable
def create(self):

View File

@ -0,0 +1,30 @@
# 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.
from nova.tests.functional.notification_sample_tests \
import notification_sample_base
from nova.tests.unit import fake_notifier
class TestServerGroupNotificationSample(
notification_sample_base.NotificationSampleTestBase):
def test_server_group_create(self):
group_req = {
"name": "test-server-group",
"policies": ["anti-affinity"]}
group = self.api.post_server_groups(group_req)
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
self._verify_notification(
'server_group-create',
replacements={'uuid': group['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[0])

View File

@ -969,6 +969,49 @@ class ComputeUtilsTestCase(test.NoDBTestCase):
mock_notify_usage.assert_has_calls(expected_notify_calls)
class ServerGroupTestCase(test.TestCase):
def setUp(self):
super(ServerGroupTestCase, self).setUp()
fake_notifier.stub_notifier(self)
self.addCleanup(fake_notifier.reset)
self.user_id = 'fake'
self.project_id = 'fake'
self.context = context.RequestContext(self.user_id, self.project_id)
def test_notify_about_server_group_action(self):
uuid = uuids.instance
group = objects.InstanceGroup(context=self.context,
id=1,
uuid=uuid,
user_id=self.user_id,
project_id=self.project_id,
name="test-server-group",
policies=["anti-affinity"])
compute_utils.notify_about_server_group_action(self.context,
group, 'create')
self.assertEqual(len(fake_notifier.VERSIONED_NOTIFICATIONS), 1)
notification = fake_notifier.VERSIONED_NOTIFICATIONS[0]
expected = {'priority': 'INFO',
'event_type': u'server_group.create',
'publisher_id': u'nova-api:fake-mini',
'payload': {
'nova_object.data': {
'name': u'test-server-group',
'policies': [u'anti-affinity'],
'project_id': u'fake',
'user_id': u'fake',
'uuid': uuid,
'hosts': None,
'members': None
},
'nova_object.name': 'ServerGroupPayload',
'nova_object.namespace': 'nova',
'nova_object.version': '1.0'
}
}
self.assertEqual(notification, expected)
class ComputeUtilsQuotaTestCase(test.TestCase):
def setUp(self):
super(ComputeUtilsQuotaTestCase, self).setUp()

View File

@ -395,6 +395,8 @@ notification_object_data = {
'KeypairNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'KeypairPayload': '1.0-6daebbbde0e1bf35c1556b1ecd9385c1',
'NotificationPublisher': '2.1-9f89fe4abb80f9a7b726e59800c905de',
'ServerGroupNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'ServerGroupPayload': '1.0-eb4bd1738b4670cfe1b7c30344c143c3',
'ServiceStatusNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'ServiceStatusPayload': '1.1-7b6856bd879db7f3ecbcd0ca9f35f92f',
}

View File

@ -20,8 +20,10 @@ from oslo_utils import timeutils
from nova import exception
from nova import objects
from nova.tests.unit.objects import test_objects
from nova.tests.unit import utils as test_utils
from nova.tests import uuidsentinel as uuids
_TS_NOW = timeutils.utcnow(with_timezone=True)
# o.vo.fields.DateTimeField converts to tz-aware and
# in process we lose microsecond resolution.
@ -122,10 +124,11 @@ class _TestInstanceGroupObject(object):
self.assertFalse(mock_db_update.called)
self.assertFalse(mock_notify.called)
@mock.patch('nova.compute.utils.notify_about_server_group_action')
@mock.patch('nova.compute.utils.notify_about_server_group_update')
@mock.patch('nova.objects.InstanceGroup._create_in_db',
return_value=_INST_GROUP_DB)
def test_create(self, mock_db_create, mock_notify):
def test_create(self, mock_db_create, mock_notify, mock_notify_action):
obj = objects.InstanceGroup(context=self.context)
obj.uuid = _DB_UUID
obj.name = _INST_GROUP_DB['name']
@ -165,7 +168,26 @@ class _TestInstanceGroupObject(object):
'policies': _INST_GROUP_DB['policies'],
'server_group_id': _DB_UUID})
def _group_matcher(group):
"""Custom mock call matcher method."""
return (group.uuid == _DB_UUID and
group.name == _INST_GROUP_DB['name'] and
group.user_id == _INST_GROUP_DB['user_id'] and
group.project_id == _INST_GROUP_DB['project_id'] and
group.created_at == _TS_NOW and
group.updated_at == _TS_NOW and
group.deleted_at is None and
group.deleted is False and
group.members == _INST_GROUP_DB['members'] and
group.policies == _INST_GROUP_DB['policies'] and
group.id == 1)
group_matcher = test_utils.CustomMockCallMatcher(_group_matcher)
self.assertRaises(exception.ObjectActionError, obj.create)
mock_notify_action.assert_called_once_with(context=self.context,
group=group_matcher,
action='create')
@mock.patch('nova.compute.utils.notify_about_server_group_update')
@mock.patch('nova.objects.InstanceGroup._destroy_in_db')