Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / compute.py @ a2ef112e

History | View | Annotate | Download (8.9 kB)

1 a1c50326 Giorgos Verigakis
# Copyright 2011 GRNET S.A. All rights reserved.
2 a1c50326 Giorgos Verigakis
#
3 a1c50326 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 a1c50326 Giorgos Verigakis
# without modification, are permitted provided that the following
5 a1c50326 Giorgos Verigakis
# conditions are met:
6 a1c50326 Giorgos Verigakis
#
7 a1c50326 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 a1c50326 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 a1c50326 Giorgos Verigakis
#      disclaimer.
10 a1c50326 Giorgos Verigakis
#
11 a1c50326 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 a1c50326 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 a1c50326 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 a1c50326 Giorgos Verigakis
#      provided with the distribution.
15 a1c50326 Giorgos Verigakis
#
16 a1c50326 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 a1c50326 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 a1c50326 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 a1c50326 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 a1c50326 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 a1c50326 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 a1c50326 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 a1c50326 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 a1c50326 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 a1c50326 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 a1c50326 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 a1c50326 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 a1c50326 Giorgos Verigakis
#
29 a1c50326 Giorgos Verigakis
# The views and conclusions contained in the software and
30 a1c50326 Giorgos Verigakis
# documentation are those of the authors and should not be
31 a1c50326 Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 a1c50326 Giorgos Verigakis
# or implied, of GRNET S.A.
33 a1c50326 Giorgos Verigakis
34 606fe15f Stavros Sachtouris
from kamaki.clients import ClientError
35 606fe15f Stavros Sachtouris
from kamaki.clients.compute_rest_api import ComputeClientApi
36 c270fe96 Stavros Sachtouris
from kamaki.clients.utils import path4url
37 bf966740 Stavros Sachtouris
import json
38 a1c50326 Giorgos Verigakis
39 3dabe5d2 Stavros Sachtouris
40 606fe15f Stavros Sachtouris
class ComputeClient(ComputeClientApi):
41 d2cea1e2 Giorgos Verigakis
    """OpenStack Compute API 1.1 client"""
42 2f749e6e Stavros Sachtouris
43 a1c50326 Giorgos Verigakis
    def list_servers(self, detail=False):
44 a2ef112e Stavros Sachtouris
        """
45 a2ef112e Stavros Sachtouris
        :param detail: if true, append full server details to each item
46 a2ef112e Stavros Sachtouris

47 a2ef112e Stavros Sachtouris
        :returns: list of server ids and names
48 a2ef112e Stavros Sachtouris
        """
49 6666f3b3 Stavros Sachtouris
        detail = 'detail' if detail else ''
50 6666f3b3 Stavros Sachtouris
        r = self.servers_get(command=detail)
51 6a0b1658 Giorgos Verigakis
        return r.json['servers']['values']
52 3dabe5d2 Stavros Sachtouris
53 c92d159d Stavros Sachtouris
    def get_server_details(self, server_id, **kwargs):
54 a2ef112e Stavros Sachtouris
        """Return detailed info for a server
55 a2ef112e Stavros Sachtouris

56 a2ef112e Stavros Sachtouris
        :param server_id: integer (int or str)
57 a2ef112e Stavros Sachtouris

58 a2ef112e Stavros Sachtouris
        :returns: dict with server details
59 a2ef112e Stavros Sachtouris
        """
60 c92d159d Stavros Sachtouris
        r = self.servers_get(server_id, **kwargs)
61 6a0b1658 Giorgos Verigakis
        return r.json['server']
62 3dabe5d2 Stavros Sachtouris
63 a1c50326 Giorgos Verigakis
    def create_server(self, name, flavor_id, image_id, personality=None):
