You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2017/04/10 22:16:41 UTC
[1/3] libcloud git commit: Added Import Snapshot and Describe Import
Snapshot to EC2 compute driver
Repository: libcloud
Updated Branches:
refs/heads/trunk 9f4d0a263 -> a5731abb0
Added Import Snapshot and Describe Import Snapshot to EC2 compute driver
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0e73f775
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0e73f775
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0e73f775
Branch: refs/heads/trunk
Commit: 0e73f7758caa6ca11b979c286c314e8b7c91f821
Parents: c62d7c9
Author: Nirzari Iyer <ni...@localhost.localdomain>
Authored: Tue Feb 14 14:36:41 2017 -0500
Committer: nirzari <ni...@redhat.com>
Committed: Sun Apr 9 22:46:39 2017 -0400
----------------------------------------------------------------------
libcloud/compute/drivers/ec2.py | 228 +++++++++++++++++++
.../ec2/describe_import_snapshot_tasks.xml | 18 ++
.../describe_import_snapshot_tasks_active.xml | 17 ++
.../compute/fixtures/ec2/import_snapshot.xml | 16 ++
libcloud/test/compute/test_ec2.py | 41 ++++
5 files changed, 320 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/0e73f775/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index 466b802..461248c 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -22,6 +22,7 @@ import sys
import base64
import copy
import warnings
+import time
try:
from lxml import etree as ET
@@ -67,6 +68,7 @@ __all__ = [
'EC2NodeLocation',
'EC2ReservedNode',
'EC2SecurityGroup',
+ 'EC2ImportSnapshotTask',
'EC2PlacementGroup',
'EC2Network',
'EC2NetworkSubnet',
@@ -2872,6 +2874,22 @@ class EC2SecurityGroup(object):
% (self.id, self.name))
+class EC2ImportSnapshotTask(object):
+ """
+ Represents information about a describe_import_snapshot_task.
+
+ Note: This class is EC2 specific.
+ """
+
+ def __init__(self, status, snapshotId):
+ self.status = status
+ self.snapshotId = snapshotId
+
+ def __repr__(self):
+ return (('<EC2SecurityGroup: status=%s, snapshotId=%s')
+ % (self.status, self.snapshotId))
+
+
class EC2PlacementGroup(object):
"""
Represents information about a Placement Grous
@@ -3906,6 +3924,138 @@ class BaseEC2NodeDriver(NodeDriver):
response = self.connection.request(self.path, params=params).object
return self._get_boolean(response)
+ def ex_import_snapshot(self, client_data=None,
+ client_token=None, description=None,
+ disk_container=None, dry_run=None, role_name=None):
+ """
+ Imports a disk into an EBS snapshot. More information can be found
+ at https://goo.gl/sbXkYA.
+
+ :param client_data: Describes the client specific data (optional)
+ :type client_data: ``dict``
+
+ :param client_token: The token to enable idempotency for VM
+ import requests.(optional)
+ :type client_token: ``str``
+
+ :param description: The description string for the
+ import snapshot task.(optional)
+ :type description: ``str``
+
+ :param disk_container:The disk container object for the
+ import snapshot request.
+ :type disk_container:``dict``
+
+ :param dry_run: Checks whether you have the permission for
+ the action, without actually making the request,
+ and provides an error response.(optional)
+ :type dry_run: ``bool``
+
+ :param role_name: The name of the role to use when not using the
+ default role, 'vmimport'.(optional)
+ :type role_name: ``str``
+
+ :rtype: :class: ``VolumeSnapshot``
+ """
+
+ params = {'Action': 'ImportSnapshot'}
+
+ if client_data is not None:
+ params.update(self._get_client_date_params(client_data))
+
+ if client_token is not None:
+ params['ClientToken'] = client_token
+
+ if description is not None:
+ params['Description'] = description
+
+ if disk_container is not None:
+ params.update(self._get_disk_container_params(disk_container))
+
+ if dry_run is not None:
+ params['DryRun'] = dry_run
+
+ if role_name is not None:
+ params['RoleName'] = role_name
+
+ importSnapshot = self.connection.request(self.path,
+ params=params).object
+
+ importTaskId = findtext(element=importSnapshot,
+ xpath='importTaskId',
+ namespace=NAMESPACE)
+
+ volumeSnapshot = self._wait_for_import_snapshot_completion(
+ import_task_id=importTaskId, timeout=1800, interval=15)
+
+ return volumeSnapshot
+
+ def _wait_for_import_snapshot_completion(self,
+ import_task_id,
+ timeout=1800,
+ interval=15):
+ """
+ It waits for import snapshot to be completed
+
+ :param import_task_id: Import task Id for the
+ current Import Snapshot Task
+ :type import_task_id: ``str``
+
+ :param timeout: Timeout value for snapshot generation
+ :type timeout: ``float``
+
+ :param interval: Time interval for repetative describe
+ import snapshot tasks requests
+ :type interval: ``float``
+
+ :rtype: :class:``VolumeSnapshot``
+ """
+ start_time = time.time()
+ snapshotId = None
+ while snapshotId is None:
+ if (time.time() - start_time >= timeout):
+ raise Exception('Timeout while waiting '
+ 'for import task Id %s'
+ % import_task_id)
+ res = self.ex_describe_import_snapshot_tasks(import_task_id)
+ snapshotId = res.snapshotId
+
+ if snapshotId is None:
+ time.sleep(interval)
+
+ volumeSnapshot = VolumeSnapshot(snapshotId, driver=self)
+ return volumeSnapshot
+
+ def ex_describe_import_snapshot_tasks(self, import_task_id, dry_run=None):
+ """
+ Describes your import snapshot tasks. More information can be found
+ at https://goo.gl/CI0MdS.
+
+ :param import_task_id: Import task Id for the current
+ Import Snapshot Task
+ :type import_task_id: ``str``
+
+ :param dry_run: Checks whether you have the permission for
+ the action, without actually making the request,
+ and provides an error response.(optional)
+ :type dry_run: ``bool``
+
+ :rtype: :class:``DescribeImportSnapshotTasks Object``
+
+ """
+ params = {'Action': 'DescribeImportSnapshotTasks'}
+
+ if dry_run is not None:
+ params['DryRun'] = dry_run
+
+ # This can be extended for multiple import snapshot tasks
+ params['ImportTaskId.1'] = import_task_id
+
+ res = self._to_import_snapshot_task(
+ self.connection.request(self.path, params=params).object
+ )
+ return res
+
def ex_list_placement_groups(self, names=None):
"""
A list of placement groups.
@@ -6040,6 +6190,19 @@ class BaseEC2NodeDriver(NodeDriver):
state=state,
name=name)
+ def _to_import_snapshot_task(self, element):
+ status = findtext(element=element, xpath='importSnapshotTaskSet/item/'
+ 'snapshotTaskDetail/status', namespace=NAMESPACE)
+
+ if status != 'completed':
+ snapshotId = None
+ else:
+ xpath = 'importSnapshotTaskSet/item/snapshotTaskDetail/snapshotId'
+ snapshotId = findtext(element=element, xpath=xpath,
+ namespace=NAMESPACE)
+
+ return EC2ImportSnapshotTask(status, snapshotId=snapshotId)
+
def _to_key_pairs(self, elems):
key_pairs = [self._to_key_pair(elem=elem) for elem in elems]
return key_pairs
@@ -6696,6 +6859,71 @@ class BaseEC2NodeDriver(NodeDriver):
% (idx, k, key)] = str(value)
return params
+ def _get_disk_container_params(self, disk_container):
+ """
+ Return a list of dictionaries with query parameters for
+ a valid disk container.
+
+ :param disk_container: List of dictionaries with
+ disk_container details
+ :type disk_container: ``list`` or ``dict``
+
+ :return: Dictionary representation of the disk_container
+ :rtype: ``dict``
+ """
+
+ if not isinstance(disk_container, (list, tuple)):
+ raise AttributeError('disk_container not list or tuple')
+
+ params = {}
+
+ for idx, content in enumerate(disk_container):
+ idx += 1 # We want 1-based indexes
+ if not isinstance(content, dict):
+ raise AttributeError(
+ 'content %s in disk_container not a dict' % content)
+
+ for k, v in content.items():
+ if not isinstance(v, dict):
+ params['DiskContainer.%s' % (k)] = str(v)
+
+ else:
+ for key, value in v.items():
+ params['DiskContainer.%s.%s'
+ % (k, key)] = str(value)
+
+ return params
+
+ def _get_client_data_params(self, client_data):
+ """
+ Return a dictionary with query parameters for
+ a valid client data.
+
+ :param client_data: List of dictionaries with the disk
+ upload details
+ :type client_data: ``dict``
+
+ :return: Dictionary representation of the client data
+ :rtype: ``dict``
+ """
+
+ if not isinstance(client_data, (list, tuple)):
+ raise AttributeError('client_data not list or tuple')
+
+ params = {}
+
+ for idx, content in enumerate(client_data):
+ idx += 1 # We want 1-based indexes
+ if not isinstance(content, dict):
+ raise AttributeError(
+ 'content %s in client_data'
+ 'not a dict' % content)
+
+ for k, v in content.items():
+ params['ClientData.%s' % (k)] = str(v)
+
+ return params
+
def _get_common_security_group_params(self, group_id, protocol,
from_port, to_port, cidr_ips,
group_pairs):
http://git-wip-us.apache.org/repos/asf/libcloud/blob/0e73f775/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks.xml b/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks.xml
new file mode 100644
index 0000000..86ae679
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks.xml
@@ -0,0 +1,18 @@
+<DescribeImportSnapshotTasksResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
+ <requestId>a8c44ac4-8e63-46e9-b8b2-8c72ce3d9b18</requestId>
+ <importSnapshotTaskSet>
+ <item>
+ <importTaskId>import-snap-fh7y6i6w</importTaskId>
+ <snapshotTaskDetail>
+ <snapshotId>snap-0ea83e8a87e138f39</snapshotId>
+ <format>RAW</format>
+ <diskImageSize>1.073741824E10</diskImageSize>
+ <userBucket>
+ <s3Bucket>dummy-bucket</s3Bucket>
+ <s3Key>dummy-key</s3Key>
+ </userBucket>
+ <status>completed</status>
+ </snapshotTaskDetail>
+ </item>
+ </importSnapshotTaskSet>
+</DescribeImportSnapshotTasksResponse>
http://git-wip-us.apache.org/repos/asf/libcloud/blob/0e73f775/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks_active.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks_active.xml b/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks_active.xml
new file mode 100644
index 0000000..edb00cd
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks_active.xml
@@ -0,0 +1,17 @@
+<DescribeImportSnapshotTasksResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
+ <requestId>a8c44ac4-8e63-46e9-b8b2-8c72ce3d9b18</requestId>
+ <importSnapshotTaskSet>
+ <item>
+ <importTaskId>import-snap-fh7y6i6w</importTaskId>
+ <snapshotTaskDetail>
+ <format>RAW</format>
+ <diskImageSize>1.073741824E10</diskImageSize>
+ <userBucket>
+ <s3Bucket>dummy-bucket</s3Bucket>
+ <s3Key>dummy-key</s3Key>
+ </userBucket>
+ <status>active</status>
+ </snapshotTaskDetail>
+ </item>
+ </importSnapshotTaskSet>
+</DescribeImportSnapshotTasksResponse>
http://git-wip-us.apache.org/repos/asf/libcloud/blob/0e73f775/libcloud/test/compute/fixtures/ec2/import_snapshot.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/import_snapshot.xml b/libcloud/test/compute/fixtures/ec2/import_snapshot.xml
new file mode 100644
index 0000000..e2d51de
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/import_snapshot.xml
@@ -0,0 +1,16 @@
+<ImportSnapshotResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
+ <requestId>0d490bf6-19cf-4456-9c71-31d097faf46d</requestId>
+ <importTaskId>import-snap-fgsddbhv</importTaskId>
+ <snapshotTaskDetail>
+ <format>RAW</format>
+ <progress>3</progress>
+ <diskImageSize>0.0</diskImageSize>
+ <statusMessage>pending</statusMessage>
+ <userBucket>
+ <s3Bucket>dummy-bucket</s3Bucket>
+ <s3Key>dummy-key</s3Key>
+ </userBucket>
+ <status>active</status>
+ </snapshotTaskDetail>
+</ImportSnapshotResponse>
+
http://git-wip-us.apache.org/repos/asf/libcloud/blob/0e73f775/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py
index 7702d82..6b942e3 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -562,6 +562,35 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
ena_support=True)
self.assertEqual(image.id, 'ami-57c2fb3e')
+ def test_ex_import_snapshot(self):
+ disk_container = [{'Description': 'Dummy import snapshot task',
+ 'Format': 'raw',
+ 'UserBucket': {'S3Bucket': 'dummy-bucket', 'S3Key': 'dummy-key'}}]
+
+ snap = self.driver.ex_import_snapshot(disk_container=disk_container)
+ self.assertEqual(snap.id, 'snap-0ea83e8a87e138f39')
+
+ def test_wait_for_import_snapshot_completion(self):
+ snap = self.driver._wait_for_import_snapshot_completion(
+ import_task_id='import-snap-fhdysyq6')
+ self.assertEqual(snap.id, 'snap-0ea83e8a87e138f39')
+
+ def test_timeout_wait_for_import_snapshot_completion(self):
+ import_task_id = 'import-snap-fhdysyq6'
+ EC2MockHttp.type = 'timeout'
+ with self.assertRaises(Exception) as context:
+ self.driver._wait_for_import_snapshot_completion(
+ import_task_id=import_task_id, timeout=0.01, interval=0.001)
+ self.assertEqual('Timeout while waiting for import task Id %s'
+ % import_task_id, str(context.exception))
+
+ def test_ex_describe_import_snapshot_tasks(self):
+ snap = self.driver.ex_describe_import_snapshot_tasks(
+ import_task_id='import-snap-fh7y6i6w<')
+
+ self.assertEqual(snap.snapshotId, 'snap-0ea83e8a87e138f39')
+ self.assertEqual(snap.status, 'completed')
+
def test_ex_list_availability_zones(self):
availability_zones = self.driver.ex_list_availability_zones()
availability_zone = availability_zones[0]
@@ -1264,6 +1293,18 @@ class EC2MockHttp(MockHttpTestCase):
body = self.fixtures.load('register_image.xml')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ def _ImportSnapshot(self, method, url, body, headers):
+ body = self.fixtures.load('import_snapshot.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _DescribeImportSnapshotTasks(self, method, url, body, headers):
+ body = self.fixtures.load('describe_import_snapshot_tasks.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _timeout_DescribeImportSnapshotTasks(self, method, url, body, headers):
+ body = self.fixtures.load('describe_import_snapshot_tasks_active.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
def _ex_imageids_DescribeImages(self, method, url, body, headers):
body = self.fixtures.load('describe_images_ex_imageids.xml')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
[3/3] libcloud git commit: changes for #1023
Posted by an...@apache.org.
changes for #1023
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/a5731abb
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/a5731abb
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/a5731abb
Branch: refs/heads/trunk
Commit: a5731abb0665d0a823f93f6c5e2c8fe7aa601385
Parents: c3dde04
Author: Anthony Shaw <an...@apache.org>
Authored: Tue Apr 11 08:16:33 2017 +1000
Committer: Anthony Shaw <an...@apache.org>
Committed: Tue Apr 11 08:16:33 2017 +1000
----------------------------------------------------------------------
CHANGES.rst | 4 ++++
1 file changed, 4 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/a5731abb/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index 221f5f1..bb4acef 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -14,6 +14,10 @@ Common
Compute
~~~~~~~
+- Added Import Snapshot and Describe Import Snapshot to EC2 compute driver
+ [GITHUB-1023]
+ (Nirzari Iyer)
+
- Add price_monthly extra param to digitalocean sizes
[GITHUB-1021]
(Francisco Ros)
[2/3] libcloud git commit: Merge branch 'github-1023' into trunk
Closes #1023
Posted by an...@apache.org.
Merge branch 'github-1023' into trunk
Closes #1023
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/c3dde041
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/c3dde041
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/c3dde041
Branch: refs/heads/trunk
Commit: c3dde041a5648cf5f4138561e75443758f292d25
Parents: 9f4d0a2 0e73f77
Author: Anthony Shaw <an...@apache.org>
Authored: Tue Apr 11 08:07:49 2017 +1000
Committer: Anthony Shaw <an...@apache.org>
Committed: Tue Apr 11 08:07:49 2017 +1000
----------------------------------------------------------------------
libcloud/compute/drivers/ec2.py | 226 +++++++++++++++++++
.../ec2/describe_import_snapshot_tasks.xml | 18 ++
.../describe_import_snapshot_tasks_active.xml | 17 ++
.../compute/fixtures/ec2/import_snapshot.xml | 16 ++
libcloud/test/compute/test_ec2.py | 41 ++++
5 files changed, 318 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/c3dde041/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --cc libcloud/compute/drivers/ec2.py
index 31b8b8e,461248c..5177327
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@@ -6799,27 -6859,69 +6962,90 @@@ class BaseEC2NodeDriver(NodeDriver)
% (idx, k, key)] = str(value)
return params
+ def _get_billing_product_params(self, billing_products):
+ """
+ Return a list of dictionaries with valid param for billing product.
+
+ :param billing_product: List of billing code values(str)
+ :type billing product: ``list``
+
+ :return: Dictionary representation of the billing product codes
+ :rtype: ``dict``
+ """
+
+ if not isinstance(billing_products, (list, tuple)):
+ raise AttributeError(
+ 'billing_products not list or tuple')
+
+ params = {}
+
+ for idx, v in enumerate(billing_products):
+ idx += 1 # We want 1-based indexes
+ params['BillingProduct.%d' % (idx)] = str(v)
+
+ def _get_disk_container_params(self, disk_container):
+ """
+ Return a list of dictionaries with query parameters for
+ a valid disk container.
+
+ :param disk_container: List of dictionaries with
+ disk_container details
+ :type disk_container: ``list`` or ``dict``
+
+ :return: Dictionary representation of the disk_container
+ :rtype: ``dict``
+ """
+
+ if not isinstance(disk_container, (list, tuple)):
+ raise AttributeError('disk_container not list or tuple')
+
+ params = {}
+
+ for idx, content in enumerate(disk_container):
+ idx += 1 # We want 1-based indexes
+ if not isinstance(content, dict):
+ raise AttributeError(
+ 'content %s in disk_container not a dict' % content)
+
+ for k, v in content.items():
+ if not isinstance(v, dict):
+ params['DiskContainer.%s' % (k)] = str(v)
+
+ else:
+ for key, value in v.items():
+ params['DiskContainer.%s.%s'
+ % (k, key)] = str(value)
+
+ return params
+
+ def _get_client_data_params(self, client_data):
+ """
+ Return a dictionary with query parameters for
+ a valid client data.
+
+ :param client_data: List of dictionaries with the disk
+ upload details
+ :type client_data: ``dict``
+
+ :return: Dictionary representation of the client data
+ :rtype: ``dict``
+ """
+
+ if not isinstance(client_data, (list, tuple)):
+ raise AttributeError('client_data not list or tuple')
+
+ params = {}
+
+ for idx, content in enumerate(client_data):
+ idx += 1 # We want 1-based indexes
+ if not isinstance(content, dict):
+ raise AttributeError(
+ 'content %s in client_data'
+ 'not a dict' % content)
+
+ for k, v in content.items():
+ params['ClientData.%s' % (k)] = str(v)
+
return params
def _get_common_security_group_params(self, group_id, protocol,
http://git-wip-us.apache.org/repos/asf/libcloud/blob/c3dde041/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --cc libcloud/test/compute/test_ec2.py
index 3e761a5,6b942e3..4d34e47
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@@ -564,11 -559,38 +564,40 @@@ class EC2Tests(LibcloudTestCase, TestCa
description='My Image',
architecture='x86_64',
block_device_mapping=mapping,
- ena_support=True)
+ ena_support=True,
+ billing_products=['ab-5dh78019'],
+ sriov_net_support='simple')
self.assertEqual(image.id, 'ami-57c2fb3e')
+ def test_ex_import_snapshot(self):
+ disk_container = [{'Description': 'Dummy import snapshot task',
+ 'Format': 'raw',
+ 'UserBucket': {'S3Bucket': 'dummy-bucket', 'S3Key': 'dummy-key'}}]
+
+ snap = self.driver.ex_import_snapshot(disk_container=disk_container)
+ self.assertEqual(snap.id, 'snap-0ea83e8a87e138f39')
+
+ def test_wait_for_import_snapshot_completion(self):
+ snap = self.driver._wait_for_import_snapshot_completion(
+ import_task_id='import-snap-fhdysyq6')
+ self.assertEqual(snap.id, 'snap-0ea83e8a87e138f39')
+
+ def test_timeout_wait_for_import_snapshot_completion(self):
+ import_task_id = 'import-snap-fhdysyq6'
+ EC2MockHttp.type = 'timeout'
+ with self.assertRaises(Exception) as context:
+ self.driver._wait_for_import_snapshot_completion(
+ import_task_id=import_task_id, timeout=0.01, interval=0.001)
+ self.assertEqual('Timeout while waiting for import task Id %s'
+ % import_task_id, str(context.exception))
+
+ def test_ex_describe_import_snapshot_tasks(self):
+ snap = self.driver.ex_describe_import_snapshot_tasks(
+ import_task_id='import-snap-fh7y6i6w<')
+
+ self.assertEqual(snap.snapshotId, 'snap-0ea83e8a87e138f39')
+ self.assertEqual(snap.status, 'completed')
+
def test_ex_list_availability_zones(self):
availability_zones = self.driver.ex_list_availability_zones()
availability_zone = availability_zones[0]