Manually added OpenStack API code
[osm/vim-emu.git] / src / emuvim / api / openstack / monitor_api.py
1 from flask_restful import Resource
2 from flask import Response, request
3 from emuvim.api.openstack.openstack_dummies.base_openstack_dummy import BaseOpenstackDummy
4 import emuvim.api.openstack.docker_util as DockerUtil
5 import logging
6 import json
7 import time
8
9
10 class MonitorDummyApi(BaseOpenstackDummy):
11 def __init__(self, inc_ip, inc_port):
12 super(MonitorDummyApi, self).__init__(inc_ip, inc_port)
13
14 self.api.add_resource(MonitorVersionsList, "/",
15 resource_class_kwargs={'api': self})
16 self.api.add_resource(MonitorVnf, "/v1/monitor/<vnf_name>",
17 resource_class_kwargs={'api': self})
18 self.api.add_resource(MonitorVnfAbs, "/v1/monitor/abs/<vnf_name>",
19 resource_class_kwargs={'api': self})
20 self.api.add_resource(MonitorVnfDcStack, "/v1/monitor/<dc>/<stack>/<vnf_name>",
21 resource_class_kwargs={'api': self})
22 self.api.add_resource(Shutdown, "/shutdown")
23
24 def _start_flask(self):
25 logging.info("Starting %s endpoint @ http://%s:%d" % ("MonitorDummyApi", self.ip, self.port))
26 if self.app is not None:
27 self.app.run(self.ip, self.port, debug=True, use_reloader=False, threaded=True)
28
29
30 class Shutdown(Resource):
31 """
32 A get request to /shutdown will shut down this endpoint.
33 """
34
35 def get(self):
36 logging.debug(("%s is beeing shut down") % (__name__))
37 func = request.environ.get('werkzeug.server.shutdown')
38 if func is None:
39 raise RuntimeError('Not running with the Werkzeug Server')
40 func()
41
42
43 class MonitorVersionsList(Resource):
44 def __init__(self, api):
45 self.api = api
46
47
48 def get(self):
49 """
50 List API versions.
51
52 :return: Returns the api versions.
53 :rtype: :class:`flask.response`
54 """
55 logging.debug("API CALL: %s GET" % str(self.__class__.__name__))
56
57 # at least let it look like an open stack function
58 try:
59 resp = dict()
60 resp['versions'] = dict()
61 resp['versions'] = [{
62 "id": "v1",
63 "links": [{
64 "href": "http://%s:%d/v1/" % (self.api.ip, self.api.port),
65 "rel": "self"
66 }],
67 "status": "CURRENT",
68 "version": "1",
69 "min_version": "1",
70 "updated": "2013-07-23T11:33:21Z"
71 }]
72
73 return Response(json.dumps(resp), status=200, mimetype="application/json")
74
75 except Exception as ex:
76 logging.exception(u"%s: Could not show list of versions." % __name__)
77 return ex.message, 500
78
79
80 class MonitorVnf(Resource):
81 def __init__(self, api):
82 self.api = api
83
84 def get(self, vnf_name):
85 """
86 Calculates the workload for the specified docker container. Requires at least one second, to calculate
87 the network traffic and cpu usage over time.
88
89 :param vnf_name: Specifies the docker container via name.
90 :type vnf_name: ``str``
91 :return: Returns a json response with network, cpu and memory usage over time, and specifies the storage
92 access, the number of running processes and the current system time.
93 :rtype: :class:`flask.response`
94 """
95 logging.debug("API CALL: %s GET" % str(self.__class__.__name__))
96 if len(vnf_name) < 3 or 'mn.' != vnf_name[:3]:
97 vnf_name = 'mn.' + vnf_name
98
99 found = False
100 from emuvim.api.heat.openstack_api_endpoint import OpenstackApiEndpoint
101 for api in OpenstackApiEndpoint.dc_apis:
102 if vnf_name[3:] in api.compute.dc.net:
103 found = True
104 break
105
106 if not found:
107 return Response(u"MonitorAPI: VNF %s does not exist.\n" % (vnf_name[3:]),
108 status=500,
109 mimetype="application/json")
110 try:
111 docker_id = DockerUtil.docker_container_id(vnf_name)
112 out_dict = dict()
113 out_dict.update(DockerUtil.monitoring_over_time(docker_id))
114 out_dict.update(DockerUtil.docker_mem(docker_id))
115 out_dict.update(DockerUtil.docker_PIDS(docker_id))
116 out_dict['SYS_time'] = int(time.time() * 1000000000)
117
118 response = Response(json.dumps(out_dict) + '\n', status=200, mimetype="application/json")
119 response.headers['Access-Control-Allow-Origin'] = '*'
120 return response
121 except Exception as e:
122 logging.exception(u"%s: Error getting monitoring information.\n %s" % (__name__, e))
123 return Response(u"Error getting monitoring information.\n", status=500, mimetype="application/json")
124
125
126 class MonitorVnfAbs(Resource):
127 def __init__(self, api):
128 self.api = api
129
130 def get(self, vnf_name):
131 """
132 Calculates the workload for the specified docker container, at this point in time.
133
134 :param vnf_name: Specifies the docker container via name.
135 :type vnf_name: ``str``
136 :return: Returns a json response with network, cpu, memory usage and storage access, as absolute values from
137 startup till this point of time. It also contains the number of running processes and the current
138 system time.
139 :rtype: :class:`flask.response`
140 """
141 logging.debug("API CALL: %s GET" % str(self.__class__.__name__))
142 if len(vnf_name) < 3 or 'mn.' != vnf_name[:3]:
143 vnf_name = 'mn.' + vnf_name
144
145 found = False
146 from emuvim.api.heat.openstack_api_endpoint import OpenstackApiEndpoint
147 for api in OpenstackApiEndpoint.dc_apis:
148 if vnf_name[3:] in api.compute.dc.net:
149 found = True
150 break
151 if not found:
152 return Response(u"MonitorAPI: VNF %s does not exist\n" % vnf_name[3:],
153 status=500,
154 mimetype="application/json")
155 try:
156 docker_id = DockerUtil.docker_container_id(vnf_name)
157 out_dict = dict()
158 out_dict.update(DockerUtil.docker_abs_cpu(docker_id))
159 out_dict.update(DockerUtil.docker_mem(docker_id))
160 out_dict.update(DockerUtil.docker_abs_net_io(docker_id))
161 out_dict.update(DockerUtil.docker_block_rw(docker_id))
162 out_dict.update(DockerUtil.docker_PIDS(docker_id))
163 out_dict['SYS_time'] = int(time.time() * 1000000000)
164
165 response = Response(json.dumps(out_dict) + '\n', status=200, mimetype="application/json")
166 response.headers['Access-Control-Allow-Origin'] = '*'
167 return response
168 except Exception as e:
169 logging.exception(u"%s: Error getting monitoring information.\n %s" % (__name__, e))
170 return Response(u"Error getting monitoring information.\n", status=500, mimetype="application/json")
171
172
173 class MonitorVnfDcStack(Resource):
174 def __init__(self, api):
175 self.api = api
176
177 def get(self, dc, stack, vnf_name):
178 """
179 Calculates the workload for the specified docker container, at this point in time.
180 This api call is for the translator to monitor a vnfs of a specific datacenter and stack.
181
182 :param dc: Target datacenter.
183 :type dc: ``str``
184 :param stack: Target stack
185 :type stack: ``str``
186 :param vnf_name: Specifies the docker container via name.
187 :type vnf_name: ``str``
188 :return: Returns a json response with network, cpu, memory usage and storage access, as absolute values from
189 startup till this point of time. It also contains the number of running processes and the current
190 system time.
191 :rtype: :class:`flask.response`
192 """
193 logging.debug("API CALL: %s GET" % str(self.__class__.__name__))
194
195 # search for real name
196 vnf_name = self._findName(dc, stack, vnf_name)
197
198 if type(vnf_name) is not str:
199 # something went wrong, vnf_name is a Response object
200 return vnf_name
201
202 try:
203 docker_id = DockerUtil.docker_container_id(vnf_name)
204 out_dict = dict()
205 out_dict.update(DockerUtil.monitoring_over_time(docker_id))
206 out_dict.update(DockerUtil.docker_mem(docker_id))
207 out_dict.update(DockerUtil.docker_PIDS(docker_id))
208 out_dict['SYS_time'] = int(time.time() * 1000000000)
209
210 response = Response(json.dumps(out_dict) + '\n', status=200, mimetype="application/json")
211 response.headers['Access-Control-Allow-Origin'] = '*'
212 return response
213 except Exception as e:
214 logging.exception(u"%s: Error getting monitoring information.\n %s" % (__name__, e))
215 return Response(u"Error getting monitoring information.\n", status=500, mimetype="application/json")
216
217 # Tries to find real container name according to heat template names
218 # Returns a string or a Response object
219 def _findName(self, dc, stack, vnf):
220 dc_real = None
221 from emuvim.api.heat.openstack_api_endpoint import OpenstackApiEndpoint
222 for api in OpenstackApiEndpoint.dc_apis:
223 # search for datacenters
224 if dc in api.manage.net.dcs:
225 dc_real = api.manage.net.dcs[dc]
226 break
227 if dc_real is None:
228 return Response(u"DC %s does not exist\n" % (dc), status=500, mimetype="application/json")
229
230 # search for related OpenStackAPIs
231 api_real = None
232 for api in OpenstackApiEndpoint.dc_apis:
233 if api.compute.dc == dc_real:
234 api_real = api
235 if api_real is None:
236 return Response(u"OpenStackAPI does not exist\n", status=500, mimetype="application/json")
237 # search for stacks
238 stack_real = None
239 for stackObj in api_real.compute.stacks.values():
240 if stackObj.stack_name == stack:
241 stack_real = stackObj
242 if stack_real is None:
243 return Response(u"Stack %s does not exist\n" % (stack), status=500, mimetype="application/json")
244 # search for servers
245 server_real = None
246 for server in stack_real.servers.values():
247 if server.template_name == vnf:
248 server_real = server
249 break
250 if server_real is None:
251 return Response(u"VNF %s does not exist\n" % (vnf), status=500, mimetype="application/json")
252 container_real = 'mn.' + server_real.name
253 return container_real