1 from flask_restful
import Resource
2 from flask
import request
, Response
3 from emuvim
.api
.openstack
.openstack_dummies
.base_openstack_dummy
import BaseOpenstackDummy
4 from datetime
import datetime
11 LOG
= logging
.getLogger("api.openstack.neutron")
14 class NeutronDummyApi(BaseOpenstackDummy
):
15 def __init__(self
, ip
, port
, compute
):
16 super(NeutronDummyApi
, self
).__init
__(ip
, port
)
17 self
.compute
= compute
19 self
.api
.add_resource(NeutronListAPIVersions
, "/")
20 self
.api
.add_resource(Shutdown
, "/shutdown")
21 self
.api
.add_resource(NeutronShowAPIv2Details
, "/v2.0")
22 self
.api
.add_resource(NeutronListNetworks
, "/v2.0/networks.json", "/v2.0/networks",
23 resource_class_kwargs
={'api': self
})
24 self
.api
.add_resource(NeutronShowNetwork
, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
25 resource_class_kwargs
={'api': self
})
26 self
.api
.add_resource(NeutronCreateNetwork
, "/v2.0/networks.json", "/v2.0/networks",
27 resource_class_kwargs
={'api': self
})
28 self
.api
.add_resource(NeutronUpdateNetwork
, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
29 resource_class_kwargs
={'api': self
})
30 self
.api
.add_resource(NeutronDeleteNetwork
, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
31 resource_class_kwargs
={'api': self
})
32 self
.api
.add_resource(NeutronListSubnets
, "/v2.0/subnets.json", "/v2.0/subnets",
33 resource_class_kwargs
={'api': self
})
34 self
.api
.add_resource(NeutronShowSubnet
, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
35 resource_class_kwargs
={'api': self
})
36 self
.api
.add_resource(NeutronCreateSubnet
, "/v2.0/subnets.json", "/v2.0/subnets",
37 resource_class_kwargs
={'api': self
})
38 self
.api
.add_resource(NeutronUpdateSubnet
, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
39 resource_class_kwargs
={'api': self
})
40 self
.api
.add_resource(NeutronDeleteSubnet
, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
41 resource_class_kwargs
={'api': self
})
42 self
.api
.add_resource(NeutronListPorts
, "/v2.0/ports.json", "/v2.0/ports",
43 resource_class_kwargs
={'api': self
})
44 self
.api
.add_resource(NeutronShowPort
, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
45 resource_class_kwargs
={'api': self
})
46 self
.api
.add_resource(NeutronCreatePort
, "/v2.0/ports.json", "/v2.0/ports",
47 resource_class_kwargs
={'api': self
})
48 self
.api
.add_resource(NeutronUpdatePort
, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
49 resource_class_kwargs
={'api': self
})
50 self
.api
.add_resource(NeutronDeletePort
, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
51 resource_class_kwargs
={'api': self
})
52 self
.api
.add_resource(NeutronAddFloatingIp
, "/v2.0/floatingips.json", "/v2.0/floatingips",
53 resource_class_kwargs
={'api': self
})
55 def _start_flask(self
):
56 LOG
.info("Starting %s endpoint @ http://%s:%d" % (__name__
, self
.ip
, self
.port
))
57 if self
.app
is not None:
58 self
.app
.before_request(self
.dump_playbook
)
59 self
.app
.run(self
.ip
, self
.port
, debug
=True, use_reloader
=False)
62 class Shutdown(Resource
):
64 LOG
.debug(("%s is beeing shut down") % (__name__
))
65 func
= request
.environ
.get('werkzeug.server.shutdown')
67 raise RuntimeError('Not running with the Werkzeug Server')
71 class NeutronListAPIVersions(Resource
):
76 :return: Returns a json with API versions.
77 :rtype: :class:`flask.response`
79 LOG
.debug("API CALL: Neutron - List API Versions")
81 resp
['versions'] = dict()
88 "href": request
.url_root
+ '/v2.0',
93 resp
['versions'] = versions
95 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
98 class NeutronShowAPIv2Details(Resource
):
103 :return: Returns a json with API details.
104 :rtype: :class:`flask.response`
106 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
109 resp
['resources'] = dict()
110 resp
['resources'] = [{
113 "href": request
.url_root
+ 'v2.0/subnets',
118 "collection": "subnets"
123 "href": request
.url_root
+ 'v2.0/networks',
128 "collection": "networks"
133 "href": request
.url_root
+ 'v2.0/ports',
138 "collection": "ports"
142 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
145 class NeutronListNetworks(Resource
):
146 def __init__(self
, api
):
151 Lists all networks, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
152 network with the name, or the networks specified via id.
154 :return: Returns a json response, starting with 'networks' as root node.
155 :rtype: :class:`flask.response`
157 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
159 if request
.args
.get('name'):
160 tmp_network
= NeutronShowNetwork(self
.api
)
161 return tmp_network
.get_network(request
.args
.get('name'), True)
162 id_list
= request
.args
.getlist('id')
163 if len(id_list
) == 1:
164 tmp_network
= NeutronShowNetwork(self
.api
)
165 return tmp_network
.get_network(request
.args
.get('id'), True)
167 network_list
= list()
168 network_dict
= dict()
170 if len(id_list
) == 0:
171 for net
in self
.api
.compute
.nets
.values():
172 tmp_network_dict
= net
.create_network_dict()
173 if tmp_network_dict
not in network_list
:
174 network_list
.append(tmp_network_dict
)
176 for net
in self
.api
.compute
.nets
.values():
177 if net
.id in id_list
:
178 tmp_network_dict
= net
.create_network_dict()
179 if tmp_network_dict
not in network_list
:
180 network_list
.append(tmp_network_dict
)
182 network_dict
["networks"] = network_list
184 return Response(json
.dumps(network_dict
), status
=200, mimetype
='application/json')
186 except Exception as ex
:
187 LOG
.exception("Neutron: List networks exception.")
188 return Response(ex
.message
, status
=500, mimetype
='application/json')
191 class NeutronShowNetwork(Resource
):
192 def __init__(self
, api
):
195 def get(self
, network_id
):
197 Returns the network, specified via 'network_id'.
199 :param network_id: The unique ID string of the network.
200 :type network_id: ``str``
201 :return: Returns a json response, starting with 'network' as root node and one network description.
202 :rtype: :class:`flask.response`
204 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
205 return self
.get_network(network_id
, False)
207 def get_network(self
, network_name_or_id
, as_list
):
209 Returns one network description of the network, specified via 'network_name_or_id'.
211 :param network_name_or_id: The indicator string, which specifies the requested network.
212 :type network_name_or_id: ``str``
213 :param as_list: Determines if the network description should start with the root node 'network' or 'networks'.
214 :type as_list: ``bool``
215 :return: Returns a json response, with one network description.
216 :rtype: :class:`flask.response`
219 net
= self
.api
.compute
.find_network_by_name_or_id(network_name_or_id
)
221 return Response(u
'Network not found.\n', status
=404, mimetype
='application/json')
223 tmp_network_dict
= net
.create_network_dict()
226 tmp_dict
["networks"] = [tmp_network_dict
]
228 tmp_dict
["network"] = tmp_network_dict
230 return Response(json
.dumps(tmp_dict
), status
=200, mimetype
='application/json')
233 except Exception as ex
:
234 logging
.exception("Neutron: Show network exception.")
235 return Response(ex
.message
, status
=500, mimetype
='application/json')
238 class NeutronCreateNetwork(Resource
):
239 def __init__(self
, api
):
244 Creates a network with the name, specified within the request under ['network']['name'].
246 :return: * 400, if the network already exists.
247 * 500, if any exception occurred while creation.
248 * 201, if everything worked out.
249 :rtype: :class:`flask.response`
251 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
253 network_dict
= json
.loads(request
.data
)
254 name
= network_dict
['network']['name']
255 net
= self
.api
.compute
.find_network_by_name_or_id(name
)
257 return Response('Network already exists.\n', status
=400, mimetype
='application/json')
259 net
= self
.api
.compute
.create_network(name
)
260 return Response(json
.dumps({"network": net
.create_network_dict()}), status
=201, mimetype
='application/json')
261 except Exception as ex
:
262 LOG
.exception("Neutron: Create network excepiton.")
263 return Response(ex
.message
, status
=500, mimetype
='application/json')
266 class NeutronUpdateNetwork(Resource
):
267 def __init__(self
, api
):
270 def put(self
, network_id
): # TODO currently only the name will be changed
272 Updates the existing network with the given parameters.
274 :param network_id: The indicator string, which specifies the requested network.
275 :type network_id: ``str``
276 :return: * 404, if the network could not be found.
277 * 500, if any exception occurred while updating the network.
278 * 200, if everything worked out.
279 :rtype: :class:`flask.response`
281 LOG
.debug("API CALL: %s PUT" % str(self
.__class
__.__name
__))
283 if network_id
in self
.api
.compute
.nets
:
284 net
= self
.api
.compute
.nets
[network_id
]
285 network_dict
= json
.loads(request
.data
)
286 old_net
= copy
.copy(net
)
288 if "status" in network_dict
["network"]:
289 net
.status
= network_dict
["network"]["status"]
290 if "subnets" in network_dict
["network"]:
291 pass # tmp_network_dict["subnets"] = None
292 if "name" in network_dict
["network"] and net
.name
!= network_dict
["network"]["name"]:
293 net
.name
= network_dict
["network"]["name"]
294 if "admin_state_up" in network_dict
["network"]:
295 pass # tmp_network_dict["admin_state_up"] = True
296 if "tenant_id" in network_dict
["network"]:
297 pass # tmp_network_dict["tenant_id"] = "c1210485b2424d48804aad5d39c61b8f"
298 if "shared" in network_dict
["network"]:
299 pass # tmp_network_dict["shared"] = False
301 return Response(json
.dumps(network_dict
), status
=200, mimetype
='application/json')
303 return Response('Network not found.\n', status
=404, mimetype
='application/json')
305 except Exception as ex
:
306 LOG
.exception("Neutron: Show networks exception.")
307 return Response(ex
.message
, status
=500, mimetype
='application/json')
310 class NeutronDeleteNetwork(Resource
):
311 def __init__(self
, api
):
314 def delete(self
, network_id
):
316 Deletes the specified network and all its subnets.
318 :param network_id: The indicator string, which specifies the requested network.
319 :type network_id: ``str``
320 :return: * 404, if the network or the subnet could not be removed.
321 * 500, if any exception occurred while deletion.
322 * 204, if everything worked out.
323 :rtype: :class:`flask.response`
325 LOG
.debug("API CALL: %s DELETE" % str(self
.__class
__.__name
__))
327 if network_id
not in self
.api
.compute
.nets
:
328 return Response('Could not find network. (' + network_id
+ ')\n',
329 status
=404, mimetype
='application/json')
331 net
= self
.api
.compute
.nets
[network_id
]
332 delete_subnet
= NeutronDeleteSubnet(self
.api
)
333 resp
= delete_subnet
.delete(net
.subnet_id
)
335 if not '204' in resp
.status
and not '404' in resp
.status
:
338 self
.api
.compute
.delete_network(network_id
)
340 return Response('Network ' + str(network_id
) + ' deleted.\n', status
=204, mimetype
='application/json')
341 except Exception as ex
:
342 LOG
.exception("Neutron: Delete network exception.")
343 return Response(ex
.message
, status
=500, mimetype
='application/json')
346 class NeutronListSubnets(Resource
):
347 def __init__(self
, api
):
352 Lists all subnets, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
353 subnet with the name, or the subnets specified via id.
355 :return: Returns a json response, starting with 'subnets' as root node.
356 :rtype: :class:`flask.response`
358 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
360 if request
.args
.get('name'):
361 show_subnet
= NeutronShowSubnet(self
.api
)
362 return show_subnet
.get_subnet(request
.args
.get('name'), True)
363 id_list
= request
.args
.getlist('id')
364 if len(id_list
) == 1:
365 show_subnet
= NeutronShowSubnet(self
.api
)
366 return show_subnet
.get_subnet(id_list
[0], True)
371 if len(id_list
) == 0:
372 for net
in self
.api
.compute
.nets
.values():
373 if net
.subnet_id
is not None:
374 tmp_subnet_dict
= net
.create_subnet_dict()
375 subnet_list
.append(tmp_subnet_dict
)
377 for net
in self
.api
.compute
.nets
.values():
378 if net
.subnet_id
in id_list
:
379 tmp_subnet_dict
= net
.create_subnet_dict()
380 subnet_list
.append(tmp_subnet_dict
)
382 subnet_dict
["subnets"] = subnet_list
384 return Response(json
.dumps(subnet_dict
), status
=200, mimetype
='application/json')
386 except Exception as ex
:
387 LOG
.exception("Neutron: List subnets exception.")
388 return Response(ex
.message
, status
=500, mimetype
='application/json')
391 class NeutronShowSubnet(Resource
):
392 def __init__(self
, api
):
395 def get(self
, subnet_id
):
397 Returns the subnet, specified via 'subnet_id'.
399 :param subnet_id: The unique ID string of the subnet.
400 :type subnet_id: ``str``
401 :return: Returns a json response, starting with 'subnet' as root node and one subnet description.
402 :rtype: :class:`flask.response`
404 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
405 return self
.get_subnet(subnet_id
, False)
407 def get_subnet(self
, subnet_name_or_id
, as_list
):
409 Returns one subnet description of the subnet, specified via 'subnet_name_or_id'.
411 :param subnet_name_or_id: The indicator string, which specifies the requested subnet.
412 :type subnet_name_or_id: ``str``
413 :param as_list: Determines if the subnet description should start with the root node 'subnet' or 'subnets'.
414 :type as_list: ``bool``
415 :return: Returns a json response, with one subnet description.
416 :rtype: :class:`flask.response`
419 for net
in self
.api
.compute
.nets
.values():
420 if net
.subnet_id
== subnet_name_or_id
or net
.subnet_name
== subnet_name_or_id
:
421 tmp_subnet_dict
= net
.create_subnet_dict()
424 tmp_dict
["subnets"] = [tmp_subnet_dict
]
426 tmp_dict
["subnet"] = tmp_subnet_dict
427 return Response(json
.dumps(tmp_dict
), status
=200, mimetype
='application/json')
429 return Response('Subnet not found. (' + subnet_name_or_id
+ ')\n', status
=404, mimetype
='application/json')
431 except Exception as ex
:
432 LOG
.exception("Neutron: Show subnet exception.")
433 return Response(ex
.message
, status
=500, mimetype
='application/json')
436 class NeutronCreateSubnet(Resource
):
437 def __init__(self
, api
):
442 Creates a subnet with the name, specified within the request under ['subnet']['name'].
444 :return: * 400, if the 'CIDR' format is wrong or it does not exist.
445 * 404, if the network was not found.
446 * 409, if the corresponding network already has one subnet.
447 * 500, if any exception occurred while creation and
448 * 201, if everything worked out.
449 :rtype: :class:`flask.response`
451 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
453 subnet_dict
= json
.loads(request
.data
)
454 net
= self
.api
.compute
.find_network_by_name_or_id(subnet_dict
['subnet']['network_id'])
457 return Response('Could not find network.\n', status
=404, mimetype
='application/json')
459 net
.subnet_name
= subnet_dict
["subnet"].get('name', str(net
.name
) + '-sub')
460 if net
.subnet_id
is not None:
461 return Response('Only one subnet per network is supported\n', status
=409, mimetype
='application/json')
463 if "id" in subnet_dict
["subnet"]:
464 net
.subnet_id
= subnet_dict
["subnet"]["id"]
466 net
.subnet_id
= str(uuid
.uuid4())
467 import emuvim
.api
.openstack
.ip_handler
as IP
468 net
.set_cidr(IP
.get_new_cidr(net
.subnet_id
))
470 if "tenant_id" in subnet_dict
["subnet"]:
472 if "allocation_pools" in subnet_dict
["subnet"]:
474 if "gateway_ip" in subnet_dict
["subnet"]:
475 net
.gateway_ip
= subnet_dict
["subnet"]["gateway_ip"]
476 if "ip_version" in subnet_dict
["subnet"]:
478 if "enable_dhcp" in subnet_dict
["subnet"]:
481 return Response(json
.dumps({'subnet': net
.create_subnet_dict()}), status
=201, mimetype
='application/json')
483 except Exception as ex
:
484 LOG
.exception("Neutron: Create network excepiton.")
485 return Response(ex
.message
, status
=500, mimetype
='application/json')
488 class NeutronUpdateSubnet(Resource
):
489 def __init__(self
, api
):
492 def put(self
, subnet_id
):
494 Updates the existing subnet with the given parameters.
496 :param subnet_id: The indicator string, which specifies the requested subnet.
497 :type subnet_id: ``str``
498 :return: * 404, if the network could not be found.
499 * 500, if any exception occurred while updating the network.
500 * 200, if everything worked out.
501 :rtype: :class:`flask.response`
503 LOG
.debug("API CALL: %s PUT" % str(self
.__class
__.__name
__))
505 for net
in self
.api
.compute
.nets
.values():
506 if net
.subnet_id
== subnet_id
:
507 subnet_dict
= json
.loads(request
.data
)
509 if "name" in subnet_dict
["subnet"]:
510 net
.subnet_name
= subnet_dict
["subnet"]["name"]
511 if "network_id" in subnet_dict
["subnet"]:
512 net
.id = subnet_dict
["subnet"]["network_id"]
513 if "tenant_id" in subnet_dict
["subnet"]:
515 if "allocation_pools" in subnet_dict
["subnet"]:
517 if "gateway_ip" in subnet_dict
["subnet"]:
518 net
.gateway_ip
= subnet_dict
["subnet"]["gateway_ip"]
519 if "ip_version" in subnet_dict
["subnet"]:
521 if "cidr" in subnet_dict
["subnet"]:
522 net
.set_cidr(subnet_dict
["subnet"]["cidr"])
523 if "id" in subnet_dict
["subnet"]:
524 net
.subnet_id
= subnet_dict
["subnet"]["id"]
525 if "enable_dhcp" in subnet_dict
["subnet"]:
528 net
.subnet_update_time
= str(datetime
.now())
529 tmp_dict
= {'subnet': net
.create_subnet_dict()}
530 return Response(json
.dumps(tmp_dict
), status
=200, mimetype
='application/json')
532 return Response('Network not found.\n', status
=404, mimetype
='application/json')
534 except Exception as ex
:
535 LOG
.exception("Neutron: Show networks exception.")
536 return Response(ex
.message
, status
=500, mimetype
='application/json')
539 class NeutronDeleteSubnet(Resource
):
540 def __init__(self
, api
):
543 def delete(self
, subnet_id
):
545 Deletes the specified subnet.
547 :param subnet_id: The indicator string, which specifies the requested subnet.
548 :type subnet_id: ``str``
549 :return: * 404, if the subnet could not be removed.
550 * 500, if any exception occurred while deletion.
551 * 204, if everything worked out.
552 :rtype: :class:`flask.response`
554 LOG
.debug("API CALL: %s DELETE" % str(self
.__class
__.__name
__))
556 for net
in self
.api
.compute
.nets
.values():
557 if net
.subnet_id
== subnet_id
:
558 for server
in self
.api
.compute
.computeUnits
.values():
559 for port_name
in server
.port_names
:
560 port
= self
.api
.compute
.find_port_by_name_or_id(port_name
)
561 if port
.net_name
== net
.name
:
562 port
.ip_address
= None
563 self
.api
.compute
.dc
.net
.removeLink(
565 node1
=self
.api
.compute
.dc
.containers
[server
.name
],
566 node2
=self
.api
.compute
.dc
.switch
)
571 return Response('Subnet ' + str(subnet_id
) + ' deleted.\n',
572 status
=204, mimetype
='application/json')
574 return Response('Could not find subnet.', status
=404, mimetype
='application/json')
575 except Exception as ex
:
576 LOG
.exception("Neutron: Delete subnet exception.")
577 return Response(ex
.message
, status
=500, mimetype
='application/json')
580 class NeutronListPorts(Resource
):
581 def __init__(self
, api
):
586 Lists all ports, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
587 port with the name, or the ports specified via id.
589 :return: Returns a json response, starting with 'ports' as root node.
590 :rtype: :class:`flask.response`
592 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
594 if request
.args
.get('name'):
595 show_port
= NeutronShowPort(self
.api
)
596 return show_port
.get_port(request
.args
.get('name'), True)
597 id_list
= request
.args
.getlist('id')
598 if len(id_list
) == 1:
599 show_port
= NeutronShowPort(self
.api
)
600 return show_port
.get_port(request
.args
.get('id'), True)
605 if len(id_list
) == 0:
606 for port
in self
.api
.compute
.ports
.values():
607 tmp_port_dict
= port
.create_port_dict(self
.api
.compute
)
608 port_list
.append(tmp_port_dict
)
610 for port
in self
.api
.compute
.ports
.values():
611 if port
.id in id_list
:
612 tmp_port_dict
= port
.create_port_dict(self
.api
.compute
)
613 port_list
.append(tmp_port_dict
)
615 port_dict
["ports"] = port_list
617 return Response(json
.dumps(port_dict
), status
=200, mimetype
='application/json')
619 except Exception as ex
:
620 LOG
.exception("Neutron: List ports exception.")
621 return Response(ex
.message
, status
=500, mimetype
='application/json')
624 class NeutronShowPort(Resource
):
625 def __init__(self
, api
):
628 def get(self
, port_id
):
630 Returns the port, specified via 'port_id'.
632 :param port_id: The unique ID string of the network.
633 :type port_id: ``str``
634 :return: Returns a json response, starting with 'port' as root node and one network description.
635 :rtype: :class:`flask.response`
637 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
638 return self
.get_port(port_id
, False)
640 def get_port(self
, port_name_or_id
, as_list
):
642 Returns one network description of the port, specified via 'port_name_or_id'.
644 :param port_name_or_id: The indicator string, which specifies the requested port.
645 :type port_name_or_id: ``str``
646 :param as_list: Determines if the port description should start with the root node 'port' or 'ports'.
647 :type as_list: ``bool``
648 :return: Returns a json response, with one port description.
649 :rtype: :class:`flask.response`
652 port
= self
.api
.compute
.find_port_by_name_or_id(port_name_or_id
)
654 return Response('Port not found. (' + port_name_or_id
+ ')\n', status
=404, mimetype
='application/json')
655 tmp_port_dict
= port
.create_port_dict(self
.api
.compute
)
658 tmp_dict
["ports"] = [tmp_port_dict
]
660 tmp_dict
["port"] = tmp_port_dict
661 return Response(json
.dumps(tmp_dict
), status
=200, mimetype
='application/json')
662 except Exception as ex
:
663 LOG
.exception("Neutron: Show port exception.")
664 return Response(ex
.message
, status
=500, mimetype
='application/json')
667 class NeutronCreatePort(Resource
):
668 def __init__(self
, api
):
673 Creates a port with the name, specified within the request under ['port']['name'].
675 :return: * 404, if the network could not be found.
676 * 500, if any exception occurred while creation and
677 * 201, if everything worked out.
678 :rtype: :class:`flask.response`
680 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
682 port_dict
= json
.loads(request
.data
)
683 net_id
= port_dict
['port']['network_id']
685 if net_id
not in self
.api
.compute
.nets
:
686 return Response('Could not find network.\n', status
=404, mimetype
='application/json')
688 net
= self
.api
.compute
.nets
[net_id
]
689 if 'name' in port_dict
['port']:
690 name
= port_dict
['port']['name']
692 num_ports
= len(self
.api
.compute
.ports
)
693 name
= "port:cp%s:man:%s" % (num_ports
, str(uuid
.uuid4()))
695 if self
.api
.compute
.find_port_by_name_or_id(name
):
696 return Response("Port with name %s already exists.\n" % name
, status
=500, mimetype
='application/json')
698 port
= self
.api
.compute
.create_port(name
)
700 port
.net_name
= net
.name
701 port
.ip_address
= net
.get_new_ip_address(name
)
703 if "admin_state_up" in port_dict
["port"]:
705 if "device_id" in port_dict
["port"]:
707 if "device_owner" in port_dict
["port"]:
709 if "fixed_ips" in port_dict
["port"]:
711 if "mac_address" in port_dict
["port"]:
712 port
.mac_address
= port_dict
["port"]["mac_address"]
713 if "status" in port_dict
["port"]:
715 if "tenant_id" in port_dict
["port"]:
718 # add the port to a stack if the specified network is a stack network
719 for stack
in self
.api
.compute
.stacks
.values():
720 for net
in stack
.nets
.values():
722 stack
.ports
[name
] = port
724 return Response(json
.dumps({'port': port
.create_port_dict(self
.api
.compute
)}), status
=201,
725 mimetype
='application/json')
726 except Exception as ex
:
727 LOG
.exception("Neutron: Show port exception.")
728 return Response(ex
.message
, status
=500, mimetype
='application/json')
731 class NeutronUpdatePort(Resource
):
732 def __init__(self
, api
):
735 def put(self
, port_id
):
737 Updates the existing port with the given parameters.
739 :param network_id: The indicator string, which specifies the requested port.
740 :type network_id: ``str``
741 :return: * 404, if the network could not be found.
742 * 500, if any exception occurred while updating the network.
743 * 200, if everything worked out.
744 :rtype: :class:`flask.response`
746 LOG
.debug("API CALL: %s PUT" % str(self
.__class
__.__name
__))
748 port_dict
= json
.loads(request
.data
)
749 port
= self
.api
.compute
.find_port_by_name_or_id(port_id
)
751 return Response("Port with id %s does not exists.\n" % port_id
, status
=404, mimetype
='application/json')
752 old_port
= copy
.copy(port
)
755 for s
in self
.api
.compute
.stacks
.values():
756 for port
in s
.ports
.values():
757 if port
.id == port_id
:
759 if "admin_state_up" in port_dict
["port"]:
761 if "device_id" in port_dict
["port"]:
763 if "device_owner" in port_dict
["port"]:
765 if "fixed_ips" in port_dict
["port"]:
767 if "id" in port_dict
["port"]:
768 port
.id = port_dict
["port"]["id"]
769 if "mac_address" in port_dict
["port"]:
770 port
.mac_address
= port_dict
["port"]["mac_address"]
771 if "name" in port_dict
["port"] and port_dict
["port"]["name"] != port
.name
:
772 port
.set_name(port_dict
["port"]["name"])
773 if stack
is not None:
774 if port
.net_name
in stack
.nets
:
775 stack
.nets
[port
.net_name
].update_port_name_for_ip_address(port
.ip_address
, port
.name
)
776 stack
.ports
[port
.name
] = stack
.ports
[old_port
.name
]
777 del stack
.ports
[old_port
.name
]
778 if "network_id" in port_dict
["port"]:
780 if "status" in port_dict
["port"]:
782 if "tenant_id" in port_dict
["port"]:
785 return Response(json
.dumps({'port': port
.create_port_dict(self
.api
.compute
)}), status
=200,
786 mimetype
='application/json')
787 except Exception as ex
:
788 LOG
.exception("Neutron: Update port exception.")
789 return Response(ex
.message
, status
=500, mimetype
='application/json')
792 class NeutronDeletePort(Resource
):
793 def __init__(self
, api
):
796 def delete(self
, port_id
):
798 Deletes the specified port.
800 :param port_id: The indicator string, which specifies the requested port.
801 :type port_id: ``str``
802 :return: * 404, if the port could not be found.
803 * 500, if any exception occurred while deletion.
804 * 204, if everything worked out.
805 :rtype: :class:`flask.response`
807 LOG
.debug("API CALL: %s DELETE" % str(self
.__class
__.__name
__))
809 port
= self
.api
.compute
.find_port_by_name_or_id(port_id
)
811 return Response("Port with id %s does not exists.\n" % port_id
, status
=404)
813 for s
in self
.api
.compute
.stacks
.values():
814 for p
in s
.ports
.values():
817 if stack
is not None:
818 if port
.net_name
in stack
.nets
:
819 stack
.nets
[port
.net_name
].withdraw_ip_address(port
.ip_address
)
820 for server
in stack
.servers
.values():
822 server
.port_names
.remove(port
.name
)
827 self
.api
.compute
.delete_port(port
.id)
829 return Response('Port ' + port_id
+ ' deleted.\n', status
=204, mimetype
='application/json')
831 except Exception as ex
:
832 LOG
.exception("Neutron: Delete port exception.")
833 return Response(ex
.message
, status
=500, mimetype
='application/json')
836 class NeutronAddFloatingIp(Resource
):
837 def __init__(self
, api
):
842 Added a quick and dirty fake for the OSM integration. Returns a list of
843 floating IPs. Has nothing to do with the setup inside the emulator.
844 But its enough to make the OSM driver happy.
845 @PG Sandman: Feel free to improve this and let it do something meaningful.
848 resp
["floatingips"] = list()
849 # create a list of floting IP definitions and return it
850 for i
in range(100, 110):
852 ip
["router_id"] = "router_id"
853 ip
["description"] = "hardcoded in api"
854 ip
["created_at"] = "router_id"
855 ip
["updated_at"] = "router_id"
856 ip
["revision_number"] = 1
857 ip
["tenant_id"] = "tenant_id"
858 ip
["project_id"] = "project_id"
859 ip
["floating_network_id"] = str(i
)
860 ip
["status"] = "ACTIVE"
862 ip
["port_id"] = "port_id"
863 ip
["floating_ip_address"] = "172.0.0.%d" % i
864 ip
["fixed_ip_address"] = "10.0.0.%d" % i
865 resp
["floatingips"].append(ip
)
866 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
871 Adds a floating IP to neutron.
873 :return: Returns a floating network description.
874 :rtype: :class:`flask.response`
876 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
878 # Fiddle with floating_network !
879 req
= json
.loads(request
.data
)
881 network_id
= req
["floatingip"]["floating_network_id"]
882 net
= self
.api
.compute
.find_network_by_name_or_id(network_id
)
883 if net
!= self
.api
.manage
.floating_network
:
884 return Response("You have to specify the existing floating network\n",
885 status
=400, mimetype
='application/json')
887 port_id
= req
["floatingip"].get("port_id", None)
888 port
= self
.api
.compute
.find_port_by_name_or_id(port_id
)
890 if port
.net_name
!= self
.api
.manage
.floating_network
.name
:
891 return Response("You have to specify a port in the floating network\n",
892 status
=400, mimetype
='application/json')
894 if port
.floating_ip
is not None:
895 return Response("We allow only one floating ip per port\n", status
=400, mimetype
='application/json')
897 num_ports
= len(self
.api
.compute
.ports
)
898 name
= "port:cp%s:fl:%s" % (num_ports
, str(uuid
.uuid4()))
899 port
= self
.api
.compute
.create_port(name
)
900 port
.net_name
= net
.name
901 port
.ip_address
= net
.get_new_ip_address(name
)
903 port
.floating_ip
= port
.ip_address
906 resp
= response
["floatingip"] = dict()
908 resp
["floating_network_id"] = net
.id
909 resp
["status"] = "ACTIVE"
911 resp
["port_id"] = port
.id
912 resp
["floating_ip_address"] = port
.floating_ip
913 resp
["fixed_ip_address"] = port
.floating_ip
915 return Response(json
.dumps(response
), status
=200, mimetype
='application/json')
916 except Exception as ex
:
917 LOG
.exception("Neutron: Create FloatingIP exception %s.", ex
)
918 return Response(ex
.message
, status
=500, mimetype
='application/json')