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