def import_file(self, import_file_path=None): skipped = 0 invalid_count = 0 if is_readable(import_file_path): import_entries = [] with open(import_file_path, "r") as infile: for line in infile: stripped_entry = line.strip() if (not stripped_entry) or (stripped_entry.startswith("#")): skipped += 1 else: line = line.partition("#")[0] line = line.rstrip() import_entry = HostsEntry.str_to_hostentry(line) if import_entry: import_entries.append(import_entry) else: invalid_count += 1 add_result = self.add(entries=import_entries) write_result = self.write() return { "result": "success", "skipped": skipped, "invalid_count": invalid_count, "add_result": add_result, "write_result": write_result, } else: return { "result": "failed", "message": "Cannot read: file {0}.".format(import_file_path), }
def get_user_data_from_file(self): file_name = self.lc_config.cloud_init if not file_name: return None if not utils.is_readable(file_name): print_msg("Can't open cloud-init file %s for reading" % file_name, bcolors.FAIL) return open(file_name, 'r').read()
def validate(self): """ Iterates over class attributes and verifies that they have been set during the config parsing or config writing process """ ok_missing = ['user_data', 'networks'] for obj in [ obj for obj in dir(self) if not obj.startswith('__') and obj not in ok_missing ]: if getattr(self, obj) is None: raise AttributeError("Config file parsing failed - key %s" " is missing or has no value in section" " 'launch-configuration'" " Try re-running with --create-config" % obj) if not isinstance(self.metadata, dict): raise AttributeError( utils.get_parse_error('metadata', 'launch-configuration', 'dictionary')) if not isinstance(self.image, str): raise AttributeError( utils.get_parse_error('image', 'launch-configuration', 'string')) if not isinstance(self.networks, list): raise AttributeError( utils.get_parse_error('networks', 'launch-configuration', 'list')) if not isinstance(self.skip_default_networks, bool): raise AttributeError( utils.get_parse_error('skip_default_networks', 'launch-configuration', 'boolean')) if self.cloud_init and self.cloud_init is not '': if not utils.is_readable(self.cloud_init): raise AttributeError("Config file validation failed cloud_init" " file not readable") self.config_drive = True else: self.cloud_init = None return True
def validate(self): """ Iterates over class attributes and verifies that they have been set during the config parsing or config writing process """ ok_missing = ['user_data', 'networks'] for obj in [obj for obj in dir(self) if not obj.startswith('__') and obj not in ok_missing]: if getattr(self, obj) is None: raise AttributeError("Config file parsing failed - key %s" " is missing or has no value in section" " 'launch-configuration'" " Try re-running with --create-config" % obj) if not isinstance(self.metadata, dict): raise AttributeError(utils.get_parse_error('metadata', 'launch-configuration', 'dictionary')) if not isinstance(self.image, str): raise AttributeError(utils.get_parse_error('image', 'launch-configuration', 'string')) if not isinstance(self.networks, list): raise AttributeError(utils.get_parse_error('networks', 'launch-configuration', 'list')) if not isinstance(self.skip_default_networks, bool): raise AttributeError(utils.get_parse_error('skip_default_networks', 'launch-configuration', 'boolean')) if self.cloud_init and self.cloud_init is not '': if not utils.is_readable(self.cloud_init): raise AttributeError( "Config file validation failed cloud_init" " file not readable") self.config_drive = True else: self.cloud_init = None return 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()