diff --git a/etc/quantum/plugins/plumgrid/plumgrid.ini b/etc/quantum/plugins/plumgrid/plumgrid.ini new file mode 100644 index 000000000..4a1068b22 --- /dev/null +++ b/etc/quantum/plugins/plumgrid/plumgrid.ini @@ -0,0 +1,39 @@ +# Config file for Quantum PLUMgrid plugin + +[DATABASE] +# This line MUST be changed to actually run the plugin. +# Example: +# sql_connection = mysql://:@:3306/plumgrid_quantum +# Replace above with the IP address of the database used by the +# main quantum server. +# sql_connection = sqlite:// +# Database reconnection retry times - in event connectivity is lost +# set to -1 implies an infinite retry count +# sql_max_retries = 10 +# Database reconnection interval in seconds - if the initial connection to the +# database fails +# reconnect_interval = 2 +# Enable the use of eventlet's db_pool for MySQL. The flags sql_min_pool_size, +# sql_max_pool_size and sql_idle_timeout are relevant only if this is enabled. +# sql_dbpool_enable = False +# Minimum number of SQL connections to keep open in a pool +# sql_min_pool_size = 1 +# Maximum number of SQL connections to keep open in a pool +# sql_max_pool_size = 5 +# Timeout in seconds before idle sql connections are reaped +# sql_idle_timeout = 3600 + +[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_server_port= +# Authentification parameters for the NOS server. +# These are the admin credentials to manage and control +# the NOS server. +# username= +# password= +# servertimeout=5 +# Name of the network topology to be deployed by NOS +# topologyname= diff --git a/quantum/plugins/plumgrid/README b/quantum/plugins/plumgrid/README new file mode 100644 index 000000000..0d1de3325 --- /dev/null +++ b/quantum/plugins/plumgrid/README @@ -0,0 +1,7 @@ +PLUMgrid Quantum Virtual Network Plugin + +This plugin implements Quantum v2 APIs and helps configure +L2/L3 virtual networks consisting of PLUMgrid Platform. + +For more details on use please refer to: +http://wiki.openstack.org/plumgrid-quantum diff --git a/quantum/plugins/plumgrid/__init__.py b/quantum/plugins/plumgrid/__init__.py new file mode 100644 index 000000000..39e9b8d13 --- /dev/null +++ b/quantum/plugins/plumgrid/__init__.py @@ -0,0 +1,17 @@ +# 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. diff --git a/quantum/plugins/plumgrid/common/__init__.py b/quantum/plugins/plumgrid/common/__init__.py new file mode 100644 index 000000000..39e9b8d13 --- /dev/null +++ b/quantum/plugins/plumgrid/common/__init__.py @@ -0,0 +1,17 @@ +# 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. diff --git a/quantum/plugins/plumgrid/common/exceptions.py b/quantum/plugins/plumgrid/common/exceptions.py new file mode 100644 index 000000000..4201cce16 --- /dev/null +++ b/quantum/plugins/plumgrid/common/exceptions.py @@ -0,0 +1,31 @@ +# 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. + + +""" Quantum PLUMgrid Plugin exceptions """ + +from quantum.common import exceptions as base_exec + + +class PLUMgridException(base_exec.QuantumException): + message = _("An unexpected error occurred in the PLUMgrid Plugin: " + "%(err_msg)s") + + +class PLUMgridConnectionFailed(PLUMgridException): + message = _("Connection failed with PLUMgrid NOS: %(err_msg)s") diff --git a/quantum/plugins/plumgrid/plumgrid_nos_plugin/__init__.py b/quantum/plugins/plumgrid/plumgrid_nos_plugin/__init__.py new file mode 100644 index 000000000..39e9b8d13 --- /dev/null +++ b/quantum/plugins/plumgrid/plumgrid_nos_plugin/__init__.py @@ -0,0 +1,17 @@ +# 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. diff --git a/quantum/plugins/plumgrid/plumgrid_nos_plugin/plugin_ver.py b/quantum/plugins/plumgrid/plumgrid_nos_plugin/plugin_ver.py new file mode 100644 index 000000000..d9286de9c --- /dev/null +++ b/quantum/plugins/plumgrid/plumgrid_nos_plugin/plugin_ver.py @@ -0,0 +1,19 @@ +# 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. + +VERSION = "0.1" diff --git a/quantum/plugins/plumgrid/plumgrid_nos_plugin/plumgrid_nos_snippets.py b/quantum/plugins/plumgrid/plumgrid_nos_plugin/plumgrid_nos_snippets.py new file mode 100644 index 000000000..02faa5a75 --- /dev/null +++ b/quantum/plugins/plumgrid/plumgrid_nos_plugin/plumgrid_nos_snippets.py @@ -0,0 +1,44 @@ +# 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 quantum.openstack.common import log as logging + + +LOG = logging.getLogger(__name__) + + +class DataNOSPLUMgrid(): + + BASE_NOS_URL = '/0/connectivity/domain/' + + def __init__(self): + LOG.info(_('QuantumPluginPLUMgrid 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 diff --git a/quantum/plugins/plumgrid/plumgrid_nos_plugin/plumgrid_plugin.py b/quantum/plugins/plumgrid/plumgrid_nos_plugin/plumgrid_plugin.py new file mode 100644 index 000000000..22e31f962 --- /dev/null +++ b/quantum/plugins/plumgrid/plumgrid_nos_plugin/plumgrid_plugin.py @@ -0,0 +1,344 @@ +# 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. + +""" +Quantum 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 sys + +from quantum.db import api as db +from quantum.db import db_base_plugin_v2 +from quantum.openstack.common import cfg +from quantum.openstack.common import log as logging +from quantum.plugins.plumgrid.common import exceptions as plum_excep +from quantum.plugins.plumgrid.plumgrid_nos_plugin import plumgrid_nos_snippets +from quantum.plugins.plumgrid.plumgrid_nos_plugin import rest_connection +from quantum.plugins.plumgrid.plumgrid_nos_plugin.plugin_ver import VERSION + + +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.IntOpt('topologyname', default='t1', + help=_("PLUMgrid NOS topology name")), ] + + +cfg.CONF.register_opts(nos_server_opts, "PLUMgridNOS") + + +class QuantumPluginPLUMgridV2(db_base_plugin_v2.QuantumDbPluginV2): + + def __init__(self): + LOG.info(_('QuantumPluginPLUMgrid 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 + nos_username = cfg.CONF.PLUMgridNOS.username + nos_password = cfg.CONF.PLUMgridNOS.password + self.rest_conn = rest_connection.RestConnection(nos_plumgrid, + nos_port, timeout) + if self.rest_conn is None: + raise SystemExit(_('QuantumPluginPLUMgrid Status: ' + 'Aborting Plugin')) + + else: + # Plugin DB initialization + db.configure_db() + + # PLUMgrid NOS info validation + LOG.info(_('QuantumPluginPLUMgrid NOS: %s'), nos_plumgrid) + if not nos_plumgrid: + raise SystemExit(_('QuantumPluginPLUMgrid Status: ' + 'NOS value is missing in config file')) + + LOG.debug(_('QuantumPluginPLUMgrid Status: Quantum server with ' + 'PLUMgrid Plugin has started')) + + def create_network(self, context, network): + """ + Create network core Quantum API + """ + + LOG.debug(_('QuantumPluginPLUMgrid 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(QuantumPluginPLUMgridV2, self).create_network(context, + network) + + try: + LOG.debug(_('QuantumPluginPLUMgrid Status: %s, %s, %s'), + tenant_id, network["network"], 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: + err_message = _("PLUMgrid NOS communication failed") + LOG.Exception(err_message) + raise plum_excep.PLUMgridException(err_message) + + # return created network + return net + + def update_network(self, context, net_id, network): + """ + Update network core Quantum API + """ + + LOG.debug(_("QuantumPluginPLUMgridV2.update_network() called")) + self._network_admin_state(network) + tenant_id = self._get_tenant_id_for_create(context, network["network"]) + + # Get initial network details + original_net = super(QuantumPluginPLUMgridV2, self).get_network( + context, net_id) + + with context.session.begin(subtransactions=True): + # Plugin DB - Network Update + new_network = super( + QuantumPluginPLUMgridV2, 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: + err_message = _("PLUMgrid NOS communication failed") + LOG.Exception(err_message) + raise plum_excep.PLUMgridException(err_message) + + # return updated network + return new_network + + def delete_network(self, context, net_id): + """ + Delete network core Quantum API + """ + LOG.debug(_("QuantumPluginPLUMgrid Status: delete_network() called")) + super(QuantumPluginPLUMgridV2, self).get_network(context, net_id) + + with context.session.begin(subtransactions=True): + # Plugin DB - Network Delete + net_deleted = super(QuantumPluginPLUMgridV2, + 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: + err_message = _("PLUMgrid NOS communication failed") + LOG.Exception(err_message) + raise plum_excep.PLUMgridException(err_message) + + def create_port(self, context, port): + """ + Create port core Quantum API + """ + LOG.debug(_("QuantumPluginPLUMgrid 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(QuantumPluginPLUMgridV2, self).create_port(context, + port) + + def update_port(self, context, port_id, port): + """ + Update port core Quantum API + + """ + LOG.debug(_("QuantumPluginPLUMgrid 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(QuantumPluginPLUMgridV2, self).update_port( + context, port_id, port) + + def delete_port(self, context, port_id): + """ + Delete port core Quantum API + """ + + LOG.debug(_("QuantumPluginPLUMgrid 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(QuantumPluginPLUMgridV2, self).delete_port(context, port_id) + + def create_subnet(self, context, subnet): + """ + Create subnet core Quantum API + """ + + LOG.debug(_("QuantumPluginPLUMgrid Status: create_subnet() called")) + + with context.session.begin(subtransactions=True): + # Plugin DB - Subnet Create + subnet = super(QuantumPluginPLUMgridV2, 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: + err_message = _("PLUMgrid NOS communication failed: ") + LOG.Exception(err_message) + raise plum_excep.PLUMgridException(err_message) + + return subnet + + def delete_subnet(self, context, subnet_id): + """ + Delete subnet core Quantum API + """ + + LOG.debug(_("QuantumPluginPLUMgrid 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(QuantumPluginPLUMgridV2, 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: + err_message = _("PLUMgrid NOS communication failed: ") + LOG.Exception(err_message) + raise plum_excep.PLUMgridException(err_message) + + return del_subnet + + def update_subnet(self, context, subnet_id, subnet): + """ + Update subnet core Quantum 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(QuantumPluginPLUMgridV2, 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: + err_message = _("PLUMgrid NOS communication failed: ") + LOG.Exception(err_message) + raise plum_excep.PLUMgridException(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: + err_message = _("Network Admin State Validation Falied: ") + LOG.Exception(err_message) + raise plum_excep.PLUMgridException(err_message) + return network diff --git a/quantum/plugins/plumgrid/plumgrid_nos_plugin/rest_connection.py b/quantum/plugins/plumgrid/plumgrid_nos_plugin/rest_connection.py new file mode 100644 index 000000000..9916958ff --- /dev/null +++ b/quantum/plugins/plumgrid/plumgrid_nos_plugin/rest_connection.py @@ -0,0 +1,92 @@ +# 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. + +""" +Quantum 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 quantum.openstack.common import jsonutils as json +from quantum.openstack.common import log as logging +from quantum.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(_('QuantumPluginPLUMgrid 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: %s %s %s"), self.server, self.port, + 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: %s %s %s"), + nos_url, body_data, headers) + conn.request(action, nos_url, body_data, headers) + resp = conn.getresponse() + resp_str = resp.read() + + LOG.debug(_("PLUMgrid_NOS_Server Connection Data: %s, %s"), + resp, 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_message) + + ret = (resp.status, resp.reason, resp_str) + except urllib2.HTTPError, e: + 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 diff --git a/quantum/tests/unit/plumgrid/__init__.py b/quantum/tests/unit/plumgrid/__init__.py new file mode 100644 index 000000000..39e9b8d13 --- /dev/null +++ b/quantum/tests/unit/plumgrid/__init__.py @@ -0,0 +1,17 @@ +# 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. diff --git a/quantum/tests/unit/plumgrid/test_plumgrid_plugin.py b/quantum/tests/unit/plumgrid/test_plumgrid_plugin.py new file mode 100644 index 000000000..301bf6af5 --- /dev/null +++ b/quantum/tests/unit/plumgrid/test_plumgrid_plugin.py @@ -0,0 +1,77 @@ +# 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. + +""" +Test cases for Quantum PLUMgrid Plug-in +""" + +from mock import patch + +from quantum.manager import QuantumManager +from quantum.tests.unit import test_db_plugin as test_plugin + + +class PLUMgridPluginV2TestCase(test_plugin.QuantumDbPluginV2TestCase): + + _plugin_name = ('quantum.plugins.plumgrid.plumgrid_nos_plugin.' + 'plumgrid_plugin.QuantumPluginPLUMgridV2') + + def setUp(self): + self.restHTTPConnection = patch('httplib.HTTPConnection') + self.restHTTPConnection.start() + super(PLUMgridPluginV2TestCase, self).setUp(self._plugin_name) + + def tearDown(self): + super(PLUMgridPluginV2TestCase, self).tearDown() + self.restHTTPConnection.stop() + + +class TestPlumgridPluginV2HTTPResponse(test_plugin.TestV2HTTPResponse, + PLUMgridPluginV2TestCase): + + pass + + +class TestPlumgridPluginPortsV2(test_plugin.TestPortsV2, + PLUMgridPluginV2TestCase): + + pass + + +class TestPlumgridPluginNetworksV2(test_plugin.TestNetworksV2, + PLUMgridPluginV2TestCase): + + pass + + +class TestPlumgridPluginSubnetsV2(test_plugin.TestSubnetsV2, + PLUMgridPluginV2TestCase): + + pass + + +class TestPlumgridNetworkAdminState(PLUMgridPluginV2TestCase): + + def test_network_admin_state(self): + name = 'network_test' + admin_status_up = False + tenant_id = 'tenant_test' + network = {'network': {'name': name, + 'admin_state_up': admin_status_up, + 'tenant_id': tenant_id}} + plugin = QuantumManager.get_plugin() + self.assertEqual(plugin._network_admin_state(network), network) diff --git a/setup.py b/setup.py index cc2e399c4..cadd35280 100644 --- a/setup.py +++ b/setup.py @@ -53,6 +53,7 @@ ryu_plugin_config_path = 'etc/quantum/plugins/ryu' meta_plugin_config_path = 'etc/quantum/plugins/metaplugin' nec_plugin_config_path = 'etc/quantum/plugins/nec' hyperv_plugin_config_path = 'etc/quantum/plugins/hyperv' +plumgrid_plugin_config_path = 'etc/quantum/plugins/plumgrid' if sys.platform == 'win32': # Windows doesn't have an "/etc" directory equivalent @@ -107,6 +108,8 @@ else: (nec_plugin_config_path, ['etc/quantum/plugins/nec/nec.ini']), (hyperv_plugin_config_path, ['etc/quantum/plugins/hyperv/hyperv_quantum_plugin.ini']), + (plumgrid_plugin_config_path, + ['etc/quantum/plugins/plumgrid/plumgrid.ini']), ] ConsoleScripts = [