Add os-server-external-events support

This adds support for the os-server-external-events extension in nova,
which allows other services to deliver events to nova.

It also adds a shell command to trigger the "network-changed" event
manually, which will cause nova to refresh its network cache from
neutron.

Related to blueprint admin-event-callback-api

Change-Id: I1a302a43b6b7a6d8bdc03965a8f4c1a151bcab88
This commit is contained in:
Dan Smith 2014-02-19 08:07:56 -08:00
parent bd72fb0a2e
commit 04a123cdee
7 changed files with 120 additions and 0 deletions

View File

@ -146,6 +146,7 @@ You'll find complete documentation on the shell by running
rate-limits Print a list of rate limits for a user
reboot Reboot a server.
rebuild Shutdown, re-image, and re-boot a server.
refresh-network Refresh server network information.
remove-fixed-ip Remove an IP address from a server.
remove-floating-ip Remove a floating IP address from a server.
rename Rename a server.

View File

@ -134,3 +134,14 @@ class FakeHTTPClient(fakes.FakeHTTPClient):
def delete_os_assisted_volume_snapshots_x(self, **kw):
return (202, {}, {})
def post_os_server_external_events(self, **kw):
return (200, {}, {'events': [
{'name': 'test-event',
'status': 'completed',
'tag': 'tag',
'server_uuid': 'fake-uuid1'},
{'name': 'test-event',
'status': 'completed',
'tag': 'tag',
'server_uuid': 'fake-uuid2'}]})

View File

@ -0,0 +1,44 @@
# Copyright (C) 2014, Red Hat, Inc.
#
# 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.
"""
External event triggering for servers, not to be used by users.
"""
from novaclient import extension
from novaclient.tests import utils
from novaclient.tests.v1_1.contrib import fakes
from novaclient.v1_1.contrib import server_external_events as ext_events
extensions = [
extension.Extension(ext_events.__name__.split(".")[-1],
ext_events),
]
cs = fakes.FakeClient(extensions=extensions)
class ServerExternalEventsTestCase(utils.TestCase):
def test_external_event(self):
events = [{'server_uuid': 'fake-uuid1',
'name': 'test-event',
'status': 'completed',
'tag': 'tag'},
{'server_uuid': 'fake-uuid2',
'name': 'test-event',
'status': 'completed',
'tag': 'tag'}]
result = cs.server_external_events.create(events)
self.assertEqual(events, result)
cs.assert_called('POST', '/os-server-external-events')

View File

@ -1991,3 +1991,8 @@ class FakeHTTPClient(base_client.HTTPClient):
"updated_at": "2012-10-29T13:42:02.000000"
}]}
return (200, {}, migrations)
def post_os_server_external_events(self, **kw):
return (200, {}, {'events': [
{'name': 'network-changed',
'server_uuid': '1234'}]})

View File

@ -946,6 +946,12 @@ class ShellTest(utils.TestCase):
self.run_command('diagnostics sample-server')
self.assert_called('GET', '/servers/1234/diagnostics')
def test_refresh_network(self):
self.run_command('refresh-network 1234')
self.assert_called('POST', '/os-server-external-events',
{'events': [{'name': 'network-changed',
'server_uuid': 1234}]})
def test_set_meta_set(self):
self.run_command('meta 1234 set key1=val1 key2=val2')
self.assert_called('POST', '/servers/1234/metadata',

View File

@ -0,0 +1,43 @@
# Copyright (C) 2014, Red Hat, Inc.
#
# 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.
"""
External event triggering for servers, not to be used by users.
"""
from novaclient import base
class Event(base.Resource):
def __repr__(self):
return "<Event: %s>" % self.name
class ServerExternalEventManager(base.Manager):
resource_class = Event
def create(self, events):
"""Create one or more server events.
:param:events: A list of dictionaries containing 'server_uuid', 'name',
'status', and 'tag' (which may be absent)
"""
body = {'events': events}
return self._create('/os-server-external-events', body, 'events',
return_raw=True)
manager_class = ServerExternalEventManager
name = 'server_external_events'

View File

@ -1366,6 +1366,16 @@ def do_diagnostics(cs, args):
utils.print_dict(cs.servers.diagnostics(server)[1], wrap=80)
@utils.arg('server', metavar='<server>',
help=_('Name or ID of a server for which the network cache should '
'be refreshed from neutron (Admin only).'))
def do_refresh_network(cs, args):
"""Refresh server network information."""
server = _find_server(cs, args.server)
cs.server_external_events.create([{'server_uuid': server.id,
'name': 'network-changed'}])
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
def do_root_password(cs, args):
"""