Merge "Transform aggregate.create notification"

This commit is contained in:
Jenkins 2017-01-04 22:48:51 +00:00 committed by Gerrit Code Review
commit 281ee20acb
10 changed files with 172 additions and 3 deletions

View File

@ -0,0 +1,19 @@
{
"priority": "INFO",
"payload": {
"nova_object.version": "1.0",
"nova_object.namespace": "nova",
"nova_object.name": "AggregatePayload",
"nova_object.data": {
"name": "my-aggregate",
"metadata": {
"availability_zone": "nova"
},
"hosts": [],
"id": 1,
"uuid": "788608ec-ebdc-45c5-bc7f-e5f24ab92c80"
}
},
"event_type": "aggregate.create.end",
"publisher_id": "nova-api:fake-mini"
}

View File

@ -0,0 +1,17 @@
{
"priority": "INFO",
"payload": {
"nova_object.version": "1.0",
"nova_object.namespace": "nova",
"nova_object.name": "AggregatePayload",
"nova_object.data": {
"name": "my-aggregate",
"metadata": {
"availability_zone": "nova"
},
"uuid": "788608ec-ebdc-45c5-bc7f-e5f24ab92c80"
}
},
"event_type": "aggregate.create.start",
"publisher_id": "nova-api:fake-mini"
}

View File

@ -32,6 +32,7 @@ from nova import exception
from nova.i18n import _LW
from nova.network import model as network_model
from nova import notifications
from nova.notifications.objects import aggregate as aggregate_notification
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
@ -451,6 +452,20 @@ def notify_about_aggregate_update(context, event_suffix, aggregate_payload):
notifier.info(context, 'aggregate.%s' % event_suffix, aggregate_payload)
def notify_about_aggregate_action(context, aggregate, action, phase):
payload = aggregate_notification.AggregatePayload(aggregate)
notification = aggregate_notification.AggregateNotification(
priority=fields.NotificationPriority.INFO,
publisher=notification_base.NotificationPublisher(
context=context, host=CONF.host, binary='nova-api'),
event_type=notification_base.EventType(
object='aggregate',
action=action,
phase=phase),
payload=payload)
notification.emit(context)
def notify_about_host_update(context, event_suffix, host_payload):
"""Send a notification about host update.

View File

@ -0,0 +1,51 @@
# 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.notifications.objects import base
from nova.objects import base as nova_base
from nova.objects import fields
@nova_base.NovaObjectRegistry.register_notification
class AggregatePayload(base.NotificationPayloadBase):
SCHEMA = {
'id': ('aggregate', 'id'),
'uuid': ('aggregate', 'uuid'),
'name': ('aggregate', 'name'),
'hosts': ('aggregate', 'hosts'),
'metadata': ('aggregate', 'metadata'),
}
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'id': fields.IntegerField(),
'uuid': fields.UUIDField(nullable=False),
'name': fields.StringField(),
'hosts': fields.ListOfStringsField(nullable=True),
'metadata': fields.DictOfStringsField(nullable=True),
}
def __init__(self, aggregate, **kwargs):
super(AggregatePayload, self).__init__(**kwargs)
self.populate_schema(aggregate=aggregate)
@base.notification_sample('aggregate-create-start.json')
@base.notification_sample('aggregate-create-end.json')
@nova_base.NovaObjectRegistry.register_notification
class AggregateNotification(base.NotificationBase):
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'payload': fields.ObjectField('AggregatePayload')
}

View File

@ -360,11 +360,18 @@ class Aggregate(base.NovaPersistentObject, base.NovaObject):
payload['meta_data'] = payload.pop('metadata')
if 'uuid' not in updates:
updates['uuid'] = uuidutils.generate_uuid()
self.uuid = updates['uuid']
LOG.debug('Generated uuid %(uuid)s for aggregate',
dict(uuid=updates['uuid']))
compute_utils.notify_about_aggregate_update(self._context,
"create.start",
payload)
compute_utils.notify_about_aggregate_action(
context=self._context,
aggregate=self,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.START)
metadata = updates.pop('metadata', None)
db_aggregate = _aggregate_create_in_db(self._context, updates,
metadata=metadata)
@ -373,6 +380,11 @@ class Aggregate(base.NovaPersistentObject, base.NovaObject):
compute_utils.notify_about_aggregate_update(self._context,
"create.end",
payload)
compute_utils.notify_about_aggregate_action(
context=self._context,
aggregate=self,
action=fields.NotificationAction.CREATE,
phase=fields.NotificationPhase.END)
@base.remotable
def save(self):

View File

@ -388,3 +388,6 @@ class TestOpenStackClient(object):
def get_instance_actions(self, server_id):
return self.api_get('/servers/%s/os-instance-actions' %
(server_id)).body['instanceActions']
def post_aggregate(self, aggregate):
return self.api_post('/os-aggregates', aggregate).body['aggregate']

View File

@ -0,0 +1,40 @@
# 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 TestAggregateNotificationSample(
notification_sample_base.NotificationSampleTestBase):
def test_aggregate_create_delete(self):
aggregate_req = {
"aggregate": {
"name": "my-aggregate",
"availability_zone": "nova"}}
aggregate = self.admin_api.post_aggregate(aggregate_req)
self.assertEqual(2, len(fake_notifier.VERSIONED_NOTIFICATIONS))
# The uuid hasn't been exposed on the REST API yet so we have no way to
# match it here, now.
self._verify_notification(
'aggregate-create-start',
replacements={
'uuid': self.ANY},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[0])
self._verify_notification(
'aggregate-create-end',
replacements={
'uuid': self.ANY,
'id': aggregate['id']},
actual=fake_notifier.VERSIONED_NOTIFICATIONS[1])

View File

@ -33,5 +33,7 @@ class TestExceptionNotificationSample(
self.assertRaises(api_client.OpenStackApiException,
self.admin_api.api_post, 'os-aggregates', post)
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
self._verify_notification('compute-exception')
self.assertEqual(4, len(fake_notifier.VERSIONED_NOTIFICATIONS))
self._verify_notification(
'compute-exception',
actual=fake_notifier.VERSIONED_NOTIFICATIONS[3])

View File

@ -10573,10 +10573,18 @@ class ComputeAPIAggrTestCase(BaseTestCase):
self.stub_out('oslo_messaging.rpc.client.call', fake_rpc_method)
self.stub_out('oslo_messaging.rpc.client.cast', fake_rpc_method)
def test_aggregate_no_zone(self):
@mock.patch('nova.compute.utils.notify_about_aggregate_action')
def test_aggregate_no_zone(self, mock_notify):
# Ensure we can create an aggregate without an availability zone
aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
None)
mock_notify.assert_has_calls([
mock.call(context=self.context, aggregate=aggr,
action='create', phase='start'),
mock.call(context=self.context, aggregate=aggr,
action='create', phase='end')])
self.api.delete_aggregate(self.context, aggr.id)
self.assertRaises(exception.AggregateNotFound,
self.api.delete_aggregate, self.context, aggr.id)

View File

@ -257,6 +257,8 @@ class TestNotificationBase(test.NoDBTestCase):
notification_object_data = {
'AggregateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'AggregatePayload': '1.0-2550af604410af7b4ad5d46fb29ba45b',
'AuditPeriodPayload': '1.0-2b429dd307b8374636703b843fa3f9cb',
'BandwidthPayload': '1.0-ee2616a7690ab78406842a2b68e34130',
'EventType': '1.4-da0f0fbcda143ca96c2ac1b93937c22c',