Skip to content

Commit fbbfd08

Browse files
authored
Merge pull request #2147 from apache/improve_upload
Add new functions to complete the Upcloud driver and move it to the last API version 1.3.
2 parents f2765fe + ddafe52 commit fbbfd08

9 files changed

Lines changed: 935 additions & 43 deletions

File tree

CHANGES.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ Compute
2121
(#2135)
2222
[Steve Kowalik - @s-t-e-v-e-n-k]
2323

24+
- [UpCloud]
25+
26+
Add new functions to complete the Upcloud driver and move it to the
27+
last API version 1.3
28+
(#2152)
29+
[Miguel Caballer - @micafer]
30+
2431
Changes in Apache Libcloud 3.9.1
2532
--------------------------------
2633

docs/compute/drivers/upcloud.rst

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,53 @@ UpCloud currently operates globally from eight (8) data centers:
1919
* San Jose, USA
2020
* Singapore, Singapore
2121

22+
This driver uses the UpCloud API 1.3 endpoints.
23+
24+
Firewall rules
25+
--------------
26+
27+
UpCloud manages network access through per-server firewall rules instead of
28+
reusable security groups. The driver exposes those rules through extension
29+
methods:
30+
31+
* ``ex_list_firewall_rules(node)``
32+
* ``ex_get_firewall_rule(node, position)``
33+
* ``ex_create_firewall_rule(node, rule)``
34+
* ``ex_create_firewall_rules(node, rules)``
35+
* ``ex_delete_firewall_rule(node, position)``
36+
2237
Instantiating a driver
2338
----------------------
2439

25-
When you instantiate a driver you need to pass the following arguments to the
26-
driver constructor:
40+
When you instantiate a driver you can authenticate with an API bearer token:
41+
42+
* ``token`` - Your UpCloud API bearer token
43+
44+
For example:
45+
46+
.. code-block:: python
47+
48+
from libcloud.compute.types import Provider
49+
from libcloud.compute.providers import get_driver
50+
51+
cls = get_driver(Provider.UPCLOUD)
52+
driver = cls(token="ucat_...")
53+
54+
You can also use basic authentication with an API enabled user:
2755

2856
* ``username`` - Your API access enabled users username
2957
* ``password`` - Your API access enabled users password
3058

59+
For example:
60+
61+
.. code-block:: python
62+
63+
from libcloud.compute.types import Provider
64+
from libcloud.compute.providers import get_driver
65+
66+
cls = get_driver(Provider.UPCLOUD)
67+
driver = cls("username", "password")
68+
3169
Enabling API access
3270
-------------------
3371

libcloud/common/upcloud.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ class UpcloudCreateNodeRequestBody:
5252
:param ex_username: User's username, which is created.
5353
Default is 'root'. (optional)
5454
:type ex_username: ``str``
55+
56+
:param ex_storage_devices: Additional UpCloud storage_device dictionaries.
57+
(optional)
58+
:type ex_storage_devices: ``list`` of ``dict``
59+
60+
:param ex_metadata: Whether to enable the UpCloud metadata service,
61+
``"yes"`` or ``"no"``. Cloud-init templates require
62+
this to be enabled. (optional)
63+
:type ex_metadata: ``str``
5564
"""
5665

5766
def __init__(
@@ -63,17 +72,25 @@ def __init__(
6372
auth=None,
6473
ex_hostname="localhost",
6574
ex_username="root",
75+
ex_storage_devices=None,
76+
ex_metadata=None,
6677
):
78+
storage_devices = _StorageDevice(image, size).to_dict()
79+
if ex_storage_devices:
80+
storage_devices["storage_device"].extend(ex_storage_devices)
81+
6782
self.body = {
6883
"server": {
6984
"title": name,
7085
"hostname": ex_hostname,
7186
"plan": size.id,
7287
"zone": location.id,
7388
"login_user": _LoginUser(ex_username, auth).to_dict(),
74-
"storage_devices": _StorageDevice(image, size).to_dict(),
89+
"storage_devices": storage_devices,
7590
}
7691
}
92+
if ex_metadata is not None:
93+
self.body["server"]["metadata"] = ex_metadata
7794

7895
def to_json(self):
7996
"""
@@ -169,9 +186,18 @@ def stop_node(self, node_id):
169186
"""
170187
body = {"stop_server": {"stop_type": "hard"}}
171188
self.connection.request(
172-
"1.2/server/{}/stop".format(node_id), method="POST", data=json.dumps(body)
189+
"1.3/server/{}/stop".format(node_id), method="POST", data=json.dumps(body)
173190
)
174191

192+
def start_node(self, node_id):
193+
"""
194+
Starts the node
195+
196+
:param node_id: Id of the Node
197+
:type node_id: ``int``
198+
"""
199+
self.connection.request("1.3/server/{}/start".format(node_id), method="POST")
200+
175201
def get_node_state(self, node_id):
176202
"""
177203
Get the state of the node.
@@ -182,7 +208,7 @@ def get_node_state(self, node_id):
182208
:rtype: ``str``
183209
"""
184210

185-
action = "1.2/server/{}".format(node_id)
211+
action = "1.3/server/{}".format(node_id)
186212
try:
187213
response = self.connection.request(action)
188214
return response.object["server"]["state"]
@@ -198,7 +224,7 @@ def destroy_node(self, node_id):
198224
:param node_id: Id of the Node
199225
:type node_id: ``int``
200226
"""
201-
self.connection.request("1.2/server/{}".format(node_id), method="DELETE")
227+
self.connection.request("1.3/server/{}".format(node_id), method="DELETE")
202228

203229

204230
class PlanPrice:

0 commit comments

Comments
 (0)