Add version to consoleauth rpc API.

Part of blueprint versioned-rpc-apis.

Change-Id: I9682bdbd06d744141b94385992b37cd2e55b8f5e
This commit is contained in:
Russell Bryant 2012-05-04 22:56:11 -04:00
parent 1b6aa2d1af
commit 9ec9fdce62
8 changed files with 164 additions and 24 deletions

View File

@ -33,6 +33,7 @@ from nova.compute import power_state
from nova.compute import task_states
from nova.compute import vm_states
from nova import crypto
from nova.consoleauth import rpcapi as consoleauth_rpcapi
from nova.db import base
from nova import exception
from nova import flags
@ -162,6 +163,7 @@ class API(BaseAPI):
self.network_api = network_api or network.API()
self.volume_api = volume_api or volume.API()
self.consoleauth_rpcapi = consoleauth_rpcapi.ConsoleAuthAPI()
super(API, self).__init__(**kwargs)
def _check_injected_file_quota(self, context, injected_files):
@ -1630,14 +1632,9 @@ class API(BaseAPI):
connect_info = self._call_compute_message('get_vnc_console',
context, instance, params={"console_type": console_type})
rpc.call(context, '%s' % FLAGS.consoleauth_topic,
{'method': 'authorize_console',
'args': {'token': connect_info['token'],
'console_type': console_type,
'host': connect_info['host'],
'port': connect_info['port'],
'internal_access_path':
connect_info['internal_access_path']}})
self.consoleauth_rpcapi.authorize_console(context,
connect_info['token'], console_type, connect_info['host'],
connect_info['port'], connect_info['internal_access_path'])
return {'url': connect_info['access_url']}

View File

@ -45,6 +45,8 @@ FLAGS.register_opts(consoleauth_opts)
class ConsoleAuthManager(manager.Manager):
"""Manages token based authentication."""
RPC_API_VERSION = '1.0'
def __init__(self, scheduler_driver=None, *args, **kwargs):
super(ConsoleAuthManager, self).__init__(*args, **kwargs)
self.tokens = {}

View File

@ -0,0 +1,53 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012, 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.
"""
Client side of the consoleauth RPC API.
"""
from nova import flags
import nova.rpc.proxy
FLAGS = flags.FLAGS
class ConsoleAuthAPI(nova.rpc.proxy.RpcProxy):
'''Client side of the consoleauth rpc API.
API version history:
1.0 - Initial version.
'''
RPC_API_VERSION = '1.0'
def __init__(self):
super(ConsoleAuthAPI, self).__init__(topic=FLAGS.consoleauth_topic,
default_version=self.RPC_API_VERSION)
def authorize_console(self, ctxt, token, console_type, host, port,
internal_access_path):
# The remote side doesn't return anything, but we want to block
# until it completes.
return self.call(ctxt,
self.make_msg('authorize_console',
token=token, console_type=console_type,
host=host, port=port,
internal_access_path=internal_access_path))
def check_token(self, ctxt, token):
return self.call(ctxt, self.make_msg('check_token', token=token))

View File

@ -0,0 +1,19 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack LLC.
# 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.
# NOTE(vish): this forces the fixtures from tests/__init.py:setup() to work
from nova.tests import *

View File

@ -41,7 +41,7 @@ class ConsoleauthTestCase(test.TestCase):
def setUp(self):
super(ConsoleauthTestCase, self).setUp()
self.manager = importutils.import_object(FLAGS.consoleauth_manager)
self.manager = manager.ConsoleAuthManager()
self.context = context.get_admin_context()
def test_tokens_expire(self):

View File

