def check_and_confirm_change(self, diffs): """ Checks whether there are any changes detected between running config and config file, and prompts whether to update the running config or not """ if not diffs: return False return utils.ask_str("Do you want to update the running" " config to match the config file? (y/n): ", yesno=True)
def write_config(config, pyrax): """ Prompt for missing keys in the config file and writes a new one out """ config.parse_config() try: if config.lc_config.validate() and \ config.as_config.validate() and \ config.as_config.id: utils.print_msg( "Config defined in %s passes validation." " Checking for misconfiguration and missing" " optional keys.." % (config.config_file), bcolors.OKGREEN) except AttributeError: pass ## # Write [autoscale] config ## if not config.as_config.id: group = utils.get_object_from_list(pyrax.autoscale, "group", create_new_option=True) if group is not None: config.set_config_option('autoscale', 'id', group) if not config.as_config.name: group_name = utils.ask_str("Name of autoscale_group: ") config.set_config_option('autoscale', 'name', group_name) if not isinstance(config.as_config.scale_up, int): scale_up = utils.ask_integer( "Number of servers to scale up by when triggered: ") config.set_config_option('autoscale', 'scale_up', scale_up) if not isinstance(config.as_config.scale_down, int): scale_down = utils.ask_integer( "Number of servers to scale down by when triggered: ") config.set_config_option('autoscale', 'scale_down', scale_down) if not isinstance(config.as_config.max_entities, int): max_entities = utils.ask_integer( "Max number of servers to scale up to (max_entities): ") config.set_config_option('autoscale', 'max_entities', max_entities) if not isinstance(config.as_config.min_entities, int): max_entities = config.as_config.max_entities min_entities = utils.ask_integer( "Never scale down below this number of servers (min_entities): ") if min_entities > max_entities: print_msg( "min_entities must be smaller than or equal" "to max_entities (%d)" % max_entities, bcolors.FAIL) min_entities = utils.ask_integer( "Never scale down below this " "number of servers" " (min_entities): ", allowed_input=xrange(0, max_entities)) config.set_config_option('autoscale', 'min_entities', min_entities) if not isinstance(config.as_config.cooldown, int): cooldown = utils.ask_integer( "Do not process scale event more frequent than" " this (cooldown, seconds): ") config.set_config_option('autoscale', 'cooldown', cooldown) ## # Write [launch-config] config ## if not config.lc_config.image: image = utils.get_object_from_list(pyrax.images, "image") config.set_config_option('launch-configuration', 'image', image) if not config.lc_config.flavor: flavor = utils.get_object_from_list(pyrax.cloudservers.flavors, "flavor") config.set_config_option('launch-configuration', 'flavor', flavor) if not config.lc_config.key_name: key_name = utils.get_object_from_list(pyrax.cloudservers.keypairs, "ssh-key to add to" " /root/.ssh/authorized_keys on" " the servers", create_new_option=True) if key_name is None: key_name = utils.add_new_key(pyrax) config.set_config_option('launch-configuration', 'key_name', key_name) if not config.lc_config.name: name = utils.ask_str("Server name (note that an 11 character suffix" " will be added to this name): ") config.set_config_option('launch-configuration', 'name', name) if config.get('launch-configuration', 'cloud_init') is None: print("When servers are booted up, the contents of the cloud-init" " script will be executed on the server. This is a way to" " install and configure the software the machine needs" " in order to serve its purpose.\n" "To use the default - input: templates/cloud-init.yml.j2") cloud_init = utils.ask_file("Path to cloud-init script: ") config.set_config_option('launch-configuration', 'cloud_init', cloud_init) if not isinstance(config.lc_config.networks, list): networks = [] utils.print_msg( "Supply one or more networks you wish to" "attach the cloud servers to", bcolors.QUESTION) while True: network = utils.get_object_from_list(pyrax.cloud_networks, "network", quit_option=True) if network and network not in networks: networks.append(str(network)) elif network: pass else: break config.set_config_option('launch-configuration', 'networks', networks) if not config.get('launch-configuration', 'skip_default_networks'): print("By default, the launch config will contain the default" " networks (PublicNet and ServiceNet). You can optionally" " disable these, but some Rackspace services will not function" " properly without them, and they are obligatory on Managed" " service levels") keep = utils.ask_str("Keep default networks? (y/n): ", yesno=True) if keep: config.set_config_option('launch-configuration', 'skip_default_networks', False) else: config.set_config_option('launch-configuration', 'skip_default_networks', True) if not config.get('launch-configuration', 'disk_config'): disk_config = utils.ask_str( "Disk config method (AUTO or MANUAL): ", allowed_input=['AUTO', 'MANUAL', 'auto', 'manual']) config.set_config_option('launch-configuration', 'disk_config', disk_config.upper()) ## # Write [rax-autoscaler] config ## if not isinstance(config.ras_config.load_balancers, list): load_balancers = [] utils.print_msg( "Supply one or more load balancers you wish to" " attach the cloud servers to", bcolors.QUESTION) while True: load_balancer = utils.get_object_from_list( pyrax.cloud_loadbalancers, "load balancer", quit_option=True) if load_balancer and load_balancer not in load_balancers: load_balancers.append(load_balancer) elif load_balancer: pass else: break config.set_config_option('rax-autoscaler', 'load_balancers', load_balancers) if not isinstance(config.ras_config.num_static_servers, int): num_static_servers = utils.ask_integer( "How many nodes in the load balancer are" " not part of the scaling group? (0 for none): ") config.set_config_option('rax-autoscaler', 'num_static_servers', num_static_servers) if not isinstance(config.ras_config.private_key, str) or \ not utils.is_readable(config.ras_config.private_key): print("When scaled up, the servers need to log in to the admin server" " in order to download the playbook, or perform other tasks as" " laid out in the cloud-init template.\nSupply a private key" " which can be used to log in as the user 'autoscale' on the" " admin server") private_key = utils.ask_file("Private key to inject" " into /root/.ssh/id_rsa on servers: ") config.set_config_option('rax-autoscaler', 'private_key', private_key) if not isinstance(config.ras_config.admin_server, str): admin_server = utils.ask_str("IP or host-name of admin server to" " download playbook from: ") config.set_config_option('rax-autoscaler', 'admin_server', admin_server) # Re-parse the file on-disk and validate config.parse_config() config.validate()
def main(): parser = argparse.ArgumentParser('Set up and manage autoscale groups') parser.add_argument('--no-create-config', required=False, action="store_true", help='Fail rather than prompt for' ' missing config variables') parser.add_argument('--config-file', type=str, default='/opt/autoscale/autoscaler.ini', help='Path to config file (default' ' /opt/autoscale/autoscaler.ini)') args = parser.parse_args() """ We need to parse the config file first of all, since we need a pyrax client for creating and further parsing the config file we require a minimal config with at least cloud credentials in it """ config = utils.config(args.config_file, credentials_only=True) username, api_key, region = config.get_credentials() pyrax.set_setting('identity_type', 'rackspace') pyrax.set_setting('region', region) pyrax.set_credentials(username, api_key) if not args.no_create_config: create_config.write_config(config, pyrax) # Re-read config if changed and run through validation config = utils.config(args.config_file) # Converts CSV user input to structures used by pyrax and names to IDs etc. utils.config_fixup(config) while True: try: auto_scale = autoscale.autoscale(config, pyrax) break except pyrax.exceptions.NotFound: question = (bcolors.FAIL + "You specified a scaling group" " with ID %s, which does not appear to exist on" " this account. Would you " " like to create it? (y/n): " % ( config.as_config.id) + bcolors.ENDC) if not utils.ask_str(question, yesno=True): exit(0) else: # If given an empty ID, __init__ in autoscale will create a # group config.as_config.id = None except Exception: raise scale_down = auto_scale.get_scale_down_policy() scale_up = auto_scale.get_scale_up_policy() config.set_config_option('rax-autoscaler', 'scale_up_webhook', auto_scale.get_webhook_url(scale_up)) config.set_config_option('rax-autoscaler', 'scale_down_webhook', auto_scale.get_webhook_url(scale_down)) config.set_config_option('rax-autoscaler', 'scale_up_policy', auto_scale.get_scale_up_policy().id) config.set_config_option('rax-autoscaler', 'scale_down_policy', auto_scale.get_scale_down_policy().id) config.set_config_option('autoscale', 'id', auto_scale.get_id()) create_config.generate_rax_as_config(config)