blob: c5aa41aa0b06243ec9537e469ff194e6bf3581c8 [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 Treinisha62347f2013-03-01 16:37:30 -050016import jsonschema
Matthew Treinish21905512015-07-13 10:33:35 -040017from oslo_serialization import jsonutils as json
Matthew Treinish89128142015-04-23 10:44:30 -040018from six.moves.urllib import parse as urllib
Masayuki Igawabfa07602015-01-20 18:47:17 +090019from tempest_lib import exceptions as lib_exc
Matthew Treinisha62347f2013-03-01 16:37:30 -050020
21from tempest.common import glance_http
Ken'ichi Ohmichi0e836652015-01-08 04:38:56 +000022from tempest.common import service_client
Matthew Treinish684d8992014-01-30 16:27:40 +000023
Matthew Treinisha62347f2013-03-01 16:37:30 -050024
Ken'ichi Ohmichia6287072015-07-02 02:43:15 +000025class ImageClientV2(service_client.ServiceClient):
Matthew Treinisha62347f2013-03-01 16:37:30 -050026
Masayuki Igawabc7e1892015-03-03 11:46:48 +090027 def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
28 build_interval=None, build_timeout=None,
29 disable_ssl_certificate_validation=None, ca_certs=None,
David Kranz85b660b2015-03-23 10:26:52 -040030 trace_requests=None):
Ken'ichi Ohmichia6287072015-07-02 02:43:15 +000031 super(ImageClientV2, self).__init__(
Ken'ichi Ohmichi0690ea42015-01-02 07:03:51 +000032 auth_provider,
Masayuki Igawabc7e1892015-03-03 11:46:48 +090033 catalog_type,
34 region,
35 endpoint_type=endpoint_type,
36 build_interval=build_interval,
37 build_timeout=build_timeout,
38 disable_ssl_certificate_validation=(
39 disable_ssl_certificate_validation),
40 ca_certs=ca_certs,
David Kranz85b660b2015-03-23 10:26:52 -040041 trace_requests=trace_requests)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000042 self._http = None
Masayuki Igawabc7e1892015-03-03 11:46:48 +090043 self.dscv = disable_ssl_certificate_validation
44 self.ca_certs = ca_certs
Matthew Treinisha62347f2013-03-01 16:37:30 -050045
46 def _get_http(self):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000047 return glance_http.HTTPClient(auth_provider=self.auth_provider,
48 filters=self.filters,
Masayuki Igawabc7e1892015-03-03 11:46:48 +090049 insecure=self.dscv,
50 ca_certs=self.ca_certs)
Matthew Treinisha62347f2013-03-01 16:37:30 -050051
Matthew Treinisha62347f2013-03-01 16:37:30 -050052 def _validate_schema(self, body, type='image'):
raiesmh08a1ce3542014-03-04 11:58:29 +053053 if type in ['image', 'images']:
Ken'ichi Ohmichi66494e92015-06-08 04:28:10 +000054 schema = self.show_schema(type)
Matthew Treinisha62347f2013-03-01 16:37:30 -050055 else:
56 raise ValueError("%s is not a valid schema type" % type)
57
58 jsonschema.validate(body, schema)
59
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000060 @property
61 def http(self):
62 if self._http is None:
Masayuki Igawabc7e1892015-03-03 11:46:48 +090063 self._http = self._get_http()
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000064 return self._http
65
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +040066 def update_image(self, image_id, patch):
67 data = json.dumps(patch)
68 self._validate_schema(data)
69
70 headers = {"Content-Type": "application/openstack-images-v2.0"
71 "-json-patch"}
72 resp, body = self.patch('v2/images/%s' % image_id, data, headers)
David Kranz9c3b3b62014-06-19 16:05:53 -040073 self.expected_success(200, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +000074 return service_client.ResponseBody(resp, self._parse_resp(body))
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +040075
Matthew Treinishce3ef922013-03-11 14:02:46 -040076 def create_image(self, name, container_format, disk_format, **kwargs):
Matthew Treinisha62347f2013-03-01 16:37:30 -050077 params = {
78 "name": name,
79 "container_format": container_format,
80 "disk_format": disk_format,
81 }
Matthew Treinishce3ef922013-03-11 14:02:46 -040082
Sean Daguec6ec4762014-05-29 08:54:21 -040083 for option in kwargs:
84 value = kwargs.get(option)
85 if isinstance(value, dict) or isinstance(value, tuple):
86 params.update(value)
87 else:
88 params[option] = value
Matthew Treinisha62347f2013-03-01 16:37:30 -050089
90 data = json.dumps(params)
91 self._validate_schema(data)
92
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +020093 resp, body = self.post('v2/images', data)
David Kranz9c3b3b62014-06-19 16:05:53 -040094 self.expected_success(201, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -050095 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +000096 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -050097
bkopilov81aaae72015-05-15 23:46:25 +030098 def deactivate_image(self, image_id):
99 url = 'v2/images/%s/actions/deactivate' % image_id
100 resp, body = self.post(url, None)
101 self.expected_success(204, resp.status)
102 return service_client.ResponseBody(resp, body)
103
104 def reactivate_image(self, image_id):
105 url = 'v2/images/%s/actions/reactivate' % image_id
106 resp, body = self.post(url, None)
107 self.expected_success(204, resp.status)
108 return service_client.ResponseBody(resp, body)
109
Matthew Treinisha62347f2013-03-01 16:37:30 -0500110 def delete_image(self, image_id):
111 url = 'v2/images/%s' % image_id
David Kranz9c3b3b62014-06-19 16:05:53 -0400112 resp, _ = self.delete(url)
113 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000114 return service_client.ResponseBody(resp)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500115
Ken'ichi Ohmichie3acc122015-05-22 00:32:54 +0000116 def list_images(self, params=None):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500117 url = 'v2/images'
118
119 if params:
120 url += '?%s' % urllib.urlencode(params)
121
122 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400123 self.expected_success(200, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500124 body = json.loads(body)
125 self._validate_schema(body, type='images')
John Warrenf3b3e952015-08-17 19:28:12 +0000126 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500127
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000128 def show_image(self, image_id):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500129 url = 'v2/images/%s' % image_id
130 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400131 self.expected_success(200, resp.status)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500132 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000133 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500134
135 def is_resource_deleted(self, id):
136 try:
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000137 self.show_image(id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900138 except lib_exc.NotFound:
Matthew Treinisha62347f2013-03-01 16:37:30 -0500139 return True
140 return False
141
Matt Riedemannd2b96512014-10-13 10:18:16 -0700142 @property
143 def resource_type(self):
144 """Returns the primary type of resource this client works with."""
145 return 'image'
146
Ken'ichi Ohmichi66494e92015-06-08 04:28:10 +0000147 def store_image_file(self, image_id, data):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500148 url = 'v2/images/%s/file' % image_id
149 headers = {'Content-Type': 'application/octet-stream'}
150 resp, body = self.http.raw_request('PUT', url, headers=headers,
151 body=data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400152 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000153 return service_client.ResponseBody(resp, body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500154
Ken'ichi Ohmichi66494e92015-06-08 04:28:10 +0000155 def load_image_file(self, image_id):
Matthew Treinisha62347f2013-03-01 16:37:30 -0500156 url = 'v2/images/%s/file' % image_id
157 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400158 self.expected_success(200, resp.status)
David Kranzd7e97b42015-02-16 09:37:31 -0500159 return service_client.ResponseBodyData(resp, body)
Anju Tiwaric4952982013-10-20 07:10:02 +0530160
161 def add_image_tag(self, image_id, tag):
162 url = 'v2/images/%s/tags/%s' % (image_id, tag)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200163 resp, body = self.put(url, body=None)
David Kranz9c3b3b62014-06-19 16:05:53 -0400164 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000165 return service_client.ResponseBody(resp, body)
Anju Tiwaric4952982013-10-20 07:10:02 +0530166
167 def delete_image_tag(self, image_id, tag):
168 url = 'v2/images/%s/tags/%s' % (image_id, tag)
169 resp, _ = self.delete(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400170 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000171 return service_client.ResponseBody(resp)
Attila Fazekas689e2652013-10-07 18:06:57 +0200172
Ken'ichi Ohmichif0df53c2015-05-22 01:16:50 +0000173 def list_image_members(self, image_id):
Attila Fazekas689e2652013-10-07 18:06:57 +0200174 url = 'v2/images/%s/members' % image_id
175 resp, body = self.get(url)
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 Ohmichic3728c62015-06-08 04:01:45 +0000180 def add_image_member(self, image_id, member_id):
Attila Fazekas689e2652013-10-07 18:06:57 +0200181 url = 'v2/images/%s/members' % image_id
182 data = json.dumps({'member': member_id})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200183 resp, body = self.post(url, data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400184 self.expected_success(200, resp.status)
Attila Fazekas689e2652013-10-07 18:06:57 +0200185 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000186 return service_client.ResponseBody(resp, body)
Attila Fazekas689e2652013-10-07 18:06:57 +0200187
Ken'ichi Ohmichic3728c62015-06-08 04:01:45 +0000188 def update_image_member(self, image_id, member_id, body):
Attila Fazekas689e2652013-10-07 18:06:57 +0200189 url = 'v2/images/%s/members/%s' % (image_id, member_id)
Ken'ichi Ohmichic3728c62015-06-08 04:01:45 +0000190 data = json.dumps(body)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200191 resp, body = self.put(url, data)
David Kranz9c3b3b62014-06-19 16:05:53 -0400192 self.expected_success(200, resp.status)
Attila Fazekas689e2652013-10-07 18:06:57 +0200193 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000194 return service_client.ResponseBody(resp, body)
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400195
Ken'ichi Ohmichic3728c62015-06-08 04:01:45 +0000196 def show_image_member(self, image_id, member_id):
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400197 url = 'v2/images/%s/members/%s' % (image_id, member_id)
198 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400199 self.expected_success(200, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000200 return service_client.ResponseBody(resp, json.loads(body))
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400201
Ken'ichi Ohmichic3728c62015-06-08 04:01:45 +0000202 def remove_image_member(self, image_id, member_id):
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400203 url = 'v2/images/%s/members/%s' % (image_id, member_id)
204 resp, _ = self.delete(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400205 self.expected_success(204, resp.status)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000206 return service_client.ResponseBody(resp)
raiesmh08a1ce3542014-03-04 11:58:29 +0530207
Ken'ichi Ohmichi66494e92015-06-08 04:28:10 +0000208 def show_schema(self, schema):
raiesmh08a1ce3542014-03-04 11:58:29 +0530209 url = 'v2/schemas/%s' % schema
210 resp, body = self.get(url)
David Kranz9c3b3b62014-06-19 16:05:53 -0400211 self.expected_success(200, resp.status)
raiesmh08a1ce3542014-03-04 11:58:29 +0530212 body = json.loads(body)
Ken'ichi Ohmichia6ac2422015-01-13 01:09:39 +0000213 return service_client.ResponseBody(resp, body)