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:12 UTC
[libcloud] 03/10: Changed code so it use with Libcloud resources'
class on Outscale Provider
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):