{"action":"created","comment":{"url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/comments/84702267","pull_request_review_id":5462840,"id":84702267,"diff_hunk":"@@ -763,38 +770,94 @@ def _delete_saved_data(self):\n         if os.path.exists(self.known_hosts_file):\n             os.remove(self.known_hosts_file)\n \n-    def _stop_all_nodes(self, wait=False):\n+\n+    def stop_all_nodes_parallel(self, nodes, max_thread_pool_size, wait=False):\n         \"\"\"\n-        Terminate all cluster nodes. Return number of failures.\n+           Terminates  nodes in parallel\n+           Calls a static _stop_node() method\n         \"\"\"\n-        failed = 0\n-        for node in self.get_all_nodes():\n-            if not node.instance_id:\n-                log.warning(\n-                    \"Node `%s` has no instance ID.\"\n-                    \" Assuming it did not start correctly,\"\n-                    \" so removing it anyway from the cluster.\", node.name)\n-                self.nodes[node.kind].remove(node)\n-                continue\n-            # try and stop node\n+\n+        # Create one thread for each node to start\n+        thread_pool_size = min(len(nodes), max_thread_pool_size)\n+        thread_pool = Pool(processes=thread_pool_size)\n+\n+        log.debug(\"Created pool of %d threads\", thread_pool_size)\n+\n+        # pressing Ctrl+C flips this flag, which in turn stops the main loop\n+        # down below\n+        keep_running = True\n+\n+        #iterate a list with noes and a wait value\n+        ## node_stat_list = ((node, wait) for node in nodes)\n+\n+        wait_list = [wait] * len(nodes)\n+        node_stat_list = zip (nodes, wait_list)\n+\n+        def sigint_handler(signal, frame):\n+            \"\"\"\n+            Makes sure the cluster is saved, before the sigint results in\n+            exiting during node startup.\n+            \"\"\"\n+            log.error(\n+                \"Interrupted: will save cluster state and exit\"\n+                \" after all nodes have started.\")\n+            keep_running = False\n+\n+        # intercept Ctrl+C\n+        with sighandler(signal.SIGINT, sigint_handler):\n+            result = thread_pool.map_async(self._stop_node,node_stat_list)\n+            while not result.ready():\n+                result.wait(1)\n+                # check if Ctrl+C was pressed\n+                if not keep_running:\n+                    log.error(\"Aborting upon user interruption ...\")\n+                    # FIXME: `.close()` will keep the pool running until all\n+                    # nodes have been started; should we use `.terminate()`\n+                    # instead to interrupt node creation as soon as possible?\n+                    thread_pool.close()\n+                    thread_pool.join()\n+                    self.repository.save_or_update(self)\n+                    # FIXME: should raise an exception instead!\n+                    sys.exit(1)\n+\n+            # TODO: might return only failed node\n+            return set(failed_node for failed_node, ok\n+                        in itertools.izip(node_stat_list, result.get()) if not ok)","path":"elasticluster/cluster.py","position":89,"original_position":89,"commit_id":"5687d1a7da712e7aa98363f1ce2762db4858d58d","original_commit_id":"5687d1a7da712e7aa98363f1ce2762db4858d58d","user":{"login":"riccardomurri","id":447228,"avatar_url":"https://avatars.githubusercontent.com/u/447228?v=3","gravatar_id":"","url":"https://api.github.com/users/riccardomurri","html_url":"https://github.com/riccardomurri","followers_url":"https://api.github.com/users/riccardomurri/followers","following_url":"https://api.github.com/users/riccardomurri/following{/other_user}","gists_url":"https://api.github.com/users/riccardomurri/gists{/gist_id}","starred_url":"https://api.github.com/users/riccardomurri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/riccardomurri/subscriptions","organizations_url":"https://api.github.com/users/riccardomurri/orgs","repos_url":"https://api.github.com/users/riccardomurri/repos","events_url":"https://api.github.com/users/riccardomurri/events{/privacy}","received_events_url":"https://api.github.com/users/riccardomurri/received_events","type":"User","site_admin":false},"body":"If you go for the lambda/local function instead, `node_stat_list` here should be `nodes` instead.","created_at":"2016-10-24T14:40:20Z","updated_at":"2016-10-24T14:40:20Z","html_url":"https://github.com/gc3-uzh-ch/elasticluster/pull/324#discussion_r84702267","pull_request_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/324","_links":{"self":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/comments/84702267"},"html":{"href":"https://github.com/gc3-uzh-ch/elasticluster/pull/324#discussion_r84702267"},"pull_request":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/324"}}},"pull_request":{"url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/324","id":89489887,"html_url":"https://github.com/gc3-uzh-ch/elasticluster/pull/324","diff_url":"https://github.com/gc3-uzh-ch/elasticluster/pull/324.diff","patch_url":"https://github.com/gc3-uzh-ch/elasticluster/pull/324.patch","issue_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/issues/324","number":324,"state":"open","locked":false,"title":"Parallelizing stop.","user":{"login":"cocoy","id":32607,"avatar_url":"https://avatars.githubusercontent.com/u/32607?v=3","gravatar_id":"","url":"https://api.github.com/users/cocoy","html_url":"https://github.com/cocoy","followers_url":"https://api.github.com/users/cocoy/followers","following_url":"https://api.github.com/users/cocoy/following{/other_user}","gists_url":"https://api.github.com/users/cocoy/gists{/gist_id}","starred_url":"https://api.github.com/users/cocoy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cocoy/subscriptions","organizations_url":"https://api.github.com/users/cocoy/orgs","repos_url":"https://api.github.com/users/cocoy/repos","events_url":"https://api.github.com/users/cocoy/events{/privacy}","received_events_url":"https://api.github.com/users/cocoy/received_events","type":"User","site_admin":false},"body":"Trying to fix parallelizing elasticluster stop #321 ","created_at":"2016-10-15T11:04:30Z","updated_at":"2016-10-24T14:40:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c7c4618e4943262f5fcd5e4e4a85060cf9961a34","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/324/commits","review_comments_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/324/comments","review_comment_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/comments{/number}","comments_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/issues/324/comments","statuses_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/statuses/5687d1a7da712e7aa98363f1ce2762db4858d58d","head":{"label":"cocoy:parallelizing_stop","ref":"parallelizing_stop","sha":"5687d1a7da712e7aa98363f1ce2762db4858d58d","user":{"login":"cocoy","id":32607,"avatar_url":"https://avatars.githubusercontent.com/u/32607?v=3","gravatar_id":"","url":"https://api.github.com/users/cocoy","html_url":"https://github.com/cocoy","followers_url":"https://api.github.com/users/cocoy/followers","following_url":"https://api.github.com/users/cocoy/following{/other_user}","gists_url":"https://api.github.com/users/cocoy/gists{/gist_id}","starred_url":"https://api.github.com/users/cocoy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cocoy/subscriptions","organizations_url":"https://api.github.com/users/cocoy/orgs","repos_url":"https://api.github.com/users/cocoy/repos","events_url":"https://api.github.com/users/cocoy/events{/privacy}","received_events_url":"https://api.github.com/users/cocoy/received_events","type":"User","site_admin":false},"repo":{"id":70783700,"name":"elasticluster","full_name":"cocoy/elasticluster","owner":{"login":"cocoy","id":32607,"avatar_url":"https://avatars.githubusercontent.com/u/32607?v=3","gravatar_id":"","url":"https://api.github.com/users/cocoy","html_url":"https://github.com/cocoy","followers_url":"https://api.github.com/users/cocoy/followers","following_url":"https://api.github.com/users/cocoy/following{/other_user}","gists_url":"https://api.github.com/users/cocoy/gists{/gist_id}","starred_url":"https://api.github.com/users/cocoy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cocoy/subscriptions","organizations_url":"https://api.github.com/users/cocoy/orgs","repos_url":"https://api.github.com/users/cocoy/repos","events_url":"https://api.github.com/users/cocoy/events{/privacy}","received_events_url":"https://api.github.com/users/cocoy/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cocoy/elasticluster","description":"Create clusters of VMs on the cloud and configure them with Ansible","fork":true,"url":"https://api.github.com/repos/cocoy/elasticluster","forks_url":"https://api.github.com/repos/cocoy/elasticluster/forks","keys_url":"https://api.github.com/repos/cocoy/elasticluster/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cocoy/elasticluster/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cocoy/elasticluster/teams","hooks_url":"https://api.github.com/repos/cocoy/elasticluster/hooks","issue_events_url":"https://api.github.com/repos/cocoy/elasticluster/issues/events{/number}","events_url":"https://api.github.com/repos/cocoy/elasticluster/events","assignees_url":"https://api.github.com/repos/cocoy/elasticluster/assignees{/user}","branches_url":"https://api.github.com/repos/cocoy/elasticluster/branches{/branch}","tags_url":"https://api.github.com/repos/cocoy/elasticluster/tags","blobs_url":"https://api.github.com/repos/cocoy/elasticluster/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cocoy/elasticluster/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cocoy/elasticluster/git/refs{/sha}","trees_url":"https://api.github.com/repos/cocoy/elasticluster/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cocoy/elasticluster/statuses/{sha}","languages_url":"https://api.github.com/repos/cocoy/elasticluster/languages","stargazers_url":"https://api.github.com/repos/cocoy/elasticluster/stargazers","contributors_url":"https://api.github.com/repos/cocoy/elasticluster/contributors","subscribers_url":"https://api.github.com/repos/cocoy/elasticluster/subscribers","subscription_url":"https://api.github.com/repos/cocoy/elasticluster/subscription","commits_url":"https://api.github.com/repos/cocoy/elasticluster/commits{/sha}","git_commits_url":"https://api.github.com/repos/cocoy/elasticluster/git/commits{/sha}","comments_url":"https://api.github.com/repos/cocoy/elasticluster/comments{/number}","issue_comment_url":"https://api.github.com/repos/cocoy/elasticluster/issues/comments{/number}","contents_url":"https://api.github.com/repos/cocoy/elasticluster/contents/{+path}","compare_url":"https://api.github.com/repos/cocoy/elasticluster/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cocoy/elasticluster/merges","archive_url":"https://api.github.com/repos/cocoy/elasticluster/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cocoy/elasticluster/downloads","issues_url":"https://api.github.com/repos/cocoy/elasticluster/issues{/number}","pulls_url":"https://api.github.com/repos/cocoy/elasticluster/pulls{/number}","milestones_url":"https://api.github.com/repos/cocoy/elasticluster/milestones{/number}","notifications_url":"https://api.github.com/repos/cocoy/elasticluster/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cocoy/elasticluster/labels{/name}","releases_url":"https://api.github.com/repos/cocoy/elasticluster/releases{/id}","deployments_url":"https://api.github.com/repos/cocoy/elasticluster/deployments","created_at":"2016-10-13T08:07:50Z","updated_at":"2016-10-13T08:07:52Z","pushed_at":"2016-10-20T11:29:18Z","git_url":"git://github.com/cocoy/elasticluster.git","ssh_url":"git@github.com:cocoy/elasticluster.git","clone_url":"https://github.com/cocoy/elasticluster.git","svn_url":"https://github.com/cocoy/elasticluster","homepage":"http://gc3-uzh-ch.github.io/elasticluster","size":2947,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"gc3-uzh-ch:master","ref":"master","sha":"878e3994bdfc0c60dad38e5a724df3f117d594bf","user":{"login":"gc3-uzh-ch","id":3878695,"avatar_url":"https://avatars.githubusercontent.com/u/3878695?v=3","gravatar_id":"","url":"https://api.github.com/users/gc3-uzh-ch","html_url":"https://github.com/gc3-uzh-ch","followers_url":"https://api.github.com/users/gc3-uzh-ch/followers","following_url":"https://api.github.com/users/gc3-uzh-ch/following{/other_user}","gists_url":"https://api.github.com/users/gc3-uzh-ch/gists{/gist_id}","starred_url":"https://api.github.com/users/gc3-uzh-ch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gc3-uzh-ch/subscriptions","organizations_url":"https://api.github.com/users/gc3-uzh-ch/orgs","repos_url":"https://api.github.com/users/gc3-uzh-ch/repos","events_url":"https://api.github.com/users/gc3-uzh-ch/events{/privacy}","received_events_url":"https://api.github.com/users/gc3-uzh-ch/received_events","type":"Organization","site_admin":false},"repo":{"id":8901369,"name":"elasticluster","full_name":"gc3-uzh-ch/elasticluster","owner":{"login":"gc3-uzh-ch","id":3878695,"avatar_url":"https://avatars.githubusercontent.com/u/3878695?v=3","gravatar_id":"","url":"https://api.github.com/users/gc3-uzh-ch","html_url":"https://github.com/gc3-uzh-ch","followers_url":"https://api.github.com/users/gc3-uzh-ch/followers","following_url":"https://api.github.com/users/gc3-uzh-ch/following{/other_user}","gists_url":"https://api.github.com/users/gc3-uzh-ch/gists{/gist_id}","starred_url":"https://api.github.com/users/gc3-uzh-ch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gc3-uzh-ch/subscriptions","organizations_url":"https://api.github.com/users/gc3-uzh-ch/orgs","repos_url":"https://api.github.com/users/gc3-uzh-ch/repos","events_url":"https://api.github.com/users/gc3-uzh-ch/events{/privacy}","received_events_url":"https://api.github.com/users/gc3-uzh-ch/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/gc3-uzh-ch/elasticluster","description":"Create clusters of VMs on the cloud and configure them with Ansible","fork":false,"url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster","forks_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/forks","keys_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/teams","hooks_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/hooks","issue_events_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/issues/events{/number}","events_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/events","assignees_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/assignees{/user}","branches_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/branches{/branch}","tags_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/tags","blobs_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/git/refs{/sha}","trees_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/statuses/{sha}","languages_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/languages","stargazers_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/stargazers","contributors_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/contributors","subscribers_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/subscribers","subscription_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/subscription","commits_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/commits{/sha}","git_commits_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/git/commits{/sha}","comments_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/comments{/number}","issue_comment_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/issues/comments{/number}","contents_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/contents/{+path}","compare_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/merges","archive_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/downloads","issues_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/issues{/number}","pulls_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls{/number}","milestones_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/milestones{/number}","notifications_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/labels{/name}","releases_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/releases{/id}","deployments_url":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/deployments","created_at":"2013-03-20T10:13:21Z","updated_at":"2016-10-15T22:09:15Z","pushed_at":"2016-10-20T11:29:19Z","git_url":"git://github.com/gc3-uzh-ch/elasticluster.git","ssh_url":"git@github.com:gc3-uzh-ch/elasticluster.git","clone_url":"https://github.com/gc3-uzh-ch/elasticluster.git","svn_url":"https://github.com/gc3-uzh-ch/elasticluster","homepage":"http://gc3-uzh-ch.github.io/elasticluster","size":3252,"stargazers_count":108,"watchers_count":108,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":61,"mirror_url":null,"open_issues_count":102,"forks":61,"open_issues":102,"watchers":108,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/324"},"html":{"href":"https://github.com/gc3-uzh-ch/elasticluster/pull/324"},"issue":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/issues/324"},"comments":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/issues/324/comments"},"review_comments":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/324/comments"},"review_comment":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/pulls/324/commits"},"statuses":{"href":"https://api.github.com/repos/gc3-uzh-ch/elasticluster/statuses/5687d1a7da712e7aa98363f1ce2762db4858d58d"}}}}
{"actor":{"display_login":"riccardomurri"}}