You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by pq...@apache.org on 2010/05/05 02:32:05 UTC

svn commit: r941122 - in /incubator/libcloud/trunk/libcloud: base.py types.py

Author: pquerna
Date: Wed May  5 00:32:05 2010
New Revision: 941122

URL: http://svn.apache.org/viewvc?rev=941122&view=rev
Log:
Add DeploymentException, which allows you to better recover and detect a failure to deploy which is different than a failure of the provider's create_node, this will let you possibly cleanup a partially boot-strapped node.

Modified:
    incubator/libcloud/trunk/libcloud/base.py
    incubator/libcloud/trunk/libcloud/types.py

Modified: incubator/libcloud/trunk/libcloud/base.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/base.py?rev=941122&r1=941121&r2=941122&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/base.py (original)
+++ incubator/libcloud/trunk/libcloud/base.py Wed May  5 00:32:05 2010
@@ -26,7 +26,7 @@ from libcloud.interface import INodeDriv
 from libcloud.interface import INodeFactory, INode
 from libcloud.interface import INodeSizeFactory, INodeSize
 from libcloud.interface import INodeImageFactory, INodeImage
-from libcloud.types import NodeState
+from libcloud.types import NodeState, DeploymentException
 from libcloud.ssh import SSHClient
 import time
 import hashlib
@@ -640,6 +640,11 @@ class NodeDriver(object):
         Depends on a Provider Driver supporting either using a specific password
         or returning a generated password.
 
+        This function may raise a L{DeplyomentException}, if a create_node
+        call was successful, but there is a later error (like SSH failing or 
+        timing out).  This exception includes a Node object which you may want
+        to destroy if incomplete deployments are not desirable.
+
         @keyword    deploy: Deployment to run once machine is online and availble to SSH.
         @type       deploy: L{Deployment}
 
@@ -659,43 +664,48 @@ class NodeDriver(object):
 
             password = kwargs['auth'].password
         node = self.create_node(**kwargs)
-        if 'generates_password' in self.features["create_node"]:
-            password = node.extra.get('password')
-        start = time.time()
-        end = start + (60 * 15)
-        while time.time() < end:
-            # need to wait until we get a public IP address.
-            # TODO: there must be a better way of doing this
-            time.sleep(WAIT_PERIOD)
-            nodes = self.list_nodes()
-            nodes = filter(lambda n: n.uuid == node.uuid, nodes)
-            if len(nodes) == 0:
-                raise Exception("Booted node[%s] is missing form list_nodes.", node)
-            if len(nodes) > 1:
-                raise Exception("Booted single node[%s], but multiple nodes have same UUID", node)
-
-            node = nodes[0]
-
-            if node.public_ip is not None and node.public_ip != "" and node.state == NodeState.RUNNING:
-                break
-
-        client = SSHClient(hostname=node.public_ip[0],
-                            port=22, username='root',
-                            password=password)
-        laste = None
-        while time.time() < end:
-            laste = None
-            try:
-                client.connect()
-                break
-            except (IOError, socket.gaierror, socket.error), e:
-                laste = e
-            time.sleep(WAIT_PERIOD)
-        if laste is not None:
-            raise e
-
-        n = kwargs["deploy"].run(node, client)
-        client.close()
+        try:
+          if 'generates_password' in self.features["create_node"]:
+              password = node.extra.get('password')
+          start = time.time()
+          end = start + (60 * 15)
+          while time.time() < end:
+              # need to wait until we get a public IP address.
+              # TODO: there must be a better way of doing this
+              time.sleep(WAIT_PERIOD)
+              nodes = self.list_nodes()
+              nodes = filter(lambda n: n.uuid == node.uuid, nodes)
+              if len(nodes) == 0:
+                  raise DeploymentException(node, "Booted node[%s] is missing form list_nodes." % node)
+              if len(nodes) > 1:
+                  raise DeploymentException(node, "Booted single node[%s], but multiple nodes have same UUID"% node)
+
+              node = nodes[0]
+
+              if node.public_ip is not None and node.public_ip != "" and node.state == NodeState.RUNNING:
+                  break
+
+          client = SSHClient(hostname=node.public_ip[0],
+                              port=22, username='root',
+                              password=password)
+          laste = None
+          while time.time() < end:
+              laste = None
+              try:
+                  client.connect()
+                  break
+              except (IOError, socket.gaierror, socket.error), e:
+                  laste = e
+              time.sleep(WAIT_PERIOD)
+          if laste is not None:
+              raise e
+
+          n = kwargs["deploy"].run(node, client)
+          client.close()
+        except DeploymentException, e:
+          raise
+        except Exception, e:
+          raise DeploymentException(node, e)
         return n
 
 def is_private_subnet(ip):

Modified: incubator/libcloud/trunk/libcloud/types.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/types.py?rev=941122&r1=941121&r2=941122&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/types.py (original)
+++ incubator/libcloud/trunk/libcloud/types.py Wed May  5 00:32:05 2010
@@ -77,3 +77,15 @@ class InvalidCredsException(Exception):
         self.value = value
     def __str__(self):
         return repr(self.value)
+
+class DeploymentException(Exception):
+    """
+    Exception used when a Deployment Task failed.
+
+    @ivar node: L{Node} on which this exception happened, you might want to call L{Node.destroy}
+    """
+    def __init__(self, node, original_exception=None):
+        self.node = node
+        self.value = original_exception
+    def __str__(self):
+        return repr(self.value)