Manually added OpenStack API code
[osm/vim-emu.git] / src / emuvim / api / openstack / openstack_dummies / neutron_dummy_api.py
diff --git a/src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py b/src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py
new file mode 100644 (file)
index 0000000..03c01c1
--- /dev/null
@@ -0,0 +1,915 @@
+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 logging
+import json
+import uuid
+import copy
+
+
+class NeutronDummyApi(BaseOpenstackDummy):
+    def __init__(self, ip, port, compute):
+        super(NeutronDummyApi, self).__init__(ip, port)
+        self.compute = compute
+
+        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})
+        self.api.add_resource(NeutronShowNetwork, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronCreateNetwork, "/v2.0/networks.json", "/v2.0/networks",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronUpdateNetwork, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronDeleteNetwork, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronListSubnets, "/v2.0/subnets.json", "/v2.0/subnets",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronShowSubnet, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronCreateSubnet, "/v2.0/subnets.json", "/v2.0/subnets",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronUpdateSubnet, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronDeleteSubnet, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronListPorts, "/v2.0/ports.json", "/v2.0/ports",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronShowPort, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronCreatePort, "/v2.0/ports.json", "/v2.0/ports",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronUpdatePort, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
+                              resource_class_kwargs={'api': self})
+        self.api.add_resource(NeutronDeletePort, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
+                              resource_class_kwargs={'api': self})
+        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)
+
+
+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()
+
+
+class NeutronListAPIVersions(Resource):
+    def get(self):
+        """
+        Lists API versions.
+
+        :return: Returns a json with API versions.
+        :rtype: :class:`flask.response`
+        """
+        logging.debug("API CALL: Neutron - List API Versions")
+        resp = dict()
+        resp['versions'] = dict()
+
+        versions = [{
+            "status": "CURRENT",
+            "id": "v2.0",
+            "links": [
+                {
+                    "href": request.url_root + '/v2.0',
+                    "rel": "self"
+                }
+            ]
+        }]
+        resp['versions'] = versions
+
+        return Response(json.dumps(resp), status=200, mimetype='application/json')
+
+
+class NeutronShowAPIv2Details(Resource):
+    def get(self):
+        """
+        Returns API details.
+
+        :return: Returns a json with API details.
+        :rtype: :class:`flask.response`
+        """
+        logging.debug("API CALL: %s GET" % str(self.__class__.__name__))
+        resp = dict()
+
+        resp['resources'] = dict()
+        resp['resources'] = [{
+            "links": [
+                {
+                    "href": request.url_root + 'v2.0/subnets',
+                    "rel": "self"
+                }
+            ],
+            "name": "subnet",
+            "collection": "subnets"
+        },
+            {
+                "links": [
+                    {
+                        "href": request.url_root + 'v2.0/networks',
+                        "rel": "self"
+                    }
+                ],
+                "name": "network",
+                "collection": "networks"
+            },
+            {
+                "links": [
+                    {
+                        "href": request.url_root + 'v2.0/ports',
+                        "rel": "self"
+                    }
+                ],
+                "name": "ports",
+                "collection": "ports"
+            }
+        ]
+
+        return Response(json.dumps(resp), status=200, mimetype='application/json')
+
+
+class NeutronListNetworks(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def get(self):
+        """
+        Lists all networks, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
+        network with the name, or the networks specified via id.
+
+        :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__))
+        try:
+            if request.args.get('name'):
+                tmp_network = NeutronShowNetwork(self.api)
+                return tmp_network.get_network(request.args.get('name'), True)
+            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)
+
+            network_list = list()
+            network_dict = dict()
+
+            if len(id_list) == 0:
+                for net in self.api.compute.nets.values():
+                    tmp_network_dict = net.create_network_dict()
+                    if tmp_network_dict not in network_list:
+                        network_list.append(tmp_network_dict)
+            else:
+                for net in self.api.compute.nets.values():
+                    if net.id in id_list:
+                        tmp_network_dict = net.create_network_dict()
+                        if tmp_network_dict not in network_list:
+                            network_list.append(tmp_network_dict)
+
+            network_dict["networks"] = network_list
+
+            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')
+
+
+class NeutronShowNetwork(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def get(self, network_id):
+        """
+        Returns the network, specified via 'network_id'.
+
+        :param network_id: The unique ID string of the network.
+        :type network_id: ``str``
+        :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__))
+        return self.get_network(network_id, False)
+
+    def get_network(self, network_name_or_id, as_list):
+        """
+        Returns one network description of the network, specified via 'network_name_or_id'.
+
+        :param network_name_or_id: The indicator string, which specifies the requested network.
+        :type network_name_or_id: ``str``
+        :param as_list: Determines if the network description should start with the root node 'network' or 'networks'.
+        :type as_list: ``bool``
+        :return: Returns a json response, with one network description.
+        :rtype: :class:`flask.response`
+        """
+        try:
+            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')
+
+            tmp_network_dict = net.create_network_dict()
+            tmp_dict = dict()
+            if as_list:
+                tmp_dict["networks"] = [tmp_network_dict]
+            else:
+                tmp_dict["network"] = tmp_network_dict
+
+            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')
+
+
+class NeutronCreateNetwork(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def post(self):
+        """
+        Creates a network with the name, specified within the request under ['network']['name'].
+
+        :return: * 400, if the network already exists.
+            * 500, if any exception occurred while creation.
+            * 201, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.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')
+
+            net = self.api.compute.create_network(name)
+            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')
+
+
+class NeutronUpdateNetwork(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def put(self, network_id):  # TODO currently only the name will be changed
+        """
+        Updates the existing network with the given parameters.
+
+        :param network_id: The indicator string, which specifies the requested network.
+        :type network_id: ``str``
+        :return: * 404, if the network could not be found.
+            * 500, if any exception occurred while updating the network.
+            * 200, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.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"]
+                if "subnets" in network_dict["network"]:
+                    pass  # tmp_network_dict["subnets"] = None
+                if "name" in network_dict["network"] and net.name != network_dict["network"]["name"]:
+                    net.name = network_dict["network"]["name"]
+                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"
+                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('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')
+
+
+class NeutronDeleteNetwork(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def delete(self, network_id):
+        """
+        Deletes the specified network and all its subnets.
+
+        :param network_id: The indicator string, which specifies the requested network.
+        :type network_id: ``str``
+        :return: * 404, if the network or the subnet could not be removed.
+            * 500, if any exception occurred while deletion.
+            * 204, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.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',
+                                status=404, mimetype='application/json')
+
+            net = self.api.compute.nets[network_id]
+            delete_subnet = NeutronDeleteSubnet(self.api)
+            resp = delete_subnet.delete(net.subnet_id)
+
+            if not '204' in resp.status and not '404' 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')
+        except Exception as ex:
+            logging.exception("Neutron: Delete network exception.")
+            return Response(ex.message, status=500, mimetype='application/json')
+
+
+class NeutronListSubnets(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def get(self):
+        """
+        Lists all subnets, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
+        subnet with the name, or the subnets specified via id.
+
+        :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__))
+        try:
+            if request.args.get('name'):
+                show_subnet = NeutronShowSubnet(self.api)
+                return show_subnet.get_subnet(request.args.get('name'), True)
+            id_list = request.args.getlist('id')
+            if len(id_list) == 1:
+                show_subnet = NeutronShowSubnet(self.api)
+                return show_subnet.get_subnet(id_list[0], True)
+
+            subnet_list = list()
+            subnet_dict = dict()
+
+            if len(id_list) == 0:
+                for net in self.api.compute.nets.values():
+                    if net.subnet_id is not None:
+                        tmp_subnet_dict = net.create_subnet_dict()
+                        subnet_list.append(tmp_subnet_dict)
+            else:
+                for net in self.api.compute.nets.values():
+                    if net.subnet_id in id_list:
+                        tmp_subnet_dict = net.create_subnet_dict()
+                        subnet_list.append(tmp_subnet_dict)
+
+            subnet_dict["subnets"] = subnet_list
+
+            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')
+
+
+class NeutronShowSubnet(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def get(self, subnet_id):
+        """
+        Returns the subnet, specified via 'subnet_id'.
+
+        :param subnet_id: The unique ID string of the subnet.
+        :type subnet_id: ``str``
+        :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__))
+        return self.get_subnet(subnet_id, False)
+
+    def get_subnet(self, subnet_name_or_id, as_list):
+        """
+        Returns one subnet description of the subnet, specified via 'subnet_name_or_id'.
+
+        :param subnet_name_or_id: The indicator string, which specifies the requested subnet.
+        :type subnet_name_or_id: ``str``
+        :param as_list: Determines if the subnet description should start with the root node 'subnet' or 'subnets'.
+        :type as_list: ``bool``
+        :return: Returns a json response, with one subnet description.
+        :rtype: :class:`flask.response`
+        """
+        try:
+            for net in self.api.compute.nets.values():
+                if net.subnet_id == subnet_name_or_id or net.subnet_name == subnet_name_or_id:
+                    tmp_subnet_dict = net.create_subnet_dict()
+                    tmp_dict = dict()
+                    if as_list:
+                        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('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')
+
+
+class NeutronCreateSubnet(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def post(self):
+        """
+        Creates a subnet with the name, specified within the request under ['subnet']['name'].
+
+        :return: * 400, if the 'CIDR' format is wrong or it does not exist.
+            * 404, if the network was not found.
+            * 409, if the corresponding network already has one subnet.
+            * 500, if any exception occurred while creation and
+            * 201, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.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'])
+
+            if net is None:
+                return Response('Could not find network.\n', status=404, mimetype='application/json')
+
+            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')
+
+            if "id" in subnet_dict["subnet"]:
+                net.subnet_id = subnet_dict["subnet"]["id"]
+            else:
+                net.subnet_id = str(uuid.uuid4())
+            import emuvim.api.heat.ip_handler as IP
+            net.set_cidr(IP.get_new_cidr(net.subnet_id))
+
+            if "tenant_id" in subnet_dict["subnet"]:
+                pass
+            if "allocation_pools" in subnet_dict["subnet"]:
+                pass
+            if "gateway_ip" in subnet_dict["subnet"]:
+                net.gateway_ip = subnet_dict["subnet"]["gateway_ip"]
+            if "ip_version" in subnet_dict["subnet"]:
+                pass
+            if "enable_dhcp" in subnet_dict["subnet"]:
+                pass
+
+            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')
+
+
+class NeutronUpdateSubnet(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def put(self, subnet_id):
+        """
+        Updates the existing subnet with the given parameters.
+
+        :param subnet_id: The indicator string, which specifies the requested subnet.
+        :type subnet_id: ``str``
+        :return: * 404, if the network could not be found.
+            * 500, if any exception occurred while updating the network.
+            * 200, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.debug("API CALL: %s PUT" % str(self.__class__.__name__))
+        try:
+            for net in self.api.compute.nets.values():
+                if net.subnet_id == subnet_id:
+                    subnet_dict = json.loads(request.data)
+
+                    if "name" in subnet_dict["subnet"]:
+                        net.subnet_name = subnet_dict["subnet"]["name"]
+                    if "network_id" in subnet_dict["subnet"]:
+                        net.id = subnet_dict["subnet"]["network_id"]
+                    if "tenant_id" in subnet_dict["subnet"]:
+                        pass
+                    if "allocation_pools" in subnet_dict["subnet"]:
+                        pass
+                    if "gateway_ip" in subnet_dict["subnet"]:
+                        net.gateway_ip = subnet_dict["subnet"]["gateway_ip"]
+                    if "ip_version" in subnet_dict["subnet"]:
+                        pass
+                    if "cidr" in subnet_dict["subnet"]:
+                        net.set_cidr(subnet_dict["subnet"]["cidr"])
+                    if "id" in subnet_dict["subnet"]:
+                        net.subnet_id = subnet_dict["subnet"]["id"]
+                    if "enable_dhcp" in subnet_dict["subnet"]:
+                        pass
+
+                    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('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')
+
+
+class NeutronDeleteSubnet(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def delete(self, subnet_id):
+        """
+        Deletes the specified subnet.
+
+        :param subnet_id: The indicator string, which specifies the requested subnet.
+        :type subnet_id: ``str``
+        :return: * 404, if the subnet could not be removed.
+            * 500, if any exception occurred while deletion.
+            * 204, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.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)
+                            if port.net_name == net.name:
+                                port.ip_address = None
+                                self.api.compute.dc.net.removeLink(
+                                    link=None,
+                                    node1=self.api.compute.dc.containers[server.name],
+                                    node2=self.api.compute.dc.switch)
+                                port.net_name = None
+
+                    net.delete_subnet()
+
+                    return Response('Subnet ' + str(subnet_id) + ' deleted.\n',
+                                    status=204, 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')
+
+
+class NeutronListPorts(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def get(self):
+        """
+        Lists all ports, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
+        port with the name, or the ports specified via id.
+
+        :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__))
+        try:
+            if request.args.get('name'):
+                show_port = NeutronShowPort(self.api)
+                return show_port.get_port(request.args.get('name'), True)
+            id_list = request.args.getlist('id')
+            if len(id_list) == 1:
+                show_port = NeutronShowPort(self.api)
+                return show_port.get_port(request.args.get('id'), True)
+
+            port_list = list()
+            port_dict = dict()
+
+            if len(id_list) == 0:
+                for port in self.api.compute.ports.values():
+                    tmp_port_dict = port.create_port_dict(self.api.compute)
+                    port_list.append(tmp_port_dict)
+            else:
+                for port in self.api.compute.ports.values():
+                    if port.id in id_list:
+                        tmp_port_dict = port.create_port_dict(self.api.compute)
+                        port_list.append(tmp_port_dict)
+
+            port_dict["ports"] = port_list
+
+            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')
+
+
+class NeutronShowPort(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def get(self, port_id):
+        """
+        Returns the port, specified via 'port_id'.
+
+        :param port_id: The unique ID string of the network.
+        :type port_id: ``str``
+        :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__))
+        return self.get_port(port_id, False)
+
+    def get_port(self, port_name_or_id, as_list):
+        """
+        Returns one network description of the port, specified via 'port_name_or_id'.
+
+        :param port_name_or_id: The indicator string, which specifies the requested port.
+        :type port_name_or_id: ``str``
+        :param as_list: Determines if the port description should start with the root node 'port' or 'ports'.
+        :type as_list: ``bool``
+        :return: Returns a json response, with one port description.
+        :rtype: :class:`flask.response`
+        """
+        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')
+            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')
+        except Exception as ex:
+            logging.exception("Neutron: Show port exception.")
+            return Response(ex.message, status=500, mimetype='application/json')
+
+
+class NeutronCreatePort(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def post(self):
+        """
+        Creates a port with the name, specified within the request under ['port']['name'].
+
+        :return: * 404, if the network could not be found.
+            * 500, if any exception occurred while creation and
+            * 201, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.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')
+
+            net = self.api.compute.nets[net_id]
+            if 'name' in port_dict['port']:
+                name = port_dict['port']['name']
+            else:
+                num_ports = len(self.api.compute.ports)
+                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')
+
+            port = self.api.compute.create_port(name)
+
+            port.net_name = net.name
+            port.ip_address = net.get_new_ip_address(name)
+
+            if "admin_state_up" in port_dict["port"]:
+                pass
+            if "device_id" in port_dict["port"]:
+                pass
+            if "device_owner" in port_dict["port"]:
+                pass
+            if "fixed_ips" in port_dict["port"]:
+                pass
+            if "mac_address" in port_dict["port"]:
+                port.mac_address = port_dict["port"]["mac_address"]
+            if "status" in port_dict["port"]:
+                pass
+            if "tenant_id" in port_dict["port"]:
+                pass
+
+            # 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:
+                        stack.ports[name] = port
+
+            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')
+
+
+class NeutronUpdatePort(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def put(self, port_id):
+        """
+        Updates the existing port with the given parameters.
+
+        :param network_id: The indicator string, which specifies the requested port.
+        :type network_id: ``str``
+        :return: * 404, if the network could not be found.
+            * 500, if any exception occurred while updating the network.
+            * 200, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.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')
+            old_port = copy.copy(port)
+
+            stack = None
+            for s in self.api.compute.stacks.values():
+                for port in s.ports.values():
+                    if port.id == port_id:
+                        stack = s
+            if "admin_state_up" in port_dict["port"]:
+                pass
+            if "device_id" in port_dict["port"]:
+                pass
+            if "device_owner" in port_dict["port"]:
+                pass
+            if "fixed_ips" in port_dict["port"]:
+                pass
+            if "id" in port_dict["port"]:
+                port.id = port_dict["port"]["id"]
+            if "mac_address" in port_dict["port"]:
+                port.mac_address = port_dict["port"]["mac_address"]
+            if "name" in port_dict["port"] and port_dict["port"]["name"] != port.name:
+                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.ports[port.name] = stack.ports[old_port.name]
+                    del stack.ports[old_port.name]
+            if "network_id" in port_dict["port"]:
+                pass
+            if "status" in port_dict["port"]:
+                pass
+            if "tenant_id" in port_dict["port"]:
+                pass
+
+            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')
+
+
+class NeutronDeletePort(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    def delete(self, port_id):
+        """
+        Deletes the specified port.
+
+        :param port_id: The indicator string, which specifies the requested port.
+        :type port_id: ``str``
+        :return: * 404, if the port could not be found.
+            * 500, if any exception occurred while deletion.
+            * 204, if everything worked out.
+        :rtype: :class:`flask.response`
+        """
+        logging.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)
+            stack = None
+            for s in self.api.compute.stacks.values():
+                for p in s.ports.values():
+                    if p.id == port_id:
+                        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)
+                for server in stack.servers.values():
+                    try:
+                        server.port_names.remove(port.name)
+                    except ValueError:
+                        pass
+
+            # delete the port
+            self.api.compute.delete_port(port.id)
+
+            return Response('Port ' + port_id + ' deleted.\n', status=204, mimetype='application/json')
+
+        except Exception as ex:
+            logging.exception("Neutron: Delete port exception.")
+            return Response(ex.message, status=500, mimetype='application/json')
+
+
+class NeutronAddFloatingIp(Resource):
+    def __init__(self, api):
+        self.api = api
+
+    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.
+        """
+        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')
+
+
+    def post(self):
+        """
+        Adds a floating IP to neutron.
+
+        :return: Returns a floating network description.
+        :rtype: :class:`flask.response`
+        """
+        logging.debug("API CALL: %s POST" % str(self.__class__.__name__))
+        try:
+            # Fiddle with floating_network !
+            req = json.loads(request.data)
+
+            network_id = req["floatingip"]["floating_network_id"]
+            net = self.api.compute.find_network_by_name_or_id(network_id)
+            if net != self.api.manage.floating_network:
+                return Response("You have to specify the existing floating network\n",
+                                status=400, mimetype='application/json')
+
+            port_id = req["floatingip"].get("port_id", None)
+            port = self.api.compute.find_port_by_name_or_id(port_id)
+            if port is not None:
+                if port.net_name != self.api.manage.floating_network.name:
+                    return Response("You have to specify a port in the floating network\n",
+                                    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')
+            else:
+                num_ports = len(self.api.compute.ports)
+                name = "port:cp%s:fl:%s" % (num_ports, str(uuid.uuid4()))
+                port = self.api.compute.create_port(name)
+                port.net_name = net.name
+                port.ip_address = net.get_new_ip_address(name)
+
+            port.floating_ip = port.ip_address
+
+            response = dict()
+            resp = response["floatingip"] = dict()
+
+            resp["floating_network_id"] = net.id
+            resp["status"] = "ACTIVE"
+            resp["id"] = net.id
+            resp["port_id"] = port.id
+            resp["floating_ip_address"] = port.floating_ip
+            resp["fixed_ip_address"] = port.floating_ip
+
+            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')