← Back to team overview

txaws-dev team mailing list archive

[Merge] lp:~fwierzbicki/txaws/empty-instances-workaround into lp:txaws

 

Frank Wierzbicki has proposed merging lp:~fwierzbicki/txaws/empty-instances-workaround into lp:txaws.

Requested reviews:
  txAWS Developers (txaws-dev)

For more details, see:
https://code.launchpad.net/~fwierzbicki/txaws/empty-instances-workaround/+merge/85562

This branch raises a more useful exception when it gets a TerminateInstancesResponse XML that lacks an instancesSet. This will allow us to see the original xml response from cloud deck so that we can work around this behavior -- see https://bugs.launchpad.net/nova/+bug/862680 for the motivating bug.

This branch also makes the error message parsing in AWSException more robust in the face of unexpected xml.
-- 
https://code.launchpad.net/~fwierzbicki/txaws/empty-instances-workaround/+merge/85562
Your team txAWS Developers is requested to review the proposed merge of lp:~fwierzbicki/txaws/empty-instances-workaround into lp:txaws.
=== modified file 'txaws/ec2/client.py'
--- txaws/ec2/client.py	2011-08-19 16:09:39 +0000
+++ txaws/ec2/client.py	2011-12-21 23:44:23 +0000
@@ -629,8 +629,14 @@
         """
         root = XML(xml_bytes)
         result = []
+        instances = root.find("instancesSet")
+        if instances is None:
+            # At this time, Nova returns an invalid response to
+            # terminate_instances (missing instancesSet).  See
+            # https://bugs.launchpad.net/nova/+bug/862680.
+            raise EC2Error(xml_bytes, 500, "Invalid missing instancesSet.")
         # May be a more elegant way to do this:
-        for instance in root.find("instancesSet"):
+        for instance in instances:
             instanceId = instance.findtext("instanceId")
             previousState = instance.find("previousState").findtext(
                 "name")

=== modified file 'txaws/ec2/tests/test_client.py'
--- txaws/ec2/tests/test_client.py	2011-08-29 19:51:50 +0000
+++ txaws/ec2/tests/test_client.py	2011-12-21 23:44:23 +0000
@@ -315,6 +315,38 @@
         d.addCallback(check_transition)
         return d
 
+    # At this time, Nova returns an invalid response to terminate_instances.
+    # See https://bugs.launchpad.net/nova/+bug/862680. txaws passes down a
+    # 500 error, but with the original xml included so a sufficiently
+    # motivated client can still work with it.
+    def test_nova_terminate_instances(self):
+
+        class StubQuery(object):
+
+            def __init__(stub, action="", creds=None, endpoint=None,
+                         other_params={}):
+                self.assertEqual(action, "TerminateInstances")
+                self.assertEqual(creds.access_key, "foo")
+                self.assertEqual(creds.secret_key, "bar")
+                self.assertEqual(
+                    other_params,
+                    {"InstanceId.1": "i-1234", "InstanceId.2": "i-5678"})
+
+            def submit(self):
+                return succeed(payload.nova_terminate_instances_result)
+
+        def check_error(error):
+            self.assertEquals(
+                str(error), ("Error Message: Error with invalid message."))
+
+        creds = AWSCredentials("foo", "bar")
+        endpoint = AWSServiceEndpoint(uri=EC2_ENDPOINT_US)
+        ec2 = client.EC2Client(creds=creds, endpoint=endpoint,
+                               query_factory=StubQuery)
+        failure = ec2.terminate_instances("i-1234", "i-5678")
+        d = self.assertFailure(failure, EC2Error)
+        return d.addCallback(check_error)
+
     def check_parsed_run_instances(self, results):
         instance = results[0]
         # check reservations
@@ -634,7 +666,6 @@
                 str(error),
                 ("Error Message: Group groupID1:GroupReferredTo is used by "
                  "groups: groupID2:UsingGroup"))
-
         creds = AWSCredentials("foo", "bar")
         ec2 = client.EC2Client(creds, query_factory=StubQuery)
         failure = ec2.delete_security_group("GroupReferredTo")

=== modified file 'txaws/exception.py'
--- txaws/exception.py	2010-03-29 17:16:46 +0000
+++ txaws/exception.py	2011-12-21 23:44:23 +0000
@@ -118,9 +118,10 @@
             return "Multiple EC2 Errors"
         elif count == 0:
             return "Empty error list"
-        else:
+        elif "Message" in self.errors[0]:
             return self.errors[0]["Message"]
-
+        else:
+            return "Error with invalid message."
 
 
 class AWSResponseParseError(Exception):

=== modified file 'txaws/testing/payload.py'
--- txaws/testing/payload.py	2011-08-29 19:51:50 +0000
+++ txaws/testing/payload.py	2011-12-21 23:44:23 +0000
@@ -177,6 +177,15 @@
 </TerminateInstancesResponse>
 """ % (version.ec2_api,)
 
+# Nova does not respond properly to terminate instances, and contains no
+# instancesSet element. See
+# https://bugs.launchpad.net/nova/+bug/862680 for more.
+nova_terminate_instances_result = """\
+<TerminateInstancesResponse xmlns="http://ec2.amazonaws.com/doc/%s/";>
+    <requestId>7ca9d4fd-db86-44da-a622-50d78f550701</requestId>
+    <return>true</return>
+</TerminateInstancesResponse>
+""" % (version.ec2_api,)
 
 sample_describe_security_groups_with_openstack = """\
 <?xml version="1.0"?>
@@ -985,4 +994,3 @@
     </Grant>
   </AccessControlList>
 </AccessControlPolicy>"""
-

=== modified file 'txaws/tests/test_exception.py'
--- txaws/tests/test_exception.py	2010-03-29 17:16:46 +0000
+++ txaws/tests/test_exception.py	2011-12-21 23:44:23 +0000
@@ -7,7 +7,6 @@
 from txaws.exception import AWSResponseParseError
 from txaws.util import XML
 
-
 REQUEST_ID = "0ef9fc37-6230-4d81-b2e6-1b36277d4247"
 
 
@@ -112,3 +111,11 @@
         error._set_500_error(XML(xml))
         self.assertEquals(error.errors[0]["Code"], "500")
         self.assertEquals(error.errors[0]["Message"], "Oops")
+
+    def test_broken_error_node(self):
+        xml = "<Error><Code>500</Code><Broken>Oops</Broken></Error>"
+        #error = AWSError(nova_terminate_instances_result, 500)
+        error = AWSError(xml, 500)
+        self.assertEquals(1, len(error.errors))
+        self.assertEquals("Error Message: Error with invalid message.",
+                          str(error))


Follow ups