blob: f50ba2f39be6c4a85812ff83e024ceb7aa708261 [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
13import json
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010014import time
15import urllib
16
Yuiko Takada4d41c2f2014-03-07 11:58:31 +000017from tempest.common import rest_client
Matthew Treinish684d8992014-01-30 16:27:40 +000018from tempest import config
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010019from tempest import exceptions
Matthew Treinishf4a9b0f2013-07-26 16:58:26 -040020from tempest.openstack.common import log as logging
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010021
Matthew Treinish684d8992014-01-30 16:27:40 +000022CONF = config.CONF
23
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010024LOG = logging.getLogger(__name__)
25
26
Yuiko Takada4d41c2f2014-03-07 11:58:31 +000027class SnapshotsClientJSON(rest_client.RestClient):
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010028 """Client class to send CRUD Volume API requests."""
29
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000030 def __init__(self, auth_provider):
31 super(SnapshotsClientJSON, self).__init__(auth_provider)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010032
Matthew Treinish684d8992014-01-30 16:27:40 +000033 self.service = CONF.volume.catalog_type
34 self.build_interval = CONF.volume.build_interval
35 self.build_timeout = CONF.volume.build_timeout
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010036
37 def list_snapshots(self, params=None):
38 """List all the snapshot."""
39 url = 'snapshots'
40 if params:
41 url += '?%s' % urllib.urlencode(params)
42
43 resp, body = self.get(url)
44 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +000045 self.expected_success(200, resp.status)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010046 return resp, body['snapshots']
47
Abhijeet Malawade5945ffe2013-09-17 05:54:44 -070048 def list_snapshots_with_detail(self, params=None):
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010049 """List the details of all snapshots."""
50 url = 'snapshots/detail'
51 if params:
52 url += '?%s' % urllib.urlencode(params)
53
54 resp, body = self.get(url)
55 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +000056 self.expected_success(200, resp.status)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010057 return resp, body['snapshots']
58
59 def get_snapshot(self, snapshot_id):
60 """Returns the details of a single snapshot."""
61 url = "snapshots/%s" % str(snapshot_id)
62 resp, body = self.get(url)
63 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +000064 self.expected_success(200, resp.status)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010065 return resp, body['snapshot']
66
67 def create_snapshot(self, volume_id, **kwargs):
68 """
69 Creates a new snapshot.
70 volume_id(Required): id of the volume.
71 force: Create a snapshot even if the volume attached (Default=False)
72 display_name: Optional snapshot Name.
73 display_description: User friendly snapshot description.
74 """
75 post_body = {'volume_id': volume_id}
76 post_body.update(kwargs)
77 post_body = json.dumps({'snapshot': post_body})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +020078 resp, body = self.post('snapshots', post_body)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010079 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +000080 self.expected_success(200, resp.status)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010081 return resp, body['snapshot']
82
QingXin Mengdc95f5e2013-09-16 19:06:44 -070083 def update_snapshot(self, snapshot_id, **kwargs):
84 """Updates a snapshot."""
85 put_body = json.dumps({'snapshot': kwargs})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +020086 resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
QingXin Mengdc95f5e2013-09-16 19:06:44 -070087 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +000088 self.expected_success(200, resp.status)
QingXin Mengdc95f5e2013-09-16 19:06:44 -070089 return resp, body['snapshot']
90
Attila Fazekasa8b5fe72013-08-01 16:59:06 +020091 # NOTE(afazekas): just for the wait function
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010092 def _get_snapshot_status(self, snapshot_id):
93 resp, body = self.get_snapshot(snapshot_id)
94 status = body['status']
Attila Fazekasa8b5fe72013-08-01 16:59:06 +020095 # NOTE(afazekas): snapshot can reach an "error"
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010096 # state in a "normal" lifecycle
97 if (status == 'error'):
98 raise exceptions.SnapshotBuildErrorException(
Sean Dague14c68182013-04-14 15:34:30 -040099 snapshot_id=snapshot_id)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +0100100
101 return status
102
Attila Fazekasa8b5fe72013-08-01 16:59:06 +0200103 # NOTE(afazkas): Wait reinvented again. It is not in the correct layer
Attila Fazekas36b1fcf2013-01-31 16:41:04 +0100104 def wait_for_snapshot_status(self, snapshot_id, status):
105 """Waits for a Snapshot to reach a given status."""
106 start_time = time.time()
107 old_value = value = self._get_snapshot_status(snapshot_id)
108 while True:
109 dtime = time.time() - start_time
110 time.sleep(self.build_interval)
111 if value != old_value:
112 LOG.info('Value transition from "%s" to "%s"'
113 'in %d second(s).', old_value,
114 value, dtime)
115 if (value == status):
116 return value
117
118 if dtime > self.build_timeout:
119 message = ('Time Limit Exceeded! (%ds)'
120 'while waiting for %s, '
121 'but we got %s.' %
122 (self.build_timeout, status, value))
123 raise exceptions.TimeoutException(message)
124 time.sleep(self.build_interval)
125 old_value = value
126 value = self._get_snapshot_status(snapshot_id)
127
128 def delete_snapshot(self, snapshot_id):
129 """Delete Snapshot."""
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000130 resp, body = self.delete("snapshots/%s" % str(snapshot_id))
131 self.expected_success(202, resp.status)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +0100132
133 def is_resource_deleted(self, id):
134 try:
135 self.get_snapshot(id)
136 except exceptions.NotFound:
137 return True
138 return False
zhangyanzid4d3c6d2013-11-06 09:27:13 +0800139
140 def reset_snapshot_status(self, snapshot_id, status):
141 """Reset the specified snapshot's status."""
142 post_body = json.dumps({'os-reset_status': {"status": status}})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200143 resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000144 self.expected_success(202, resp.status)
zhangyanzid4d3c6d2013-11-06 09:27:13 +0800145 return resp, body
146
147 def update_snapshot_status(self, snapshot_id, status, progress):
148 """Update the specified snapshot's status."""
149 post_body = {
150 'status': status,
151 'progress': progress
152 }
153 post_body = json.dumps({'os-update_snapshot_status': post_body})
154 url = 'snapshots/%s/action' % str(snapshot_id)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200155 resp, body = self.post(url, post_body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000156 self.expected_success(202, resp.status)
zhangyanzid4d3c6d2013-11-06 09:27:13 +0800157 return resp, body
huangtianhua1346d702013-12-09 18:42:35 +0800158
159 def create_snapshot_metadata(self, snapshot_id, metadata):
160 """Create metadata for the snapshot."""
161 put_body = json.dumps({'metadata': metadata})
162 url = "snapshots/%s/metadata" % str(snapshot_id)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200163 resp, body = self.post(url, put_body)
huangtianhua1346d702013-12-09 18:42:35 +0800164 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000165 self.expected_success(200, resp.status)
huangtianhua1346d702013-12-09 18:42:35 +0800166 return resp, body['metadata']
167
168 def get_snapshot_metadata(self, snapshot_id):
169 """Get metadata of the snapshot."""
170 url = "snapshots/%s/metadata" % str(snapshot_id)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200171 resp, body = self.get(url)
huangtianhua1346d702013-12-09 18:42:35 +0800172 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000173 self.expected_success(200, resp.status)
huangtianhua1346d702013-12-09 18:42:35 +0800174 return resp, body['metadata']
175
176 def update_snapshot_metadata(self, snapshot_id, metadata):
177 """Update metadata for the snapshot."""
178 put_body = json.dumps({'metadata': metadata})
179 url = "snapshots/%s/metadata" % str(snapshot_id)
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200180 resp, body = self.put(url, put_body)
huangtianhua1346d702013-12-09 18:42:35 +0800181 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000182 self.expected_success(200, resp.status)
huangtianhua1346d702013-12-09 18:42:35 +0800183 return resp, body['metadata']
184
185 def update_snapshot_metadata_item(self, snapshot_id, id, meta_item):
186 """Update metadata item for the snapshot."""
187 put_body = json.dumps({'meta': meta_item})
188 url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200189 resp, body = self.put(url, put_body)
huangtianhua1346d702013-12-09 18:42:35 +0800190 body = json.loads(body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000191 self.expected_success(200, resp.status)
huangtianhua1346d702013-12-09 18:42:35 +0800192 return resp, body['meta']
193
194 def delete_snapshot_metadata_item(self, snapshot_id, id):
195 """Delete metadata item for the snapshot."""
196 url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200197 resp, body = self.delete(url)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000198 self.expected_success(200, resp.status)
wanghaofa3908c2014-01-15 19:34:03 +0800199
200 def force_delete_snapshot(self, snapshot_id):
201 """Force Delete Snapshot."""
202 post_body = json.dumps({'os-force_delete': {}})
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200203 resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
Swapnil Kulkarnid9df38c2014-08-16 18:06:52 +0000204 self.expected_success(202, resp.status)
wanghaofa3908c2014-01-15 19:34:03 +0800205 return resp, body