64 a1c50326 Giorgos Verigakis
        """Submit request to create a new server
65 a1c50326 Giorgos Verigakis

66 a2ef112e Stavros Sachtouris
        :param name: (str)
67 a2ef112e Stavros Sachtouris

68 a2ef112e Stavros Sachtouris
        :param flavor_id: integer id denoting a preset hardware configuration
69 a2ef112e Stavros Sachtouris

70 a2ef112e Stavros Sachtouris
        :param image_id: (str) id denoting the OS image to run on the VM
71 a1c50326 Giorgos Verigakis

72 a2ef112e Stavros Sachtouris
        :param personality: a list of (file path, file contents) tuples,
73 a2ef112e Stavros Sachtouris
            describing files to be injected into VM upon creation.
74 a1c50326 Giorgos Verigakis

75 a2ef112e Stavros Sachtouris
        :returns: a dict with the new VMs details
76 a2ef112e Stavros Sachtouris

77 a2ef112e Stavros Sachtouris
        :raises ClientError: wraps request errors
78 a1c50326 Giorgos Verigakis
        """
79 6a0b1658 Giorgos Verigakis
        req = {'server': {'name': name,
80 6a0b1658 Giorgos Verigakis
                          'flavorRef': flavor_id,
81 6a0b1658 Giorgos Verigakis
                          'imageRef': image_id}}
82 ae3c77f9 Stavros Sachtouris
83 ae3c77f9 Stavros Sachtouris
        image = self.get_image_details(image_id)
84 ae3c77f9 Stavros Sachtouris
        img_meta = image['metadata']['values']
85 ae3c77f9 Stavros Sachtouris
        metadata = {}
86 ae3c77f9 Stavros Sachtouris
        for key in ('os', 'users'):
87 ae3c77f9 Stavros Sachtouris
            try:
88 ae3c77f9 Stavros Sachtouris
                metadata[key] = img_meta[key]
89 ae3c77f9 Stavros Sachtouris
            except KeyError:
90 ae3c77f9 Stavros Sachtouris
                pass
91 ae3c77f9 Stavros Sachtouris
        if metadata:
92 ae3c77f9 Stavros Sachtouris
            req['server']['metadata'] = metadata
93 ae3c77f9 Stavros Sachtouris
94 a1c50326 Giorgos Verigakis
        if personality:
95 c4922a05 Giorgos Verigakis
            req['server']['personality'] = personality
96 3dabe5d2 Stavros Sachtouris
97 486e55f4 Stavros Sachtouris
        try:
98 486e55f4 Stavros Sachtouris
            r = self.servers_post(json_data=req)
99 486e55f4 Stavros Sachtouris
        except ClientError as err:
100 486e55f4 Stavros Sachtouris
            try:
101 3dabe5d2 Stavros Sachtouris
                tmp_err = err.details.split(',')
102 3dabe5d2 Stavros Sachtouris
                tmp_err = tmp_err[0].split(':')
103 3dabe5d2 Stavros Sachtouris
                tmp_err = tmp_err[2].split('"')
104 3dabe5d2 Stavros Sachtouris
                err.message = tmp_err[1]
105 486e55f4 Stavros Sachtouris
            finally:
106 486e55f4 Stavros Sachtouris
                raise err
107 6a0b1658 Giorgos Verigakis
        return r.json['server']
108 3dabe5d2 Stavros Sachtouris
109 a1c50326 Giorgos Verigakis
    def update_server_name(self, server_id, new_name):
110 a2ef112e Stavros Sachtouris
        """Update the name of the server as reported by the API (does not
111 a2ef112e Stavros Sachtouris
            modify the hostname used inside the VM)
112 a2ef112e Stavros Sachtouris

113 a2ef112e Stavros Sachtouris
        :param server_id: integer (str or int)
114 a1c50326 Giorgos Verigakis

115 a2ef112e Stavros Sachtouris
        :param new_name: (str) 
116 a1c50326 Giorgos Verigakis
        """
117 6a0b1658 Giorgos Verigakis
        req = {'server': {'name': new_name}}
118 6ce9fc72 Stavros Sachtouris
        r = self.servers_put(server_id, json_data=req)
119 6ce9fc72 Stavros Sachtouris
        r.release()
120 3dabe5d2 Stavros Sachtouris
121 a1c50326 Giorgos Verigakis
    def delete_server(self, server_id):
