Transform servergroup.addmember notification

The servergroup.addmember notification has been transformed
to the versioned notification framework.

Change-Id: I5291e453ba06f0f26c4928e4f7482c40e725a781
Implements: bp versioned-notification-transformation-rocky
This commit is contained in:
Takashi NATSUME 2018-02-05 15:41:47 +09:00
parent 01333a7f18
commit c4397d5e5a
12 changed files with 113 additions and 15 deletions

View File

@ -0,0 +1,11 @@
{
"priority": "INFO",
"payload": {
"$ref": "common_payloads/ServerGroupPayload.json#",
"nova_object.data": {
"members": ["54238a20-f9be-47a7-897e-d7cb0e4c03d0"]
}
},
"event_type": "server_group.add_member",
"publisher_id": "nova-api:fake-mini"
}

View File

@ -665,6 +665,21 @@ def notify_about_server_group_action(context, group, action):
notification.emit(context) notification.emit(context)
@rpc.if_notifications_enabled
def notify_about_server_group_add_member(context, group_id):
group = objects.InstanceGroup.get_by_uuid(context, group_id)
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=fields.NotificationAction.ADD_MEMBER),
payload=payload)
notification.emit(context)
def refresh_info_cache_for_instance(context, instance): def refresh_info_cache_for_instance(context, instance):
"""Refresh the info cache for an instance. """Refresh the info cache for an instance.

View File

