1 from flask_restful
import Resource
2 from flask
import Response
, request
3 from emuvim
.api
.openstack
.openstack_dummies
.base_openstack_dummy
import BaseOpenstackDummy
7 from mininet
.link
import Link
10 LOG
= logging
.getLogger("api.openstack.nova")
13 class NovaDummyApi(BaseOpenstackDummy
):
14 def __init__(self
, in_ip
, in_port
, compute
):
15 super(NovaDummyApi
, self
).__init
__(in_ip
, in_port
)
16 self
.compute
= compute
18 self
.api
.add_resource(NovaVersionsList
, "/",
19 resource_class_kwargs
={'api': self
})
20 self
.api
.add_resource(Shutdown
, "/shutdown")
21 self
.api
.add_resource(NovaVersionShow
, "/v2.1/<id>",
22 resource_class_kwargs
={'api': self
})
23 self
.api
.add_resource(NovaListServersApi
, "/v2.1/<id>/servers",
24 resource_class_kwargs
={'api': self
})
25 self
.api
.add_resource(NovaListServersAndPortsApi
, "/v2.1/<id>/servers/andPorts",
26 resource_class_kwargs
={'api': self
})
27 self
.api
.add_resource(NovaListServersDetailed
, "/v2.1/<id>/servers/detail",
28 resource_class_kwargs
={'api': self
})
29 self
.api
.add_resource(NovaShowServerDetails
, "/v2.1/<id>/servers/<serverid>",
30 resource_class_kwargs
={'api': self
})
31 self
.api
.add_resource(NovaInterfaceToServer
, "/v2.1/<id>/servers/<serverid>/os-interface",
32 resource_class_kwargs
={'api': self
})
33 self
.api
.add_resource(NovaShowAndDeleteInterfaceAtServer
, "/v2.1/<id>/servers/<serverid>/os-interface/<port_id>",
34 resource_class_kwargs
={'api': self
})
35 self
.api
.add_resource(NovaListFlavors
, "/v2.1/<id>/flavors", "/v2/<id>/flavors",
36 resource_class_kwargs
={'api': self
})
37 self
.api
.add_resource(NovaListFlavorsDetails
, "/v2.1/<id>/flavors/detail", "/v2/<id>/flavors/detail",
38 resource_class_kwargs
={'api': self
})
39 self
.api
.add_resource(NovaListFlavorById
, "/v2.1/<id>/flavors/<flavorid>", "/v2/<id>/flavors/<flavorid>",
40 resource_class_kwargs
={'api': self
})
41 self
.api
.add_resource(NovaListImages
, "/v2.1/<id>/images",
42 resource_class_kwargs
={'api': self
})
43 self
.api
.add_resource(NovaListImagesDetails
, "/v2.1/<id>/images/detail",
44 resource_class_kwargs
={'api': self
})
45 self
.api
.add_resource(NovaListImageById
, "/v2.1/<id>/images/<imageid>",
46 resource_class_kwargs
={'api': self
})
48 def _start_flask(self
):
49 LOG
.info("Starting %s endpoint @ http://%s:%d" % ("NovaDummyApi", self
.ip
, self
.port
))
50 # add some flavors for good measure
51 self
.compute
.add_flavor('m1.tiny', 1, 512, "MB", 1, "GB")
52 self
.compute
.add_flavor('m1.nano', 1, 64, "MB", 0, "GB")
53 self
.compute
.add_flavor('m1.micro', 1, 128, "MB", 0, "GB")
54 self
.compute
.add_flavor('m1.small', 1, 1024, "MB", 2, "GB")
55 if self
.app
is not None:
56 self
.app
.before_request(self
.dump_playbook
)
57 self
.app
.run(self
.ip
, self
.port
, debug
=True, use_reloader
=False)
60 class Shutdown(Resource
):
62 A get request to /shutdown will shut down this endpoint.
66 LOG
.debug(("%s is beeing shut doen") % (__name__
))
67 func
= request
.environ
.get('werkzeug.server.shutdown')
69 raise RuntimeError('Not running with the Werkzeug Server')
73 class NovaVersionsList(Resource
):
74 def __init__(self
, api
):
81 :return: Returns a json with API versions.
82 :rtype: :class:`flask.response`
84 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
93 "href": "http://%s:%d/v2.1/",
100 "updated": "2013-07-23T11:33:21Z"
104 """ % (self
.api
.ip
, self
.api
.port
)
106 response
= Response(resp
, status
=200, mimetype
="application/json")
107 response
.headers
['Access-Control-Allow-Origin'] = '*'
110 except Exception as ex
:
111 LOG
.exception(u
"%s: Could not show list of versions." % __name__
)
112 return ex
.message
, 500
115 class NovaVersionShow(Resource
):
116 def __init__(self
, api
):
125 :return: Returns a json with API details.
126 :rtype: :class:`flask.response`
128 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
137 "href": "http://%s:%d/v2.1/",
141 "href": "http://docs.openstack.org/",
142 "rel": "describedby",
148 "base": "application/json",
149 "type": "application/vnd.openstack.compute+json;version=2.1"
154 "min_version": "2.1",
155 "updated": "2013-07-23T11:33:21Z"
158 """ % (self
.api
.ip
, self
.api
.port
)
160 response
= Response(resp
, status
=200, mimetype
="application/json")
161 response
.headers
['Access-Control-Allow-Origin'] = '*'
164 except Exception as ex
:
165 LOG
.exception(u
"%s: Could not show list of versions." % __name__
)
166 return ex
.message
, 500
169 class NovaListServersApi(Resource
):
170 def __init__(self
, api
):
175 Creates a list with all running servers and their detailed information.
177 :param id: Used to create a individual link to quarry further information.
179 :return: Returns a json response with a dictionary that contains the server information.
180 :rtype: :class:`flask.response`
182 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
186 resp
['servers'] = list()
187 for server
in self
.api
.compute
.computeUnits
.values():
188 s
= server
.create_server_dict(self
.api
.compute
)
189 s
['links'] = [{'href': "http://%s:%d/v2.1/%s/servers/%s" % (self
.api
.ip
,
194 resp
['servers'].append(s
)
196 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
197 response
.headers
['Access-Control-Allow-Origin'] = '*'
200 except Exception as ex
:
201 LOG
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
202 return ex
.message
, 500
206 Creates a server instance.
208 :param id: tenant id, we ignore this most of the time
210 :return: Returns a flask response, with detailed information about the just created server.
211 :rtype: :class:`flask.response`
213 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
215 server_dict
= json
.loads(request
.data
)['server']
216 networks
= server_dict
.get('networks', None)
217 name
= str(self
.api
.compute
.dc
.label
) + "_man_" + server_dict
["name"][0:12]
219 if self
.api
.compute
.find_server_by_name_or_id(name
) is not None:
220 return Response("Server with name %s already exists." % name
, status
=409)
221 # TODO: not finished!
224 server
= self
.api
.compute
.create_server(name
)
225 server
.full_name
= str(self
.api
.compute
.dc
.label
) + "_man_" + server_dict
["name"]
226 server
.template_name
= server_dict
["name"]
228 for flavor
in self
.api
.compute
.flavors
.values():
229 if flavor
.id == server_dict
.get('flavorRef', ''):
230 server
.flavor
= flavor
.name
231 for image
in self
.api
.compute
.images
.values():
232 if image
.id in server_dict
['imageRef']:
233 server
.image
= image
.name
235 if networks
is not None:
237 port
= self
.api
.compute
.find_port_by_name_or_id(net
.get('port', ""))
239 server
.port_names
.append(port
.name
)
241 return Response("Currently only networking by port is supported.", status
=400)
243 self
.api
.compute
._start
_compute
(server
)
245 response
= NovaShowServerDetails(self
.api
).get(id, server
.id)
246 response
.headers
['Access-Control-Allow-Origin'] = '*'
249 except Exception as ex
:
250 LOG
.exception(u
"%s: Could not create the server." % __name__
)
251 return ex
.message
, 500
254 class NovaListServersAndPortsApi(Resource
):
255 def __init__(self
, api
):
260 Creates a list with all running servers and their detailed information. This function also presents all
261 port information of each server.
263 :param id: Used to create a individual link to quarry further information.
265 :return: Returns a json response with a dictionary that contains the server information.
266 :rtype: :class:`flask.response`
268 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
272 resp
['servers'] = list()
273 for server
in self
.api
.compute
.computeUnits
.values():
274 s
= server
.create_server_dict(self
.api
.compute
)
275 s
['links'] = [{'href': "http://%s:%d/v2.1/%s/servers/%s" % (self
.api
.ip
,
281 for port_name
in server
.port_names
:
282 port
= self
.api
.compute
.find_port_by_name_or_id(port_name
)
286 tmp
= port
.create_port_dict(self
.api
.compute
)
287 tmp
['intf_name'] = port
.intf_name
288 s
['ports'].append(tmp
)
290 resp
['servers'].append(s
)
292 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
293 response
.headers
['Access-Control-Allow-Origin'] = '*'
296 except Exception as ex
:
297 LOG
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
298 return ex
.message
, 500
301 class NovaListServersDetailed(Resource
):
302 def __init__(self
, api
):
307 As List Servers, it lists all running servers and their details but furthermore it also states the
308 used flavor and the server image.
310 :param id: tenant id, used for the 'href' link.
312 :return: Returns a flask response, with detailed information aboit the servers and their flavor and image.
313 :rtype: :class:`flask.response`
315 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
318 resp
= {"servers": list()}
319 for server
in self
.api
.compute
.computeUnits
.values():
320 s
= server
.create_server_dict(self
.api
.compute
)
321 s
['links'] = [{'href': "http://%s:%d/v2.1/%s/servers/%s" % (self
.api
.ip
,
325 flavor
= self
.api
.compute
.flavors
[server
.flavor
]
330 "href": "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
338 image
= self
.api
.compute
.images
[server
.image
]
343 "href": "http://%s:%d/v2.1/%s/images/%s" % (self
.api
.ip
,
352 resp
['servers'].append(s
)
354 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
355 response
.headers
['Access-Control-Allow-Origin'] = '*'
358 except Exception as ex
:
359 LOG
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
360 return ex
.message
, 500
363 class NovaListFlavors(Resource
):
364 def __init__(self
, api
):
369 Lists all available flavors.
371 :param id: tenant id, used for the 'href' link
373 :return: Returns a flask response with a list of all flavors.
374 :rtype: :class:`flask.response`
376 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
379 resp
['flavors'] = list()
380 for flavor
in self
.api
.compute
.flavors
.values():
381 f
= flavor
.__dict
__.copy()
383 f
['name'] = flavor
.name
384 f
['links'] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
388 resp
['flavors'].append(f
)
390 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
391 response
.headers
['Access-Control-Allow-Origin'] = '*'
394 except Exception as ex
:
395 LOG
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
396 return ex
.message
, 500
399 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
400 data
= json
.loads(request
.data
).get("flavor")
401 LOG
.warning("Create Flavor: %s" % str(data
))
402 # add to internal dict
403 f
= self
.api
.compute
.add_flavor(
406 data
.get("ram"), "MB",
407 data
.get("disk"), "GB")
408 # create response based on incoming data
410 data
["links"] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
414 resp
= {"flavor": data
}
415 return Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
418 class NovaListFlavorsDetails(Resource
):
419 def __init__(self
, api
):
424 Lists all flavors with additional information like ram and disk space.
426 :param id: tenant id, used for the 'href' link
428 :return: Returns a flask response with a list of all flavors with additional information.
429 :rtype: :class:`flask.response`
431 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
434 resp
['flavors'] = list()
435 for flavor
in self
.api
.compute
.flavors
.values():
436 # use the class dict. it should work fine
437 # but use a copy so we don't modifiy the original
438 f
= flavor
.__dict
__.copy()
439 # add additional expected stuff stay openstack compatible
440 f
['links'] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
444 f
['OS-FLV-DISABLED:disabled'] = False
445 f
['OS-FLV-EXT-DATA:ephemeral'] = 0
446 f
['os-flavor-access:is_public'] = True
447 f
['ram'] = flavor
.memory
448 f
['vcpus'] = flavor
.cpu
450 f
['disk'] = flavor
.storage
451 f
['rxtx_factor'] = 1.0
452 resp
['flavors'].append(f
)
454 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
455 response
.headers
['Access-Control-Allow-Origin'] = '*'
458 except Exception as ex
:
459 LOG
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
460 return ex
.message
, 500
463 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
464 data
= json
.loads(request
.data
).get("flavor")
465 LOG
.warning("Create Flavor: %s" % str(data
))
466 # add to internal dict
467 f
= self
.api
.compute
.add_flavor(
470 data
.get("ram"), "MB",
471 data
.get("disk"), "GB")
472 # create response based on incoming data
474 data
["links"] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
478 resp
= {"flavor": data
}
479 return Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
482 class NovaListFlavorById(Resource
):
483 def __init__(self
, api
):
486 def get(self
, id, flavorid
):
488 Returns details about one flavor.
490 :param id: tenant id, used for the 'href' link
492 :param flavorid: Represents the flavor.
493 :type flavorid: ``str``
494 :return: Returns a flask response with detailed information about the flavor.
495 :rtype: :class:`flask.response`
497 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
500 resp
['flavor'] = dict()
501 flavor
= self
.api
.compute
.flavors
.get(flavorid
, None)
503 for f
in self
.api
.compute
.flavors
.values():
507 resp
['flavor']['id'] = flavor
.id
508 resp
['flavor']['name'] = flavor
.name
509 resp
['flavor']['links'] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
513 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
514 response
.headers
['Access-Control-Allow-Origin'] = '*'
517 except Exception as ex
:
518 LOG
.exception(u
"%s: Could not retrieve flavor with id %s" % (__name__
, flavorid
))
519 return ex
.message
, 500
522 class NovaListImages(Resource
):
523 def __init__(self
, api
):
528 Creates a list of all usable images.
530 :param id: tenant id, used for the 'href' link
532 :return: Returns a flask response with a list of available images.
533 :rtype: :class:`flask.response`
535 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
538 resp
['images'] = list()
539 for image
in self
.api
.compute
.images
.values():
542 f
['name'] = str(image
.name
).replace(":latest", "")
543 f
['links'] = [{'href': "http://%s:%d/v2.1/%s/images/%s" % (self
.api
.ip
,
547 resp
['images'].append(f
)
548 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
549 response
.headers
['Access-Control-Allow-Origin'] = '*'
552 except Exception as ex
:
553 LOG
.exception(u
"%s: Could not retrieve the list of images." % __name__
)
554 return ex
.message
, 500
557 class NovaListImagesDetails(Resource
):
558 def __init__(self
, api
):
563 As List Images but with additional metadata.
565 :param id: tenant id, used for the 'href' link
567 :return: Returns a flask response with a list of images and their metadata.
568 :rtype: :class:`flask.response`
570 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
573 resp
['images'] = list()
574 for image
in self
.api
.compute
.images
.values():
575 # use the class dict. it should work fine
576 # but use a copy so we don't modifiy the original
577 f
= image
.__dict
__.copy()
578 # add additional expected stuff stay openstack compatible
579 f
['name'] = str(image
.name
).replace(":latest", "")
580 f
['links'] = [{'href': "http://%s:%d/v2.1/%s/images/%s" % (self
.api
.ip
,
585 "architecture": "x86_64",
586 "auto_disk_config": "True",
587 "kernel_id": "nokernel",
588 "ramdisk_id": "nokernel"
590 resp
['images'].append(f
)
592 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
593 response
.headers
['Access-Control-Allow-Origin'] = '*'
596 except Exception as ex
:
597 LOG
.exception(u
"%s: Could not retrieve the list of images." % __name__
)
598 return ex
.message
, 500
601 class NovaListImageById(Resource
):
602 def __init__(self
, api
):
605 def get(self
, id, imageid
):
607 Gets an image by id from the emulator with openstack nova compliant return values.
609 :param id: tenantid, we ignore this most of the time
611 :param imageid: id of the image. If it is 1 the dummy CREATE-IMAGE is returned
612 :type imageid: ``str``
613 :return: Returns a flask response with the information about one image.
614 :rtype: :class:`flask.response`
616 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
619 i
= resp
['image'] = dict()
620 for image
in self
.api
.compute
.images
.values():
621 if image
.id == imageid
or image
.name
== imageid
:
623 i
['name'] = image
.name
625 return Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
627 response
= Response("Image with id or name %s does not exists." % imageid
, status
=404)
628 response
.headers
['Access-Control-Allow-Origin'] = '*'
631 except Exception as ex
:
632 LOG
.exception(u
"%s: Could not retrieve image with id %s." % (__name__
, imageid
))
633 return ex
.message
, 500
636 class NovaShowServerDetails(Resource
):
637 def __init__(self
, api
):
640 def get(self
, id, serverid
):
642 Returns detailed information about the specified server.
644 :param id: tenant id, used for the 'href' link
646 :param serverid: Specifies the requested server.
647 :type serverid: ``str``
648 :return: Returns a flask response with details about the server.
649 :rtype: :class:`flask.response`
651 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
653 server
= self
.api
.compute
.find_server_by_name_or_id(serverid
)
655 return Response("Server with id or name %s does not exists." % serverid
, status
=404)
656 s
= server
.create_server_dict()
657 s
['links'] = [{'href': "http://%s:%d/v2.1/%s/servers/%s" % (self
.api
.ip
,
662 flavor
= self
.api
.compute
.flavors
[server
.flavor
]
667 "href": "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
675 image
= self
.api
.compute
.images
[server
.image
]
680 "href": "http://%s:%d/v2.1/%s/images/%s" % (self
.api
.ip
,
689 response
= Response(json
.dumps({'server': s
}), status
=200, mimetype
="application/json")
690 response
.headers
['Access-Control-Allow-Origin'] = '*'
693 except Exception as ex
:
694 LOG
.exception(u
"%s: Could not retrieve the server details." % __name__
)
695 return ex
.message
, 500
697 def delete(self
, id, serverid
):
699 Delete a server instance.
701 :param id: tenant id, we ignore this most of the time
703 :param serverid: The UUID of the server
704 :type serverid: ``str``
705 :return: Returns 200 if everything is fine.
706 :rtype: :class:`flask.response`
708 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
710 server
= self
.api
.compute
.find_server_by_name_or_id(serverid
)
712 return Response('Could not find server.', status
=404, mimetype
="application/json")
714 self
.api
.compute
.stop_compute(server
)
716 response
= Response('Server deleted.', status
=204, mimetype
="application/json")
717 response
.headers
['Access-Control-Allow-Origin'] = '*'
720 except Exception as ex
:
721 LOG
.exception(u
"%s: Could not create the server." % __name__
)
722 return ex
.message
, 500
725 class NovaInterfaceToServer(Resource
):
726 def __init__(self
, api
):
729 def post(self
, id, serverid
):
731 Add an interface to the specified server.
733 :param id: tenant id, we ignore this most of the time
735 :param serverid: Specifies the server.
736 :type serverid: ``str``
737 :return: Returns a flask response with information about the attached interface.
738 :rtype: :class:`flask.response`
740 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
742 server
= self
.api
.compute
.find_server_by_name_or_id(serverid
)
744 return Response("Server with id or name %s does not exists." % serverid
, status
=404)
746 if server
.emulator_compute
is None:
747 LOG
.error("The targeted container does not exist.")
748 return Response("The targeted container of %s does not exist." % serverid
, status
=404)
749 data
= json
.loads(request
.data
).get("interfaceAttachment")
751 port
= data
.get("port_id", None)
752 net
= data
.get("net_id", None)
753 dc
= self
.api
.compute
.dc
754 network_dict
= dict()
757 if net
is not None and port
is not None:
758 port
= self
.api
.compute
.find_port_by_name_or_id(port
)
759 network
= self
.api
.compute
.find_network_by_name_or_id(net
)
760 network_dict
['id'] = port
.intf_name
761 network_dict
['ip'] = port
.ip_address
762 network_dict
[network_dict
['id']] = network
.name
763 elif net
is not None:
764 network
= self
.api
.compute
.find_network_by_name_or_id(net
)
766 return Response("Network with id or name %s does not exists." % net
, status
=404)
767 port
= self
.api
.compute
.create_port("port:cp%s:fl:%s" %
768 (len(self
.api
.compute
.ports
), str(uuid
.uuid4())))
770 port
.net_name
= network
.name
771 port
.ip_address
= network
.get_new_ip_address(port
.name
)
772 network_dict
['id'] = port
.intf_name
773 network_dict
['ip'] = port
.ip_address
774 network_dict
[network_dict
['id']] = network
.name
775 elif port
is not None:
776 port
= self
.api
.compute
.find_port_by_name_or_id(port
)
777 network_dict
['id'] = port
.intf_name
778 network_dict
['ip'] = port
.ip_address
779 network
= self
.api
.compute
.find_network_by_name_or_id(port
.net_name
)
780 network_dict
[network_dict
['id']] = network
.name
782 raise Exception("You can only attach interfaces by port or network at the moment")
784 if network
== self
.api
.manage
.floating_network
:
785 dc
.net
.addLink(server
.emulator_compute
, self
.api
.manage
.floating_switch
,
786 params1
=network_dict
, cls
=Link
, intfName1
=port
.intf_name
)
788 dc
.net
.addLink(server
.emulator_compute
, dc
.switch
,
789 params1
=network_dict
, cls
=Link
, intfName1
=port
.intf_name
)
790 resp
["port_state"] = "ACTIVE"
791 resp
["port_id"] = port
.id
792 resp
["net_id"] = self
.api
.compute
.find_network_by_name_or_id(port
.net_name
).id
793 resp
["mac_addr"] = port
.mac_address
794 resp
["fixed_ips"] = list()
796 fixed_ips
["ip_address"] = port
.ip_address
797 fixed_ips
["subnet_id"] = network
.subnet_name
798 resp
["fixed_ips"].append(fixed_ips
)
799 response
= Response(json
.dumps({"interfaceAttachment": resp
}), status
=202, mimetype
="application/json")
800 response
.headers
['Access-Control-Allow-Origin'] = '*'
803 except Exception as ex
:
804 LOG
.exception(u
"%s: Could not add interface to the server." % __name__
)
805 return ex
.message
, 500
808 class NovaShowAndDeleteInterfaceAtServer(Resource
):
809 def __init__(self
, api
):
812 def delete(self
, id, serverid
, port_id
):
814 Deletes an existing interface.
816 :param id: tenant id, we ignore this most of the time
818 :param serverid: Specifies the server, where the interface will be deleted.
819 :type serverid: ``str``
820 :param port_id: Specifies the port of the interface.
821 :type port_id: ``str``
822 :return: Returns a flask response with 202 if everything worked out. Otherwise it will return 404 and an
824 :rtype: :class:`flask.response`
826 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
828 server
= self
.api
.compute
.find_server_by_name_or_id(serverid
)
830 return Response("Server with id or name %s does not exists." % serverid
, status
=404)
831 port
= self
.api
.compute
.find_port_by_name_or_id(port_id
)
833 return Response("Port with id or name %s does not exists." % port_id
, status
=404)
835 for link
in self
.api
.compute
.dc
.net
.links
:
836 if str(link
.intf1
) == port
.intf_name
and \
837 str(link
.intf1
.ip
) == port
.ip_address
.split('/')[0]:
838 self
.api
.compute
.dc
.net
.removeLink(link
)
841 response
= Response("", status
=202, mimetype
="application/json")
842 response
.headers
['Access-Control-Allow-Origin'] = '*'
845 except Exception as ex
:
846 LOG
.exception(u
"%s: Could not detach interface from the server." % __name__
)
847 return ex
.message
, 500