Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / compute.py @ 890e1a48

History | View | Annotate | Download (6.6 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 df79206f Giorgos Verigakis
from . import Client, ClientError
35 a1c50326 Giorgos Verigakis
36 a1c50326 Giorgos Verigakis
37 df79206f Giorgos Verigakis
class ComputeClient(Client):
38 d2cea1e2 Giorgos Verigakis
    """OpenStack Compute API 1.1 client"""
39 d2cea1e2 Giorgos Verigakis
    
40 df79206f Giorgos Verigakis
    def raise_for_status(self, r):
41 df79206f Giorgos Verigakis
        d = r.json
42 df79206f Giorgos Verigakis
        key = d.keys()[0]
43 df79206f Giorgos Verigakis
        val = d[key]
44 df79206f Giorgos Verigakis
        message = '%s: %s' % (key, val.get('message', ''))
45 df79206f Giorgos Verigakis
        details = val.get('details', '')
46 df79206f Giorgos Verigakis
        raise ClientError(message, r.status_code, details)
47 d2cea1e2 Giorgos Verigakis
    
48 a1c50326 Giorgos Verigakis
    def list_servers(self, detail=False):
49 a1c50326 Giorgos Verigakis
        """List servers, returned detailed output if detailed is True"""
50 df79206f Giorgos Verigakis
        
51 a1c50326 Giorgos Verigakis
        path = '/servers/detail' if detail else '/servers'
52 df79206f Giorgos Verigakis
        r = self.get(path, success=200)
53 df79206f Giorgos Verigakis
        return r.json['servers']['values']
54 a1c50326 Giorgos Verigakis
    
55 a1c50326 Giorgos Verigakis
    def get_server_details(self, server_id):
56 a1c50326 Giorgos Verigakis
        """Return detailed output on a server specified by its id"""
57 df79206f Giorgos Verigakis
        
58 df79206f Giorgos Verigakis
        path = '/servers/%s' % (server_id,)
59 df79206f Giorgos Verigakis
        r = self.get(path, success=200)
60 df79206f Giorgos Verigakis
        return r.json['server']
61 a1c50326 Giorgos Verigakis
    
62 a1c50326 Giorgos Verigakis
    def create_server(self, name, flavor_id, image_id, personality=None):
63 a1c50326 Giorgos Verigakis
        """Submit request to create a new server
64 a1c50326 Giorgos Verigakis

65 a1c50326 Giorgos Verigakis
        The flavor_id specifies the hardware configuration to use,
66 a1c50326 Giorgos Verigakis
        the image_id specifies the OS Image to be deployed inside the new
67 a1c50326 Giorgos Verigakis
        server.
68 a1c50326 Giorgos Verigakis

69 a1c50326 Giorgos Verigakis
        The personality argument is a list of (file path, file contents)
70 a1c50326 Giorgos Verigakis
        tuples, describing files to be injected into the server upon creation.
71 a1c50326 Giorgos Verigakis

72 a1c50326 Giorgos Verigakis
        The call returns a dictionary describing the newly created server.
73 a1c50326 Giorgos Verigakis
        """
74 df79206f Giorgos Verigakis
        req = {'server': {'name': name,
75 df79206f Giorgos Verigakis
                          'flavorRef': flavor_id,
76 df79206f Giorgos Verigakis
                          'imageRef': image_id}}
77 a1c50326 Giorgos Verigakis
        if personality:
78 2394d9e1 Giorgos Verigakis
            req['server']['personality'] = personality
79 a1c50326 Giorgos Verigakis
        
80 df79206f Giorgos Verigakis
        r = self.post('/servers', json=req, success=202)
81 df79206f Giorgos Verigakis
        return r.json['server']
82 a1c50326 Giorgos Verigakis
    
83 a1c50326 Giorgos Verigakis
    def update_server_name(self, server_id, new_name):
84 a1c50326 Giorgos Verigakis
        """Update the name of the server as reported by the API.
85 a1c50326 Giorgos Verigakis

86 a1c50326 Giorgos Verigakis
        This call does not modify the hostname actually used by the server
87 a1c50326 Giorgos Verigakis
        internally.
88 a1c50326 Giorgos Verigakis
        """
89 df79206f Giorgos Verigakis
        path = '/servers/%s' % (server_id,)
90 df79206f Giorgos Verigakis
        req = {'server': {'name': new_name}}
91 df79206f Giorgos Verigakis
        self.put(path, json=req, success=204)
92 a1c50326 Giorgos Verigakis
    
93 a1c50326 Giorgos Verigakis
    def delete_server(self, server_id):
94 a1c50326 Giorgos Verigakis
        """Submit a deletion request for a server specified by id"""
95 df79206f Giorgos Verigakis
        
96 df79206f Giorgos Verigakis
        path = '/servers/%s' % (server_id,)
97 df79206f Giorgos Verigakis
        self.delete(path, success=204)
98 a1c50326 Giorgos Verigakis
    
99 a1c50326 Giorgos Verigakis
    def reboot_server(self, server_id, hard=False):
100 a1c50326 Giorgos Verigakis
        """Submit a reboot request for a server specified by id"""
101 a1c50326 Giorgos Verigakis
        
102 df79206f Giorgos Verigakis
        path = '/servers/%s/action' % (server_id,)
103 df79206f Giorgos Verigakis
        type = 'HARD' if hard else 'SOFT'
104 df79206f Giorgos Verigakis
        req = {'reboot': {'type': type}}
105 df79206f Giorgos Verigakis
        self.post(path, json=req, success=202)
106 df79206f Giorgos Verigakis
    
107 a1c50326 Giorgos Verigakis
    def get_server_metadata(self, server_id, key=None):
108 df79206f Giorgos Verigakis
        path = '/servers/%s/meta' % (server_id,)
109 a1c50326 Giorgos Verigakis
        if key:
110 a1c50326 Giorgos Verigakis
            path += '/%s' % key
111 df79206f Giorgos Verigakis
        r = self.get(path, success=200)
112 df79206f Giorgos Verigakis
        return r.json['meta'] if key else r.json['metadata']['values']
113 a1c50326 Giorgos Verigakis
    
114 a1c50326 Giorgos Verigakis
    def create_server_metadata(self, server_id, key, val):
115 a1c50326 Giorgos Verigakis
        path = '/servers/%d/meta/%s' % (server_id, key)
116 df79206f Giorgos Verigakis
        req = {'meta': {key: val}}
117 df79206f Giorgos Verigakis
        r = self.put(path, json=req, success=201)
118 df79206f Giorgos Verigakis
        return r.json['meta']
119 a1c50326 Giorgos Verigakis
    
120 a1c50326 Giorgos Verigakis
    def update_server_metadata(self, server_id, **metadata):
121 df79206f Giorgos Verigakis
        path = '/servers/%d/meta' % (server_id,)
122 df79206f Giorgos Verigakis
        req = {'metadata': metadata}
123 df79206f Giorgos Verigakis
        r = self.post(path, json=req, success=201)
124 df79206f Giorgos Verigakis
        return r.json['metadata']
125 a1c50326 Giorgos Verigakis
    
126 a1c50326 Giorgos Verigakis
    def delete_server_metadata(self, server_id, key):
127 a1c50326 Giorgos Verigakis
        path = '/servers/%d/meta/%s' % (server_id, key)
128 df79206f Giorgos Verigakis
        self.delete(path, success=204)
129 df79206f Giorgos Verigakis
    
130 df79206f Giorgos Verigakis
    
131 a1c50326 Giorgos Verigakis
    def list_flavors(self, detail=False):
132 a1c50326 Giorgos Verigakis
        path = '/flavors/detail' if detail else '/flavors'
133 df79206f Giorgos Verigakis
        r = self.get(path, success=200)
134 df79206f Giorgos Verigakis
        return r.json['flavors']['values']
135 a1c50326 Giorgos Verigakis
136 a1c50326 Giorgos Verigakis
    def get_flavor_details(self, flavor_id):
137 a1c50326 Giorgos Verigakis
        path = '/flavors/%d' % flavor_id
138 df79206f Giorgos Verigakis
        r = self.get(path, success=200)
139 df79206f Giorgos Verigakis
        return r.json['flavor']
140 a1c50326 Giorgos Verigakis
    
141 a1c50326 Giorgos Verigakis
    
142 a1c50326 Giorgos Verigakis
    def list_images(self, detail=False):
143 a1c50326 Giorgos Verigakis
        path = '/images/detail' if detail else '/images'
144 df79206f Giorgos Verigakis
        r = self.get(path, success=200)
145 df79206f Giorgos Verigakis
        return r.json['images']['values']
146 b3b32add Giorgos Verigakis
    
147 a1c50326 Giorgos Verigakis
    def get_image_details(self, image_id):
148 df79206f Giorgos Verigakis
        path = '/images/%s' % (image_id,)
149 df79206f Giorgos Verigakis
        r = self.get(path, success=200)
150 df79206f Giorgos Verigakis
        return r.json['image']
151 b3b32add Giorgos Verigakis
    
152 a1c50326 Giorgos Verigakis
    def delete_image(self, image_id):
153 df79206f Giorgos Verigakis
        path = '/images/%s' % (image_id,)
154 df79206f Giorgos Verigakis
        self.delete(path, success=204)
155 a1c50326 Giorgos Verigakis
156 a1c50326 Giorgos Verigakis
    def get_image_metadata(self, image_id, key=None):
157 df79206f Giorgos Verigakis
        path = '/images/%s/meta' % (image_id,)
158 a1c50326 Giorgos Verigakis
        if key:
159 a1c50326 Giorgos Verigakis
            path += '/%s' % key
160 df79206f Giorgos Verigakis
        r = self.get(path, success=200)
161 df79206f Giorgos Verigakis
        return r.json['meta'] if key else r.json['metadata']['values']
162 a1c50326 Giorgos Verigakis
    
163 a1c50326 Giorgos Verigakis
    def create_image_metadata(self, image_id, key, val):
164 b3b32add Giorgos Verigakis
        path = '/images/%s/meta/%s' % (image_id, key)
165 df79206f Giorgos Verigakis
        req = {'meta': {key: val}}
166 df79206f Giorgos Verigakis
        r = self.put(path, json=req, success=201)
167 df79206f Giorgos Verigakis
        return r.json['meta']
168 a1c50326 Giorgos Verigakis
169 a1c50326 Giorgos Verigakis
    def update_image_metadata(self, image_id, **metadata):
170 df79206f Giorgos Verigakis
        path = '/images/%s/meta' % (image_id,)
171 df79206f Giorgos Verigakis
        req = {'metadata': metadata}
172 df79206f Giorgos Verigakis
        r = self.post(path, json=req, success=201)
173 df79206f Giorgos Verigakis
        return r.json['metadata']
174 a1c50326 Giorgos Verigakis
175 a1c50326 Giorgos Verigakis
    def delete_image_metadata(self, image_id, key):
176 b3b32add Giorgos Verigakis
        path = '/images/%s/meta/%s' % (image_id, key)
177 df79206f Giorgos Verigakis
        self.delete(path, success=204)