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 2014/01/03 15:59:21 UTC

[09/44] git commit: Fixes for dealing with disk on multiple node creation/destruction.

Fixes for dealing with disk on multiple node creation/destruction.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/a0aa4557
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/a0aa4557
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/a0aa4557

Branch: refs/heads/trunk
Commit: a0aa455735ac8b2c1c4bb1a02dc8e7a96eba3920
Parents: ca96c9b
Author: Rick Wright <ri...@google.com>
Authored: Mon Dec 16 12:29:34 2013 -0800
Committer: Rick Wright <ri...@google.com>
Committed: Mon Dec 16 12:29:34 2013 -0800

----------------------------------------------------------------------
 demos/gce_lb_demo.py            |   3 +-
 libcloud/compute/drivers/gce.py | 104 +++++++++++++++++++++++++++--------
 2 files changed, 83 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/a0aa4557/demos/gce_lb_demo.py
----------------------------------------------------------------------
diff --git a/demos/gce_lb_demo.py b/demos/gce_lb_demo.py
index 3c2cdac..e977ac7 100755
--- a/demos/gce_lb_demo.py
+++ b/demos/gce_lb_demo.py
@@ -202,7 +202,8 @@ def main():
                            'value': startup_script}]}
     lb_nodes = gce.ex_create_multiple_nodes(base_name, size, image,
                                             number, ex_tags=[tag],
-                                            ex_metadata=metadata)
+                                            ex_metadata=metadata,
+                                            ignore_errors=False)
     display('Created Nodes', lb_nodes)
 
     # == Create a Firewall for instances ==

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a0aa4557/libcloud/compute/drivers/gce.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py
index d8cdc09..d38b42b 100644
--- a/libcloud/compute/drivers/gce.py
+++ b/libcloud/compute/drivers/gce.py
@@ -1488,9 +1488,17 @@ class GCENodeDriver(NodeDriver):
             else:
                 disk_req, disk_data, disk_params = self._create_vol_req(
                     None, name, location=location, image=image)
-                disk_res = self.connection.request(disk_req, method='POST',
-                                                   data=disk_data,
-                                                   params=disk_params).object
+                try:
+                    disk_res = self.connection.request(
+                        disk_req, method='POST', data=disk_data,
+                        params=disk_params).object
+                except:
+                     e = self._catch_error(ignore_errors=ignore_errors)
+                     error = e.value
+                     code = e.code
+                     disk_res = None
+                     status['disk'] = GCEFailedDisk(status['name'],
+                                                    error, code)
                 status['disk_response'] = disk_res
 
             status_list.append(status)
@@ -1528,11 +1536,22 @@ class GCENodeDriver(NodeDriver):
                 # on its status if already in progress.
                 if status['disk'] and not status['node']:
                     if not status['node_response']:
+                        if hasattr(status['disk'], 'error'):
+                            status['node'] = status['disk']
+                            continue
                         request, node_data = self._create_node_req(
                             status['name'], size, image, location, ex_network,
                             ex_tags, ex_metadata, boot_disk=status['disk'])
-                        node_res = self.connection.request(
-                            request, method='POST', data=node_data).object
+                        try:
+                            node_res = self.connection.request(
+                                request, method='POST', data=node_data).object
+                        except:
+                            e = self._catch_error(ignore_errors=ignore_errors)
+                            error = e.value
+                            code = e.code
+                            node_res = None
+                            status['node'] = GCEFailedNode(status['name'],
+                                                           error, code)
                         status['node_response'] = node_res
                     else:
                         error = None
@@ -2191,8 +2210,7 @@ class GCENodeDriver(NodeDriver):
                   that the node was successfully destroyed.
         :rtype:   ``list`` of ``bool``
         """
-        responses = []
-        success = [False] * len(nodelist)
+        status_list = []
         complete = False
         start_time = time.time()
         for node in nodelist:
@@ -2204,29 +2222,69 @@ class GCENodeDriver(NodeDriver):
             except:
                 self._catch_error(ignore_errors=ignore_errors)
                 response = None
-            responses.append(response)
+
+            status = {'node': node,
+                      'node_success': False,
+                      'node_response': response,
+                      'disk_success': not destroy_boot_disk,
+                      'disk_response': None}
+
+            status_list.append(status)
 
         while not complete:
             if (time.time() - start_time >= timeout):
                 raise Exception("Timeout (%s sec) while waiting to delete "
                                 "multiple instances")
             complete = True
-            for i, operation in enumerate(responses):
-                if operation is None:
-                    continue
-                no_errors = True
-                try:
-                    response = self.connection.request(
-                        operation['selfLink']).object
-                except:
-                    self._catch_error(ignore_errors=ignore_errors)
-                    no_errors = False
-                if response['status'] == 'DONE':
-                    responses[i] = None
-                    success[i] = no_errors
-                else:
-                    complete = False
+            for status in status_list:
+                # If one of the operations is running, check the status
+                operation = status['node_response'] or status['disk_response']
+                delete_disk = False
+                if operation:
+                    no_errors = True
+                    try:
+                        response = self.connection.request(
+                            operation['selfLink']).object
+                    except:
+                        self._catch_error(ignore_errors=ignore_errors)
+                        no_errors = False
+                        response = {'status': 'DONE'}
+                    if response['status'] == 'DONE':
+                        # If a node was deleted, update status and indicate
+                        # that the disk is ready to be deleted.
+                        if status['node_response']:
+                            status['node_response'] = None
+                            status['node_success'] = no_errors
+                            delete_disk = True
+                        else:
+                            status['disk_response'] = None
+                            status['disk_success'] = no_errors
+                # If we are destroying disks, and the node has been deleted,
+                # destroy the disk.
+                if delete_disk and destroy_boot_disk:
+                    boot_disk = status['node'].extra['boot_disk']
+                    if boot_disk:
+                        request = '/zones/%s/disks/%s' % (
+                            boot_disk.extra['zone'].name, boot_disk.name)
+                        try:
+                            response = self.connection.request(
+                                request, method='DELETE').object
+                        except:
+                            self._catch_error(ignore_errors=ignore_errors)
+                            no_errors = False
+                            response = None
+                        status['disk_response'] = response
+                    else:  # If there is no boot disk, ignore
+                        status['disk_success'] = True
+                operation = status['node_response'] or status['disk_response']
+                if operation:
                     time.sleep(2)
+                    complete = False
+
+        success = []
+        for status in status_list:
+            s = status['node_success'] and status['disk_success']
+            success.append(s)
         return success
 
     def ex_destroy_targetpool(self, targetpool):