Revision 6a0b1658 kamaki/clients/compute.py

b/kamaki/clients/compute.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
import json
34
from . import Client, ClientError
35 35

  
36
from . import ClientError
37
from .http import HTTPClient
38 36

  
39

  
40
class ComputeClient(HTTPClient):
37
class ComputeClient(Client):
41 38
    """OpenStack Compute API 1.1 client"""
42 39
    
43
    @property
44
    def url(self):
45
        url = self.config.get('compute_url') or self.config.get('url')
46
        if not url:
47
            raise ClientError('No URL was given')
48
        return url
49
    
50
    @property
51
    def token(self):
52
        token = self.config.get('compute_token') or self.config.get('token')
53
        if not token:
54
            raise ClientError('No token was given')
55
        return token
40
    def raise_for_status(self, r):
41
        d = r.json
42
        key = d.keys()[0]
43
        val = d[key]
44
        message = '%s: %s' % (key, val.get('message', ''))
45
        details = val.get('details', '')
46
        raise ClientError(message, r.status_code, details)
56 47
    
57 48
    def list_servers(self, detail=False):
58 49
        """List servers, returned detailed output if detailed is True"""
50
        
59 51
        path = '/servers/detail' if detail else '/servers'
60
        reply = self.http_get(path)
61
        return reply['servers']['values']
52
        r = self.get(path, success=200)
53
        return r.json['servers']['values']
62 54
    
63 55
    def get_server_details(self, server_id):
64 56
        """Return detailed output on a server specified by its id"""
65
        path = '/servers/%d' % server_id
66
        reply = self.http_get(path)
67
        return reply['server']
57
        
58
        path = '/servers/%s' % (server_id,)
59
        r = self.get(path, success=200)
60
        return r.json['server']
68 61
    
69 62
    def create_server(self, name, flavor_id, image_id, personality=None):
70 63
        """Submit request to create a new server
......
78 71

  
79 72
        The call returns a dictionary describing the newly created server.
80 73
        """
81
        req = {'name': name, 'flavorRef': flavor_id, 'imageRef': image_id}
74
        req = {'server': {'name': name,
75
                          'flavorRef': flavor_id,
76
                          'imageRef': image_id}}
82 77
        if personality:
83 78
            req['personality'] = personality
84 79
        
85
        body = json.dumps({'server': req})
86
        reply = self.http_post('/servers', body)
87
        return reply['server']
80
        r = self.post('/servers', json=req, success=202)
81
        return r.json['server']
88 82
    
89 83
    def update_server_name(self, server_id, new_name):
90 84
        """Update the name of the server as reported by the API.
......
92 86
        This call does not modify the hostname actually used by the server
93 87
        internally.
94 88
        """
95
        path = '/servers/%d' % server_id
96
        body = json.dumps({'server': {'name': new_name}})
97
        self.http_put(path, body)
89
        path = '/servers/%s' % (server_id,)
90
        req = {'server': {'name': new_name}}
91
        self.put(path, json=req, success=204)
98 92
    
99 93
    def delete_server(self, server_id):
100 94
        """Submit a deletion request for a server specified by id"""
101
        path = '/servers/%d' % server_id
102
        self.http_delete(path)
95
        
96
        path = '/servers/%s' % (server_id,)
97
        self.delete(path, success=204)
103 98
    
104 99
    def reboot_server(self, server_id, hard=False):
105 100
        """Submit a reboot request for a server specified by id"""
106
        path = '/servers/%d/action' % server_id
107
        type = 'HARD' if hard else 'SOFT'
108
        body = json.dumps({'reboot': {'type': type}})
109
        self.http_post(path, body)
110 101
        
102
        path = '/servers/%s/action' % (server_id,)
103
        type = 'HARD' if hard else 'SOFT'
104
        req = {'reboot': {'type': type}}
105
        self.post(path, json=req, success=202)
106
    
111 107
    def get_server_metadata(self, server_id, key=None):
112
        path = '/servers/%d/meta' % server_id
108
        path = '/servers/%s/meta' % (server_id,)
113 109
        if key:
114 110
            path += '/%s' % key
115
        reply = self.http_get(path)
116
        return reply['meta'] if key else reply['metadata']['values']
