You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2020/08/30 14:50:09 UTC

[libcloud] branch trunk updated (7ddda6a -> e6c32e5)

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

tomaz pushed a change to branch trunk
in repository https://gitbox.apache.org/repos/asf/libcloud.git.


    from 7ddda6a  Merge pull request #1483 from Kami/paramiko_compression_and_keepalive
     add 869b0d3  Create new compute driver outscale sdk
     add f263c39  Basic calls for compute driver outscale sdk
     add d3810a4  Add test file for compute driver outscale sdk
     add d4fa505  added an osc signature class and some unit tests for it
     add e34ccc7  outscale sdk replacement start
     add c509400  All is working, before refactoring
     add 100bee9  Providers added
     add e21580f  Refactored
     add 69fd665  Added some unit tests
     add 692ae5c  Contribution Guideline friendly code changes
     add fea49fe  Remove oustcale_sdk implementation
     add 7dbc5f2  Resolve some merge errors
     add dc26248  Resolve some linting errors
     add 87cc2df  changes for Flake8 compliance
     add a3af73f  splited every line over 79 character for Flake8 compliance
     add 9c1e71b  Flake8 indent corrections
     add d54a569  unittest reworked
     add 5e7fc13  resolved a date issue in test_osc
     add 956c95e  Changed an endpoint on list_nodes method for Outscale API
     new 64a0d90  type annotation for MyPy, changed signer creation and usage
     new 8921ede  Worked on Outscale Provider comply more with Libcloud API
     new bf576d1  Changed code so it use with Libcloud resources' class on Outscale Provider
     new fe5e236  Changed some utils function and some return value for more compliance with libcloud standard provider methods
     new 882d2fa  modified list_location for better compliance with base Driver and reorganised outscale driver methods order
     new 6f78c1a  Flake8 and MyPy compliance for outscale driver
     new 48fa2fa  Reduced duplication in outscale driver
     new 86ef1f1  Merge branch 'trunk' of https://github.com/outscale-dev/libcloud into outscale-dev-trunk
     new ea0df48  Update docstrings.
     new e6c32e5  Add changelog entry.

The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CHANGES.rst                          |    6 +
 libcloud/common/osc.py               |  160 ++++++
 libcloud/compute/drivers/outscale.py | 1019 ++++++++++++++++++++++++++++++++++
 libcloud/compute/providers.py        |    2 +
 libcloud/compute/types.py            |    2 +
 libcloud/test/common/test_osc.py     |  142 +++++
 6 files changed, 1331 insertions(+)
 create mode 100644 libcloud/common/osc.py
 create mode 100644 libcloud/compute/drivers/outscale.py
 create mode 100644 libcloud/test/common/test_osc.py


[libcloud] 03/10: Changed code so it use with Libcloud resources' class on Outscale Provider

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit bf576d18ecbfab23a477f7125a00d94eff1b9eee
Author: Tio Gobin <ti...@epitech.eu>
AuthorDate: Sun Aug 23 18:49:15 2020 +0200

    Changed code so it use with Libcloud resources' class on Outscale Provider
---
 libcloud/compute/drivers/outscale.py | 270 +++++++++++++++++++++--------------
 1 file changed, 160 insertions(+), 110 deletions(-)

diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index 97a4015..58bd08f 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -24,7 +24,7 @@ from libcloud.compute.base import NodeDriver
 from libcloud.compute.types import Provider
 from libcloud.common.osc import OSCRequestSignerAlgorithmV4
 from libcloud.common.base import ConnectionUserAndKey
-from libcloud.compute.base import Node, NodeImage, KeyPair
+from libcloud.compute.base import Node, NodeImage, KeyPair, StorageVolume, VolumeSnapshot
 from libcloud.compute.types import NodeState
 
 
@@ -743,85 +743,103 @@ class OutscaleNodeDriver(NodeDriver):
         key_pair = requests.post(endpoint, data=data, headers=headers).json()["Keypairs"][0]
         return self._to_key_pair(key_pair)
 
-    def delete_key_pair(self, name: str):
+    def delete_key_pair(self, key_pair: KeyPair):
         """
         Delete an image.
 
-        :param      name: the name of the keypair you want to delete (required)
-        :type       name: ``str``
+        :param      key_pair: the name of the keypair you want to delete (required)
+        :type       key_pair: ``KeyPair``
 
-        :return: request
-        :rtype: ``dict``
+        :return: boolean
+        :rtype: ``bool``
         """
         action = "DeleteKeypair"
-        data = '{"KeypairName": "' + name + '"}'
+        data = '{"KeypairName": "' + key_pair.name + '"}'
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
+
+    def _to_volume(self, volume):
+        name = ""
+        for tag in volume["Tags"]:
+            if tag["Key"] == "Name":
+                name = tag["Value"]
+        return StorageVolume(
+            id=volume["VolumeId"],
+            name=name,
+            size=volume["Size"],
+            driver=self,
+            state=volume["State"],
+            extra=volume
+        )
+
+    def _to_volumes(self, volumes):
+        return [self._to_volumes(volume) for volume in volumes]
 
-    def create_snapshot(self,
-                        description: str = None,
-                        dry_run: bool = False,
-                        file_location: str = None,
-                        snapshot_size: int = None,
-                        source_region_name: str = None,
-                        source_snapshot_id: str = None,
-                        volume_id: str = None,
-                        ):
+    def create_volume_snapshot(
+        self,
+        ex_description: str = None,
+        ex_dry_run: bool = False,
+        ex_file_location: str = None,
+        ex_snapshot_size: int = None,
+        ex_source_region_name: str = None,
+        ex_source_snapshot: VolumeSnapshot = None,
+        volume: StorageVolume = None):
         """
         Create a new snapshot.
 
-        :param      description: a description for the new OMI
-        :type       description: ``str``
+        :param      ex_description: a description for the new OMI
+        :type       ex_description: ``str``
 
-        :param      snapshot_size: The size of the snapshot created in your
+        :param      ex_snapshot_size: The size of the snapshot created in your
         account, in bytes. This size must be
         exactly the same as the source snapshot one.
-        :type       snapshot_size: ``integer``
+        :type       ex_snapshot_size: ``integer``
 
-        :param      source_snapshot_id: The ID of the snapshot you want to
+        :param      ex_source_snapshot: The ID of the snapshot you want to
         copy.
-        :type       source_snapshot_id: ``str``
+        :type       ex_source_snapshot: ``str``
 
-        :param      volume_id: The ID of the volume you want to create a
+        :param      volume: The ID of the volume you want to create a
         snapshot of.
-        :type       volume_id: ``str``
+        :type       volume: ``str``
 
-        :param      source_region_name: The name of the source Region,
-        which must be the same
-        as the Region of your account.
-        :type       source_region_name: ``str``
+        :param      ex_source_region_name: The name of the source Region,
+        which must be the same as the Region of your account.
+        :type       ex_source_region_name: ``str``
 
-        :param      file_location: The pre-signed URL of the OMI manifest
+        :param      ex_file_location: The pre-signed URL of the OMI manifest
         file, or the full path to the OMI stored in
         an OSU bucket. If you specify this parameter, a copy of the OMI is
         created in your account.
-        :type       file_location: ``str``
+        :type       ex_file_location: ``str``
 
-        :param      dry_run: If true, checks whether you have the required
+        :param      ex_dry_run: If true, checks whether you have the required
         permissions to perform the action.
-        :type       dry_run: ``bool``
+        :type       ex_dry_run: ``bool``
 
         :return: the created snapshot
         :rtype: ``dict``
         """
         data = {
-            "DryRun": dry_run,
+            "DryRun": ex_dry_run,
         }
-        if description is not None:
-            data.update({"Description": description})
-        if file_location is not None:
-            data.update({"FileLocation": file_location})
-        if snapshot_size is not None:
-            data.update({"SnapshotSize": snapshot_size})
-        if source_region_name is not None:
-            data.update({"SourceRegionName": source_region_name})
-        if source_snapshot_id is not None:
-            data.update({"SourceSnapshotId": source_snapshot_id})
-        if volume_id is not None:
-            data.update({"VolumeId": volume_id})
+        if ex_description is not None:
+            data.update({"Description": ex_description})
+        if ex_file_location is not None:
+            data.update({"FileLocation": ex_file_location})
+        if ex_snapshot_size is not None:
+            data.update({"SnapshotSize": ex_snapshot_size})
+        if ex_source_region_name is not None:
+            data.update({"SourceRegionName": ex_source_region_name})
+        if ex_source_snapshot is not None:
+            data.update({"SourceSnapshotId": ex_source_snapshot.id})
+        if volume is not None:
+            data.update({"VolumeId": volume.id})
         data = json.dumps(data)
         action = "CreateSnapshot"
         headers = self._ex_generate_headers(action, data)
@@ -830,7 +848,25 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_snapshots(self, data: str = "{}"):
+    def _to_snapshot(self, snapshot):
+        name = None
+        for tag in snapshot["Tags"]:
+            if tag["Key"] == "Name":
+                name = tag["Value"]
+        return VolumeSnapshot(
+            id=snapshot["SnapshotId"],
+            name=name,
+            size=snapshot["Size"],
+            driver=self,
+            state=snapshot["State"],
+            created=None,
+            extra=snapshot
+        )
+
+    def _to_snapshots(self, snapshots):
+        return [self._to_snapshot(snapshot) for snapshot in snapshots]
+
+    def list_snapshots(self, ex_data: str = "{}"):
         """
         List all snapshots.
 
@@ -838,84 +874,88 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadSnapshots"
-        headers = self._ex_generate_headers(action, data)
+        headers = self._ex_generate_headers(action, ex_data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        snapshots = requests.post(endpoint, data=ex_data, headers=headers).json()
 
-    def delete_snapshot(self, snapshot_id: str):
+        return self._to_snapshots(snapshots)
+
+    def destroy_volume_snapshot(self, snapshot: VolumeSnapshot):
         """
         Delete a snapshot.
 
-        :param      snapshot_id: the ID of the snapshot
+        :param      snapshot: the ID of the snapshot
                     you want to delete (required)
-        :type       snapshot_id: ``str``
+        :type       snapshot: ``str``
 
         :return: request
         :rtype: ``dict``
         """
         action = "DeleteSnapshot"
-        data = '{"SnapshotId": "' + snapshot_id + '"}'
+        data = '{"SnapshotId": "' + snapshot.id + '"}'
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
     def create_volume(
         self,
-        subregion_name: str,
-        dry_run: bool = False,
-        iops: int = None,
+        ex_subregion_name: str,
+        ex_dry_run: bool = False,
+        ex_iops: int = None,
         size: int = None,
-        snapshot_id: str = None,
-        volume_type: str = None,
+        snapshot: VolumeSnapshot = None,
+        ex_volume_type: str = None,
     ):
         """
         Create a new volume.
 
-        :param      snapshot_id: the ID of the snapshot from which
+        :param      snapshot: the ID of the snapshot from which
                     you want to create the volume (required)
-        :type       snapshot_id: ``str``
+        :type       snapshot: ``str``
 
-        :param      dry_run: If true, checks whether you have the required
+        :param      ex_dry_run: If true, checks whether you have the required
         permissions to perform the action.
-        :type       dry_run: ``bool``
+        :type       ex_dry_run: ``bool``
 
         :param      size: the size of the volume, in gibibytes (GiB),
                     the maximum allowed size for a volume is 14,901 GiB
         :type       size: ``int``
 
-        :param      subregion_name: The Subregion in which you want to
+        :param      ex_subregion_name: The Subregion in which you want to
         create the volume.
-        :type       subregion_name: ``str``
+        :type       ex_subregion_name: ``str``
 