@ -0,0 +1,74 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012, 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.
"""
Unit Tests for nova.consoleauth.rpcapi
"""
from nova.consoleauth import rpcapi as consoleauth_rpcapi
from nova import context
from nova import flags
from nova import rpc
from nova import test
FLAGS = flags.FLAGS
class ConsoleAuthRpcAPITestCase(test.TestCase):
def setUp(self):
super(ConsoleAuthRpcAPITestCase, self).setUp()
def tearDown(self):
super(ConsoleAuthRpcAPITestCase, self).tearDown()
def _test_consoleauth_api(self, method, **kwargs):
ctxt = context.RequestContext('fake_user', 'fake_project')
rpcapi = consoleauth_rpcapi.ConsoleAuthAPI()
expected_retval = 'foo'
expected_msg = rpcapi.make_msg(method, **kwargs)
expected_msg['version'] = rpcapi.RPC_API_VERSION
self.call_ctxt = None
self.call_topic = None
self.call_msg = None
self.call_timeout = None
def _fake_call(_ctxt, _topic, _msg, _timeout):
self.call_ctxt = _ctxt
self.call_topic = _topic
self.call_msg = _msg
self.call_timeout = _timeout
return expected_retval
self.stubs.Set(rpc, 'call', _fake_call)
retval = getattr(rpcapi, method)(ctxt, **kwargs)
self.assertEqual(retval, expected_retval)
self.assertEqual(self.call_ctxt, ctxt)
self.assertEqual(self.call_topic, FLAGS.consoleauth_topic)
self.assertEqual(self.call_msg, expected_msg)
self.assertEqual(self.call_timeout, None)
def test_authorize_console(self):
self._test_consoleauth_api('authorize_console', token='token',
console_type='ctype', host='h', port='p',
internal_access_path='iap')
def test_check_token(self):
self._test_consoleauth_api('check_token', token='t')

View File

@ -3484,26 +3484,23 @@ class ComputeAPITestCase(BaseTestCase):
'console_type': fake_console_type,
'host': 'fake_console_host',
'port': 'fake_console_port',
'internal_access_path': 'fake_access_path',
'access_url': 'fake_console_url'}
'internal_access_path': 'fake_access_path'}
fake_connect_info2 = copy.deepcopy(fake_connect_info)
fake_connect_info2['access_url'] = 'fake_console_url'
self.mox.StubOutWithMock(rpc, 'call')
rpc_msg1 = {'method': 'get_vnc_console',
'args': {'instance_uuid': fake_instance['uuid'],
'console_type': fake_console_type}}
# 2nd rpc.call receives almost everything from fake_connect_info
# except 'access_url'
rpc_msg2_args = dict([(k, v)
for k, v in fake_connect_info.items()
if k != 'access_url'])
rpc_msg2 = {'method': 'authorize_console',
'args': rpc_msg2_args}
'args': fake_connect_info,
'version': '1.0'}
rpc.call(self.context, 'compute.%s' % fake_instance['host'],
rpc_msg1).AndReturn(fake_connect_info)
rpc_msg1).AndReturn(fake_connect_info2)
rpc.call(self.context, FLAGS.consoleauth_topic,
rpc_msg2).AndReturn(None)
rpc_msg2, None).AndReturn(None)
self.mox.ReplayAll()

View File

@ -26,6 +26,7 @@ import eventlet.green
import eventlet.greenio
import eventlet.wsgi
from nova.consoleauth import rpcapi as consoleauth_rpcapi
from nova import context
from nova import flags
from nova import log as logging
@ -49,8 +50,6 @@ xvp_proxy_opts = [
FLAGS = flags.FLAGS
FLAGS.register_opts(xvp_proxy_opts)
flags.DECLARE('consoleauth_topic', 'nova.consoleauth')
class XCPVNCProxy(object):
"""Class to use the xvp auth protocol to proxy instance vnc consoles."""
@ -145,9 +144,8 @@ class XCPVNCProxy(object):
return "Invalid Request"
ctxt = context.get_admin_context()
connect_info = rpc.call(ctxt, FLAGS.consoleauth_topic,
{'method': 'check_token',
'args': {'token': token}})
api = consoleauth_rpcapi.ConsoleAuthAPI()
connect_info = api.check_token(ctxt, token)
if not connect_info:
LOG.audit(_("Request made with invalid token: %s"), req)