Fixed missing license headers
[osm/vim-emu.git] / src / emuvim / api / openstack / openstack_dummies / keystone_dummy_api.py
1 """
2 Copyright (c) 2017 SONATA-NFV and Paderborn University
3 ALL RIGHTS RESERVED.
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 Neither the name of the SONATA-NFV, Paderborn University
18 nor the names of its contributors may be used to endorse or promote
19 products derived from this software without specific prior written
20 permission.
21
22 This work has been performed in the framework of the SONATA project,
23 funded by the European Commission under Grant number 671517 through
24 the Horizon 2020 and 5G-PPP programmes. The authors would like to
25 acknowledge the contributions of their colleagues of the SONATA
26 partner consortium (www.sonata-nfv.eu).
27 """
28 from flask_restful import Resource
29 from flask import request, Response
30 from emuvim.api.openstack.openstack_dummies.base_openstack_dummy import BaseOpenstackDummy
31 from emuvim.api.openstack.helper import get_host
32 import logging
33 import json
34
35 LOG = logging.getLogger("api.openstack.keystone")
36
37
38 class KeystoneDummyApi(BaseOpenstackDummy):
39 def __init__(self, in_ip, in_port):
40 super(KeystoneDummyApi, self).__init__(in_ip, in_port)
41
42 self.api.add_resource(KeystoneListVersions, "/", resource_class_kwargs={'api': self})
43 self.api.add_resource(Shutdown, "/shutdown")
44 self.api.add_resource(KeystoneShowAPIv2, "/v2.0", resource_class_kwargs={'api': self})
45 self.api.add_resource(KeystoneGetToken, "/v2.0/tokens", resource_class_kwargs={'api': self})
46 self.api.add_resource(KeystoneShowAPIv3, "/v3.0", resource_class_kwargs={'api': self})
47 self.api.add_resource(KeystoneGetTokenv3, "/v3.0/auth/tokens", resource_class_kwargs={'api': self})
48
49 def _start_flask(self):
50 LOG.info("Starting %s endpoint @ http://%s:%d" % (__name__, self.ip, self.port))
51 if self.app is not None:
52 self.app.before_request(self.dump_playbook)
53 self.app.run(self.ip, self.port, debug=True, use_reloader=False)
54
55
56 class Shutdown(Resource):
57 """
58 A get request to /shutdown will shut down this endpoint.
59 """
60
61 def get(self):
62 LOG.debug(("%s is beeing shut down") % (__name__))
63 func = request.environ.get('werkzeug.server.shutdown')
64 if func is None:
65 raise RuntimeError('Not running with the Werkzeug Server')
66 func()
67
68
69 class KeystoneListVersions(Resource):
70 """
71 List all known keystone versions.
72 Hardcoded for our version!
73 """
74
75 def __init__(self, api):
76 self.api = api
77
78 def get(self):
79 """
80 List API versions.
81
82 :return: Returns the api versions.
83 :rtype: :class:`flask.response` containing a static json encoded dict.
84 """
85 LOG.debug("API CALL: %s GET" % str(self.__class__.__name__))
86 resp = dict()
87 resp['versions'] = dict()
88
89 version = [{
90 "id": "v2.0",
91 "links": [
92 {
93 "href": "http://%s:%d/v2.0" % (get_host(request), self.api.port),
94 "rel": "self"
95 }
96 ],
97 "media-types": [
98 {
99 "base": "application/json",
100 "type": "application/vnd.openstack.identity-v2.0+json"
101 }
102 ],
103 "status": "stable",
104 "updated": "2014-04-17T00:00:00Z"
105 }]
106 resp['versions']['values'] = version
107
108 return Response(json.dumps(resp), status=200, mimetype='application/json')
109
110
111 class KeystoneShowAPIv2(Resource):
112 """
113 Entrypoint for all openstack clients.
114 This returns all current entrypoints running on son-emu.
115 """
116
117 def __init__(self, api):
118 self.api = api
119
120 def get(self):
121 """
122 List API entrypoints.
123
124 :return: Returns an openstack style response for all entrypoints.
125 :rtype: :class:`flask.response`
126 """
127 LOG.debug("API CALL: %s GET" % str(self.__class__.__name__))
128
129 neutron_port = self.api.port + 4696
130 heat_port = self.api.port + 3004
131
132 resp = dict()
133 resp['version'] = {
134 "status": "stable",
135 "media-types": [
136 {
137 "base": "application/json",
138 "type": "application/vnd.openstack.identity-v2.0+json"
139 }
140 ],
141 "id": "v2.0",
142 "links": [
143 {
144 "href": "http://%s:%d/v2.0" % (get_host(request), self.api.port),
145 "rel": "self"
146 }
147 ]
148 }
149 LOG.debug(json.dumps(resp))
150 return Response(json.dumps(resp), status=200, mimetype='application/json')
151
152
153 class KeystoneShowAPIv3(Resource):
154 """
155 Entrypoint for all openstack clients.
156 This returns all current entrypoints running on son-emu.
157 """
158
159 def __init__(self, api):
160 self.api = api
161
162 def get(self):
163 """
164 List API entrypoints.
165
166 :return: Returns an openstack style response for all entrypoints.
167 :rtype: :class:`flask.response`
168 """
169 LOG.debug("API CALL: %s GET" % str(self.__class__.__name__))
170
171 neutron_port = self.api.port + 4696
172 heat_port = self.api.port + 3004
173
174 resp = dict()
175 resp['version'] = {
176 "status": "stable",
177 "media-types": [
178 {
179 "base": "application/json",
180 "type": "application/vnd.openstack.identity-v3.0+json"
181 }
182 ],
183 "id": "v3.0",
184 "links": [
185 {
186 "href": "http://%s:%d/v3.0" % (get_host(request), self.api.port),
187 "rel": "self"
188 }
189 ]
190 }
191
192 return Response(json.dumps(resp), status=200, mimetype='application/json')
193
194
195 class KeystoneGetToken(Resource):
196 """
197 Returns a static keystone token.
198 We don't do any validation so we don't care.
199 """
200
201 def __init__(self, api):
202 self.api = api
203
204 def post(self):
205 """
206 List API entrypoints.
207
208 This is hardcoded. For a working "authentication" use these ENVVARS:
209
210 * OS_AUTH_URL=http://<ip>:<port>/v2.0
211 * OS_IDENTITY_API_VERSION=2.0
212 * OS_TENANT_ID=fc394f2ab2df4114bde39905f800dc57
213 * OS_REGION_NAME=RegionOne
214 * OS_USERNAME=bla
215 * OS_PASSWORD=bla
216
217 :return: Returns an openstack style response for all entrypoints.
218 :rtype: :class:`flask.response`
219 """
220
221 LOG.debug("API CALL: %s POST" % str(self.__class__.__name__))
222 try:
223 ret = dict()
224 req = json.loads(request.data)
225 ret['access'] = dict()
226 ret['access']['token'] = dict()
227 token = ret['access']['token']
228
229 token['issued_at'] = "2014-01-30T15:30:58.819Z"
230 token['expires'] = "2999-01-30T15:30:58.819Z"
231 token['id'] = req['auth'].get('token', {'id': 'fc394f2ab2df4114bde39905f800dc57'}).get('id')
232 token['tenant'] = dict()
233 token['tenant']['description'] = None
234 token['tenant']['enabled'] = True
235 token['tenant']['id'] = req['auth'].get('tenantId', 'fc394f2ab2df4114bde39905f800dc57')
236 token['tenant']['name'] = "tenantName"
237
238 ret['access']['user'] = dict()
239 user = ret['access']['user']
240 user['username'] = req.get('username', "username")
241 user['name'] = "tenantName"
242 user['roles_links'] = list()
243 user['id'] = token['tenant'].get('id', "fc394f2ab2df4114bde39905f800dc57")
244 user['roles'] = [{'name': 'Member'}]
245
246 ret['access']['region_name'] = "RegionOne"
247
248 ret['access']['serviceCatalog'] = [{
249 "endpoints": [
250 {
251 "adminURL": "http://%s:%s/v2.1/%s" % (get_host(request), self.api.port + 3774, user['id']),
252 "region": "RegionOne",
253 "internalURL": "http://%s:%s/v2.1/%s" % (get_host(request), self.api.port + 3774, user['id']),
254 "id": "2dad48f09e2a447a9bf852bcd93548ef",
255 "publicURL": "http://%s:%s/v2.1/%s" % (get_host(request), self.api.port + 3774, user['id'])
256 }
257 ],
258 "endpoints_links": [],
259 "type": "compute",
260 "name": "nova"
261 },
262 {
263 "endpoints": [
264 {
265 "adminURL": "http://%s:%s/v2.0" % (get_host(request), self.api.port),
266 "region": "RegionOne",
267 "internalURL": "http://%s:%s/v2.0" % (get_host(request), self.api.port),
268 "id": "2dad48f09e2a447a9bf852bcd93543fc",
269 "publicURL": "http://%s:%s/v2" % (get_host(request), self.api.port)
270 }
271 ],
272 "endpoints_links": [],
273 "type": "identity",
274 "name": "keystone"
275 },
276 {
277 "endpoints": [
278 {
279 "adminURL": "http://%s:%s" % (get_host(request), self.api.port + 4696),
280 "region": "RegionOne",
281 "internalURL": "http://%s:%s" % (get_host(request), self.api.port + 4696),
282 "id": "2dad48f09e2a447a9bf852bcd93548cf",
283 "publicURL": "http://%s:%s" % (get_host(request), self.api.port + 4696)
284 }
285 ],
286 "endpoints_links": [],
287 "type": "network",
288 "name": "neutron"
289 },
290 {
291 "endpoints": [
292 {
293 "adminURL": "http://%s:%s" % (get_host(request), self.api.port + 4242),
294 "region": "RegionOne",
295 "internalURL": "http://%s:%s" % (get_host(request), self.api.port + 4242),
296 "id": "2dad48f09e2a447a9bf852bcd93548cf",
297 "publicURL": "http://%s:%s" % (get_host(request), self.api.port + 4242)
298 }
299 ],
300 "endpoints_links": [],
301 "type": "image",
302 "name": "glance"
303 },
304 {
305 "endpoints": [
306 {
307 "adminURL": "http://%s:%s/v1/%s" % (get_host(request), self.api.port + 3004, user['id']),
308 "region": "RegionOne",
309 "internalURL": "http://%s:%s/v1/%s" % (get_host(request), self.api.port + 3004, user['id']),
310 "id": "2dad48f09e2a447a9bf852bcd93548bf",
311 "publicURL": "http://%s:%s/v1/%s" % (get_host(request), self.api.port + 3004, user['id'])
312 }
313 ],
314 "endpoints_links": [],
315 "type": "orchestration",
316 "name": "heat"
317 }
318 ]
319
320 ret['access']["metadata"] = {
321 "is_admin": 0,
322 "roles": [
323 "7598ac3c634d4c3da4b9126a5f67ca2b"
324 ]
325 },
326 ret['access']['trust'] = {
327 "id": "394998fa61f14736b1f0c1f322882949",
328 "trustee_user_id": "269348fdd9374b8885da1418e0730af1",
329 "trustor_user_id": "3ec3164f750146be97f21559ee4d9c51",
330 "impersonation": False
331 }
332 return Response(json.dumps(ret), status=200, mimetype='application/json')
333
334 except Exception as ex:
335 logging.exception("Keystone: Get token failed.")
336 return ex.message, 500
337
338 class KeystoneGetTokenv3(Resource):
339 """
340 Returns a static keystone token.
341 We don't do any validation so we don't care.
342 """
343
344 def __init__(self, api):
345 self.api = api
346
347 def post(self):
348 """
349 List API entrypoints.
350
351 This is hardcoded. For a working "authentication" use these ENVVARS:
352
353 * OS_AUTH_URL=http://<ip>:<port>/v3
354 * OS_IDENTITY_API_VERSION=2.0
355 * OS_TENANT_ID=fc394f2ab2df4114bde39905f800dc57
356 * OS_REGION_NAME=RegionOne
357 * OS_USERNAME=bla
358 * OS_PASSWORD=bla
359
360 :return: Returns an openstack style response for all entrypoints.
361 :rtype: :class:`flask.response`
362 """
363
364 LOG.debug("API CALL: %s POST" % str(self.__class__.__name__))
365 try:
366 ret = dict()
367 req = json.loads(request.data)
368 ret['token'] = dict()
369 token = ret['token']
370
371 token['issued_at'] = "2014-01-30T15:30:58.819Z"
372 token['expires_at'] = "2999-01-30T15:30:58.819Z"
373 token['methods'] = ["password"]
374 token['extras'] = dict()
375 token['user'] = dict()
376 user = token['user']
377 user['id'] = req['auth'].get('token', {'id': 'fc394f2ab2df4114bde39905f800dc57'}).get('id')
378 user['name'] = "tenantName"
379 user['password_expires_at'] = None
380 user['domain'] = {"id": "default", "name": "Default"}
381 token['audit_ids'] = ["ZzZwkUflQfygX7pdYDBCQQ"]
382
383 # project
384 token['project'] = {
385 "domain": {
386 "id" : "default",
387 "name": "Default"
388 },
389 "id": "8538a3f13f9541b28c2620eb19065e45",
390 "name": "tenantName"
391 }
392
393 # catalog
394 token['catalog'] = [{
395 "endpoints": [
396 {
397 "url": "http://%s:%s/v2.1/%s" % (get_host(request), self.api.port + 3774, user['id']),
398 "region": "RegionOne",
399 "interface": "public",
400 "id": "2dad48f09e2a447a9bf852bcd93548ef"
401 }
402 ],
403 "id": "2dad48f09e2a447a9bf852bcd93548ef",
404 "type": "compute",
405 "name": "nova"
406 },
407 {
408 "endpoints": [
409 {
410 "url": "http://%s:%s/v2.0" % (get_host(request), self.api.port),
411 "region": "RegionOne",
412 "interface": "public",
413 "id": "2dad48f09e2a447a9bf852bcd93543fc"
414 }
415 ],
416 "id": "2dad48f09e2a447a9bf852bcd93543fc",
417 "type": "identity",
418 "name": "keystone"
419 },
420 {
421 "endpoints": [
422 {
423 "url": "http://%s:%s" % (get_host(request), self.api.port + 4696),
424 "region": "RegionOne",
425 "interface": "public",
426 "id": "2dad48f09e2a447a9bf852bcd93548cf"
427 }
428 ],
429 "id": "2dad48f09e2a447a9bf852bcd93548cf",
430 "type": "network",
431 "name": "neutron"
432 },
433 {
434 "endpoints": [
435 {
436 "url": "http://%s:%s" % (get_host(request), self.api.port + 4242),
437 "region": "RegionOne",
438 "interface": "public",
439 "id": "2dad48f09e2a447a9bf852bcd93548cf"
440 }
441 ],
442 "id": "2dad48f09e2a447a9bf852bcd93548cf",
443 "type": "image",
444 "name": "glance"
445 },
446 {
447 "endpoints": [
448 {
449 "url": "http://%s:%s/v1/%s" % (get_host(request), self.api.port + 3004, user['id']),
450 "region": "RegionOne",
451 "interface": "public",
452 "id": "2dad48f09e2a447a9bf852bcd93548bf"
453 }
454 ],
455 "id": "2dad48f09e2a447a9bf852bcd93548bf",
456 "type": "orchestration",
457 "name": "heat"
458 }
459 ]
460 return Response(json.dumps(ret), status=201, mimetype='application/json')
461
462 except Exception as ex:
463 logging.exception("Keystone: Get token failed.")
464 return ex.message, 500