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 <[email protected]>
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):
         """

Reply via email to