Skip to content

Commit 9fe4545

Browse files
author
Elias Nygren
committed
refactor storages
1 parent ed9ee63 commit 9fe4545

File tree

7 files changed

+152
-143
lines changed

7 files changed

+152
-143
lines changed

test/test_server.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ def test_attach_and_detach_storage(self, manager):
114114
status = 200,
115115
content_type='application/json'
116116
)
117-
118117
server.remove_storage(server.storage_devices[1])
119118

120119
assert len(server.storage_devices) == 1

test/test_server_creation.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,22 @@ class TestCreateServer(object):
1515

1616
def test_storage_prepare_post_body(self, manager):
1717
s1 = Storage(os='Ubuntu 14.04', size=10)
18-
body1 = s1.prepare_post_body('my.example.com', 1)
19-
20-
assert body1['title'] == 'my.example.com OS disk'
18+
body1 = s1.to_dict()
2119
assert body1['tier'] == 'maxiops'
2220
assert body1['size'] == 10
23-
assert body1['storage'] == '01000000-0000-4000-8000-000030040200'
24-
assert body1['action'] == 'clone'
2521

2622
s2 = Storage(size=100)
27-
body2 = s2.prepare_post_body('my.example.com', 1)
28-
29-
assert body2['title'] == 'my.example.com storage disk 1'
23+
body2 = s2.to_dict()
3024
assert body2['tier'] == 'maxiops'
31-
assert body2['action'] == 'create'
3225
assert body2['size'] == 100
3326

3427
def test_storage_prepare_post_body_optional_attributes(self, manager):
35-
s2 = Storage(size=100, address='virtio:0', type='disk')
36-
body2 = s2.prepare_post_body('my.example.com', 1)
28+
s2 = Storage(size=100, address='virtio:0')
29+
body2 = s2.to_dict()
3730

38-
assert body2['title'] == 'my.example.com storage disk 1'
3931
assert body2['tier'] == 'maxiops'
40-
assert body2['action'] == 'create'
4132
assert body2['size'] == 100
4233
assert body2['address'] == 'virtio:0'
43-
assert body2['type'] == 'disk'
4434

