Skip to content

Commit bc47610

Browse files
author
Adrian Huber
committed
Server creation with placement group
1 parent 529e8b8 commit bc47610

4 files changed

Lines changed: 111 additions & 40 deletions

File tree

hcloud/servers/client.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from hcloud.datacenters.client import BoundDatacenter
2626
from hcloud.networks.client import BoundNetwork # noqa
2727
from hcloud.networks.domain import Network # noqa
28+
from hcloud.placement_groups.client import BoundPlacementGroup
2829

2930

3031
class BoundServer(BoundModelBase):
@@ -101,6 +102,11 @@ def __init__(self, client, data, complete=True):
101102
]
102103
data["private_net"] = private_nets
103104

105+
placement_group = data.get("placement_group")
106+
if placement_group:
107+
placement_group = BoundPlacementGroup(client._client.placement_groups, placement_group)
108+
data['placement_group'] = placement_group
109+
104110
super(BoundServer, self).__init__(client, data, complete)
105111

106112
def get_actions_list(self, status=None, sort=None, page=None, per_page=None):
@@ -456,22 +462,22 @@ def get_by_name(self, name):
456462
"""
457463
return super(ServersClient, self).get_by_name(name)
458464

459-
def create(
460-
self,
461-
name, # type: str
462-
server_type, # type: ServerType
463-
image, # type: Image
464-
ssh_keys=None, # type: Optional[List[SSHKey]]
465-
volumes=None, # type: Optional[List[Volume]]
466-
firewalls=None, # type: Optional[List[Firewall]]
467-
networks=None, # type: Optional[List[Network]]
468-
user_data=None, # type: Optional[str]
469-
labels=None, # type: Optional[Dict[str, str]]
470-
location=None, # type: Optional[Location]
471-
datacenter=None, # type: Optional[Datacenter]
472-
start_after_create=True, # type: Optional[bool]
473-
automount=None, # type: Optional[bool]
474-
):
465+
def create(self,
466+
name, # type: str
467+
server_type, # type: ServerType
468+
image, # type: Image
469+
ssh_keys=None, # type: Optional[List[SSHKey]]
470+
volumes=None, # type: Optional[List[Volume]]
471+
firewalls=None, # type: Optional[List[Firewall]]
472+
networks=None, # type: Optional[List[Network]]
473+
user_data=None, # type: Optional[str]
474+
labels=None, # type: Optional[Dict[str, str]]
475+
location=None, # type: Optional[Location]
476+
datacenter=None, # type: Optional[Datacenter]
477+
start_after_create=True, # type: Optional[bool]
478+
automount=None, # type: Optional[bool]
479+
placement_group=None # type: Optional[PlacementGroup]
480+
):
475481
# type: (...) -> CreateServerResponse
476482
"""Creates a new server. Returns preliminary information about the server as well as an action that covers progress of creation.
477483
@@ -497,6 +503,8 @@ def create(
497503
Start Server right after creation. Defaults to True.
498504
:param automount: boolean (optional)
499505
Auto mount volumes after attach.
506+
:param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>` or :class:`Location <hcloud.placement_groups.domain.PlacementGroup>`
507+
Placement Group where server should be added during creation
500508
:return: :class:`CreateServerResponse <hcloud.servers.domain.CreateServerResponse>`
501509
"""
502510
data = {
@@ -524,6 +532,8 @@ def create(
524532
data["labels"] = labels
525533
if automount is not None:
526534
data["automount"] = automount
535+
if placement_group is not None:
536+
data['placement_group'] = placement_group.id
527537

528538
response = self._client.request(url="/servers", method="POST", json=data)
529539

hcloud/servers/domain.py

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -84,30 +84,32 @@ class Server(BaseDomain):
8484
"private_net",
8585
"created",
8686
"primary_disk_size",
87+
"placement_group"
8788
)
8889

8990
def __init__(
90-
self,
91-
id,
92-
name=None,
93-
status=None,
94-
created=None,
95-
public_net=None,
96-
server_type=None,
97-
datacenter=None,
98-
image=None,
99-
iso=None,
100-
rescue_enabled=None,
101-
locked=None,
102-
backup_window=None,
103-
outgoing_traffic=None,
104-
ingoing_traffic=None,
105-
included_traffic=None,
106-
protection=None,
107-
labels=None,
108-
volumes=None,
109-
private_net=None,
110-
primary_disk_size=None,
91+
self,
92+
id,
93+
name=None,
94+
status=None,
95+
created=None,
96+
public_net=None,
97+
server_type=None,
98+
datacenter=None,
99+
image=None,
100+
iso=None,
101+
rescue_enabled=None,
102+
locked=None,
103+
backup_window=None,
104+
outgoing_traffic=None,
105+
ingoing_traffic=None,
106+
included_traffic=None,
107+
protection=None,
108+
labels=None,
109+
volumes=None,
110+
private_net=None,
111+
primary_disk_size=None,
112+
placement_group=None,
111113
):
112114
self.id = id
113115
self.name = name
@@ -129,6 +131,7 @@ def __init__(
129131
self.volumes = volumes
130132
self.private_net = private_net
131133
self.primary_disk_size = primary_disk_size
134+
self.placement_group = placement_group
132135

133136

134137
class CreateServerResponse(BaseDomain):

tests/unit/servers/conftest.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,19 @@ def response_full_server():
627627
"type": "public",
628628
"deprecated": "2018-02-28T00:00:00+00:00",
629629
},
630+
"placement_group": {
631+
"created": "2019-01-08T12:10:00+00:00",
632+
"id": 897,
633+
"labels": {
634+
"key": "value"
635+
},
636+
"name": "my Placement Group",
637+
"servers": [
638+
4711,
639+
4712
640+
],
641+
"type": "spread"
642+
},
630643
"rescue_enabled": False,
631644
"locked": False,
632645
"backup_window": "22-02",

tests/unit/servers/test_client.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ def test_bound_server_init(self, response_full_server):
117117
assert len(bound_server.private_net[0].alias_ips) == 1
118118
assert bound_server.private_net[0].alias_ips[0] == "10.1.1.8"
119119

120+
assert isinstance(bound_server.placement_group, BoundPlacementGroup)
121+
assert bound_server.placement_group._client == bound_server._client._client.placement_groups
122+
assert bound_server.placement_group.id == 897
123+
assert bound_server.placement_group.name == "my Placement Group"
124+
assert bound_server.placement_group.complete is True
125+
120126
@pytest.mark.parametrize(
121127
"params",
122128
[
@@ -741,9 +747,48 @@ def test_create_with_firewalls(self, servers_client, response_create_simple_serv
741747

742748
assert next_actions[0].id == 13
743749

744-
@pytest.mark.parametrize(
745-
"server", [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))]
746-
)
750+
def test_create_with_placement_group(self, servers_client, response_create_simple_server):
751+
servers_client._client.request.return_value = response_create_simple_server
752+
placement_group = PlacementGroup(id=1)
753+
response = servers_client.create(
754+
"my-server",
755+
server_type=ServerType(name="cx11"),
756+
image=Image(id=4711),
757+
start_after_create=False,
758+
placement_group=placement_group
759+
)
760+
761+
servers_client._client.request.assert_called_with(
762+
url="/servers",
763+
method="POST",
764+
json={
765+
'name': "my-server",
766+
'server_type': "cx11",
767+
'image': 4711,
768+
'placement_group': 1,
769+
"start_after_create": False
770+
}
771+
)
772+
773+
bound_server = response.server
774+
bound_action = response.action
775+
next_actions = response.next_actions
776+
root_password = response.root_password
777+
778+
assert root_password == "YItygq1v3GYjjMomLaKc"
779+
780+
assert bound_server._client is servers_client
781+
assert bound_server.id == 1
782+
assert bound_server.name == "my-server"
783+
784+
assert isinstance(bound_action, BoundAction)
785+
assert bound_action._client == servers_client._client.actions
786+
assert bound_action.id == 1
787+
assert bound_action.command == "create_server"
788+
789+
assert next_actions[0].id == 13
790+
791+
@pytest.mark.parametrize("server", [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
747792
def test_get_actions_list(self, servers_client, server, response_get_actions):
748793
servers_client._client.request.return_value = response_get_actions
749794
result = servers_client.get_actions_list(server)

0 commit comments

Comments
 (0)