@ -53,7 +53,8 @@ class EventType(NotificationObject):
# Version 1.7: REMOVE_FIXED_IP replaced with INTERFACE_DETACH in # Version 1.7: REMOVE_FIXED_IP replaced with INTERFACE_DETACH in
# NotificationActionField enum # NotificationActionField enum
# Version 1.8: IMPORT value is added to NotificationActionField enum # Version 1.8: IMPORT value is added to NotificationActionField enum
VERSION = '1.8' # Version 1.9: ADD_MEMBER value is added to NotificationActionField enum
VERSION = '1.9'
fields = { fields = {
'object': fields.StringField(nullable=False), 'object': fields.StringField(nullable=False),

View File

@ -49,6 +49,7 @@ class ServerGroupPayload(base.NotificationPayloadBase):
self.populate_schema(group=cgroup) self.populate_schema(group=cgroup)
@base.notification_sample('server_group-add_member.json')
@base.notification_sample('server_group-create.json') @base.notification_sample('server_group-create.json')
@base.notification_sample('server_group-delete.json') @base.notification_sample('server_group-delete.json')
@nova_base.NovaObjectRegistry.register_notification @nova_base.NovaObjectRegistry.register_notification

View File

@ -869,6 +869,7 @@ class NotificationAction(BaseNovaEnum):
UNSHELVE = 'unshelve' UNSHELVE = 'unshelve'
ADD_HOST = 'add_host' ADD_HOST = 'add_host'
REMOVE_HOST = 'remove_host' REMOVE_HOST = 'remove_host'
ADD_MEMBER = 'add_member'
ALL = (UPDATE, EXCEPTION, DELETE, PAUSE, UNPAUSE, RESIZE, VOLUME_SWAP, ALL = (UPDATE, EXCEPTION, DELETE, PAUSE, UNPAUSE, RESIZE, VOLUME_SWAP,
SUSPEND, POWER_ON, REBOOT, SHUTDOWN, SNAPSHOT, INTERFACE_ATTACH, SUSPEND, POWER_ON, REBOOT, SHUTDOWN, SNAPSHOT, INTERFACE_ATTACH,
@ -879,7 +880,7 @@ class NotificationAction(BaseNovaEnum):
LIVE_MIGRATION_ROLLBACK_DEST, REBUILD, INTERFACE_DETACH, LIVE_MIGRATION_ROLLBACK_DEST, REBUILD, INTERFACE_DETACH,
RESIZE_CONFIRM, RESIZE_PREP, RESIZE_REVERT, SHELVE_OFFLOAD, RESIZE_CONFIRM, RESIZE_PREP, RESIZE_REVERT, SHELVE_OFFLOAD,
SOFT_DELETE, TRIGGER_CRASH_DUMP, UNRESCUE, UNSHELVE, ADD_HOST, SOFT_DELETE, TRIGGER_CRASH_DUMP, UNRESCUE, UNSHELVE, ADD_HOST,
REMOVE_HOST) REMOVE_HOST, ADD_MEMBER)
# TODO(rlrossit): These should be changed over to be a StateMachine enum from # TODO(rlrossit): These should be changed over to be a StateMachine enum from

View File

@ -454,6 +454,7 @@ class InstanceGroup(base.NovaPersistentObject, base.NovaObject,
instance_uuids) instance_uuids)
compute_utils.notify_about_server_group_update(context, compute_utils.notify_about_server_group_update(context,
"addmember", payload) "addmember", payload)
compute_utils.notify_about_server_group_add_member(context, group_uuid)
return list(members) return list(members)
@base.remotable @base.remotable

View File

@ -46,6 +46,8 @@ class QuotaTestCase(test.NoDBTestCase):
# Create a server group the instances will use. # Create a server group the instances will use.
group = objects.InstanceGroup(context=ctxt) group = objects.InstanceGroup(context=ctxt)
group.project_id = ctxt.project_id
group.user_id = ctxt.user_id
group.create() group.create()
instance_uuids = [] instance_uuids = []

View File

@ -149,7 +149,8 @@ class NotificationSampleTestBase(test.TestCase,
self.assertJsonEqual(sample_obj, notification) self.assertJsonEqual(sample_obj, notification)
def _boot_a_server(self, expected_status='ACTIVE', extra_params=None): def _boot_a_server(self, expected_status='ACTIVE', extra_params=None,
scheduler_hints=None):
# We have to depend on a specific image and flavor to fix the content # We have to depend on a specific image and flavor to fix the content
# of the notification that will be emitted # of the notification that will be emitted
@ -201,6 +202,9 @@ class NotificationSampleTestBase(test.TestCase,
server.update(extra_params) server.update(extra_params)
post = {'server': server} post = {'server': server}
if scheduler_hints:
post.update({"os:scheduler_hints": scheduler_hints})
created_server = self.api.post_server(post) created_server = self.api.post_server(post)
reservation_id = created_server['reservation_id'] reservation_id = created_server['reservation_id']
created_server = self.api.get_servers( created_server = self.api.get_servers(

View File

@ -9,6 +9,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from nova.tests import fixtures
from nova.tests.functional.notification_sample_tests \ from nova.tests.functional.notification_sample_tests \
import notification_sample_base import notification_sample_base
from nova.tests.unit import fake_notifier from nova.tests.unit import fake_notifier
@ -17,6 +18,12 @@ from nova.tests.unit import fake_notifier
class TestServerGroupNotificationSample( class TestServerGroupNotificationSample(
notification_sample_base.NotificationSampleTestBase): notification_sample_base.NotificationSampleTestBase):
def setUp(self):
self.flags(use_neutron=True)
super(TestServerGroupNotificationSample, self).setUp()
self.neutron = fixtures.NeutronFixture(self)
self.useFixture(self.neutron)
def test_server_group_create_delete(self): def test_server_group_create_delete(self):
group_req = { group_req = {
"name": "test-server-group", "name": "test-server-group",
@ -37,3 +44,26 @@ class TestServerGroupNotificationSample(
'server_group-delete', 'server_group-delete',
replacements={'uuid': group['id']}, replacements={'uuid': group['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[0]) actual=fake_notifier.VERSIONED_NOTIFICATIONS[0])
def test_server_group_add_member(self):
group_req = {
"name": "test-server-group",
"policies": ["anti-affinity"]}
group = self.api.post_server_groups(group_req)
fake_notifier.reset()
server = self._boot_a_server(
extra_params={'networks': [{'port': self.neutron.port_1['id']}]},
scheduler_hints={"group": group['id']})
self._wait_for_notification('instance.update')
# 0: server_group.add_member
# 1: instance.create.start
# 2: instance.create.end
# 3: instance.update
# (Due to adding server tags in the '_boot_a_server' method.)
self.assertEqual(4, len(fake_notifier.VERSIONED_NOTIFICATIONS))
self._verify_notification(
'server_group-add_member',
replacements={'uuid': group['id'],
'members': [server['id']]},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[0])

View File

@ -1082,18 +1082,17 @@ class ServerGroupTestCase(test.TestCase):
self.user_id = 'fake' self.user_id = 'fake'
self.project_id = 'fake' self.project_id = 'fake'
self.context = context.RequestContext(self.user_id, self.project_id) self.context = context.RequestContext(self.user_id, self.project_id)
self.group = objects.InstanceGroup(context=self.context,
def test_notify_about_server_group_action(self):
uuid = uuids.instance
group = objects.InstanceGroup(context=self.context,
id=1, id=1,
uuid=uuid, uuid=uuids.server_group,
user_id=self.user_id, user_id=self.user_id,
project_id=self.project_id, project_id=self.project_id,
name="test-server-group", name="test-server-group",
policies=["anti-affinity"]) policies=["anti-affinity"])
def test_notify_about_server_group_action(self):
compute_utils.notify_about_server_group_action(self.context, compute_utils.notify_about_server_group_action(self.context,
group, 'create') self.group, 'create')
self.assertEqual(len(fake_notifier.VERSIONED_NOTIFICATIONS), 1) self.assertEqual(len(fake_notifier.VERSIONED_NOTIFICATIONS), 1)
notification = fake_notifier.VERSIONED_NOTIFICATIONS[0] notification = fake_notifier.VERSIONED_NOTIFICATIONS[0]
expected = {'priority': 'INFO', expected = {'priority': 'INFO',
@ -1105,7 +1104,7 @@ class ServerGroupTestCase(test.TestCase):
'policies': [u'anti-affinity'], 'policies': [u'anti-affinity'],
'project_id': u'fake', 'project_id': u'fake',
'user_id': u'fake', 'user_id': u'fake',
'uuid': uuid, 'uuid': uuids.server_group,
'hosts': None, 'hosts': None,
'members': None 'members': None
}, },
@ -1116,6 +1115,36 @@ class ServerGroupTestCase(test.TestCase):
} }
self.assertEqual(notification, expected) self.assertEqual(notification, expected)
@mock.patch.object(objects.InstanceGroup, 'get_by_uuid')
def test_notify_about_server_group_add_member(self, mock_get_by_uuid):
self.group.members = [uuids.instance]
mock_get_by_uuid.return_value = self.group
compute_utils.notify_about_server_group_add_member(
self.context, uuids.server_group)
mock_get_by_uuid.assert_called_once_with(self.context,
uuids.server_group)
self.assertEqual(len(fake_notifier.VERSIONED_NOTIFICATIONS), 1)
notification = fake_notifier.VERSIONED_NOTIFICATIONS[0]
expected = {'priority': 'INFO',
'event_type': u'server_group.add_member',
'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': uuids.server_group,
'hosts': None,
'members': [uuids.instance]
},
'nova_object.name': 'ServerGroupPayload',
'nova_object.namespace': 'nova',
'nova_object.version': '1.0'
}
}
self.assertEqual(notification, expected)
class ComputeUtilsQuotaTestCase(test.TestCase): class ComputeUtilsQuotaTestCase(test.TestCase):
def setUp(self): def setUp(self):

View File

@ -373,7 +373,7 @@ notification_object_data = {
'AuditPeriodPayload': '1.0-2b429dd307b8374636703b843fa3f9cb', 'AuditPeriodPayload': '1.0-2b429dd307b8374636703b843fa3f9cb',
'BandwidthPayload': '1.0-ee2616a7690ab78406842a2b68e34130', 'BandwidthPayload': '1.0-ee2616a7690ab78406842a2b68e34130',
'BlockDevicePayload': '1.0-29751e1b6d41b1454e36768a1e764df8', 'BlockDevicePayload': '1.0-29751e1b6d41b1454e36768a1e764df8',
'EventType': '1.8-0f8fb2dbc76f10c7c56d1680c65ad0cf', 'EventType': '1.9-0ef3553b1d64b4cf92780776eda80883',
'ExceptionNotification': '1.0-a73147b93b520ff0061865849d3dfa56', 'ExceptionNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'ExceptionPayload': '1.0-27db46ee34cd97e39f2643ed92ad0cc5', 'ExceptionPayload': '1.0-27db46ee34cd97e39f2643ed92ad0cc5',
'FlavorNotification': '1.0-a73147b93b520ff0061865849d3dfa56', 'FlavorNotification': '1.0-a73147b93b520ff0061865849d3dfa56',

View File

@ -207,9 +207,11 @@ class _TestInstanceGroupObject(object):
mock_notify.assert_called_once_with(self.context, "delete", mock_notify.assert_called_once_with(self.context, "delete",
{'server_group_id': _DB_UUID}) {'server_group_id': _DB_UUID})
@mock.patch('nova.compute.utils.notify_about_server_group_add_member')
@mock.patch('nova.compute.utils.notify_about_server_group_update') @mock.patch('nova.compute.utils.notify_about_server_group_update')
@mock.patch('nova.objects.InstanceGroup._add_members_in_db') @mock.patch('nova.objects.InstanceGroup._add_members_in_db')
def test_add_members(self, mock_members_add_db, mock_notify): def test_add_members(self, mock_members_add_db, mock_notify,
mock_notify_add_member):
fake_member_models = [{'instance_uuid': mock.sentinel.uuid}] fake_member_models = [{'instance_uuid': mock.sentinel.uuid}]
fake_member_uuids = [mock.sentinel.uuid] fake_member_uuids = [mock.sentinel.uuid]
mock_members_add_db.return_value = fake_member_models mock_members_add_db.return_value = fake_member_models
@ -225,6 +227,7 @@ class _TestInstanceGroupObject(object):
self.context, "addmember", self.context, "addmember",
{'instance_uuids': fake_member_uuids, {'instance_uuids': fake_member_uuids,
'server_group_id': _DB_UUID}) 'server_group_id': _DB_UUID})
mock_notify_add_member.assert_called_once_with(self.context, _DB_UUID)
@mock.patch('nova.objects.InstanceList.get_by_filters') @mock.patch('nova.objects.InstanceList.get_by_filters')
@mock.patch('nova.objects.InstanceGroup._get_from_db_by_uuid', @mock.patch('nova.objects.InstanceGroup._get_from_db_by_uuid',