This is an automated email from the ASF dual-hosted git repository.

micafer pushed a commit to branch improve_upload
in repository https://gitbox.apache.org/repos/asf/libcloud.git


The following commit(s) were added to refs/heads/improve_upload by this push:
     new 4a9e7d09f Fix to 1.2 version
4a9e7d09f is described below

commit 4a9e7d09f5a747acc5306c056febef4ccc70ae59
Author: Miguel Caballer <[email protected]>
AuthorDate: Fri Jul 3 12:14:17 2026 +0200

    Fix to 1.2 version
---
 libcloud/common/upcloud.py                         |  6 +-
 libcloud/compute/drivers/upcloud.py                | 79 ++++++++--------------
 ...orage_01d4fcd4-e446-433b-8a9c-551a1284952e.json |  9 +--
 .../fixtures/upcloud/api_1_2_storage_create.json   |  9 +--
 .../fixtures/upcloud/api_1_2_storage_normal.json   | 11 +--
 libcloud/test/compute/test_upcloud.py              | 60 +++++++---------
 6 files changed, 57 insertions(+), 117 deletions(-)

diff --git a/libcloud/common/upcloud.py b/libcloud/common/upcloud.py
index 632695335..5b4273da8 100644
--- a/libcloud/common/upcloud.py
+++ b/libcloud/common/upcloud.py
@@ -188,11 +188,7 @@ class UpcloudNodeOperations:
         :param  node_id: Id of the Node
         :type   node_id: ``int``
         """
-        self.connection.request(
-            "1.2/server/{}/start".format(node_id),
-            method="POST",
-            data=json.dumps({"server": {}}),
-        )
+        self.connection.request("1.2/server/{}/start".format(node_id), 
method="POST")
 
     def get_node_state(self, node_id):
         """
diff --git a/libcloud/compute/drivers/upcloud.py 
b/libcloud/compute/drivers/upcloud.py
index 1f781d19a..36dbf4edd 100644
--- a/libcloud/compute/drivers/upcloud.py
+++ b/libcloud/compute/drivers/upcloud.py
@@ -240,8 +240,6 @@ class UpcloudDriver(NodeDriver):
         location=None,
         snapshot=None,
         ex_tier="maxiops",
-        ex_encrypted=False,
-        ex_labels=None,
         ex_backup_rule=None,
     ):
         """
@@ -256,17 +254,10 @@ class UpcloudDriver(NodeDriver):
         :param location: Which data center to create a volume in. (required)
         :type location: :class:`.NodeLocation`
 
-        :param ex_tier: UpCloud storage tier: ``maxiops``, ``standard``, or
-                        ``hdd``. Default is ``maxiops``. (optional)
+        :param ex_tier: UpCloud storage tier: ``maxiops`` or ``hdd``.
+                        Default is ``maxiops``. (optional)
         :type ex_tier: ``str``
 
-        :param ex_encrypted: Create the volume encrypted at rest. Default is
-                             False. (optional)
-        :type ex_encrypted: ``bool``
-
-        :param ex_labels: Labels for the volume. (optional)
-        :type ex_labels: ``list`` of ``dict``
-
         :param ex_backup_rule: Backup rule block for automatic backups.
                                (optional)
         :type ex_backup_rule: ``dict``
@@ -284,10 +275,7 @@ class UpcloudDriver(NodeDriver):
             "title": name,
             "zone": location.id,
             "tier": ex_tier,
-            "encrypted": "yes" if ex_encrypted else "no",
         }
-        if ex_labels is not None:
-            storage["labels"] = ex_labels
         if ex_backup_rule is not None:
             storage["backup_rule"] = ex_backup_rule
 
@@ -327,35 +315,51 @@ class UpcloudDriver(NodeDriver):
                              Default is False. (optional)
         :type ex_boot_disk: ``bool``
 
-        :rtype: :class:`StorageVolume`
+        :rtype: ``bool``
         """
         storage_device = {
             "type": ex_type,
-            "server": node.id,
+            "storage": volume.id,
             "boot_disk": "1" if ex_boot_disk else "0",
         }
         if device is not None:
             storage_device["address"] = device
 
-        response = self.connection.request(
-            "1.2/storage/{}/attach".format(volume.id),
+        self.connection.request(
+            "1.2/server/{}/storage/attach".format(node.id),
             method="POST",
             data=json.dumps({"storage_device": storage_device}),
         )
-        return self._to_volume(response.object["storage"])
+        return True
 
-    def detach_volume(self, volume):
+    def detach_volume(self, volume, ex_node=None, ex_address=None):
         """
         Detach a storage volume from its server.
 
         :param volume: Volume to detach.
         :type volume: :class:`StorageVolume`
 
+        :param ex_node: Node where the volume is attached. Required by the
+                        UpCloud 1.2 detach endpoint.
+        :type ex_node: :class:`Node`
+
+        :param ex_address: Device address to detach, for example
+                           ``scsi:0:0``. Required by the UpCloud 1.2 detach
+                           endpoint.
+        :type ex_address: ``str``
+
         :rtype: ``bool``
         """
+        if ex_node is None or ex_address is None:
+            raise ValueError(
+                "UpCloud API 1.2 requires `ex_node` and `ex_address` "
+                "when detaching a volume."
+            )
+
         self.connection.request(
-            "1.2/storage/{}/detach".format(volume.id),
+            "1.2/server/{}/storage/detach".format(ex_node.id),
             method="POST",
+            data=json.dumps({"storage_device": {"address": ex_address}}),
         )
         return True
 
@@ -401,45 +405,16 @@ class UpcloudDriver(NodeDriver):
         )
         return True
 
