blob: 017ca95631489c66d701a8a8906b457e29e02a94 [file] [log] [blame]
Attila Fazekas36b1fcf2013-01-31 16:41:04 +01001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010015import time
16import urllib
17
18from lxml import etree
19
20from tempest.common.rest_client import RestClientXML
21from tempest import exceptions
Matthew Treinishf4a9b0f2013-07-26 16:58:26 -040022from tempest.openstack.common import log as logging
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010023from tempest.services.compute.xml.common import Document
24from tempest.services.compute.xml.common import Element
25from tempest.services.compute.xml.common import xml_to_json
26from tempest.services.compute.xml.common import XMLNS_11
27
28LOG = logging.getLogger(__name__)
29
30
31class SnapshotsClientXML(RestClientXML):
32 """Client class to send CRUD Volume API requests."""
33
34 def __init__(self, config, username, password, auth_url, tenant_name=None):
35 super(SnapshotsClientXML, self).__init__(config, username, password,
36 auth_url, tenant_name)
37
38 self.service = self.config.volume.catalog_type
39 self.build_interval = self.config.volume.build_interval
40 self.build_timeout = self.config.volume.build_timeout
41
42 def list_snapshots(self, params=None):
43 """List all snapshot."""
44 url = 'snapshots'
45
46 if params:
47 url += '?%s' % urllib.urlencode(params)
48
49 resp, body = self.get(url, self.headers)
50 body = etree.fromstring(body)
Giulio Fidentee92956b2013-06-06 18:38:48 +020051 snapshots = []
52 for snap in body:
53 snapshots.append(xml_to_json(snap))
54 return resp, snapshots
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010055
56 def list_snapshots_with_detail(self, params=None):
57 """List all the details of snapshot."""
58 url = 'snapshots/detail'
59
60 if params:
61 url += '?%s' % urllib.urlencode(params)
62
63 resp, body = self.get(url, self.headers)
64 body = etree.fromstring(body)
65 snapshots = []
Giulio Fidentee92956b2013-06-06 18:38:48 +020066 for snap in body:
67 snapshots.append(xml_to_json(snap))
68 return resp, snapshots
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010069
70 def get_snapshot(self, snapshot_id):
71 """Returns the details of a single snapshot."""
72 url = "snapshots/%s" % str(snapshot_id)
73 resp, body = self.get(url, self.headers)
74 body = etree.fromstring(body)
75 return resp, xml_to_json(body)
76
77 def create_snapshot(self, volume_id, **kwargs):
Attila Fazekasb2902af2013-02-16 16:22:44 +010078 """Creates a new snapshot.
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010079 volume_id(Required): id of the volume.
80 force: Create a snapshot even if the volume attached (Default=False)
81 display_name: Optional snapshot Name.
82 display_description: User friendly snapshot description.
83 """
84 #NOTE(afazekas): it should use the volume namaspace
85 snapshot = Element("snapshot", xmlns=XMLNS_11, volume_id=volume_id)
86 for key, value in kwargs.items():
87 snapshot.add_attr(key, value)
88 resp, body = self.post('snapshots', str(Document(snapshot)),
89 self.headers)
90 body = xml_to_json(etree.fromstring(body))
91 return resp, body
92
Attila Fazekas36b1fcf2013-01-31 16:41:04 +010093 #NOTE(afazekas): just for the wait function
94 def _get_snapshot_status(self, snapshot_id):
95 resp, body = self.get_snapshot(snapshot_id)
96 status = body['status']
97 #NOTE(afazekas): snapshot can reach an "error"
98 # state in a "normal" lifecycle
99 if (status == 'error'):
100 raise exceptions.SnapshotBuildErrorException(
Sean Dague14c68182013-04-14 15:34:30 -0400101 snapshot_id=snapshot_id)
Attila Fazekas36b1fcf2013-01-31 16:41:04 +0100102
103 return status
104
105 #NOTE(afazkas): Wait reinvented again. It is not in the correct layer
106 def wait_for_snapshot_status(self, snapshot_id, status):
107 """Waits for a Snapshot to reach a given status."""
108 start_time = time.time()
109 old_value = value = self._get_snapshot_status(snapshot_id)
110 while True:
111 dtime = time.time() - start_time
112 time.sleep(self.build_interval)
113 if value != old_value:
114 LOG.info('Value transition from "%s" to "%s"'
115 'in %d second(s).', old_value,
116 value, dtime)
117 if (value == status):
118 return value
119
120 if dtime > self.build_timeout:
121 message = ('Time Limit Exceeded! (%ds)'
122 'while waiting for %s, '
123 'but we got %s.' %
124 (self.build_timeout, status, value))
125 raise exceptions.TimeoutException(message)
126 time.sleep(self.build_interval)
127 old_value = value
128 value = self._get_snapshot_status(snapshot_id)
129
130 def delete_snapshot(self, snapshot_id):
131 """Delete Snapshot."""
132 return self.delete("snapshots/%s" % str(snapshot_id))
133
134 def is_resource_deleted(self, id):
135 try:
136 self.get_snapshot(id)
137 except exceptions.NotFound:
138 return True
139 return False