Merge "Adds json sample for the versioned notifications"
This commit is contained in:
commit
159f379e16
21
doc/notification_samples/service-update.json
Normal file
21
doc/notification_samples/service-update.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"priority": "INFO",
|
||||
"payload": {
|
||||
"nova_object.namespace": "nova",
|
||||
"nova_object.name": "ServiceStatusPayload",
|
||||
"nova_object.version": "1.0",
|
||||
"nova_object.data": {
|
||||
"host": "host1",
|
||||
"disabled": false,
|
||||
"last_seen_up": "2012-10-29T13:42:05Z",
|
||||
"binary": "nova-compute",
|
||||
"topic": "compute",
|
||||
"disabled_reason": null,
|
||||
"report_count": 1,
|
||||
"forced_down": false,
|
||||
"version": 5
|
||||
}
|
||||
},
|
||||
"event_type": "service.update",
|
||||
"publisher_id": "nova-compute:host1"
|
||||
}
|
@ -210,13 +210,16 @@ class TestOpenStackClient(object):
|
||||
kwargs.setdefault('check_response_status', [200, 202])
|
||||
return APIResponse(self.api_request(relative_uri, **kwargs))
|
||||
|
||||
def api_put(self, relative_uri, body, **kwargs):
|
||||
def api_put(self, relative_uri, body, api_version=None, **kwargs):
|
||||
kwargs['method'] = 'PUT'
|
||||
if body:
|
||||
headers = kwargs.setdefault('headers', {})
|
||||
headers['Content-Type'] = 'application/json'
|
||||
kwargs['body'] = jsonutils.dumps(body)
|
||||
|
||||
if api_version:
|
||||
headers['X-OpenStack-Nova-API-Version'] = api_version
|
||||
|
||||
kwargs.setdefault('check_response_status', [200, 202, 204])
|
||||
return APIResponse(self.api_request(relative_uri, **kwargs))
|
||||
|
||||
|
@ -18,7 +18,6 @@ from oslo_utils import fixture as utils_fixture
|
||||
|
||||
from nova.tests.functional.api_sample_tests import api_sample_base
|
||||
from nova.tests.unit.api.openstack.compute import test_services
|
||||
from nova.tests.unit import fake_notifier
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -52,18 +51,6 @@ class ServicesJsonTest(api_sample_base.ApiSampleTestBaseV21):
|
||||
self.stub_out("nova.db.service_update",
|
||||
test_services.fake_service_update)
|
||||
self.useFixture(utils_fixture.TimeFixture(test_services.fake_utcnow()))
|
||||
fake_notifier.stub_notifier(self.stubs)
|
||||
self.addCleanup(fake_notifier.reset)
|
||||
|
||||
def _verify_notification(self, **kwargs):
|
||||
# TODO(gibi): store notification sample and start using that for
|
||||
# verification instead
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
payload = fake_notifier.VERSIONED_NOTIFICATIONS[0]['payload']
|
||||
fields = payload['nova_object.data']
|
||||
for key, value in kwargs.items():
|
||||
self.assertEqual(value, fields[key],
|
||||
'Mismatch in key %s' % key)
|
||||
|
||||
def test_services_list(self):
|
||||
"""Return a list of all agent builds."""
|
||||
@ -75,7 +62,6 @@ class ServicesJsonTest(api_sample_base.ApiSampleTestBaseV21):
|
||||
'status': 'disabled',
|
||||
'state': 'up'}
|
||||
self._verify_response('services-list-get-resp', subs, response, 200)
|
||||
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
def test_service_enable(self):
|
||||
"""Enable an existing agent build."""
|
||||
@ -85,7 +71,6 @@ class ServicesJsonTest(api_sample_base.ApiSampleTestBaseV21):
|
||||
'service-enable-put-req', subs,
|
||||
api_version=self.microversion)
|
||||
self._verify_response('service-enable-put-resp', subs, response, 200)
|
||||
self._verify_notification(disabled=False, disabled_reason=None)
|
||||
|
||||
def test_service_disable(self):
|
||||
"""Disable an existing agent build."""
|
||||
@ -95,7 +80,6 @@ class ServicesJsonTest(api_sample_base.ApiSampleTestBaseV21):
|
||||
'service-disable-put-req', subs,
|
||||
api_version=self.microversion)
|
||||
self._verify_response('service-disable-put-resp', subs, response, 200)
|
||||
self._verify_notification(disabled=True, disabled_reason=None)
|
||||
|
||||
def test_service_disable_log_reason(self):
|
||||
"""Disable an existing service and log the reason."""
|
||||
@ -107,7 +91,6 @@ class ServicesJsonTest(api_sample_base.ApiSampleTestBaseV21):
|
||||
api_version=self.microversion)
|
||||
self._verify_response('service-disable-log-put-resp',
|
||||
subs, response, 200)
|
||||
self._verify_notification(disabled=True, disabled_reason='test2')
|
||||
|
||||
def test_service_delete(self):
|
||||
"""Delete an existing service."""
|
||||
@ -115,7 +98,6 @@ class ServicesJsonTest(api_sample_base.ApiSampleTestBaseV21):
|
||||
api_version=self.microversion)
|
||||
self.assertEqual(204, response.status_code)
|
||||
self.assertEqual("", response.content)
|
||||
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
|
||||
class ServicesV211JsonTest(ServicesJsonTest):
|
||||
@ -135,7 +117,6 @@ class ServicesV211JsonTest(ServicesJsonTest):
|
||||
'status': 'disabled',
|
||||
'state': 'up'}
|
||||
self._verify_response('services-list-get-resp', subs, response, 200)
|
||||
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
def test_force_down(self):
|
||||
"""Set forced_down flag"""
|
||||
@ -147,4 +128,3 @@ class ServicesV211JsonTest(ServicesJsonTest):
|
||||
api_version=self.microversion)
|
||||
self._verify_response('service-force-down-put-resp', subs,
|
||||
response, 200)
|
||||
self._verify_notification(forced_down=True)
|
||||
|
@ -0,0 +1,92 @@
|
||||
# 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 os
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from nova import test
|
||||
from nova.tests import fixtures as nova_fixtures
|
||||
from nova.tests.unit import fake_notifier
|
||||
|
||||
|
||||
class NotificationSampleTestBase(test.TestCase):
|
||||
"""Base class for notification sample testing.
|
||||
|
||||
To add tests for a versioned notification you have to store a sample file
|
||||
under doc/notification_sample directory. In the test method in the subclass
|
||||
trigger a change in the system that expected to generate the notification
|
||||
then use the _verify_notification function to assert if the stored sample
|
||||
matches with the generated one.
|
||||
|
||||
If the notification has different payload content depending on the state
|
||||
change you triggered then the replacements parameter of the
|
||||
_verify_notification function can be used to override values coming from
|
||||
the sample file.
|
||||
|
||||
Check nova.functional.notification_sample_tests.test_service_update as an
|
||||
example.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(NotificationSampleTestBase, self).setUp()
|
||||
|
||||
api_fixture = self.useFixture(nova_fixtures.OSAPIFixture(
|
||||
api_version='v2.1'))
|
||||
|
||||
self.api = api_fixture.api
|
||||
self.admin_api = api_fixture.admin_api
|
||||
|
||||
fake_notifier.stub_notifier(self.stubs)
|
||||
self.addCleanup(fake_notifier.reset)
|
||||
|
||||
def _get_notification_sample(self, sample):
|
||||
sample_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
sample_dir = os.path.normpath(os.path.join(
|
||||
sample_dir,
|
||||
"../../../../doc/notification_samples"))
|
||||
return sample_dir + '/' + sample + '.json'
|
||||
|
||||
def _apply_replacements(self, replacements, sample_obj):
|
||||
replacements = replacements or {}
|
||||
for key, value in replacements.items():
|
||||
obj = sample_obj['payload']
|
||||
for sub_key in key.split('.')[:-1]:
|
||||
obj = obj['nova_object.data'][sub_key]
|
||||
obj['nova_object.data'][key.split('.')[-1]] = value
|
||||
|
||||
def _verify_notification(self, sample_file_name, replacements=None):
|
||||
"""Assert if the generated notification matches with the stored sample
|
||||
|
||||
:param sample_file_name: The name of the sample file to match relative
|
||||
to doc/notification_samples
|
||||
:param replacements: A dict of key value pairs that is used to update
|
||||
the payload field of the sample data before it is
|
||||
matched against the generated notification.
|
||||
The 'x.y':'new-value' key-value pair selects the
|
||||
["payload"]["nova_object.data"]["x"]
|
||||
["nova_object.data"]["y"] value from the sample
|
||||
data and overrides it with 'new-value'.
|
||||
"""
|
||||
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
notification = fake_notifier.VERSIONED_NOTIFICATIONS[0]
|
||||
|
||||
with open(self._get_notification_sample(sample_file_name)) as sample:
|
||||
sample_data = sample.read()
|
||||
|
||||
sample_obj = jsonutils.loads(sample_data)
|
||||
self._apply_replacements(replacements, sample_obj)
|
||||
|
||||
self.assertJsonEqual(sample_obj, notification)
|
@ -0,0 +1,65 @@
|
||||
# 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.
|
||||
|
||||
from oslo_utils import fixture as utils_fixture
|
||||
|
||||
from nova.tests.functional.notification_sample_tests \
|
||||
import notification_sample_base
|
||||
from nova.tests.unit.api.openstack.compute import test_services
|
||||
|
||||
|
||||
class TestServiceUpdateNotificationSample(
|
||||
notification_sample_base.NotificationSampleTestBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestServiceUpdateNotificationSample, self).setUp()
|
||||
self.stub_out("nova.db.service_get_by_host_and_binary",
|
||||
test_services.fake_service_get_by_host_binary)
|
||||
self.stub_out("nova.db.service_update",
|
||||
test_services.fake_service_update)
|
||||
self.useFixture(utils_fixture.TimeFixture(test_services.fake_utcnow()))
|
||||
|
||||
def test_service_enable(self):
|
||||
body = {'host': 'host1',
|
||||
'binary': 'nova-compute'}
|
||||
self.admin_api.api_put('os-services/enable', body)
|
||||
self._verify_notification('service-update')
|
||||
|
||||
def test_service_disabled(self):
|
||||
body = {'host': 'host1',
|
||||
'binary': 'nova-compute'}
|
||||
self.admin_api.api_put('os-services/disable', body)
|
||||
self._verify_notification('service-update',
|
||||
replacements={'disabled': True})
|
||||
|
||||
def test_service_disabled_log_reason(self):
|
||||
body = {'host': 'host1',
|
||||
'binary': 'nova-compute',
|
||||
'disabled_reason': 'test2'}
|
||||
self.admin_api.api_put('os-services/disable-log-reason', body)
|
||||
self._verify_notification('service-update',
|
||||
replacements={'disabled': True,
|
||||
'disabled_reason': 'test2'})
|
||||
|
||||
def test_service_force_down(self):
|
||||
body = {'host': 'host1',
|
||||
'binary': 'nova-compute',
|
||||
'forced_down': True}
|
||||
self.admin_api.api_put('os-services/force-down',
|
||||
body,
|
||||
api_version='2.12')
|
||||
self._verify_notification('service-update',
|
||||
replacements={'forced_down': True,
|
||||
'disabled': True,
|
||||
'disabled_reason': 'test2'})
|
@ -48,6 +48,7 @@ fake_services_list = [
|
||||
topic='scheduler',
|
||||
updated_at=datetime.datetime(2012, 10, 29, 13, 42, 2),
|
||||
created_at=datetime.datetime(2012, 9, 18, 2, 46, 27),
|
||||
last_seen_up=datetime.datetime(2012, 10, 29, 13, 42, 2),
|
||||
forced_down=False,
|
||||
disabled_reason='test1'),
|
||||
dict(test_service.fake_service,
|
||||
@ -58,6 +59,7 @@ fake_services_list = [
|
||||
topic='compute',
|
||||
updated_at=datetime.datetime(2012, 10, 29, 13, 42, 5),
|
||||
created_at=datetime.datetime(2012, 9, 18, 2, 46, 27),
|
||||
last_seen_up=datetime.datetime(2012, 10, 29, 13, 42, 5),
|
||||
forced_down=False,
|
||||
disabled_reason='test2'),
|
||||
dict(test_service.fake_service,
|
||||
@ -68,6 +70,7 @@ fake_services_list = [
|
||||
topic='scheduler',
|
||||
updated_at=datetime.datetime(2012, 9, 19, 6, 55, 34),
|
||||
created_at=datetime.datetime(2012, 9, 18, 2, 46, 28),
|
||||
last_seen_up=datetime.datetime(2012, 9, 19, 6, 55, 34),
|
||||
forced_down=False,
|
||||
disabled_reason=None),
|
||||
dict(test_service.fake_service,
|
||||
@ -78,6 +81,7 @@ fake_services_list = [
|
||||
topic='compute',
|
||||
updated_at=datetime.datetime(2012, 9, 18, 8, 3, 38),
|
||||
created_at=datetime.datetime(2012, 9, 18, 2, 46, 28),
|
||||
last_seen_up=datetime.datetime(2012, 9, 18, 8, 3, 38),
|
||||
forced_down=False,
|
||||
disabled_reason='test4'),
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user