26707bdbe7
We have git to track authorship, so let's not pad source files with it as well. A hacking check has been added for this. The value is N322. Change-Id: Iab0b64d417e0bb41a6b455e2ac377deee64ec3ee
665 lines
27 KiB
Python
665 lines
27 KiB
Python
# Copyright 2014 IBM Corp.
|
|
#
|
|
# 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 functools
|
|
|
|
from oslo.config import cfg
|
|
|
|
from neutron.common import constants as n_const
|
|
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 agents_db
|
|
from neutron.db import db_base_plugin_v2
|
|
from neutron.db import external_net_db
|
|
from neutron.db import l3_gwmode_db
|
|
from neutron.db import portbindings_db
|
|
from neutron.db import quota_db # noqa
|
|
from neutron.extensions import portbindings
|
|
from neutron.openstack.common import excutils
|
|
from neutron.openstack.common import log as logging
|
|
from neutron.plugins.ibm.common import config # noqa
|
|
from neutron.plugins.ibm.common import constants
|
|
from neutron.plugins.ibm.common import exceptions as sdnve_exc
|
|
from neutron.plugins.ibm import sdnve_api as sdnve
|
|
from neutron.plugins.ibm import sdnve_api_fake as sdnve_fake
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class SdnveRpcCallbacks():
|
|
|
|
def __init__(self, notifier):
|
|
self.notifier = notifier # used to notify the agent
|
|
|
|
def sdnve_info(self, rpc_context, **kwargs):
|
|
'''Update new information.'''
|
|
info = kwargs.get('info')
|
|
# Notify all other listening agents
|
|
self.notifier.info_update(rpc_context, info)
|
|
return info
|
|
|
|
|
|
class AgentNotifierApi(n_rpc.RpcProxy):
|
|
'''Agent side of the SDN-VE rpc API.'''
|
|
|
|
BASE_RPC_API_VERSION = '1.0'
|
|
|
|
def __init__(self, topic):
|
|
super(AgentNotifierApi, self).__init__(
|
|
topic=topic, default_version=self.BASE_RPC_API_VERSION)
|
|
|
|
self.topic_info_update = topics.get_topic_name(topic,
|
|
constants.INFO,
|
|
topics.UPDATE)
|
|
|
|
def info_update(self, context, info):
|
|
self.fanout_cast(context,
|
|
self.make_msg('info_update',
|
|
info=info),
|
|
topic=self.topic_info_update)
|
|
|
|
|
|
def _ha(func):
|
|
'''Supports the high availability feature of the controller.'''
|
|
|
|
@functools.wraps(func)
|
|
def hawrapper(self, *args, **kwargs):
|
|
'''This wrapper sets the new controller if necessary
|
|
|
|
When a controller is detected to be not responding, and a
|
|
new controller is chosen to be used in its place, this decorator
|
|
makes sure the existing integration bridges are set to point
|
|
to the new controller by calling the set_controller method.
|
|
'''
|
|
ret_func = func(self, *args, **kwargs)
|
|
self.set_controller(args[0])
|
|
return ret_func
|
|
return hawrapper
|
|
|
|
|
|
class SdnvePluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
|
external_net_db.External_net_db_mixin,
|
|
portbindings_db.PortBindingMixin,
|
|
l3_gwmode_db.L3_NAT_db_mixin,
|
|
agents_db.AgentDbMixin,
|
|
):
|
|
|
|
'''
|
|
Implement the Neutron abstractions using SDN-VE SDN Controller.
|
|
'''
|
|
|
|
__native_bulk_support = False
|
|
__native_pagination_support = False
|
|
__native_sorting_support = False
|
|
|
|
supported_extension_aliases = ["binding", "router", "external-net",
|
|
"agent", "quotas"]
|
|
|
|
def __init__(self, configfile=None):
|
|
self.base_binding_dict = {
|
|
portbindings.VIF_TYPE: portbindings.VIF_TYPE_OVS,
|
|
portbindings.VIF_DETAILS: {portbindings.CAP_PORT_FILTER: False}}
|
|
|
|
super(SdnvePluginV2, self).__init__()
|
|
self.setup_rpc()
|
|
self.sdnve_controller_select()
|
|
if self.fake_controller:
|
|
self.sdnve_client = sdnve_fake.FakeClient()
|
|
else:
|
|
self.sdnve_client = sdnve.Client()
|
|
|
|
def sdnve_controller_select(self):
|
|
self.fake_controller = cfg.CONF.SDNVE.use_fake_controller
|
|
|
|
def setup_rpc(self):
|
|
# RPC support
|
|
self.topic = topics.PLUGIN
|
|
self.conn = n_rpc.create_connection(new=True)
|
|
self.notifier = AgentNotifierApi(topics.AGENT)
|
|
self.endpoints = [SdnveRpcCallbacks(self.notifier),
|
|
agents_db.AgentExtRpcCallback()]
|
|
self.conn.create_consumer(self.topic, self.endpoints,
|
|
fanout=False)
|
|
# Consume from all consumers in threads
|
|
self.conn.consume_in_threads()
|
|
|
|
def _update_base_binding_dict(self, tenant_type):
|
|
if tenant_type == constants.TENANT_TYPE_OVERLAY:
|
|
self.base_binding_dict[
|
|
portbindings.VIF_TYPE] = portbindings.VIF_TYPE_BRIDGE
|
|
if tenant_type == constants.TENANT_TYPE_OF:
|
|
self.base_binding_dict[
|
|
portbindings.VIF_TYPE] = portbindings.VIF_TYPE_OVS
|
|
|
|
def set_controller(self, context):
|
|
LOG.info(_("Set a new controller if needed."))
|
|
new_controller = self.sdnve_client.sdnve_get_controller()
|
|
if new_controller:
|
|
self.notifier.info_update(
|
|
context,
|
|
{'new_controller': new_controller})
|
|
LOG.info(_("Set the controller to a new controller: %s"),
|
|
new_controller)
|
|
|
|
def _process_request(self, request, current):
|
|
new_request = dict(
|
|
(k, v) for k, v in request.items()
|
|
if v != current.get(k))
|
|
|
|
msg = _("Original SDN-VE HTTP request: %(orig)s; New request: %(new)s")
|
|
LOG.debug(msg, {'orig': request, 'new': new_request})
|
|
return new_request
|
|
|
|
#
|
|
# Network
|
|
#
|
|
|
|
@_ha
|
|
def create_network(self, context, network):
|
|
LOG.debug(_("Create network in progress: %r"), network)
|
|
session = context.session
|
|
|
|
tenant_id = self._get_tenant_id_for_create(context, network['network'])
|
|
# Create a new SDN-VE tenant if need be
|
|
sdnve_tenant = self.sdnve_client.sdnve_check_and_create_tenant(
|
|
tenant_id)
|
|
if sdnve_tenant is None:
|
|
raise sdnve_exc.SdnveException(
|
|
msg=_('Create net failed: no SDN-VE tenant.'))
|
|
|
|
with session.begin(subtransactions=True):
|
|
net = super(SdnvePluginV2, self).create_network(context, network)
|
|
self._process_l3_create(context, net, network['network'])
|
|
|
|
# Create SDN-VE network
|
|
(res, data) = self.sdnve_client.sdnve_create('network', net)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
super(SdnvePluginV2, self).delete_network(context, net['id'])
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Create net failed in SDN-VE: %s') % res))
|
|
|
|
LOG.debug(_("Created network: %s"), net['id'])
|
|
return net
|
|
|
|
@_ha
|
|
def update_network(self, context, id, network):
|
|
LOG.debug(_("Update network in progress: %r"), network)
|
|
session = context.session
|
|
|
|
processed_request = {}
|
|
with session.begin(subtransactions=True):
|
|
original_network = super(SdnvePluginV2, self).get_network(
|
|
context, id)
|
|
processed_request['network'] = self._process_request(
|
|
network['network'], original_network)
|
|
net = super(SdnvePluginV2, self).update_network(
|
|
context, id, network)
|
|
self._process_l3_update(context, net, network['network'])
|
|
|
|
if processed_request['network']:
|
|
(res, data) = self.sdnve_client.sdnve_update(
|
|
'network', id, processed_request['network'])
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
net = super(SdnvePluginV2, self).update_network(
|
|
context, id, {'network': original_network})
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Update net failed in SDN-VE: %s') % res))
|
|
|
|
return net
|
|
|
|
@_ha
|
|
def delete_network(self, context, id):
|
|
LOG.debug(_("Delete network in progress: %s"), id)
|
|
session = context.session
|
|
|
|
with session.begin(subtransactions=True):
|
|
self._process_l3_delete(context, id)
|
|
super(SdnvePluginV2, self).delete_network(context, id)
|
|
|
|
(res, data) = self.sdnve_client.sdnve_delete('network', id)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
LOG.error(
|
|
_("Delete net failed after deleting the network in DB: %s"),
|
|
res)
|
|
|
|
@_ha
|
|
def get_network(self, context, id, fields=None):
|
|
LOG.debug(_("Get network in progress: %s"), id)
|
|
return super(SdnvePluginV2, self).get_network(context, id, fields)
|
|
|
|
@_ha
|
|
def get_networks(self, context, filters=None, fields=None, sorts=None,
|
|
limit=None, marker=None, page_reverse=False):
|
|
LOG.debug(_("Get networks in progress"))
|
|
return super(SdnvePluginV2, self).get_networks(
|
|
context, filters, fields, sorts, limit, marker, page_reverse)
|
|
|
|
#
|
|
# Port
|
|
#
|
|
|
|
@_ha
|
|
def create_port(self, context, port):
|
|
LOG.debug(_("Create port in progress: %r"), port)
|
|
session = context.session
|
|
|
|
# Set port status as 'ACTIVE' to avoid needing the agent
|
|
port['port']['status'] = n_const.PORT_STATUS_ACTIVE
|
|
port_data = port['port']
|
|
|
|
with session.begin(subtransactions=True):
|
|
port = super(SdnvePluginV2, self).create_port(context, port)
|
|
if 'id' not in port:
|
|
return port
|
|
# If the tenant_id is set to '' by create_port, add the id to
|
|
# the request being sent to the controller as the controller
|
|
# requires a tenant id
|
|
tenant_id = port.get('tenant_id')
|
|
if not tenant_id:
|
|
LOG.debug(_("Create port does not have tenant id info"))
|
|
original_network = super(SdnvePluginV2, self).get_network(
|
|
context, port['network_id'])
|
|
original_tenant_id = original_network['tenant_id']
|
|
port['tenant_id'] = original_tenant_id
|
|
LOG.debug(
|
|
_("Create port does not have tenant id info; "
|
|
"obtained is: %s"),
|
|
port['tenant_id'])
|
|
|
|
os_tenant_id = tenant_id
|
|
id_na, tenant_type = self.sdnve_client.sdnve_get_tenant_byid(
|
|
os_tenant_id)
|
|
self._update_base_binding_dict(tenant_type)
|
|
self._process_portbindings_create_and_update(context,
|
|
port_data, port)
|
|
|
|
# NOTE(mb): Remove this block when controller is updated
|
|
# Remove the information that the controller does not accept
|
|
sdnve_port = port.copy()
|
|
sdnve_port.pop('device_id', None)
|
|
sdnve_port.pop('device_owner', None)
|
|
|
|
(res, data) = self.sdnve_client.sdnve_create('port', sdnve_port)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
super(SdnvePluginV2, self).delete_port(context, port['id'])
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Create port failed in SDN-VE: %s') % res))
|
|
|
|
LOG.debug(_("Created port: %s"), port.get('id', 'id not found'))
|
|
return port
|
|
|
|
@_ha
|
|
def update_port(self, context, id, port):
|
|
LOG.debug(_("Update port in progress: %r"), port)
|
|
session = context.session
|
|
|
|
processed_request = {}
|
|
with session.begin(subtransactions=True):
|
|
original_port = super(SdnvePluginV2, self).get_port(
|
|
context, id)
|
|
processed_request['port'] = self._process_request(
|
|
port['port'], original_port)
|
|
updated_port = super(SdnvePluginV2, self).update_port(
|
|
context, id, port)
|
|
|
|
os_tenant_id = updated_port['tenant_id']
|
|
id_na, tenant_type = self.sdnve_client.sdnve_get_tenant_byid(
|
|
os_tenant_id)
|
|
self._update_base_binding_dict(tenant_type)
|
|
self._process_portbindings_create_and_update(context,
|
|
port['port'],
|
|
updated_port)
|
|
|
|
if processed_request['port']:
|
|
(res, data) = self.sdnve_client.sdnve_update(
|
|
'port', id, processed_request['port'])
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
updated_port = super(SdnvePluginV2, self).update_port(
|
|
context, id, {'port': original_port})
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Update port failed in SDN-VE: %s') % res))
|
|
|
|
return updated_port
|
|
|
|
@_ha
|
|
def delete_port(self, context, id, l3_port_check=True):
|
|
LOG.debug(_("Delete port in progress: %s"), id)
|
|
|
|
# if needed, check to see if this is a port owned by
|
|
# an l3-router. If so, we should prevent deletion.
|
|
if l3_port_check:
|
|
self.prevent_l3_port_deletion(context, id)
|
|
self.disassociate_floatingips(context, id)
|
|
|
|
super(SdnvePluginV2, self).delete_port(context, id)
|
|
|
|
(res, data) = self.sdnve_client.sdnve_delete('port', id)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
LOG.error(
|
|
_("Delete port operation failed in SDN-VE "
|
|
"after deleting the port from DB: %s"), res)
|
|
|
|
#
|
|
# Subnet
|
|
#
|
|
|
|
@_ha
|
|
def create_subnet(self, context, subnet):
|
|
LOG.debug(_("Create subnet in progress: %r"), subnet)
|
|
new_subnet = super(SdnvePluginV2, self).create_subnet(context, subnet)
|
|
|
|
# Note(mb): Use of null string currently required by controller
|
|
sdnve_subnet = new_subnet.copy()
|
|
if subnet.get('gateway_ip') is None:
|
|
sdnve_subnet['gateway_ip'] = 'null'
|
|
(res, data) = self.sdnve_client.sdnve_create('subnet', sdnve_subnet)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
super(SdnvePluginV2, self).delete_subnet(context,
|
|
new_subnet['id'])
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Create subnet failed in SDN-VE: %s') % res))
|
|
|
|
LOG.debug(_("Subnet created: %s"), new_subnet['id'])
|
|
|
|
return new_subnet
|
|
|
|
@_ha
|
|
def update_subnet(self, context, id, subnet):
|
|
LOG.debug(_("Update subnet in progress: %r"), subnet)
|
|
session = context.session
|
|
|
|
processed_request = {}
|
|
with session.begin(subtransactions=True):
|
|
original_subnet = super(SdnvePluginV2, self).get_subnet(
|
|
context, id)
|
|
processed_request['subnet'] = self._process_request(
|
|
subnet['subnet'], original_subnet)
|
|
updated_subnet = super(SdnvePluginV2, self).update_subnet(
|
|
context, id, subnet)
|
|
|
|
if processed_request['subnet']:
|
|
# Note(mb): Use of string containing null required by controller
|
|
if 'gateway_ip' in processed_request['subnet']:
|
|
if processed_request['subnet'].get('gateway_ip') is None:
|
|
processed_request['subnet']['gateway_ip'] = 'null'
|
|
(res, data) = self.sdnve_client.sdnve_update(
|
|
'subnet', id, processed_request['subnet'])
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
for key in subnet['subnet'].keys():
|
|
subnet['subnet'][key] = original_subnet[key]
|
|
super(SdnvePluginV2, self).update_subnet(
|
|
context, id, subnet)
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Update subnet failed in SDN-VE: %s') % res))
|
|
|
|
return updated_subnet
|
|
|
|
@_ha
|
|
def delete_subnet(self, context, id):
|
|
LOG.debug(_("Delete subnet in progress: %s"), id)
|
|
super(SdnvePluginV2, self).delete_subnet(context, id)
|
|
|
|
(res, data) = self.sdnve_client.sdnve_delete('subnet', id)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
LOG.error(_("Delete subnet operation failed in SDN-VE after "
|
|
"deleting the subnet from DB: %s"), res)
|
|
|
|
#
|
|
# Router
|
|
#
|
|
|
|
@_ha
|
|
def create_router(self, context, router):
|
|
LOG.debug(_("Create router in progress: %r"), router)
|
|
|
|
if router['router']['admin_state_up'] is False:
|
|
LOG.warning(_('Ignoring admin_state_up=False for router=%r. '
|
|
'Overriding with True'), router)
|
|
router['router']['admin_state_up'] = True
|
|
|
|
tenant_id = self._get_tenant_id_for_create(context, router['router'])
|
|
# Create a new SDN-VE tenant if need be
|
|
sdnve_tenant = self.sdnve_client.sdnve_check_and_create_tenant(
|
|
tenant_id)
|
|
if sdnve_tenant is None:
|
|
raise sdnve_exc.SdnveException(
|
|
msg=_('Create router failed: no SDN-VE tenant.'))
|
|
|
|
new_router = super(SdnvePluginV2, self).create_router(context, router)
|
|
# Create SDN-VE router
|
|
(res, data) = self.sdnve_client.sdnve_create('router', new_router)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
super(SdnvePluginV2, self).delete_router(context, new_router['id'])
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Create router failed in SDN-VE: %s') % res))
|
|
|
|
LOG.debug(_("Router created: %r"), new_router)
|
|
return new_router
|
|
|
|
@_ha
|
|
def update_router(self, context, id, router):
|
|
LOG.debug(_("Update router in progress: id=%(id)s "
|
|
"router=%(router)r"),
|
|
{'id': id, 'router': router})
|
|
session = context.session
|
|
|
|
processed_request = {}
|
|
if not router['router'].get('admin_state_up', True):
|
|
raise n_exc.NotImplementedError(_('admin_state_up=False '
|
|
'routers are not '
|
|
'supported.'))
|
|
|
|
with session.begin(subtransactions=True):
|
|
original_router = super(SdnvePluginV2, self).get_router(
|
|
context, id)
|
|
processed_request['router'] = self._process_request(
|
|
router['router'], original_router)
|
|
updated_router = super(SdnvePluginV2, self).update_router(
|
|
context, id, router)
|
|
|
|
if processed_request['router']:
|
|
egw = processed_request['router'].get('external_gateway_info')
|
|
# Check for existing empty set (different from None) in request
|
|
if egw == {}:
|
|
processed_request['router'][
|
|
'external_gateway_info'] = {'network_id': 'null'}
|
|
(res, data) = self.sdnve_client.sdnve_update(
|
|
'router', id, processed_request['router'])
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
super(SdnvePluginV2, self).update_router(
|
|
context, id, {'router': original_router})
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Update router failed in SDN-VE: %s') % res))
|
|
|
|
return updated_router
|
|
|
|
@_ha
|
|
def delete_router(self, context, id):
|
|
LOG.debug(_("Delete router in progress: %s"), id)
|
|
|
|
super(SdnvePluginV2, self).delete_router(context, id)
|
|
|
|
(res, data) = self.sdnve_client.sdnve_delete('router', id)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
LOG.error(
|
|
_("Delete router operation failed in SDN-VE after "
|
|
"deleting the router in DB: %s"), res)
|
|
|
|
@_ha
|
|
def add_router_interface(self, context, router_id, interface_info):
|
|
LOG.debug(_("Add router interface in progress: "
|
|
"router_id=%(router_id)s "
|
|
"interface_info=%(interface_info)r"),
|
|
{'router_id': router_id, 'interface_info': interface_info})
|
|
|
|
new_interface = super(SdnvePluginV2, self).add_router_interface(
|
|
context, router_id, interface_info)
|
|
LOG.debug(
|
|
_("SdnvePluginV2.add_router_interface called. Port info: %s"),
|
|
new_interface)
|
|
request_info = interface_info.copy()
|
|
request_info['port_id'] = new_interface['port_id']
|
|
# Add the subnet_id to the request sent to the controller
|
|
if 'subnet_id' not in interface_info:
|
|
request_info['subnet_id'] = new_interface['subnet_id']
|
|
|
|
(res, data) = self.sdnve_client.sdnve_update(
|
|
'router', router_id + '/add_router_interface', request_info)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
super(SdnvePluginV2, self).remove_router_interface(
|
|
context, router_id, interface_info)
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Update router-add-interface failed in SDN-VE: %s') %
|
|
res))
|
|
|
|
LOG.debug(_("Added router interface: %r"), new_interface)
|
|
return new_interface
|
|
|
|
def _add_router_interface_only(self, context, router_id, interface_info):
|
|
LOG.debug(_("Add router interface only called: "
|
|
"router_id=%(router_id)s "
|
|
"interface_info=%(interface_info)r"),
|
|
{'router_id': router_id, 'interface_info': interface_info})
|
|
|
|
port_id = interface_info.get('port_id')
|
|
if port_id:
|
|
(res, data) = self.sdnve_client.sdnve_update(
|
|
'router', router_id + '/add_router_interface', interface_info)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
LOG.error(_("SdnvePluginV2._add_router_interface_only: "
|
|
"failed to add the interface in the roll back."
|
|
" of a remove_router_interface operation"))
|
|
|
|
@_ha
|
|
def remove_router_interface(self, context, router_id, interface_info):
|
|
LOG.debug(_("Remove router interface in progress: "
|
|
"router_id=%(router_id)s "
|
|
"interface_info=%(interface_info)r"),
|
|
{'router_id': router_id, 'interface_info': interface_info})
|
|
|
|
subnet_id = interface_info.get('subnet_id')
|
|
port_id = interface_info.get('port_id')
|
|
if not subnet_id:
|
|
if not port_id:
|
|
raise sdnve_exc.BadInputException(msg=_('No port ID'))
|
|
myport = super(SdnvePluginV2, self).get_port(context, port_id)
|
|
LOG.debug(_("SdnvePluginV2.remove_router_interface port: %s"),
|
|
myport)
|
|
myfixed_ips = myport.get('fixed_ips')
|
|
if not myfixed_ips:
|
|
raise sdnve_exc.BadInputException(msg=_('No fixed IP'))
|
|
subnet_id = myfixed_ips[0].get('subnet_id')
|
|
if subnet_id:
|
|
interface_info['subnet_id'] = subnet_id
|
|
LOG.debug(
|
|
_("SdnvePluginV2.remove_router_interface subnet_id: %s"),
|
|
subnet_id)
|
|
else:
|
|
if not port_id:
|
|
# The backend requires port id info in the request
|
|
subnet = super(SdnvePluginV2, self).get_subnet(context,
|
|
subnet_id)
|
|
df = {'device_id': [router_id],
|
|
'device_owner': [n_const.DEVICE_OWNER_ROUTER_INTF],
|
|
'network_id': [subnet['network_id']]}
|
|
ports = self.get_ports(context, filters=df)
|
|
if ports:
|
|
pid = ports[0]['id']
|
|
interface_info['port_id'] = pid
|
|
msg = ("SdnvePluginV2.remove_router_interface "
|
|
"subnet_id: %(sid)s port_id: %(pid)s")
|
|
LOG.debug(msg, {'sid': subnet_id, 'pid': pid})
|
|
|
|
(res, data) = self.sdnve_client.sdnve_update(
|
|
'router', router_id + '/remove_router_interface', interface_info)
|
|
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Update router-remove-interface failed SDN-VE: %s') %
|
|
res))
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
try:
|
|
info = super(SdnvePluginV2, self).remove_router_interface(
|
|
context, router_id, interface_info)
|
|
except Exception:
|
|
with excutils.save_and_reraise_exception():
|
|
self._add_router_interface_only(context,
|
|
router_id, interface_info)
|
|
|
|
return info
|
|
|
|
#
|
|
# Floating Ip
|
|
#
|
|
|
|
@_ha
|
|
def create_floatingip(self, context, floatingip):
|
|
LOG.debug(_("Create floatingip in progress: %r"),
|
|
floatingip)
|
|
new_floatingip = super(SdnvePluginV2, self).create_floatingip(
|
|
context, floatingip)
|
|
|
|
(res, data) = self.sdnve_client.sdnve_create(
|
|
'floatingip', {'floatingip': new_floatingip})
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
super(SdnvePluginV2, self).delete_floatingip(
|
|
context, new_floatingip['id'])
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Creating floating ip operation failed '
|
|
'in SDN-VE controller: %s') % res))
|
|
|
|
LOG.debug(_("Created floatingip : %r"), new_floatingip)
|
|
return new_floatingip
|
|
|
|
@_ha
|
|
def update_floatingip(self, context, id, floatingip):
|
|
LOG.debug(_("Update floatingip in progress: %r"), floatingip)
|
|
session = context.session
|
|
|
|
processed_request = {}
|
|
with session.begin(subtransactions=True):
|
|
original_floatingip = super(
|
|
SdnvePluginV2, self).get_floatingip(context, id)
|
|
processed_request['floatingip'] = self._process_request(
|
|
floatingip['floatingip'], original_floatingip)
|
|
updated_floatingip = super(
|
|
SdnvePluginV2, self).update_floatingip(context, id, floatingip)
|
|
|
|
if processed_request['floatingip']:
|
|
(res, data) = self.sdnve_client.sdnve_update(
|
|
'floatingip', id,
|
|
{'floatingip': processed_request['floatingip']})
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
super(SdnvePluginV2, self).update_floatingip(
|
|
context, id, {'floatingip': original_floatingip})
|
|
raise sdnve_exc.SdnveException(
|
|
msg=(_('Update floating ip failed in SDN-VE: %s') % res))
|
|
|
|
return updated_floatingip
|
|
|
|
@_ha
|
|
def delete_floatingip(self, context, id):
|
|
LOG.debug(_("Delete floatingip in progress: %s"), id)
|
|
super(SdnvePluginV2, self).delete_floatingip(context, id)
|
|
|
|
(res, data) = self.sdnve_client.sdnve_delete('floatingip', id)
|
|
if res not in constants.HTTP_ACCEPTABLE:
|
|
LOG.error(_("Delete floatingip failed in SDN-VE: %s"), res)
|