blob: 44062eaff7cfc4586fb4f8134798f00390a9541b [file] [log] [blame]
Kurt Taylor6a6f5be2013-04-02 18:53:47 -04001# Copyright 2013 IBM Corp.
Matthew Treinisha62347f2013-03-01 16:37:30 -05002# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# 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, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
Matthew Treinish21905512015-07-13 10:33:35 -040016from oslo_serialization import jsonutils as json
Matthew Treinish89128142015-04-23 10:44:30 -040017from six.moves.urllib import parse as urllib
Masayuki Igawabfa07602015-01-20 18:47:17 +090018from tempest_lib import exceptions as lib_exc
Matthew Treinisha62347f2013-03-01 16:37:30 -050019
20from tempest.common import glance_http
Ken'ichi Ohmichi0e836652015-01-08 04:38:56 +000021from tempest.common import service_client
Matthew Treinish684d8992014-01-30 16:27:40 +000022
Matthew Treinisha62347f2013-03-01 16:37:30 -050023
Ken'ichi Ohmichi69dcf442015-11-30 11:48:01 +000024class ImagesClientV2(service_client.ServiceClient):
Matthew Treinisha62347f2013-03-01 16:37:30 -050025
Masayuki Igawabc7e1892015-03-03 11:46:48 +090026 def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
27 build_interval=None, build_timeout=None,
28 disable_ssl_certificate_validation=None, ca_certs=None,
David Kranz85b660b2015-03-23 10:26:52 -040029 trace_requests=None):
Ken'ichi Ohmichi69dcf442015-11-30 11:48:01 +000030 super(ImagesClientV2, self).__init__(
Ken'ichi Ohmichi0690ea42015-01-02 07:03:51 +000031 auth_provider,
Masayuki Igawabc7e1892015-03-03 11:46:48 +090032 catalog_type,
33 region,
34 endpoint_type=endpoint_type,
35 build_interval=build_interval,
36 build_timeout=build_timeout,
37 disable_ssl_certificate_validation=(
38 disable_ssl_certificate_validation),
39 ca_certs=ca_certs,
David Kranz85b660b2015-03-23 10:26:52 -040040 trace_requests=trace_requests)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000041 self._http = None
Masayuki Igawabc7e1892015-03-03 11:46:48 +090042 self.dscv = disable_ssl_certificate_validation
43 self.ca_certs = ca_certs
Matthew Treinisha62347f2013-03-01 16:37:30 -050044
45 def _get_http(self):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000046 return glance_http.HTTPClient(auth_provider=self.auth_provider,
47 filters=self.filters,
Masayuki Igawabc7e1892015-03-03 11:46:48 +090048 insecure=self.dscv,
49 ca_certs=self.ca_certs)
Matthew Treinisha62347f2013-03-01 16:37:30 -050050
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000051 @property
52 def http(self):
53 if self._http is None:
Masayuki Igawabc7e1892015-03-03 11:46:48 +090054 self._http = self._get_http()
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000055 return self._http
56
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +040057 def update_image(self, image_id, patch):
58 data = json.dumps(patch)
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +040059 headers = {"Content-Type": "application/openstack-images-v2.0"
60 "-json-patch"}
61 resp, body = self.patch('v2/images/%s' % image_id, data, headers)
David Kranz9c3b3b62014-06-19 16:05:53 -040062 self.expected_success(200, resp.status)
ghanshyam08a73f92015-08-31 17:32:49 +090063 body = json.loads(body)
64 return service_client.ResponseBody(resp, body)
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +040065
Matthew Treinishce3ef922013-03-11 14:02:46 -040066 def create_image(self, name, container_format, disk_format, **kwargs):
Matthew Treinisha62347f2013-03-01 16:37:30 -050067 params = {
68 "name": name,
69 "container_format": container_format,
70 "disk_format": disk_format,
71 }
Matthew Treinishce3ef922013-03-11 14:02:46 -040072
Sean Daguec6ec4762014-05-29 08:54:21 -040073 for option in kwargs:
74 value = kwargs.get(option)
75 if isinstance(value, dict) or isinstance(value, tuple):
76 params.update(value)
77 else:
78 params[option] = value
Matthew Treinisha62347f2013-03-01 16:37:30 -050079
80 data = json.dumps(params)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +020081 resp, body = self.post('v2/images', data)
David Kranz9c3b3b62014-06-19 16:05:53 -040082 self.expected_success(201, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -050083 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +000084 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -050085
bkopilov81aaae72015-05-15 23:46:25 +030086 def deactivate_image(self, image_id):
87 url = 'v2/images/%s/actions/deactivate' % image_id
88 resp, body = self.post(url, None)
89 self.expected_success(204, resp.status)
90 return service_client.ResponseBody(resp, body)
91
92 def reactivate_image(self, image_id):
93 url = 'v2/images/%s/actions/reactivate' % image_id
94 resp, body = self.post(url, None)
95 self.expected_success(204, resp.status)
96 return service_client.ResponseBody(resp, body)
97
Matthew Treinisha62347f2013-03-01 16:37:30 -050098 def delete_image(self, image_id):
99 url = 'v2/images/%s' % image_id
David Kranz9c3b3b62014-06-19 16:05:53 -0400100 resp, _ = self.delete(url)
101 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000102 return service_client.ResponseBody(resp)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500103
Ken'ichi Ohmichie3acc122015-05-22 00:32:54 +0000104 def list_images(self, params=None):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500105 url = 'v2/images'
106
107 if params:
108 url += '?%s' % urllib.urlencode(params)
109
110 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400111 self.expected_success(200, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500112 body = json.loads(body)
John Warrenf3b3e952015-08-17 19:28:12 +0000113 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500114
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000115 def show_image(self, image_id):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500116 url = 'v2/images/%s' % image_id
117 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400118 self.expected_success(200, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500119 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000120 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500121
122 def is_resource_deleted(self, id):
123 try:
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000124 self.show_image(id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900125 except lib_exc.NotFound:
Matthew Treinisha62347f2013-03-01 16:37:30 -0500126 return True
127 return False
128
Matt Riedemannd2b96512014-10-13 10:18:16 -0700129 @property
130 def resource_type(self):
131 """Returns the primary type of resource this client works with."""
132 return 'image'
133
Ken'ichi Ohmichi66494e92015-06-08 04:28:10 +0000134 def store_image_file(self, image_id, data):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500135 url = 'v2/images/%s/file' % image_id
136 headers = {'Content-Type': 'application/octet-stream'}
137 resp, body = self.http.raw_request('PUT', url, headers=headers,
138 body=data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400139 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000140 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500141
Ken'ichi Ohmichi6bd6f202015-11-20 05:29:38 +0000142 def show_image_file(self, image_id):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500143 url = 'v2/images/%s/file' % image_id
144 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400145 self.expected_success(200, resp.status)
David Kranzd7e97b42015-02-16 09:37:31 -0500146 return service_client.ResponseBodyData(resp, body)
Anju Tiwaric4952982013-10-20 07:10:02 +0530147
148 def add_image_tag(self, image_id, tag):
149 url = 'v2/images/%s/tags/%s' % (image_id, tag)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200150 resp, body = self.put(url, body=None)
David Kranz9c3b3b62014-06-19 16:05:53 -0400151 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000152 return service_client.ResponseBody(resp, body)
Anju Tiwaric4952982013-10-20 07:10:02 +0530153
154 def delete_image_tag(self, image_id, tag):
155 url = 'v2/images/%s/tags/%s' % (image_id, tag)
156 resp, _ = self.delete(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400157 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000158 return service_client.ResponseBody(resp)
Attila Fazekas689e2652013-10-07 18:06:57 +0200159
Ken'ichi Ohmichif0df53c2015-05-22 01:16:50 +0000160 def list_image_members(self, image_id):
Attila Fazekas689e2652013-10-07 18:06:57 +0200161 url = 'v2/images/%s/members' % image_id
162 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400163 self.expected_success(200, resp.status)
Attila Fazekas689e2652013-10-07 18:06:57 +0200164 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000165 return service_client.ResponseBody(resp, body)
Attila Fazekas689e2652013-10-07 18:06:57 +0200166
Ken'ichi Ohmichi9dacbe02015-11-30 12:01:39 +0000167 def create_image_member(self, image_id, **kwargs):
168 """Create an image member.
169
170 Available params: see http://developer.openstack.org/
171 api-ref-image-v2.html#createImageMember-v2
172 """
Attila Fazekas689e2652013-10-07 18:06:57 +0200173 url = 'v2/images/%s/members' % image_id
Ken'ichi Ohmichi2f8f6c22015-11-24 02:28:52 +0000174 data = json.dumps(kwargs)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200175 resp, body = self.post(url, data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400176 self.expected_success(200, resp.status)
Attila Fazekas689e2652013-10-07 18:06:57 +0200177 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000178 return service_client.ResponseBody(resp, body)
Attila Fazekas689e2652013-10-07 18:06:57 +0200179
Ken'ichi Ohmichi2f8f6c22015-11-24 02:28:52 +0000180 def update_image_member(self, image_id, member_id, **kwargs):
Ken'ichi Ohmichi5a1c9342015-11-30 12:12:19 +0000181 """Update an image member.
182
183 Available params: see http://developer.openstack.org/
184 api-ref-image-v2.html#updateImageMember-v2
185 """
Attila Fazekas689e2652013-10-07 18:06:57 +0200186 url = 'v2/images/%s/members/%s' % (image_id, member_id)
Ken'ichi Ohmichi2f8f6c22015-11-24 02:28:52 +0000187 data = json.dumps(kwargs)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200188 resp, body = self.put(url, data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400189 self.expected_success(200, resp.status)
Attila Fazekas689e2652013-10-07 18:06:57 +0200190 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000191 return service_client.ResponseBody(resp, body)
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400192
Ken'ichi Ohmichic3728c62015-06-08 04:01:45 +0000193 def show_image_member(self, image_id, member_id):
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400194 url = 'v2/images/%s/members/%s' % (image_id, member_id)
195 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400196 self.expected_success(200, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000197 return service_client.ResponseBody(resp, json.loads(body))
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400198
Ken'ichi Ohmichib8461cb2015-11-20 08:10:51 +0000199 def delete_image_member(self, image_id, member_id):
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400200 url = 'v2/images/%s/members/%s' % (image_id, member_id)
201 resp, _ = self.delete(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400202 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000203 return service_client.ResponseBody(resp)
raiesmh08a1ce3542014-03-04 11:58:29 +0530204
Ken'ichi Ohmichi66494e92015-06-08 04:28:10 +0000205 def show_schema(self, schema):
raiesmh08a1ce3542014-03-04 11:58:29 +0530206 url = 'v2/schemas/%s' % schema
207 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400208 self.expected_success(200, resp.status)
raiesmh08a1ce3542014-03-04 11:58:29 +0530209 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000210 return service_client.ResponseBody(resp, body)
piyush1107865f829d72015-09-11 11:46:35 +0530211
212 def list_resource_types(self):
213 url = '/v2/metadefs/resource_types'
214 resp, body = self.get(url)
215 self.expected_success(200, resp.status)
216 body = json.loads(body)
217 return service_client.ResponseBody(resp, body)
218
Ken'ichi Ohmichi2f8f6c22015-11-24 02:28:52 +0000219 def create_namespace(self, **kwargs):
220 """Create a namespace.
piyush1107865f829d72015-09-11 11:46:35 +0530221
Ken'ichi Ohmichi2f8f6c22015-11-24 02:28:52 +0000222 Available params: see http://developer.openstack.org/
223 api-ref-image-v2.html#createNamespace-v2
224 """
225 data = json.dumps(kwargs)
piyush1107865f829d72015-09-11 11:46:35 +0530226 resp, body = self.post('/v2/metadefs/namespaces', data)
227 self.expected_success(201, resp.status)
228 body = json.loads(body)
229 return service_client.ResponseBody(resp, body)
230
Ken'ichi Ohmichi19515632015-11-24 02:08:24 +0000231 def show_namespace(self, namespace):
piyush1107865f829d72015-09-11 11:46:35 +0530232 url = '/v2/metadefs/namespaces/%s' % namespace
233 resp, body = self.get(url)
234 self.expected_success(200, resp.status)
235 body = json.loads(body)
236 return service_client.ResponseBody(resp, body)
237
Ken'ichi Ohmichi2f8f6c22015-11-24 02:28:52 +0000238 def update_namespace(self, namespace, **kwargs):
239 """Update a namespace.
piyush1107865f829d72015-09-11 11:46:35 +0530240
Ken'ichi Ohmichi2f8f6c22015-11-24 02:28:52 +0000241 Available params: see http://developer.openstack.org/
242 api-ref-image-v2.html#updateNamespace-v2
243 """
244 # NOTE: On Glance API, we need to pass namespace on both URI
245 # and a request body.
246 params = {'namespace': namespace}
247 params.update(kwargs)
piyush1107865f829d72015-09-11 11:46:35 +0530248 data = json.dumps(params)
piyush1107865f829d72015-09-11 11:46:35 +0530249 url = '/v2/metadefs/namespaces/%s' % namespace
250 resp, body = self.put(url, body=data)
251 self.expected_success(200, resp.status)
252 body = json.loads(body)
253 return service_client.ResponseBody(resp, body)
254
Ken'ichi Ohmichi19515632015-11-24 02:08:24 +0000255 def delete_namespace(self, namespace):
piyush1107865f829d72015-09-11 11:46:35 +0530256 url = '/v2/metadefs/namespaces/%s' % namespace
257 resp, _ = self.delete(url)
258 self.expected_success(204, resp.status)
259 return service_client.ResponseBody(resp)