111
        r = self.get(path, success=200)
112
        return r.json['meta'] if key else r.json['metadata']['values']
117 113
    
118 114
    def create_server_metadata(self, server_id, key, val):
119 115
        path = '/servers/%d/meta/%s' % (server_id, key)
120
        body = json.dumps({'meta': {key: val}})
121
        reply = self.http_put(path, body, success=201)
122
        return reply['meta']
116
        req = {'meta': {key: val}}
117
        r = self.put(path, json=req, success=201)
118
        return r.json['meta']
123 119
    
124 120
    def update_server_metadata(self, server_id, **metadata):
125
        path = '/servers/%d/meta' % server_id
126
        body = json.dumps({'metadata': metadata})
127
        reply = self.http_post(path, body, success=201)
128
        return reply['metadata']
121
        path = '/servers/%d/meta' % (server_id,)
122
        req = {'metadata': metadata}
123
        r = self.post(path, json=req, success=201)
124
        return r.json['metadata']
129 125
    
130 126
    def delete_server_metadata(self, server_id, key):
131 127
        path = '/servers/%d/meta/%s' % (server_id, key)
132
        reply = self.http_delete(path)
133
        
134
        
128
        self.delete(path, success=204)
129
    
130
    
135 131
    def list_flavors(self, detail=False):
136 132
        path = '/flavors/detail' if detail else '/flavors'
137
        reply = self.http_get(path)
138
        return reply['flavors']['values']
133
        r = self.get(path, success=200)
134
        return r.json['flavors']['values']
139 135

  
140 136
    def get_flavor_details(self, flavor_id):
141 137
        path = '/flavors/%d' % flavor_id
142
        reply = self.http_get(path)
143
        return reply['flavor']
138
        r = self.get(path, success=200)
139
        return r.json['flavor']
144 140
    
145 141
    
146 142
    def list_images(self, detail=False):
147 143
        path = '/images/detail' if detail else '/images'
148
        reply = self.http_get(path)
149
        return reply['images']['values']
144
        r = self.get(path, success=200)
145
        return r.json['images']['values']
150 146
    
151 147
    def get_image_details(self, image_id):
152
        path = '/images/%s' % image_id
153
        reply = self.http_get(path)
154
        return reply['image']
148
        path = '/images/%s' % (image_id,)
149
        r = self.get(path, success=200)
150
        return r.json['image']
155 151
    
156 152
    def delete_image(self, image_id):
157
        path = '/images/%s' % image_id
158
        self.http_delete(path)
153
        path = '/images/%s' % (image_id,)
154
        self.delete(path, success=204)
159 155

  
160 156
    def get_image_metadata(self, image_id, key=None):
161
        path = '/images/%s/meta' % image_id
157
        path = '/images/%s/meta' % (image_id,)
162 158
        if key:
163 159
            path += '/%s' % key
164
        reply = self.http_get(path)
165
        return reply['meta'] if key else reply['metadata']['values']
160
        r = self.get(path, success=200)
161
        return r.json['meta'] if key else r.json['metadata']['values']
166 162
    
167 163
    def create_image_metadata(self, image_id, key, val):
168 164
        path = '/images/%s/meta/%s' % (image_id, key)
169
        body = json.dumps({'meta': {key: val}})
170
        reply = self.http_put(path, body, success=201)
171
        return reply['meta']
165
        req = {'meta': {key: val}}
166
        r = self.put(path, json=req, success=201)
167
        return r.json['meta']
172 168

  
173 169
    def update_image_metadata(self, image_id, **metadata):
174
        path = '/images/%s/meta' % image_id
175
        body = json.dumps({'metadata': metadata})
176
        reply = self.http_post(path, body, success=201)
177
        return reply['metadata']
170
        path = '/images/%s/meta' % (image_id,)
171
        req = {'metadata': metadata}
172
        r = self.post(path, json=req, success=201)
173
        return r.json['metadata']
178 174

  
179 175
    def delete_image_metadata(self, image_id, key):
180 176
        path = '/images/%s/meta/%s' % (image_id, key)
181
        self.http_delete(path)
177
        self.delete(path, success=204)

Also available in: Unified diff