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 class NovaDummyApi(BaseOpenstackDummy
):
11 def __init__(self
, in_ip
, in_port
, compute
):
12 super(NovaDummyApi
, self
).__init
__(in_ip
, in_port
)
13 self
.compute
= compute
15 self
.api
.add_resource(NovaVersionsList
, "/",
16 resource_class_kwargs
={'api': self
})
17 self
.api
.add_resource(Shutdown
, "/shutdown")
18 self
.api
.add_resource(NovaVersionShow
, "/v2.1/<id>",
19 resource_class_kwargs
={'api': self
})
20 self
.api
.add_resource(NovaListServersApi
, "/v2.1/<id>/servers",
21 resource_class_kwargs
={'api': self
})
22 self
.api
.add_resource(NovaListServersAndPortsApi
, "/v2.1/<id>/servers/andPorts",
23 resource_class_kwargs
={'api': self
})
24 self
.api
.add_resource(NovaListServersDetailed
, "/v2.1/<id>/servers/detail",
25 resource_class_kwargs
={'api': self
})
26 self
.api
.add_resource(NovaShowServerDetails
, "/v2.1/<id>/servers/<serverid>",
27 resource_class_kwargs
={'api': self
})
28 self
.api
.add_resource(NovaInterfaceToServer
, "/v2.1/<id>/servers/<serverid>/os-interface",
29 resource_class_kwargs
={'api': self
})
30 self
.api
.add_resource(NovaShowAndDeleteInterfaceAtServer
, "/v2.1/<id>/servers/<serverid>/os-interface/<port_id>",
31 resource_class_kwargs
={'api': self
})
32 self
.api
.add_resource(NovaListFlavors
, "/v2.1/<id>/flavors", "/v2/<id>/flavors",
33 resource_class_kwargs
={'api': self
})
34 self
.api
.add_resource(NovaListFlavorsDetails
, "/v2.1/<id>/flavors/detail", "/v2/<id>/flavors/detail",
35 resource_class_kwargs
={'api': self
})
36 self
.api
.add_resource(NovaListFlavorById
, "/v2.1/<id>/flavors/<flavorid>", "/v2/<id>/flavors/<flavorid>",
37 resource_class_kwargs
={'api': self
})
38 self
.api
.add_resource(NovaListImages
, "/v2.1/<id>/images",
39 resource_class_kwargs
={'api': self
})
40 self
.api
.add_resource(NovaListImagesDetails
, "/v2.1/<id>/images/detail",
41 resource_class_kwargs
={'api': self
})
42 self
.api
.add_resource(NovaListImageById
, "/v2.1/<id>/images/<imageid>",
43 resource_class_kwargs
={'api': self
})
45 def _start_flask(self
):
46 logging
.info("Starting %s endpoint @ http://%s:%d" % ("NovaDummyApi", self
.ip
, self
.port
))
47 # add some flavors for good measure
48 self
.compute
.add_flavor('m1.tiny', 1, 512, "MB", 1, "GB")
49 self
.compute
.add_flavor('m1.nano', 1, 64, "MB", 0, "GB")
50 self
.compute
.add_flavor('m1.micro', 1, 128, "MB", 0, "GB")
51 self
.compute
.add_flavor('m1.small', 1, 1024, "MB", 2, "GB")
52 if self
.app
is not None:
53 self
.app
.before_request(self
.dump_playbook
)
54 self
.app
.run(self
.ip
, self
.port
, debug
=True, use_reloader
=False)
57 class Shutdown(Resource
):
59 A get request to /shutdown will shut down this endpoint.
63 logging
.debug(("%s is beeing shut doen") % (__name__
))
64 func
= request
.environ
.get('werkzeug.server.shutdown')
66 raise RuntimeError('Not running with the Werkzeug Server')
70 class NovaVersionsList(Resource
):
71 def __init__(self
, api
):
78 :return: Returns a json with API versions.
79 :rtype: :class:`flask.response`
81 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
90 "href": "http://%s:%d/v2.1/",
97 "updated": "2013-07-23T11:33:21Z"
101 """ % (self
.api
.ip
, self
.api
.port
)
103 response
= Response(resp
, status
=200, mimetype
="application/json")
104 response
.headers
['Access-Control-Allow-Origin'] = '*'
107 except Exception as ex
:
108 logging
.exception(u
"%s: Could not show list of versions." % __name__
)
109 return ex
.message
, 500
112 class NovaVersionShow(Resource
):
113 def __init__(self
, api
):
122 :return: Returns a json with API details.
123 :rtype: :class:`flask.response`
125 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
134 "href": "http://%s:%d/v2.1/",
138 "href": "http://docs.openstack.org/",
139 "rel": "describedby",
145 "base": "application/json",
146 "type": "application/vnd.openstack.compute+json;version=2.1"
151 "min_version": "2.1",
152 "updated": "2013-07-23T11:33:21Z"
155 """ % (self
.api
.ip
, self
.api
.port
)
157 response
= Response(resp
, status
=200, mimetype
="application/json")
158 response
.headers
['Access-Control-Allow-Origin'] = '*'
161 except Exception as ex
:
162 logging
.exception(u
"%s: Could not show list of versions." % __name__
)
163 return ex
.message
, 500
166 class NovaListServersApi(Resource
):
167 def __init__(self
, api
):
172 Creates a list with all running servers and their detailed information.
174 :param id: Used to create a individual link to quarry further information.
176 :return: Returns a json response with a dictionary that contains the server information.
177 :rtype: :class:`flask.response`
179 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
183 resp
['servers'] = list()
184 for server
in self
.api
.compute
.computeUnits
.values():
185 s
= server
.create_server_dict(self
.api
.compute
)
186 s
['links'] = [{'href': "http://%s:%d/v2.1/%s/servers/%s" % (self
.api
.ip
,
191 resp
['servers'].append(s
)
193 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
194 response
.headers
['Access-Control-Allow-Origin'] = '*'
197 except Exception as ex
:
198 logging
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
199 return ex
.message
, 500
203 Creates a server instance.
205 :param id: tenant id, we ignore this most of the time
207 :return: Returns a flask response, with detailed information about the just created server.
208 :rtype: :class:`flask.response`
210 logging
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
212 server_dict
= json
.loads(request
.data
)['server']
213 networks
= server_dict
.get('networks', None)
214 name
= str(self
.api
.compute
.dc
.label
) + "_man_" + server_dict
["name"][0:12]
216 if self
.api
.compute
.find_server_by_name_or_id(name
) is not None:
217 return Response("Server with name %s already exists." % name
, status
=409)
218 # TODO: not finished!
221 server
= self
.api
.compute
.create_server(name
)
222 server
.full_name
= str(self
.api
.compute
.dc
.label
) + "_man_" + server_dict
["name"]
223 server
.template_name
= server_dict
["name"]
225 for flavor
in self
.api
.compute
.flavors
.values():
226 if flavor
.id == server_dict
.get('flavorRef', ''):
227 server
.flavor
= flavor
.name
228 for image
in self
.api
.compute
.images
.values():
229 if image
.id in server_dict
['imageRef']:
230 server
.image
= image
.name
232 if networks
is not None:
234 port
= self
.api
.compute
.find_port_by_name_or_id(net
.get('port', ""))
236 server
.port_names
.append(port
.name
)
238 return Response("Currently only networking by port is supported.", status
=400)
240 self
.api
.compute
._start
_compute
(server
)
242 response
= NovaShowServerDetails(self
.api
).get(id, server
.id)
243 response
.headers
['Access-Control-Allow-Origin'] = '*'
246 except Exception as ex
:
247 logging
.exception(u
"%s: Could not create the server." % __name__
)
248 return ex
.message
, 500
251 class NovaListServersAndPortsApi(Resource
):
252 def __init__(self
, api
):
257 Creates a list with all running servers and their detailed information. This function also presents all
258 port information of each server.
260 :param id: Used to create a individual link to quarry further information.
262 :return: Returns a json response with a dictionary that contains the server information.
263 :rtype: :class:`flask.response`
265 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
269 resp
['servers'] = list()
270 for server
in self
.api
.compute
.computeUnits
.values():
271 s
= server
.create_server_dict(self
.api
.compute
)
272 s
['links'] = [{'href': "http://%s:%d/v2.1/%s/servers/%s" % (self
.api
.ip
,
278 for port_name
in server
.port_names
:
279 port
= self
.api
.compute
.find_port_by_name_or_id(port_name
)
283 tmp
= port
.create_port_dict(self
.api
.compute
)
284 tmp
['intf_name'] = port
.intf_name
285 s
['ports'].append(tmp
)
287 resp
['servers'].append(s
)
289 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
290 response
.headers
['Access-Control-Allow-Origin'] = '*'
293 except Exception as ex
:
294 logging
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
295 return ex
.message
, 500
298 class NovaListServersDetailed(Resource
):
299 def __init__(self
, api
):
304 As List Servers, it lists all running servers and their details but furthermore it also states the
305 used flavor and the server image.
307 :param id: tenant id, used for the 'href' link.
309 :return: Returns a flask response, with detailed information aboit the servers and their flavor and image.
310 :rtype: :class:`flask.response`
312 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
315 resp
= {"servers": list()}
316 for server
in self
.api
.compute
.computeUnits
.values():
317 s
= server
.create_server_dict(self
.api
.compute
)
318 s
['links'] = [{'href': "http://%s:%d/v2.1/%s/servers/%s" % (self
.api
.ip
,
322 flavor
= self
.api
.compute
.flavors
[server
.flavor
]
327 "href": "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
335 image
= self
.api
.compute
.images
[server
.image
]
340 "href": "http://%s:%d/v2.1/%s/images/%s" % (self
.api
.ip
,
349 resp
['servers'].append(s
)
351 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
352 response
.headers
['Access-Control-Allow-Origin'] = '*'
355 except Exception as ex
:
356 logging
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
357 return ex
.message
, 500
360 class NovaListFlavors(Resource
):
361 def __init__(self
, api
):
366 Lists all available flavors.
368 :param id: tenant id, used for the 'href' link
370 :return: Returns a flask response with a list of all flavors.
371 :rtype: :class:`flask.response`
373 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
376 resp
['flavors'] = list()
377 for flavor
in self
.api
.compute
.flavors
.values():
378 f
= flavor
.__dict
__.copy()
380 f
['name'] = flavor
.name
381 f
['links'] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
385 resp
['flavors'].append(f
)
387 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
388 response
.headers
['Access-Control-Allow-Origin'] = '*'
391 except Exception as ex
:
392 logging
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
393 return ex
.message
, 500
396 logging
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
397 data
= json
.loads(request
.data
).get("flavor")
398 logging
.warning("Create Flavor: %s" % str(data
))
399 # add to internal dict
400 f
= self
.api
.compute
.add_flavor(
403 data
.get("ram"), "MB",
404 data
.get("disk"), "GB")
405 # create response based on incoming data
407 data
["links"] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
411 resp
= {"flavor": data
}
412 return Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
415 class NovaListFlavorsDetails(Resource
):
416 def __init__(self
, api
):
421 Lists all flavors with additional information like ram and disk space.
423 :param id: tenant id, used for the 'href' link
425 :return: Returns a flask response with a list of all flavors with additional information.
426 :rtype: :class:`flask.response`
428 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
431 resp
['flavors'] = list()
432 for flavor
in self
.api
.compute
.flavors
.values():
433 # use the class dict. it should work fine
434 # but use a copy so we don't modifiy the original
435 f
= flavor
.__dict
__.copy()
436 # add additional expected stuff stay openstack compatible
437 f
['links'] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
441 f
['OS-FLV-DISABLED:disabled'] = False
442 f
['OS-FLV-EXT-DATA:ephemeral'] = 0
443 f
['os-flavor-access:is_public'] = True
444 f
['ram'] = flavor
.memory
445 f
['vcpus'] = flavor
.cpu
447 f
['disk'] = flavor
.storage
448 f
['rxtx_factor'] = 1.0
449 resp
['flavors'].append(f
)
451 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
452 response
.headers
['Access-Control-Allow-Origin'] = '*'
455 except Exception as ex
:
456 logging
.exception(u
"%s: Could not retrieve the list of servers." % __name__
)
457 return ex
.message
, 500
460 logging
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
461 data
= json
.loads(request
.data
).get("flavor")
462 logging
.warning("Create Flavor: %s" % str(data
))
463 # add to internal dict
464 f
= self
.api
.compute
.add_flavor(
467 data
.get("ram"), "MB",
468 data
.get("disk"), "GB")
469 # create response based on incoming data
471 data
["links"] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
475 resp
= {"flavor": data
}
476 return Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
479 class NovaListFlavorById(Resource
):
480 def __init__(self
, api
):
483 def get(self
, id, flavorid
):
485 Returns details about one flavor.
487 :param id: tenant id, used for the 'href' link
489 :param flavorid: Represents the flavor.
490 :type flavorid: ``str``
491 :return: Returns a flask response with detailed information about the flavor.
492 :rtype: :class:`flask.response`
494 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
497 resp
['flavor'] = dict()
498 flavor
= self
.api
.compute
.flavors
.get(flavorid
, None)
500 for f
in self
.api
.compute
.flavors
.values():
504 resp
['flavor']['id'] = flavor
.id
505 resp
['flavor']['name'] = flavor
.name
506 resp
['flavor']['links'] = [{'href': "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
510 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
511 response
.headers
['Access-Control-Allow-Origin'] = '*'
514 except Exception as ex
:
515 logging
.exception(u
"%s: Could not retrieve flavor with id %s" % (__name__
, flavorid
))
516 return ex
.message
, 500
519 class NovaListImages(Resource
):
520 def __init__(self
, api
):
525 Creates a list of all usable images.
527 :param id: tenant id, used for the 'href' link
529 :return: Returns a flask response with a list of available images.
530 :rtype: :class:`flask.response`
532 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
535 resp
['images'] = list()
536 for image
in self
.api
.compute
.images
.values():
539 f
['name'] = str(image
.name
).replace(":latest", "")
540 f
['links'] = [{'href': "http://%s:%d/v2.1/%s/images/%s" % (self
.api
.ip
,
544 resp
['images'].append(f
)
545 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
546 response
.headers
['Access-Control-Allow-Origin'] = '*'
549 except Exception as ex
:
550 logging
.exception(u
"%s: Could not retrieve the list of images." % __name__
)
551 return ex
.message
, 500
554 class NovaListImagesDetails(Resource
):
555 def __init__(self
, api
):
560 As List Images but with additional metadata.
562 :param id: tenant id, used for the 'href' link
564 :return: Returns a flask response with a list of images and their metadata.
565 :rtype: :class:`flask.response`
567 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
570 resp
['images'] = list()
571 for image
in self
.api
.compute
.images
.values():
572 # use the class dict. it should work fine
573 # but use a copy so we don't modifiy the original
574 f
= image
.__dict
__.copy()
575 # add additional expected stuff stay openstack compatible
576 f
['name'] = str(image
.name
).replace(":latest", "")
577 f
['links'] = [{'href': "http://%s:%d/v2.1/%s/images/%s" % (self
.api
.ip
,
582 "architecture": "x86_64",
583 "auto_disk_config": "True",
584 "kernel_id": "nokernel",
585 "ramdisk_id": "nokernel"
587 resp
['images'].append(f
)
589 response
= Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
590 response
.headers
['Access-Control-Allow-Origin'] = '*'
593 except Exception as ex
:
594 logging
.exception(u
"%s: Could not retrieve the list of images." % __name__
)
595 return ex
.message
, 500
598 class NovaListImageById(Resource
):
599 def __init__(self
, api
):
602 def get(self
, id, imageid
):
604 Gets an image by id from the emulator with openstack nova compliant return values.
606 :param id: tenantid, we ignore this most of the time
608 :param imageid: id of the image. If it is 1 the dummy CREATE-IMAGE is returned
609 :type imageid: ``str``
610 :return: Returns a flask response with the information about one image.
611 :rtype: :class:`flask.response`
613 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
616 i
= resp
['image'] = dict()
617 for image
in self
.api
.compute
.images
.values():
618 if image
.id == imageid
or image
.name
== imageid
:
620 i
['name'] = image
.name
622 return Response(json
.dumps(resp
), status
=200, mimetype
="application/json")
624 response
= Response("Image with id or name %s does not exists." % imageid
, status
=404)
625 response
.headers
['Access-Control-Allow-Origin'] = '*'
628 except Exception as ex
:
629 logging
.exception(u
"%s: Could not retrieve image with id %s." % (__name__
, imageid
))
630 return ex
.message
, 500
633 class NovaShowServerDetails(Resource
):
634 def __init__(self
, api
):
637 def get(self
, id, serverid
):
639 Returns detailed information about the specified server.
641 :param id: tenant id, used for the 'href' link
643 :param serverid: Specifies the requested server.
644 :type serverid: ``str``
645 :return: Returns a flask response with details about the server.
646 :rtype: :class:`flask.response`
648 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
650 server
= self
.api
.compute
.find_server_by_name_or_id(serverid
)
652 return Response("Server with id or name %s does not exists." % serverid
, status
=404)
653 s
= server
.create_server_dict()
654 s
['links'] = [{'href': "http://%s:%d/v2.1/%s/servers/%s" % (self
.api
.ip
,
659 flavor
= self
.api
.compute
.flavors
[server
.flavor
]
664 "href": "http://%s:%d/v2.1/%s/flavors/%s" % (self
.api
.ip
,
672 image
= self
.api
.compute
.images
[server
.image
]
677 "href": "http://%s:%d/v2.1/%s/images/%s" % (self
.api
.ip
,
686 response
= Response(json
.dumps({'server': s
}), status
=200, mimetype
="application/json")
687 response
.headers
['Access-Control-Allow-Origin'] = '*'
690 except Exception as ex
:
691 logging
.exception(u
"%s: Could not retrieve the server details." % __name__
)
692 return ex
.message
, 500
694 def delete(self
, id, serverid
):
696 Delete a server instance.
698 :param id: tenant id, we ignore this most of the time
700 :param serverid: The UUID of the server
701 :type serverid: ``str``
702 :return: Returns 200 if everything is fine.
703 :rtype: :class:`flask.response`
705 logging
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
707 server
= self
.api
.compute
.find_server_by_name_or_id(serverid
)
709 return Response('Could not find server.', status
=404, mimetype
="application/json")
711 self
.api
.compute
.stop_compute(server
)
713 response
= Response('Server deleted.', status
=204, mimetype
="application/json")
714 response
.headers
['Access-Control-Allow-Origin'] = '*'
717 except Exception as ex
:
718 logging
.exception(u
"%s: Could not create the server." % __name__
)
719 return ex
.message
, 500
722 class NovaInterfaceToServer(Resource
):
723 def __init__(self
, api
):
726 def post(self
, id, serverid
):
728 Add an interface to the specified server.
730 :param id: tenant id, we ignore this most of the time
732 :param serverid: Specifies the server.
733 :type serverid: ``str``
734 :return: Returns a flask response with information about the attached interface.
735 :rtype: :class:`flask.response`
737 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
739 server
= self
.api
.compute
.find_server_by_name_or_id(serverid
)
741 return Response("Server with id or name %s does not exists." % serverid
, status
=404)
743 if server
.emulator_compute
is None:
744 logging
.error("The targeted container does not exist.")
745 return Response("The targeted container of %s does not exist." % serverid
, status
=404)
746 data
= json
.loads(request
.data
).get("interfaceAttachment")
748 port
= data
.get("port_id", None)
749 net
= data
.get("net_id", None)
750 dc
= self
.api
.compute
.dc
751 network_dict
= dict()
754 if net
is not None and port
is not None:
755 port
= self
.api
.compute
.find_port_by_name_or_id(port
)
756 network
= self
.api
.compute
.find_network_by_name_or_id(net
)
757 network_dict
['id'] = port
.intf_name
758 network_dict
['ip'] = port
.ip_address
759 network_dict
[network_dict
['id']] = network
.name
760 elif net
is not None:
761 network
= self
.api
.compute
.find_network_by_name_or_id(net
)
763 return Response("Network with id or name %s does not exists." % net
, status
=404)
764 port
= self
.api
.compute
.create_port("port:cp%s:fl:%s" %
765 (len(self
.api
.compute
.ports
), str(uuid
.uuid4())))
767 port
.net_name
= network
.name
768 port
.ip_address
= network
.get_new_ip_address(port
.name
)
769 network_dict
['id'] = port
.intf_name
770 network_dict
['ip'] = port
.ip_address
771 network_dict
[network_dict
['id']] = network
.name
772 elif port
is not None:
773 port
= self
.api
.compute
.find_port_by_name_or_id(port
)
774 network_dict
['id'] = port
.intf_name
775 network_dict
['ip'] = port
.ip_address
776 network
= self
.api
.compute
.find_network_by_name_or_id(port
.net_name
)
777 network_dict
[network_dict
['id']] = network
.name
779 raise Exception("You can only attach interfaces by port or network at the moment")
781 if network
== self
.api
.manage
.floating_network
:
782 dc
.net
.addLink(server
.emulator_compute
, self
.api
.manage
.floating_switch
,
783 params1
=network_dict
, cls
=Link
, intfName1
=port
.intf_name
)
785 dc
.net
.addLink(server
.emulator_compute
, dc
.switch
,
786 params1
=network_dict
, cls
=Link
, intfName1
=port
.intf_name
)
787 resp
["port_state"] = "ACTIVE"
788 resp
["port_id"] = port
.id
789 resp
["net_id"] = self
.api
.compute
.find_network_by_name_or_id(port
.net_name
).id
790 resp
["mac_addr"] = port
.mac_address
791 resp
["fixed_ips"] = list()
793 fixed_ips
["ip_address"] = port
.ip_address
794 fixed_ips
["subnet_id"] = network
.subnet_name
795 resp
["fixed_ips"].append(fixed_ips
)
796 response
= Response(json
.dumps({"interfaceAttachment": resp
}), status
=202, mimetype
="application/json")
797 response
.headers
['Access-Control-Allow-Origin'] = '*'
800 except Exception as ex
:
801 logging
.exception(u
"%s: Could not add interface to the server." % __name__
)
802 return ex
.message
, 500
805 class NovaShowAndDeleteInterfaceAtServer(Resource
):
806 def __init__(self
, api
):
809 def delete(self
, id, serverid
, port_id
):
811 Deletes an existing interface.
813 :param id: tenant id, we ignore this most of the time
815 :param serverid: Specifies the server, where the interface will be deleted.
816 :type serverid: ``str``
817 :param port_id: Specifies the port of the interface.
818 :type port_id: ``str``
819 :return: Returns a flask response with 202 if everything worked out. Otherwise it will return 404 and an
821 :rtype: :class:`flask.response`
823 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
825 server
= self
.api
.compute
.find_server_by_name_or_id(serverid
)
827 return Response("Server with id or name %s does not exists." % serverid
, status
=404)
828 port
= self
.api
.compute
.find_port_by_name_or_id(port_id
)
830 return Response("Port with id or name %s does not exists." % port_id
, status
=404)
832 for link
in self
.api
.compute
.dc
.net
.links
:
833 if str(link
.intf1
) == port
.intf_name
and \
834 str(link
.intf1
.ip
) == port
.ip_address
.split('/')[0]:
835 self
.api
.compute
.dc
.net
.removeLink(link
)
838 response
= Response("", status
=202, mimetype
="application/json")
839 response
.headers
['Access-Control-Allow-Origin'] = '*'
842 except Exception as ex
:
843 logging
.exception(u
"%s: Could not detach interface from the server." % __name__
)
844 return ex
.message
, 500