Provide rpc for port status update
Tricircle Neutron plugin provides rpc for bottom service to update port status in top layer. Change-Id: I0ffff9cec472af9ac725815715f3373ee5949018
This commit is contained in:
parent
2b1f7aa559
commit
80d037fb4e
48
tricircle/common/rpc.py
Normal file
48
tricircle/common/rpc.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 neutron.common.rpc as neutron_rpc
|
||||||
|
import neutron.common.topics as neutron_topics
|
||||||
|
import neutron.context as neutron_context
|
||||||
|
from oslo_config import cfg
|
||||||
|
import oslo_messaging
|
||||||
|
|
||||||
|
|
||||||
|
class NetworkingRpcApi(object):
|
||||||
|
def __init__(self):
|
||||||
|
if not neutron_rpc.TRANSPORT:
|
||||||
|
neutron_rpc.init(cfg.CONF)
|
||||||
|
target = oslo_messaging.Target(topic=neutron_topics.PLUGIN,
|
||||||
|
version='1.0')
|
||||||
|
self.client = neutron_rpc.get_client(target)
|
||||||
|
|
||||||
|
# adapt tricircle context to neutron context
|
||||||
|
def _make_neutron_context(self, context):
|
||||||
|
return neutron_context.ContextBase(context.user, context.tenant,
|
||||||
|
auth_token=context.auth_token,
|
||||||
|
is_admin=context.is_admin,
|
||||||
|
request_id=context.request_id,
|
||||||
|
user_name=context.user_name,
|
||||||
|
tenant_name=context.tenant_name)
|
||||||
|
|
||||||
|
def update_port_up(self, context, port_id):
|
||||||
|
call_context = self.client.prepare()
|
||||||
|
return call_context.call(self._make_neutron_context(context),
|
||||||
|
'update_port_up', port_id=port_id)
|
||||||
|
|
||||||
|
def update_port_down(self, context, port_id):
|
||||||
|
call_context = self.client.prepare()
|
||||||
|
return call_context.call(self._make_neutron_context(context),
|
||||||
|
'update_port_down', port_id=port_id)
|
@ -14,10 +14,14 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
|
import oslo_log.helpers as log_helpers
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
from neutron.extensions import portbindings
|
from neutron.extensions import portbindings
|
||||||
|
|
||||||
|
from neutron.common import exceptions as n_exc
|
||||||
|
from neutron.common import rpc as n_rpc
|
||||||
|
from neutron.common import topics
|
||||||
from neutron.db import agentschedulers_db
|
from neutron.db import agentschedulers_db
|
||||||
from neutron.db import db_base_plugin_v2
|
from neutron.db import db_base_plugin_v2
|
||||||
from neutron.db import external_net_db
|
from neutron.db import external_net_db
|
||||||
@ -27,6 +31,7 @@ from neutron.db import portbindings_db
|
|||||||
from neutron.db import securitygroups_db
|
from neutron.db import securitygroups_db
|
||||||
from neutron.i18n import _LI
|
from neutron.i18n import _LI
|
||||||
from tricircle.common import cascading_networking_api as c_net_api
|
from tricircle.common import cascading_networking_api as c_net_api
|
||||||
|
from tricircle.networking_tricircle import rpc as c_net_rpc
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -60,6 +65,18 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
|
|
||||||
self._cascading_rpc_api = c_net_api.CascadingNetworkingNotifyAPI()
|
self._cascading_rpc_api = c_net_api.CascadingNetworkingNotifyAPI()
|
||||||
|
|
||||||
|
self._setup_rpc()
|
||||||
|
|
||||||
|
def _setup_rpc(self):
|
||||||
|
self.endpoints = [c_net_rpc.RpcCallbacks()]
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def start_rpc_listeners(self):
|
||||||
|
self.topic = topics.PLUGIN
|
||||||
|
self.conn = n_rpc.create_connection(new=True)
|
||||||
|
self.conn.create_consumer(self.topic, self.endpoints, fanout=False)
|
||||||
|
return self.conn.consume_in_threads()
|
||||||
|
|
||||||
def create_network(self, context, network):
|
def create_network(self, context, network):
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
result = super(TricirclePlugin, self).create_network(
|
result = super(TricirclePlugin, self).create_network(
|
||||||
@ -118,6 +135,19 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
|
def update_port_status(self, context, port_id, port_status):
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
try:
|
||||||
|
port = super(TricirclePlugin, self).get_port(context, port_id)
|
||||||
|
port['status'] = port_status
|
||||||
|
neutron_db = super(TricirclePlugin, self).update_port(
|
||||||
|
context, port_id, {'port': port})
|
||||||
|
except n_exc.PortNotFound:
|
||||||
|
LOG.debug("Port %(port)s update to %(status)s not found",
|
||||||
|
{'port': port_id, 'status': port_status})
|
||||||
|
return None
|
||||||
|
return neutron_db
|
||||||
|
|
||||||
def extend_port_dict_binding(self, port_res, port_db):
|
def extend_port_dict_binding(self, port_res, port_db):
|
||||||
super(TricirclePlugin, self).extend_port_dict_binding(
|
super(TricirclePlugin, self).extend_port_dict_binding(
|
||||||
port_res, port_db)
|
port_res, port_db)
|
||||||
|
38
tricircle/networking_tricircle/rpc.py
Normal file
38
tricircle/networking_tricircle/rpc.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 neutron.common.constants as neutron_const
|
||||||
|
from neutron import manager
|
||||||
|
from oslo_log import log
|
||||||
|
import oslo_messaging
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class RpcCallbacks(object):
|
||||||
|
|
||||||
|
target = oslo_messaging.Target(version='1.0')
|
||||||
|
|
||||||
|
def update_port_up(self, context, **kwargs):
|
||||||
|
port_id = kwargs.get('port_id')
|
||||||
|
plugin = manager.NeutronManager.get_plugin()
|
||||||
|
plugin.update_port_status(context, port_id,
|
||||||
|
neutron_const.PORT_STATUS_ACTIVE)
|
||||||
|
|
||||||
|
def update_port_down(self, context, **kwargs):
|
||||||
|
port_id = kwargs.get('port_id')
|
||||||
|
plugin = manager.NeutronManager.get_plugin()
|
||||||
|
plugin.update_port_status(context, port_id,
|
||||||
|
neutron_const.PORT_STATUS_DOWN)
|
76
tricircle/tests/unit/networking_tricircle/test_plugin.py
Normal file
76
tricircle/tests/unit/networking_tricircle/test_plugin.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 mock
|
||||||
|
from mock import patch
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from neutron.common import constants as neutron_const
|
||||||
|
from neutron.common import exceptions as neutron_exceptions
|
||||||
|
from neutron.common import rpc as neutron_rpc
|
||||||
|
from neutron.db import db_base_plugin_v2
|
||||||
|
|
||||||
|
from tricircle import context
|
||||||
|
from tricircle.networking_tricircle.plugin import TricirclePlugin
|
||||||
|
|
||||||
|
|
||||||
|
FAKE_PORT_ID = 'fake_port_uuid'
|
||||||
|
FAKE_PORT = {
|
||||||
|
'id': FAKE_PORT_ID,
|
||||||
|
'status': neutron_const.PORT_STATUS_DOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def fake_get_port(instance, context, port_id):
|
||||||
|
if port_id == FAKE_PORT_ID:
|
||||||
|
return FAKE_PORT
|
||||||
|
else:
|
||||||
|
raise neutron_exceptions.PortNotFound(port_id=port_id)
|
||||||
|
|
||||||
|
|
||||||
|
def fake_update_port(instance, context, port_id, port):
|
||||||
|
FAKE_PORT['status'] = port['port']['status']
|
||||||
|
return FAKE_PORT
|
||||||
|
|
||||||
|
|
||||||
|
class TricirclePluginTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
FAKE_PORT['status'] = neutron_const.PORT_STATUS_DOWN
|
||||||
|
|
||||||
|
@patch.object(neutron_rpc, 'get_client', new=mock.Mock())
|
||||||
|
@patch.object(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
'update_port', new=fake_update_port)
|
||||||
|
@patch.object(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
'get_port', new=fake_get_port)
|
||||||
|
def test_update_port_status(self):
|
||||||
|
plugin = TricirclePlugin()
|
||||||
|
# this method requires a neutron context, but for test we just pass
|
||||||
|
# a tricircle context
|
||||||
|
port = plugin.update_port_status(context.Context(), FAKE_PORT_ID,
|
||||||
|
neutron_const.PORT_STATUS_ACTIVE)
|
||||||
|
self.assertEqual(FAKE_PORT['status'], neutron_const.PORT_STATUS_ACTIVE)
|
||||||
|
self.assertIsNotNone(port)
|
||||||
|
|
||||||
|
@patch.object(neutron_rpc, 'get_client', new=mock.Mock())
|
||||||
|
@patch.object(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
'update_port', new=fake_update_port)
|
||||||
|
@patch.object(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
'get_port', new=fake_get_port)
|
||||||
|
def test_update_port_status_port_not_found(self):
|
||||||
|
plugin = TricirclePlugin()
|
||||||
|
port = plugin.update_port_status(context.Context(), 'no_such_port',
|
||||||
|
neutron_const.PORT_STATUS_ACTIVE)
|
||||||
|
self.assertEqual(FAKE_PORT['status'], neutron_const.PORT_STATUS_DOWN)
|
||||||
|
self.assertIsNone(port)
|
59
tricircle/tests/unit/networking_tricircle/test_rpc.py
Normal file
59
tricircle/tests/unit/networking_tricircle/test_rpc.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 mock
|
||||||
|
from mock import patch
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from neutron.common import constants as neutron_const
|
||||||
|
from neutron.common import rpc as neutron_rpc
|
||||||
|
from neutron import manager
|
||||||
|
|
||||||
|
from tricircle.networking_tricircle import plugin
|
||||||
|
from tricircle.networking_tricircle import rpc
|
||||||
|
|
||||||
|
|
||||||
|
FAKE_PORT_ID = 'fake_port_uuid'
|
||||||
|
FAKE_CONTEXT = object()
|
||||||
|
|
||||||
|
|
||||||
|
class RpcCallbacksTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.callbacks = rpc.RpcCallbacks()
|
||||||
|
|
||||||
|
@patch.object(neutron_rpc, 'get_client', new=mock.Mock())
|
||||||
|
def test_update_port_up(self):
|
||||||
|
with patch.object(manager.NeutronManager,
|
||||||
|
'get_plugin') as get_plugin_method:
|
||||||
|
with patch.object(plugin.TricirclePlugin,
|
||||||
|
'update_port_status') as update_method:
|
||||||
|
get_plugin_method.return_value = plugin.TricirclePlugin()
|
||||||
|
self.callbacks.update_port_up(FAKE_CONTEXT,
|
||||||
|
port_id=FAKE_PORT_ID)
|
||||||
|
update_method.assert_called_once_with(
|
||||||
|
FAKE_CONTEXT, FAKE_PORT_ID,
|
||||||
|
neutron_const.PORT_STATUS_ACTIVE)
|
||||||
|
|
||||||
|
@patch.object(neutron_rpc, 'get_client', new=mock.Mock())
|
||||||
|
def test_update_port_down(self):
|
||||||
|
with patch.object(manager.NeutronManager,
|
||||||
|
'get_plugin') as get_plugin_method:
|
||||||
|
with patch.object(plugin.TricirclePlugin,
|
||||||
|
'update_port_status') as update_method:
|
||||||
|
get_plugin_method.return_value = plugin.TricirclePlugin()
|
||||||
|
self.callbacks.update_port_down(FAKE_CONTEXT,
|
||||||
|
port_id=FAKE_PORT_ID)
|
||||||
|
update_method.assert_called_once_with(
|
||||||
|
FAKE_CONTEXT, FAKE_PORT_ID, neutron_const.PORT_STATUS_DOWN)
|
Loading…
Reference in New Issue
Block a user