122 a2ef112e Stavros Sachtouris
        """Submit a deletion request for a server specified by id
123 a2ef112e Stavros Sachtouris

124 a2ef112e Stavros Sachtouris
        :param server_id: integer (str or int)
125 a2ef112e Stavros Sachtouris
        """
126 6ce9fc72 Stavros Sachtouris
        r = self.servers_delete(server_id)
127 6ce9fc72 Stavros Sachtouris
        r.release()
128 6ce9fc72 Stavros Sachtouris
129 a1c50326 Giorgos Verigakis
    def reboot_server(self, server_id, hard=False):
130 a2ef112e Stavros Sachtouris
        """
131 a2ef112e Stavros Sachtouris
        :param server_id: integer (str or int)
132 a2ef112e Stavros Sachtouris

133 a2ef112e Stavros Sachtouris
        :param hard: perform a hard reboot if true, soft reboot otherwise
134 a2ef112e Stavros Sachtouris
        """
135 6a0b1658 Giorgos Verigakis
        type = 'HARD' if hard else 'SOFT'
136 6a0b1658 Giorgos Verigakis
        req = {'reboot': {'type': type}}
137 6ce9fc72 Stavros Sachtouris
        r = self.servers_post(server_id, 'action', json_data=req)
138 6ce9fc72 Stavros Sachtouris
        r.release()
139 3dabe5d2 Stavros Sachtouris
140 6666f3b3 Stavros Sachtouris
    def get_server_metadata(self, server_id, key=''):
141 a2ef112e Stavros Sachtouris
        """
142 a2ef112e Stavros Sachtouris
        :param server_id: integer (str or int)
143 a2ef112e Stavros Sachtouris

144 a2ef112e Stavros Sachtouris
        :param key: (str) the metadatum key (all metadata if not given)
145 a2ef112e Stavros Sachtouris

146 a2ef112e Stavros Sachtouris
        :returns: a key:val dict of requests metadata
147 a2ef112e Stavros Sachtouris
        """
148 6666f3b3 Stavros Sachtouris
        command = path4url('meta', key)
149 6666f3b3 Stavros Sachtouris
        r = self.servers_get(server_id, command)
150 6666f3b3 Stavros Sachtouris
        return r.json['meta'] if key != '' else r.json['metadata']['values']
151 3dabe5d2 Stavros Sachtouris
152 a1c50326 Giorgos Verigakis
    def create_server_metadata(self, server_id, key, val):
153 a2ef112e Stavros Sachtouris
        """
154 a2ef112e Stavros Sachtouris
        :param server_id: integer (str or int)
155 a2ef112e Stavros Sachtouris

156 a2ef112e Stavros Sachtouris
        :param key: (str)
157 a2ef112e Stavros Sachtouris

158 a2ef112e Stavros Sachtouris
        :param val: (str)
159 a2ef112e Stavros Sachtouris

160 a2ef112e Stavros Sachtouris
        :returns: dict of updated key:val metadata
161 a2ef112e Stavros Sachtouris
        """
162 6a0b1658 Giorgos Verigakis
        req = {'meta': {key: val}}
163 3dabe5d2 Stavros Sachtouris
        r = self.servers_put(server_id,
164 3dabe5d2 Stavros Sachtouris
            'meta/' + key,
165 3dabe5d2 Stavros Sachtouris
            json_data=req,
166 3dabe5d2 Stavros Sachtouris
            success=201)
167 6a0b1658 Giorgos Verigakis
        return r.json['meta']
168 3dabe5d2 Stavros Sachtouris
169 a1c50326 Giorgos Verigakis
    def update_server_metadata(self, server_id, **metadata):
170 a2ef112e Stavros Sachtouris
        """
171 a2ef112e Stavros Sachtouris
        :param server_id: integer (str or int)
172 a2ef112e Stavros Sachtouris

173 a2ef112e Stavros Sachtouris
        :param metadata: dict of key:val metadata
174 a2ef112e Stavros Sachtouris

175 a2ef112e Stavros Sachtouris
        :returns: dict of updated key:val metadata
176 a2ef112e Stavros Sachtouris
        """
