6edaa721ac09a2831a7063cd032d675cf9859f72
[osm/vim-emu.git] / src / emuvim / api / openstack / openstack_dummies / glance_dummy_api.py
1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
2 # ALL RIGHTS RESERVED.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # Neither the name of the SONATA-NFV, Paderborn University
17 # nor the names of its contributors may be used to endorse or promote
18 # products derived from this software without specific prior written
19 # permission.
20 #
21 # This work has been performed in the framework of the SONATA project,
22 # funded by the European Commission under Grant number 671517 through
23 # the Horizon 2020 and 5G-PPP programmes. The authors would like to
24 # acknowledge the contributions of their colleagues of the SONATA
25 # partner consortium (www.sonata-nfv.eu).
26 from flask_restful import Resource
27 from flask import Response, request
28 from emuvim.api.openstack.openstack_dummies.base_openstack_dummy import BaseOpenstackDummy
29 from emuvim.api.openstack.helper import get_host
30 import logging
31 import json
32
33
34 LOG = logging.getLogger("api.openstack.glance")
35
36
37 class GlanceDummyApi(BaseOpenstackDummy):
38 def __init__(self, in_ip, in_port, compute):
39 super(GlanceDummyApi, self).__init__(in_ip, in_port)
40 self.compute = compute
41 self.api.add_resource(GlanceListApiVersions,
42 "/versions")
43 self.api.add_resource(GlanceSchema,
44 "/v2/schemas/image",
45 "/v2/schemas/metadefs/namespace",
46 "/v2/schemas/metadefs/resource_type")
47 self.api.add_resource(GlanceListImagesApi,
48 "/v1/images",
49 "/v1/images/detail",
50 "/v2/images",
51 "/v2/images/detail",
52 resource_class_kwargs={'api': self})
53 self.api.add_resource(GlanceImageByIdApi,
54 "/v1/images/<id>",
55 "/v2/images/<id>",
56 resource_class_kwargs={'api': self})
57 self.api.add_resource(GlanceImageByDockerNameApi,
58 "/v1/images/<owner>/<container>",
59 "/v2/images/<owner>/<container>",
60 resource_class_kwargs={'api': self})
61
62
63 class GlanceListApiVersions(Resource):
64 def get(self):
65 LOG.debug("API CALL: %s GET" % str(self.__class__.__name__))
66 resp = dict()
67 resp['versions'] = dict()
68 versions = [{
69 "status": "CURRENT",
70 "id": "v2",
71 "links": [
72 {
73 "href": request.url_root + '/v2',
74 "rel": "self"
75 }
76 ]
77 }]
78 resp['versions'] = versions
79 return Response(json.dumps(resp), status=200,
80 mimetype='application/json')
81
82
83 class GlanceSchema(Resource):
84 def get(self):
85 LOG.debug("API CALL: %s GET" % str(self.__class__.__name__))
86 resp = dict()
87 resp['name'] = 'someImageName'
88 resp['properties'] = dict()
89 # just an ugly hack to allow the openstack client to work
90 return Response(json.dumps(resp), status=200,
91 mimetype='application/json')
92
93
94 class GlanceListImagesApi(Resource):
95 def __init__(self, api):
96 self.api = api
97
98 def get(self):
99 LOG.debug("API CALL: %s GET" % str(self.__class__.__name__))
100 try:
101 resp = dict()
102 resp['next'] = None
103 resp['first'] = "/v2/images"
104 resp['schema'] = "/v2/schemas/images"
105 resp['images'] = list()
106 limit = 18
107 c = 0
108 for image in self.api.compute.images.values():
109 f = dict()
110 f['id'] = image.id
111 f['name'] = str(image.name).replace(":latest", "")
112 f['checksum'] = "2dad48f09e2a447a9bf852bcd93548c1"
113 f['container_format'] = "docker"
114 f['disk_format'] = "raw"
115 f['size'] = 1
116 f['created_at'] = "2016-03-15T15:09:07.000000"
117 f['deleted'] = False
118 f['deleted_at'] = None
119 f['is_public'] = True
120 f['min_disk'] = 1
121 f['min_ram'] = 128
122 f['owner'] = "3dad48f09e2a447a9bf852bcd93548c1"
123 f['properties'] = {}
124 f['protected'] = False
125 f['status'] = "active"
126 f['updated_at'] = "2016-03-15T15:09:07.000000"
127 f['virtual_size'] = 1
128 f['marker'] = None
129 resp['images'].append(f)
130 c += 1
131 if c > limit: # ugly hack to stop buggy glance client to do infinite requests
132 break
133 if "marker" in request.args: # ugly hack to fix pageination of openstack client
134 resp['images'] = None
135 return Response(json.dumps(resp), status=200,
136 mimetype="application/json")
137
138 except Exception as ex:
139 LOG.exception(
140 u"%s: Could not retrieve the list of images." % __name__)
141 return ex.message, 500
142
143 def post(self):
144 """
145 This one is a real fake! It does not really create anything and the mentioned image
146 should already be registered with Docker. However, this function returns a reply that looks
147 like the image was just created to make orchestrators, like OSM, happy.
148 """
149 LOG.debug("API CALL: %s POST" % str(self.__class__.__name__))
150 try:
151 body_data = json.loads(request.data)
152 except BaseException:
153 body_data = dict()
154 # lets see what we should create
155 img_name = request.headers.get("X-Image-Meta-Name")
156 img_size = request.headers.get("X-Image-Meta-Size")
157 img_disk_format = request.headers.get("X-Image-Meta-Disk-Format")
158 img_is_public = request.headers.get("X-Image-Meta-Is-Public")
159 img_container_format = request.headers.get(
160 "X-Image-Meta-Container-Format")
161 # try to use body payload if header fields are empty
162 if img_name is None:
163 img_name = body_data.get("name")
164 img_size = 1234
165 img_disk_format = body_data.get("disk_format")
166 img_is_public = True if "public" in body_data.get(
167 "visibility") else False
168 img_container_format = body_data.get("container_format")
169 # try to find ID of already existing image (matched by name)
170 img_id = None
171 for image in self.api.compute.images.values():
172 if str(img_name) in image.name:
173 img_id = image.id
174 LOG.debug("Image name: %s" % img_name)
175 LOG.debug("Image id: %s" % img_id)
176 # build a response body that looks like a real one
177 resp = dict()
178 f = dict()
179 f['id'] = img_id
180 f['name'] = img_name
181 f['checksum'] = "2dad48f09e2a447a9bf852bcd93548c1"
182 f['container_format'] = img_container_format
183 f['disk_format'] = img_disk_format
184 f['size'] = img_size
185 f['created_at'] = "2016-03-15T15:09:07.000000"
186 f['deleted'] = False
187 f['deleted_at'] = None
188 f['is_public'] = img_is_public
189 f['min_disk'] = 1
190 f['min_ram'] = 128
191 f['owner'] = "3dad48f09e2a447a9bf852bcd93548c1"
192 f['properties'] = {}
193 f['protected'] = False
194 f['status'] = "active"
195 f['updated_at'] = "2016-03-15T15:09:07.000000"
196 f['virtual_size'] = 1
197 resp['image'] = f
198 # build actual response with headers and everything
199 r = Response(json.dumps(resp), status=201, mimetype="application/json")
200 r.headers.add("Location", "http://%s:%d/v1/images/%s" % (get_host(request),
201 self.api.port,
202 img_id))
203 return r
204
205
206 class GlanceImageByIdApi(Resource):
207 def __init__(self, api):
208 self.api = api
209
210 def get(self, id):
211 LOG.debug("API CALL: %s GET" % str(self.__class__.__name__))
212 try:
213 resp = dict()
214 for image in self.api.compute.images.values():
215 if image.id == id or image.name == id:
216 resp['id'] = image.id
217 resp['name'] = image.name
218
219 return Response(json.dumps(resp), status=200,
220 mimetype="application/json")
221
222 response = Response(
223 "Image with id or name %s does not exists." % id, status=404)
224 response.headers['Access-Control-Allow-Origin'] = '*'
225 return response
226
227 except Exception as ex:
228 LOG.exception(
229 u"%s: Could not retrieve image with id %s." % (__name__, id))
230 return Response(ex.message, status=500,
231 mimetype='application/json')
232
233 def put(self, id):
234 LOG.debug("API CALL: %s " % str(self.__class__.__name__))
235 LOG.warning("Endpoint not implemented")
236 return None
237
238
239 class GlanceImageByDockerNameApi(Resource):
240 def __init__(self, api):
241 self.api = api
242
243 def get(self, owner, container):
244 logging.debug("API CALL: %s GET" % str(self.__class__.__name__))
245 try:
246 name = "%s/%s" % (owner, container)
247 if name in self.api.compute.images:
248 image = self.api.compute.images[name]
249 resp = dict()
250 resp['id'] = image.id
251 resp['name'] = image.name
252 return Response(json.dumps(resp), status=200,
253 mimetype="application/json")
254
255 response = Response(
256 "Image with id or name %s does not exists." % id, status=404)
257 response.headers['Access-Control-Allow-Origin'] = '*'
258 return response
259
260 except Exception as ex:
261 logging.exception(
262 u"%s: Could not retrieve image with id %s." % (__name__, id))
263 return Response(ex.message, status=500,
264 mimetype='application/json')