-        :param      volume_type: the type of volume you want to create (io1
+        :param      ex_volume_type: the type of volume you want to create (io1
         | gp2 | standard)
-        :type       volume_type: ``str``
+        :type       ex_volume_type: ``str``
 
-        :param      iops: The number of I/O operations per second (IOPS).
+        :param      ex_iops: The number of I/O operations per second (IOPS).
         This parameter must be specified only if
         you create an io1 volume. The maximum number of IOPS allowed for io1
         volumes is 13000.
-        :type       iops: ``integer``
+        :type       ex_iops: ``integer``
 
         :return: the created volume
         :rtype: ``dict``
         """
         data = {
-            "DryRun": dry_run,
-            "SubregionName": subregion_name
+            "DryRun": ex_dry_run,
+            "SubregionName": ex_subregion_name
         }
-        if iops is not None:
-            data.update({"Iops": iops})
+        if ex_iops is not None:
+            data.update({"Iops": ex_iops})
         if size is not None:
             data.update({"Size": size})
-        if snapshot_id is not None:
-            data.update({"SnapshotId": snapshot_id})
-        if volume_type is not None:
-            data.update({"VolumeType": volume_type})
+        if snapshot is not None:
+            data.update({"SnapshotId": snapshot.id})
+        if ex_volume_type is not None:
+            data.update({"VolumeType": ex_volume_type})
         data = json.dumps(data)
         action = "CreateVolume"
         headers = self._ex_generate_headers(action, data)
@@ -923,9 +963,12 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
 
-    def list_volumes(self, data: str = "{}"):
+        volume = requests.post(endpoint, data=data, headers=headers).json()["Volume"]
+
+        return self._to_volume(volume)
+
+    def list_volumes(self, ex_data: str = "{}"):
         """
         List all volumes.
 
@@ -933,94 +976,101 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadVolumes"
-        headers = self._ex_generate_headers(action, data)
+        headers = self._ex_generate_headers(action, ex_data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        volumes = requests.post(endpoint, data=ex_data, headers=headers).json()["Volumes"]
+        return self._to_volumes(volumes)
 
-    def delete_volume(self, volume_id: str):
+    def destroy_volume(self, volume: StorageVolume):
         """
         Delete a volume.
 
-        :param      volume_id: the ID of the volume
+        :param      volume: the ID of the volume
                     you want to delete (required)
-        :type       volume_id: ``str``
+        :type       volume: ``str``
 
         :return: request
         :rtype: ``dict``
         """
         action = "DeleteVolume"
-        data = '{"VolumeId": "' + volume_id + '"}'
+        data = '{"VolumeId": "' + volume.id + '"}'
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
-    def attach_volume(self, node_id: str, volume_id: str, device_name: str):
+    def attach_volume(self, node: Node, volume: StorageVolume, device: str = None):
         """
         Attach a volume.
 
-        :param      node_id: the ID of the VM you want
+        :param      node: the ID of the VM you want
                     to attach the volume to (required)
-        :type       node_id: ``str``
+        :type       node: ``str``
 
-        :param      volume_id: the ID of the volume
+        :param      volume: the ID of the volume
                     you want to attach (required)
-        :type       volume_id: ``str``
+        :type       volume: ``str``
 
-        :param      device_name: the name of the device (required)
-        :type       device_name: ``str``
+        :param      device: the name of the device (required)
+        :type       device: ``str``
 
         :return: the attached volume
         :rtype: ``dict``
         """
         action = "LinkVolume"
         data = json.dumps({
-            "VmId": node_id,
-            "VolumeId": volume_id,
-            "DeviceName": device_name
+            "VmId": node.id,
+            "VolumeId": volume.id,
+            "DeviceName": device
         })
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
     def detach_volume(self,
-                      volume_id: str,
-                      dry_run: bool = False,
-                      force_unlink: bool = False):
+                      volume: StorageVolume,
+                      ex_dry_run: bool = False,
+                      ex_force_unlink: bool = False):
         """
         Detach a volume.
 
-        :param      volume_id: the ID of the volume you want to detach
+        :param      volume: the ID of the volume you want to detach
         (required)
-        :type       volume_id: ``str``
+        :type       volume: ``str``
 
-        :param      force_unlink: Forces the detachment of the volume in
+        :param      ex_force_unlink: Forces the detachment of the volume in
         case of previous failure.
         Important: This action may damage your data or file systems.
-        :type       force_unlink: ``bool``
+        :type       ex_force_unlink: ``bool``
 
-        :param      dry_run: If true, checks whether you have the required
+        :param      ex_dry_run: If true, checks whether you have the required
         permissions to perform the action.
-        :type       dry_run: ``bool``
+        :type       ex_dry_run: ``bool``
 
         :return: the attached volume
         :rtype: ``dict``
         """
         action = "UnlinkVolume"
-        data = {"DryRun": dry_run, "VolumeId": volume_id}
-        if force_unlink is not None:
-            data.update({"ForceUnlink": force_unlink})
+        data = {"DryRun": ex_dry_run, "VolumeId": volume.id}
+        if ex_force_unlink is not None:
+            data.update({"ForceUnlink": ex_force_unlink})
         data = json.dumps(data)
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
     @staticmethod
     def _get_outscale_endpoint(region: str, version: str, action: str):


[libcloud] 05/10: modified list_location for better compliance with base Driver and reorganised outscale driver methods order

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 882d2fa84f769208085e2d83984986ef01fd1c57
Author: Tio Gobin <ti...@outscale.com>
AuthorDate: Mon Aug 24 13:29:07 2020 +0200

    modified list_location for better compliance with base Driver and reorganised outscale driver methods order
---
 libcloud/compute/drivers/outscale.py | 156 +++++++++++++++++++----------------
 1 file changed, 86 insertions(+), 70 deletions(-)

diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index 5e57ca3..fe1b80b 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -24,7 +24,13 @@ from libcloud.compute.base import NodeDriver
 from libcloud.compute.types import Provider
 from libcloud.common.osc import OSCRequestSignerAlgorithmV4
 from libcloud.common.base import ConnectionUserAndKey
-from libcloud.compute.base import Node, NodeImage, KeyPair, StorageVolume, VolumeSnapshot
+from libcloud.compute.base import \
+    Node,\
+    NodeImage, \
+    KeyPair, \
+    StorageVolume, \
+    VolumeSnapshot, \
+    NodeLocation
 from libcloud.compute.types import NodeState
 
 
@@ -88,7 +94,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        regions = requests.post(endpoint, data=data, headers=headers).json()
+        return self._to_locations(regions["Regions"])
 
     def ex_create_public_ip(self, dry_run: bool = False):
         """
@@ -463,39 +470,6 @@ class OutscaleNodeDriver(NodeDriver):
             return False
         return False
 
-    def _to_node(self, vm):
-        name = ""
-        private_ips = []
-        for tag in vm["Tags"]:
-            if tag["Key"] == "Name":
-                name = tag["Value"]
-        if "PrivateIps" in vm["Nics"]:
-            private_ips = vm["Nics"]["PrivateIps"]
-
-        return Node(id=vm["VmId"],
-                    name=name,
-                    state=self.NODE_STATE[vm["State"]],
-                    public_ips=[],
-                    private_ips=private_ips,
-                    driver=self,
-                    extra=vm)
-
-    def _to_nodes(self, vms: list):
-        return [self._to_node(vm) for vm in vms]
-
-    def _to_node_image(self, image):
-        name = ""
-        for tag in image["Tags"]:
-            if tag["Key"] == "Name":
-                name = tag["Value"]
-        return NodeImage(id=image["NodeId"],
-                         name=name,
-                         driver=self,
-                         extra=image)
-
-    def _to_node_images(self, node_images: list):
-        return [self._to_node_image(node_image) for node_image in node_images]
-
     def list_nodes(self, ex_data: str = "{}"):
         """
         List all nodes.
@@ -773,23 +747,6 @@ class OutscaleNodeDriver(NodeDriver):
             return True
         return False
 
-    def _to_volume(self, volume):
-        name = ""
-        for tag in volume["Tags"]:
-            if tag["Key"] == "Name":
-                name = tag["Value"]
-        return StorageVolume(
-            id=volume["VolumeId"],
-            name=name,
-            size=volume["Size"],
-            driver=self,
-            state=volume["State"],
-            extra=volume
-        )
-
-    def _to_volumes(self, volumes):
-        return [self._to_volumes(volume) for volume in volumes]
-
     def create_volume_snapshot(
         self,
         ex_description: str = None,
@@ -860,24 +817,6 @@ class OutscaleNodeDriver(NodeDriver):
         snapshot = requests.post(endpoint, data=data, headers=headers).json()["Volume"]
         return self._to_snapshot(snapshot)
 
-    def _to_snapshot(self, snapshot):
-        name = None
-        for tag in snapshot["Tags"]:
-            if tag["Key"] == "Name":
-                name = tag["Value"]
-        return VolumeSnapshot(
-            id=snapshot["SnapshotId"],
-            name=name,
-            size=snapshot["Size"],
-            driver=self,
-            state=snapshot["State"],
-            created=None,
-            extra=snapshot
-        )
-
-    def _to_snapshots(self, snapshots):
-        return [self._to_snapshot(snapshot) for snapshot in snapshots]
-
     def list_snapshots(self, ex_data: str = "{}"):
         """
         List all snapshots.
@@ -1096,3 +1035,80 @@ class OutscaleNodeDriver(NodeDriver):
                                              service_name=self.service_name,
                                              region=self.region)
 
+    def _to_location(self, region):
+        return NodeLocation(id="",
+                    name=region["RegionName"],
+                    country="",
+                    driver=self,
+                    extra=region)
+
+    def _to_locations(self, regions: list):
+        return [self._to_location(region) for region in regions]
+
+    def _to_snapshot(self, snapshot):
+        name = None
+        for tag in snapshot["Tags"]:
+            if tag["Key"] == "Name":
+                name = tag["Value"]
+        return VolumeSnapshot(
+            id=snapshot["SnapshotId"],
+            name=name,
+            size=snapshot["Size"],
+            driver=self,
+            state=snapshot["State"],
+            created=None,
+            extra=snapshot
+        )
+
+    def _to_snapshots(self, snapshots):
+        return [self._to_snapshot(snapshot) for snapshot in snapshots]
+
+    def _to_volume(self, volume):
+        name = ""
+        for tag in volume["Tags"]:
+            if tag["Key"] == "Name":
+                name = tag["Value"]
+        return StorageVolume(
+            id=volume["VolumeId"],
+            name=name,
+            size=volume["Size"],
+            driver=self,
+            state=volume["State"],
+            extra=volume
+        )
+
+    def _to_volumes(self, volumes):
+        return [self._to_volumes(volume) for volume in volumes]
+
+    def _to_node(self, vm):
+        name = ""
+        private_ips = []
+        for tag in vm["Tags"]:
+            if tag["Key"] == "Name":
+                name = tag["Value"]
+        if "Nics" in vm:
+            private_ips = vm["Nics"]["PrivateIps"]
+
+        return Node(id=vm["VmId"],
+                    name=name,
+                    state=self.NODE_STATE[vm["State"]],
+                    public_ips=[],
+                    private_ips=private_ips,
+                    driver=self,
+                    extra=vm)
+
+    def _to_nodes(self, vms: list):
+        return [self._to_node(vm) for vm in vms]
+
+    def _to_node_image(self, image):
+        name = ""
+        for tag in image["Tags"]:
+            if tag["Key"] == "Name":
+                name = tag["Value"]
+        return NodeImage(id=image["NodeId"],
+                         name=name,
+                         driver=self,
+                         extra=image)
+
+    def _to_node_images(self, node_images: list):
+        return [self._to_node_image(node_image) for node_image in node_images]


[libcloud] 02/10: Worked on Outscale Provider comply more with Libcloud API

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 8921ede58112c878368d1f9b8e117cc135ed8cf3
Author: Tio Gobin <ti...@epitech.eu>
AuthorDate: Sat Aug 15 17:00:44 2020 +0200

    Worked on Outscale Provider comply more with Libcloud API
---
 libcloud/compute/drivers/outscale.py | 447 +++++++++++++++++++++--------------
 1 file changed, 270 insertions(+), 177 deletions(-)

diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index 5e8326b..97a4015 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -24,6 +24,8 @@ from libcloud.compute.base import NodeDriver
 from libcloud.compute.types import Provider
 from libcloud.common.osc import OSCRequestSignerAlgorithmV4
 from libcloud.common.base import ConnectionUserAndKey
+from libcloud.compute.base import Node, NodeImage, KeyPair
+from libcloud.compute.types import NodeState
 
 
 class OutscaleNodeDriver(NodeDriver):
@@ -55,15 +57,25 @@ class OutscaleNodeDriver(NodeDriver):
                                              version=self.version,
                                              connection=self.connection)
 
-    def list_locations(self, dry_run: bool = False):
+        self.NODE_STATE = {
+            'pending': NodeState.PENDING,
+            'running': NodeState.RUNNING,
+            'shutting-down': NodeState.UNKNOWN,
+            'terminated': NodeState.TERMINATED,
+            'stopped': NodeState.STOPPED
+        }
+
+    def list_locations(self, ex_dry_run: bool = False):
         """
         Lists available regions details.
-
+        :param      ex_dry_run: If true, checks whether you have the required
+        permissions to perform the action.
+        :type       ex_dry_run: ``bool``
         :return: regions details
         :rtype: ``dict``
         """
         action = "ReadRegions"
-        data = json.dumps({"DryRun": dry_run})
+        data = json.dumps({"DryRun": ex_dry_run})
         signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
                                              access_secret=self.secret,
                                              version=self.version,
@@ -77,7 +89,7 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def create_public_ip(self, dry_run: bool = False):
+    def ex_create_public_ip(self, dry_run: bool = False):
         """
         Create a new public ip.
 
@@ -96,9 +108,10 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def delete_public_ip(self, dry_run: bool = False,
-                         public_ip: str = None,
-                         public_ip_id: str = None):
+    def ex_delete_public_ip(self,
+                            dry_run: bool = False,
+                            public_ip: str = None,
+                            public_ip_id: str = None):
         """
         Delete instances.
 
@@ -131,7 +144,7 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_public_ips(self, data: str = "{}"):
+    def ex_list_public_ips(self, data: str = "{}"):
         """
         List all nodes.
 
@@ -149,7 +162,7 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_public_ip_ranges(self, dry_run: bool = False):
+    def ex_list_public_ip_ranges(self, dry_run: bool = False):
         """
         Lists available regions details.
 
@@ -168,14 +181,14 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def attach_public_ip(self,
-                         allow_relink: bool = None,
-                         dry_run: bool = False,
-                         nic_id: str = None,
-                         vm_id: str = None,
-                         public_ip: str = None,
-                         public_ip_id: str = None,
-                         ):
+    def ex_attach_public_ip(self,
+                            allow_relink: bool = None,
+                            dry_run: bool = False,
+                            nic_id: str = None,
+                            vm_id: str = None,
+                            public_ip: str = None,
+                            public_ip_id: str = None,
+                            ):
         """
         Attach a volume.
 
@@ -228,9 +241,10 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def detach_public_ip(self, public_ip: str = None,
-                         link_public_ip_id: str = None,
-                         dry_run: bool = False):
+    def ex_detach_public_ip(self,
+                            public_ip: str = None,
+                            link_public_ip_id: str = None,
+                            dry_run: bool = False):
         """
         Detach a volume.
 
@@ -264,130 +278,150 @@ class OutscaleNodeDriver(NodeDriver):
         return requests.post(endpoint, data=data, headers=headers)
 
     def create_node(self,
-                    image_id: str,
-                    dry_run: bool = False,
-                    block_device_mapping: dict = None,
-                    boot_on_creation: bool = True,
-                    bsu_optimized: bool = True,
-                    client_token: str = None,
-                    deletion_protection: bool = False,
-                    keypair_name: str = None,
-                    max_vms_count: int = None,
-                    min_vms_count: int = None,
-                    nics: dict = None,
-                    performance: str = None,
-                    placement: dict = None,
-                    private_ips: [str] = None,
-                    security_group_ids: [str] = None,
-                    security_groups: [str] = None,
-                    subnet_id: str = None,
+                    ex_image_id: str,
+                    ex_dry_run: bool = False,
+                    ex_block_device_mapping: dict = None,
+                    ex_boot_on_creation: bool = True,
+                    ex_bsu_optimized: bool = True,
+                    ex_client_token: str = None,
+                    ex_deletion_protection: bool = False,
+                    ex_keypair_name: str = None,
+                    ex_max_vms_count: int = None,
+                    ex_min_vms_count: int = None,
+                    ex_nics: dict = None,
+                    ex_performance: str = None,
+                    ex_placement: dict = None,
+                    ex_private_ips: [str] = None,
+                    ex_security_group_ids: [str] = None,
+                    ex_security_groups: [str] = None,
+                    ex_subnet_id: str = None,
+                    ex_user_data: str = None,
+                    ex_vm_initiated_shutdown_behavior: str = None,
+                    ex_vm_type: str = None
                     ):
         """
         Create a new instance.
 
-        :param      image_id: The ID of the OMI used to create the VM.
-        :type       image_id: ``str``
+        :param      ex_image_id: The ID of the OMI used to create the VM.
+        :type       ex_image_id: ``str``
 
-        :param      dry_run: If true, checks whether you have the required
+        :param      ex_dry_run: If true, checks whether you have the required
         permissions to perform the action.
-        :type       dry_run: ``bool``
+        :type       ex_dry_run: ``bool``
 
-        :param      block_device_mapping: One or more block device mappings.
-        :type       block_device_mapping: ``dict``
+        :param      ex_block_device_mapping: One or more block device mappings.
+        :type       ex_block_device_mapping: ``dict``
 
-        :param      boot_on_creation: By default or if true, the VM is
+        :param      ex_boot_on_creation: By default or if true, the VM is
         started on creation. If false, the VM is
         stopped on creation.
-        :type       boot_on_creation: ``bool``
+        :type       ex_boot_on_creation: ``bool``
 
-        :param      bsu_optimized: If true, the VM is created with optimized
+        :param      ex_bsu_optimized: If true, the VM is created with optimized
         BSU I/O.
-        :type       bsu_optimized: ``bool``
+        :type       ex_bsu_optimized: ``bool``
 
-        :param      client_token: A unique identifier which enables you to
+        :param      ex_client_token: A unique identifier which enables you to
         manage the idempotency.
-        :type       client_token: ``bool``
+        :type       ex_client_token: ``bool``
 
-        :param      deletion_protection: If true, you cannot terminate the
+        :param      ex_deletion_protection: If true, you cannot terminate the
         VM using Cockpit, the CLI or the API.
         If false, you can.
-        :type       deletion_protection: ``bool``
+        :type       ex_deletion_protection: ``bool``
 
-        :param      keypair_name: The name of the keypair.
-        :type       keypair_name: ``str``
+        :param      ex_keypair_name: The name of the keypair.
+        :type       ex_keypair_name: ``str``
 
-        :param      max_vms_count: The maximum number of VMs you want to
+        :param      ex_max_vms_count: The maximum number of VMs you want to
         create. If all the VMs cannot be created, the
         largest possible number of VMs above MinVmsCount is created.
-        :type       max_vms_count: ``integer``
+        :type       ex_max_vms_count: ``integer``
 
-        :param      min_vms_count: The minimum number of VMs you want to
+        :param      ex_min_vms_count: The minimum number of VMs you want to
         create. If this number of VMs cannot be
         created, no VMs are created.
-        :type       min_vms_count: ``integer``
+        :type       ex_min_vms_count: ``integer``
 
-        :param      nics: One or more NICs. If you specify this parameter,
+        :param      ex_nics: One or more NICs. If you specify this parameter,
         you must define one NIC as the primary
         network interface of the VM with 0 as its device number.
-        :type       nics: ``dict``
+        :type       ex_nics: ``dict``
 
-        :param      performance: The performance of the VM (standard | high
+        :param      ex_performance: The performance of the VM (standard | high
         | highest).
-        :type       performance: ``str``
+        :type       ex_performance: ``str``
 
-        :param      placement: Information about the placement of the VM.
-        :type       placement: ``dict``
+        :param      ex_placement: Information about the placement of the VM.
+        :type       ex_placement: ``dict``
 
-        :param      private_ips: One or more private IP addresses of the VM.
-        :type       private_ips: ``list``
+        :param      ex_private_ips: One or more private IP addresses of the VM.
+        :type       ex_private_ips: ``list``
 
-        :param      security_group_ids: One or more IDs of security group
+        :param      ex_security_group_ids: One or more IDs of security group
         for the VMs.
-        :type       security_group_ids: ``list``
+        :type       ex_security_group_ids: ``list``
 
-        :param      security_groups: One or more names of security groups
+        :param      ex_security_groups: One or more names of security groups
         for the VMs.
-        :type       security_groups: ``list``
+        :type       ex_security_groups: ``list``
+
+        :param      ex_subnet_id: The ID of the Subnet in which you want to
+        create the VM.
+        :type       ex_subnet_id: ``str``
+
+        :param      ex_user_data: Data or script used to add a specific configuration to the VM. It must be base64-encoded.
+        :type       ex_user_data: ``str``
 
-        :param      subnet_id: The ID of the Subnet in which you want to
+        :param      ex_vm_initiated_shutdown_behavior: The VM behavior when you stop it. By default or if set to stop, the
+        VM stops. If set to restart, the VM stops then automatically restarts. If set to terminate, the VM stops and is terminated.
         create the VM.
-        :type       subnet_id: ``str``
+        :type       ex_vm_initiated_shutdown_behavior: ``str``
+
+        :param      ex_vm_type: The type of VM (t2.small by default).
+        :type       ex_vm_type: ``str``
 
         :return: the created instance
         :rtype: ``dict``
         """
         data = {
-            "DryRun": dry_run,
-            "BootOnCreation": boot_on_creation,
-            "BsuOptimized": bsu_optimized,
-            "ImageId": image_id
+            "DryRun": ex_dry_run,
+            "BootOnCreation": ex_boot_on_creation,
+            "BsuOptimized": ex_bsu_optimized,
+            "ImageId": ex_image_id
         }
-        if block_device_mapping is not None:
-            data.update({"BlockDeviceMappings": block_device_mapping})
-        if client_token is not None:
-            data.update({"ClientToken": client_token})
-        if deletion_protection is not None:
-            data.update({"DeletionProtection": deletion_protection})
-        if keypair_name is not None:
-            data.update({"KeypairName": keypair_name})
-        if max_vms_count is not None:
-            data.update({"MaxVmsCount": max_vms_count})
-        if min_vms_count is not None:
-            data.update({"MinVmsCount": min_vms_count})
-        if nics is not None:
-            data.update({"Nics": nics})
-        if performance is not None:
-            data.update({"Performance": performance})
-        if placement is not None:
-            data.update({"Placement": placement})
-        if private_ips is not None:
-            data.update({"PrivateIps": private_ips})
-        if security_group_ids is not None:
-            data.update({"SecurityGroupIds": security_group_ids})
-        if security_groups is not None:
-            data.update({"SecurityGroups": security_groups})
-        if subnet_id is not None:
-            data.update({"SubnetId": subnet_id})
+        if ex_block_device_mapping is not None:
+            data.update({"BlockDeviceMappings": ex_block_device_mapping})
+        if ex_client_token is not None:
+            data.update({"ClientToken": ex_client_token})
+        if ex_deletion_protection is not None:
+            data.update({"DeletionProtection": ex_deletion_protection})
+        if ex_keypair_name is not None:
+            data.update({"KeypairName": ex_keypair_name})
+        if ex_max_vms_count is not None:
+            data.update({"MaxVmsCount": ex_max_vms_count})
+        if ex_min_vms_count is not None:
+            data.update({"MinVmsCount": ex_min_vms_count})
+        if ex_nics is not None:
+            data.update({"Nics": ex_nics})
+        if ex_performance is not None:
+            data.update({"Performance": ex_performance})
+        if ex_placement is not None:
+            data.update({"Placement": ex_placement})
+        if ex_private_ips is not None:
+            data.update({"PrivateIps": ex_private_ips})
+        if ex_security_group_ids is not None:
+            data.update({"SecurityGroupIds": ex_security_group_ids})
+        if ex_security_groups is not None:
+            data.update({"SecurityGroups": ex_security_groups})
+        if ex_user_data is not None:
+            data.update({"UserData": ex_user_data})
+        if ex_vm_initiated_shutdown_behavior is not None:
+            data.update({"VmInstantiatedShutdownBehavior": ex_vm_initiated_shutdown_behavior})
+        if ex_vm_type is not None:
+            data.update({"VmType": ex_vm_type})
+        if ex_subnet_id is not None:
+            data.update({"SubnetId": ex_subnet_id})
         action = "CreateVms"
         data = json.dumps(data)
         headers = self._ex_generate_headers(action, data)
@@ -396,26 +430,65 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def reboot_node(self, node_ids: [str]):
+    def reboot_node(self, node: Node):
         """
         Reboot instances.
 
-        :param      node_ids: the ID(s) of the VM(s)
+        :param      node: the ID(s) of the VM(s)
                     you want to reboot (required)
-        :type       node_ids: ``list``
+        :type       node: ``list``
 
         :return: the rebooted instances
         :rtype: ``dict``
         """
         action = "RebootVms"
-        data = json.dumps({"VmIds": node_ids})
+        data = json.dumps({"VmIds": node.id})
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_nodes(self, data: str = "{}"):
+    def _to_nodes(self, vms: list):
+        nodes_list = []
+        for vm in vms:
+            name = ""
+            private_ips = []
+            for tag in vm["Tags"]:
+                if tag["Key"] == "Name":
+                    name = tag["Value"]
+            if "PrivateIps" in vm["Nics"]:
+                private_ips = vm["Nics"]["PrivateIps"]
+
+            node = Node(id=vm["VmId"],
+                        name=name,
+                        state=self.NODE_STATE[vm["State"]],
+                        public_ips=[],
+                        private_ips=private_ips,
+                        driver=self,
+                        extra=vm)
+            nodes_list.append(node)
+        return nodes_list
+
+    def _to_node_images(self, node_images: list):
+        node_image_list = []
+        for image in node_images:
+            name = ""
+            private_ips = []
+            for tag in image["Tags"]:
+                if tag["Key"] == "Name":
+                    name = tag["Value"]
+            if "PrivateIps" in image["Nics"]:
+                private_ips = image["Nics"]["PrivateIps"]
+
+            node = NodeImage(id=image["NodeId"],
+                             name=name,
+                             driver=self,
+                             extra=image)
+            node_image_list.append(node)
+        return node_image_list
+
+    def list_nodes(self, ex_data: str = "{}"):
         """
         List all nodes.
 
@@ -423,24 +496,25 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadVms"
-        headers = self._ex_generate_headers(action, data)
+        headers = self._ex_generate_headers(action, ex_data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        vms = requests.post(endpoint, data=ex_data, headers=headers).json()["Vms"]
+        return self._to_nodes(vms)
 
-    def delete_node(self, node_ids: [str]):
+    def destroy_node(self, node: Node):
         """
         Delete instances.
 
-        :param      node_ids: one or more IDs of VMs (required)
-        :type       node_ids: ``list``
+        :param      node: one or more IDs of VMs (required)
+        :type       node: ``Node``
 
         :return: request
         :rtype: ``dict``
         """
         action = "DeleteVms"
-        data = json.dumps({"VmIds": node_ids})
+        data = json.dumps({"VmIds": node.id})
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
@@ -449,81 +523,80 @@ class OutscaleNodeDriver(NodeDriver):
 
     def create_image(
         self,
-        architecture: str = None,
-        vm_id: str = None,
-        image_name: str = None,
+        ex_architecture: str = None,
+        node: Node = None,
+        name: str = None,
         description: str = None,
-        block_device_mapping: dict = None,
-        no_reboot: bool = False,
-        root_device_name: str = None,
-        dry_run: bool = False,
-        source_region_name: str = None,
-        file_location: str = None
+        ex_block_device_mapping: dict = None,
+        ex_no_reboot: bool = False,
+        ex_root_device_name: str = None,
+        ex_dry_run: bool = False,
+        ex_source_region_name: str = None,
+        ex_file_location: str = None
     ):
         """
         Create a new image.
 
-        :param      vm_id: the ID of the VM from which
-                    you want to create the OMI (required)
-        :type       vm_id: ``str``
+        :param      node: a valid Node object
+        :type       node: ``str``
 
-        :param      architecture: The architecture of the OMI (by default,
+        :param      ex_architecture: The architecture of the OMI (by default,
         i386).
-        :type       architecture: ``str``
+        :type       ex_architecture: ``str``
 
         :param      description: a description for the new OMI
         :type       description: ``str``
 
-        :param      image_name: A unique name for the new OMI.
-        :type       image_name: ``str``
+        :param      name: A unique name for the new OMI.
+        :type       name: ``str``
 
-        :param      block_device_mapping: One or more block device mappings.
-        :type       block_device_mapping: ``dict``
+        :param      ex_block_device_mapping: One or more block device mappings.
+        :type       ex_block_device_mapping: ``dict``
 
-        :param      no_reboot: If false, the VM shuts down before creating
+        :param      ex_no_reboot: If false, the VM shuts down before creating
         the OMI and then reboots.
         If true, the VM does not.
-        :type       no_reboot: ``bool``
+        :type       ex_no_reboot: ``bool``
 
-        :param      root_device_name: The name of the root device.
-        :type       root_device_name: ``str``
+        :param      ex_root_device_name: The name of the root device.
+        :type       ex_root_device_name: ``str``
 
-        :param      source_region_name: The name of the source Region,
+        :param      ex_source_region_name: The name of the source Region,
         which must be the same
         as the Region of your account.
-        :type       source_region_name: ``str``
+        :type       ex_source_region_name: ``str``
 
-        :param      file_location: The pre-signed URL of the OMI manifest
+        :param      ex_file_location: The pre-signed URL of the OMI manifest
         file, or the full path to the OMI stored in
         an OSU bucket. If you specify this parameter, a copy of the OMI is
         created in your account.
-        :type       file_location: ``str``
+        :type       ex_file_location: ``str``
 
-        :param      dry_run: If true, checks whether you have the required
+        :param      ex_dry_run: If true, checks whether you have the required
         permissions to perform the action.
-        :type       dry_run: ``bool``
+        :type       ex_dry_run: ``bool``
 
         :return: the created image
         :rtype: ``dict``
         """
         data = {
-            "DryRun": dry_run,
-            "NoReboot": no_reboot,
+            "DryRun": ex_dry_run,
+            "NoReboot": ex_no_reboot,
         }
-        if block_device_mapping is not None:
-            data.update({"BlockDeviceMappings": block_device_mapping})
-        if image_name is not None:
-            data.update({"ImageName": image_name})
+        if ex_block_device_mapping is not None:
+            data.update({"BlockDeviceMappings": ex_block_device_mapping})
+        if name is not None:
+            data.update({"ImageName": name})
         if description is not None:
             data.update({"Description": description})
-        if vm_id is not None:
-            data.update({"VmId": vm_id})
-        if root_device_name is not None:
-            data.update({"RootDeviceName": root_device_name})
-        if source_region_name is not None:
-            data.update({"SourceRegionName": source_region_name})
-        if file_location is not None:
-            data.update({"FileLocation": file_location})
+        if node.id is not None:
+            data.update({"VmId": node.id})
+        if ex_root_device_name is not None:
+            data.update({"RootDeviceName": ex_root_device_name})
+        if ex_source_region_name is not None:
+            data.update({"SourceRegionName": ex_source_region_name})
+        if ex_file_location is not None:
+            data.update({"FileLocation": ex_file_location})
         data = json.dumps(data)
         action = "CreateImage"
         headers = self._ex_generate_headers(action, data)
@@ -532,7 +605,7 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_images(self, data: str = "{}"):
+    def list_images(self, ex_data: str = "{}"):
         """
         List all images.
 
@@ -540,11 +613,12 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadImages"
-        headers = self._ex_generate_headers(action, data)
+        headers = self._ex_generate_headers(action, ex_data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        images = requests.post(endpoint, data=ex_data, headers=headers).json()["Images"]
+        return self._to_node_images(images)
 
     def get_image(self, image_id: str):
         """
@@ -562,30 +636,46 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        images = requests.post(endpoint, data=data, headers=headers).json()["Images"]
+        return self._to_node_images(images)[0]
 
-    def delete_image(self, image_id: str):
+    def delete_image(self, node_image: NodeImage):
         """
         Delete an image.
 
-        :param      image_id: the ID of the OMI you want to delete (required)
-        :type       image_id: ``str``
+        :param      node_image: the ID of the OMI you want to delete (required)
+        :type       node_image: ``str``
 
         :return: request
         :rtype: ``dict``
         """
         action = "DeleteImage"
-        data = '{"ImageId": "' + image_id + '"}'
+        data = '{"ImageId": "' + node_image.id + '"}'
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
+            return True
+        return False
+
+    def _to_key_pairs(self, key_pairs):
+        return [self._to_key_pair(key_pair) for key_pair in key_pairs]
+
+    def _to_key_pair(self, key_pair):
+        private_key = key_pair["PrivateKey"] if "PrivateKey" in key_pair else ""
+        return KeyPair(
+            name=key_pair["KeypairName"],
+            public_key=None,
+            private_key=private_key,
+            fingerprint=key_pair["KeypairFingerprint"],
+            driver=self)
 
     def create_key_pair(self,
                         name: str,
-                        dry_run: bool = False,
-                        public_key: str = None):
+                        ex_dry_run: bool = False,
+                        ex_public_key: str = None):
         """
         Create a new key pair.
 
@@ -593,31 +683,32 @@ class OutscaleNodeDriver(NodeDriver):
         length of 255 ASCII printable characters.
         :type       name: ``str``
 
-        :param      dry_run: If true, checks whether you have the required
+        :param      ex_dry_run: If true, checks whether you have the required
         permissions to perform the action.
-        :type       dry_run: ``bool``
+        :type       ex_dry_run: ``bool``
 
-        :param      public_key: The public key. It must be base64-encoded.
-        :type       public_key: ``str``
+        :param      ex_public_key: The public key. It must be base64-encoded.
+        :type       ex_public_key: ``str``
 
         :return: the created key pair
         :rtype: ``dict``
         """
         data = {
             "KeypairName": name,
-            "DryRun": dry_run,
+            "DryRun": ex_dry_run,
         }
-        if public_key is not None:
-            data.update({"PublicKey": public_key})
+        if ex_public_key is not None:
+            data.update({"PublicKey": ex_public_key})
         data = json.dumps(data)
         action = "CreateKeypair"
         headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        key_pair = requests.post(endpoint, data=data, headers=headers).json()
+        return self._to_key_pair(key_pair["Keypair"])
 
-    def list_key_pairs(self, data: str = "{}"):
+    def list_key_pairs(self, ex_data: str = "{}"):
         """
         List all key pairs.
 
@@ -625,11 +716,12 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadKeypairs"
-        headers = self._ex_generate_headers(action, data)
+        headers = self._ex_generate_headers(action, ex_data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        key_pairs = requests.post(endpoint, data=ex_data, headers=headers).json()
+        return self._to_key_pairs(key_pairs["Keypairs"])
 
     def get_key_pair(self, name: str):
         """
@@ -648,7 +740,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        key_pair = requests.post(endpoint, data=data, headers=headers).json()["Keypairs"][0]
+        return self._to_key_pair(key_pair)
 
     def delete_key_pair(self, name: str):
         """


[libcloud] 06/10: Flake8 and MyPy compliance for outscale driver

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 6f78c1aafb8bb48e36ee6f90e5e22d691110ea69
Author: Tio Gobin <ti...@outscale.com>
AuthorDate: Tue Aug 25 11:41:57 2020 +0200

    Flake8 and MyPy compliance for outscale driver
---
 libcloud/common/osc.py               |  25 +++---
 libcloud/compute/drivers/outscale.py | 148 +++++++++++++++++++++--------------
 2 files changed, 101 insertions(+), 72 deletions(-)

diff --git a/libcloud/common/osc.py b/libcloud/common/osc.py
index a00d155..475f327 100644
--- a/libcloud/common/osc.py
+++ b/libcloud/common/osc.py
@@ -54,7 +54,7 @@ class OSCRequestSigner(object):
 
 class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
     @staticmethod
-    def sign(key: str, msg: str):
+    def sign(key, msg):
         return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
 
     @staticmethod
@@ -73,7 +73,7 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
                          for k, v in sorted(params.items())])
 
     def get_request_headers(self, service_name: str, region: str, action: str,
-                            data: dict = None):
+                            data: str):
         date = datetime.utcnow()
         host = "{}.{}.outscale.com".format(service_name, region)
         headers = {
@@ -97,10 +97,10 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
         return headers
 
     def _get_authorization_v4_header(self, headers: dict,
+                                     data: str,
                                      dt: datetime,
                                      method: str = 'GET',
-                                     path: str = '/',
-                                     data: dict = None):
+                                     path: str = '/'):
         credentials_scope = self._get_credential_scope(dt=dt)
         signed_headers = self._get_signed_headers(headers=headers)
         signature = self._get_signature(headers=headers, dt=dt,
@@ -115,23 +115,25 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
                }
 
     def _get_signature(self, headers: dict, dt: datetime,
-                       method: str, path: str, data: dict):
+                       method: str, path: str, data: str):
         string_to_sign = self._get_string_to_sign(headers=headers, dt=dt,
                                                   method=method, path=path,
                                                   data=data)
-        signing_key = self._get_key_to_sign_with(self.access_secret, dt)
+        signing_key = self._get_key_to_sign_with(
+            self.access_secret,
+            dt.strftime('%Y%m%d')
+        )
         return hmac.new(signing_key, string_to_sign.encode('utf-8'),
                         hashlib.sha256).hexdigest()
 
-    def _get_key_to_sign_with(self, key: str, dt: datetime):
-        dt = dt.strftime('%Y%m%d')
+    def _get_key_to_sign_with(self, key: str, dt: str):
         k_date = self.sign(('OSC4' + key).encode('utf-8'), dt)
         k_region = self.sign(k_date, self.connection.region_name)
         k_service = self.sign(k_region, self.connection.service_name)
         return self.sign(k_service, 'osc4_request')
 
     def _get_string_to_sign(self, headers: dict, dt: datetime, method: str,
-                            path: str, data: dict):
+                            path: str, data: str):
         canonical_request = self._get_canonical_request(headers=headers,
                                                         method=method,
                                                         path=path,
@@ -147,8 +149,7 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
                          self.connection.service_name,
                          'osc4_request'])
 
-    def _get_canonical_request(self, headers, method, path, data = "{}"):
-        data = data if data else "{}"
+    def _get_canonical_request(self, headers, method, path, data):
         return '\n'.join([
             method,
             path,
@@ -156,4 +157,4 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
             self._get_canonical_headers(headers),
             self._get_signed_headers(headers),
             hashlib.sha256(data.encode('utf-8')).hexdigest()
-        ])
\ No newline at end of file
+        ])
diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index fe1b80b..df43b10 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -114,8 +114,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -153,7 +153,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -252,7 +253,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -290,7 +292,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -387,11 +390,14 @@ class OutscaleNodeDriver(NodeDriver):
         create the VM.
         :type       ex_subnet_id: ``str``
 
-        :param      ex_user_data: Data or script used to add a specific configuration to the VM. It must be base64-encoded.
+        :param      ex_user_data: Data or script used to add a specific
+        configuration to the VM. It must be base64-encoded.
         :type       ex_user_data: ``str``
 
-        :param      ex_vm_initiated_shutdown_behavior: The VM behavior when you stop it. By default or if set to stop, the
-        VM stops. If set to restart, the VM stops then automatically restarts. If set to terminate, the VM stops and is terminated.
+        :param      ex_vm_initiated_shutdown_behavior: The VM behavior when
+        you stop it. By default or if set to stop, the
+        VM stops. If set to restart, the VM stops then automatically restarts.
+        If set to terminate, the VM stops and is terminated.
         create the VM.
         :type       ex_vm_initiated_shutdown_behavior: ``str``
 
@@ -434,7 +440,10 @@ class OutscaleNodeDriver(NodeDriver):
         if ex_user_data is not None:
             data.update({"UserData": ex_user_data})
         if ex_vm_initiated_shutdown_behavior is not None:
-            data.update({"VmInstantiatedShutdownBehavior": ex_vm_initiated_shutdown_behavior})
+            data.update({
+                "VmInstantiatedShutdownBehavior":
+                    ex_vm_initiated_shutdown_behavior
+            })
         if ex_vm_type is not None:
             data.update({"VmType": ex_vm_type})
         if ex_subnet_id is not None:
@@ -445,8 +454,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        vm = requests.post(endpoint, data=data, headers=headers).json()["Vms"][0]
-
+        response = requests.post(endpoint, data=data, headers=headers)
+        vm = response.json()["Vms"][0]
         return self._to_node(vm)
 
     def reboot_node(self, node: Node):
@@ -466,7 +475,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return False
         return False
 
@@ -482,8 +492,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        vms = requests.post(endpoint, data=ex_data, headers=headers).json()["Vms"]
-        return self._to_nodes(vms)
+        vms = requests.post(endpoint, data=ex_data, headers=headers)
+        return self._to_nodes(vms.json()["Vms"])
 
     def destroy_node(self, node: Node):
         """
@@ -501,7 +511,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -587,8 +598,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        image = requests.post(endpoint, data=data, headers=headers).json()["Image"]
-        return self._to_node_images(image)
+        image = requests.post(endpoint, data=data, headers=headers).json()
+        return self._to_node_image(image["Image"])
 
     def list_images(self, ex_data: str = "{}"):
         """
@@ -602,8 +613,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        images = requests.post(endpoint, data=ex_data, headers=headers).json()["Images"]
-        return self._to_node_images(images)
+        images = requests.post(endpoint, data=ex_data, headers=headers).json()
+        return self._to_node_images(images["Images"])
 
     def get_image(self, image_id: str):
         """
@@ -621,8 +632,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        images = requests.post(endpoint, data=data, headers=headers).json()["Images"]
-        return self._to_node_image(images)
+        images = requests.post(endpoint, data=data, headers=headers).json()
+        return self._to_node_image(images["Images"])
 
     def delete_image(self, node_image: NodeImage):
         """
@@ -640,7 +651,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -648,7 +660,9 @@ class OutscaleNodeDriver(NodeDriver):
         return [self._to_key_pair(key_pair) for key_pair in key_pairs]
 
     def _to_key_pair(self, key_pair):
-        private_key = key_pair["PrivateKey"] if "PrivateKey" in key_pair else ""
+        private_key = ""
+        if "PrivateKey" in key_pair:
+            private_key = key_pair["PrivateKey"]
         return KeyPair(
             name=key_pair["KeypairName"],
             public_key="",
@@ -704,8 +718,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        key_pairs = requests.post(endpoint, data=ex_data, headers=headers).json()
-        return self._to_key_pairs(key_pairs["Keypairs"])
+        key_pairs = requests.post(endpoint, data=ex_data, headers=headers)
+        return self._to_key_pairs(key_pairs.json()["Keypairs"])
 
     def get_key_pair(self, name: str):
         """
@@ -724,14 +738,15 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        key_pair = requests.post(endpoint, data=data, headers=headers).json()["Keypairs"][0]
-        return self._to_key_pair(key_pair)
+        key_pair = requests.post(endpoint, data=data, headers=headers).json()
+        return self._to_key_pair(key_pair["Keypairs"][0])
 
     def delete_key_pair(self, key_pair: KeyPair):
         """
         Delete an image.
 
-        :param      key_pair: the name of the keypair you want to delete (required)
+        :param      key_pair: the name of the keypair
+        you want to delete (required)
         :type       key_pair: ``KeyPair``
 
         :return: boolean
@@ -743,7 +758,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -814,8 +830,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        snapshot = requests.post(endpoint, data=data, headers=headers).json()["Volume"]
-        return self._to_snapshot(snapshot)
+        snapshot = requests.post(endpoint, data=data, headers=headers)
+        return self._to_snapshot(snapshot.json()["Volume"])
 
     def list_snapshots(self, ex_data: str = "{}"):
         """
@@ -829,9 +845,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        snapshots = requests.post(endpoint, data=ex_data, headers=headers).json()
-
-        return self._to_snapshots(snapshots)
+        snapshots = requests.post(endpoint, data=ex_data, headers=headers)
+        return self._to_snapshots(snapshots.json()["Snapshots"])
 
     def destroy_volume_snapshot(self, snapshot: VolumeSnapshot):
         """
@@ -839,10 +854,10 @@ class OutscaleNodeDriver(NodeDriver):
 
         :param      snapshot: the ID of the snapshot
                     you want to delete (required)
-        :type       snapshot: ``str``
+        :type       snapshot: ``VolumeSnapshot``
 
         :return: request
-        :rtype: ``dict``
+        :rtype: ``bool``
         """
         action = "DeleteSnapshot"
         data = '{"SnapshotId": "' + snapshot.id + '"}'
@@ -850,7 +865,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -914,8 +930,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        volume = requests.post(endpoint, data=data, headers=headers).json()["Volume"]
-        return self._to_volume(volume)
+        volume = requests.post(endpoint, data=data, headers=headers)
+        return self._to_volume(volume.json()["Volume"])
 
     def list_volumes(self, ex_data: str = "{}"):
         """
@@ -929,8 +945,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        volumes = requests.post(endpoint, data=ex_data, headers=headers).json()["Volumes"]
-        return self._to_volumes(volumes)
+        volumes = requests.post(endpoint, data=ex_data, headers=headers)
+        return self._to_volumes(volumes.json()["Volumes"])
 
     def destroy_volume(self, volume: StorageVolume):
         """
@@ -938,10 +954,10 @@ class OutscaleNodeDriver(NodeDriver):
 
         :param      volume: the ID of the volume
                     you want to delete (required)
-        :type       volume: ``str``
+        :type       volume: ``StorageVolume``
 
         :return: request
-        :rtype: ``dict``
+        :rtype: ``bool``
         """
         action = "DeleteVolume"
         data = '{"VolumeId": "' + volume.id + '"}'
@@ -949,21 +965,27 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
-    def attach_volume(self, node: Node, volume: StorageVolume, device: str = None):
+    def attach_volume(
+        self,
+        node: Node,
+        volume: StorageVolume,
+        device: str = None
+    ):
         """
         Attach a volume.
 
         :param      node: the ID of the VM you want
                     to attach the volume to (required)
-        :type       node: ``str``
+        :type       node: ``Node``
 
         :param      volume: the ID of the volume
                     you want to attach (required)
-        :type       volume: ``str``
+        :type       volume: ``StorageVolume``
 
         :param      device: the name of the device (required)
         :type       device: ``str``
@@ -981,7 +1003,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -1017,7 +1040,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+        response = requests.post(endpoint, data=data, headers=headers)
+        if response.status_code == 200:
             return True
         return False
 
@@ -1029,18 +1053,22 @@ class OutscaleNodeDriver(NodeDriver):
             action
         )
 
-    def _ex_generate_headers(self, action: str, data: dict):
-        return self.signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+    def _ex_generate_headers(self, action: str, data: str):
+        return self.signer.get_request_headers(
+            action=action,
+            data=data,
+            service_name=self.service_name,
+            region=self.region
+        )
 
     def _to_location(self, region):
-        return NodeLocation(id="",
-                    name=region["RegionName"],
-                    country="",
-                    driver=self,
-                    extra=region)
+        return NodeLocation(
+            id="",
+            name=region["RegionName"],
+            country="",
+            driver=self,
+            extra=region
+        )
 
     def _to_locations(self, regions: list):
         return [self._to_location(region) for region in regions]
@@ -1053,7 +1081,7 @@ class OutscaleNodeDriver(NodeDriver):
         return VolumeSnapshot(
             id=snapshot["SnapshotId"],
             name=name,
-            size=snapshot["Size"],
+            size=snapshot["VolumeSize"],
             driver=self,
             state=snapshot["State"],
             created=None,


[libcloud] 09/10: Update docstrings.

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ea0df48ba40ab2a89008cad80a662404fcf145a3
Author: Tomaz Muraus <to...@tomaz.me>
AuthorDate: Sun Aug 30 16:43:21 2020 +0200

    Update docstrings.
---
 libcloud/compute/drivers/outscale.py | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index 5fcfa6a..7d42cbf 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -75,6 +75,7 @@ class OutscaleNodeDriver(NodeDriver):
     def list_locations(self, ex_dry_run: bool = False):
         """
         Lists available regions details.
+
         :param      ex_dry_run: If true, checks whether you have the required
         permissions to perform the action.
         :type       ex_dry_run: ``bool``
@@ -108,7 +109,7 @@ class OutscaleNodeDriver(NodeDriver):
                             public_ip: str = None,
                             public_ip_id: str = None):
         """
-        Delete instances.
+        Delete public ip.
 
         :param      dry_run: If true, checks whether you have the required
         permissions to perform the action.
@@ -139,7 +140,7 @@ class OutscaleNodeDriver(NodeDriver):
 
     def ex_list_public_ips(self, data: str = "{}"):
         """
-        List all nodes.
+        List all public IPs.
 
         :param      data: json stringify following the outscale api
         documentation for filter
@@ -175,7 +176,7 @@ class OutscaleNodeDriver(NodeDriver):
                             public_ip_id: str = None,
                             ):
         """
-        Attach a volume.
+        Attach public ip to a node.
 
         :param      allow_relink: If true, allows the EIP to be associated
         with the VM or NIC that you specify even if
@@ -229,7 +230,7 @@ class OutscaleNodeDriver(NodeDriver):
                             link_public_ip_id: str = None,
                             dry_run: bool = False):
         """
-        Detach a volume.
+        Detach public ip from a node.
 
         :param      public_ip: (Required in a Net) The ID representing the
         association of the EIP with the VM or the NIC
@@ -415,7 +416,7 @@ class OutscaleNodeDriver(NodeDriver):
 
     def reboot_node(self, node: Node):
         """
-        Reboot instances.
+        Reboot instance.
 
         :param      node: the ID(s) of the VM(s)
                     you want to reboot (required)
@@ -442,7 +443,7 @@ class OutscaleNodeDriver(NodeDriver):
 
     def destroy_node(self, node: Node):
         """
-        Delete instances.
+        Delete instance.
 
         :param      node: one or more IDs of VMs (required)
         :type       node: ``Node``
@@ -640,7 +641,7 @@ class OutscaleNodeDriver(NodeDriver):
 
     def delete_key_pair(self, key_pair: KeyPair):
         """
-        Delete an image.
+        Delete a key pair.
 
         :param      key_pair: the name of the keypair
         you want to delete (required)
@@ -666,7 +667,7 @@ class OutscaleNodeDriver(NodeDriver):
         volume: StorageVolume = None
     ):
         """
-        Create a new snapshot.
+        Create a new volume snapshot.
 
         :param      ex_description: a description for the new OMI
         :type       ex_description: ``str``
@@ -723,7 +724,7 @@ class OutscaleNodeDriver(NodeDriver):
 
     def list_snapshots(self, ex_data: str = "{}"):
         """
-        List all snapshots.
+        List all volume snapshots.
 
         :return: snapshots
         :rtype: ``dict``
@@ -734,7 +735,7 @@ class OutscaleNodeDriver(NodeDriver):
 
     def destroy_volume_snapshot(self, snapshot: VolumeSnapshot):
         """
-        Delete a snapshot.
+        Delete a volume snapshot.
 
         :param      snapshot: the ID of the snapshot
                     you want to delete (required)
@@ -842,7 +843,7 @@ class OutscaleNodeDriver(NodeDriver):
         device: str = None
     ):
         """
-        Attach a volume.
+        Attach a volume to a node.
 
         :param      node: the ID of the VM you want
                     to attach the volume to (required)
@@ -873,7 +874,7 @@ class OutscaleNodeDriver(NodeDriver):
                       ex_dry_run: bool = False,
                       ex_force_unlink: bool = False):
         """
-        Detach a volume.
+        Detach a volume from a node.
 
         :param      volume: the ID of the volume you want to detach
         (required)


[libcloud] 01/10: type annotation for MyPy, changed signer creation and usage

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 64a0d90273a80cfc386642e5bcf4658f1c4b48ae
Author: Tio Gobin <ti...@outscale.com>
AuthorDate: Fri Aug 14 18:39:57 2020 +0200

    type annotation for MyPy, changed signer creation and usage
---
 libcloud/common/osc.py               |  36 ++--
 libcloud/compute/drivers/outscale.py | 408 +++++++++++------------------------
 2 files changed, 144 insertions(+), 300 deletions(-)

diff --git a/libcloud/common/osc.py b/libcloud/common/osc.py
index c030288..a00d155 100644
--- a/libcloud/common/osc.py
+++ b/libcloud/common/osc.py
@@ -29,7 +29,10 @@ class OSCRequestSigner(object):
     Class which handles signing the outgoing AWS requests.
     """
 
