+++ /dev/null
-[sdnve]
-# (ListOpt) The IP address of one (or more) SDN-VE controllers
-# Default value is: controller_ips = 127.0.0.1
-# Example: controller_ips = 127.0.0.1,127.0.0.2
-# (StrOpt) The integration bridge for OF based implementation
-# The default value for integration_bridge is None
-# Example: integration_bridge = br-int
-# (ListOpt) The interface mapping connecting the integration
-# bridge to external network as a list of physical network names and
-# interfaces: <physical_network_name>:<interface_name>
-# Example: interface_mappings = default:eth2
-# (BoolOpt) Used to reset the integration bridge, if exists
-# The default value for reset_bridge is True
-# Example: reset_bridge = False
-# (BoolOpt) Used to set the OVS controller as out-of-band
-# The default value for out_of_band is True
-# Example: out_of_band = False
-#
-# (BoolOpt) The fake controller for testing purposes
-# Default value is: use_fake_controller = False
-# (StrOpt) The port number for use with controller
-# The default value for the port is 8443
-# Example: port = 8443
-# (StrOpt) The userid for use with controller
-# The default value for the userid is admin
-# Example: userid = sdnve_user
-# (StrOpt) The password for use with controller
-# The default value for the password is admin
-# Example: password = sdnve_password
-#
-# (StrOpt) The default type of tenants (and associated resources)
-# Available choices are: OVERLAY or OF
-# The default value for tenant type is OVERLAY
-# Example: default_tenant_type = OVERLAY
-# (StrOpt) The string in tenant description that indicates
-# Default value for OF tenants: of_signature = SDNVE-OF
-# (StrOpt) The string in tenant description that indicates
-# Default value for OVERLAY tenants: overlay_signature = SDNVE-OVERLAY
-
-[sdnve_agent]
-# (IntOpt) Agent's polling interval in seconds
-# polling_interval = 2
-# (StrOpt) What to use for root helper
-# The default value: root_helper = 'sudo'
-# (BoolOpt) Whether to use rpc or not
-# The default value: rpc = True
-
-[securitygroup]
-# The security group is not supported:
-# firewall_driver = neutron.agent.firewall.NoopFirewallDriver
+++ /dev/null
-IBM SDN-VE Neutron Plugin
-
-This plugin implements Neutron v2 APIs.
-
-For more details on how to use it please refer to the following page:
-http://wiki.openstack.org/wiki/IBM-Neutron
+++ /dev/null
-# 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 socket
-import sys
-import time
-
-import eventlet
-eventlet.monkey_patch()
-
-from oslo_config import cfg
-from oslo_log import log as logging
-import oslo_messaging
-from oslo_service import loopingcall
-import six
-
-from neutron.agent.common import ovs_lib
-from neutron.agent.linux import ip_lib
-from neutron.agent import rpc as agent_rpc
-from neutron.common import config as common_config
-from neutron.common import constants as n_const
-from neutron.common import topics
-from neutron.common import utils as n_utils
-from neutron.i18n import _LE, _LI
-from neutron import context
-from neutron.plugins.ibm.common import constants
-
-
-LOG = logging.getLogger(__name__)
-cfg.CONF.import_group('SDNVE', 'neutron.plugins.ibm.common.config')
-cfg.CONF.import_group('SDNVE_AGENT', 'neutron.plugins.ibm.common.config')
-
-AGENT_TYPE_SDNVE = 'IBM SDN-VE agent'
-
-
-class SdnvePluginApi(agent_rpc.PluginApi):
-
- def sdnve_info(self, context, info):
- cctxt = self.client.prepare()
- return cctxt.call(context, 'sdnve_info', info=info)
-
-
-class SdnveNeutronAgent(object):
-
- target = oslo_messaging.Target(version='1.1')
-
- def __init__(self, integ_br, interface_mappings,
- info, polling_interval,
- controller_ip, reset_br, out_of_band):
- '''The agent initialization.
-
- Sets the following parameters and sets up the integration
- bridge and physical interfaces if need be.
- :param integ_br: name of the integration bridge.
- :param interface_mappings: interfaces to physical networks.
- :param info: local IP address of this hypervisor.
- :param polling_interval: interval (secs) to poll DB.
- :param controller_ip: Ip address of SDN-VE controller.
- '''
-
- super(SdnveNeutronAgent, self).__init__()
- self.int_bridge_name = integ_br
- self.controller_ip = controller_ip
- self.interface_mappings = interface_mappings
- self.polling_interval = polling_interval
- self.info = info
- self.reset_br = reset_br
- self.out_of_band = out_of_band
-
- self.agent_state = {
- 'binary': 'neutron-sdnve-agent',
- 'host': cfg.CONF.host,
- 'topic': n_const.L2_AGENT_TOPIC,
- 'configurations': {'interface_mappings': interface_mappings,
- 'reset_br': self.reset_br,
- 'out_of_band': self.out_of_band,
- 'controller_ip': self.controller_ip},
- 'agent_type': AGENT_TYPE_SDNVE,
- 'start_flag': True}
-
- if self.int_bridge_name:
- self.int_br = self.setup_integration_br(integ_br, reset_br,
- out_of_band,
- self.controller_ip)
- self.setup_physical_interfaces(self.interface_mappings)
- else:
- self.int_br = None
-
- self.setup_rpc()
-
- def _report_state(self):
- try:
- self.state_rpc.report_state(self.context,
- self.agent_state)
- self.agent_state.pop('start_flag', None)
- except Exception:
- LOG.exception(_LE("Failed reporting state!"))
-
- def setup_rpc(self):
- if self.int_br:
- mac = self.int_br.get_local_port_mac()
- self.agent_id = '%s%s' % ('sdnve', (mac.replace(":", "")))
- else:
- nameaddr = socket.gethostbyname(socket.gethostname())
- self.agent_id = '%s%s' % ('sdnve_', (nameaddr.replace(".", "_")))
-
- self.topic = topics.AGENT
- self.plugin_rpc = SdnvePluginApi(topics.PLUGIN)
- self.state_rpc = agent_rpc.PluginReportStateAPI(topics.PLUGIN)
-
- self.context = context.get_admin_context_without_session()
- self.endpoints = [self]
- consumers = [[constants.INFO, topics.UPDATE]]
-
- self.connection = agent_rpc.create_consumers(self.endpoints,
- self.topic,
- consumers)
- if self.polling_interval:
- heartbeat = loopingcall.FixedIntervalLoopingCall(
- self._report_state)
- heartbeat.start(interval=self.polling_interval)
-
- # Plugin calls the agents through the following
- def info_update(self, context, **kwargs):
- LOG.debug("info_update received")
- info = kwargs.get('info', {})
- new_controller = info.get('new_controller')
- out_of_band = info.get('out_of_band')
- if self.int_br and new_controller:
- LOG.debug("info_update received. New controller "
- "is to be set to: %s", new_controller)
- self.int_br.set_controller(["tcp:" + new_controller])
- if out_of_band:
- LOG.debug("info_update received. New controller "
- "is set to be out of band")
- self.int_br.set_db_attribute("Controller",
- self.int_bridge_name,
- "connection-mode",
- "out-of-band")
-
- def setup_integration_br(self, bridge_name, reset_br, out_of_band,
- controller_ip=None):
- '''Sets up the integration bridge.
-
- Create the bridge and remove all existing flows if reset_br is True.
- Otherwise, creates the bridge if not already existing.
- :param bridge_name: the name of the integration bridge.
- :param reset_br: A boolean to rest the bridge if True.
- :param out_of_band: A boolean indicating controller is out of band.
- :param controller_ip: IP address to use as the bridge controller.
- :returns: the integration bridge
- '''
-
- int_br = ovs_lib.OVSBridge(bridge_name)
- if reset_br:
- int_br.reset_bridge()
- int_br.remove_all_flows()
- else:
- int_br.create()
-
- # set the controller
- if controller_ip:
- int_br.set_controller(["tcp:" + controller_ip])
- if out_of_band:
- int_br.set_db_attribute("Controller", bridge_name,
- "connection-mode", "out-of-band")
-
- return int_br
-
- def setup_physical_interfaces(self, interface_mappings):
- '''Sets up the physical network interfaces.
-
- Link physical interfaces to the integration bridge.
- :param interface_mappings: map physical net names to interface names.
- '''
-
- for physical_network, interface in six.iteritems(interface_mappings):
- LOG.info(_LI("Mapping physical network %(physical_network)s to "
- "interface %(interface)s"),
- {'physical_network': physical_network,
- 'interface': interface})
- # Connect the physical interface to the bridge
- if not ip_lib.device_exists(interface):
- LOG.error(_LE("Interface %(interface)s for physical network "
- "%(physical_network)s does not exist. Agent "
- "terminated!"),
- {'physical_network': physical_network,
- 'interface': interface})
- raise SystemExit(1)
- self.int_br.add_port(interface)
-
- def sdnve_info(self):
- details = self.plugin_rpc.sdnve_info(
- self.context,
- {'info': self.info})
- return details
-
- def rpc_loop(self):
-
- while True:
- start = time.time()
- LOG.debug("Agent in the rpc loop.")
-
- # sleep till end of polling interval
- elapsed = (time.time() - start)
- if (elapsed < self.polling_interval):
- time.sleep(self.polling_interval - elapsed)
- else:
- LOG.info(_LI("Loop iteration exceeded interval "
- "(%(polling_interval)s vs. %(elapsed)s)!"),
- {'polling_interval': self.polling_interval,
- 'elapsed': elapsed})
-
- def daemon_loop(self):
- self.rpc_loop()
-
-
-def create_agent_config_map(config):
- interface_mappings = n_utils.parse_mappings(
- config.SDNVE.interface_mappings)
-
- controller_ips = config.SDNVE.controller_ips
- LOG.info(_LI("Controller IPs: %s"), controller_ips)
- controller_ip = controller_ips[0]
-
- return {
- 'integ_br': config.SDNVE.integration_bridge,
- 'interface_mappings': interface_mappings,
- 'controller_ip': controller_ip,
- 'info': config.SDNVE.info,
- 'polling_interval': config.SDNVE_AGENT.polling_interval,
- 'reset_br': config.SDNVE.reset_bridge,
- 'out_of_band': config.SDNVE.out_of_band}
-
-
-def main():
- cfg.CONF.register_opts(ip_lib.OPTS)
- common_config.init(sys.argv[1:])
- common_config.setup_logging()
-
- try:
- agent_config = create_agent_config_map(cfg.CONF)
- except ValueError as e:
- LOG.exception(_LE("%s Agent terminated!"), e)
- raise SystemExit(1)
-
- plugin = SdnveNeutronAgent(**agent_config)
-
- # Start everything.
- LOG.info(_LI("Agent initialized successfully, now running... "))
- plugin.daemon_loop()
+++ /dev/null
-# 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.
-
-
-from oslo_config import cfg
-
-
-DEFAULT_INTERFACE_MAPPINGS = []
-DEFAULT_CONTROLLER_IPS = ['127.0.0.1']
-
-sdnve_opts = [
- cfg.BoolOpt('use_fake_controller', default=False,
- help=_("Whether to use a fake controller.")),
- cfg.StrOpt('base_url', default='/one/nb/v2/',
- help=_("Base URL for SDN-VE controller REST API.")),
- cfg.ListOpt('controller_ips', default=DEFAULT_CONTROLLER_IPS,
- help=_("List of IP addresses of SDN-VE controller(s).")),
- cfg.StrOpt('info', default='sdnve_info_string',
- help=_("SDN-VE RPC subject.")),
- cfg.StrOpt('port', default='8443',
- help=_("SDN-VE controller port number.")),
- cfg.StrOpt('format', default='json',
- help=_("SDN-VE request/response format.")),
- cfg.StrOpt('userid', default='admin',
- help=_("SDN-VE administrator user ID.")),
- cfg.StrOpt('password', default='admin', secret=True,
- help=_("SDN-VE administrator password.")),
- cfg.StrOpt('integration_bridge',
- help=_("Integration bridge to use.")),
- cfg.BoolOpt('reset_bridge', default=True,
- help=_("Whether to reset the integration bridge before use.")),
- cfg.BoolOpt('out_of_band', default=True,
- help=_("Indicating if controller is out of band or not.")),
- cfg.ListOpt('interface_mappings',
- default=DEFAULT_INTERFACE_MAPPINGS,
- help=_("List of <physical_network_name>:<interface_name> "
- "mappings.")),
- cfg.StrOpt('default_tenant_type', default='OVERLAY',
- help=_("Tenant type: OVERLAY (default) or OF.")),
- cfg.StrOpt('overlay_signature', default='SDNVE-OVERLAY',
- help=_("The string in tenant description that indicates "
- "the tenant is a OVERLAY tenant.")),
- cfg.StrOpt('of_signature', default='SDNVE-OF',
- help=_("The string in tenant description that indicates "
- "the tenant is a OF tenant.")),
-]
-
-sdnve_agent_opts = [
- cfg.IntOpt('polling_interval', default=2,
- help=_("Agent polling interval if necessary.")),
- cfg.BoolOpt('rpc', default=True,
- help=_("Whether to use rpc.")),
-
-]
-
-
-cfg.CONF.register_opts(sdnve_opts, "SDNVE")
-cfg.CONF.register_opts(sdnve_agent_opts, "SDNVE_AGENT")
+++ /dev/null
-# 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.
-
-
-from six.moves import http_client as httplib
-
-# Topic for info notifications between the plugin and agent
-INFO = 'info'
-
-TENANT_TYPE_OF = 'OF'
-TENANT_TYPE_OVERLAY = 'OVERLAY'
-
-HTTP_ACCEPTABLE = [httplib.OK,
- httplib.CREATED,
- httplib.ACCEPTED,
- httplib.NO_CONTENT
- ]
+++ /dev/null
-# 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.
-
-from neutron.common import exceptions
-
-
-class SdnveException(exceptions.NeutronException):
- message = _("An unexpected error occurred in the SDN-VE Plugin. "
- "Here is the error message: %(msg)s")
-
-
-class BadInputException(exceptions.BadRequest):
- message = _("The input does not contain nececessary info: %(msg)s")
+++ /dev/null
-# 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.
-
-
-from six.moves import http_client as httplib
-
-import httplib2
-from keystoneclient.v2_0 import client as keyclient
-from oslo_config import cfg
-from oslo_log import log as logging
-from six.moves.urllib import parse
-
-from neutron.api.v2 import attributes
-from neutron.common import utils
-from neutron.i18n import _LE, _LI
-from neutron.plugins.ibm.common import config # noqa
-from neutron.plugins.ibm.common import constants
-from neutron import wsgi
-
-LOG = logging.getLogger(__name__)
-
-SDNVE_VERSION = '2.0'
-SDNVE_ACTION_PREFIX = '/sdnve'
-SDNVE_RETRIES = 0
-SDNVE_RETRIY_INTERVAL = 1
-SDNVE_TENANT_TYPE_OVERLAY = u'DOVE'
-SDNVE_URL = 'https://%s:%s%s'
-
-
-class RequestHandler(object):
- '''Handles processing requests to and responses from controller.'''
-
- def __init__(self, controller_ips=None, port=None, ssl=None,
- base_url=None, userid=None, password=None,
- timeout=10, formats=None):
- '''Initializes the RequestHandler for communication with controller
-
- Following keyword arguments are used; if not specified, default
- values are used.
- :param port: Username for authentication.
- :param timeout: Time out for http requests.
- :param userid: User id for accessing controller.
- :param password: Password for accessing the controller.
- :param base_url: The base url for the controller.
- :param controller_ips: List of controller IP addresses.
- :param formats: Supported formats.
- '''
- self.port = port or cfg.CONF.SDNVE.port
- self.timeout = timeout
- self._s_meta = None
- self.connection = None
- self.httpclient = httplib2.Http(
- disable_ssl_certificate_validation=True)
- self.cookie = None
-
- userid = userid or cfg.CONF.SDNVE.userid
- password = password or cfg.CONF.SDNVE.password
- if (userid and password):
- self.httpclient.add_credentials(userid, password)
-
- self.base_url = base_url or cfg.CONF.SDNVE.base_url
- self.controller_ips = controller_ips or cfg.CONF.SDNVE.controller_ips
-
- LOG.info(_LI("The IP addr of available SDN-VE controllers: %s"),
- self.controller_ips)
- self.controller_ip = self.controller_ips[0]
- LOG.info(_LI("The SDN-VE controller IP address: %s"),
- self.controller_ip)
-
- self.new_controller = False
- self.format = formats or cfg.CONF.SDNVE.format
-
- self.version = SDNVE_VERSION
- self.action_prefix = SDNVE_ACTION_PREFIX
- self.retries = SDNVE_RETRIES
- self.retry_interval = SDNVE_RETRIY_INTERVAL
-
- def serialize(self, data):
- '''Serializes a dictionary with a single key.'''
-
- if isinstance(data, dict):
- return wsgi.Serializer().serialize(data, self.content_type())
- elif data:
- raise TypeError(_("unable to serialize object type: '%s'") %
- type(data))
-
- def deserialize(self, data, status_code):
- '''Deserializes an xml or json string into a dictionary.'''
-
- # NOTE(mb): Temporary fix for backend controller requirement
- data = data.replace("router_external", "router:external")
-
- if status_code == httplib.NO_CONTENT:
- return data
- try:
- deserialized_data = wsgi.Serializer(
- metadata=self._s_meta).deserialize(data, self.content_type())
- deserialized_data = deserialized_data['body']
- except Exception:
- deserialized_data = data
-
- return deserialized_data
-
- def content_type(self, format=None):
- '''Returns the mime-type for either 'xml' or 'json'.'''
-
- return 'application/%s' % (format or self.format)
-
- def delete(self, url, body=None, headers=None, params=None):
- return self.do_request("DELETE", url, body=body,
- headers=headers, params=params)
-
- def get(self, url, body=None, headers=None, params=None):
- return self.do_request("GET", url, body=body,
- headers=headers, params=params)
-
- def post(self, url, body=None, headers=None, params=None):
- return self.do_request("POST", url, body=body,
- headers=headers, params=params)
-
- def put(self, url, body=None, headers=None, params=None):
- return self.do_request("PUT", url, body=body,
- headers=headers, params=params)
-
- def do_request(self, method, url, body=None, headers=None,
- params=None, connection_type=None):
-
- status_code = -1
- replybody_deserialized = ''
-
- if body:
- body = self.serialize(body)
-
- self.headers = headers or {'Content-Type': self.content_type()}
- if self.cookie:
- self.headers['cookie'] = self.cookie
-
- if self.controller_ip != self.controller_ips[0]:
- controllers = [self.controller_ip]
- else:
- controllers = []
- controllers.extend(self.controller_ips)
-
- for controller_ip in controllers:
- serverurl = SDNVE_URL % (controller_ip, self.port, self.base_url)
- myurl = serverurl + url
- if params and isinstance(params, dict):
- myurl += '?' + parse.urlencode(params, doseq=1)
-
- try:
- LOG.debug("Sending request to SDN-VE. url: "
- "%(myurl)s method: %(method)s body: "
- "%(body)s header: %(header)s ",
- {'myurl': myurl, 'method': method,
- 'body': body, 'header': self.headers})
- resp, replybody = self.httpclient.request(
- myurl, method=method, body=body, headers=self.headers)
- LOG.debug("Response recd from SDN-VE. resp: %(resp)s "
- "body: %(body)s",
- {'resp': resp.status, 'body': replybody})
- status_code = resp.status
-
- except Exception as e:
- LOG.error(_LE("Error: Could not reach server: %(url)s "
- "Exception: %(excp)s."),
- {'url': myurl, 'excp': e})
- self.cookie = None
- continue
-
- if status_code not in constants.HTTP_ACCEPTABLE:
- LOG.debug("Error message: %(reply)s -- Status: %(status)s",
- {'reply': replybody, 'status': status_code})
- else:
- LOG.debug("Received response status: %s", status_code)
-
- if resp.get('set-cookie'):
- self.cookie = resp['set-cookie']
- replybody_deserialized = self.deserialize(
- replybody,
- status_code)
- LOG.debug("Deserialized body: %s", replybody_deserialized)
- if controller_ip != self.controller_ip:
- # bcast the change of controller
- self.new_controller = True
- self.controller_ip = controller_ip
-
- return (status_code, replybody_deserialized)
-
- return (httplib.REQUEST_TIMEOUT, 'Could not reach server(s)')
-
-
-class Client(RequestHandler):
- '''Client for SDNVE controller.'''
-
- def __init__(self):
- '''Initialize a new SDNVE client.'''
- super(Client, self).__init__()
-
- self.keystoneclient = KeystoneClient()
-
- resource_path = {
- 'network': "ln/networks/",
- 'subnet': "ln/subnets/",
- 'port': "ln/ports/",
- 'tenant': "ln/tenants/",
- 'router': "ln/routers/",
- 'floatingip': "ln/floatingips/",
- }
-
- def process_request(self, body):
- '''Processes requests according to requirements of controller.'''
- if self.format == 'json':
- body = dict(
- (k.replace(':', '_'), v) for k, v in body.items()
- if attributes.is_attr_set(v))
- return body
-
- def sdnve_list(self, resource, **params):
- '''Fetches a list of resources.'''
-
- res = self.resource_path.get(resource, None)
- if not res:
- LOG.info(_LI("Bad resource for forming a list request"))
- return 0, ''
-
- return self.get(res, params=params)
-
- def sdnve_show(self, resource, specific, **params):
- '''Fetches information of a certain resource.'''
-
- res = self.resource_path.get(resource, None)
- if not res:
- LOG.info(_LI("Bad resource for forming a show request"))
- return 0, ''
-
- return self.get(res + specific, params=params)
-
- def sdnve_create(self, resource, body):
- '''Creates a new resource.'''
-
- res = self.resource_path.get(resource, None)
- if not res:
- LOG.info(_LI("Bad resource for forming a create request"))
- return 0, ''
-
- body = self.process_request(body)
- status, data = self.post(res, body=body)
- return (status, data)
-
- def sdnve_update(self, resource, specific, body=None):
- '''Updates a resource.'''
-
- res = self.resource_path.get(resource, None)
- if not res:
- LOG.info(_LI("Bad resource for forming a update request"))
- return 0, ''
-
- body = self.process_request(body)
- return self.put(res + specific, body=body)
-
- def sdnve_delete(self, resource, specific):
- '''Deletes the specified resource.'''
-
- res = self.resource_path.get(resource, None)
- if not res:
- LOG.info(_LI("Bad resource for forming a delete request"))
- return 0, ''
-
- return self.delete(res + specific)
-
- def _tenant_id_conversion(self, osid):
- return osid
-
- def sdnve_get_tenant_byid(self, os_tenant_id):
- sdnve_tenant_id = self._tenant_id_conversion(os_tenant_id)
- resp, content = self.sdnve_show('tenant', sdnve_tenant_id)
- if resp in constants.HTTP_ACCEPTABLE:
- tenant_id = content.get('id')
- tenant_type = content.get('network_type')
- if tenant_type == SDNVE_TENANT_TYPE_OVERLAY:
- tenant_type = constants.TENANT_TYPE_OVERLAY
- return tenant_id, tenant_type
- return None, None
-
- def sdnve_check_and_create_tenant(self, os_tenant_id, network_type=None):
-
- if not os_tenant_id:
- return
- tenant_id, tenant_type = self.sdnve_get_tenant_byid(os_tenant_id)
- if tenant_id:
- if not network_type:
- return tenant_id
- if tenant_type != network_type:
- LOG.info(_LI("Non matching tenant and network types: "
- "%(ttype)s %(ntype)s"),
- {'ttype': tenant_type, 'ntype': network_type})
- return
- return tenant_id
-
- # Have to create a new tenant
- sdnve_tenant_id = self._tenant_id_conversion(os_tenant_id)
- if not network_type:
- network_type = self.keystoneclient.get_tenant_type(os_tenant_id)
- if network_type == constants.TENANT_TYPE_OVERLAY:
- network_type = SDNVE_TENANT_TYPE_OVERLAY
-
- pinn_desc = ("Created by SDN-VE Neutron Plugin, OS project name = " +
- self.keystoneclient.get_tenant_name(os_tenant_id))
-
- res, content = self.sdnve_create('tenant',
- {'id': sdnve_tenant_id,
- 'name': os_tenant_id,
- 'network_type': network_type,
- 'description': pinn_desc})
- if res not in constants.HTTP_ACCEPTABLE:
- return
-
- return sdnve_tenant_id
-
- def sdnve_get_controller(self):
- if self.new_controller:
- self.new_controller = False
- return self.controller_ip
-
-
-class KeystoneClient(object):
-
- def __init__(self, username=None, tenant_name=None, password=None,
- auth_url=None):
-
- keystone_conf = cfg.CONF.keystone_authtoken
-
- username = username or keystone_conf.admin_user
- tenant_name = tenant_name or keystone_conf.admin_tenant_name
- password = password or keystone_conf.admin_password
- # FIXME(ihrachys): plugins should not construct keystone URL
- # from configuration file and should instead rely on service
- # catalog contents
- auth_url = auth_url or utils.get_keystone_url(keystone_conf)
-
- self.overlay_signature = cfg.CONF.SDNVE.overlay_signature
- self.of_signature = cfg.CONF.SDNVE.of_signature
- self.default_tenant_type = cfg.CONF.SDNVE.default_tenant_type
-
- self.client = keyclient.Client(username=username,
- password=password,
- tenant_name=tenant_name,
- auth_url=auth_url)
-
- def get_tenant_byid(self, id):
-
- try:
- return self.client.tenants.get(id)
- except Exception:
- LOG.exception(_LE("Did not find tenant: %r"), id)
-
- def get_tenant_type(self, id):
-
- tenant = self.get_tenant_byid(id)
- if tenant:
- description = tenant.description
- if description:
- if (description.find(self.overlay_signature) >= 0):
- return constants.TENANT_TYPE_OVERLAY
- if (description.find(self.of_signature) >= 0):
- return constants.TENANT_TYPE_OF
- return self.default_tenant_type
-
- def get_tenant_name(self, id):
-
- tenant = self.get_tenant_byid(id)
- if tenant:
- return tenant.name
- return 'not found'
+++ /dev/null
-# 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.
-
-from oslo_log import log as logging
-
-from neutron.i18n import _LI
-from neutron.plugins.ibm.common import constants
-
-LOG = logging.getLogger(__name__)
-
-HTTP_OK = 200
-
-
-class FakeClient(object):
-
- '''Fake Client for SDNVE controller.'''
-
- def __init__(self, **kwargs):
- LOG.info(_LI('Fake SDNVE controller initialized'))
-
- def sdnve_list(self, resource, **_params):
- LOG.info(_LI('Fake SDNVE controller: list'))
- return (HTTP_OK, None)
-
- def sdnve_show(self, resource, specific, **_params):
- LOG.info(_LI('Fake SDNVE controller: show'))
- return (HTTP_OK, None)
-
- def sdnve_create(self, resource, body):
- LOG.info(_LI('Fake SDNVE controller: create'))
- return (HTTP_OK, None)
-
- def sdnve_update(self, resource, specific, body=None):
- LOG.info(_LI('Fake SDNVE controller: update'))
- return (HTTP_OK, None)
-
- def sdnve_delete(self, resource, specific):
- LOG.info(_LI('Fake SDNVE controller: delete'))
- return (HTTP_OK, None)
-
- def sdnve_get_tenant_byid(self, id):
- LOG.info(_LI('Fake SDNVE controller: get tenant by id'))
- return id, constants.TENANT_TYPE_OF
-
- def sdnve_check_and_create_tenant(self, id, network_type=None):
- LOG.info(_LI('Fake SDNVE controller: check and create tenant'))
- return id
-
- def sdnve_get_controller(self):
- LOG.info(_LI('Fake SDNVE controller: get controller'))
- return None
+++ /dev/null
-# 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 oslo_log import log as logging
-import oslo_messaging
-from oslo_utils import excutils
-
-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.extensions import portbindings
-from neutron.i18n import _LE, _LI, _LW
-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(object):
-
- 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(object):
- '''Agent side of the SDN-VE rpc API.'''
-
- def __init__(self, topic):
- target = oslo_messaging.Target(topic=topic, version='1.0')
- self.client = n_rpc.get_client(target)
- self.topic_info_update = topics.get_topic_name(topic,
- constants.INFO,
- topics.UPDATE)
-
- def info_update(self, context, info):
- cctxt = self.client.prepare(topic=self.topic_info_update, fanout=True)
- cctxt.cast(context, 'info_update', info=info)
-
-
-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(_LI("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(_LI("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(
- _LE("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(
- _LE("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(_LE("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(_LW('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(
- _LE("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(_LE("SdnvePluginV2._add_router_interface_only: "
- "failed to add the interface in the roll back."
- " of a remove_router_interface operation"))
-
- def _find_router_port_by_subnet_id(self, ports, subnet_id):
- for p in ports:
- subnet_ids = [fip['subnet_id'] for fip in p['fixed_ips']]
- if subnet_id in subnet_ids:
- return p['id']
-
- @_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 = self._find_router_port_by_subnet_id(ports, subnet_id)
- if not pid:
- raise sdnve_exc.SdnveException(
- msg=(_('Update router-remove-interface '
- 'failed SDN-VE: subnet %(sid) is not '
- 'associated with any ports on router '
- '%(rid)'), {'sid': subnet_id,
- 'rid': router_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:
- if not port_id:
- # port_id was not originally given in interface_info,
- # so we want to remove the interface by subnet instead
- # of port
- del interface_info['port_id']
- 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(_LE("Delete floatingip failed in SDN-VE: %s"), res)
+++ /dev/null
-# 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 mock
-from oslo_config import cfg
-
-from neutron.agent.linux import ip_lib
-from neutron.plugins.ibm.agent import sdnve_neutron_agent
-from neutron.tests import base
-
-
-NOTIFIER = ('neutron.plugins.ibm.'
- 'sdnve_neutron_plugin.AgentNotifierApi')
-
-
-class CreateAgentConfigMap(base.BaseTestCase):
-
- def test_create_agent_config_map_succeeds(self):
- self.assertTrue(sdnve_neutron_agent.create_agent_config_map(cfg.CONF))
-
- def test_create_agent_config_using_controller_ips(self):
- cfg.CONF.set_override('controller_ips',
- ['10.10.10.1', '10.10.10.2'], group='SDNVE')
- cfgmap = sdnve_neutron_agent.create_agent_config_map(cfg.CONF)
- self.assertEqual(cfgmap['controller_ip'], '10.10.10.1')
-
- def test_create_agent_config_using_interface_mappings(self):
- cfg.CONF.set_override('interface_mappings',
- ['interface1 : eth1', 'interface2 : eth2'],
- group='SDNVE')
- cfgmap = sdnve_neutron_agent.create_agent_config_map(cfg.CONF)
- self.assertEqual(cfgmap['interface_mappings'],
- {'interface1': 'eth1', 'interface2': 'eth2'})
-
-
-class TestSdnveNeutronAgent(base.BaseTestCase):
-
- def setUp(self):
- super(TestSdnveNeutronAgent, self).setUp()
- notifier_p = mock.patch(NOTIFIER)
- notifier_cls = notifier_p.start()
- self.notifier = mock.Mock()
- notifier_cls.return_value = self.notifier
- cfg.CONF.set_override('integration_bridge',
- 'br_int', group='SDNVE')
- kwargs = sdnve_neutron_agent.create_agent_config_map(cfg.CONF)
-
- class MockFixedIntervalLoopingCall(object):
- def __init__(self, f):
- self.f = f
-
- def start(self, interval=0):
- self.f()
-
- with mock.patch('neutron.plugins.ibm.agent.sdnve_neutron_agent.'
- 'SdnveNeutronAgent.setup_integration_br',
- return_value=mock.Mock()),\
- mock.patch('oslo_service.loopingcall.'
- 'FixedIntervalLoopingCall',
- new=MockFixedIntervalLoopingCall):
- self.agent = sdnve_neutron_agent.SdnveNeutronAgent(**kwargs)
-
- def test_setup_physical_interfaces(self):
- with mock.patch.object(self.agent.int_br,
- 'add_port') as add_port_func:
- with mock.patch.object(ip_lib,
- 'device_exists',
- return_valxue=True):
- self.agent.setup_physical_interfaces({"interface1": "eth1"})
- add_port_func.assert_called_once_with('eth1')
-
- def test_setup_physical_interfaces_none(self):
- with mock.patch.object(self.agent.int_br,
- 'add_port') as add_port_func:
- with mock.patch.object(ip_lib,
- 'device_exists',
- return_valxue=True):
- self.agent.setup_physical_interfaces({})
- self.assertFalse(add_port_func.called)
-
- def test_get_info_set_controller(self):
- with mock.patch.object(self.agent.int_br,
- 'set_controller') as set_controller_func:
- kwargs = {}
- kwargs['info'] = {'new_controller': '10.10.10.1'}
- self.agent.info_update('dummy', **kwargs)
- set_controller_func.assert_called_once_with(['tcp:10.10.10.1'])
-
- def test_get_info(self):
- with mock.patch.object(self.agent.int_br,
- 'set_controller') as set_controller_func:
- kwargs = {}
- self.agent.info_update('dummy', **kwargs)
- self.assertFalse(set_controller_func.called)
+++ /dev/null
-# 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 mock
-from oslo_utils import uuidutils
-
-from neutron.plugins.ibm.common import constants
-from neutron.plugins.ibm import sdnve_api
-from neutron.tests import base
-
-RESOURCE_PATH = {
- 'network': "ln/networks/",
-}
-RESOURCE = 'network'
-HTTP_OK = 200
-TENANT_ID = uuidutils.generate_uuid()
-
-
-class TestSdnveApi(base.BaseTestCase):
-
- def setUp(self):
- super(TestSdnveApi, self).setUp()
-
- class MockKeystoneClient(object):
- def __init__(self, **kwargs):
- pass
-
- def get_tenant_name(self, id):
- return 'test tenant name'
-
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'KeystoneClient',
- new=MockKeystoneClient):
- self.api = sdnve_api.Client()
-
- def mock_do_request(self, method, url, body=None, headers=None,
- params=None, connection_type=None):
- return (HTTP_OK, url)
-
- def mock_do_request_tenant(self, method, url, body=None, headers=None,
- params=None, connection_type=None):
- return (HTTP_OK, {'id': TENANT_ID,
- 'network_type': constants.TENANT_TYPE_OF})
-
- def mock_do_request_no_tenant(self, method, url, body=None, headers=None,
- params=None, connection_type=None):
- return (None, None)
-
- def mock_process_request(self, body):
- return body
-
- def test_sdnve_api_list(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.do_request',
- new=self.mock_do_request):
- result = self.api.sdnve_list(RESOURCE)
- self.assertEqual(result, (HTTP_OK, RESOURCE_PATH[RESOURCE]))
-
- def test_sdnve_api_show(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.do_request',
- new=self.mock_do_request):
- result = self.api.sdnve_show(RESOURCE, TENANT_ID)
- self.assertEqual(result,
- (HTTP_OK, RESOURCE_PATH[RESOURCE] + TENANT_ID))
-
- def test_sdnve_api_create(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.do_request',
- new=self.mock_do_request):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.process_request',
- new=self.mock_process_request):
- result = self.api.sdnve_create(RESOURCE, '')
- self.assertEqual(result, (HTTP_OK, RESOURCE_PATH[RESOURCE]))
-
- def test_sdnve_api_update(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.do_request',
- new=self.mock_do_request):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.process_request',
- new=self.mock_process_request):
- result = self.api.sdnve_update(RESOURCE, TENANT_ID, '')
- self.assertEqual(result,
- (HTTP_OK,
- RESOURCE_PATH[RESOURCE] + TENANT_ID))
-
- def test_sdnve_api_delete(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.do_request',
- new=self.mock_do_request):
- result = self.api.sdnve_delete(RESOURCE, TENANT_ID)
- self.assertEqual(result,
- (HTTP_OK, RESOURCE_PATH[RESOURCE] + TENANT_ID))
-
- def test_sdnve_get_tenant_by_id(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.do_request',
- new=self.mock_do_request_tenant):
- id = TENANT_ID
- result = self.api.sdnve_get_tenant_byid(id)
- self.assertEqual(result,
- (TENANT_ID, constants.TENANT_TYPE_OF))
-
- def test_sdnve_check_and_create_tenant(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.do_request',
- new=self.mock_do_request_tenant):
- id = TENANT_ID
- result = self.api.sdnve_check_and_create_tenant(id)
- self.assertEqual(result, TENANT_ID)
-
- def test_sdnve_check_and_create_tenant_fail(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.'
- 'Client.do_request',
- new=self.mock_do_request_no_tenant):
- id = TENANT_ID
- result = self.api.sdnve_check_and_create_tenant(
- id, constants.TENANT_TYPE_OF)
- self.assertIsNone(result)
-
- def test_process_request(self):
- my_request = {'key_1': 'value_1', 'router:external': 'True',
- 'key_2': 'value_2'}
- expected = {'key_1': 'value_1', 'router_external': 'True',
- 'key_2': 'value_2'}
- result = self.api.process_request(my_request)
- self.assertEqual(expected, result)
+++ /dev/null
-# 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 mock
-
-from neutron.extensions import portbindings
-from neutron.tests.unit import _test_extension_portbindings as test_bindings
-from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
-from neutron.tests.unit.extensions import test_l3 as test_l3
-
-from neutron.plugins.ibm.common import constants
-
-
-_plugin_name = ('neutron.plugins.ibm.'
- 'sdnve_neutron_plugin.SdnvePluginV2')
-HTTP_OK = 200
-
-
-class MockClient(object):
- def sdnve_list(self, resource, **params):
- return (HTTP_OK, 'body')
-
- def sdnve_show(self, resource, specific, **params):
- return (HTTP_OK, 'body')
-
- def sdnve_create(self, resource, body):
- return (HTTP_OK, 'body')
-
- def sdnve_update(self, resource, specific, body=None):
- return (HTTP_OK, 'body')
-
- def sdnve_delete(self, resource, specific):
- return (HTTP_OK, 'body')
-
- def sdnve_get_tenant_byid(self, os_tenant_id):
- return (os_tenant_id, constants.TENANT_TYPE_OF)
-
- def sdnve_check_and_create_tenant(
- self, os_tenant_id, network_type=None):
- return os_tenant_id
-
- def sdnve_get_controller(self):
- return
-
-
-class MockKeystoneClient(object):
- def __init__(self, **kwargs):
- pass
-
- def get_tenant_type(self, id):
- return constants.TENANT_TYPE_OF
-
- def get_tenant_name(self, id):
- return "tenant name"
-
-
-class IBMPluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
- def setUp(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.' 'KeystoneClient',
- new=MockKeystoneClient),\
- mock.patch('neutron.plugins.ibm.sdnve_api.' 'Client',
- new=MockClient):
- super(IBMPluginV2TestCase, self).setUp(plugin=_plugin_name)
-
-
-class TestIBMBasicGet(test_plugin.TestBasicGet,
- IBMPluginV2TestCase):
- pass
-
-
-class TestIBMV2HTTPResponse(test_plugin.TestV2HTTPResponse,
- IBMPluginV2TestCase):
- pass
-
-
-class TestIBMNetworksV2(test_plugin.TestNetworksV2,
- IBMPluginV2TestCase):
- pass
-
-
-class TestIBMPortsV2(test_plugin.TestPortsV2,
- IBMPluginV2TestCase):
- pass
-
-
-class TestIBMSubnetsV2(test_plugin.TestSubnetsV2,
- IBMPluginV2TestCase):
- pass
-
-
-class TestIBMPortBinding(IBMPluginV2TestCase,
- test_bindings.PortBindingsTestCase):
- VIF_TYPE = portbindings.VIF_TYPE_OVS
-
-
-class IBMPluginRouterTestCase(test_l3.L3NatDBIntTestCase):
-
- def setUp(self):
- with mock.patch('neutron.plugins.ibm.sdnve_api.' 'KeystoneClient',
- new=MockKeystoneClient),\
- mock.patch('neutron.plugins.ibm.sdnve_api.' 'Client',
- new=MockClient):
- super(IBMPluginRouterTestCase, self).setUp(plugin=_plugin_name)
-
- def test_floating_port_status_not_applicable(self):
- self.skipTest('Plugin changes floating port status')
etc/neutron/plugins/cisco/cisco_router_plugin.ini
etc/neutron/plugins/cisco/cisco_vpn_agent.ini
etc/neutron/plugins/embrane = etc/neutron/plugins/embrane/heleos_conf.ini
- etc/neutron/plugins/ibm = etc/neutron/plugins/ibm/sdnve_neutron_plugin.ini
etc/neutron/plugins/midonet = etc/neutron/plugins/midonet/midonet.ini
etc/neutron/plugins/ml2 =
etc/neutron/plugins/bigswitch/restproxy.ini
neutron-dhcp-agent = neutron.cmd.eventlet.agents.dhcp:main
neutron-hyperv-agent = neutron.cmd.eventlet.plugins.hyperv_neutron_agent:main
neutron-keepalived-state-change = neutron.cmd.keepalived_state_change:main
- neutron-ibm-agent = neutron.plugins.ibm.agent.sdnve_neutron_agent:main
neutron-ipset-cleanup = neutron.cmd.ipset_cleanup:main
neutron-l3-agent = neutron.cmd.eventlet.agents.l3:main
neutron-linuxbridge-agent = neutron.plugins.ml2.drivers.linuxbridge.agent.linuxbridge_neutron_agent:main
brocade = neutron.plugins.brocade.NeutronPlugin:BrocadePluginV2
cisco = neutron.plugins.cisco.network_plugin:PluginV2
embrane = neutron.plugins.embrane.plugins.embrane_ml2_plugin:EmbraneMl2Plugin
- ibm = neutron.plugins.ibm.sdnve_neutron_plugin:SdnvePluginV2
midonet = neutron.plugins.midonet.plugin:MidonetPluginV2
ml2 = neutron.plugins.ml2.plugin:Ml2Plugin
nuage = neutron.plugins.nuage.plugin:NuagePlugin