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 class NeutronDummyApi(BaseOpenstackDummy
):
12 def __init__(self
, ip
, port
, compute
):
13 super(NeutronDummyApi
, self
).__init
__(ip
, port
)
14 self
.compute
= compute
16 self
.api
.add_resource(NeutronListAPIVersions
, "/")
17 self
.api
.add_resource(Shutdown
, "/shutdown")
18 self
.api
.add_resource(NeutronShowAPIv2Details
, "/v2.0")
19 self
.api
.add_resource(NeutronListNetworks
, "/v2.0/networks.json", "/v2.0/networks",
20 resource_class_kwargs
={'api': self
})
21 self
.api
.add_resource(NeutronShowNetwork
, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
22 resource_class_kwargs
={'api': self
})
23 self
.api
.add_resource(NeutronCreateNetwork
, "/v2.0/networks.json", "/v2.0/networks",
24 resource_class_kwargs
={'api': self
})
25 self
.api
.add_resource(NeutronUpdateNetwork
, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
26 resource_class_kwargs
={'api': self
})
27 self
.api
.add_resource(NeutronDeleteNetwork
, "/v2.0/networks/<network_id>.json", "/v2.0/networks/<network_id>",
28 resource_class_kwargs
={'api': self
})
29 self
.api
.add_resource(NeutronListSubnets
, "/v2.0/subnets.json", "/v2.0/subnets",
30 resource_class_kwargs
={'api': self
})
31 self
.api
.add_resource(NeutronShowSubnet
, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
32 resource_class_kwargs
={'api': self
})
33 self
.api
.add_resource(NeutronCreateSubnet
, "/v2.0/subnets.json", "/v2.0/subnets",
34 resource_class_kwargs
={'api': self
})
35 self
.api
.add_resource(NeutronUpdateSubnet
, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
36 resource_class_kwargs
={'api': self
})
37 self
.api
.add_resource(NeutronDeleteSubnet
, "/v2.0/subnets/<subnet_id>.json", "/v2.0/subnets/<subnet_id>",
38 resource_class_kwargs
={'api': self
})
39 self
.api
.add_resource(NeutronListPorts
, "/v2.0/ports.json", "/v2.0/ports",
40 resource_class_kwargs
={'api': self
})
41 self
.api
.add_resource(NeutronShowPort
, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
42 resource_class_kwargs
={'api': self
})
43 self
.api
.add_resource(NeutronCreatePort
, "/v2.0/ports.json", "/v2.0/ports",
44 resource_class_kwargs
={'api': self
})
45 self
.api
.add_resource(NeutronUpdatePort
, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
46 resource_class_kwargs
={'api': self
})
47 self
.api
.add_resource(NeutronDeletePort
, "/v2.0/ports/<port_id>.json", "/v2.0/ports/<port_id>",
48 resource_class_kwargs
={'api': self
})
49 self
.api
.add_resource(NeutronAddFloatingIp
, "/v2.0/floatingips.json", "/v2.0/floatingips",
50 resource_class_kwargs
={'api': self
})
52 def _start_flask(self
):
53 logging
.info("Starting %s endpoint @ http://%s:%d" % (__name__
, self
.ip
, self
.port
))
54 if self
.app
is not None:
55 self
.app
.before_request(self
.dump_playbook
)
56 self
.app
.run(self
.ip
, self
.port
, debug
=True, use_reloader
=False)
59 class Shutdown(Resource
):
61 logging
.debug(("%s is beeing shut down") % (__name__
))
62 func
= request
.environ
.get('werkzeug.server.shutdown')
64 raise RuntimeError('Not running with the Werkzeug Server')
68 class NeutronListAPIVersions(Resource
):
73 :return: Returns a json with API versions.
74 :rtype: :class:`flask.response`
76 logging
.debug("API CALL: Neutron - List API Versions")
78 resp
['versions'] = dict()
85 "href": request
.url_root
+ '/v2.0',
90 resp
['versions'] = versions
92 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
95 class NeutronShowAPIv2Details(Resource
):
100 :return: Returns a json with API details.
101 :rtype: :class:`flask.response`
103 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
106 resp
['resources'] = dict()
107 resp
['resources'] = [{
110 "href": request
.url_root
+ 'v2.0/subnets',
115 "collection": "subnets"
120 "href": request
.url_root
+ 'v2.0/networks',
125 "collection": "networks"
130 "href": request
.url_root
+ 'v2.0/ports',
135 "collection": "ports"
139 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
142 class NeutronListNetworks(Resource
):
143 def __init__(self
, api
):
148 Lists all networks, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
149 network with the name, or the networks specified via id.
151 :return: Returns a json response, starting with 'networks' as root node.
152 :rtype: :class:`flask.response`
154 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
156 if request
.args
.get('name'):
157 tmp_network
= NeutronShowNetwork(self
.api
)
158 return tmp_network
.get_network(request
.args
.get('name'), True)
159 id_list
= request
.args
.getlist('id')
160 if len(id_list
) == 1:
161 tmp_network
= NeutronShowNetwork(self
.api
)
162 return tmp_network
.get_network(request
.args
.get('id'), True)
164 network_list
= list()
165 network_dict
= dict()
167 if len(id_list
) == 0:
168 for net
in self
.api
.compute
.nets
.values():
169 tmp_network_dict
= net
.create_network_dict()
170 if tmp_network_dict
not in network_list
:
171 network_list
.append(tmp_network_dict
)
173 for net
in self
.api
.compute
.nets
.values():
174 if net
.id in id_list
:
175 tmp_network_dict
= net
.create_network_dict()
176 if tmp_network_dict
not in network_list
:
177 network_list
.append(tmp_network_dict
)
179 network_dict
["networks"] = network_list
181 return Response(json
.dumps(network_dict
), status
=200, mimetype
='application/json')
183 except Exception as ex
:
184 logging
.exception("Neutron: List networks exception.")
185 return Response(ex
.message
, status
=500, mimetype
='application/json')
188 class NeutronShowNetwork(Resource
):
189 def __init__(self
, api
):
192 def get(self
, network_id
):
194 Returns the network, specified via 'network_id'.
196 :param network_id: The unique ID string of the network.
197 :type network_id: ``str``
198 :return: Returns a json response, starting with 'network' as root node and one network description.
199 :rtype: :class:`flask.response`
201 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
202 return self
.get_network(network_id
, False)
204 def get_network(self
, network_name_or_id
, as_list
):
206 Returns one network description of the network, specified via 'network_name_or_id'.
208 :param network_name_or_id: The indicator string, which specifies the requested network.
209 :type network_name_or_id: ``str``
210 :param as_list: Determines if the network description should start with the root node 'network' or 'networks'.
211 :type as_list: ``bool``
212 :return: Returns a json response, with one network description.
213 :rtype: :class:`flask.response`
216 net
= self
.api
.compute
.find_network_by_name_or_id(network_name_or_id
)
218 return Response(u
'Network not found.\n', status
=404, mimetype
='application/json')
220 tmp_network_dict
= net
.create_network_dict()
223 tmp_dict
["networks"] = [tmp_network_dict
]
225 tmp_dict
["network"] = tmp_network_dict
227 return Response(json
.dumps(tmp_dict
), status
=200, mimetype
='application/json')
230 except Exception as ex
:
231 logging
.exception("Neutron: Show network exception.")
232 return Response(ex
.message
, status
=500, mimetype
='application/json')
235 class NeutronCreateNetwork(Resource
):
236 def __init__(self
, api
):
241 Creates a network with the name, specified within the request under ['network']['name'].
243 :return: * 400, if the network already exists.
244 * 500, if any exception occurred while creation.
245 * 201, if everything worked out.
246 :rtype: :class:`flask.response`
248 logging
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
250 network_dict
= json
.loads(request
.data
)
251 name
= network_dict
['network']['name']
252 net
= self
.api
.compute
.find_network_by_name_or_id(name
)
254 return Response('Network already exists.\n', status
=400, mimetype
='application/json')
256 net
= self
.api
.compute
.create_network(name
)
257 return Response(json
.dumps({"network": net
.create_network_dict()}), status
=201, mimetype
='application/json')
258 except Exception as ex
:
259 logging
.exception("Neutron: Create network excepiton.")
260 return Response(ex
.message
, status
=500, mimetype
='application/json')
263 class NeutronUpdateNetwork(Resource
):
264 def __init__(self
, api
):
267 def put(self
, network_id
): # TODO currently only the name will be changed
269 Updates the existing network with the given parameters.
271 :param network_id: The indicator string, which specifies the requested network.
272 :type network_id: ``str``
273 :return: * 404, if the network could not be found.
274 * 500, if any exception occurred while updating the network.
275 * 200, if everything worked out.
276 :rtype: :class:`flask.response`
278 logging
.debug("API CALL: %s PUT" % str(self
.__class
__.__name
__))
280 if network_id
in self
.api
.compute
.nets
:
281 net
= self
.api
.compute
.nets
[network_id
]
282 network_dict
= json
.loads(request
.data
)
283 old_net
= copy
.copy(net
)
285 if "status" in network_dict
["network"]:
286 net
.status
= network_dict
["network"]["status"]
287 if "subnets" in network_dict
["network"]:
288 pass # tmp_network_dict["subnets"] = None
289 if "name" in network_dict
["network"] and net
.name
!= network_dict
["network"]["name"]:
290 net
.name
= network_dict
["network"]["name"]
291 if "admin_state_up" in network_dict
["network"]:
292 pass # tmp_network_dict["admin_state_up"] = True
293 if "tenant_id" in network_dict
["network"]:
294 pass # tmp_network_dict["tenant_id"] = "c1210485b2424d48804aad5d39c61b8f"
295 if "shared" in network_dict
["network"]:
296 pass # tmp_network_dict["shared"] = False
298 return Response(json
.dumps(network_dict
), status
=200, mimetype
='application/json')
300 return Response('Network not found.\n', status
=404, mimetype
='application/json')
302 except Exception as ex
:
303 logging
.exception("Neutron: Show networks exception.")
304 return Response(ex
.message
, status
=500, mimetype
='application/json')
307 class NeutronDeleteNetwork(Resource
):
308 def __init__(self
, api
):
311 def delete(self
, network_id
):
313 Deletes the specified network and all its subnets.
315 :param network_id: The indicator string, which specifies the requested network.
316 :type network_id: ``str``
317 :return: * 404, if the network or the subnet could not be removed.
318 * 500, if any exception occurred while deletion.
319 * 204, if everything worked out.
320 :rtype: :class:`flask.response`
322 logging
.debug("API CALL: %s DELETE" % str(self
.__class
__.__name
__))
324 if network_id
not in self
.api
.compute
.nets
:
325 return Response('Could not find network. (' + network_id
+ ')\n',
326 status
=404, mimetype
='application/json')
328 net
= self
.api
.compute
.nets
[network_id
]
329 delete_subnet
= NeutronDeleteSubnet(self
.api
)
330 resp
= delete_subnet
.delete(net
.subnet_id
)
332 if not '204' in resp
.status
and not '404' in resp
.status
:
335 self
.api
.compute
.delete_network(network_id
)
337 return Response('Network ' + str(network_id
) + ' deleted.\n', status
=204, mimetype
='application/json')
338 except Exception as ex
:
339 logging
.exception("Neutron: Delete network exception.")
340 return Response(ex
.message
, status
=500, mimetype
='application/json')
343 class NeutronListSubnets(Resource
):
344 def __init__(self
, api
):
349 Lists all subnets, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
350 subnet with the name, or the subnets specified via id.
352 :return: Returns a json response, starting with 'subnets' as root node.
353 :rtype: :class:`flask.response`
355 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
357 if request
.args
.get('name'):
358 show_subnet
= NeutronShowSubnet(self
.api
)
359 return show_subnet
.get_subnet(request
.args
.get('name'), True)
360 id_list
= request
.args
.getlist('id')
361 if len(id_list
) == 1:
362 show_subnet
= NeutronShowSubnet(self
.api
)
363 return show_subnet
.get_subnet(id_list
[0], True)
368 if len(id_list
) == 0:
369 for net
in self
.api
.compute
.nets
.values():
370 if net
.subnet_id
is not None:
371 tmp_subnet_dict
= net
.create_subnet_dict()
372 subnet_list
.append(tmp_subnet_dict
)
374 for net
in self
.api
.compute
.nets
.values():
375 if net
.subnet_id
in id_list
:
376 tmp_subnet_dict
= net
.create_subnet_dict()
377 subnet_list
.append(tmp_subnet_dict
)
379 subnet_dict
["subnets"] = subnet_list
381 return Response(json
.dumps(subnet_dict
), status
=200, mimetype
='application/json')
383 except Exception as ex
:
384 logging
.exception("Neutron: List subnets exception.")
385 return Response(ex
.message
, status
=500, mimetype
='application/json')
388 class NeutronShowSubnet(Resource
):
389 def __init__(self
, api
):
392 def get(self
, subnet_id
):
394 Returns the subnet, specified via 'subnet_id'.
396 :param subnet_id: The unique ID string of the subnet.
397 :type subnet_id: ``str``
398 :return: Returns a json response, starting with 'subnet' as root node and one subnet description.
399 :rtype: :class:`flask.response`
401 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
402 return self
.get_subnet(subnet_id
, False)
404 def get_subnet(self
, subnet_name_or_id
, as_list
):
406 Returns one subnet description of the subnet, specified via 'subnet_name_or_id'.
408 :param subnet_name_or_id: The indicator string, which specifies the requested subnet.
409 :type subnet_name_or_id: ``str``
410 :param as_list: Determines if the subnet description should start with the root node 'subnet' or 'subnets'.
411 :type as_list: ``bool``
412 :return: Returns a json response, with one subnet description.
413 :rtype: :class:`flask.response`
416 for net
in self
.api
.compute
.nets
.values():
417 if net
.subnet_id
== subnet_name_or_id
or net
.subnet_name
== subnet_name_or_id
:
418 tmp_subnet_dict
= net
.create_subnet_dict()
421 tmp_dict
["subnets"] = [tmp_subnet_dict
]
423 tmp_dict
["subnet"] = tmp_subnet_dict
424 return Response(json
.dumps(tmp_dict
), status
=200, mimetype
='application/json')
426 return Response('Subnet not found. (' + subnet_name_or_id
+ ')\n', status
=404, mimetype
='application/json')
428 except Exception as ex
:
429 logging
.exception("Neutron: Show subnet exception.")
430 return Response(ex
.message
, status
=500, mimetype
='application/json')
433 class NeutronCreateSubnet(Resource
):
434 def __init__(self
, api
):
439 Creates a subnet with the name, specified within the request under ['subnet']['name'].
441 :return: * 400, if the 'CIDR' format is wrong or it does not exist.
442 * 404, if the network was not found.
443 * 409, if the corresponding network already has one subnet.
444 * 500, if any exception occurred while creation and
445 * 201, if everything worked out.
446 :rtype: :class:`flask.response`
448 logging
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
450 subnet_dict
= json
.loads(request
.data
)
451 net
= self
.api
.compute
.find_network_by_name_or_id(subnet_dict
['subnet']['network_id'])
454 return Response('Could not find network.\n', status
=404, mimetype
='application/json')
456 net
.subnet_name
= subnet_dict
["subnet"].get('name', str(net
.name
) + '-sub')
457 if net
.subnet_id
is not None:
458 return Response('Only one subnet per network is supported\n', status
=409, mimetype
='application/json')
460 if "id" in subnet_dict
["subnet"]:
461 net
.subnet_id
= subnet_dict
["subnet"]["id"]
463 net
.subnet_id
= str(uuid
.uuid4())
464 import emuvim
.api
.openstack
.ip_handler
as IP
465 net
.set_cidr(IP
.get_new_cidr(net
.subnet_id
))
467 if "tenant_id" in subnet_dict
["subnet"]:
469 if "allocation_pools" in subnet_dict
["subnet"]:
471 if "gateway_ip" in subnet_dict
["subnet"]:
472 net
.gateway_ip
= subnet_dict
["subnet"]["gateway_ip"]
473 if "ip_version" in subnet_dict
["subnet"]:
475 if "enable_dhcp" in subnet_dict
["subnet"]:
478 return Response(json
.dumps({'subnet': net
.create_subnet_dict()}), status
=201, mimetype
='application/json')
480 except Exception as ex
:
481 logging
.exception("Neutron: Create network excepiton.")
482 return Response(ex
.message
, status
=500, mimetype
='application/json')
485 class NeutronUpdateSubnet(Resource
):
486 def __init__(self
, api
):
489 def put(self
, subnet_id
):
491 Updates the existing subnet with the given parameters.
493 :param subnet_id: The indicator string, which specifies the requested subnet.
494 :type subnet_id: ``str``
495 :return: * 404, if the network could not be found.
496 * 500, if any exception occurred while updating the network.
497 * 200, if everything worked out.
498 :rtype: :class:`flask.response`
500 logging
.debug("API CALL: %s PUT" % str(self
.__class
__.__name
__))
502 for net
in self
.api
.compute
.nets
.values():
503 if net
.subnet_id
== subnet_id
:
504 subnet_dict
= json
.loads(request
.data
)
506 if "name" in subnet_dict
["subnet"]:
507 net
.subnet_name
= subnet_dict
["subnet"]["name"]
508 if "network_id" in subnet_dict
["subnet"]:
509 net
.id = subnet_dict
["subnet"]["network_id"]
510 if "tenant_id" in subnet_dict
["subnet"]:
512 if "allocation_pools" in subnet_dict
["subnet"]:
514 if "gateway_ip" in subnet_dict
["subnet"]:
515 net
.gateway_ip
= subnet_dict
["subnet"]["gateway_ip"]
516 if "ip_version" in subnet_dict
["subnet"]:
518 if "cidr" in subnet_dict
["subnet"]:
519 net
.set_cidr(subnet_dict
["subnet"]["cidr"])
520 if "id" in subnet_dict
["subnet"]:
521 net
.subnet_id
= subnet_dict
["subnet"]["id"]
522 if "enable_dhcp" in subnet_dict
["subnet"]:
525 net
.subnet_update_time
= str(datetime
.now())
526 tmp_dict
= {'subnet': net
.create_subnet_dict()}
527 return Response(json
.dumps(tmp_dict
), status
=200, mimetype
='application/json')
529 return Response('Network not found.\n', status
=404, mimetype
='application/json')
531 except Exception as ex
:
532 logging
.exception("Neutron: Show networks exception.")
533 return Response(ex
.message
, status
=500, mimetype
='application/json')
536 class NeutronDeleteSubnet(Resource
):
537 def __init__(self
, api
):
540 def delete(self
, subnet_id
):
542 Deletes the specified subnet.
544 :param subnet_id: The indicator string, which specifies the requested subnet.
545 :type subnet_id: ``str``
546 :return: * 404, if the subnet could not be removed.
547 * 500, if any exception occurred while deletion.
548 * 204, if everything worked out.
549 :rtype: :class:`flask.response`
551 logging
.debug("API CALL: %s DELETE" % str(self
.__class
__.__name
__))
553 for net
in self
.api
.compute
.nets
.values():
554 if net
.subnet_id
== subnet_id
:
555 for server
in self
.api
.compute
.computeUnits
.values():
556 for port_name
in server
.port_names
:
557 port
= self
.api
.compute
.find_port_by_name_or_id(port_name
)
558 if port
.net_name
== net
.name
:
559 port
.ip_address
= None
560 self
.api
.compute
.dc
.net
.removeLink(
562 node1
=self
.api
.compute
.dc
.containers
[server
.name
],
563 node2
=self
.api
.compute
.dc
.switch
)
568 return Response('Subnet ' + str(subnet_id
) + ' deleted.\n',
569 status
=204, mimetype
='application/json')
571 return Response('Could not find subnet.', status
=404, mimetype
='application/json')
572 except Exception as ex
:
573 logging
.exception("Neutron: Delete subnet exception.")
574 return Response(ex
.message
, status
=500, mimetype
='application/json')
577 class NeutronListPorts(Resource
):
578 def __init__(self
, api
):
583 Lists all ports, used in son-emu. If a 'name' or one or more 'id's are specified, it will only list the
584 port with the name, or the ports specified via id.
586 :return: Returns a json response, starting with 'ports' as root node.
587 :rtype: :class:`flask.response`
589 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
591 if request
.args
.get('name'):
592 show_port
= NeutronShowPort(self
.api
)
593 return show_port
.get_port(request
.args
.get('name'), True)
594 id_list
= request
.args
.getlist('id')
595 if len(id_list
) == 1:
596 show_port
= NeutronShowPort(self
.api
)
597 return show_port
.get_port(request
.args
.get('id'), True)
602 if len(id_list
) == 0:
603 for port
in self
.api
.compute
.ports
.values():
604 tmp_port_dict
= port
.create_port_dict(self
.api
.compute
)
605 port_list
.append(tmp_port_dict
)
607 for port
in self
.api
.compute
.ports
.values():
608 if port
.id in id_list
:
609 tmp_port_dict
= port
.create_port_dict(self
.api
.compute
)
610 port_list
.append(tmp_port_dict
)
612 port_dict
["ports"] = port_list
614 return Response(json
.dumps(port_dict
), status
=200, mimetype
='application/json')
616 except Exception as ex
:
617 logging
.exception("Neutron: List ports exception.")
618 return Response(ex
.message
, status
=500, mimetype
='application/json')
621 class NeutronShowPort(Resource
):
622 def __init__(self
, api
):
625 def get(self
, port_id
):
627 Returns the port, specified via 'port_id'.
629 :param port_id: The unique ID string of the network.
630 :type port_id: ``str``
631 :return: Returns a json response, starting with 'port' as root node and one network description.
632 :rtype: :class:`flask.response`
634 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
635 return self
.get_port(port_id
, False)
637 def get_port(self
, port_name_or_id
, as_list
):
639 Returns one network description of the port, specified via 'port_name_or_id'.
641 :param port_name_or_id: The indicator string, which specifies the requested port.
642 :type port_name_or_id: ``str``
643 :param as_list: Determines if the port description should start with the root node 'port' or 'ports'.
644 :type as_list: ``bool``
645 :return: Returns a json response, with one port description.
646 :rtype: :class:`flask.response`
649 port
= self
.api
.compute
.find_port_by_name_or_id(port_name_or_id
)
651 return Response('Port not found. (' + port_name_or_id
+ ')\n', status
=404, mimetype
='application/json')
652 tmp_port_dict
= port
.create_port_dict(self
.api
.compute
)
655 tmp_dict
["ports"] = [tmp_port_dict
]
657 tmp_dict
["port"] = tmp_port_dict
658 return Response(json
.dumps(tmp_dict
), status
=200, mimetype
='application/json')
659 except Exception as ex
:
660 logging
.exception("Neutron: Show port exception.")
661 return Response(ex
.message
, status
=500, mimetype
='application/json')
664 class NeutronCreatePort(Resource
):
665 def __init__(self
, api
):
670 Creates a port with the name, specified within the request under ['port']['name'].
672 :return: * 404, if the network could not be found.
673 * 500, if any exception occurred while creation and
674 * 201, if everything worked out.
675 :rtype: :class:`flask.response`
677 logging
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
679 port_dict
= json
.loads(request
.data
)
680 net_id
= port_dict
['port']['network_id']
682 if net_id
not in self
.api
.compute
.nets
:
683 return Response('Could not find network.\n', status
=404, mimetype
='application/json')
685 net
= self
.api
.compute
.nets
[net_id
]
686 if 'name' in port_dict
['port']:
687 name
= port_dict
['port']['name']
689 num_ports
= len(self
.api
.compute
.ports
)
690 name
= "port:cp%s:man:%s" % (num_ports
, str(uuid
.uuid4()))
692 if self
.api
.compute
.find_port_by_name_or_id(name
):
693 return Response("Port with name %s already exists.\n" % name
, status
=500, mimetype
='application/json')
695 port
= self
.api
.compute
.create_port(name
)
697 port
.net_name
= net
.name
698 port
.ip_address
= net
.get_new_ip_address(name
)
700 if "admin_state_up" in port_dict
["port"]:
702 if "device_id" in port_dict
["port"]:
704 if "device_owner" in port_dict
["port"]:
706 if "fixed_ips" in port_dict
["port"]:
708 if "mac_address" in port_dict
["port"]:
709 port
.mac_address
= port_dict
["port"]["mac_address"]
710 if "status" in port_dict
["port"]:
712 if "tenant_id" in port_dict
["port"]:
715 # add the port to a stack if the specified network is a stack network
716 for stack
in self
.api
.compute
.stacks
.values():
717 for net
in stack
.nets
.values():
719 stack
.ports
[name
] = port
721 return Response(json
.dumps({'port': port
.create_port_dict(self
.api
.compute
)}), status
=201,
722 mimetype
='application/json')
723 except Exception as ex
:
724 logging
.exception("Neutron: Show port exception.")
725 return Response(ex
.message
, status
=500, mimetype
='application/json')
728 class NeutronUpdatePort(Resource
):
729 def __init__(self
, api
):
732 def put(self
, port_id
):
734 Updates the existing port with the given parameters.
736 :param network_id: The indicator string, which specifies the requested port.
737 :type network_id: ``str``
738 :return: * 404, if the network could not be found.
739 * 500, if any exception occurred while updating the network.
740 * 200, if everything worked out.
741 :rtype: :class:`flask.response`
743 logging
.debug("API CALL: %s PUT" % str(self
.__class
__.__name
__))
745 port_dict
= json
.loads(request
.data
)
746 port
= self
.api
.compute
.find_port_by_name_or_id(port_id
)
748 return Response("Port with id %s does not exists.\n" % port_id
, status
=404, mimetype
='application/json')
749 old_port
= copy
.copy(port
)
752 for s
in self
.api
.compute
.stacks
.values():
753 for port
in s
.ports
.values():
754 if port
.id == port_id
:
756 if "admin_state_up" in port_dict
["port"]:
758 if "device_id" in port_dict
["port"]:
760 if "device_owner" in port_dict
["port"]:
762 if "fixed_ips" in port_dict
["port"]:
764 if "id" in port_dict
["port"]:
765 port
.id = port_dict
["port"]["id"]
766 if "mac_address" in port_dict
["port"]:
767 port
.mac_address
= port_dict
["port"]["mac_address"]
768 if "name" in port_dict
["port"] and port_dict
["port"]["name"] != port
.name
:
769 port
.set_name(port_dict
["port"]["name"])
770 if stack
is not None:
771 if port
.net_name
in stack
.nets
:
772 stack
.nets
[port
.net_name
].update_port_name_for_ip_address(port
.ip_address
, port
.name
)
773 stack
.ports
[port
.name
] = stack
.ports
[old_port
.name
]
774 del stack
.ports
[old_port
.name
]
775 if "network_id" in port_dict
["port"]:
777 if "status" in port_dict
["port"]:
779 if "tenant_id" in port_dict
["port"]:
782 return Response(json
.dumps({'port': port
.create_port_dict(self
.api
.compute
)}), status
=200,
783 mimetype
='application/json')
784 except Exception as ex
:
785 logging
.exception("Neutron: Update port exception.")
786 return Response(ex
.message
, status
=500, mimetype
='application/json')
789 class NeutronDeletePort(Resource
):
790 def __init__(self
, api
):
793 def delete(self
, port_id
):
795 Deletes the specified port.
797 :param port_id: The indicator string, which specifies the requested port.
798 :type port_id: ``str``
799 :return: * 404, if the port could not be found.
800 * 500, if any exception occurred while deletion.
801 * 204, if everything worked out.
802 :rtype: :class:`flask.response`
804 logging
.debug("API CALL: %s DELETE" % str(self
.__class
__.__name
__))
806 port
= self
.api
.compute
.find_port_by_name_or_id(port_id
)
808 return Response("Port with id %s does not exists.\n" % port_id
, status
=404)
810 for s
in self
.api
.compute
.stacks
.values():
811 for p
in s
.ports
.values():
814 if stack
is not None:
815 if port
.net_name
in stack
.nets
:
816 stack
.nets
[port
.net_name
].withdraw_ip_address(port
.ip_address
)
817 for server
in stack
.servers
.values():
819 server
.port_names
.remove(port
.name
)
824 self
.api
.compute
.delete_port(port
.id)
826 return Response('Port ' + port_id
+ ' deleted.\n', status
=204, mimetype
='application/json')
828 except Exception as ex
:
829 logging
.exception("Neutron: Delete port exception.")
830 return Response(ex
.message
, status
=500, mimetype
='application/json')
833 class NeutronAddFloatingIp(Resource
):
834 def __init__(self
, api
):
839 Added a quick and dirty fake for the OSM integration. Returns a list of
840 floating IPs. Has nothing to do with the setup inside the emulator.
841 But its enough to make the OSM driver happy.
842 @PG Sandman: Feel free to improve this and let it do something meaningful.
845 resp
["floatingips"] = list()
846 # create a list of floting IP definitions and return it
847 for i
in range(100, 110):
849 ip
["router_id"] = "router_id"
850 ip
["description"] = "hardcoded in api"
851 ip
["created_at"] = "router_id"
852 ip
["updated_at"] = "router_id"
853 ip
["revision_number"] = 1
854 ip
["tenant_id"] = "tenant_id"
855 ip
["project_id"] = "project_id"
856 ip
["floating_network_id"] = str(i
)
857 ip
["status"] = "ACTIVE"
859 ip
["port_id"] = "port_id"
860 ip
["floating_ip_address"] = "172.0.0.%d" % i
861 ip
["fixed_ip_address"] = "10.0.0.%d" % i
862 resp
["floatingips"].append(ip
)
863 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
868 Adds a floating IP to neutron.
870 :return: Returns a floating network description.
871 :rtype: :class:`flask.response`
873 logging
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
875 # Fiddle with floating_network !
876 req
= json
.loads(request
.data
)
878 network_id
= req
["floatingip"]["floating_network_id"]
879 net
= self
.api
.compute
.find_network_by_name_or_id(network_id
)
880 if net
!= self
.api
.manage
.floating_network
:
881 return Response("You have to specify the existing floating network\n",
882 status
=400, mimetype
='application/json')
884 port_id
= req
["floatingip"].get("port_id", None)
885 port
= self
.api
.compute
.find_port_by_name_or_id(port_id
)
887 if port
.net_name
!= self
.api
.manage
.floating_network
.name
:
888 return Response("You have to specify a port in the floating network\n",
889 status
=400, mimetype
='application/json')
891 if port
.floating_ip
is not None:
892 return Response("We allow only one floating ip per port\n", status
=400, mimetype
='application/json')
894 num_ports
= len(self
.api
.compute
.ports
)
895 name
= "port:cp%s:fl:%s" % (num_ports
, str(uuid
.uuid4()))
896 port
= self
.api
.compute
.create_port(name
)
897 port
.net_name
= net
.name
898 port
.ip_address
= net
.get_new_ip_address(name
)
900 port
.floating_ip
= port
.ip_address
903 resp
= response
["floatingip"] = dict()
905 resp
["floating_network_id"] = net
.id
906 resp
["status"] = "ACTIVE"
908 resp
["port_id"] = port
.id
909 resp
["floating_ip_address"] = port
.floating_ip
910 resp
["fixed_ip_address"] = port
.floating_ip
912 return Response(json
.dumps(response
), status
=200, mimetype
='application/json')
913 except Exception as ex
:
914 logging
.exception("Neutron: Create FloatingIP exception %s.", ex
)
915 return Response(ex
.message
, status
=500, mimetype
='application/json')