177 6a0b1658 Giorgos Verigakis
        req = {'metadata': metadata}
178 6666f3b3 Stavros Sachtouris
        r = self.servers_post(server_id, 'meta', json_data=req, success=201)
179 6a0b1658 Giorgos Verigakis
        return r.json['metadata']
180 3dabe5d2 Stavros Sachtouris
181 a1c50326 Giorgos Verigakis
    def delete_server_metadata(self, server_id, key):
182 a2ef112e Stavros Sachtouris
        """
183 a2ef112e Stavros Sachtouris
        :param server_id: integer (str or int)
184 a2ef112e Stavros Sachtouris

185 a2ef112e Stavros Sachtouris
        :param key: (str) the meta key
186 a2ef112e Stavros Sachtouris
        """
187 3dabe5d2 Stavros Sachtouris
        r = self.servers_delete(server_id, 'meta/' + key)
188 6ce9fc72 Stavros Sachtouris
        r.release()
189 6666f3b3 Stavros Sachtouris
190 a2ef112e Stavros Sachtouris
    def list_flavors(self, detail=False):
191 6666f3b3 Stavros Sachtouris
        """
192 a2ef112e Stavros Sachtouris
        :param detail: (bool) detailed flavor info if set, short if not
193 6666f3b3 Stavros Sachtouris

194 a2ef112e Stavros Sachtouris
        :returns: (dict) flavor info
195 a2ef112e Stavros Sachtouris
        """
196 6666f3b3 Stavros Sachtouris
        detail = 'detail' if detail else ''
197 9bdc89da Stavros Sachtouris
        r = self.flavors_get(command='detail')
198 6a0b1658 Giorgos Verigakis
        return r.json['flavors']['values']
199 a1c50326 Giorgos Verigakis
200 a1c50326 Giorgos Verigakis
    def get_flavor_details(self, flavor_id):
201 a2ef112e Stavros Sachtouris
        """
202 a2ef112e Stavros Sachtouris
        :param flavor_id: integer (str or int)
203 a2ef112e Stavros Sachtouris

204 a2ef112e Stavros Sachtouris
        :returns: dict
205 a2ef112e Stavros Sachtouris
        """
206 6666f3b3 Stavros Sachtouris
        r = self.flavors_get(flavor_id)
207 6a0b1658 Giorgos Verigakis
        return r.json['flavor']
208 6666f3b3 Stavros Sachtouris
209 a1c50326 Giorgos Verigakis
    def list_images(self, detail=False):
210 a2ef112e Stavros Sachtouris
        """
211 a2ef112e Stavros Sachtouris
        :param detail: (bool) detailed info if set, short if not
212 a2ef112e Stavros Sachtouris

213 a2ef112e Stavros Sachtouris
        :returns: dict id,name + full info if detail
214 a2ef112e Stavros Sachtouris
        """
215 14af08c0 Stavros Sachtouris
        detail = 'detail' if detail else ''
216 6666f3b3 Stavros Sachtouris
        r = self.images_get(command=detail)
217 6a0b1658 Giorgos Verigakis
        return r.json['images']['values']
218 3dabe5d2 Stavros Sachtouris
219 71286858 Stavros Sachtouris
    def get_image_details(self, image_id, **kwargs):
220 a2ef112e Stavros Sachtouris
        """
221 a2ef112e Stavros Sachtouris
        :param image_id: integer (str or int)
222 a2ef112e Stavros Sachtouris

223 a2ef112e Stavros Sachtouris
        :returns: dict
224 a2ef112e Stavros Sachtouris

225 a2ef112e Stavros Sachtouris
        :raises ClientError: 404 if image not available
226 a2ef112e Stavros Sachtouris
        """
227 71286858 Stavros Sachtouris
        r = self.images_get(image_id, **kwargs)
228 71286858 Stavros Sachtouris
        try:
229 71286858 Stavros Sachtouris
            return r.json['image']
230 71286858 Stavros Sachtouris
        except KeyError:
231 71286858 Stavros Sachtouris
            raise ClientError('Image not available', 404,
232 71286858 Stavros Sachtouris
                details='Image %d not found or not accessible')
