-# Config file for Neutron PLUMgrid plugin
+# Config file for Neutron PLUMgrid Plugin
-[plumgridnos]
-# This line should be pointing to the NOS server,
-# for the PLUMgrid platform. In other deployments,
-# this is known as controller
-# nos_server=<nos-ip-address>
-# nos_server_port=<nos-port>
-# Authentification parameters for the NOS server.
+[PLUMgridDirector]
+# This line should be pointing to the PLUMgrid Director,
+# for the PLUMgrid platform.
+# director_server=<director-ip-address>
+# director_server_port=<director-port>
+# Authentification parameters for the Director.
# These are the admin credentials to manage and control
-# the NOS server.
-# username=<nos-admin-username>
-# password=<nos-admin-password>
+# the PLUMgrid Director server.
+# username=<director-admin-username>
+# password=<director-admin-password>
# servertimeout=5
-# Name of the network topology to be deployed by NOS
-# topologyname=<nos-topology-name>
VIF_TYPE_UNBOUND = 'unbound'
VIF_TYPE_BINDING_FAILED = 'binding_failed'
+VIF_TYPE_IOVISOR = 'iovisor'
VIF_TYPE_OVS = 'ovs'
VIF_TYPE_IVS = 'ivs'
VIF_TYPE_BRIDGE = 'bridge'
-PLUMgrid Neutron Virtual Network Plugin
+PLUMgrid Neutron Plugin for Virtual Network Infrastructure (VNI)
This plugin implements Neutron v2 APIs and helps configure
L2/L3 virtual networks consisting of PLUMgrid Platform.
+Implements External Networks and Port Binding Extension
For more details on use please refer to:
-http://wiki.openstack.org/plumgrid-neutron
+http://wiki.openstack.org/PLUMgrid-Neutron
class PLUMgridConnectionFailed(PLUMgridException):
- message = _("Connection failed with PLUMgrid NOS: %(err_msg)s")
+ message = _("Connection failed with PLUMgrid Director: %(err_msg)s")
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright 2013 PLUMgrid, Inc. 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.
+#
+# @author: Edgar Magana, emagana@plumgrid.com, PLUMgrid, Inc.
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright 2013 PLUMgrid, Inc. 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.
+#
+# @author: Edgar Magana, emagana@plumgrid.com, PLUMgrid, Inc.
+
+
+from neutron.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+
+class Plumlib():
+ """
+ Class PLUMgrid Fake Library. This library is a by-pass implementation
+ for the PLUMgrid Library. This class is being used by the unit test
+ integration in Neutron.
+ """
+
+ def __init__(self):
+ LOG.info('Python PLUMgrid Fake Library Started ')
+ pass
+
+ def director_conn(self, director_plumgrid, director_port, timeout):
+ LOG.info('Fake Director: %s', director_plumgrid + ':' + director_port)
+ pass
+
+ def create_network(self, tenant_id, net_db):
+ pass
+
+ def update_network(self, tenant_id, net_id):
+ pass
+
+ def delete_network(self, net_db, net_id):
+ pass
+
+ def create_subnet(self, sub_db, net_db, ipnet):
+ pass
+
+ def update_subnet(self, org_sub_db, new_sub_db, ipnet):
+ pass
+
+ def delete_subnet(self, tenant_id, net_db, net_id):
+ pass
+
+ def create_port(self, port_db, router_db):
+ pass
+
+ def update_port(self, port_db, router_db):
+ pass
+
+ def delete_port(self, port_db, router_db):
+ pass
+
+ def create_router(self, tenant_id, router_db):
+ pass
+
+ def update_router(self, router_db, router_id):
+ pass
+
+ def delete_router(self, tenant_id, router_id):
+ pass
+
+ def add_router_interface(self, tenant_id, router_id, port_db, ipnet):
+ pass
+
+ def remove_router_interface(self, tenant_id, net_id, router_id):
+ pass
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright 2013 PLUMgrid, Inc. 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.
+#
+# @author: Edgar Magana, emagana@plumgrid.com, PLUMgrid, Inc.
+
+"""
+Neutron Plug-in for PLUMgrid Virtual Networking Infrastructure (VNI)
+This plugin will forward authenticated REST API calls
+to the PLUMgrid Network Management System called Director
+"""
+
+from plumgridlib import plumlib
+
+from neutron.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+
+class Plumlib(object):
+ """
+ Class PLUMgrid Python Library. This library is a third-party tool
+ needed by PLUMgrid plugin to implement all core API in Neutron.
+ """
+
+ def __init__(self):
+ LOG.info('Python PLUMgrid Library Started ')
+
+ def director_conn(self, director_plumgrid, director_port, timeout):
+ self.plumlib = plumlib.Plumlib(director_plumgrid,
+ director_port,
+ timeout)
+
+ def create_network(self, tenant_id, net_db):
+ self.plumlib.create_network(tenant_id, net_db)
+
+ def update_network(self, tenant_id, net_id):
+ self.plumlib.update_network(tenant_id, net_id)
+
+ def delete_network(self, net_db, net_id):
+ self.plumlib.delete_network(net_db, net_id)
+
+ def create_subnet(self, sub_db, net_db, ipnet):
+ self.plumlib.create_subnet(sub_db, net_db, ipnet)
+
+ def update_subnet(self, org_sub_db, new_sub_db, ipnet):
+ self.plumlib.update_subnet(org_sub_db, new_sub_db, ipnet)
+
+ def delete_subnet(self, tenant_id, net_db, net_id):
+ self.plumlib.delete_subnet(tenant_id, net_db, net_id)
+
+ def create_port(self, port_db, router_db):
+ self.plumlib.create_port(port_db, router_db)
+
+ def update_port(self, port_db, router_db):
+ self.plumlib.update_port(port_db, router_db)
+
+ def delete_port(self, port_db, router_db):
+ self.plumlib.delete_port(port_db, router_db)
+
+ def create_router(self, tenant_id, router_db):
+ self.plumlib.create_router(tenant_id, router_db)
+
+ def update_router(self, router_db, router_id):
+ self.plumlib.update_router(router_db, router_id)
+
+ def delete_router(self, tenant_id, router_id):
+ self.plumlib.delete_router(tenant_id, router_id)
+
+ def add_router_interface(self, tenant_id, router_id, port_db, ipnet):
+ self.plumlib.add_router_interface(tenant_id, router_id, port_db, ipnet)
+
+ def remove_router_interface(self, tenant_id, net_id, router_id):
+ self.plumlib.remove_router_interface(tenant_id, net_id, router_id)
+++ /dev/null
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2013 PLUMgrid, Inc. 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.
-#
-# @author: Edgar Magana, emagana@plumgrid.com, PLUMgrid, Inc.
-# @author: Brenden Blanco, bblanco@plumgrid.com, PLUMgrid, Inc.
-
-"""
-Snippets needed by the PLUMgrid Plugin
-"""
-
-from neutron.openstack.common import log as logging
-
-
-LOG = logging.getLogger(__name__)
-
-
-class DataNOSPLUMgrid():
-
- BASE_NOS_URL = '/0/connectivity/domain/'
-
- def __init__(self):
- LOG.info(_('NeutronPluginPLUMgrid Status: NOS Body Data Creation'))
-
- def create_domain_body_data(self, tenant_id):
- body_data = {"container_group": tenant_id}
- return body_data
-
- def create_network_body_data(self, tenant_id, topology_name):
- body_data = {"config_template": "single_bridge",
- "container_group": tenant_id,
- "topology_name": topology_name}
- return body_data
+++ /dev/null
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2013 PLUMgrid, Inc. 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.
-#
-# @author: Edgar Magana, emagana@plumgrid.com, PLUMgrid, Inc.
-
-"""
-Neutron PLUMgrid Plug-in for PLUMgrid Virtual Technology
-This plugin will forward authenticated REST API calls
-to the Network Operating System by PLUMgrid called NOS
-"""
-
-from oslo.config import cfg
-
-from neutron.db import api as db
-from neutron.db import db_base_plugin_v2
-from neutron.openstack.common import log as logging
-from neutron.plugins.plumgrid.common import exceptions as plum_excep
-from neutron.plugins.plumgrid.plumgrid_nos_plugin.plugin_ver import VERSION
-from neutron.plugins.plumgrid.plumgrid_nos_plugin import plumgrid_nos_snippets
-from neutron.plugins.plumgrid.plumgrid_nos_plugin import rest_connection
-
-
-LOG = logging.getLogger(__name__)
-
-
-nos_server_opts = [
- cfg.StrOpt('nos_server', default='localhost',
- help=_("PLUMgrid NOS server to connect to")),
- cfg.StrOpt('nos_server_port', default='8080',
- help=_("PLUMgrid NOS server port to connect to")),
- cfg.StrOpt('username', default='username',
- help=_("PLUMgrid NOS admin username")),
- cfg.StrOpt('password', default='password', secret=True,
- help=_("PLUMgrid NOS admin password")),
- cfg.IntOpt('servertimeout', default=5,
- help=_("PLUMgrid NOS server timeout")),
- cfg.StrOpt('topologyname', default='t1',
- help=_("PLUMgrid NOS topology name")), ]
-
-
-cfg.CONF.register_opts(nos_server_opts, "PLUMgridNOS")
-
-
-class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2):
-
- def __init__(self):
- LOG.info(_('NeutronPluginPLUMgrid Status: Starting Plugin'))
-
- # PLUMgrid NOS configuration
- nos_plumgrid = cfg.CONF.PLUMgridNOS.nos_server
- nos_port = cfg.CONF.PLUMgridNOS.nos_server_port
- timeout = cfg.CONF.PLUMgridNOS.servertimeout
- self.topology_name = cfg.CONF.PLUMgridNOS.topologyname
- self.snippets = plumgrid_nos_snippets.DataNOSPLUMgrid()
-
- # TODO(Edgar) These are placeholders for next PLUMgrid release
- cfg.CONF.PLUMgridNOS.username
- cfg.CONF.PLUMgridNOS.password
- self.rest_conn = rest_connection.RestConnection(nos_plumgrid,
- nos_port, timeout)
- if self.rest_conn is None:
- raise SystemExit(_('NeutronPluginPLUMgrid Status: '
- 'Aborting Plugin'))
-
- else:
- # Plugin DB initialization
- db.configure_db()
-
- # PLUMgrid NOS info validation
- LOG.info(_('NeutronPluginPLUMgrid NOS: %s'), nos_plumgrid)
- if not nos_plumgrid:
- raise SystemExit(_('NeutronPluginPLUMgrid Status: '
- 'NOS value is missing in config file'))
-
- LOG.debug(_('NeutronPluginPLUMgrid Status: Neutron server with '
- 'PLUMgrid Plugin has started'))
-
- def create_network(self, context, network):
- """Create network core Neutron API."""
-
- LOG.debug(_('NeutronPluginPLUMgrid Status: create_network() called'))
-
- # Plugin DB - Network Create and validation
- tenant_id = self._get_tenant_id_for_create(context,
- network["network"])
- self._network_admin_state(network)
-
- with context.session.begin(subtransactions=True):
- net = super(NeutronPluginPLUMgridV2, self).create_network(context,
- network)
-
- try:
- LOG.debug(_('NeutronPluginPLUMgrid Status: %(tenant_id)s, '
- '%(network)s, %(network_id)s'),
- dict(
- tenant_id=tenant_id,
- network=network["network"],
- network_id=net["id"],
- ))
- nos_url = self.snippets.BASE_NOS_URL + net["id"]
- headers = {}
- body_data = self.snippets.create_domain_body_data(tenant_id)
- self.rest_conn.nos_rest_conn(nos_url,
- 'PUT', body_data, headers)
-
- except Exception:
- err_message = _("PLUMgrid NOS communication failed")
- LOG.Exception(err_message)
- raise plum_excep.PLUMgridException(err_msg=err_message)
-
- # return created network
- return net
-
- def update_network(self, context, net_id, network):
- """Update network core Neutron API."""
-
- LOG.debug(_("NeutronPluginPLUMgridV2.update_network() called"))
- self._network_admin_state(network)
- tenant_id = self._get_tenant_id_for_create(context, network["network"])
-
- with context.session.begin(subtransactions=True):
- # Plugin DB - Network Update
- new_network = super(
- NeutronPluginPLUMgridV2, self).update_network(context,
- net_id, network)
-
- try:
- # PLUMgrid Server does not support updating resources yet
- nos_url = self.snippets.BASE_NOS_URL + net_id
- headers = {}
- body_data = {}
- self.rest_conn.nos_rest_conn(nos_url,
- 'DELETE', body_data, headers)
- nos_url = self.snippets.BASE_NOS_URL + new_network["id"]
- body_data = self.snippets.create_domain_body_data(tenant_id)
- self.rest_conn.nos_rest_conn(nos_url,
- 'PUT', body_data, headers)
- except Exception:
- err_message = _("PLUMgrid NOS communication failed")
- LOG.Exception(err_message)
- raise plum_excep.PLUMgridException(err_msg=err_message)
-
- # return updated network
- return new_network
-
- def delete_network(self, context, net_id):
- """Delete network core Neutron API."""
- LOG.debug(_("NeutronPluginPLUMgrid Status: delete_network() called"))
- super(NeutronPluginPLUMgridV2, self).get_network(context, net_id)
-
- with context.session.begin(subtransactions=True):
- # Plugin DB - Network Delete
- super(NeutronPluginPLUMgridV2, self).delete_network(context,
- net_id)
-
- try:
- nos_url = self.snippets.BASE_NOS_URL + net_id
- headers = {}
- body_data = {}
- self.rest_conn.nos_rest_conn(nos_url,
- 'DELETE', body_data, headers)
- except Exception:
- err_message = _("PLUMgrid NOS communication failed")
- LOG.Exception(err_message)
- raise plum_excep.PLUMgridException(err_msg=err_message)
-
- def create_port(self, context, port):
- """Create port core Neutron API."""
- LOG.debug(_("NeutronPluginPLUMgrid Status: create_port() called"))
-
- # Port operations on PLUMgrid NOS is an automatic operation from the
- # VIF driver operations in Nova. It requires admin_state_up to be True
- port["port"]["admin_state_up"] = True
-
- # Plugin DB - Port Create and Return port
- return super(NeutronPluginPLUMgridV2, self).create_port(context,
- port)
-
- def update_port(self, context, port_id, port):
- """Update port core Neutron API."""
- LOG.debug(_("NeutronPluginPLUMgrid Status: update_port() called"))
-
- # Port operations on PLUMgrid NOS is an automatic operation from the
- # VIF driver operations in Nova.
-
- # Plugin DB - Port Update
- return super(NeutronPluginPLUMgridV2, self).update_port(
- context, port_id, port)
-
- def delete_port(self, context, port_id):
- """Delete port core Neutron API."""
-
- LOG.debug(_("NeutronPluginPLUMgrid Status: delete_port() called"))
-
- # Port operations on PLUMgrid NOS is an automatic operation from the
- # VIF driver operations in Nova.
-
- # Plugin DB - Port Delete
- super(NeutronPluginPLUMgridV2, self).delete_port(context, port_id)
-
- def create_subnet(self, context, subnet):
- """Create subnet core Neutron API."""
-
- LOG.debug(_("NeutronPluginPLUMgrid Status: create_subnet() called"))
-
- with context.session.begin(subtransactions=True):
- # Plugin DB - Subnet Create
- subnet = super(NeutronPluginPLUMgridV2, self).create_subnet(
- context, subnet)
- subnet_details = self._get_subnet(context, subnet["id"])
- net_id = subnet_details["network_id"]
- tenant_id = subnet_details["tenant_id"]
-
- try:
- nos_url = self.snippets.BASE_NOS_URL + net_id
- headers = {}
- body_data = self.snippets.create_network_body_data(
- tenant_id, self.topology_name)
- self.rest_conn.nos_rest_conn(nos_url,
- 'PUT', body_data, headers)
- except Exception:
- err_message = _("PLUMgrid NOS communication failed: ")
- LOG.Exception(err_message)
- raise plum_excep.PLUMgridException(err_msg=err_message)
-
- return subnet
-
- def delete_subnet(self, context, subnet_id):
- """Delete subnet core Neutron API."""
-
- LOG.debug(_("NeutronPluginPLUMgrid Status: delete_subnet() called"))
- #Collecting subnet info
- subnet_details = self._get_subnet(context, subnet_id)
-
- with context.session.begin(subtransactions=True):
- # Plugin DB - Subnet Delete
- del_subnet = super(NeutronPluginPLUMgridV2, self).delete_subnet(
- context, subnet_id)
- try:
- headers = {}
- body_data = {}
- net_id = subnet_details["network_id"]
- self._cleaning_nos_subnet_structure(body_data, headers, net_id)
- except Exception:
- err_message = _("PLUMgrid NOS communication failed: ")
- LOG.Exception(err_message)
- raise plum_excep.PLUMgridException(err_msg=err_message)
-
- return del_subnet
-
- def update_subnet(self, context, subnet_id, subnet):
- """Update subnet core Neutron API."""
-
- LOG.debug(_("update_subnet() called"))
- #Collecting subnet info
- initial_subnet = self._get_subnet(context, subnet_id)
- net_id = initial_subnet["network_id"]
- tenant_id = initial_subnet["tenant_id"]
-
- with context.session.begin(subtransactions=True):
- # Plugin DB - Subnet Update
- new_subnet = super(NeutronPluginPLUMgridV2, self).update_subnet(
- context, subnet_id, subnet)
-
- try:
- # PLUMgrid Server does not support updating resources yet
- headers = {}
- body_data = {}
- self._cleaning_nos_subnet_structure(body_data, headers, net_id)
- nos_url = self.snippets.BASE_NOS_URL + net_id
- body_data = self.snippets.create_network_body_data(
- tenant_id, self.topology_name)
- self.rest_conn.nos_rest_conn(nos_url,
- 'PUT', body_data, headers)
-
- except Exception:
- err_message = _("PLUMgrid NOS communication failed: ")
- LOG.Exception(err_message)
- raise plum_excep.PLUMgridException(err_msg=err_message)
-
- return new_subnet
-
- """
- Extension API implementation
- """
- # TODO(Edgar) Complete extensions for PLUMgrid
-
- """
- Internal PLUMgrid fuctions
- """
-
- def _get_plugin_version(self):
- return VERSION
-
- def _cleaning_nos_subnet_structure(self, body_data, headers, net_id):
- domain_structure = ['/properties', '/link', '/ne']
- for structure in domain_structure:
- nos_url = self.snippets.BASE_NOS_URL + net_id + structure
- self.rest_conn.nos_rest_conn(nos_url, 'DELETE', body_data, headers)
-
- def _network_admin_state(self, network):
- try:
- if network["network"].get("admin_state_up"):
- network_name = network["network"]["name"]
- if network["network"]["admin_state_up"] is False:
- LOG.warning(_("Network with admin_state_up=False are not "
- "supported yet by this plugin. Ignoring "
- "setting for network %s"), network_name)
- except Exception:
- err_message = _("Network Admin State Validation Falied: ")
- LOG.Exception(err_message)
- raise plum_excep.PLUMgridException(err_msg=err_message)
- return network
+++ /dev/null
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2013 PLUMgrid, Inc. 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.
-#
-# @author: Edgar Magana, emagana@plumgrid.com, PLUMgrid, Inc.
-# @author: Brenden Blanco, bblanco@plumgrid.com, PLUMgrid, Inc.
-
-"""
-Neutron PLUMgrid Plug-in for PLUMgrid Virtual Technology
-This plugin will forward authenticated REST API calls
-to the Network Operating System by PLUMgrid called NOS
-"""
-
-import httplib
-import urllib2
-
-from neutron.openstack.common import jsonutils as json
-from neutron.openstack.common import log as logging
-from neutron.plugins.plumgrid.common import exceptions as plum_excep
-
-
-LOG = logging.getLogger(__name__)
-
-
-class RestConnection(object):
- """REST Connection to PLUMgrid NOS Server."""
-
- def __init__(self, server, port, timeout):
- LOG.debug(_('NeutronPluginPLUMgrid Status: REST Connection Started'))
- self.server = server
- self.port = port
- self.timeout = timeout
-
- def nos_rest_conn(self, nos_url, action, data, headers):
- self.nos_url = nos_url
- body_data = json.dumps(data)
- if not headers:
- headers = {}
- headers['Content-type'] = 'application/json'
- headers['Accept'] = 'application/json'
-
- LOG.debug(_("PLUMgrid_NOS_Server: %(server)s %(port)s %(action)s"),
- dict(server=self.server, port=self.port, action=action))
-
- conn = httplib.HTTPConnection(self.server, self.port,
- timeout=self.timeout)
- if conn is None:
- LOG.error(_('PLUMgrid_NOS_Server: Could not establish HTTP '
- 'connection'))
- return
-
- try:
- LOG.debug(_("PLUMgrid_NOS_Server Sending Data: %(nos_url)s "
- "%(body_data)s %(headers)s"),
- dict(
- nos_url=nos_url,
- body_data=body_data,
- headers=headers,
- ))
- conn.request(action, nos_url, body_data, headers)
- resp = conn.getresponse()
- resp_str = resp.read()
-
- LOG.debug(_("PLUMgrid_NOS_Server Connection Data: %(resp)s, "
- "%(resp_str)s"), dict(resp=resp, resp_str=resp_str))
-
- if resp.status is httplib.OK:
- try:
- respdata = json.loads(resp_str)
- LOG.debug(_("PLUMgrid_NOS_Server Connection RESP: %s"),
- respdata)
- pass
- except ValueError:
- err_message = _("PLUMgrid HTTP Connection Failed: ")
- LOG.Exception(err_message)
- raise plum_excep.PLUMgridException(err_msg=err_message)
-
- ret = (resp.status, resp.reason, resp_str)
- except urllib2.HTTPError:
- LOG.error(_('PLUMgrid_NOS_Server: %(action)s failure, %(e)r'))
- ret = 0, None, None, None
- conn.close()
- LOG.debug(_("PLUMgrid_NOS_Server: status=%(status)d, "
- "reason=%(reason)r, ret=%(ret)s"),
- {'status': ret[0], 'reason': ret[1], 'ret': ret[2]})
- return ret
#
# @author: Edgar Magana, emagana@plumgrid.com, PLUMgrid, Inc.
-VERSION = "0.1"
+VERSION = "0.2"
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright 2013 PLUMgrid, Inc. 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.
+#
+# @author: Edgar Magana, emagana@plumgrid.com, PLUMgrid, Inc.
+
+"""
+Neutron Plug-in for PLUMgrid Virtual Networking Infrastructure (VNI)
+This plugin will forward authenticated REST API calls
+to the PLUMgrid Network Management System called Director
+"""
+
+import netaddr
+from oslo.config import cfg
+
+from neutron.api.v2 import attributes
+from neutron.db import api as db
+from neutron.db import db_base_plugin_v2
+from neutron.db import l3_db
+from neutron.db import portbindings_db
+from neutron.extensions import portbindings
+from neutron.openstack.common import importutils
+from neutron.openstack.common import log as logging
+from neutron.plugins.plumgrid.common import exceptions as plum_excep
+from neutron.plugins.plumgrid.plumgrid_plugin.plugin_ver import VERSION
+from neutron import policy
+
+LOG = logging.getLogger(__name__)
+PLUM_DRIVER = 'neutron.plugins.plumgrid.drivers.plumlib.Plumlib'
+ERR_MESSAGE = 'PLUMgrid Director communication failed'
+
+director_server_opts = [
+ cfg.StrOpt('director_server', default='localhost',
+ help=_("PLUMgrid Director server to connect to")),
+ cfg.StrOpt('director_server_port', default='8080',
+ help=_("PLUMgrid Director server port to connect to")),
+ cfg.StrOpt('username', default='username',
+ help=_("PLUMgrid Director admin username")),
+ cfg.StrOpt('password', default='password', secret=True,
+ help=_("PLUMgrid Director admin password")),
+ cfg.IntOpt('servertimeout', default=5,
+ help=_("PLUMgrid Director server timeout")), ]
+
+cfg.CONF.register_opts(director_server_opts, "PLUMgridDirector")
+
+
+class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2,
+ portbindings_db.PortBindingMixin,
+ l3_db.L3_NAT_db_mixin):
+
+ supported_extension_aliases = ["router", "binding"]
+
+ binding_view = "extension:port_binding:view"
+ binding_set = "extension:port_binding:set"
+
+ def __init__(self):
+ LOG.info(_('Neutron PLUMgrid Director: Starting Plugin'))
+
+ # Plugin DB initialization
+ db.configure_db()
+
+ self.plumgrid_init()
+
+ LOG.debug(_('Neutron PLUMgrid Director: Neutron server with '
+ 'PLUMgrid Plugin has started'))
+
+ def plumgrid_init(self):
+ """PLUMgrid initialization."""
+ director_plumgrid = cfg.CONF.PLUMgridDirector.director_server
+ director_port = cfg.CONF.PLUMgridDirector.director_server_port
+ timeout = cfg.CONF.PLUMgridDirector.servertimeout
+
+ # PLUMgrid Director info validation
+ LOG.info(_('Neutron PLUMgrid Director: %s'), director_plumgrid)
+ self._plumlib = importutils.import_object(PLUM_DRIVER)
+ self._plumlib.director_conn(director_plumgrid, director_port, timeout)
+
+ def create_network(self, context, network):
+ """Create Neutron network.
+
+ Creates a PLUMgrid-based bridge.
+ """
+
+ LOG.debug(_('Neutron PLUMgrid Director: create_network() called'))
+
+ # Plugin DB - Network Create and validation
+ tenant_id = self._get_tenant_id_for_create(context,
+ network["network"])
+ self._network_admin_state(network)
+
+ with context.session.begin(subtransactions=True):
+ net_db = super(NeutronPluginPLUMgridV2,
+ self).create_network(context, network)
+ # Propagate all L3 data into DB
+ self._process_l3_create(context, net_db, network['network'])
+
+ try:
+ LOG.debug(_('PLUMgrid Library: create_network() called'))
+ self._plumlib.create_network(tenant_id, net_db)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ # Return created network
+ return net_db
+
+ def update_network(self, context, net_id, network):
+ """Update Neutron network.
+
+ Updates a PLUMgrid-based bridge.
+ """
+
+ LOG.debug(_("Neutron PLUMgrid Director: update_network() called"))
+ self._network_admin_state(network)
+ tenant_id = self._get_tenant_id_for_create(context, network["network"])
+
+ with context.session.begin(subtransactions=True):
+ # Plugin DB - Network Update
+ net_db = super(
+ NeutronPluginPLUMgridV2, self).update_network(context,
+ net_id, network)
+
+ try:
+ LOG.debug(_("PLUMgrid Library: update_network() called"))
+ self._plumlib.update_network(tenant_id, net_id)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ # Return updated network
+ return net_db
+
+ def delete_network(self, context, net_id):
+ """Delete Neutron network.
+
+ Deletes a PLUMgrid-based bridge.
+ """
+
+ LOG.debug(_("Neutron PLUMgrid Director: delete_network() called"))
+ net_db = super(NeutronPluginPLUMgridV2,
+ self).get_network(context, net_id)
+
+ with context.session.begin(subtransactions=True):
+ # Plugin DB - Network Delete
+ super(NeutronPluginPLUMgridV2, self).delete_network(context,
+ net_id)
+
+ try:
+ LOG.debug(_("PLUMgrid Library: update_network() called"))
+ self._plumlib.delete_network(net_db, net_id)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ def create_port(self, context, port):
+ """Create Neutron port.
+
+ Creates a PLUMgrid-based port on the specific Virtual Network
+ Function (VNF).
+ """
+ LOG.debug(_("Neutron PLUMgrid Director: create_port() called"))
+
+ # Port operations on PLUMgrid Director is an automatic operation
+ # from the VIF driver operations in Nova.
+ # It requires admin_state_up to be True
+
+ port["port"]["admin_state_up"] = True
+
+ with context.session.begin(subtransactions=True):
+ # Plugin DB - Port Create and Return port
+ port_db = super(NeutronPluginPLUMgridV2, self).create_port(context,
+ port)
+ device_id = port_db["device_id"]
+ if port_db["device_owner"] == "network:router_gateway":
+ router_db = self._get_router(context, device_id)
+ else:
+ router_db = None
+
+ try:
+ LOG.debug(_("PLUMgrid Library: create_port() called"))
+ self._plumlib.create_port(port_db, router_db)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ # Plugin DB - Port Create and Return port
+ return self._port_viftype_binding(context, port_db)
+
+ def update_port(self, context, port_id, port):
+ """Update Neutron port.
+
+ Updates a PLUMgrid-based port on the specific Virtual Network
+ Function (VNF).
+ """
+ LOG.debug(_("Neutron PLUMgrid Director: update_port() called"))
+
+ with context.session.begin(subtransactions=True):
+ # Plugin DB - Port Create and Return port
+ port_db = super(NeutronPluginPLUMgridV2, self).update_port(
+ context, port_id, port)
+ device_id = port_db["device_id"]
+ if port_db["device_owner"] == "network:router_gateway":
+ router_db = self._get_router(context, device_id)
+ else:
+ router_db = None
+ try:
+ LOG.debug(_("PLUMgrid Library: create_port() called"))
+ self._plumlib.update_port(port_db, router_db)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ # Plugin DB - Port Update
+ return self._port_viftype_binding(context, port_db)
+
+ def delete_port(self, context, port_id, l3_port_check=True):
+ """Delete Neutron port.
+
+ Deletes a PLUMgrid-based port on the specific Virtual Network
+ Function (VNF).
+ """
+
+ LOG.debug(_("Neutron PLUMgrid Director: delete_port() called"))
+
+ with context.session.begin(subtransactions=True):
+ # Plugin DB - Port Create and Return port
+ port_db = super(NeutronPluginPLUMgridV2,
+ self).get_port(context, port_id)
+ super(NeutronPluginPLUMgridV2, self).delete_port(context, port_id)
+
+ if port_db["device_owner"] == "network:router_gateway":
+ device_id = port_db["device_id"]
+ router_db = self._get_router(context, device_id)
+ else:
+ router_db = None
+ try:
+ LOG.debug(_("PLUMgrid Library: delete_port() called"))
+ self._plumlib.delete_port(port_db, router_db)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ def get_port(self, context, id, fields=None):
+ with context.session.begin(subtransactions=True):
+ port_db = super(NeutronPluginPLUMgridV2,
+ self).get_port(context, id, fields)
+
+ self._port_viftype_binding(context, port_db)
+ return self._fields(port_db, fields)
+
+ def get_ports(self, context, filters=None, fields=None):
+ with context.session.begin(subtransactions=True):
+ ports_db = super(NeutronPluginPLUMgridV2,
+ self).get_ports(context, filters, fields)
+ for port_db in ports_db:
+ self._port_viftype_binding(context, port_db)
+ return [self._fields(port, fields) for port in ports_db]
+
+ def create_subnet(self, context, subnet):
+ """Create Neutron subnet.
+
+ Creates a PLUMgrid-based DHCP and NAT Virtual Network
+ Functions (VNFs).
+ """
+
+ LOG.debug(_("Neutron PLUMgrid Director: create_subnet() called"))
+
+ with context.session.begin(subtransactions=True):
+ # Plugin DB - Subnet Create
+ net_db = super(NeutronPluginPLUMgridV2, self).get_network(
+ context, subnet['subnet']['network_id'], fields=None)
+ s = subnet['subnet']
+ ipnet = netaddr.IPNetwork(s['cidr'])
+
+ # PLUMgrid Director reserves the last IP address for GW
+ # when is not defined
+ if s['gateway_ip'] is attributes.ATTR_NOT_SPECIFIED:
+ gw_ip = str(netaddr.IPAddress(ipnet.last - 1))
+ subnet['subnet']['gateway_ip'] = gw_ip
+
+ # PLUMgrid reserves the first IP
+ if s['allocation_pools'] == attributes.ATTR_NOT_SPECIFIED:
+ allocation_pool = self._allocate_pools_for_subnet(context, s)
+ subnet['subnet']['allocation_pools'] = allocation_pool
+
+ sub_db = super(NeutronPluginPLUMgridV2, self).create_subnet(
+ context, subnet)
+
+ try:
+ LOG.debug(_("PLUMgrid Library: create_subnet() called"))
+ self._plumlib.create_subnet(sub_db, net_db, ipnet)
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ return sub_db
+
+ def delete_subnet(self, context, subnet_id):
+ """Delete subnet core Neutron API."""
+
+ LOG.debug(_("Neutron PLUMgrid Director: delete_subnet() called"))
+ # Collecting subnet info
+ sub_db = self._get_subnet(context, subnet_id)
+ tenant_id = self._get_tenant_id_for_create(context, subnet_id)
+ net_id = sub_db["network_id"]
+ net_db = self.get_network(context, net_id)
+
+ with context.session.begin(subtransactions=True):
+ # Plugin DB - Subnet Delete
+ super(NeutronPluginPLUMgridV2, self).delete_subnet(
+ context, subnet_id)
+ try:
+ LOG.debug(_("PLUMgrid Library: delete_subnet() called"))
+ self._plumlib.delete_subnet(tenant_id, net_db, net_id)
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ def update_subnet(self, context, subnet_id, subnet):
+ """Update subnet core Neutron API."""
+
+ LOG.debug(_("update_subnet() called"))
+ # Collecting subnet info
+ org_sub_db = self._get_subnet(context, subnet_id)
+
+ with context.session.begin(subtransactions=True):
+ # Plugin DB - Subnet Update
+ new_sub_db = super(NeutronPluginPLUMgridV2,
+ self).update_subnet(context, subnet_id, subnet)
+ ipnet = netaddr.IPNetwork(new_sub_db['cidr'])
+
+ try:
+ # PLUMgrid Server does not support updating resources yet
+ LOG.debug(_("PLUMgrid Library: update_network() called"))
+ self._plumlib.update_subnet(org_sub_db, new_sub_db, ipnet)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ return new_sub_db
+
+ def create_router(self, context, router):
+ """
+ Create router extension Neutron API
+ """
+ LOG.debug(_("Neutron PLUMgrid Director: create_router() called"))
+
+ tenant_id = self._get_tenant_id_for_create(context, router["router"])
+
+ with context.session.begin(subtransactions=True):
+
+ # Create router in DB
+ router_db = super(NeutronPluginPLUMgridV2,
+ self).create_router(context, router)
+ # Create router on the network controller
+ try:
+ # Add Router to VND
+ LOG.debug(_("PLUMgrid Library: create_router() called"))
+ self._plumlib.create_router(tenant_id, router_db)
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ # Return created router
+ return router_db
+
+ def update_router(self, context, router_id, router):
+
+ LOG.debug(_("Neutron PLUMgrid Director: update_router() called"))
+
+ with context.session.begin(subtransactions=True):
+ router_db = super(NeutronPluginPLUMgridV2,
+ self).update_router(context, router_id, router)
+ try:
+ LOG.debug(_("PLUMgrid Library: update_router() called"))
+ self._plumlib.update_router(router_db, router_id)
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ # Return updated router
+ return router_db
+
+ def delete_router(self, context, router_id):
+ LOG.debug(_("Neutron PLUMgrid Director: delete_router() called"))
+
+ with context.session.begin(subtransactions=True):
+ orig_router = self._get_router(context, router_id)
+ tenant_id = orig_router["tenant_id"]
+
+ super(NeutronPluginPLUMgridV2, self).delete_router(context,
+ router_id)
+
+ try:
+ LOG.debug(_("PLUMgrid Library: delete_router() called"))
+ self._plumlib.delete_router(tenant_id, router_id)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ def add_router_interface(self, context, router_id, interface_info):
+
+ LOG.debug(_("Neutron PLUMgrid Director: "
+ "add_router_interface() called"))
+ with context.session.begin(subtransactions=True):
+ # Validate args
+ router_db = self._get_router(context, router_id)
+ tenant_id = router_db['tenant_id']
+
+ # Create interface in DB
+ int_router = super(NeutronPluginPLUMgridV2,
+ self).add_router_interface(context,
+ router_id,
+ interface_info)
+ port_db = self._get_port(context, int_router['port_id'])
+ subnet_id = port_db["fixed_ips"][0]["subnet_id"]
+ subnet_db = super(NeutronPluginPLUMgridV2,
+ self)._get_subnet(context, subnet_id)
+ ipnet = netaddr.IPNetwork(subnet_db['cidr'])
+
+ # Create interface on the network controller
+ try:
+ LOG.debug(_("PLUMgrid Library: add_router_interface() called"))
+ self._plumlib.add_router_interface(tenant_id, router_id,
+ port_db, ipnet)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ return int_router
+
+ def remove_router_interface(self, context, router_id, int_info):
+
+ LOG.debug(_("Neutron PLUMgrid Director: "
+ "remove_router_interface() called"))
+ with context.session.begin(subtransactions=True):
+ # Validate args
+ router_db = self._get_router(context, router_id)
+ tenant_id = router_db['tenant_id']
+ if 'port_id' in int_info:
+ port = self._get_port(context, int_info['port_id'])
+ net_id = port['network_id']
+
+ elif 'subnet_id' in int_info:
+ subnet_id = int_info['subnet_id']
+ subnet = self._get_subnet(context, subnet_id)
+ net_id = subnet['network_id']
+
+ # Remove router in DB
+ del_int_router = super(NeutronPluginPLUMgridV2,
+ self).remove_router_interface(context,
+ router_id,
+ int_info)
+
+ try:
+ LOG.debug(_("PLUMgrid Library: "
+ "remove_router_interface() called"))
+ self._plumlib.remove_router_interface(tenant_id,
+ net_id, router_id)
+
+ except Exception:
+ LOG.error(ERR_MESSAGE)
+ raise plum_excep.PLUMgridException(err_msg=ERR_MESSAGE)
+
+ return del_int_router
+
+ """
+ Internal PLUMgrid Fuctions
+ """
+
+ def _get_plugin_version(self):
+ return VERSION
+
+ def _port_viftype_binding(self, context, port):
+ if self._check_view_auth(context, port, self.binding_view):
+ port[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_IOVISOR
+ port[portbindings.CAPABILITIES] = {
+ portbindings.CAP_PORT_FILTER:
+ 'security-group' in self.supported_extension_aliases}
+ return port
+
+ def _check_view_auth(self, context, resource, action):
+ return policy.check(context, action, resource)
+
+ def _network_admin_state(self, network):
+ try:
+ if network["network"].get("admin_state_up"):
+ network_name = network["network"]["name"]
+ if network["network"]["admin_state_up"] is False:
+ LOG.warning(_("Network with admin_state_up=False are not "
+ "supported yet by this plugin. Ignoring "
+ "setting for network %s"), network_name)
+ except Exception:
+ err_message = _("Network Admin State Validation Falied: ")
+ LOG.error(err_message)
+ raise plum_excep.PLUMgridException(err_msg=err_message)
+ return network
+
+ def _allocate_pools_for_subnet(self, context, subnet):
+ """Create IP allocation pools for a given subnet
+
+ Pools are defined by the 'allocation_pools' attribute,
+ a list of dict objects with 'start' and 'end' keys for
+ defining the pool range.
+ Modified from Neutron DB based class
+
+ """
+
+ pools = []
+ # Auto allocate the pool around gateway_ip
+ net = netaddr.IPNetwork(subnet['cidr'])
+ first_ip = net.first + 2
+ last_ip = net.last - 1
+ gw_ip = int(netaddr.IPAddress(subnet['gateway_ip'] or net.last))
+ # Use the gw_ip to find a point for splitting allocation pools
+ # for this subnet
+ split_ip = min(max(gw_ip, net.first), net.last)
+ if split_ip > first_ip:
+ pools.append({'start': str(netaddr.IPAddress(first_ip)),
+ 'end': str(netaddr.IPAddress(split_ip - 1))})
+ if split_ip < last_ip:
+ pools.append({'start': str(netaddr.IPAddress(split_ip + 1)),
+ 'end': str(netaddr.IPAddress(last_ip))})
+ # return auto-generated pools
+ # no need to check for their validity
+ return pools
Test cases for Neutron PLUMgrid Plug-in
"""
-from mock import patch
+import mock
+from neutron.extensions import portbindings
from neutron.manager import NeutronManager
+from neutron.openstack.common import importutils
+from neutron.plugins.plumgrid.plumgrid_plugin import plumgrid_plugin
+from neutron.tests.unit import _test_extension_portbindings as test_bindings
from neutron.tests.unit import test_db_plugin as test_plugin
-class PLUMgridPluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
+PLUM_DRIVER = ('neutron.plugins.plumgrid.drivers.fake_plumlib.Plumlib')
+FAKE_DIRECTOR = '1.1.1.1'
+FAKE_PORT = '1234'
+FAKE_TIMEOUT = '0'
+
- _plugin_name = ('neutron.plugins.plumgrid.plumgrid_nos_plugin.'
+class PLUMgridPluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
+ _plugin_name = ('neutron.plugins.plumgrid.plumgrid_plugin.'
'plumgrid_plugin.NeutronPluginPLUMgridV2')
def setUp(self):
- self.restHTTPConnection = patch('httplib.HTTPConnection')
- self.restHTTPConnection.start()
- super(PLUMgridPluginV2TestCase, self).setUp(self._plugin_name)
+ def mocked_plumlib_init(self):
+ director_plumgrid = FAKE_DIRECTOR
+ director_port = FAKE_PORT
+ timeout = FAKE_TIMEOUT
+ self._plumlib = importutils.import_object(PLUM_DRIVER)
+ self._plumlib.director_conn(director_plumgrid,
+ director_port, timeout)
+
+ with mock.patch.object(plumgrid_plugin.NeutronPluginPLUMgridV2,
+ 'plumgrid_init', new=mocked_plumlib_init):
+ super(PLUMgridPluginV2TestCase, self).setUp(self._plugin_name)
def tearDown(self):
super(PLUMgridPluginV2TestCase, self).tearDown()
- self.restHTTPConnection.stop()
-class TestPlumgridPluginV2HTTPResponse(test_plugin.TestV2HTTPResponse,
- PLUMgridPluginV2TestCase):
+class TestPlumgridPluginNetworksV2(test_plugin.TestNetworksV2,
+ PLUMgridPluginV2TestCase):
+ pass
+
+class TestPlumgridV2HTTPResponse(test_plugin.TestV2HTTPResponse,
+ PLUMgridPluginV2TestCase):
pass
class TestPlumgridPluginPortsV2(test_plugin.TestPortsV2,
PLUMgridPluginV2TestCase):
+ def test_range_allocation(self):
+ self.skipTest("Plugin does not support Neutron allocation process")
- pass
+class TestPlumgridPluginSubnetsV2(test_plugin.TestSubnetsV2,
+ PLUMgridPluginV2TestCase):
+ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409(
+ self):
+ self.skipTest("Plugin does not support Neutron allocation process")
-class TestPlumgridPluginNetworksV2(test_plugin.TestNetworksV2,
- PLUMgridPluginV2TestCase):
+ def test_create_subnet_defaults(self):
+ self.skipTest("Plugin does not support Neutron allocation process")
- pass
+ def test_create_subnet_gw_values(self):
+ self.skipTest("Plugin does not support Neutron allocation process")
+ def test_update_subnet_gateway_in_allocation_pool_returns_409(self):
+ self.skipTest("Plugin does not support Neutron allocation process")
-class TestPlumgridPluginSubnetsV2(test_plugin.TestSubnetsV2,
- PLUMgridPluginV2TestCase):
- pass
+class TestPlumgridPluginPortBinding(PLUMgridPluginV2TestCase,
+ test_bindings.PortBindingsTestCase):
+ VIF_TYPE = portbindings.VIF_TYPE_IOVISOR
+ def setUp(self):
+ super(TestPlumgridPluginPortBinding, self).setUp()
-class TestPlumgridNetworkAdminState(PLUMgridPluginV2TestCase):
+class TestPlumgridNetworkAdminState(PLUMgridPluginV2TestCase):
def test_network_admin_state(self):
name = 'network_test'
admin_status_up = False
'tenant_id': tenant_id}}
plugin = NeutronManager.get_plugin()
self.assertEqual(plugin._network_admin_state(network), network)
+
+
+class TestPlumgridAllocationPool(PLUMgridPluginV2TestCase):
+ def test_allocate_pools_for_subnet(self):
+ cidr = '10.0.0.0/24'
+ gateway_ip = '10.0.0.254'
+ subnet = {'gateway_ip': gateway_ip,
+ 'cidr': cidr,
+ 'ip_version': 4}
+ allocation_pool = [{"start": '10.0.0.2',
+ "end": '10.0.0.253'}]
+ context = None
+ plugin = NeutronManager.get_plugin()
+ pool = plugin._allocate_pools_for_subnet(context, subnet)
+ self.assertEqual(allocation_pool, pool)