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