-    def __init__(self, access_key, access_secret, version, connection):
+    def __init__(self, access_key: str,
+                 access_secret: str,
+                 version: str,
+                 connection):
         """
         :param access_key: Access key.
         :type access_key: ``str``
@@ -51,26 +54,26 @@ class OSCRequestSigner(object):
 
 class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
     @staticmethod
-    def sign(key, msg):
+    def sign(key: str, msg: str):
         return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
 
     @staticmethod
-    def _get_signed_headers(headers):
+    def _get_signed_headers(headers: dict):
         return ';'.join([k.lower() for k in sorted(headers.keys())])
 
     @staticmethod
-    def _get_canonical_headers(headers):
+    def _get_canonical_headers(headers: dict):
         return '\n'.join([':'.join([k.lower(), str(v).strip()])
                           for k, v in sorted(headers.items())]) + '\n'
 
     @staticmethod
-    def _get_request_params(params):
+    def _get_request_params(params: dict):
         return '&'.join(["%s=%s" %
                          (urlquote(k, safe=''), urlquote(str(v), safe='~'))
                          for k, v in sorted(params.items())])
 
-    def get_request_headers(self, service_name, region, action,
-                            data=None):
+    def get_request_headers(self, service_name: str, region: str, action: str,
+                            data: dict = None):
         date = datetime.utcnow()
         host = "{}.{}.outscale.com".format(service_name, region)
         headers = {
@@ -93,8 +96,11 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
         headers.update({'Authorization': sig})
         return headers
 
-    def _get_authorization_v4_header(self, headers, dt, method='GET',
-                                     path='/', data=None):
+    def _get_authorization_v4_header(self, headers: dict,
+                                     dt: datetime,
+                                     method: str = 'GET',
+                                     path: str = '/',
+                                     data: dict = None):
         credentials_scope = self._get_credential_scope(dt=dt)
         signed_headers = self._get_signed_headers(headers=headers)
         signature = self._get_signature(headers=headers, dt=dt,
@@ -108,7 +114,8 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
                    's': signature
                }
 
-    def _get_signature(self, headers, dt, method, path, data):
+    def _get_signature(self, headers: dict, dt: datetime,
+                       method: str, path: str, data: dict):
         string_to_sign = self._get_string_to_sign(headers=headers, dt=dt,
                                                   method=method, path=path,
                                                   data=data)
@@ -116,14 +123,15 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
         return hmac.new(signing_key, string_to_sign.encode('utf-8'),
                         hashlib.sha256).hexdigest()
 
-    def _get_key_to_sign_with(self, key, dt):
+    def _get_key_to_sign_with(self, key: str, dt: datetime):
         dt = dt.strftime('%Y%m%d')
         k_date = self.sign(('OSC4' + key).encode('utf-8'), dt)
         k_region = self.sign(k_date, self.connection.region_name)
         k_service = self.sign(k_region, self.connection.service_name)
         return self.sign(k_service, 'osc4_request')
 
-    def _get_string_to_sign(self, headers, dt, method, path, data):
+    def _get_string_to_sign(self, headers: dict, dt: datetime, method: str,
+                            path: str, data: dict):
         canonical_request = self._get_canonical_request(headers=headers,
                                                         method=method,
                                                         path=path,
@@ -139,7 +147,7 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
                          self.connection.service_name,
                          'osc4_request'])
 
-    def _get_canonical_request(self, headers, method, path, data="{}"):
+    def _get_canonical_request(self, headers, method, path, data = "{}"):
         data = data if data else "{}"
         return '\n'.join([
             method,
@@ -148,4 +156,4 @@ class OSCRequestSignerAlgorithmV4(OSCRequestSigner):
             self._get_canonical_headers(headers),
             self._get_signed_headers(headers),
             hashlib.sha256(data.encode('utf-8')).hexdigest()
-        ])
+        ])
\ No newline at end of file
diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index 370fbb4..5e8326b 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -36,11 +36,11 @@ class OutscaleNodeDriver(NodeDriver):
     website = 'http://www.outscale.com'
 
     def __init__(self,
-                 key=None,
-                 secret=None,
-                 region='eu-west-2',
-                 service='api',
-                 version='latest'
+                 key: str = None,
+                 secret: str = None,
+                 region: str = 'eu-west-2',
+                 service: str = 'api',
+                 version: str = 'latest'
                  ):
         self.key = key
         self.secret = secret
@@ -50,8 +50,12 @@ class OutscaleNodeDriver(NodeDriver):
         self.connection.service_name = service
         self.service_name = service
         self.version = version
+        self.signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
+                                             access_secret=self.secret,
+                                             version=self.version,
+                                             connection=self.connection)
 
-    def list_locations(self, dry_run=False):
+    def list_locations(self, dry_run: bool = False):
         """
         Lists available regions details.
 
