Skip to content

Commit

Permalink
feat(api): Labels support for servers & storages, server group support
Browse files Browse the repository at this point in the history
  • Loading branch information
ajmyyra committed Jul 27, 2023
1 parent 5a894a6 commit d02adbe
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 16 deletions.
2 changes: 2 additions & 0 deletions upcloud_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
from upcloud_api.interface import Interface
from upcloud_api.ip_address import IPAddress
from upcloud_api.ip_network import IpNetwork
from upcloud_api.label import Label
from upcloud_api.network import Network
from upcloud_api.object_storage import ObjectStorage
from upcloud_api.router import Router
from upcloud_api.server import Server, login_user_block
from upcloud_api.server_group import ServerGroup, ServerGroupAffinityPolicy
from upcloud_api.storage import Storage
from upcloud_api.storage_import import StorageImport
from upcloud_api.tag import Tag
Expand Down
23 changes: 22 additions & 1 deletion upcloud_api/cloud_manager/server_mixin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from upcloud_api.api import API
from upcloud_api.ip_address import IPAddress
from upcloud_api.server import Server
from upcloud_api.server_group import ServerGroup
from upcloud_api.storage import BackupDeletionPolicy, Storage


Expand Down Expand Up @@ -91,9 +92,10 @@ def create_server(self, server: Server) -> Server:
memory_amount = 1024,
hostname = "my.example.1",
zone = "uk-lon1",
labels = [Label('role', 'example')],
storage_devices = [
Storage(os = "01000000-0000-4000-8000-000030200200", size=10, tier=maxiops, title='Example OS disk'),
Storage(size=10),
Storage(size=10, labels=[Label('usage', 'data_disk')]),
Storage()
title = "My Example Server"
])
Expand Down Expand Up @@ -191,3 +193,22 @@ def get_server_data(self, uuid: str):
storages = Storage._create_storage_objs(server.pop('storage_devices'), cloud_manager=self)

return server, IPAddresses, storages

def create_server_group(self, server_group: ServerGroup) -> ServerGroup:
"""
Creates a new server group. Allows including servers and defining labels.
"""
if not isinstance(server_group, ServerGroup):
server_group = ServerGroup(server_group)
body = server_group.to_dict()

res = self.api.post_request('/server-group', body)
return ServerGroup(cloud_manager=self, **res['server_group'])

def delete_server_group(self, uuid: str):
"""
DELETE '/server-group/UUID'. Destroys the server group, but not attached servers.
Returns an empty object.
"""
return self.api.delete_request(f'/server-group/{uuid}')
35 changes: 35 additions & 0 deletions upcloud_api/label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from upcloud_api.upcloud_resource import UpCloudResource


class Label(UpCloudResource):
"""
Class representation of UpCloud resource label
"""

ATTRIBUTES = {
'key': "",
'value': "",
}

def __init__(self, key="", value="") -> None:
"""
Initialize label.
Set both values for label if given
"""
self.key = key
self.value = value

def __str__(self) -> str:
return f"{self.key}={self.value}"

def to_dict(self):
"""
Return a dict that can be serialised to JSON and sent to UpCloud's API.
"""
body = {
'key': self.key,
'value': self.value,
}

return body
38 changes: 27 additions & 11 deletions upcloud_api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from upcloud_api.firewall import FirewallRule
from upcloud_api.ip_address import IPAddress
from upcloud_api.server_group import ServerGroup
from upcloud_api.storage import Storage
from upcloud_api.utils import try_it_n_times

Expand Down Expand Up @@ -47,31 +48,34 @@ class Server:
'core_number',
'firewall',
'hostname',
'labels',
'memory_amount',
'nic_model',
'plan',
'title',
'timezone',
'video_model',
'vnc',
'vnc_password',
'plan',
]

