1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
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
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
34 LOG
= logging
.getLogger("api.openstack.glance")
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
,
43 self
.api
.add_resource(GlanceSchema
,
45 "/v2/schemas/metadefs/namespace",
46 "/v2/schemas/metadefs/resource_type")
47 self
.api
.add_resource(GlanceListImagesApi
,
52 resource_class_kwargs
={'api': self
})
53 self
.api
.add_resource(GlanceImageByIdApi
,
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
})
63 class GlanceListApiVersions(Resource
):
65 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
67 resp
['versions'] = dict()
73 "href": request
.url_root
+ '/v2',
78 resp
['versions'] = versions
79 return Response(json
.dumps(resp
), status
=200,
80 mimetype
='application/json')
83 class GlanceSchema(Resource
):
85 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
87 resp
['name'] = 'someImageName'
88 resp
['properties'] = dict()
89 resp
['links'] = list()
90 # just an ugly hack to allow the openstack client to work
91 return Response(json
.dumps(resp
), status
=200,
92 mimetype
='application/json')
95 class GlanceListImagesApi(Resource
):
96 def __init__(self
, api
):
100 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
102 img_list
= self
.api
.compute
.images
.values()
103 LOG
.debug("Found {} Docker images: {}".format(
104 len(img_list
), [i
.name
for i
in img_list
]))
106 # resp['next'] = None
107 resp
['first'] = "/v2/images"
108 resp
['schema'] = "/v2/schemas/images"
109 resp
['images'] = list()
110 for image
in img_list
:
113 f
['name'] = str(image
.name
).replace(":latest", "")
114 f
['checksum'] = "2dad48f09e2a447a9bf852bcd93548c1"
115 f
['container_format'] = "docker"
116 f
['disk_format'] = "raw"
118 f
['created_at'] = "2016-03-15T15:09:07.000000"
120 f
['deleted_at'] = None
121 f
['is_public'] = True
124 f
['owner'] = "3dad48f09e2a447a9bf852bcd93548c1"
126 f
['protected'] = False
127 f
['status'] = "active"
128 f
['updated_at'] = "2016-03-15T15:09:07.000000"
129 f
['virtual_size'] = 1
131 resp
['images'].append(f
)
132 if "marker" in request
.args
: # ugly hack to fix pageination of openstack client
133 resp
['images'] = None
134 return Response(json
.dumps(resp
), status
=200,
135 mimetype
="application/json")
137 except Exception as ex
:
139 u
"%s: Could not retrieve the list of images." % __name__
)
140 return ex
.message
, 500
144 This one is a real fake! It does not really create anything and the mentioned image
145 should already be registered with Docker. However, this function returns a reply that looks
146 like the image was just created to make orchestrators, like OSM, happy.
148 LOG
.debug("API CALL: %s POST" % str(self
.__class
__.__name
__))
150 body_data
= json
.loads(request
.data
)
151 except BaseException
:
153 # lets see what we should create
154 img_name
= request
.headers
.get("X-Image-Meta-Name")
155 img_size
= request
.headers
.get("X-Image-Meta-Size")
156 img_disk_format
= request
.headers
.get("X-Image-Meta-Disk-Format")
157 img_is_public
= request
.headers
.get("X-Image-Meta-Is-Public")
158 img_container_format
= request
.headers
.get(
159 "X-Image-Meta-Container-Format")
160 # try to use body payload if header fields are empty
162 img_name
= body_data
.get("name")
164 img_disk_format
= body_data
.get("disk_format")
165 img_is_public
= True if "public" in body_data
.get(
166 "visibility") else False
167 img_container_format
= body_data
.get("container_format")
168 # try to find ID of already existing image (matched by name)
170 for image
in self
.api
.compute
.images
.values():
171 if str(img_name
) in image
.name
:
173 LOG
.debug("Image name: %s" % img_name
)
174 LOG
.debug("Image id: %s" % img_id
)
175 # build a response body that looks like a real one
180 f
['checksum'] = "2dad48f09e2a447a9bf852bcd93548c1"
181 f
['container_format'] = img_container_format
182 f
['disk_format'] = img_disk_format
184 f
['created_at'] = "2016-03-15T15:09:07.000000"
186 f
['deleted_at'] = None
187 f
['is_public'] = img_is_public
190 f
['owner'] = "3dad48f09e2a447a9bf852bcd93548c1"
192 f
['protected'] = False
193 f
['status'] = "active"
194 f
['updated_at'] = "2016-03-15T15:09:07.000000"
195 f
['virtual_size'] = 1
197 # build actual response with headers and everything
198 r
= Response(json
.dumps(resp
), status
=201, mimetype
="application/json")
199 r
.headers
.add("Location", "http://%s:%d/v1/images/%s" % (get_host(request
),
205 class GlanceImageByIdApi(Resource
):
206 def __init__(self
, api
):
210 LOG
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
213 for image
in self
.api
.compute
.images
.values():
214 if image
.id == id or image
.name
== id:
215 resp
['id'] = image
.id
216 resp
['name'] = image
.name
218 return Response(json
.dumps(resp
), status
=200,
219 mimetype
="application/json")
222 "Image with id or name %s does not exists." % id, status
=404)
223 response
.headers
['Access-Control-Allow-Origin'] = '*'
226 except Exception as ex
:
228 u
"%s: Could not retrieve image with id %s." % (__name__
, id))
229 return Response(ex
.message
, status
=500,
230 mimetype
='application/json')
233 LOG
.debug("API CALL: %s " % str(self
.__class
__.__name
__))
234 LOG
.warning("Endpoint not implemented")
238 class GlanceImageByDockerNameApi(Resource
):
239 def __init__(self
, api
):
242 def get(self
, owner
, container
):
243 logging
.debug("API CALL: %s GET" % str(self
.__class
__.__name
__))
245 name
= "%s/%s" % (owner
, container
)
246 if name
in self
.api
.compute
.images
:
247 image
= self
.api
.compute
.images
[name
]
249 resp
['id'] = image
.id
250 resp
['name'] = image
.name
251 return Response(json
.dumps(resp
), status
=200,
252 mimetype
="application/json")
255 "Image with id or name %s does not exists." % id, status
=404)
256 response
.headers
['Access-Control-Allow-Origin'] = '*'
259 except Exception as ex
:
261 u
"%s: Could not retrieve image with id %s." % (__name__
, id))
262 return Response(ex
.message
, status
=500,
263 mimetype
='application/json')