@@ -73,7 +77,7 @@ class OutscaleNodeDriver(NodeDriver):
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def create_public_ip(self, dry_run=False):
+    def create_public_ip(self, dry_run: bool = False):
         """
         Create a new public ip.
 
@@ -86,22 +90,15 @@ class OutscaleNodeDriver(NodeDriver):
             """
         action = "CreatePublicIp"
         data = json.dumps({"DryRun": dry_run})
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def delete_public_ip(self, dry_run=False,
-                         public_ip=None,
-                         public_ip_id=None):
+    def delete_public_ip(self, dry_run: bool = False,
+                         public_ip: str = None,
+                         public_ip_id: str = None):
         """
         Delete instances.
 
@@ -128,20 +125,13 @@ class OutscaleNodeDriver(NodeDriver):
         if public_ip_id is not None:
             data.update({"PublicIpId": public_ip_id})
         data = json.dumps(data)
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_public_ips(self, data="{}"):
+    def list_public_ips(self, data: str = "{}"):
         """
         List all nodes.
 
@@ -153,20 +143,13 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadPublicIps"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_public_ip_ranges(self, dry_run=False):
+    def list_public_ip_ranges(self, dry_run: bool = False):
         """
         Lists available regions details.
 
@@ -179,26 +162,19 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "ReadPublicIpRanges"
         data = json.dumps({"DryRun": dry_run})
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
     def attach_public_ip(self,
-                         allow_relink=None,
-                         dry_run=False,
-                         nic_id=None,
-                         vm_id=None,
-                         public_ip=None,
-                         public_ip_id=None,
+                         allow_relink: bool = None,
+                         dry_run: bool = False,
+                         nic_id: str = None,
+                         vm_id: str = None,
+                         public_ip: str = None,
+                         public_ip_id: str = None,
                          ):
         """
         Attach a volume.