optional_fields = [
'plan',
'core_number',
'memory_amount',
'avoid_host',
'boot_order',
'core_number',
'firewall',
'labels',
'login_user',
'memory_amount',
'nic_model',
'password_delivery',
'plan',
'server_group',
'timezone',
'metadata',
'user_data',
'video_model',
'vnc_password',
'password_delivery',
'avoid_host',
'login_user',
'user_data',
'metadata',
]

def __init__(self, server=None, **kwargs) -> None:
Expand Down Expand Up @@ -149,11 +153,11 @@ def save(self) -> None:
self.cloud_manager.modify_server(self.uuid, **kwargs)
self._reset(kwargs)

def destroy(self):
def destroy(self, delete_storages=False):
"""
Destroy the server.
"""
self.cloud_manager.delete_server(self.uuid)
self.cloud_manager.delete_server(self.uuid, delete_storages=delete_storages)

def shutdown(self, hard: bool = False, timeout: int = 30) -> None:
"""
Expand Down Expand Up @@ -335,6 +339,18 @@ def prepare_post_body(self):
if hasattr(self, optional_field):
body['server'][optional_field] = getattr(self, optional_field)

if hasattr(self, 'labels'):
dict_labels = {'label': []}
for label in self.labels:
dict_labels['label'].append(label.to_dict())
body['server']['labels'] = dict_labels

if hasattr(self, 'metadata') and isinstance(self.metadata, bool):
body['server']['metadata'] = "yes" if self.metadata else "no"

if hasattr(self, 'server_group') and isinstance(self.server_group, ServerGroup):
body['server']['server_group'] = f"{self.server_group.uuid}"

# set password_delivery default as 'none' to prevent API from sending
# emails (with credentials) about each created server
if not hasattr(self, 'password_delivery'):
Expand Down
57 changes: 57 additions & 0 deletions upcloud_api/server_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from enum import Enum

from upcloud_api.upcloud_resource import UpCloudResource


class ServerGroupAffinityPolicy(str, Enum):
"""
Enum representation of affinity policy for a server group
"""

STRICT_ANTI_AFFINITY = 'strict'
ANTI_AFFINITY_PREFERRED = 'yes'
NO_ANTI_AFFINITY = 'no'


class ServerGroup(UpCloudResource):
"""
Class representation of UpCloud server group resource
"""

ATTRIBUTES = {
'anti_affinity': ServerGroupAffinityPolicy.NO_ANTI_AFFINITY,
'labels': None,
'servers': None,
'title': None,
'uuid': None,
}

def __str__(self) -> str:
return self.title

def to_dict(self):
"""
Return a dict that can be serialised to JSON and sent to UpCloud's API.
"""
body = {
'title': self.title,
}

if hasattr(self, 'anti_affinity'):
body['anti_affinity'] = f"{self.anti_affinity}"

if hasattr(self, 'servers'):
servers = []
for server in self.servers:
if isinstance(server, server.Server) and hasattr(server, 'uuid'):
servers.append(server.uuid)
else:
servers.append(server)

if hasattr(self, 'labels'):
dict_labels = {'label': []}
for label in self.labels:
dict_labels['label'].append(label.to_dict())
body['labels'] = dict_labels

return {'server_group': body}
15 changes: 11 additions & 4 deletions upcloud_api/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ class Storage(UpCloudResource):
"""

ATTRIBUTES = {
'uuid': None,
'tier': 'maxiops',
'size': 10,
'access': None,
'address': None,
'labels': None,
'license': None,
'state': None,
'size': 10,
'tier': 'maxiops',
'title': '',
'type': None,
'address': None,
'uuid': None,
'zone': None,
}

Expand Down Expand Up @@ -146,6 +147,12 @@ def to_dict(self):
if hasattr(self, 'zone') and self.zone:
body['zone'] = self.zone

if hasattr(self, 'labels'):
dict_labels = []
for label in self.labels:
dict_labels.append(label.to_dict())
body['labels'] = dict_labels

return body

@staticmethod
Expand Down

0 comments on commit d02adbe

Please sign in to comment.