-    def start_node(
-        self,
-        node,
-        ex_host=None,
-        ex_avoid_host=None,
-        ex_start_type=None,
-    ):
+    def start_node(self, node):
         """
         Start the given node.
 
         :param node: the node to start
         :type node: :class:`Node`
 
-        :param ex_host: Host id to start the node on. Only available for
-                        private cloud hosts. (optional)
-        :type ex_host: ``int``
-
-        :param ex_avoid_host: Host id to avoid when starting the node.
-                              (optional)
-        :type ex_avoid_host: ``int``
-
-        :param ex_start_type: Start type, ``sync`` or ``async``. (optional)
-        :type ex_start_type: ``str``
-
         :rtype: ``bool``
         """
-        server = {}
-        if ex_host is not None:
-            server["host"] = ex_host
-        if ex_avoid_host is not None:
-            server["avoid_host"] = ex_avoid_host
-        if ex_start_type is not None:
-            server["start_type"] = ex_start_type
-
-        self.connection.request(
-            "1.2/server/{}/start".format(node.id),
-            method="POST",
-            data=json.dumps({"server": server}),
-        )
+        self.connection.request("1.2/server/{}/start".format(node.id), 
method="POST")
         return True
 
     def stop_node(self, node, ex_stop_type="hard", ex_timeout=None):
diff --git 
a/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_01d4fcd4-e446-433b-8a9c-551a1284952e.json
 