@@ -246,22 +222,15 @@ class OutscaleNodeDriver(NodeDriver):
         if allow_relink is not None:
             data.update({"AllowRelink": allow_relink})
         data = json.dumps(data)
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def detach_public_ip(self, public_ip=None,
-                         link_public_ip_id=None,
-                         dry_run=False):
+    def detach_public_ip(self, public_ip: str = None,
+                         link_public_ip_id: str = None,
+                         dry_run: bool = False):
         """
         Detach a volume.
 
@@ -288,37 +257,30 @@ class OutscaleNodeDriver(NodeDriver):
         if link_public_ip_id is not None:
             data.update({"LinkPublicIpId": link_public_ip_id})
         data = json.dumps(data)
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
     def create_node(self,
-                    image_id,
-                    dry_run=False,
-                    block_device_mapping=None,
-                    boot_on_creation=True,
-                    bsu_optimized=True,
-                    client_token=None,
-                    deletion_protection=False,
-                    keypair_name=None,
-                    max_vms_count=None,
-                    min_vms_count=None,
-                    nics=None,
-                    performance=None,
-                    placement=None,
-                    private_ips=None,
-                    security_group_ids=None,
-                    security_groups=None,
-                    subnet_id=None,
+                    image_id: str,
+                    dry_run: bool = False,
+                    block_device_mapping: dict = None,
+                    boot_on_creation: bool = True,
+                    bsu_optimized: bool = True,
+                    client_token: str = None,
+                    deletion_protection: bool = False,
+                    keypair_name: str = None,
+                    max_vms_count: int = None,
+                    min_vms_count: int = None,
+                    nics: dict = None,
+                    performance: str = None,
+                    placement: dict = None,
+                    private_ips: [str] = None,
+                    security_group_ids: [str] = None,
+                    security_groups: [str] = None,
+                    subnet_id: str = None,
                     ):
         """
         Create a new instance.
