def get_nodes_tasks(node_id): """ :param node_id: an integer number of node id :return: a set of deployment tasks for corresponding node """ tasks = set() ssh = SSHManager() result = ssh.execute_on_remote(ssh.admin_ip, "ls /var/log/astute") filenames = [filename.strip() for filename in result['stdout']] for filename in filenames: ssh.download_from_remote( ssh.admin_ip, destination="/var/log/astute/{0}".format(filename), target="/tmp/{0}".format(filename)) data = fileinput.FileInput( files=["/tmp/{0}".format(filename) for filename in filenames], openhook=fileinput.hook_compressed) for line in data: if "Task time summary" in line \ and "node {}".format(node_id) in line: # FIXME: define an exact search of task task_name = line.split("Task time summary: ")[1].split()[0] check = any([excluded_task in task_name for excluded_task in TASKS_BLACKLIST]) if check: continue tasks.add(task_name) return tasks
def store_astute_yaml_for_one_node(nailgun_node): ssh_manager = SSHManager() if 'roles' not in nailgun_node: return None errmsg = 'Downloading "{0}.yaml" from the {1} failed' msg = 'File "{0}.yaml" was downloaded from the {1}' nodename = nailgun_node['name'] ip = nailgun_node['ip'] for role in nailgun_node['roles']: filename = '{0}/{1}-{2}-{3}.yaml'.format(settings.LOGS_DIR, func_name, nodename, role) if not ssh_manager.isfile_on_remote(ip, '/etc/{0}.yaml'.format(role)): role = 'primary-' + role if ssh_manager.download_from_remote(ip, '/etc/{0}.yaml'.format(role), filename): logger.info(msg.format(role, nodename)) else: logger.error(errmsg.format(role, nodename)) if settings.DOWNLOAD_FACTS: fact_filename = re.sub(r'-\w*\.', '-facts.', filename) generate_facts(ip) if ssh_manager.download_from_remote(ip, '/tmp/facts.yaml', fact_filename): logger.info(msg.format('facts', nodename)) else: logger.error(errmsg.format('facts', nodename))
def get_nodes_tasks(node_id): """ :param node_id: an integer number of node id :return: a set of deployment tasks for corresponding node """ tasks = set() ssh = SSHManager() result = ssh.execute_on_remote(ssh.admin_ip, "ls /var/log/astute") filenames = [filename.strip() for filename in result['stdout']] for filename in filenames: ssh.download_from_remote( ssh.admin_ip, destination="/var/log/astute/{0}".format(filename), target="/tmp/{0}".format(filename)) data = fileinput.FileInput( files=["/tmp/{0}".format(filename) for filename in filenames], openhook=fileinput.hook_compressed) for line in data: if "Task time summary" in line \ and "node {}".format(node_id) in line: # FIXME: define an exact search of task task_name = line.split("Task time summary: ")[1].split()[0] check = any([excluded_task in task_name for excluded_task in TASKS_BLACKLIST]) if check: continue tasks.add(task_name) return tasks
def store_astute_yaml_for_one_node(nailgun_node): ssh_manager = SSHManager() if 'roles' not in nailgun_node: return None errmsg = 'Downloading "{0}.yaml" from the {1} failed' msg = 'File "{0}.yaml" was downloaded from the {1}' nodename = nailgun_node['name'] ip = nailgun_node['ip'] for role in nailgun_node['roles']: filename = '{0}/{1}-{2}-{3}.yaml'.format(settings.LOGS_DIR, func_name, nodename, role) if not ssh_manager.isfile_on_remote(ip, '/etc/{0}.yaml'.format(role)): role = 'primary-' + role if ssh_manager.download_from_remote(ip, '/etc/{0}.yaml'.format(role), filename): logger.info(msg.format(role, nodename)) else: logger.error(errmsg.format(role, nodename)) if settings.DOWNLOAD_FACTS: fact_filename = re.sub(r'-\w*\.', '-facts.', filename) generate_facts(ip) if ssh_manager.download_from_remote(ip, '/tmp/facts.yaml', fact_filename): logger.info(msg.format('facts', nodename)) else: logger.error(errmsg.format('facts', nodename))
class BaseActions(object): """BaseActions.""" # TODO documentation def __init__(self): self.ssh_manager = SSHManager() self.admin_ip = self.ssh_manager.admin_ip self.container = None def __repr__(self): klass, obj_id = type(self), hex(id(self)) container = getattr(self, 'container', None) return "[{klass}({obj_id}), container:{container}]".format( klass=klass, obj_id=obj_id, container=container) def execute_in_container(self, command, container=None, exit_code=None, stdin=None): if not container: container = self.container cmd = 'dockerctl shell {0} {1}'.format(container, command) if stdin is not None: cmd = 'echo "{0}" | {1}'.format(stdin, cmd) result = self.ssh_manager.execute(ip=self.admin_ip, cmd=cmd) if exit_code is not None: assert_equal(exit_code, result['exit_code'], ('Command {cmd} returned exit code "{e}", but ' 'expected "{c}". Output: {out}; {err} ').format( cmd=cmd, e=result['exit_code'], c=exit_code, out=result['stdout'], err=result['stderr'])) return ''.join(result['stdout']).strip() def copy_between_node_and_container(self, copy_from, copy_to): """ Copy files from/to container. :param copy_from: path to copy file from :param copy_to: path to copy file to For ex.: - to copy from container to master node use: copy_from = container:path_from copy_to = path_to - to copy from master node to container use: copy_from = path_from copy_to = container:path_to :return: Standard output from console """ cmd = 'dockerctl copy {0} {1}'.format(copy_from, copy_to) result = self.ssh_manager.execute(ip=self.admin_ip, cmd=cmd) assert_equal(0, result['exit_code'], ('Command copy returned exit code "{e}", but ' 'expected "0". Output: {out}; {err} ').format( cmd=cmd, e=result['exit_code'], out=result['stdout'], err=result['stderr'])) return ''.join(result['stdout']).strip() @property def is_container_ready(self): result = self.ssh_manager.execute( ip=self.admin_ip, cmd="timeout 5 dockerctl check {0}".format(self.container)) return result['exit_code'] == 0 def wait_for_ready_container(self, timeout=300): wait(lambda: self.is_container_ready, timeout=timeout) def put_value_to_local_yaml(self, old_file, new_file, element, value): """Changes content in old_file at element is given to the new value and creates new file with changed content :param old_file: a path to the file content from to be changed :param new_file: a path to the new file to ve created with new content :param element: tuple with path to element to be changed for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return: nothing """ with open(old_file, 'r') as f_old: yaml_dict = yaml.load(f_old) origin_yaml = yaml_dict for k in element[:-1]: yaml_dict = yaml_dict[k] yaml_dict[element[-1]] = value with open(new_file, 'w') as f_new: yaml.dump(origin_yaml, f_new, default_flow_style=False, default_style='"') def get_value_from_local_yaml(self, yaml_file, element): """Get a value of the element from the local yaml file :param str yaml_file: a path to the yaml file :param list element: list with path to element to be read for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return obj: value """ with open(yaml_file, 'r') as f_old: yaml_dict = yaml.load(f_old) for i, k in enumerate(element): try: yaml_dict = yaml_dict[k] except IndexError: raise IndexError( "Element {0} not found in the file {1}".format( element[:i + 1], f_old)) except KeyError: raise KeyError("Element {0} not found in the file {1}".format( element[:i + 1], f_old)) return yaml_dict def change_yaml_file_in_container(self, path_to_file, element, value, container=None): """Changes values in the yaml file stored at container There is no need to copy file manually :param path_to_file: absolutely path to the file :param element: list with path to the element be changed :param value: new value for element :param container: Container with file. By default it is nailgun :return: Nothing """ if not container: container = self.container old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid())) new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid())) self.copy_between_node_and_container( '{0}:{1}'.format(container, path_to_file), old_file) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=old_file, target=old_file) self.put_value_to_local_yaml(old_file, new_file, element, value) self.ssh_manager.upload_to_remote(ip=self.admin_ip, source=new_file, target=new_file) self.copy_between_node_and_container( new_file, '{0}:{1}'.format(container, path_to_file)) os.remove(old_file) os.remove(new_file) def get_value_from_yaml(self, path_to_file, element): """Get a value from the yaml file stored in container or on master node if self.container is None :param str path_to_file: absolutely path to the file :param list element: list with path to the element be changed :return obj: value """ if self.container: admin_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.copy_between_node_and_container( '{0}:{1}'.format(self.container, path_to_file), admin_tmp_file) else: admin_tmp_file = path_to_file host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=admin_tmp_file, target=host_tmp_file) value = self.get_value_from_local_yaml(host_tmp_file, element) os.remove(host_tmp_file) return value def put_value_to_yaml(self, path_to_file, element, value): """Put a value to the yaml file stored in container or on master node if self.container is None :param str path_to_file: absolutely path to the file :param list element: list with path to the element be changed :param value: new value for element :return: None """ if self.container: admin_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.copy_between_node_and_container( '{0}:{1}'.format(self.container, path_to_file), admin_tmp_file) else: admin_tmp_file = path_to_file host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=admin_tmp_file, target=host_tmp_file) self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element, value) self.ssh_manager.upload_to_remote(ip=self.admin_ip, source=host_tmp_file, target=admin_tmp_file) if self.container: self.copy_between_node_and_container( admin_tmp_file, '{0}:{1}'.format(self.container, path_to_file)) os.remove(host_tmp_file)
class BaseActions(object): """BaseActions.""" # TODO documentation def __init__(self): self.ssh_manager = SSHManager() self.admin_ip = self.ssh_manager.admin_ip def __repr__(self): klass, obj_id = type(self), hex(id(self)) return "[{klass}({obj_id})]".format( klass=klass, obj_id=obj_id) # TODO(kozhukalov): This method seems not needed and # can easily be replaced by using execute_on_remote # available in SSHManager (up to the type of return value) def execute(self, cmd, exit_code=None, stdin=None): if stdin is not None: cmd = 'echo "{0}" | {1}'.format(stdin, cmd) result = self.ssh_manager.execute( ip=self.admin_ip, cmd=cmd ) if exit_code is not None: assert_equal(exit_code, result['exit_code'], ('Command {cmd} returned exit code "{e}", but ' 'expected "{c}". Output: {out}; {err} ').format( cmd=cmd, e=result['exit_code'], c=exit_code, out=result['stdout'], err=result['stderr'] )) return ''.join(result['stdout']).strip() def restart_service(self, service): result = self.ssh_manager( ip=self.admin_ip, cmd="systemctl restart {0}".format(service)) return result['exit_code'] == 0 def put_value_to_local_yaml(self, old_file, new_file, element, value): """Changes content in old_file at element is given to the new value and creates new file with changed content :param old_file: a path to the file content from to be changed :param new_file: a path to the new file to ve created with new content :param element: tuple with path to element to be changed for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return: nothing """ with open(old_file, 'r') as f_old: yaml_dict = yaml.load(f_old) origin_yaml = yaml_dict for k in element[:-1]: yaml_dict = yaml_dict[k] yaml_dict[element[-1]] = value with open(new_file, 'w') as f_new: yaml.dump(origin_yaml, f_new, default_flow_style=False, default_style='"') def get_value_from_local_yaml(self, yaml_file, element): """Get a value of the element from the local yaml file :param str yaml_file: a path to the yaml file :param list element: list with path to element to be read for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return obj: value """ with open(yaml_file, 'r') as f_old: yaml_dict = yaml.load(f_old) for i, k in enumerate(element): try: yaml_dict = yaml_dict[k] except IndexError: raise IndexError("Element {0} not found in the file {1}" .format(element[: i + 1], f_old)) except KeyError: raise KeyError("Element {0} not found in the file {1}" .format(element[: i + 1], f_old)) return yaml_dict def change_remote_yaml(self, path_to_file, element, value): """Changes values in the yaml file stored There is no need to copy file manually :param path_to_file: absolute path to the file :param element: list with path to the element be changed :param value: new value for element :return: Nothing """ old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid())) new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=path_to_file, target=old_file ) self.put_value_to_local_yaml(old_file, new_file, element, value) self.ssh_manager.upload_to_remote( ip=self.admin_ip, source=new_file, target=path_to_file ) os.remove(old_file) os.remove(new_file) def get_value_from_remote_yaml(self, path_to_file, element): """Get a value from the yaml file stored on the master node :param str path_to_file: absolute path to the file :param list element: list with path to the element :return obj: value """ host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=path_to_file, target=host_tmp_file ) value = self.get_value_from_local_yaml(host_tmp_file, element) os.remove(host_tmp_file) return value def put_value_to_remote_yaml(self, path_to_file, element, value): """Put a value to the yaml file stored on the master node :param str path_to_file: absolute path to the file :param list element: list with path to the element be changed :param value: new value for element :return: None """ host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=path_to_file, target=host_tmp_file ) self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element, value) self.ssh_manager.upload_to_remote( ip=self.admin_ip, source=host_tmp_file, target=path_to_file ) os.remove(host_tmp_file)
class BaseActions(object): """BaseActions.""" # TODO documentation def __init__(self): self.ssh_manager = SSHManager() self.admin_ip = self.ssh_manager.admin_ip def __repr__(self): klass, obj_id = type(self), hex(id(self)) return "[{klass}({obj_id})]".format(klass=klass, obj_id=obj_id) def restart_service(self, service): result = self.ssh_manager.execute( ip=self.admin_ip, cmd="systemctl restart {0}".format(service)) return result['exit_code'] == 0 @staticmethod def put_value_to_local_yaml(old_file, new_file, element, value): """Changes content in old_file at element is given to the new value and creates new file with changed content :param old_file: a path to the file content from to be changed :param new_file: a path to the new file to ve created with new content :param element: tuple with path to element to be changed for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return: nothing """ with open(old_file, 'r') as f_old: yaml_dict = yaml.load(f_old) origin_yaml = yaml_dict for k in element[:-1]: yaml_dict = yaml_dict[k] yaml_dict[element[-1]] = value with open(new_file, 'w') as f_new: yaml.dump(origin_yaml, f_new, default_flow_style=False, default_style='"') @staticmethod def get_value_from_local_yaml(yaml_file, element): """Get a value of the element from the local yaml file :param str yaml_file: a path to the yaml file :param list element: list with path to element to be read for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return obj: value """ with open(yaml_file, 'r') as f_old: yaml_dict = yaml.load(f_old) for i, k in enumerate(element): try: yaml_dict = yaml_dict[k] except IndexError: raise IndexError( "Element {0} not found in the file {1}".format( element[:i + 1], f_old)) except KeyError: raise KeyError("Element {0} not found in the file {1}".format( element[:i + 1], f_old)) return yaml_dict def change_remote_yaml(self, path_to_file, element, value): """Changes values in the yaml file stored There is no need to copy file manually :param path_to_file: absolute path to the file :param element: list with path to the element be changed :param value: new value for element :return: Nothing """ old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid())) new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=path_to_file, target=old_file) self.put_value_to_local_yaml(old_file, new_file, element, value) self.ssh_manager.upload_to_remote(ip=self.admin_ip, source=new_file, target=path_to_file) os.remove(old_file) os.remove(new_file) def get_value_from_remote_yaml(self, path_to_file, element): """Get a value from the yaml file stored on the master node :param str path_to_file: absolute path to the file :param list element: list with path to the element :return obj: value """ host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=path_to_file, target=host_tmp_file) value = self.get_value_from_local_yaml(host_tmp_file, element) os.remove(host_tmp_file) return value def put_value_to_remote_yaml(self, path_to_file, element, value): """Put a value to the yaml file stored on the master node :param str path_to_file: absolute path to the file :param list element: list with path to the element be changed :param value: new value for element :return: None """ host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=path_to_file, target=host_tmp_file) self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element, value) self.ssh_manager.upload_to_remote(ip=self.admin_ip, source=host_tmp_file, target=path_to_file) os.remove(host_tmp_file)
class BaseActions(object): """BaseActions.""" # TODO documentation def __init__(self): self.ssh_manager = SSHManager() self.admin_ip = self.ssh_manager.admin_ip self.container = None def __repr__(self): klass, obj_id = type(self), hex(id(self)) container = getattr(self, 'container', None) return "[{klass}({obj_id}), container:{container}]".format( klass=klass, obj_id=obj_id, container=container) def execute_in_container(self, command, container=None, exit_code=None, stdin=None): if not container: container = self.container cmd = 'dockerctl shell {0} {1}'.format(container, command) if stdin is not None: cmd = 'echo "{0}" | {1}'.format(stdin, cmd) result = self.ssh_manager.execute( ip=self.admin_ip, cmd=cmd ) if exit_code is not None: assert_equal(exit_code, result['exit_code'], ('Command {cmd} returned exit code "{e}", but ' 'expected "{c}". Output: {out}; {err} ').format( cmd=cmd, e=result['exit_code'], c=exit_code, out=result['stdout'], err=result['stderr'] )) return ''.join(result['stdout']).strip() def copy_between_node_and_container(self, copy_from, copy_to): """ Copy files from/to container. :param copy_from: path to copy file from :param copy_to: path to copy file to For ex.: - to copy from container to master node use: copy_from = container:path_from copy_to = path_to - to copy from master node to container use: copy_from = path_from copy_to = container:path_to :return: Standard output from console """ cmd = 'dockerctl copy {0} {1}'.format(copy_from, copy_to) result = self.ssh_manager.execute( ip=self.admin_ip, cmd=cmd ) assert_equal(0, result['exit_code'], ('Command copy returned exit code "{e}", but ' 'expected "0". Output: {out}; {err} ').format( cmd=cmd, e=result['exit_code'], out=result['stdout'], err=result['stderr'])) return ''.join(result['stdout']).strip() @property def is_container_ready(self): result = self.ssh_manager.execute( ip=self.admin_ip, cmd="timeout 5 dockerctl check {0}".format(self.container) ) return result['exit_code'] == 0 def wait_for_ready_container(self, timeout=300): wait(lambda: self.is_container_ready, timeout=timeout) def put_value_to_local_yaml(self, old_file, new_file, element, value): """Changes content in old_file at element is given to the new value and creates new file with changed content :param old_file: a path to the file content from to be changed :param new_file: a path to the new file to ve created with new content :param element: tuple with path to element to be changed for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return: nothing """ with open(old_file, 'r') as f_old: yaml_dict = yaml.load(f_old) origin_yaml = yaml_dict for k in element[:-1]: yaml_dict = yaml_dict[k] yaml_dict[element[-1]] = value with open(new_file, 'w') as f_new: yaml.dump(origin_yaml, f_new, default_flow_style=False, default_style='"') def get_value_from_local_yaml(self, yaml_file, element): """Get a value of the element from the local yaml file :param str yaml_file: a path to the yaml file :param list element: list with path to element to be read for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return obj: value """ with open(yaml_file, 'r') as f_old: yaml_dict = yaml.load(f_old) for i, k in enumerate(element): try: yaml_dict = yaml_dict[k] except IndexError: raise IndexError("Element {0} not found in the file {1}" .format(element[: i + 1], f_old)) except KeyError: raise KeyError("Element {0} not found in the file {1}" .format(element[: i + 1], f_old)) return yaml_dict def change_yaml_file_in_container( self, path_to_file, element, value, container=None): """Changes values in the yaml file stored at container There is no need to copy file manually :param path_to_file: absolutely path to the file :param element: list with path to the element be changed :param value: new value for element :param container: Container with file. By default it is nailgun :return: Nothing """ if not container: container = self.container old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid())) new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid())) self.copy_between_node_and_container( '{0}:{1}'.format(container, path_to_file), old_file) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=old_file, target=old_file ) self.put_value_to_local_yaml(old_file, new_file, element, value) self.ssh_manager.upload_to_remote( ip=self.admin_ip, source=new_file, target=new_file ) self.copy_between_node_and_container( new_file, '{0}:{1}'.format(container, path_to_file)) os.remove(old_file) os.remove(new_file) def get_value_from_yaml(self, path_to_file, element): """Get a value from the yaml file stored in container or on master node if self.container is None :param str path_to_file: absolutely path to the file :param list element: list with path to the element be changed :return obj: value """ if self.container: admin_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.copy_between_node_and_container( '{0}:{1}'.format(self.container, path_to_file), admin_tmp_file) else: admin_tmp_file = path_to_file host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=admin_tmp_file, target=host_tmp_file ) value = self.get_value_from_local_yaml(host_tmp_file, element) os.remove(host_tmp_file) return value def put_value_to_yaml(self, path_to_file, element, value): """Put a value to the yaml file stored in container or on master node if self.container is None :param str path_to_file: absolutely path to the file :param list element: list with path to the element be changed :param value: new value for element :return: None """ if self.container: admin_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.copy_between_node_and_container( '{0}:{1}'.format(self.container, path_to_file), admin_tmp_file) else: admin_tmp_file = path_to_file host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=admin_tmp_file, target=host_tmp_file ) self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element, value) self.ssh_manager.upload_to_remote( ip=self.admin_ip, source=host_tmp_file, target=admin_tmp_file ) if self.container: self.copy_between_node_and_container( admin_tmp_file, '{0}:{1}'.format(self.container, path_to_file)) os.remove(host_tmp_file)
class BaseActions(object): """BaseActions.""" # TODO documentation def __init__(self): self.ssh_manager = SSHManager() self.admin_ip = self.ssh_manager.admin_ip def __repr__(self): klass, obj_id = type(self), hex(id(self)) return "[{klass}({obj_id})]".format( klass=klass, obj_id=obj_id) def restart_service(self, service): result = self.ssh_manager.execute( ip=self.admin_ip, cmd="systemctl restart {0}".format(service)) return result['exit_code'] == 0 @staticmethod def put_value_to_local_yaml(old_file, new_file, element, value): """Changes content in old_file at element is given to the new value and creates new file with changed content :param old_file: a path to the file content from to be changed :param new_file: a path to the new file to ve created with new content :param element: tuple with path to element to be changed for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return: nothing """ with open(old_file, 'r') as f_old: yaml_dict = yaml.load(f_old) origin_yaml = yaml_dict for k in element[:-1]: yaml_dict = yaml_dict[k] yaml_dict[element[-1]] = value with open(new_file, 'w') as f_new: yaml.dump(origin_yaml, f_new, default_flow_style=False, default_style='"') @staticmethod def get_value_from_local_yaml(yaml_file, element): """Get a value of the element from the local yaml file :param str yaml_file: a path to the yaml file :param list element: list with path to element to be read for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return obj: value """ with open(yaml_file, 'r') as f_old: yaml_dict = yaml.load(f_old) for i, k in enumerate(element): try: yaml_dict = yaml_dict[k] except IndexError: raise IndexError("Element {0} not found in the file {1}" .format(element[: i + 1], f_old)) except KeyError: raise KeyError("Element {0} not found in the file {1}" .format(element[: i + 1], f_old)) return yaml_dict def change_remote_yaml(self, path_to_file, element, value): """Changes values in the yaml file stored There is no need to copy file manually :param path_to_file: absolute path to the file :param element: list with path to the element be changed :param value: new value for element :return: Nothing """ old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid())) new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=path_to_file, target=old_file ) self.put_value_to_local_yaml(old_file, new_file, element, value) self.ssh_manager.upload_to_remote( ip=self.admin_ip, source=new_file, target=path_to_file ) os.remove(old_file) os.remove(new_file) def get_value_from_remote_yaml(self, path_to_file, element): """Get a value from the yaml file stored on the master node :param str path_to_file: absolute path to the file :param list element: list with path to the element :return obj: value """ host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=path_to_file, target=host_tmp_file ) value = self.get_value_from_local_yaml(host_tmp_file, element) os.remove(host_tmp_file) return value def put_value_to_remote_yaml(self, path_to_file, element, value): """Put a value to the yaml file stored on the master node :param str path_to_file: absolute path to the file :param list element: list with path to the element be changed :param value: new value for element :return: None """ host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote( ip=self.admin_ip, destination=path_to_file, target=host_tmp_file ) self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element, value) self.ssh_manager.upload_to_remote( ip=self.admin_ip, source=host_tmp_file, target=path_to_file ) os.remove(host_tmp_file)
class BaseActions(object): """BaseActions.""" # TODO documentation def __init__(self): self.ssh_manager = SSHManager() self.admin_ip = self.ssh_manager.admin_ip def __repr__(self): klass, obj_id = type(self), hex(id(self)) return "[{klass}({obj_id})]".format(klass=klass, obj_id=obj_id) # TODO(kozhukalov): This method seems not needed and # can easily be replaced by using execute_on_remote # available in SSHManager (up to the type of return value) def execute(self, cmd, exit_code=None, stdin=None): if stdin is not None: cmd = 'echo "{0}" | {1}'.format(stdin, cmd) result = self.ssh_manager.execute(ip=self.admin_ip, cmd=cmd) if exit_code is not None: assert_equal(exit_code, result['exit_code'], ('Command {cmd} returned exit code "{e}", but ' 'expected "{c}". Output: {out}; {err} ').format( cmd=cmd, e=result['exit_code'], c=exit_code, out=result['stdout'], err=result['stderr'])) return ''.join(result['stdout']).strip() def restart_service(self, service): result = self.ssh_manager(ip=self.admin_ip, cmd="systemctl restart {0}".format(service)) return result['exit_code'] == 0 def put_value_to_local_yaml(self, old_file, new_file, element, value): """Changes content in old_file at element is given to the new value and creates new file with changed content :param old_file: a path to the file content from to be changed :param new_file: a path to the new file to ve created with new content :param element: tuple with path to element to be changed for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return: nothing """ with open(old_file, 'r') as f_old: yaml_dict = yaml.load(f_old) origin_yaml = yaml_dict for k in element[:-1]: yaml_dict = yaml_dict[k] yaml_dict[element[-1]] = value with open(new_file, 'w') as f_new: yaml.dump(origin_yaml, f_new, default_flow_style=False, default_style='"') def get_value_from_local_yaml(self, yaml_file, element): """Get a value of the element from the local yaml file :param str yaml_file: a path to the yaml file :param list element: list with path to element to be read for example: ['root_elem', 'first_elem', 'target_elem'] if there are a few elements with equal names use integer to identify which element should be used :return obj: value """ with open(yaml_file, 'r') as f_old: yaml_dict = yaml.load(f_old) for i, k in enumerate(element): try: yaml_dict = yaml_dict[k] except IndexError: raise IndexError( "Element {0} not found in the file {1}".format( element[:i + 1], f_old)) except KeyError: raise KeyError("Element {0} not found in the file {1}".format( element[:i + 1], f_old)) return yaml_dict def change_remote_yaml(self, path_to_file, element, value): """Changes values in the yaml file stored There is no need to copy file manually :param path_to_file: absolute path to the file :param element: list with path to the element be changed :param value: new value for element :return: Nothing """ old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid())) new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=path_to_file, target=old_file) self.put_value_to_local_yaml(old_file, new_file, element, value) self.ssh_manager.upload_to_remote(ip=self.admin_ip, source=new_file, target=path_to_file) os.remove(old_file) os.remove(new_file) def get_value_from_remote_yaml(self, path_to_file, element): """Get a value from the yaml file stored on the master node :param str path_to_file: absolute path to the file :param list element: list with path to the element :return obj: value """ host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=path_to_file, target=host_tmp_file) value = self.get_value_from_local_yaml(host_tmp_file, element) os.remove(host_tmp_file) return value def put_value_to_remote_yaml(self, path_to_file, element, value): """Put a value to the yaml file stored on the master node :param str path_to_file: absolute path to the file :param list element: list with path to the element be changed :param value: new value for element :return: None """ host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid())) self.ssh_manager.download_from_remote(ip=self.admin_ip, destination=path_to_file, target=host_tmp_file) self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element, value) self.ssh_manager.upload_to_remote(ip=self.admin_ip, source=host_tmp_file, target=path_to_file) os.remove(host_tmp_file)