def _ask_for_subnets(subnet_list): master_subnet_id = prompt_iterable("Master Subnet ID", subnet_list) compute_subnet_id = prompt_iterable("Compute Subnet ID", subnet_list, default_value=master_subnet_id) vpc_parameters = {"master_subnet_id": master_subnet_id} if master_subnet_id != compute_subnet_id: vpc_parameters["compute_subnet_id"] = compute_subnet_id return vpc_parameters
def _choose_network_configuration(cluster_config): if cluster_config.scheduler == "awsbatch": return PublicPrivateNetworkConfig() azs_for_head_node_type = get_supported_az_for_one_instance_type( cluster_config.head_node_instance_type) azs_for_compute_type = get_supported_az_for_one_instance_type( cluster_config.compute_instance_type) common_availability_zones = set(azs_for_head_node_type) & set( azs_for_compute_type) if not common_availability_zones: # Automate subnet creation only allows subnets to reside in a single az. # But user can bypass it by using manual subnets creation during configure or modify the config file directly. print( "Error: There is no single availability zone offering head node and compute in current region.\n" "To create your cluster, make sure you have a subnet for head node in {0}" ", and a subnet for compute nodes in {1}. Then run pcluster configure again" "and avoid using Automate VPC/Subnet creation.".format( azs_for_head_node_type, azs_for_compute_type)) print("Exiting...") sys.exit(1) target_type = prompt_iterable( "Network Configuration", options=[ configuration.value.config_type for configuration in NetworkConfiguration ], default_value=PublicPrivateNetworkConfig().config_type, ) network_configuration = next( configuration.value for configuration in NetworkConfiguration if configuration.value.config_type == target_type) network_configuration.availability_zones = common_availability_zones return network_configuration
def _create_vpc_parameters(vpc_section, scheduler, min_subnet_size, automate_vpc_creation=True): vpc_parameters = {} min_subnet_size = int(min_subnet_size) if automate_vpc_creation: vpc_parameters.update( automate_vpc_with_subnet_creation( _choose_network_configuration(scheduler), min_subnet_size)) else: vpc_and_subnets = _get_vpcs_and_subnets() vpc_list = vpc_and_subnets["vpc_list"] if not vpc_list: print( "There are no VPC for the given region. Starting automatic creation of VPC and subnets..." ) vpc_parameters.update( automate_vpc_with_subnet_creation( _choose_network_configuration(scheduler), min_subnet_size)) else: vpc_id = prompt_iterable("VPC ID", vpc_list, vpc_section.get_param_value("vpc_id")) vpc_parameters["vpc_id"] = vpc_id subnet_list = vpc_and_subnets["vpc_subnets"][vpc_id] if not subnet_list or (prompt("Automate Subnet creation? (y/n)", lambda x: x in ("y", "n"), default_value="y") == "y"): vpc_parameters.update( automate_subnet_creation( vpc_id, _choose_network_configuration(scheduler), min_subnet_size)) else: vpc_parameters.update(_ask_for_subnets(subnet_list)) return vpc_parameters
def prompt_os(self): """Ask for os, if necessary.""" if not self.is_aws_batch: self.base_os = prompt_iterable( "Operating System", get_supported_os_for_scheduler(self.scheduler), default_value=self.cluster_section.get_param_value("base_os"), )
def _create_vpc_parameters(vpc_section, cluster_config): vpc_parameters = {} min_subnet_size = int(cluster_config.max_cluster_size) automate_vpc_creation = prompt("Automate VPC creation? (y/n)", lambda x: x in ("y", "n"), default_value="n") == "y" if automate_vpc_creation: vpc_parameters.update( automate_vpc_with_subnet_creation( _choose_network_configuration(cluster_config), min_subnet_size)) else: vpc_and_subnets = _get_vpcs_and_subnets() vpc_list = vpc_and_subnets["vpc_list"] if not vpc_list: print( "There are no VPC for the given region. Starting automatic creation of VPC and subnets..." ) vpc_parameters.update( automate_vpc_with_subnet_creation( _choose_network_configuration(cluster_config), min_subnet_size)) else: default_vpc = vpc_section.get_param_value("vpc_id") vpc_id = prompt_iterable("VPC ID", vpc_list, default_value=default_vpc) vpc_parameters["vpc_id"] = vpc_id subnet_list = vpc_and_subnets["vpc_subnets"][vpc_id] qualified_head_node_subnets = _filter_subnets_offering_instance_type( subnet_list, cluster_config.head_node_instance_type) if cluster_config.scheduler != "awsbatch": qualified_compute_subnets = _filter_subnets_offering_instance_type( subnet_list, cluster_config.compute_instance_type) else: # Special case of awsbatch, where compute instance type is not specified qualified_compute_subnets = subnet_list if (not qualified_head_node_subnets or not qualified_compute_subnets or (prompt("Automate Subnet creation? (y/n)", lambda x: x in ("y", "n"), default_value="y") == "y")): # Start auto subnets creation in the absence of qualified subnets. # Otherwise, user selects between manual and automate subnets creation if not qualified_head_node_subnets or not qualified_compute_subnets: print( "There are no qualified subnets. Starting automatic creation of subnets..." ) vpc_parameters.update( automate_subnet_creation( vpc_id, _choose_network_configuration(cluster_config), min_subnet_size)) else: vpc_parameters.update( _ask_for_subnets(subnet_list, vpc_section, qualified_head_node_subnets, qualified_compute_subnets)) return vpc_parameters
def _prompt_for_subnet(default_subnet, all_subnets, qualified_subnets, message): total_omitted_subnets = len(all_subnets) - len(qualified_subnets) if total_omitted_subnets > 0: print("Note: {0} subnet(s) is/are not listed, " "because the instance type is not in their availability zone(s)". format(total_omitted_subnets)) return prompt_iterable(message, qualified_subnets, default_value=default_subnet)
def _choose_network_configuration(scheduler): if scheduler == "awsbatch": return PublicPrivateNetworkConfig() target_type = prompt_iterable( "Network Configuration", options=[ configuration.value.config_type for configuration in NetworkConfiguration ], default_value=PublicPrivateNetworkConfig().config_type, ) return next(configuration.value for configuration in NetworkConfiguration if configuration.value.config_type == target_type)
def _ask_for_subnets(subnet_list, vpc_section): available_subnets = [subnet_entry[0] for subnet_entry in subnet_list] default_master_subnet = vpc_section.get_param_value("master_subnet_id") master_subnet_id = prompt_iterable( "Master Subnet ID", subnet_list, default_value=default_master_subnet if default_master_subnet in available_subnets else None, ) default_compute_subnet = vpc_section.get_param_value("compute_subnet_id") compute_subnet_id = prompt_iterable( "Compute Subnet ID", subnet_list, default_value=(default_compute_subnet if default_compute_subnet in available_subnets else None) or master_subnet_id, ) vpc_parameters = {"master_subnet_id": master_subnet_id} if master_subnet_id != compute_subnet_id: vpc_parameters["compute_subnet_id"] = compute_subnet_id return vpc_parameters
def configure(args): # Check for invalid path (eg. a directory) if args.config_file and os.path.exists( args.config_file) and not os.path.isfile(args.config_file): error("Invalid configuration file path: {0}".format(args.config_file)) pcluster_config = PclusterConfig(config_file=args.config_file, fail_on_error=False, auto_refresh=False) # FIXME: Overriding HIT config files is currently not supported. if pcluster_config.cluster_model == ClusterModel.HIT: error( "Configuration in file {0} cannot be overwritten. Please specify a different file path" .format(pcluster_config.config_file)) if os.path.exists(pcluster_config.config_file): msg = "WARNING: Configuration file {0} will be overwritten." else: msg = "INFO: Configuration file {0} will be written." print(msg.format(pcluster_config.config_file)) print("Press CTRL-C to interrupt the procedure.\n\n") if not args.region: # Use built in boto regions as an available option available_regions = get_regions() default_region = pcluster_config.get_section("aws").get_param_value( "aws_region_name") aws_region_name = prompt_iterable("AWS Region ID", available_regions, default_value=default_region) # Set provided region into os environment for suggestions and validations from here on os.environ["AWS_DEFAULT_REGION"] = aws_region_name else: aws_region_name = args.region cluster_section = pcluster_config.get_section("cluster") global_config = pcluster_config.get_section("global") cluster_label = global_config.get_param_value("cluster_template") vpc_section = pcluster_config.get_section("vpc") vpc_label = vpc_section.label # Get the key name from the current region, if any available_keys = _get_keys() default_key = cluster_section.get_param_value("key_name") key_name = prompt_iterable("EC2 Key Pair Name", available_keys, default_value=default_key) scheduler = prompt_iterable( "Scheduler", get_supported_schedulers(), default_value=cluster_section.get_param_value("scheduler")) cluster_config = ClusterConfigureHelper(cluster_section, scheduler) cluster_config.prompt_os() cluster_config.prompt_cluster_size() cluster_config.prompt_instance_types() vpc_parameters = _create_vpc_parameters(vpc_section, cluster_config) # Here is the end of prompt. Code below assembles config and write to file cluster_parameters = {"key_name": key_name, "scheduler": scheduler} cluster_parameters.update(cluster_config.get_scheduler_parameters()) # Remove parameters from the past configuration that can conflict with the user's choices. _reset_config_params(cluster_section, cluster_config.get_parameters_to_reset()) _reset_config_params( vpc_section, ("compute_subnet_id", "use_public_ips", "compute_subnet_cidr")) # Update configuration values according to user's choices pcluster_config.region = aws_region_name cluster_section.label = cluster_label for param_key, param_value in cluster_parameters.items(): param = cluster_section.get_param(param_key) param.value = param.get_value_from_string(param_value) vpc_section.label = vpc_label for param_key, param_value in vpc_parameters.items(): param = vpc_section.get_param(param_key) param.value = param.get_value_from_string(param_value) # Update internal params according to provided parameters and enable auto-refresh before eventual hit conversion pcluster_config.refresh() pcluster_config.auto_refresh = True # Convert file if needed HitConverter(pcluster_config).convert(prepare_to_file=True) # Update config file by overriding changed settings pcluster_config.to_file() print("Configuration file written to {0}".format( pcluster_config.config_file)) print( "You can edit your configuration file or simply run 'pcluster create -c {0} cluster-name' " "to create your cluster".format(pcluster_config.config_file))
def configure(args): # Check for invalid path (eg. a directory) if args.config_file and os.path.exists( args.config_file) and not os.path.isfile(args.config_file): error("Invalid configuration file path: {0}".format(args.config_file)) pcluster_config = PclusterConfig(config_file=args.config_file, fail_on_error=False) if os.path.exists(pcluster_config.config_file): msg = "WARNING: Configuration file {0} will be overwritten." else: msg = "INFO: Configuration file {0} will be written." print(msg.format(pcluster_config.config_file)) print("Press CTRL-C to interrupt the procedure.\n\n") cluster_section = pcluster_config.get_section("cluster") global_config = pcluster_config.get_section("global") cluster_label = global_config.get_param_value("cluster_template") vpc_section = pcluster_config.get_section("vpc") vpc_label = vpc_section.label # Use built in boto regions as an available option available_regions = get_regions() default_region = pcluster_config.get_section("aws").get_param_value( "aws_region_name") aws_region_name = prompt_iterable( "AWS Region ID", available_regions, default_value=default_region if default_region in available_regions else None, ) # Set provided region into os environment for suggestions and validations from here on os.environ["AWS_DEFAULT_REGION"] = aws_region_name # Get the key name from the current region, if any available_keys = _get_keys() default_key = cluster_section.get_param_value("key_name") key_name = prompt_iterable( "EC2 Key Pair Name", available_keys, default_value=default_key if default_key in available_keys else None) scheduler = prompt_iterable( "Scheduler", get_supported_schedulers(), default_value=cluster_section.get_param_value("scheduler")) scheduler_handler = SchedulerHandler(cluster_section, scheduler) scheduler_handler.prompt_os() scheduler_handler.prompt_cluster_size() master_instance_type = prompt( "Master instance type", lambda x: x in get_supported_instance_types(), default_value=cluster_section.get_param_value("master_instance_type"), ) scheduler_handler.prompt_compute_instance_type() automate_vpc = prompt("Automate VPC creation? (y/n)", lambda x: x in ("y", "n"), default_value="n") == "y" vpc_parameters = _create_vpc_parameters(vpc_section, scheduler, scheduler_handler.max_cluster_size, automate_vpc_creation=automate_vpc) cluster_parameters = { "key_name": key_name, "scheduler": scheduler, "master_instance_type": master_instance_type } cluster_parameters.update(scheduler_handler.get_scheduler_parameters()) # Remove parameters from the past configuration that can conflict with the user's choices. _reset_config_params(cluster_section, scheduler_handler.get_parameters_to_reset()) _reset_config_params( vpc_section, ("compute_subnet_id", "use_public_ips", "compute_subnet_cidr")) # Update configuration values according to user's choices pcluster_config.region = aws_region_name cluster_section.label = cluster_label for param_key, param_value in cluster_parameters.items(): param = cluster_section.get_param(param_key) param.value = param.get_value_from_string(param_value) vpc_section.label = vpc_label for param_key, param_value in vpc_parameters.items(): param = vpc_section.get_param(param_key) param.value = param.get_value_from_string(param_value) # Update config file by overriding changed settings pcluster_config.to_file() print("Configuration file written to {0}".format( pcluster_config.config_file)) print( "You can edit your configuration file or simply run 'pcluster create -c {0} cluster-name' " "to create your cluster".format(pcluster_config.config_file))