@@ -428,20 +390,13 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"SubnetId": subnet_id})
         action = "CreateVms"
         data = json.dumps(data)
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def reboot_node(self, node_ids):
+    def reboot_node(self, node_ids: [str]):
         """
         Reboot instances.
 
@@ -454,20 +409,13 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "RebootVms"
         data = json.dumps({"VmIds": node_ids})
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_nodes(self, data="{}"):
+    def list_nodes(self, data: str = "{}"):
         """
         List all nodes.
 
@@ -475,20 +423,13 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadVms"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def delete_node(self, node_ids):
+    def delete_node(self, node_ids: [str]):
         """
         Delete instances.
 
@@ -500,14 +441,7 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteVms"
         data = json.dumps({"VmIds": node_ids})
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
@@ -515,16 +449,16 @@ class OutscaleNodeDriver(NodeDriver):
 
     def create_image(
         self,
-        architecture=None,
-        vm_id=None,
-        image_name=None,
-        description=None,
-        block_device_mapping=None,
-        no_reboot=False,
-        root_device_name=None,
-        dry_run=False,
-        source_region_name=None,
-        file_location=None
+        architecture: str = None,
+        vm_id: str = None,
+        image_name: str = None,
+        description: str = None,
+        block_device_mapping: dict = None,
+        no_reboot: bool = False,
+        root_device_name: str = None,
+        dry_run: bool = False,
+        source_region_name: str = None,
+        file_location: str = None
     ):
         """
         Create a new image.