b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_01d4fcd4-e446-433b-8a9c-551a1284952e.json
index 2269ac415..10f3e7738 100644
--- 
a/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_01d4fcd4-e446-433b-8a9c-551a1284952e.json
+++ 
b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_01d4fcd4-e446-433b-8a9c-551a1284952e.json
@@ -1,17 +1,10 @@
 {
   "storage": {
     "access": "private",
-    "encrypted": "yes",
     "backup_rule": "",
     "backups": {
       "backup": []
     },
-    "labels": [
-      {
-        "key": "env",
-        "value": "test"
-      }
-    ],
     "license": 0,
     "servers": {
       "server": [
@@ -20,7 +13,7 @@
     },
     "size": 50,
     "state": "online",
-    "tier": "standard",
+    "tier": "maxiops",
     "title": "data",
     "type": "normal",
     "uuid": "01d4fcd4-e446-433b-8a9c-551a1284952e",
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_create.json 
b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_create.json
index aa16983f1..60dc27094 100644
--- a/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_create.json
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_create.json
@@ -1,24 +1,17 @@
 {
   "storage": {
     "access": "private",
-    "encrypted": "yes",
     "backup_rule": "",
     "backups": {
       "backup": []
     },
-    "labels": [
-      {
-        "key": "env",
-        "value": "test"
-      }
-    ],
     "license": 0,
     "servers": {
       "server": []
     },
     "size": 50,
     "state": "online",
-    "tier": "standard",
+    "tier": "maxiops",
     "title": "data",
     "type": "normal",
     "uuid": "01d4fcd4-e446-433b-8a9c-551a1284952e",
diff --git a/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_normal.json 
b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_normal.json
index 2c274c5d2..1fdc1cbef 100644
--- a/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_normal.json
+++ b/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_normal.json
@@ -3,8 +3,6 @@
     "storage": [
       {
         "access": "private",
-        "encrypted": "no",
-        "labels": [],
         "license": 0,
         "size": 10,
         "state": "online",
@@ -16,20 +14,13 @@
       },
       {
         "access": "private",
-        "encrypted": "yes",
-        "labels": [
-          {
-            "key": "env",
-            "value": "test"
-          }
-        ],
         "license": 0,
         "servers": {
           "server": []
         },
         "size": 50,
         "state": "online",
-        "tier": "standard",
+        "tier": "maxiops",
         "title": "data",
         "type": "normal",
         "uuid": "01d4fcd4-e446-433b-8a9c-551a1284952e",
diff --git a/libcloud/test/compute/test_upcloud.py 
b/libcloud/test/compute/test_upcloud.py
index 06d5a7c6b..a8ea45cf6 100644
--- a/libcloud/test/compute/test_upcloud.py
+++ b/libcloud/test/compute/test_upcloud.py
@@ -221,7 +221,7 @@ class UpcloudDriverTests(LibcloudTestCase):
             "action": "create",
             "title": "data",
             "size": 25,
-            "tier": "standard",
+            "tier": "maxiops",
         }
 
         self.driver.create_node(
@@ -256,19 +256,16 @@ class UpcloudDriverTests(LibcloudTestCase):
             size=50,
             name="data",
             location=location,
-            ex_tier="standard",
-            ex_encrypted=True,
-            ex_labels=[{"key": "env", "value": "test"}],
+            ex_tier="maxiops",
         )
 
         self.assertEqual(volume.id, "01d4fcd4-e446-433b-8a9c-551a1284952e")
         self.assertEqual(volume.name, "data")
         self.assertEqual(volume.size, 50)
-        self.assertEqual(volume.extra["encrypted"], "yes")
         request_storage = UpcloudMockHttp.last_request_body["storage"]
-        self.assertEqual(request_storage["tier"], "standard")
-        self.assertEqual(request_storage["encrypted"], "yes")
-        self.assertEqual(request_storage["labels"], [{"key": "env", "value": 
"test"}])
+        self.assertEqual(request_storage["tier"], "maxiops")
+        self.assertNotIn("encrypted", request_storage)
+        self.assertNotIn("labels", request_storage)
 
     def test_create_volume_requires_location(self):
         with self.assertRaises(ValueError):
@@ -278,18 +275,26 @@ class UpcloudDriverTests(LibcloudTestCase):
         node = self.driver.list_nodes()[0]
         volume = self.driver.list_volumes()[1]
 
-        attached_volume = self.driver.attach_volume(node, volume, 
device="scsi")
+        success = self.driver.attach_volume(node, volume, device="scsi")
 
-        self.assertIsInstance(attached_volume, StorageVolume)
-        self.assertEqual(attached_volume.id, volume.id)
+        self.assertTrue(success)
         request_device = UpcloudMockHttp.last_request_body["storage_device"]
-        self.assertEqual(request_device["server"], node.id)
+        self.assertEqual(request_device["storage"], volume.id)
         self.assertEqual(request_device["address"], "scsi")
         self.assertEqual(request_device["boot_disk"], "0")
 
     def test_detach_volume(self):
+        node = self.driver.list_nodes()[0]
+        volume = self.driver.list_volumes()[1]
+        self.assertTrue(self.driver.detach_volume(volume, ex_node=node, 
ex_address="scsi:0:0"))
+
+        request_device = UpcloudMockHttp.last_request_body["storage_device"]
+        self.assertEqual(request_device["address"], "scsi:0:0")
+
+    def test_detach_volume_requires_node_and_address(self):
         volume = self.driver.list_volumes()[1]
-        self.assertTrue(self.driver.detach_volume(volume))
+        with self.assertRaises(ValueError):
+            self.driver.detach_volume(volume)
 
     def test_destroy_volume(self):
         volume = self.driver.list_volumes()[1]
@@ -313,24 +318,10 @@ class UpcloudDriverTests(LibcloudTestCase):
 
     def test_start_node(self):
         nodes = self.driver.list_nodes()
-        success = self.driver.start_node(
-            nodes[0],
-            ex_host=8055964291,
-            ex_avoid_host=7653311107,
-            ex_start_type="async",
-        )
+        success = self.driver.start_node(nodes[0])
 
         self.assertTrue(success)
-        self.assertEqual(
-            UpcloudMockHttp.last_request_body,
-            {
-                "server": {
-                    "host": 8055964291,
-                    "avoid_host": 7653311107,
-                    "start_type": "async",
-                }
-            },
-        )
+        self.assertIsNone(UpcloudMockHttp.last_request_body)
 
     def test_stop_node(self):
         nodes = self.driver.list_nodes()
@@ -443,17 +434,18 @@ class UpcloudMockHttp(MockHttp):
         body = self.fixtures.load("api_1_2_storage_create.json")
         return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
 
-    def _1_2_storage_01d4fcd4_e446_433b_8a9c_551a1284952e_attach(
+    def _1_2_server_00f8c525_7e62_4108_8115_3958df5b43dc_storage_attach(
         self, method, url, body, headers
     ):
         self.__class__.last_request_body = json.loads(body)
-        body = 
self.fixtures.load("api_1_2_storage_01d4fcd4-e446-433b-8a9c-551a1284952e.json")
+        body = 
self.fixtures.load("api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json")
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _1_2_storage_01d4fcd4_e446_433b_8a9c_551a1284952e_detach(
+    def _1_2_server_00f8c525_7e62_4108_8115_3958df5b43dc_storage_detach(
         self, method, url, body, headers
     ):
-        body = 
self.fixtures.load("api_1_2_storage_01d4fcd4-e446-433b-8a9c-551a1284952e.json")
+        self.__class__.last_request_body = json.loads(body)
+        body = 
self.fixtures.load("api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json")
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _1_2_storage_01d4fcd4_e446_433b_8a9c_551a1284952e(self, method, url, 
body, headers):
@@ -470,7 +462,7 @@ class UpcloudMockHttp(MockHttp):
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _1_2_server_00f8c525_7e62_4108_8115_3958df5b43dc_start(self, method, 
url, body, headers):
-        self.__class__.last_request_body = json.loads(body)
+        self.__class__.last_request_body = body
         body = 
self.fixtures.load("api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json")
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 

Reply via email to