X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2Fvim-emu.git;a=blobdiff_plain;f=src%2Femuvim%2Fapi%2Fopenstack%2Fopenstack_dummies%2Fneutron_dummy_api.py;h=e094f0e963c060ee6cbb43eb8f264d5c1d64820b;hp=38a5ad4d419d53deb0ad8d40643c129b9a1e332a;hb=b87991a24a3071c35560333617135d433ac16b8f;hpb=78faf0ec78bffc066105e090646b13faa6a26305 diff --git a/src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py b/src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py old mode 100644 new mode 100755 index 38a5ad4..e094f0e --- a/src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py +++ b/src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py @@ -1,20 +1,52 @@ +# Copyright (c) 2015 SONATA-NFV and Paderborn University +# 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. +# +# Neither the name of the SONATA-NFV, Paderborn University +# nor the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# This work has been performed in the framework of the SONATA project, +# funded by the European Commission under Grant number 671517 through +# the Horizon 2020 and 5G-PPP programmes. The authors would like to +# acknowledge the contributions of their colleagues of the SONATA +# partner consortium (www.sonata-nfv.eu). from flask_restful import Resource from flask import request, Response from emuvim.api.openstack.openstack_dummies.base_openstack_dummy import BaseOpenstackDummy from datetime import datetime +import neutron_sfc_dummy_api as SFC import logging import json import uuid import copy +LOG = logging.getLogger("api.openstack.neutron") + class NeutronDummyApi(BaseOpenstackDummy): def __init__(self, ip, port, compute): super(NeutronDummyApi, self).__init__(ip, port) self.compute = compute + # create default networks (OSM usually assumes to have these + # pre-configured) + self.compute.create_network("mgmt") + self.compute.create_network("mgmtnet") + self.api.add_resource(NeutronListAPIVersions, "/") - self.api.add_resource(Shutdown, "/shutdown") self.api.add_resource(NeutronShowAPIv2Details, "/v2.0") self.api.add_resource(NeutronListNetworks, "/v2.0/networks.json", "/v2.0/networks", resource_class_kwargs={'api': self}) @@ -49,20 +81,62 @@ class NeutronDummyApi(BaseOpenstackDummy): self.api.add_resource(NeutronAddFloatingIp, "/v2.0/floatingips.json", "/v2.0/floatingips", resource_class_kwargs={'api': self}) - def _start_flask(self): - logging.info("Starting %s endpoint @ http://%s:%d" % (__name__, self.ip, self.port)) - if self.app is not None: - self.app.before_request(self.dump_playbook) - self.app.run(self.ip, self.port, debug=True, use_reloader=False) + # Service Function Chaining (SFC) API + self.api.add_resource(SFC.PortPairsCreate, "/v2.0/sfc/port_pairs.json", "/v2.0/sfc/port_pairs", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairsUpdate, "/v2.0/sfc/port_pairs/.json", + "/v2.0/sfc/port_pairs/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairsDelete, "/v2.0/sfc/port_pairs/.json", + "/v2.0/sfc/port_pairs/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairsList, "/v2.0/sfc/port_pairs.json", "/v2.0/sfc/port_pairs", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairsShow, "/v2.0/sfc/port_pairs/.json", + "/v2.0/sfc/port_pairs/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairGroupCreate, "/v2.0/sfc/port_pair_groups.json", "/v2.0/sfc/port_pair_groups", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairGroupUpdate, "/v2.0/sfc/port_pair_groups/.json", + "/v2.0/sfc/port_pair_groups/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairGroupDelete, "/v2.0/sfc/port_pair_groups/.json", + "/v2.0/sfc/port_pair_groups/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairGroupList, "/v2.0/sfc/port_pair_groups.json", "/v2.0/sfc/port_pair_groups", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortPairGroupShow, "/v2.0/sfc/port_pair_groups/.json", + "/v2.0/sfc/port_pair_groups/", + resource_class_kwargs={'api': self}) -class Shutdown(Resource): - def get(self): - logging.debug(("%s is beeing shut down") % (__name__)) - func = request.environ.get('werkzeug.server.shutdown') - if func is None: - raise RuntimeError('Not running with the Werkzeug Server') - func() + self.api.add_resource(SFC.FlowClassifierCreate, "/v2.0/sfc/flow_classifiers.json", "/v2.0/sfc/flow_classifiers", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.FlowClassifierUpdate, "/v2.0/sfc/flow_classifiers/.json", + "/v2.0/sfc/flow_classifiers/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.FlowClassifierDelete, "/v2.0/sfc/flow_classifiers/.json", + "/v2.0/sfc/flow_classifiers/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.FlowClassifierList, "/v2.0/sfc/flow_classifiers.json", "/v2.0/sfc/flow_classifiers", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.FlowClassifierShow, "/v2.0/sfc/flow_classifiers/.json", + "/v2.0/sfc/flow_classifiers/", + resource_class_kwargs={'api': self}) + + self.api.add_resource(SFC.PortChainCreate, "/v2.0/sfc/port_chains.json", "/v2.0/sfc/port_chains", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortChainUpdate, "/v2.0/sfc/port_chains/.json", + "/v2.0/sfc/port_chains/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortChainDelete, "/v2.0/sfc/port_chains/.json", + "/v2.0/sfc/port_chains/", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortChainList, "/v2.0/sfc/port_chains.json", "/v2.0/sfc/port_chains", + resource_class_kwargs={'api': self}) + self.api.add_resource(SFC.PortChainShow, "/v2.0/sfc/port_chains/.json", + "/v2.0/sfc/port_chains/", + resource_class_kwargs={'api': self}) class NeutronListAPIVersions(Resource): @@ -73,7 +147,7 @@ class NeutronListAPIVersions(Resource): :return: Returns a json with API versions. :rtype: :class:`flask.response` """ - logging.debug("API CALL: Neutron - List API Versions") + LOG.debug("API CALL: Neutron - List API Versions") resp = dict() resp['versions'] = dict() @@ -89,7 +163,8 @@ class NeutronListAPIVersions(Resource): }] resp['versions'] = versions - return Response(json.dumps(resp), status=200, mimetype='application/json') + return Response(json.dumps(resp), status=200, + mimetype='application/json') class NeutronShowAPIv2Details(Resource): @@ -100,7 +175,7 @@ class NeutronShowAPIv2Details(Resource): :return: Returns a json with API details. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s GET" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s GET" % str(self.__class__.__name__)) resp = dict() resp['resources'] = dict() @@ -123,7 +198,7 @@ class NeutronShowAPIv2Details(Resource): ], "name": "network", "collection": "networks" - }, + }, { "links": [ { @@ -133,10 +208,11 @@ class NeutronShowAPIv2Details(Resource): ], "name": "ports", "collection": "ports" - } + } ] - return Response(json.dumps(resp), status=200, mimetype='application/json') + return Response(json.dumps(resp), status=200, + mimetype='application/json') class NeutronListNetworks(Resource): @@ -151,15 +227,24 @@ class NeutronListNetworks(Resource): :return: Returns a json response, starting with 'networks' as root node. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s GET" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s GET" % str(self.__class__.__name__)) + # LOG.debug("ARGS: {}".format(request.args)) try: if request.args.get('name'): tmp_network = NeutronShowNetwork(self.api) - return tmp_network.get_network(request.args.get('name'), True) + response = tmp_network.get_network( + request.args.get('name'), True) + LOG.debug("{} RESPONSE (1): {}".format( + self.__class__.__name__, response)) + return response id_list = request.args.getlist('id') if len(id_list) == 1: tmp_network = NeutronShowNetwork(self.api) - return tmp_network.get_network(request.args.get('id'), True) + response = tmp_network.get_network( + request.args.get('id'), True) + LOG.debug("{} RESPONSE (2): {}".format( + self.__class__.__name__, response)) + return response network_list = list() network_dict = dict() @@ -177,12 +262,15 @@ class NeutronListNetworks(Resource): network_list.append(tmp_network_dict) network_dict["networks"] = network_list - - return Response(json.dumps(network_dict), status=200, mimetype='application/json') + LOG.debug("{} RESPONSE (3): {}".format( + self.__class__.__name__, network_dict)) + return Response(json.dumps(network_dict), + status=200, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: List networks exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: List networks exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronShowNetwork(Resource): @@ -198,7 +286,7 @@ class NeutronShowNetwork(Resource): :return: Returns a json response, starting with 'network' as root node and one network description. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s GET" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s GET" % str(self.__class__.__name__)) return self.get_network(network_id, False) def get_network(self, network_name_or_id, as_list): @@ -213,9 +301,11 @@ class NeutronShowNetwork(Resource): :rtype: :class:`flask.response` """ try: - net = self.api.compute.find_network_by_name_or_id(network_name_or_id) + net = self.api.compute.find_network_by_name_or_id( + network_name_or_id) if net is None: - return Response(u'Network not found.\n', status=404, mimetype='application/json') + return Response(u'Network not found.\n', + status=404, mimetype='application/json') tmp_network_dict = net.create_network_dict() tmp_dict = dict() @@ -224,12 +314,13 @@ class NeutronShowNetwork(Resource): else: tmp_dict["network"] = tmp_network_dict - return Response(json.dumps(tmp_dict), status=200, mimetype='application/json') - + return Response(json.dumps(tmp_dict), status=200, + mimetype='application/json') except Exception as ex: logging.exception("Neutron: Show network exception.") - return Response(ex.message, status=500, mimetype='application/json') + return Response(ex.message, status=500, + mimetype='application/json') class NeutronCreateNetwork(Resource): @@ -245,19 +336,22 @@ class NeutronCreateNetwork(Resource): * 201, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s POST" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s POST" % str(self.__class__.__name__)) try: network_dict = json.loads(request.data) name = network_dict['network']['name'] net = self.api.compute.find_network_by_name_or_id(name) if net is not None: - return Response('Network already exists.\n', status=400, mimetype='application/json') + return Response('Network already exists.\n', + status=400, mimetype='application/json') net = self.api.compute.create_network(name) - return Response(json.dumps({"network": net.create_network_dict()}), status=201, mimetype='application/json') + return Response(json.dumps( + {"network": net.create_network_dict()}), status=201, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Create network excepiton.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Create network excepiton.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronUpdateNetwork(Resource): @@ -275,12 +369,11 @@ class NeutronUpdateNetwork(Resource): * 200, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s PUT" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s PUT" % str(self.__class__.__name__)) try: if network_id in self.api.compute.nets: net = self.api.compute.nets[network_id] network_dict = json.loads(request.data) - old_net = copy.copy(net) if "status" in network_dict["network"]: net.status = network_dict["network"]["status"] @@ -291,17 +384,21 @@ class NeutronUpdateNetwork(Resource): if "admin_state_up" in network_dict["network"]: pass # tmp_network_dict["admin_state_up"] = True if "tenant_id" in network_dict["network"]: - pass # tmp_network_dict["tenant_id"] = "c1210485b2424d48804aad5d39c61b8f" + # tmp_network_dict["tenant_id"] = "c1210485b2424d48804aad5d39c61b8f" + pass if "shared" in network_dict["network"]: pass # tmp_network_dict["shared"] = False - return Response(json.dumps(network_dict), status=200, mimetype='application/json') + return Response(json.dumps(network_dict), + status=200, mimetype='application/json') - return Response('Network not found.\n', status=404, mimetype='application/json') + return Response('Network not found.\n', status=404, + mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Show networks exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Show networks exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronDeleteNetwork(Resource): @@ -319,7 +416,7 @@ class NeutronDeleteNetwork(Resource): * 204, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s DELETE" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s DELETE" % str(self.__class__.__name__)) try: if network_id not in self.api.compute.nets: return Response('Could not find network. (' + network_id + ')\n', @@ -329,15 +426,16 @@ class NeutronDeleteNetwork(Resource): delete_subnet = NeutronDeleteSubnet(self.api) resp = delete_subnet.delete(net.subnet_id) - if not '204' in resp.status and not '404' in resp.status: + if '204' not in resp.status and '404' not in resp.status: return resp self.api.compute.delete_network(network_id) - return Response('Network ' + str(network_id) + ' deleted.\n', status=204, mimetype='application/json') + return Response('', status=204, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Delete network exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Delete network exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronListSubnets(Resource): @@ -352,7 +450,7 @@ class NeutronListSubnets(Resource): :return: Returns a json response, starting with 'subnets' as root node. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s GET" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s GET" % str(self.__class__.__name__)) try: if request.args.get('name'): show_subnet = NeutronShowSubnet(self.api) @@ -378,11 +476,13 @@ class NeutronListSubnets(Resource): subnet_dict["subnets"] = subnet_list - return Response(json.dumps(subnet_dict), status=200, mimetype='application/json') + return Response(json.dumps(subnet_dict), status=200, + mimetype='application/json') except Exception as ex: - logging.exception("Neutron: List subnets exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: List subnets exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronShowSubnet(Resource): @@ -398,7 +498,7 @@ class NeutronShowSubnet(Resource): :return: Returns a json response, starting with 'subnet' as root node and one subnet description. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s GET" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s GET" % str(self.__class__.__name__)) return self.get_subnet(subnet_id, False) def get_subnet(self, subnet_name_or_id, as_list): @@ -421,13 +521,16 @@ class NeutronShowSubnet(Resource): tmp_dict["subnets"] = [tmp_subnet_dict] else: tmp_dict["subnet"] = tmp_subnet_dict - return Response(json.dumps(tmp_dict), status=200, mimetype='application/json') + return Response(json.dumps(tmp_dict), + status=200, mimetype='application/json') - return Response('Subnet not found. (' + subnet_name_or_id + ')\n', status=404, mimetype='application/json') + return Response('Subnet not found. (' + subnet_name_or_id + + ')\n', status=404, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Show subnet exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Show subnet exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronCreateSubnet(Resource): @@ -445,17 +548,23 @@ class NeutronCreateSubnet(Resource): * 201, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s POST" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s POST" % str(self.__class__.__name__)) try: subnet_dict = json.loads(request.data) - net = self.api.compute.find_network_by_name_or_id(subnet_dict['subnet']['network_id']) + net = self.api.compute.find_network_by_name_or_id( + subnet_dict['subnet']['network_id']) if net is None: - return Response('Could not find network.\n', status=404, mimetype='application/json') + return Response('Could not find network.\n', + status=404, mimetype='application/json') - net.subnet_name = subnet_dict["subnet"].get('name', str(net.name) + '-sub') + net.subnet_name = subnet_dict["subnet"].get( + 'name', str(net.name) + '-sub') if net.subnet_id is not None: - return Response('Only one subnet per network is supported\n', status=409, mimetype='application/json') + LOG.error( + "Only one subnet per network is supported: {}".format(net.subnet_id)) + return Response('Only one subnet per network is supported\n', + status=409, mimetype='application/json') if "id" in subnet_dict["subnet"]: net.subnet_id = subnet_dict["subnet"]["id"] @@ -475,11 +584,13 @@ class NeutronCreateSubnet(Resource): if "enable_dhcp" in subnet_dict["subnet"]: pass - return Response(json.dumps({'subnet': net.create_subnet_dict()}), status=201, mimetype='application/json') + return Response(json.dumps( + {'subnet': net.create_subnet_dict()}), status=201, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Create network excepiton.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Create network excepiton.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronUpdateSubnet(Resource): @@ -497,7 +608,7 @@ class NeutronUpdateSubnet(Resource): * 200, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s PUT" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s PUT" % str(self.__class__.__name__)) try: for net in self.api.compute.nets.values(): if net.subnet_id == subnet_id: @@ -524,13 +635,16 @@ class NeutronUpdateSubnet(Resource): net.subnet_update_time = str(datetime.now()) tmp_dict = {'subnet': net.create_subnet_dict()} - return Response(json.dumps(tmp_dict), status=200, mimetype='application/json') + return Response(json.dumps(tmp_dict), + status=200, mimetype='application/json') - return Response('Network not found.\n', status=404, mimetype='application/json') + return Response('Network not found.\n', status=404, + mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Show networks exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Show networks exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronDeleteSubnet(Resource): @@ -548,13 +662,18 @@ class NeutronDeleteSubnet(Resource): * 204, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s DELETE" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s DELETE" % str(self.__class__.__name__)) try: for net in self.api.compute.nets.values(): if net.subnet_id == subnet_id: for server in self.api.compute.computeUnits.values(): for port_name in server.port_names: - port = self.api.compute.find_port_by_name_or_id(port_name) + port = self.api.compute.find_port_by_name_or_id( + port_name) + if port is None: + LOG.warning( + "Port search for {} returned None.".format(port_name)) + continue if port.net_name == net.name: port.ip_address = None self.api.compute.dc.net.removeLink( @@ -565,13 +684,15 @@ class NeutronDeleteSubnet(Resource): net.delete_subnet() - return Response('Subnet ' + str(subnet_id) + ' deleted.\n', - status=204, mimetype='application/json') + return Response( + '', status=204, mimetype='application/json') - return Response('Could not find subnet.', status=404, mimetype='application/json') + return Response('Could not find subnet.', + status=404, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Delete subnet exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Delete subnet exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronListPorts(Resource): @@ -586,7 +707,7 @@ class NeutronListPorts(Resource): :return: Returns a json response, starting with 'ports' as root node. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s GET" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s GET" % str(self.__class__.__name__)) try: if request.args.get('name'): show_port = NeutronShowPort(self.api) @@ -611,11 +732,13 @@ class NeutronListPorts(Resource): port_dict["ports"] = port_list - return Response(json.dumps(port_dict), status=200, mimetype='application/json') + return Response(json.dumps(port_dict), status=200, + mimetype='application/json') except Exception as ex: - logging.exception("Neutron: List ports exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: List ports exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronShowPort(Resource): @@ -631,7 +754,7 @@ class NeutronShowPort(Resource): :return: Returns a json response, starting with 'port' as root node and one network description. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s GET" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s GET" % str(self.__class__.__name__)) return self.get_port(port_id, False) def get_port(self, port_name_or_id, as_list): @@ -648,17 +771,20 @@ class NeutronShowPort(Resource): try: port = self.api.compute.find_port_by_name_or_id(port_name_or_id) if port is None: - return Response('Port not found. (' + port_name_or_id + ')\n', status=404, mimetype='application/json') + return Response('Port not found. (' + port_name_or_id + ')\n', + status=404, mimetype='application/json') tmp_port_dict = port.create_port_dict(self.api.compute) tmp_dict = dict() if as_list: tmp_dict["ports"] = [tmp_port_dict] else: tmp_dict["port"] = tmp_port_dict - return Response(json.dumps(tmp_dict), status=200, mimetype='application/json') + return Response(json.dumps(tmp_dict), status=200, + mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Show port exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Show port exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronCreatePort(Resource): @@ -674,13 +800,14 @@ class NeutronCreatePort(Resource): * 201, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s POST" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s POST" % str(self.__class__.__name__)) try: port_dict = json.loads(request.data) net_id = port_dict['port']['network_id'] if net_id not in self.api.compute.nets: - return Response('Could not find network.\n', status=404, mimetype='application/json') + return Response('Could not find network.\n', + status=404, mimetype='application/json') net = self.api.compute.nets[net_id] if 'name' in port_dict['port']: @@ -690,7 +817,8 @@ class NeutronCreatePort(Resource): name = "port:cp%s:man:%s" % (num_ports, str(uuid.uuid4())) if self.api.compute.find_port_by_name_or_id(name): - return Response("Port with name %s already exists.\n" % name, status=500, mimetype='application/json') + return Response("Port with name %s already exists.\n" % + name, status=500, mimetype='application/json') port = self.api.compute.create_port(name) @@ -712,7 +840,8 @@ class NeutronCreatePort(Resource): if "tenant_id" in port_dict["port"]: pass - # add the port to a stack if the specified network is a stack network + # add the port to a stack if the specified network is a stack + # network for stack in self.api.compute.stacks.values(): for net in stack.nets.values(): if net.id == net_id: @@ -721,8 +850,9 @@ class NeutronCreatePort(Resource): return Response(json.dumps({'port': port.create_port_dict(self.api.compute)}), status=201, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Show port exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Show port exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronUpdatePort(Resource): @@ -740,12 +870,13 @@ class NeutronUpdatePort(Resource): * 200, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s PUT" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s PUT" % str(self.__class__.__name__)) try: port_dict = json.loads(request.data) port = self.api.compute.find_port_by_name_or_id(port_id) if port is None: - return Response("Port with id %s does not exists.\n" % port_id, status=404, mimetype='application/json') + return Response("Port with id %s does not exists.\n" % + port_id, status=404, mimetype='application/json') old_port = copy.copy(port) stack = None @@ -769,7 +900,8 @@ class NeutronUpdatePort(Resource): port.set_name(port_dict["port"]["name"]) if stack is not None: if port.net_name in stack.nets: - stack.nets[port.net_name].update_port_name_for_ip_address(port.ip_address, port.name) + stack.nets[port.net_name].update_port_name_for_ip_address( + port.ip_address, port.name) stack.ports[port.name] = stack.ports[old_port.name] del stack.ports[old_port.name] if "network_id" in port_dict["port"]: @@ -782,8 +914,9 @@ class NeutronUpdatePort(Resource): return Response(json.dumps({'port': port.create_port_dict(self.api.compute)}), status=200, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Update port exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Update port exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronDeletePort(Resource): @@ -801,11 +934,12 @@ class NeutronDeletePort(Resource): * 204, if everything worked out. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s DELETE" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s DELETE" % str(self.__class__.__name__)) try: port = self.api.compute.find_port_by_name_or_id(port_id) if port is None: - return Response("Port with id %s does not exists.\n" % port_id, status=404) + return Response("Port with id %s does not exists.\n" % + port_id, status=404) stack = None for s in self.api.compute.stacks.values(): for p in s.ports.values(): @@ -813,7 +947,8 @@ class NeutronDeletePort(Resource): stack = s if stack is not None: if port.net_name in stack.nets: - stack.nets[port.net_name].withdraw_ip_address(port.ip_address) + stack.nets[port.net_name].withdraw_ip_address( + port.ip_address) for server in stack.servers.values(): try: server.port_names.remove(port.name) @@ -823,11 +958,12 @@ class NeutronDeletePort(Resource): # delete the port self.api.compute.delete_port(port.id) - return Response('Port ' + port_id + ' deleted.\n', status=204, mimetype='application/json') + return Response('', status=204, mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Delete port exception.") - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Delete port exception.") + return Response(ex.message, status=500, + mimetype='application/json') class NeutronAddFloatingIp(Resource): @@ -836,32 +972,25 @@ class NeutronAddFloatingIp(Resource): def get(self): """ - Added a quick and dirty fake for the OSM integration. Returns a list of - floating IPs. Has nothing to do with the setup inside the emulator. - But its enough to make the OSM driver happy. - @PG Sandman: Feel free to improve this and let it do something meaningful. + Returns a Floating IP for a port. + + Currently ports are not mapped to individual IPs, but the + (potentially shared) Docker external IP is returned. """ + port_id = request.args.get("port_id") + if not port_id: + message = "Neutron: List API for FloatingIPs is not implemented" + LOG.exception(message) + return Response(message, status=500, + mimetype='application/json') + port = self.api.compute.find_port_by_name_or_id(port_id) + ip = port.assigned_container.dcinfo["NetworkSettings"]["IPAddress"] resp = dict() - resp["floatingips"] = list() - # create a list of floting IP definitions and return it - for i in range(100, 110): - ip=dict() - ip["router_id"] = "router_id" - ip["description"] = "hardcoded in api" - ip["created_at"] = "router_id" - ip["updated_at"] = "router_id" - ip["revision_number"] = 1 - ip["tenant_id"] = "tenant_id" - ip["project_id"] = "project_id" - ip["floating_network_id"] = str(i) - ip["status"] = "ACTIVE" - ip["id"] = str(i) - ip["port_id"] = "port_id" - ip["floating_ip_address"] = "172.0.0.%d" % i - ip["fixed_ip_address"] = "10.0.0.%d" % i - resp["floatingips"].append(ip) - return Response(json.dumps(resp), status=200, mimetype='application/json') - + resp["floatingips"] = [ + {'floating_ip_address': ip} + ] + return Response(json.dumps(resp), status=200, + mimetype='application/json') def post(self): """ @@ -870,7 +999,7 @@ class NeutronAddFloatingIp(Resource): :return: Returns a floating network description. :rtype: :class:`flask.response` """ - logging.debug("API CALL: %s POST" % str(self.__class__.__name__)) + LOG.debug("API CALL: %s POST" % str(self.__class__.__name__)) try: # Fiddle with floating_network ! req = json.loads(request.data) @@ -889,7 +1018,8 @@ class NeutronAddFloatingIp(Resource): status=400, mimetype='application/json') if port.floating_ip is not None: - return Response("We allow only one floating ip per port\n", status=400, mimetype='application/json') + return Response("We allow only one floating ip per port\n", + status=400, mimetype='application/json') else: num_ports = len(self.api.compute.ports) name = "port:cp%s:fl:%s" % (num_ports, str(uuid.uuid4())) @@ -909,7 +1039,9 @@ class NeutronAddFloatingIp(Resource): resp["floating_ip_address"] = port.floating_ip resp["fixed_ip_address"] = port.floating_ip - return Response(json.dumps(response), status=200, mimetype='application/json') + return Response(json.dumps(response), status=200, + mimetype='application/json') except Exception as ex: - logging.exception("Neutron: Create FloatingIP exception %s.", ex) - return Response(ex.message, status=500, mimetype='application/json') + LOG.exception("Neutron: Create FloatingIP exception %s.", ex) + return Response(ex.message, status=500, + mimetype='application/json')