@@ -592,20 +526,13 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"FileLocation": file_location})
         data = json.dumps(data)
         action = "CreateImage"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_images(self, data="{}"):
+    def list_images(self, data: str = "{}"):
         """
         List all images.
 
@@ -613,20 +540,13 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadImages"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def get_image(self, image_id):
+    def get_image(self, image_id: str):
         """
         Get a specific image.
 
@@ -638,20 +558,13 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "ReadImages"
         data = '{"Filters": {"ImageIds": ["' + image_id + '"]}}'
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def delete_image(self, image_id):
+    def delete_image(self, image_id: str):
         """
         Delete an image.
 
@@ -663,20 +576,16 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteImage"
         data = '{"ImageId": "' + image_id + '"}'
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def create_key_pair(self, name, dry_run=False, public_key=None):
+    def create_key_pair(self,
+                        name: str,
+                        dry_run: bool = False,
+                        public_key: str = None):
         """
         Create a new key pair.
 
@@ -702,20 +611,13 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"PublicKey": public_key})
         data = json.dumps(data)
         action = "CreateKeypair"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_key_pairs(self, data="{}"):
+    def list_key_pairs(self, data: str = "{}"):
         """
         List all key pairs.
 
@@ -723,20 +625,13 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadKeypairs"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def get_key_pair(self, name):
+    def get_key_pair(self, name: str):
         """
         Get a specific key pair.
 
@@ -749,20 +644,13 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "ReadKeypairs"
         data = '{"Filters": {"KeypairNames" : ["' + name + '"]}}'
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def delete_key_pair(self, name):
+    def delete_key_pair(self, name: str):
         """
         Delete an image.
 
@@ -774,27 +662,20 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteKeypair"
         data = '{"KeypairName": "' + name + '"}'
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
     def create_snapshot(self,
-                        description=None,
-                        dry_run=False,
-                        file_location=None,
-                        snapshot_size=None,
-                        source_region_name=None,
-                        source_snapshot_id=None,
-                        volume_id=None,
+                        description: str = None,
+                        dry_run: bool = False,
+                        file_location: str = None,
+                        snapshot_size: int = None,
+                        source_region_name: str = None,
+                        source_snapshot_id: str = None,
+                        volume_id: str = None,
                         ):
         """
         Create a new snapshot.
@@ -850,20 +731,13 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"VolumeId": volume_id})
         data = json.dumps(data)
         action = "CreateSnapshot"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_snapshots(self, data="{}"):
+    def list_snapshots(self, data: str = "{}"):
         """
         List all snapshots.
 
@@ -871,20 +745,13 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadSnapshots"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def delete_snapshot(self, snapshot_id):
+    def delete_snapshot(self, snapshot_id: str):
         """
         Delete a snapshot.
 
@@ -897,14 +764,7 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteSnapshot"
         data = '{"SnapshotId": "' + snapshot_id + '"}'
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
@@ -912,12 +772,12 @@ class OutscaleNodeDriver(NodeDriver):
 
     def create_volume(
         self,
-        subregion_name,
-        dry_run=False,
-        iops=None,
-        size=None,
-        snapshot_id=None,
-        volume_type=None,
+        subregion_name: str,
+        dry_run: bool = False,
+        iops: int = None,
+        size: int = None,
+        snapshot_id: str = None,
+        volume_type: str = None,
     ):
         """
         Create a new volume.
@@ -965,20 +825,14 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"VolumeType": volume_type})
         data = json.dumps(data)
         action = "CreateVolume"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
+
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def list_volumes(self, data="{}"):
+    def list_volumes(self, data: str = "{}"):
         """
         List all volumes.
 
@@ -986,20 +840,13 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadVolumes"
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def delete_volume(self, volume_id):
+    def delete_volume(self, volume_id: str):
         """
         Delete a volume.
 
@@ -1012,20 +859,13 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteVolume"
         data = '{"VolumeId": "' + volume_id + '"}'
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def attach_volume(self, node_id, volume_id, device_name):
+    def attach_volume(self, node_id: str, volume_id: str, device_name: str):
         """
         Attach a volume.
 
@@ -1049,20 +889,16 @@ class OutscaleNodeDriver(NodeDriver):
             "VolumeId": volume_id,
             "DeviceName": device_name
         })
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
-    def detach_volume(self, volume_id, dry_run=False, force_unlink=False):
+    def detach_volume(self,
+                      volume_id: str,
+                      dry_run: bool = False,
+                      force_unlink: bool = False):
         """
         Detach a volume.
 
@@ -1087,23 +923,23 @@ class OutscaleNodeDriver(NodeDriver):
         if force_unlink is not None:
             data.update({"ForceUnlink": force_unlink})
         data = json.dumps(data)
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
+        headers = self._ex_generate_headers(action, data)
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
         return requests.post(endpoint, data=data, headers=headers)
 
     @staticmethod
-    def _get_outscale_endpoint(region, version, action):
+    def _get_outscale_endpoint(region: str, version: str, action: str):
         return "https://api.{}.outscale.com/api/{}/{}".format(
             region,
             version,
             action
         )
+
+    def _ex_generate_headers(self, action: str, data: dict):
+        return self.signer.get_request_headers(action=action,
+                                             data=data,
+                                             service_name=self.service_name,
+                                             region=self.region)
+


[libcloud] 07/10: Reduced duplication in outscale driver

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 48fa2fa026b24530709a06a14567510c0dd362c8
Author: Tio Gobin <ti...@outscale.com>
AuthorDate: Tue Aug 25 14:42:12 2020 +0200

    Reduced duplication in outscale driver
---
 libcloud/compute/drivers/outscale.py | 242 +++++++++--------------------------
 1 file changed, 59 insertions(+), 183 deletions(-)

diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index df43b10..5fcfa6a 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -83,19 +83,8 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "ReadRegions"
         data = json.dumps({"DryRun": ex_dry_run})
-        signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-        headers = signer.get_request_headers(action=action,
-                                             data=data,
-                                             service_name=self.service_name,
-                                             region=self.region)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        regions = requests.post(endpoint, data=data, headers=headers).json()
-        return self._to_locations(regions["Regions"])
+        response = self._call_api(action, data)
+        return self._to_locations(response.json()["Regions"])
 
     def ex_create_public_ip(self, dry_run: bool = False):
         """
@@ -110,12 +99,7 @@ class OutscaleNodeDriver(NodeDriver):
             """
         action = "CreatePublicIp"
         data = json.dumps({"DryRun": dry_run})
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -149,12 +133,7 @@ class OutscaleNodeDriver(NodeDriver):
         if public_ip_id is not None:
             data.update({"PublicIpId": public_ip_id})
         data = json.dumps(data)
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -170,11 +149,7 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadPublicIps"
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        return requests.post(endpoint, data=data, headers=headers)
+        return self._call_api(action, data)
 
     def ex_list_public_ip_ranges(self, dry_run: bool = False):
         """
@@ -189,11 +164,7 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "ReadPublicIpRanges"
         data = json.dumps({"DryRun": dry_run})
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        return requests.post(endpoint, data=data, headers=headers)
+        return self._call_api(action, data)
 
     def ex_attach_public_ip(self,
                             allow_relink: bool = None,
@@ -249,12 +220,7 @@ class OutscaleNodeDriver(NodeDriver):
         if allow_relink is not None:
             data.update({"AllowRelink": allow_relink})
         data = json.dumps(data)
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -288,12 +254,7 @@ class OutscaleNodeDriver(NodeDriver):
         if link_public_ip_id is not None:
             data.update({"LinkPublicIpId": link_public_ip_id})
         data = json.dumps(data)
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -450,13 +411,7 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"SubnetId": ex_subnet_id})
         action = "CreateVms"
         data = json.dumps(data)
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        vm = response.json()["Vms"][0]
-        return self._to_node(vm)
+        return self._to_node(self._call_api(action, data).json()["Vms"][0])
 
     def reboot_node(self, node: Node):
         """
@@ -471,12 +426,7 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "RebootVms"
         data = json.dumps({"VmIds": node.id})
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return False
         return False
 
@@ -488,12 +438,7 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadVms"
-        headers = self._ex_generate_headers(action, ex_data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        vms = requests.post(endpoint, data=ex_data, headers=headers)
-        return self._to_nodes(vms.json()["Vms"])
+        return self._to_nodes(self._call_api(action, ex_data).json()["Vms"])
 
     def destroy_node(self, node: Node):
         """
@@ -507,12 +452,7 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteVms"
         data = json.dumps({"VmIds": node.id})
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -594,12 +534,8 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"FileLocation": ex_file_location})
         data = json.dumps(data)
         action = "CreateImage"
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        image = requests.post(endpoint, data=data, headers=headers).json()
-        return self._to_node_image(image["Image"])
+        response = self._call_api(action, data)
+        return self._to_node_image(response.json()["Image"])
 
     def list_images(self, ex_data: str = "{}"):
         """
@@ -609,12 +545,8 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadImages"
-        headers = self._ex_generate_headers(action, ex_data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        images = requests.post(endpoint, data=ex_data, headers=headers).json()
-        return self._to_node_images(images["Images"])
+        response = self._call_api(action, ex_data)
+        return self._to_node_images(response.json()["Images"])
 
     def get_image(self, image_id: str):
         """
@@ -628,12 +560,8 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "ReadImages"
         data = '{"Filters": {"ImageIds": ["' + image_id + '"]}}'
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        images = requests.post(endpoint, data=data, headers=headers).json()
-        return self._to_node_image(images["Images"])
+        response = self._call_api(action, data)
+        return self._to_node_image(response.json()["Images"][0])
 
     def delete_image(self, node_image: NodeImage):
         """
@@ -647,29 +575,10 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteImage"
         data = '{"ImageId": "' + node_image.id + '"}'
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
-    def _to_key_pairs(self, key_pairs):
-        return [self._to_key_pair(key_pair) for key_pair in key_pairs]
-
-    def _to_key_pair(self, key_pair):
-        private_key = ""
-        if "PrivateKey" in key_pair:
-            private_key = key_pair["PrivateKey"]
-        return KeyPair(
-            name=key_pair["KeypairName"],
-            public_key="",
-            private_key=private_key,
-            fingerprint=key_pair["KeypairFingerprint"],
-            driver=self)
-
     def create_key_pair(self,
                         name: str,
                         ex_dry_run: bool = False,
@@ -699,12 +608,8 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"PublicKey": ex_public_key})
         data = json.dumps(data)
         action = "CreateKeypair"
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        key_pair = requests.post(endpoint, data=data, headers=headers).json()
-        return self._to_key_pair(key_pair["Keypair"])
+        response = self._call_api(action, data)
+        return self._to_key_pair(response.json()["Keypair"])
 
     def list_key_pairs(self, ex_data: str = "{}"):
         """
