2 Copyright (c) 2017 SONATA-NFV and Paderborn University
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
9 http://www.apache.org/licenses/LICENSE-2.0
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.
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
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).
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
35 LOG
= logging
.getLogger("api.openstack.keystone")
38 class KeystoneDummyApi(BaseOpenstackDummy
):
39 def __init__(self
, in_ip
, in_port
):
40 super(KeystoneDummyApi
, self
).__init
__(in_ip
, in_port
)
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
})
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)
56 class Shutdown(Resource
):
58 A get request to /shutdown will shut down this endpoint.
62 LOG
.debug(("%s is beeing shut down") % (__name__
))
63 func
= request
.environ
.get('werkzeug.server.shutdown')
65 raise RuntimeError('Not running with the Werkzeug Server')
69 class KeystoneListVersions(Resource
):
71 List all known keystone versions.
72 Hardcoded for our version!
75 def __init__(self
, api
):
82 :return: Returns the api versions.
83 :rtype: :class:`flask.response` containing a static json encoded dict.
85 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
87 resp
['versions'] = dict()
93 "href": "http://%s:%d/v2.0" % (get_host(request
), self
.api
.port
),
99 "base": "application/json",
100 "type": "application/vnd.openstack.identity-v2.0+json"
104 "updated": "2014-04-17T00:00:00Z"
106 resp
['versions']['values'] = version
108 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
111 class KeystoneShowAPIv2(Resource
):
113 Entrypoint for all openstack clients.
114 This returns all current entrypoints running on son-emu.
117 def __init__(self
, api
):
122 List API entrypoints.
124 :return: Returns an openstack style response for all entrypoints.
125 :rtype: :class:`flask.response`
127 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
129 neutron_port
= self
.api
.port
+ 4696
130 heat_port
= self
.api
.port
+ 3004
137 "base": "application/json",
138 "type": "application/vnd.openstack.identity-v2.0+json"
144 "href": "http://%s:%d/v2.0" % (get_host(request
), self
.api
.port
),
149 LOG
.debug(json
.dumps(resp
))
150 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
153 class KeystoneShowAPIv3(Resource
):
155 Entrypoint for all openstack clients.
156 This returns all current entrypoints running on son-emu.
159 def __init__(self
, api
):
164 List API entrypoints.
166 :return: Returns an openstack style response for all entrypoints.
167 :rtype: :class:`flask.response`
169 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
171 neutron_port
= self
.api
.port
+ 4696
172 heat_port
= self
.api
.port
+ 3004
179 "base": "application/json",
180 "type": "application/vnd.openstack.identity-v3.0+json"
186 "href": "http://%s:%d/v3.0" % (get_host(request
), self
.api
.port
),
192 return Response(json
.dumps(resp
), status
=200, mimetype
='application/json')
195 class KeystoneGetToken(Resource
):
197 Returns a static keystone token.
198 We don't do any validation so we don't care.
201 def __init__(self
, api
):
206 List API entrypoints.
208 This is hardcoded. For a working "authentication" use these ENVVARS:
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
217 :return: Returns an openstack style response for all entrypoints.
218 :rtype: :class:`flask.response`
221 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
224 req
= json
.loads(request
.data
)
225 ret
['access'] = dict()
226 ret
['access']['token'] = dict()
227 token
= ret
['access']['token']
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"
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'}]
246 ret
['access']['region_name'] = "RegionOne"
248 ret
['access']['serviceCatalog'] = [{
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'])
258 "endpoints_links": [],
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
)
272 "endpoints_links": [],
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)
286 "endpoints_links": [],
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)
300 "endpoints_links": [],
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'])
314 "endpoints_links": [],
315 "type": "orchestration",
320 ret
['access']["metadata"] = {
323 "7598ac3c634d4c3da4b9126a5f67ca2b"
326 ret
['access']['trust'] = {
327 "id": "394998fa61f14736b1f0c1f322882949",
328 "trustee_user_id": "269348fdd9374b8885da1418e0730af1",
329 "trustor_user_id": "3ec3164f750146be97f21559ee4d9c51",
330 "impersonation": False
332 return Response(json
.dumps(ret
), status
=200, mimetype
='application/json')
334 except Exception as ex
:
335 logging
.exception("Keystone: Get token failed.")
336 return ex
.message
, 500
338 class KeystoneGetTokenv3(Resource
):
340 Returns a static keystone token.
341 We don't do any validation so we don't care.
344 def __init__(self
, api
):
349 List API entrypoints.
351 This is hardcoded. For a working "authentication" use these ENVVARS:
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
360 :return: Returns an openstack style response for all entrypoints.
361 :rtype: :class:`flask.response`
364 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
367 req
= json
.loads(request
.data
)
368 ret
['token'] = dict()
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()
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"]
389 "id": "8538a3f13f9541b28c2620eb19065e45",
394 token
['catalog'] = [{
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"
403 "id": "2dad48f09e2a447a9bf852bcd93548ef",
410 "url": "http://%s:%s/v2.0" % (get_host(request
), self
.api
.port
),
411 "region": "RegionOne",
412 "interface": "public",
413 "id": "2dad48f09e2a447a9bf852bcd93543fc"
416 "id": "2dad48f09e2a447a9bf852bcd93543fc",
423 "url": "http://%s:%s" % (get_host(request
), self
.api
.port
+ 4696),
424 "region": "RegionOne",
425 "interface": "public",
426 "id": "2dad48f09e2a447a9bf852bcd93548cf"
429 "id": "2dad48f09e2a447a9bf852bcd93548cf",
436 "url": "http://%s:%s" % (get_host(request
), self
.api
.port
+ 4242),
437 "region": "RegionOne",
438 "interface": "public",
439 "id": "2dad48f09e2a447a9bf852bcd93548cf"
442 "id": "2dad48f09e2a447a9bf852bcd93548cf",
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"
455 "id": "2dad48f09e2a447a9bf852bcd93548bf",
456 "type": "orchestration",
460 return Response(json
.dumps(ret
), status
=201, mimetype
='application/json')
462 except Exception as ex
:
463 logging
.exception("Keystone: Get token failed.")
464 return ex
.message
, 500