4535
def test_server_init(self, manager):
4636
server1 = Server(

test/test_storage.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ def test_storage_update_oop(self, manager):
4949
storage = manager.get_storage("01d4fcd4-e446-433b-8a9c-551a1284952e")
5050

5151
Mock.mock_put("storage/01d4fcd4-e446-433b-8a9c-551a1284952e")
52-
storage.update(title="my bigger data collection", size=15)
52+
storage.title = "my bigger data collection"
53+
storage.size = 15
54+
storage.save()
5355
assert storage.title == "my bigger data collection"
5456
assert storage.size == 15
5557

upcloud_api/cloud_manager/storage_mixin.py

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,64 +20,72 @@ def get_storages(self, storage_type='normal'):
2020
res = self.get_request('/storage/' + storage_type)
2121
return Storage._create_storage_objs(res['storages'], cloud_manager=self)
2222

23-
def get_storage(self, UUID):
23+
def get_storage(self, storage):
2424
"""
2525
Return a Storage object from the API.
2626
"""
27-
res = self.get_request('/storage/' + UUID)
28-
return Storage._create_storage_obj(res['storage'], cloud_manager=self)
27+
res = self.get_request('/storage/' + str(storage))
28+
return Storage(cloud_manager=self, **res['storage'])
2929

3030
def create_storage(self, size=10, tier='maxiops', title='Storage disk', zone='fi-hel1'):
3131
"""
3232
Create a Storage object. Returns an object based on the API's response.
3333
"""
34-
body = dict()
35-
body['storage'] = {
36-
'size': size,
37-
'tier': tier,
38-
'title': title,
39-
'zone': zone
34+
body = {
35+
'storage': {
36+
'size': size,
37+
'tier': tier,
38+
'title': title,
39+
'zone': zone
40+
}
4041
}
4142
res = self.post_request('/storage', body)
42-
return Storage._create_storage_obj(res['storage'], cloud_manager=self)
43+
return Storage(cloud_manager=self, **res['storage'])
4344

44-
def modify_storage(self, UUID, size, title):
45+
def _modify_storage(self, storage, size, title):
46+
body = {'storage': {}}
47+
if size:
48+
body['storage']['size'] = size
49+
if title:
50+
body['storage']['title'] = title
51+
return self.request('PUT', '/storage/' + str(storage), body)
52+
53+
def modify_storage(self, storage, size, title):
4554
"""
4655
Modify a Storage object. Returns an object based on the API's response.
4756
"""
48-
body = Storage.prepare_put_body(size, title)
49-
res = self.request('PUT', '/storage/' + UUID, body)
50-
return Storage._create_storage_obj(res['storage'], cloud_manager=self)
57+
res = self._modify_storage(str(storage), size, title)
58+
return Storage(cloud_manager=self, **res['storage'])
5159

5260
def delete_storage(self, UUID):
5361
"""
5462
Destroy a Storage object.
5563
"""
5664
return self.request('DELETE', '/storage/' + UUID)
5765

58-
def attach_storage(self, server_uuid, storage_uuid, storage_type, address):
66+
def attach_storage(self, server, storage, storage_type, address):
5967
"""
6068
Attach a Storage object to a Server. Return a list of the server's storages.
6169
"""
6270
body = {'storage_device': {}}
63-
if storage_uuid:
64-
body['storage_device']['storage'] = storage_uuid
71+
if storage:
72+
body['storage_device']['storage'] = str(storage)
6573

6674
if storage_type:
6775
body['storage_device']['type'] = storage_type
6876

6977
if address:
7078
body['storage_device']['address'] = address
7179

72-
url = '/server/{0}/storage/attach'.format(server_uuid)
80+
url = '/server/{0}/storage/attach'.format(server)
7381
res = self.post_request(url, body)
7482
return Storage._create_storage_objs(res['server']['storage_devices'], cloud_manager=self)
7583

76-
def detach_storage(self, server_uuid, address):
84+
def detach_storage(self, server, address):
7785
"""
7886
Detach a Storage object to a Server. Return a list of the server's storages.
7987
"""
8088
body = {'storage_device': {'address': address}}
81-
url = '/server/{0}/storage/detach'.format(server_uuid)
89+
url = '/server/{0}/storage/detach'.format(server)
8290
res = self.post_request(url, body)
8391
return Storage._create_storage_objs(res['server']['storage_devices'], cloud_manager=self)

upcloud_api/errors.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11

22
class UpCloudClientError(Exception):
3+
"""
4+
Base exception for UpCloud API client.
5+
6+
All exceptions thrown by the client should be of the type UpCloudClientError
7+
or at least one of its subclasses.
8+
"""
39
pass
410

511
class UpCloudAPIError(UpCloudClientError):

upcloud_api/server.py

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import itertools
55
from time import sleep
66

7-
from upcloud_api import Storage, IPAddress, UpCloudAPIError
7+
from upcloud_api import Storage, IPAddress, UpCloudAPIError, OperatingSystems
88
from upcloud_api.utils import try_it_n_times
99

1010

@@ -208,19 +208,21 @@ def remove_ip(self, IPAddress):
208208
self.cloud_manager.release_ip(IPAddress.address)
209209
self.ip_addresses.remove(IPAddress)
210210

211-
def add_storage(self, Storage=None, type='disk', address=None):
211+
def add_storage(self, storage=None, type='disk', address=None):
212212
"""
213-
Attach the given Storage to the Server.
213+
Attach the given storage to the Server.
214214
215-
Default address is next available. To add a CDROM slot: add_storage('cdrom').
215+
Default address is next available.
216216
"""
217-
self.cloud_manager.attach_storage(server_uuid=self.uuid,
218-
storage_uuid=Storage.uuid,
217+
self.cloud_manager.attach_storage(server=self.uuid,
218+
storage=storage.uuid,
219219
storage_type=type,
220220
address=address)
221-
self.storage_devices.append(Storage)
221+
storage.address = address
222+
storage.type = type
223+
self.storage_devices.append(storage)
222224

223-
def remove_storage(self, Storage):
225+
def remove_storage(self, storage):
224226
"""
225227
Remove Storage from a Server.
226228
@@ -229,16 +231,16 @@ def remove_storage(self, Storage):
229231
230232
A Storage from get_storage(uuid) will not work as it is missing the 'address' property.
231233
"""
232-
if not hasattr(Storage, 'address'):
234+
if not hasattr(storage, 'address'):
233235
raise Exception(
234236
('Storage does not have an address. '
235237
'Access the Storage via Server.storage_devices '
236238
'so they include an address. '
237239
'(This is due how the API handles Storages)')
238240
)
239241

240-
self.cloud_manager.detach_storage(server_uuid=self.uuid, address=Storage.address)
241-
self.storage_devices.remove(Storage)
242+
self.cloud_manager.detach_storage(server=self.uuid, address=storage.address)
243+
self.storage_devices.remove(storage)
242244

243245
def add_firewall_rule(self, FirewallRule):
244246
"""
@@ -326,9 +328,26 @@ def prepare_post_body(self):
326328

327329
storage_title_id = 0 # running number for unique storage titles
328330
for storage in self.storage_devices:
329-
if storage.os is None:
331+
if not hasattr(storage, 'os') or storage.os is None:
330332
storage_title_id += 1
331-
storage_body = storage.prepare_post_body(self.hostname, storage_title_id)
333+
storage_body = storage.to_dict()
334+
335+
# setup default titles for storages unless use has specified them
336+
# at storage.title
337+
if not hasattr(storage, 'title') or not storage.title:
338+
if hasattr(storage, 'os') and storage.os:
339+
storage_body['title'] = self.hostname + ' OS disk'
340+
else:
341+
storage_body['title'] = self.hostname + ' storage disk ' + str(storage_title_id)
342+
343+
344+
# clone from public template OR create empty storage
345+
if hasattr(storage, 'os') and storage.os:
346+
storage_body['action'] = 'clone'
347+
storage_body['storage'] = OperatingSystems.get_OS_UUID(storage.os)
348+
else:
349+
storage_body['action'] = 'create'
350+
332351
body['server']['storage_devices']['storage_device'].append(storage_body)
333352

334353
return body

0 commit comments

Comments
 (0)