def start(self, min_nodes=None, max_concurrent_requests=0):
        """
        Starts up all the instances in the cloud.

        To speed things up, all
        instances are started in a seperate thread. To make sure
        ElastiCluster is not stopped during creation of an instance, it will
        overwrite the sigint handler. As soon as the last started instance
        is returned and saved to the repository, sigint is executed as usual.

        A VM instance is considered 'up and running' as soon as an SSH
        connection can be established. If the startup timeout is reached before
        all instances are started, ElastiCluster stops the cluster and
        terminates all VM instances.

        This method is blocking and might take some time depending on the
        amount of instances to start.

        :param min_nodes: minimum number of nodes to start in case the quota
                          is reached before all instances are up
        :type min_nodes: dict [node_kind] = number
        :param int max_concurrent_requests:
          Issue at most this number of requests to start
          VMs; if 1 or less, start nodes one at a time (sequentially).
          The special value ``0`` means run 4 threads for each available
          processor.
        """

        nodes = self.get_all_nodes()

        log.info(
            "Starting cluster nodes (timeout: %d seconds) ...",
            self.start_timeout)
        if max_concurrent_requests == 0:
            try:
                max_concurrent_requests = 4 * get_num_processors()
            except RuntimeError:
                log.warning(
                    "Cannot determine number of processors!"
                    " will start nodes sequentially...")
                max_concurrent_requests = 1
        if max_concurrent_requests > 1:
            nodes = self._start_nodes_parallel(nodes, max_concurrent_requests)
        else:
            nodes = self._start_nodes_sequentially(nodes)

        # checkpoint cluster state
        self.repository.save_or_update(self)

        not_started_nodes = self._check_starting_nodes(nodes, self.start_timeout)

        # now that all nodes are up, checkpoint cluster state again
        self.repository.save_or_update(self)

        # Try to connect to each node to gather IP addresses and SSH host keys
        started_nodes = nodes - not_started_nodes
        if not started_nodes:
            raise ClusterSizeError("No nodes could be started!")
        log.info(
            "Checking SSH connection to nodes (timeout: %d seconds) ...",
            self.start_timeout)
        self._gather_node_ip_addresses(
            started_nodes, self.start_timeout, self.ssh_probe_timeout)
        # It's possible that the node.connect() call updated the
        # `preferred_ip` attribute, so, let's save the cluster again.
        self.repository.save_or_update(self)

        # A lot of things could go wrong when starting the cluster.
        # Check that the minimum number of nodes within each groups is
        # reachable. Raise `ClusterSizeError()` if not.
        self._check_cluster_size(self._compute_min_nodes(min_nodes))
Starts up all the instances in the cloud.

        To speed things up, all
        instances are started in a seperate thread. To make sure
        ElastiCluster is not stopped during creation of an instance, it will
        overwrite the sigint handler. As soon as the last started instance
        is returned and saved to the repository, sigint is executed as usual.

        A VM instance is considered 'up and running' as soon as an SSH
        connection can be established. If the startup timeout is reached before
        all instances are started, ElastiCluster stops the cluster and
        terminates all VM instances.

        This method is blocking and might take some time depending on the
        amount of instances to start.

        :param min_nodes: minimum number of nodes to start in case the quota
                          is reached before all instances are up
        :type min_nodes: dict [node_kind] = number
        :param int max_concurrent_requests:
          Issue at most this number of requests to start
          VMs; if 1 or less, start nodes one at a time (sequentially).
          The special value ``0`` means run 4 threads for each available
          processor.