You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by je...@apache.org on 2011/01/04 15:35:34 UTC

svn commit: r1055059 - in /incubator/libcloud/trunk: libcloud/drivers/ec2.py test/test_ec2.py

Author: jerry
Date: Tue Jan  4 14:35:34 2011
New Revision: 1055059

URL: http://svn.apache.org/viewvc?rev=1055059&view=rev
Log:
Tests for EC2 Idempotent launches; LIBCLOUD-69

Submitted By: David LaBissoniere

Modified:
    incubator/libcloud/trunk/libcloud/drivers/ec2.py
    incubator/libcloud/trunk/test/test_ec2.py

Modified: incubator/libcloud/trunk/libcloud/drivers/ec2.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/drivers/ec2.py?rev=1055059&r1=1055058&r2=1055059&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/drivers/ec2.py (original)
+++ incubator/libcloud/trunk/libcloud/drivers/ec2.py Tue Jan  4 14:35:34 2011
@@ -17,7 +17,7 @@
 Amazon EC2 driver
 """
 from libcloud.providers import Provider
-from libcloud.types import NodeState, InvalidCredsError, MalformedResponseError
+from libcloud.types import NodeState, InvalidCredsError, MalformedResponseError, LibcloudError
 from libcloud.base import Node, Response, ConnectionUserAndKey
 from libcloud.base import NodeDriver, NodeSize, NodeImage, NodeLocation
 import base64
@@ -198,6 +198,8 @@ class EC2Response(Response):
                 raise InvalidCredsError(err_list[-1])
             if code.text == "OptInRequired":
                 raise InvalidCredsError(err_list[-1])
+            if code.text == "IdempotentParameterMismatch":
+                raise IdempotentParamError(err_list[-1])
         return "\n".join(err_list)
 
 class EC2Connection(ConnectionUserAndKey):
@@ -654,6 +656,12 @@ class EC2NodeDriver(NodeDriver):
         res = self.connection.request(self.path, params=params).object
         return self._get_terminate_boolean(res)
 
+class IdempotentParamError(LibcloudError):
+    """
+    Request used the same client token as a previous, but non-identical request.
+    """
+    def __str__(self):
+        return repr(self.value)
 
 class EC2EUConnection(EC2Connection):
     """

Modified: incubator/libcloud/trunk/test/test_ec2.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/test_ec2.py?rev=1055059&r1=1055058&r2=1055059&view=diff
==============================================================================
--- incubator/libcloud/trunk/test/test_ec2.py (original)
+++ incubator/libcloud/trunk/test/test_ec2.py Tue Jan  4 14:35:34 2011
@@ -15,7 +15,7 @@
 import sys
 import unittest
 
-from libcloud.drivers.ec2 import EC2NodeDriver, EC2APSENodeDriver
+from libcloud.drivers.ec2 import EC2NodeDriver, EC2APSENodeDriver, IdempotentParamError
 from libcloud.base import Node, NodeImage, NodeSize
 
 from test import MockHttp, TestCaseMixin
@@ -30,6 +30,7 @@ class EC2Tests(unittest.TestCase, TestCa
     def setUp(self):
         EC2NodeDriver.connectionCls.conn_classes = (None, EC2MockHttp)
         EC2MockHttp.use_param = 'Action'
+        EC2MockHttp.type = None
         self.driver = EC2NodeDriver(EC2_ACCESS_ID, EC2_SECRET)
 
     def test_create_node(self):
@@ -40,7 +41,36 @@ class EC2Tests(unittest.TestCase, TestCa
         node = self.driver.create_node(name='foo', image=image, size=size)
         self.assertEqual(node.id, 'i-2ba64342')
 
-    # TODO: add tests for create_node for ex_clienttoken
+    def test_create_node_idempotent(self):
+        EC2MockHttp.type = 'idempotent'
+        image = NodeImage(id='ami-be3adfd7',
+                          name='ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml',
+                          driver=self.driver)
+        size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver)
+        token = 'testclienttoken'
+        node = self.driver.create_node(name='foo', image=image, size=size,
+                ex_clienttoken=token)
+        self.assertEqual(node.id, 'i-2ba64342')
+        self.assertEqual(node.extra['clienttoken'], token)
+
+        # from: http://docs.amazonwebservices.com/AWSEC2/latest/DeveloperGuide/index.html?Run_Instance_Idempotency.html
+
+        #    If you repeat the request with the same client token, but change
+        #    another request parameter, Amazon EC2 returns an
+        #    IdempotentParameterMismatch error.
+
+        # In our case, changing the parameter doesn't actually matter since we
+        # are forcing the error response fixture.
+        EC2MockHttp.type = 'idempotent_mismatch'
+
+        idem_error = None
+        try:
+            self.driver.create_node(name='foo', image=image, size=size,
+                    ex_mincount='2', ex_maxcount='2', # different count
+                    ex_clienttoken=token)
+        except IdempotentParamError, e:
+            idem_error = e
+        self.assertTrue(idem_error is not None)
 
     def test_list_nodes(self):
         node = self.driver.list_nodes()[0]
@@ -115,6 +145,14 @@ class EC2MockHttp(MockHttp):
         body = self.fixtures.load('run_instances.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _idempotent_RunInstances(self, method, url, body, headers):
+        body = self.fixtures.load('run_instances_idem.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _idempotent_mismatch_RunInstances(self, method, url, body, headers):
+        body = self.fixtures.load('run_instances_idem_mismatch.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.BAD_REQUEST])
+
     def _TerminateInstances(self, method, url, body, headers):
         body = self.fixtures.load('terminate_instances.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
@@ -123,6 +161,7 @@ class EC2APSETests(EC2Tests):
     def setUp(self):
         EC2APSENodeDriver.connectionCls.conn_classes = (None, EC2MockHttp)
         EC2MockHttp.use_param = 'Action'
+        EC2MockHttp.type = None
         self.driver = EC2APSENodeDriver(EC2_ACCESS_ID, EC2_SECRET)
 
 if __name__ == '__main__':