Manually added OpenStack API code
[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 import logging
5 import json
6
7
8 class KeystoneDummyApi(BaseOpenstackDummy):
9 def __init__(self, in_ip, in_port):
10 super(KeystoneDummyApi, self).__init__(in_ip, in_port)
11
12 self.api.add_resource(KeystoneListVersions, "/", resource_class_kwargs={'api': self})
13 self.api.add_resource(Shutdown, "/shutdown")
14 self.api.add_resource(KeystoneShowAPIv2, "/v2.0", resource_class_kwargs={'api': self})
15 self.api.add_resource(KeystoneGetToken, "/v2.0/tokens", resource_class_kwargs={'api': self})
16
17 def _start_flask(self):
18 logging.info("Starting %s endpoint @ http://%s:%d" % (__name__, self.ip, self.port))
19 if self.app is not None:
20 self.app.before_request(self.dump_playbook)
21 self.app.run(self.ip, self.port, debug=True, use_reloader=False)
22
23
24 class Shutdown(Resource):
25 """
26 A get request to /shutdown will shut down this endpoint.
27 """
28
29 def get(self):
30 logging.debug(("%s is beeing shut down") % (__name__))
31 func = request.environ.get('werkzeug.server.shutdown')
32 if func is None:
33 raise RuntimeError('Not running with the Werkzeug Server')
34 func()
35
36
37 class KeystoneListVersions(Resource):
38 """
39 List all known keystone versions.
40 Hardcoded for our version!
41 """
42
43 def __init__(self, api):
44 self.api = api
45
46 def get(self):
47 """
48 List API versions.
49
50 :return: Returns the api versions.
51 :rtype: :class:`flask.response` containing a static json encoded dict.
52 """
53 logging.debug("API CALL: %s GET" % str(self.__class__.__name__))
54 resp = dict()
55 resp['versions'] = dict()
56
57 version = [{
58 "id": "v2.0",
59 "links": [
60 {
61 "href": "http://%s:%d/v2.0" % (self.api.ip, self.api.port),
62 "rel": "self"
63 }
64 ],
65 "media-types": [
66 {
67 "base": "application/json",
68 "type": "application/vnd.openstack.identity-v2.0+json"
69 }
70 ],
71 "status": "stable",
72 "updated": "2014-04-17T00:00:00Z"
73 }]
74 resp['versions']['values'] = version
75
76 return Response(json.dumps(resp), status=200, mimetype='application/json')
77
78
79 class KeystoneShowAPIv2(Resource):
80 """
81 Entrypoint for all openstack clients.
82 This returns all current entrypoints running on son-emu.
83 """
84
85 def __init__(self, api):
86 self.api = api
87
88 def get(self):
89 """
90 List API entrypoints.
91
92 :return: Returns an openstack style response for all entrypoints.
93 :rtype: :class:`flask.response`
94 """
95 logging.debug("API CALL: %s GET" % str(self.__class__.__name__))
96
97 neutron_port = self.api.port + 4696
98 heat_port = self.api.port + 3004
99
100 resp = dict()
101 resp['version'] = {
102 "status": "stable",
103 "media-types": [
104 {
105 "base": "application/json",
106 "type": "application/vnd.openstack.identity-v2.0+json"
107 }
108 ],
109 "id": "v2.0",
110 "links": [
111 {
112 "href": "http://%s:%d/v2.0" % (self.api.ip, self.api.port),
113 "rel": "self"
114 },
115 {
116 "href": "http://%s:%d/v2.0/tokens" % (self.api.ip, self.api.port),
117 "rel": "self"
118 },
119 {
120 "href": "http://%s:%d/v2.0/networks" % (self.api.ip, neutron_port),
121 "rel": "self"
122 },
123 {
124 "href": "http://%s:%d/v2.0/subnets" % (self.api.ip, neutron_port),
125 "rel": "self"
126 },
127 {
128 "href": "http://%s:%d/v2.0/ports" % (self.api.ip, neutron_port),
129 "rel": "self"
130 },
131 {
132 "href": "http://%s:%d/v1/<tenant_id>/stacks" % (self.api.ip, heat_port),
133 "rel": "self"
134 }
135 ]
136 }
137
138 return Response(json.dumps(resp), status=200, mimetype='application/json')
139
140
141 class KeystoneGetToken(Resource):
142 """
143 Returns a static keystone token.
144 We don't do any validation so we don't care.
145 """
146
147 def __init__(self, api):
148 self.api = api
149
150 def post(self):
151 """
152 List API entrypoints.
153
154 This is hardcoded. For a working "authentication" use these ENVVARS:
155
156 * OS_AUTH_URL=http://<ip>:<port>/v2.0
157 * OS_IDENTITY_API_VERSION=2.0
158 * OS_TENANT_ID=fc394f2ab2df4114bde39905f800dc57
159 * OS_REGION_NAME=RegionOne
160 * OS_USERNAME=bla
161 * OS_PASSWORD=bla
162
163 :return: Returns an openstack style response for all entrypoints.
164 :rtype: :class:`flask.response`
165 """
166
167 logging.debug("API CALL: %s POST" % str(self.__class__.__name__))
168 try:
169 ret = dict()
170 req = json.loads(request.data)
171 ret['access'] = dict()
172 ret['access']['token'] = dict()
173 token = ret['access']['token']
174
175 token['issued_at'] = "2014-01-30T15:30:58.819Z"
176 token['expires'] = "2999-01-30T15:30:58.819Z"
177 token['id'] = req['auth'].get('token', {'id': 'fc394f2ab2df4114bde39905f800dc57'}).get('id')
178 token['tenant'] = dict()
179 token['tenant']['description'] = None
180 token['tenant']['enabled'] = True
181 token['tenant']['id'] = req['auth'].get('tenantId', 'fc394f2ab2df4114bde39905f800dc57')
182 token['tenant']['name'] = "tenantName"
183
184 ret['access']['user'] = dict()
185 user = ret['access']['user']
186 user['username'] = req.get('username', "username")
187 user['name'] = "tenantName"
188 user['roles_links'] = list()
189 user['id'] = token['tenant'].get('id', "fc394f2ab2df4114bde39905f800dc57")
190 user['roles'] = [{'name': 'Member'}]
191
192 ret['access']['region_name'] = "RegionOne"
193
194 ret['access']['serviceCatalog'] = [{
195 "endpoints": [
196 {
197 "adminURL": "http://%s:%s/v2.1/%s" % (self.api.ip, self.api.port + 3774, user['id']),
198 "region": "RegionOne",
199 "internalURL": "http://%s:%s/v2.1/%s" % (self.api.ip, self.api.port + 3774, user['id']),
200 "id": "2dad48f09e2a447a9bf852bcd93548ef",
201 "publicURL": "http://%s:%s/v2.1/%s" % (self.api.ip, self.api.port + 3774, user['id'])
202 }
203 ],
204 "endpoints_links": [],
205 "type": "compute",
206 "name": "nova"
207 },
208 {
209 "endpoints": [
210 {
211 "adminURL": "http://%s:%s/v2.0" % (self.api.ip, self.api.port),
212 "region": "RegionOne",
213 "internalURL": "http://%s:%s/v2.0" % (self.api.ip, self.api.port),
214 "id": "2dad48f09e2a447a9bf852bcd93543fc",
215 "publicURL": "http://%s:%s/v2" % (self.api.ip, self.api.port)
216 }
217 ],
218 "endpoints_links": [],
219 "type": "identity",
220 "name": "keystone"
221 },
222 {
223 "endpoints": [
224 {
225 "adminURL": "http://%s:%s" % (self.api.ip, self.api.port + 4696),
226 "region": "RegionOne",
227 "internalURL": "http://%s:%s" % (self.api.ip, self.api.port + 4696),
228 "id": "2dad48f09e2a447a9bf852bcd93548cf",
229 "publicURL": "http://%s:%s" % (self.api.ip, self.api.port + 4696)
230 }
231 ],
232 "endpoints_links": [],
233 "type": "network",
234 "name": "neutron"
235 },
236 {
237 "endpoints": [
238 {
239 "adminURL": "http://%s:%s" % (self.api.ip, self.api.port + 4242),
240 "region": "RegionOne",
241 "internalURL": "http://%s:%s" % (self.api.ip, self.api.port + 4242),
242 "id": "2dad48f09e2a447a9bf852bcd93548cf",
243 "publicURL": "http://%s:%s" % (self.api.ip, self.api.port + 4242)
244 }
245 ],
246 "endpoints_links": [],
247 "type": "image",
248 "name": "glance"
249 },
250 {
251 "endpoints": [
252 {
253 "adminURL": "http://%s:%s/v1/%s" % (self.api.ip, self.api.port + 3004, user['id']),
254 "region": "RegionOne",
255 "internalURL": "http://%s:%s/v1/%s" % (self.api.ip, self.api.port + 3004, user['id']),
256 "id": "2dad48f09e2a447a9bf852bcd93548bf",
257 "publicURL": "http://%s:%s/v1/%s" % (self.api.ip, self.api.port + 3004, user['id'])
258 }
259 ],
260 "endpoints_links": [],
261 "type": "orchestration",
262 "name": "heat"
263 }
264 ]
265
266 ret['access']["metadata"] = {
267 "is_admin": 0,
268 "roles": [
269 "7598ac3c634d4c3da4b9126a5f67ca2b"
270 ]
271 },
272 ret['access']['trust'] = {
273 "id": "394998fa61f14736b1f0c1f322882949",
274 "trustee_user_id": "269348fdd9374b8885da1418e0730af1",
275 "trustor_user_id": "3ec3164f750146be97f21559ee4d9c51",
276 "impersonation": False
277 }
278 return Response(json.dumps(ret), status=200, mimetype='application/json')
279
280 except Exception as ex:
281 logging.exception("Keystone: Get token failed.")
282 return ex.message, 500