@@ -714,12 +619,8 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadKeypairs"
-        headers = self._ex_generate_headers(action, ex_data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        key_pairs = requests.post(endpoint, data=ex_data, headers=headers)
-        return self._to_key_pairs(key_pairs.json()["Keypairs"])
+        response = self._call_api(action, ex_data)
+        return self._to_key_pairs(response.json()["Keypairs"])
 
     def get_key_pair(self, name: str):
         """
@@ -734,12 +635,8 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "ReadKeypairs"
         data = '{"Filters": {"KeypairNames" : ["' + name + '"]}}'
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        key_pair = requests.post(endpoint, data=data, headers=headers).json()
-        return self._to_key_pair(key_pair["Keypairs"][0])
+        response = self._call_api(action, data)
+        return self._to_key_pair(response.json()["Keypairs"][0])
 
     def delete_key_pair(self, key_pair: KeyPair):
         """
@@ -754,12 +651,7 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteKeypair"
         data = '{"KeypairName": "' + key_pair.name + '"}'
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -826,12 +718,8 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"VolumeId": volume.id})
         data = json.dumps(data)
         action = "CreateSnapshot"
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        snapshot = requests.post(endpoint, data=data, headers=headers)
-        return self._to_snapshot(snapshot.json()["Volume"])
+        response = self._call_api(action, data)
+        return self._to_snapshot(response.json()["Volume"])
 
     def list_snapshots(self, ex_data: str = "{}"):
         """
@@ -841,12 +729,8 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadSnapshots"
-        headers = self._ex_generate_headers(action, ex_data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        snapshots = requests.post(endpoint, data=ex_data, headers=headers)
-        return self._to_snapshots(snapshots.json()["Snapshots"])
+        response = self._call_api(action, ex_data)
+        return self._to_snapshots(response.json()["Snapshots"])
 
     def destroy_volume_snapshot(self, snapshot: VolumeSnapshot):
         """
@@ -861,12 +745,7 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteSnapshot"
         data = '{"SnapshotId": "' + snapshot.id + '"}'
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -925,13 +804,8 @@ class OutscaleNodeDriver(NodeDriver):
             data.update({"VolumeType": ex_volume_type})
         data = json.dumps(data)
         action = "CreateVolume"
-        headers = self._ex_generate_headers(action, data)
-
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        volume = requests.post(endpoint, data=data, headers=headers)
-        return self._to_volume(volume.json()["Volume"])
+        response = self._call_api(action, data)
+        return self._to_volume(response.json()["Volume"])
 
     def list_volumes(self, ex_data: str = "{}"):
         """
@@ -941,12 +815,8 @@ class OutscaleNodeDriver(NodeDriver):
         :rtype: ``dict``
         """
         action = "ReadVolumes"
-        headers = self._ex_generate_headers(action, ex_data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        volumes = requests.post(endpoint, data=ex_data, headers=headers)
-        return self._to_volumes(volumes.json()["Volumes"])
+        response = self._call_api(action, ex_data)
+        return self._to_volumes(response.json()["Volumes"])
 
     def destroy_volume(self, volume: StorageVolume):
         """
@@ -961,12 +831,7 @@ class OutscaleNodeDriver(NodeDriver):
         """
         action = "DeleteVolume"
         data = '{"VolumeId": "' + volume.id + '"}'
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -999,12 +864,7 @@ class OutscaleNodeDriver(NodeDriver):
             "VolumeId": volume.id,
             "DeviceName": device
         })
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -1036,12 +896,7 @@ class OutscaleNodeDriver(NodeDriver):
         if ex_force_unlink is not None:
             data.update({"ForceUnlink": ex_force_unlink})
         data = json.dumps(data)
-        headers = self._ex_generate_headers(action, data)
-        endpoint = self._get_outscale_endpoint(self.region,
-                                               self.version,
-                                               action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if self._call_api(action, data).status_code == 200:
             return True
         return False
 
@@ -1053,6 +908,13 @@ class OutscaleNodeDriver(NodeDriver):
             action
         )
 
+    def _call_api(self, action: str, data: str):
+        headers = self._ex_generate_headers(action, data)
+        endpoint = self._get_outscale_endpoint(self.region,
+                                               self.version,
+                                               action)
+        return requests.post(endpoint, data=data, headers=headers)
+
     def _ex_generate_headers(self, action: str, data: str):
         return self.signer.get_request_headers(
             action=action,
@@ -1140,3 +1002,17 @@ class OutscaleNodeDriver(NodeDriver):
 
     def _to_node_images(self, node_images: list):
         return [self._to_node_image(node_image) for node_image in node_images]
+
+    def _to_key_pairs(self, key_pairs):
+        return [self._to_key_pair(key_pair) for key_pair in key_pairs]
+
+    def _to_key_pair(self, key_pair):
+        private_key = ""
+        if "PrivateKey" in key_pair:
+            private_key = key_pair["PrivateKey"]
+        return KeyPair(
+            name=key_pair["KeypairName"],
+            public_key="",
+            private_key=private_key,
+            fingerprint=key_pair["KeypairFingerprint"],
+            driver=self)


[libcloud] 04/10: Changed some utils function and some return value for more compliance with libcloud standard provider methods

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit fe5e2363d2b80ab34a8a56ed25ddefaf5998008a
Author: Tio Gobin <ti...@epitech.eu>
AuthorDate: Sun Aug 23 22:02:49 2020 +0200

    Changed some utils function and some return value for more compliance with libcloud standard provider methods
---
 libcloud/compute/drivers/outscale.py | 122 +++++++++++++++++++----------------
 1 file changed, 66 insertions(+), 56 deletions(-)

diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index 58bd08f..5e57ca3 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -52,11 +52,12 @@ class OutscaleNodeDriver(NodeDriver):
         self.connection.service_name = service
         self.service_name = service
         self.version = version
-        self.signer = OSCRequestSignerAlgorithmV4(access_key=self.key,
-                                             access_secret=self.secret,
-                                             version=self.version,
-                                             connection=self.connection)
-
+        self.signer = OSCRequestSignerAlgorithmV4(
+            access_key=self.key,
+            access_secret=self.secret,
+            version=self.version,
+            connection=self.connection
+        )
         self.NODE_STATE = {
             'pending': NodeState.PENDING,
             'running': NodeState.RUNNING,
@@ -106,7 +107,10 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
     def ex_delete_public_ip(self,
                             dry_run: bool = False,
@@ -142,7 +146,9 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
     def ex_list_public_ips(self, data: str = "{}"):
         """
@@ -239,7 +245,9 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
     def ex_detach_public_ip(self,
                             public_ip: str = None,
@@ -275,7 +283,9 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
     def create_node(self,
                     ex_image_id: str,
@@ -428,7 +438,9 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        vm = requests.post(endpoint, data=data, headers=headers).json()["Vms"][0]
+
+        return self._to_node(vm)
 
     def reboot_node(self, node: Node):
         """
@@ -447,46 +459,42 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return False
+        return False
+
+    def _to_node(self, vm):
+        name = ""
+        private_ips = []
+        for tag in vm["Tags"]:
+            if tag["Key"] == "Name":
+                name = tag["Value"]
+        if "PrivateIps" in vm["Nics"]:
+            private_ips = vm["Nics"]["PrivateIps"]
+
+        return Node(id=vm["VmId"],
+                    name=name,
+                    state=self.NODE_STATE[vm["State"]],
+                    public_ips=[],
+                    private_ips=private_ips,
+                    driver=self,
+                    extra=vm)
 
     def _to_nodes(self, vms: list):
-        nodes_list = []
-        for vm in vms:
-            name = ""
-            private_ips = []
-            for tag in vm["Tags"]:
-                if tag["Key"] == "Name":
-                    name = tag["Value"]
-            if "PrivateIps" in vm["Nics"]:
-                private_ips = vm["Nics"]["PrivateIps"]
-
-            node = Node(id=vm["VmId"],
-                        name=name,
-                        state=self.NODE_STATE[vm["State"]],
-                        public_ips=[],
-                        private_ips=private_ips,
-                        driver=self,
-                        extra=vm)
-            nodes_list.append(node)
-        return nodes_list
+        return [self._to_node(vm) for vm in vms]
+
+    def _to_node_image(self, image):
+        name = ""
+        for tag in image["Tags"]:
+            if tag["Key"] == "Name":
+                name = tag["Value"]
+        return NodeImage(id=image["NodeId"],
+                         name=name,
+                         driver=self,
+                         extra=image)
 
     def _to_node_images(self, node_images: list):
-        node_image_list = []
-        for image in node_images:
-            name = ""
-            private_ips = []
-            for tag in image["Tags"]:
-                if tag["Key"] == "Name":
-                    name = tag["Value"]
-            if "PrivateIps" in image["Nics"]:
-                private_ips = image["Nics"]["PrivateIps"]
-
-            node = NodeImage(id=image["NodeId"],
-                             name=name,
-                             driver=self,
-                             extra=image)
-            node_image_list.append(node)
-        return node_image_list
+        return [self._to_node_image(node_image) for node_image in node_images]
 
     def list_nodes(self, ex_data: str = "{}"):
         """
@@ -519,7 +527,9 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
+            return True
+        return False
 
     def create_image(
         self,
@@ -603,7 +613,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        image = requests.post(endpoint, data=data, headers=headers).json()["Image"]
+        return self._to_node_images(image)
 
     def list_images(self, ex_data: str = "{}"):
         """
@@ -637,7 +648,7 @@ class OutscaleNodeDriver(NodeDriver):
                                                self.version,
                                                action)
         images = requests.post(endpoint, data=data, headers=headers).json()["Images"]
-        return self._to_node_images(images)[0]
+        return self._to_node_image(images)
 
     def delete_image(self, node_image: NodeImage):
         """
@@ -655,8 +666,7 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        response = requests.post(endpoint, data=data, headers=headers)
-        if response.status_code == 200:
+        if requests.post(endpoint, data=data, headers=headers).status_code == 200:
             return True
         return False
 
@@ -667,7 +677,7 @@ class OutscaleNodeDriver(NodeDriver):
         private_key = key_pair["PrivateKey"] if "PrivateKey" in key_pair else ""
         return KeyPair(
             name=key_pair["KeypairName"],
-            public_key=None,
+            public_key="",
             private_key=private_key,
             fingerprint=key_pair["KeypairFingerprint"],
             driver=self)
@@ -788,7 +798,8 @@ class OutscaleNodeDriver(NodeDriver):
         ex_snapshot_size: int = None,
         ex_source_region_name: str = None,
         ex_source_snapshot: VolumeSnapshot = None,
-        volume: StorageVolume = None):
+        volume: StorageVolume = None
+    ):
         """
         Create a new snapshot.
 
@@ -846,7 +857,8 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-        return requests.post(endpoint, data=data, headers=headers)
+        snapshot = requests.post(endpoint, data=data, headers=headers).json()["Volume"]
+        return self._to_snapshot(snapshot)
 
     def _to_snapshot(self, snapshot):
         name = None
@@ -963,9 +975,7 @@ class OutscaleNodeDriver(NodeDriver):
         endpoint = self._get_outscale_endpoint(self.region,
                                                self.version,
                                                action)
-
         volume = requests.post(endpoint, data=data, headers=headers).json()["Volume"]
-
         return self._to_volume(volume)
 
     def list_volumes(self, ex_data: str = "{}"):


[libcloud] 08/10: Merge branch 'trunk' of https://github.com/outscale-dev/libcloud into outscale-dev-trunk

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 86ef1f18d8da22dbd68cb6ca5bbcdbd68c788336
Merge: 7ddda6a 48fa2fa
Author: Tomaz Muraus <to...@tomaz.me>
AuthorDate: Sun Aug 30 16:41:32 2020 +0200

    Merge branch 'trunk' of https://github.com/outscale-dev/libcloud into outscale-dev-trunk

 libcloud/common/osc.py               |  160 ++++++
 libcloud/compute/drivers/outscale.py | 1018 ++++++++++++++++++++++++++++++++++
 libcloud/compute/providers.py        |    2 +
 libcloud/compute/types.py            |    2 +
 libcloud/test/common/test_osc.py     |  142 +++++
 5 files changed, 1324 insertions(+)


[libcloud] 10/10: Add changelog entry.

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e6c32e5e337424d5b846d3ef4384c52e85679745
Author: Tomaz Muraus <to...@tomaz.me>
AuthorDate: Sun Aug 30 16:45:35 2020 +0200

    Add changelog entry.
---
 CHANGES.rst | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/CHANGES.rst b/CHANGES.rst
index 8f08ffd..fa583e0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -104,6 +104,12 @@ Compute
   when we are executing commands on a Windows server.
   [Arthur Kamalov, Tomaz Muraus]
 
+- [Outscale] Add a new driver for the Outscale provider. Existing Outscale
+  driver utilizes the EC2 compatible API and this one utilizes native Outscale
+  API.
+  (GITHUB-1476)
+  [Tio Gobin - @tgn-outscale]
+
 Changes in Apache Libcloud 3.1.0
 --------------------------------