Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / compute.py @ 6c62a96d

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 6a0b1658 Giorgos Verigakis
from . import Client, ClientError
35 a1c50326 Giorgos Verigakis
36 a1c50326 Giorgos Verigakis
37 6a0b1658 Giorgos Verigakis
class ComputeClient(Client):
38 d2cea1e2 Giorgos Verigakis
    """OpenStack Compute API 1.1 client"""
39 d2cea1e2 Giorgos Verigakis
    
40 6a0b1658 Giorgos Verigakis
    def raise_for_status(self, r):
41 6a0b1658 Giorgos Verigakis
        d = r.json
42 6a0b1658 Giorgos Verigakis
        key = d.keys()[0]
43 6a0b1658 Giorgos Verigakis
        val = d[key]
44 6a0b1658 Giorgos Verigakis
        message = '%s: %s' % (key, val.get('message', ''))
45 6a0b1658 Giorgos Verigakis
        details = val.get('details', '')
46 6a0b1658 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 6a0b1658 Giorgos Verigakis
        
51 a1c50326 Giorgos Verigakis
        path = '/servers/detail' if detail else '/servers'
52 6a0b1658 Giorgos Verigakis
        r = self.get(path, success=200)
53 6a0b1658 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 6a0b1658 Giorgos Verigakis
        
58 6a0b1658 Giorgos Verigakis
        path = '/servers/%s' % (server_id,)
59 6a0b1658 Giorgos Verigakis
        r = self.get(path, success=200)
60 6a0b1658 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 6a0b1658 Giorgos Verigakis
        req = {'server': {'name': name,
75 6a0b1658 Giorgos Verigakis
                          'flavorRef': flavor_id,
76 6a0b1658 Giorgos Verigakis
                          'imageRef': image_id}}
77 a1c50326 Giorgos Verigakis
        if personality:
78 c4922a05 Giorgos Verigakis
            req['server']['personality'] = personality
79 a1c50326 Giorgos Verigakis
        
80 6a0b1658 Giorgos Verigakis
        r = self.post('/servers', json=req, success=202)
81 6a0b1658 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 6a0b1658 Giorgos Verigakis
        path = '/servers/%s' % (server_id,)
90 6a0b1658 Giorgos Verigakis
        req = {'server': {'name': new_name}}
91 6a0b1658 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 6a0b1658 Giorgos Verigakis
        
96 6a0b1658 Giorgos Verigakis
        path = '/servers/%s' % (server_id,)
97 6a0b1658 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 6a0b1658 Giorgos Verigakis
        path = '/servers/%s/action' % (server_id,)
103 6a0b1658 Giorgos Verigakis
        type = 'HARD' if hard else 'SOFT'
104 6a0b1658 Giorgos Verigakis
        req = {'reboot': {'type': type}}
105 6a0b1658 Giorgos Verigakis
        self.post(path, json=req, success=202)
106 6a0b1658 Giorgos Verigakis
    
107 a1c50326 Giorgos Verigakis
    def get_server_metadata(self, server_id, key=None):
108 6a0b1658 Giorgos Verigakis
        path = '/servers/%s/meta' % (server_id,)
109 a1c50326 Giorgos Verigakis
        if key:
110 a1c50326 Giorgos Verigakis
            path += '/%s' % key
111 6a0b1658 Giorgos Verigakis
        r = self.get(path, success=200)
112 6a0b1658 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 6a0b1658 Giorgos Verigakis
        req = {'meta': {key: val}}
117 6a0b1658 Giorgos Verigakis
        r = self.put(path, json=req, success=201)
118 6a0b1658 Giorgos Verigakis
        return r.json['meta']
119 a1c50326 Giorgos Verigakis
    
120 a1c50326 Giorgos Verigakis
    def update_server_metadata(self, server_id, **metadata):
121 6a0b1658 Giorgos Verigakis
        path = '/servers/%d/meta' % (server_id,)
122 6a0b1658 Giorgos Verigakis
        req = {'metadata': metadata}
123 6a0b1658 Giorgos Verigakis
        r = self.post(path, json=req, success=201)
124 6a0b1658 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 6a0b1658 Giorgos Verigakis
        self.delete(path, success=204)
129 6a0b1658 Giorgos Verigakis
    
130 6a0b1658 Giorgos Verigakis
    
131 a1c50326 Giorgos Verigakis
    def list_flavors(self, detail=False):
132 a1c50326 Giorgos Verigakis
        path = '/flavors/detail' if detail else '/flavors'
133 6a0b1658 Giorgos Verigakis
        r = self.get(path, success=200)
134 6a0b1658 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 6a0b1658 Giorgos Verigakis
        r = self.get(path, success=200)
139 6a0b1658 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 6a0b1658 Giorgos Verigakis
        r = self.get(path, success=200)
145 6a0b1658 Giorgos Verigakis
        return r.json['images']['values']
146 b3b32add Giorgos Verigakis
    
147 a1c50326 Giorgos Verigakis
    def get_image_details(self, image_id):
148 6a0b1658 Giorgos Verigakis
        path = '/images/%s' % (image_id,)
149 6a0b1658 Giorgos Verigakis
        r = self.get(path, success=200)
150 6a0b1658 Giorgos Verigakis
        return r.json['image']
151 b3b32add Giorgos Verigakis
    
152 a1c50326 Giorgos Verigakis
    def delete_image(self, image_id):
153 6a0b1658 Giorgos Verigakis
        path = '/images/%s' % (image_id,)
154 6a0b1658 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 6a0b1658 Giorgos Verigakis
        path = '/images/%s/meta' % (image_id,)
158 a1c50326 Giorgos Verigakis
        if key:
159 a1c50326 Giorgos Verigakis
            path += '/%s' % key
160 6a0b1658 Giorgos Verigakis
        r = self.get(path, success=200)
161 6a0b1658 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 6a0b1658 Giorgos Verigakis
        req = {'meta': {key: val}}
166 6a0b1658 Giorgos Verigakis
        r = self.put(path, json=req, success=201)
167 6a0b1658 Giorgos Verigakis
        return r.json['meta']
168 a1c50326 Giorgos Verigakis
169 a1c50326 Giorgos Verigakis
    def update_image_metadata(self, image_id, **metadata):
170 6a0b1658 Giorgos Verigakis
        path = '/images/%s/meta' % (image_id,)
171 6a0b1658 Giorgos Verigakis
        req = {'metadata': metadata}
172 6a0b1658 Giorgos Verigakis
        r = self.post(path, json=req, success=201)
173 6a0b1658 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 6a0b1658 Giorgos Verigakis
        self.delete(path, success=204)