blob: a4cb48c4d1a35c11a7886e23e6188fd35b4a8ee2 [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
16import json
Matthew Treinisha62347f2013-03-01 16:37:30 -050017
18import jsonschema
Matthew Treinish89128142015-04-23 10:44:30 -040019from six.moves.urllib import parse as urllib
Masayuki Igawabfa07602015-01-20 18:47:17 +090020from tempest_lib import exceptions as lib_exc
Matthew Treinisha62347f2013-03-01 16:37:30 -050021
22from tempest.common import glance_http
Ken'ichi Ohmichi0e836652015-01-08 04:38:56 +000023from tempest.common import service_client
Matthew Treinish684d8992014-01-30 16:27:40 +000024
Matthew Treinisha62347f2013-03-01 16:37:30 -050025
Ken'ichi Ohmichi0e836652015-01-08 04:38:56 +000026class ImageClientV2JSON(service_client.ServiceClient):
Matthew Treinisha62347f2013-03-01 16:37:30 -050027
Masayuki Igawabc7e1892015-03-03 11:46:48 +090028 def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
29 build_interval=None, build_timeout=None,
30 disable_ssl_certificate_validation=None, ca_certs=None,
David Kranz85b660b2015-03-23 10:26:52 -040031 trace_requests=None):
Ken'ichi Ohmichi0690ea42015-01-02 07:03:51 +000032 super(ImageClientV2JSON, self).__init__(
33 auth_provider,
Masayuki Igawabc7e1892015-03-03 11:46:48 +090034 catalog_type,
35 region,
36 endpoint_type=endpoint_type,
37 build_interval=build_interval,
38 build_timeout=build_timeout,
39 disable_ssl_certificate_validation=(
40 disable_ssl_certificate_validation),
41 ca_certs=ca_certs,
David Kranz85b660b2015-03-23 10:26:52 -040042 trace_requests=trace_requests)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000043 self._http = None
Masayuki Igawabc7e1892015-03-03 11:46:48 +090044 self.dscv = disable_ssl_certificate_validation
45 self.ca_certs = ca_certs
Matthew Treinisha62347f2013-03-01 16:37:30 -050046
47 def _get_http(self):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000048 return glance_http.HTTPClient(auth_provider=self.auth_provider,
49 filters=self.filters,
Masayuki Igawabc7e1892015-03-03 11:46:48 +090050 insecure=self.dscv,
51 ca_certs=self.ca_certs)
Matthew Treinisha62347f2013-03-01 16:37:30 -050052
Matthew Treinisha62347f2013-03-01 16:37:30 -050053 def _validate_schema(self, body, type='image'):
raiesmh08a1ce3542014-03-04 11:58:29 +053054 if type in ['image', 'images']:
David Kranz34f18782015-01-06 13:43:55 -050055 schema = self.get_schema(type)
Matthew Treinisha62347f2013-03-01 16:37:30 -050056 else:
57 raise ValueError("%s is not a valid schema type" % type)
58
59 jsonschema.validate(body, schema)
60
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000061 @property
62 def http(self):
63 if self._http is None:
Masayuki Igawabc7e1892015-03-03 11:46:48 +090064 self._http = self._get_http()
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000065 return self._http
66
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +040067 def update_image(self, image_id, patch):
68 data = json.dumps(patch)
69 self._validate_schema(data)
70
71 headers = {"Content-Type": "application/openstack-images-v2.0"
72 "-json-patch"}
73 resp, body = self.patch('v2/images/%s' % image_id, data, headers)
David Kranz9c3b3b62014-06-19 16:05:53 -040074 self.expected_success(200, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +000075 return service_client.ResponseBody(resp, self._parse_resp(body))
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +040076
Matthew Treinishce3ef922013-03-11 14:02:46 -040077 def create_image(self, name, container_format, disk_format, **kwargs):
Matthew Treinisha62347f2013-03-01 16:37:30 -050078 params = {
79 "name": name,
80 "container_format": container_format,
81 "disk_format": disk_format,
82 }
Matthew Treinishce3ef922013-03-11 14:02:46 -040083
Sean Daguec6ec4762014-05-29 08:54:21 -040084 for option in kwargs:
85 value = kwargs.get(option)
86 if isinstance(value, dict) or isinstance(value, tuple):
87 params.update(value)
88 else:
89 params[option] = value
Matthew Treinisha62347f2013-03-01 16:37:30 -050090
91 data = json.dumps(params)
92 self._validate_schema(data)
93
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +020094 resp, body = self.post('v2/images', data)
David Kranz9c3b3b62014-06-19 16:05:53 -040095 self.expected_success(201, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -050096 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +000097 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -050098
99 def delete_image(self, image_id):
100 url = 'v2/images/%s' % image_id
David Kranz9c3b3b62014-06-19 16:05:53 -0400101 resp, _ = self.delete(url)
102 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000103 return service_client.ResponseBody(resp)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500104
Ken'ichi Ohmichie3acc122015-05-22 00:32:54 +0000105 def list_images(self, params=None):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500106 url = 'v2/images'
107
108 if params:
109 url += '?%s' % urllib.urlencode(params)
110
111 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400112 self.expected_success(200, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500113 body = json.loads(body)
114 self._validate_schema(body, type='images')
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000115 return service_client.ResponseBodyList(resp, body['images'])
Matthew Treinisha62347f2013-03-01 16:37:30 -0500116
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000117 def show_image(self, image_id):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500118 url = 'v2/images/%s' % image_id
119 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400120 self.expected_success(200, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500121 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000122 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500123
124 def is_resource_deleted(self, id):
125 try:
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000126 self.show_image(id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900127 except lib_exc.NotFound:
Matthew Treinisha62347f2013-03-01 16:37:30 -0500128 return True
129 return False
130
Matt Riedemannd2b96512014-10-13 10:18:16 -0700131 @property
132 def resource_type(self):
133 """Returns the primary type of resource this client works with."""
134 return 'image'
135
Matthew Treinisha62347f2013-03-01 16:37:30 -0500136 def store_image(self, image_id, data):
137 url = 'v2/images/%s/file' % image_id
138 headers = {'Content-Type': 'application/octet-stream'}
139 resp, body = self.http.raw_request('PUT', url, headers=headers,
140 body=data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400141 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000142 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500143
144 def get_image_file(self, image_id):
145 url = 'v2/images/%s/file' % image_id
146 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400147 self.expected_success(200, resp.status)
David Kranzd7e97b42015-02-16 09:37:31 -0500148 return service_client.ResponseBodyData(resp, body)
Anju Tiwaric4952982013-10-20 07:10:02 +0530149
150 def add_image_tag(self, image_id, tag):
151 url = 'v2/images/%s/tags/%s' % (image_id, tag)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200152 resp, body = self.put(url, body=None)
David Kranz9c3b3b62014-06-19 16:05:53 -0400153 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000154 return service_client.ResponseBody(resp, body)
Anju Tiwaric4952982013-10-20 07:10:02 +0530155
156 def delete_image_tag(self, image_id, tag):
157 url = 'v2/images/%s/tags/%s' % (image_id, tag)
158 resp, _ = self.delete(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400159 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000160 return service_client.ResponseBody(resp)
Attila Fazekas689e2652013-10-07 18:06:57 +0200161
Ken'ichi Ohmichif0df53c2015-05-22 01:16:50 +0000162 def list_image_members(self, image_id):
Attila Fazekas689e2652013-10-07 18:06:57 +0200163 url = 'v2/images/%s/members' % image_id
164 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400165 self.expected_success(200, resp.status)
Attila Fazekas689e2652013-10-07 18:06:57 +0200166 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000167 return service_client.ResponseBody(resp, body)
Attila Fazekas689e2652013-10-07 18:06:57 +0200168
169 def add_member(self, image_id, member_id):
170 url = 'v2/images/%s/members' % image_id
171 data = json.dumps({'member': member_id})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200172 resp, body = self.post(url, data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400173 self.expected_success(200, resp.status)
Attila Fazekas689e2652013-10-07 18:06:57 +0200174 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000175 return service_client.ResponseBody(resp, body)
Attila Fazekas689e2652013-10-07 18:06:57 +0200176
177 def update_member_status(self, image_id, member_id, status):
178 """Valid status are: ``pending``, ``accepted``, ``rejected``."""
179 url = 'v2/images/%s/members/%s' % (image_id, member_id)
180 data = json.dumps({'status': status})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200181 resp, body = self.put(url, data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400182 self.expected_success(200, resp.status)
Attila Fazekas689e2652013-10-07 18:06:57 +0200183 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000184 return service_client.ResponseBody(resp, body)
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400185
186 def get_member(self, image_id, member_id):
187 url = 'v2/images/%s/members/%s' % (image_id, member_id)
188 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400189 self.expected_success(200, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000190 return service_client.ResponseBody(resp, json.loads(body))
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400191
192 def remove_member(self, image_id, member_id):
193 url = 'v2/images/%s/members/%s' % (image_id, member_id)
194 resp, _ = self.delete(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400195 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000196 return service_client.ResponseBody(resp)
raiesmh08a1ce3542014-03-04 11:58:29 +0530197
198 def get_schema(self, schema):
199 url = 'v2/schemas/%s' % schema
200 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400201 self.expected_success(200, resp.status)
raiesmh08a1ce3542014-03-04 11:58:29 +0530202 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000203 return service_client.ResponseBody(resp, body)