233 3dabe5d2 Stavros Sachtouris
234 a1c50326 Giorgos Verigakis
    def delete_image(self, image_id):
235 a2ef112e Stavros Sachtouris
        """
236 a2ef112e Stavros Sachtouris
        :param image_id: (str)
237 a2ef112e Stavros Sachtouris
        """
238 6ce9fc72 Stavros Sachtouris
        r = self.images_delete(image_id)
239 6ce9fc72 Stavros Sachtouris
        r.release()
240 6666f3b3 Stavros Sachtouris
241 6666f3b3 Stavros Sachtouris
    def get_image_metadata(self, image_id, key=''):
242 a2ef112e Stavros Sachtouris
        """
243 a2ef112e Stavros Sachtouris
        :param image_id: (str)
244 a2ef112e Stavros Sachtouris

245 a2ef112e Stavros Sachtouris
        :param key: (str) the metadatum key
246 a2ef112e Stavros Sachtouris

247 a2ef112e Stavros Sachtouris
        :returns (dict) metadata if key not set, specific metadatum otherwise
248 a2ef112e Stavros Sachtouris
        """
249 6666f3b3 Stavros Sachtouris
        command = path4url('meta', key)
250 6666f3b3 Stavros Sachtouris
        r = self.images_get(image_id, command)
251 a2ef112e Stavros Sachtouris
        return r.json['meta'] if key else r.json['metadata']['values']
252 3dabe5d2 Stavros Sachtouris
253 a1c50326 Giorgos Verigakis
    def create_image_metadata(self, image_id, key, val):
254 a2ef112e Stavros Sachtouris
        """
255 a2ef112e Stavros Sachtouris
        :param image_id: integer (str or int)
256 a2ef112e Stavros Sachtouris

257 a2ef112e Stavros Sachtouris
        :param key: (str) metadatum key
258 a2ef112e Stavros Sachtouris

259 a2ef112e Stavros Sachtouris
        :param val: (str) metadatum value
260 a2ef112e Stavros Sachtouris

261 a2ef112e Stavros Sachtouris
        :returns: (dict) updated metadata
262 a2ef112e Stavros Sachtouris
        """
263 6a0b1658 Giorgos Verigakis
        req = {'meta': {key: val}}
264 3dabe5d2 Stavros Sachtouris
        r = self.images_put(image_id, 'meta/' + key, json_data=req)
265 6a0b1658 Giorgos Verigakis
        return r.json['meta']
266 a1c50326 Giorgos Verigakis
267 a1c50326 Giorgos Verigakis
    def update_image_metadata(self, image_id, **metadata):
268 a2ef112e Stavros Sachtouris
        """
269 a2ef112e Stavros Sachtouris
        :param image_id: (str)
270 a2ef112e Stavros Sachtouris

271 a2ef112e Stavros Sachtouris
        :param metadata: dict
272 a2ef112e Stavros Sachtouris

273 a2ef112e Stavros Sachtouris
        :returns: updated metadata
274 a2ef112e Stavros Sachtouris
        """
275 6a0b1658 Giorgos Verigakis
        req = {'metadata': metadata}
276 3dabe5d2 Stavros Sachtouris
        r = self.images_post(image_id, 'meta', json_data=req)
277 6a0b1658 Giorgos Verigakis
        return r.json['metadata']
278 a1c50326 Giorgos Verigakis
279 a1c50326 Giorgos Verigakis
    def delete_image_metadata(self, image_id, key):
280 a2ef112e Stavros Sachtouris
        """
281 a2ef112e Stavros Sachtouris
        :param image_id: (str)
282 a2ef112e Stavros Sachtouris

283 a2ef112e Stavros Sachtouris
        :param key: (str) metadatum key
284 a2ef112e Stavros Sachtouris
        """
285 6666f3b3 Stavros Sachtouris
        command = path4url('meta', key)
286 6ce9fc72 Stavros Sachtouris
        r = self.images_delete(image_id, command)
287 6ce9fc72 Stavros Sachtouris
        r.release()