def terminate_cloud_infrastructure(cls, keyname, is_verbose): """Powers off all machines in the currently running AppScale deployment. Args: keyname: The name of the SSH keypair used for this AppScale deployment. is_verbose: A bool that indicates if we should print the commands executed to stdout. """ AppScaleLogger.log("About to terminate deployment and instances with " "keyname {0}. Press Ctrl-C to stop.".format(keyname)) # This sleep is here to allow a moment for user to Ctrl-C time.sleep(2) # get all the instance IDs for machines in our deployment agent = InfrastructureAgentFactory.create_agent( LocalState.get_infrastructure(keyname)) params = agent.get_cloud_params(keyname) params['IS_VERBOSE'] = is_verbose params['autoscale_agent'] = False # We want to terminate also the pending instances. pending = True _, _, instance_ids = agent.describe_instances(params, pending=pending) # If using persistent disks, unmount them and detach them before we blow # away the instances. nodes = LocalState.get_local_nodes_info(keyname) for node in nodes: if node.get('disk'): AppScaleLogger.log("Unmounting persistent disk at {0}". format(node['public_ip'])) cls.unmount_persistent_disk(node['public_ip'], keyname, is_verbose) agent.detach_disk(params, node['disk'], node['instance_id']) # terminate all the machines AppScaleLogger.log("Terminating instances spawned with keyname {0}" .format(keyname)) params[agent.PARAM_INSTANCE_IDS] = instance_ids agent.terminate_instances(params) # Delete the network configuration created for the cloud. agent.cleanup_state(params) # Cleanup the keyname files created on the local filesystem. # For GCE and Azure, the keypairs are created on the filesystem, # rather than the cloud. So we have to clean up afterwards. LocalState.cleanup_keyname(keyname)
def start_all_nodes(cls, options, node_layout): """ Starts all nodes in the designated public cloud. Args: options: A Namespace that includes parameters passed in by the user that define non-placement-strategy-related deployment options (e.g., keypair names, security group names). node_layout: The node layout of the system including roles. Returns: The node layout (dummy values in non-cloud deployments) corresponding to the nodes that were started. """ agent = InfrastructureAgentFactory.create_agent(options.infrastructure) params = agent.get_params_from_args(options) # If we have running instances under the current keyname, we try to # re-attach to them. If we have issue finding the locations file or the # IP of the head node, we throw an exception. login_ip = None public_ips, private_ips, instance_ids = agent.describe_instances(params) if public_ips: try: login_ip = LocalState.get_login_host(options.keyname) except (IOError, BadConfigurationException): raise AppScaleException( "Couldn't get login ip for running deployment with keyname" " {}.".format(options.keyname)) if login_ip not in public_ips: raise AppScaleException( "Couldn't recognize running instances for deployment with" " keyname {}.".format(options.keyname)) if login_ip in public_ips: AppScaleLogger.log("Reusing already running instances.") # Get the node_info from the locations JSON. node_info = LocalState.get_local_nodes_info(keyname=options.keyname) previous_node_list = node_layout.from_locations_json_list(node_info) # If this is None, the AppScalefile has been changed or the nodes could # not be matched up by roles/jobs. if previous_node_list is None: raise BadConfigurationException("AppScale does not currently support " "changes to AppScalefile or locations " "JSON between a down and an up. If " "you would like to " "change the node layout use " "down --terminate before an up.") node_layout.nodes = previous_node_list for node_index, node in enumerate(node_layout.nodes): try: index = instance_ids.index(node.instance_id) except ValueError: raise BadConfigurationException("Previous instance_id {} does not " "currently exist." .format(node.instance_id)) node_layout.nodes[node_index].public_ip = public_ips[index] node_layout.nodes[node_index].private_ip = private_ips[index] node_layout.nodes[node_index].instance_id = instance_ids[index] return node_layout agent.configure_instance_security(params) load_balancer_roles = {} instance_type_roles = {} for node in node_layout.get_nodes('load_balancer', True): load_balancer_roles.setdefault(node.instance_type, []).append(node) for node in node_layout.get_nodes('load_balancer', False): instance_type = instance_type_roles instance_type.setdefault(node.instance_type, []).append(node) spawned_instance_ids = [] for instance_type, load_balancer_nodes in load_balancer_roles.items(): # Copy parameters so we can modify the instance type. instance_type_params = params.copy() instance_type_params['instance_type'] = instance_type try: instance_ids, public_ips, private_ips = cls.spawn_nodes_in_cloud( agent, instance_type_params, count=len(load_balancer_nodes), load_balancer=True) except (AgentRuntimeException, BotoServerError): AppScaleLogger.warn("AppScale was unable to start the requested number " "of instances, attempting to terminate those that " "were started.") if len(spawned_instance_ids) > 0: AppScaleLogger.warn("Attempting to terminate those that were started.") cls.terminate_spawned_instances(spawned_instance_ids, agent, params) # Cleanup the keyname since it failed. LocalState.cleanup_keyname(options.keyname) # Re-raise the original exception. raise # Keep track of instances we have started. spawned_instance_ids.extend(instance_ids) for node_index, node in enumerate(load_balancer_nodes): index = node_layout.nodes.index(node) node_layout.nodes[index].public_ip = public_ips[node_index] node_layout.nodes[index].private_ip = private_ips[node_index] node_layout.nodes[index].instance_id = instance_ids[node_index] if options.static_ip: node = node_layout.head_node() agent.associate_static_ip(params, node.instance_id, options.static_ip) node.public_ip = options.static_ip AppScaleLogger.log("Static IP associated with head node.") AppScaleLogger.log("\nPlease wait for AppScale to prepare your machines " "for use. This can take few minutes.") for instance_type, nodes in instance_type_roles.items(): # Copy parameters so we can modify the instance type. instance_type_params = params.copy() instance_type_params['instance_type'] = instance_type try: _instance_ids, _public_ips, _private_ips = cls.spawn_nodes_in_cloud( agent, instance_type_params, count=len(nodes)) except (AgentRuntimeException, BotoServerError): AppScaleLogger.warn("AppScale was unable to start the requested number " "of instances, attempting to terminate those that " "were started.") if len(spawned_instance_ids) > 0: AppScaleLogger.warn("Attempting to terminate those that were started.") cls.terminate_spawned_instances(spawned_instance_ids, agent, params) # Cleanup the keyname since it failed. LocalState.cleanup_keyname(options.keyname) # Re-raise the original exception. raise # Keep track of instances we have started. spawned_instance_ids.extend(_instance_ids) for node_index, node in enumerate(nodes): index = node_layout.nodes.index(node) node_layout.nodes[index].public_ip = _public_ips[node_index] node_layout.nodes[index].private_ip = _private_ips[node_index] node_layout.nodes[index].instance_id = _instance_ids[node_index] return node_layout