blob: 1388e9c09939dde5e120c34c57a37d2180b1db68 [file] [log] [blame]
Attila Fazekas36b1fcf2013-01-31 16:41:04 +01001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010013import time
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010014
Doug Hellmann583ce2c2015-03-11 14:55:46 +000015from oslo_log import log as logging
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
19
Joseph Lanoux6809bab2014-12-18 14:57:18 +000020from tempest.common import service_client
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010021from tempest import exceptions
22
Matthew Treinish684d8992014-01-30 16:27:40 +000023
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010024LOG = logging.getLogger(__name__)
25
26
Ken'ichi Ohmichia6287072015-07-02 02:43:15 +000027class BaseSnapshotsClient(service_client.ServiceClient):
Zhi Kun Liu38641c62014-07-10 20:12:48 +080028 """Base Client class to send CRUD Volume API requests."""
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010029
Ken'ichi Ohmichia39d0be2014-12-17 08:46:11 +000030 create_resp = 200
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010031
Ghanshyam0b75b632015-12-11 15:08:28 +090032 def list_snapshots(self, detail=False, **params):
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010033 """List all the snapshot."""
34 url = 'snapshots'
Ken'ichi Ohmichi35798fb2015-04-06 01:22:41 +000035 if detail:
36 url += '/detail'
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010037 if params:
Ken'ichi Ohmichi35798fb2015-04-06 01:22:41 +000038 url += '?%s' % urllib.urlencode(params)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010039
40 resp, body = self.get(url)
41 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +000042 self.expected_success(200, resp.status)
John Warrenff7faf62015-08-17 16:59:06 +000043 return service_client.ResponseBody(resp, body)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010044
Ken'ichi Ohmichi35798fb2015-04-06 01:22:41 +000045 def show_snapshot(self, snapshot_id):
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010046 """Returns the details of a single snapshot."""
47 url = "snapshots/%s" % str(snapshot_id)
48 resp, body = self.get(url)
49 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +000050 self.expected_success(200, resp.status)
John Warrenff7faf62015-08-17 16:59:06 +000051 return service_client.ResponseBody(resp, body)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010052
Ghanshyam0b75b632015-12-11 15:08:28 +090053 def create_snapshot(self, **kwargs):
Ken'ichi Ohmichib2790842015-11-17 11:46:13 +000054 """Creates a new snapshot.
55
Ghanshyam0b75b632015-12-11 15:08:28 +090056 Available params: see http://developer.openstack.org/
57 api-ref-blockstorage-v2.html#createSnapshot
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010058 """
Ghanshyam0b75b632015-12-11 15:08:28 +090059 post_body = json.dumps({'snapshot': kwargs})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +020060 resp, body = self.post('snapshots', post_body)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010061 body = json.loads(body)
Zhi Kun Liu38641c62014-07-10 20:12:48 +080062 self.expected_success(self.create_resp, resp.status)
John Warrenff7faf62015-08-17 16:59:06 +000063 return service_client.ResponseBody(resp, body)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010064
QingXin Mengdc95f5e2013-09-16 19:06:44 -070065 def update_snapshot(self, snapshot_id, **kwargs):
66 """Updates a snapshot."""
67 put_body = json.dumps({'snapshot': kwargs})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +020068 resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
QingXin Mengdc95f5e2013-09-16 19:06:44 -070069 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +000070 self.expected_success(200, resp.status)
John Warrenff7faf62015-08-17 16:59:06 +000071 return service_client.ResponseBody(resp, body)
QingXin Mengdc95f5e2013-09-16 19:06:44 -070072
Attila Fazekasa8b5fe72013-08-01 16:59:06 +020073 # NOTE(afazekas): just for the wait function
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010074 def _get_snapshot_status(self, snapshot_id):
John Warrenff7faf62015-08-17 16:59:06 +000075 body = self.show_snapshot(snapshot_id)['snapshot']
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010076 status = body['status']
Attila Fazekasa8b5fe72013-08-01 16:59:06 +020077 # NOTE(afazekas): snapshot can reach an "error"
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010078 # state in a "normal" lifecycle
79 if (status == 'error'):
80 raise exceptions.SnapshotBuildErrorException(
Sean Dague14c68182013-04-14 15:34:30 -040081 snapshot_id=snapshot_id)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010082
83 return status
84
Attila Fazekasa8b5fe72013-08-01 16:59:06 +020085 # NOTE(afazkas): Wait reinvented again. It is not in the correct layer
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010086 def wait_for_snapshot_status(self, snapshot_id, status):
87 """Waits for a Snapshot to reach a given status."""
88 start_time = time.time()
89 old_value = value = self._get_snapshot_status(snapshot_id)
90 while True:
91 dtime = time.time() - start_time
92 time.sleep(self.build_interval)
93 if value != old_value:
94 LOG.info('Value transition from "%s" to "%s"'
95 'in %d second(s).', old_value,
96 value, dtime)
97 if (value == status):
98 return value
99
100 if dtime > self.build_timeout:
101 message = ('Time Limit Exceeded! (%ds)'
102 'while waiting for %s, '
103 'but we got %s.' %
104 (self.build_timeout, status, value))
105 raise exceptions.TimeoutException(message)
106 time.sleep(self.build_interval)
107 old_value = value
108 value = self._get_snapshot_status(snapshot_id)
109
110 def delete_snapshot(self, snapshot_id):
111 """Delete Snapshot."""
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000112 resp, body = self.delete("snapshots/%s" % str(snapshot_id))
113 self.expected_success(202, resp.status)
Joseph Lanoux2cdd5502015-01-16 14:46:51 +0000114 return service_client.ResponseBody(resp, body)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +0100115
116 def is_resource_deleted(self, id):
117 try:
Ken'ichi Ohmichi35798fb2015-04-06 01:22:41 +0000118 self.show_snapshot(id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900119 except lib_exc.NotFound:
Attila Fazekas36b1fcf2013-01-31 16:41:04 +0100120 return True
121 return False
zhangyanzid4d3c6d2013-11-06 09:27:13 +0800122
Matt Riedemannd2b96512014-10-13 10:18:16 -0700123 @property
124 def resource_type(self):
125 """Returns the primary type of resource this client works with."""
126 return 'volume-snapshot'
127
zhangyanzid4d3c6d2013-11-06 09:27:13 +0800128 def reset_snapshot_status(self, snapshot_id, status):
129 """Reset the specified snapshot's status."""
130 post_body = json.dumps({'os-reset_status': {"status": status}})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200131 resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000132 self.expected_success(202, resp.status)
Joseph Lanoux6809bab2014-12-18 14:57:18 +0000133 return service_client.ResponseBody(resp, body)
zhangyanzid4d3c6d2013-11-06 09:27:13 +0800134
Ghanshyam0b75b632015-12-11 15:08:28 +0900135 def update_snapshot_status(self, snapshot_id, **kwargs):
zhangyanzid4d3c6d2013-11-06 09:27:13 +0800136 """Update the specified snapshot's status."""
Ghanshyam0b75b632015-12-11 15:08:28 +0900137 # TODO(gmann): api-site doesn't contain doc ref
138 # for this API. After fixing the api-site, we need to
139 # add the link here.
140 # Bug https://bugs.launchpad.net/openstack-api-site/+bug/1532645
141
142 post_body = json.dumps({'os-update_snapshot_status': kwargs})
zhangyanzid4d3c6d2013-11-06 09:27:13 +0800143 url = 'snapshots/%s/action' % str(snapshot_id)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200144 resp, body = self.post(url, post_body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000145 self.expected_success(202, resp.status)
Joseph Lanoux6809bab2014-12-18 14:57:18 +0000146 return service_client.ResponseBody(resp, body)
huangtianhua1346d702013-12-09 18:42:35 +0800147
148 def create_snapshot_metadata(self, snapshot_id, metadata):
149 """Create metadata for the snapshot."""
150 put_body = json.dumps({'metadata': metadata})
151 url = "snapshots/%s/metadata" % str(snapshot_id)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200152 resp, body = self.post(url, put_body)
huangtianhua1346d702013-12-09 18:42:35 +0800153 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000154 self.expected_success(200, resp.status)
John Warrenff7faf62015-08-17 16:59:06 +0000155 return service_client.ResponseBody(resp, body)
huangtianhua1346d702013-12-09 18:42:35 +0800156
Ken'ichi Ohmichi35798fb2015-04-06 01:22:41 +0000157 def show_snapshot_metadata(self, snapshot_id):
huangtianhua1346d702013-12-09 18:42:35 +0800158 """Get metadata of the snapshot."""
159 url = "snapshots/%s/metadata" % str(snapshot_id)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200160 resp, body = self.get(url)
huangtianhua1346d702013-12-09 18:42:35 +0800161 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000162 self.expected_success(200, resp.status)
John Warrenff7faf62015-08-17 16:59:06 +0000163 return service_client.ResponseBody(resp, body)
huangtianhua1346d702013-12-09 18:42:35 +0800164
piyush11078661fd3f02015-12-24 17:09:45 +0530165 def update_snapshot_metadata(self, snapshot_id, **kwargs):
huangtianhua1346d702013-12-09 18:42:35 +0800166 """Update metadata for the snapshot."""
piyush11078661fd3f02015-12-24 17:09:45 +0530167 # TODO(piyush): Current api-site doesn't contain this API description.
168 # After fixing the api-site, we need to fix here also for putting the
169 # link to api-site.
170 # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1529063
171 put_body = json.dumps(kwargs)
huangtianhua1346d702013-12-09 18:42:35 +0800172 url = "snapshots/%s/metadata" % str(snapshot_id)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200173 resp, body = self.put(url, put_body)
huangtianhua1346d702013-12-09 18:42:35 +0800174 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000175 self.expected_success(200, resp.status)
John Warrenff7faf62015-08-17 16:59:06 +0000176 return service_client.ResponseBody(resp, body)
huangtianhua1346d702013-12-09 18:42:35 +0800177
piyush11078661fd3f02015-12-24 17:09:45 +0530178 def update_snapshot_metadata_item(self, snapshot_id, id, **kwargs):
huangtianhua1346d702013-12-09 18:42:35 +0800179 """Update metadata item for the snapshot."""
piyush11078661fd3f02015-12-24 17:09:45 +0530180 # TODO(piyush): Current api-site doesn't contain this API description.
181 # After fixing the api-site, we need to fix here also for putting the
182 # link to api-site.
183 # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1529064
184 put_body = json.dumps(kwargs)
huangtianhua1346d702013-12-09 18:42:35 +0800185 url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200186 resp, body = self.put(url, put_body)
huangtianhua1346d702013-12-09 18:42:35 +0800187 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000188 self.expected_success(200, resp.status)
John Warrenff7faf62015-08-17 16:59:06 +0000189 return service_client.ResponseBody(resp, body)
huangtianhua1346d702013-12-09 18:42:35 +0800190
191 def delete_snapshot_metadata_item(self, snapshot_id, id):
192 """Delete metadata item for the snapshot."""
193 url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200194 resp, body = self.delete(url)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000195 self.expected_success(200, resp.status)
Joseph Lanoux2cdd5502015-01-16 14:46:51 +0000196 return service_client.ResponseBody(resp, body)
wanghaofa3908c2014-01-15 19:34:03 +0800197
198 def force_delete_snapshot(self, snapshot_id):
199 """Force Delete Snapshot."""
200 post_body = json.dumps({'os-force_delete': {}})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200201 resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000202 self.expected_success(202, resp.status)
Joseph Lanoux6809bab2014-12-18 14:57:18 +0000203 return service_client.ResponseBody(resp, body)