def install_with_pip(package_name): ''' Calls pip install --user <package_name>. ''' log = logger.logger_for_me(install_with_pip) my_pip = detect_pip_version() cmd = '{} install --user {}'.format(my_pip, package_name) log.debug('Calling: >>{}<<'.format(cmd)) runit.execute(cmd, logger=log, log_level=logging.INFO)
def deploy(self, compose_definition): ''' Calls docker-compose with the contents of a compose file as input. ''' # save definition in file fs_util.create_dir_dont_complain(self.compose_path) definition_file = os.path.join(self.compose_path, 'docker-cluster.yml') with open(definition_file, 'w') as df: df.write(compose_definition) # call docker-compose command, should pick up the created file # note: apparently, using docker-compose.yml and removing '-f' fails to # to acknowledge the --force-recreate option # cmd = 'docker-compose --no-ansi -f docker-cluster.yml up -d --force-recreate' run = runit.execute(cmd, cwd=self.compose_path, env=os.environ) # always show the output of the docker-compose call print(run[1]) print(run[0]) if run[2] or run[0]: # return code is different than 0, something went wrong raise ComposeFailure('docker-compose command failed, check output')
def ensure_docker_compose(): ''' Looks for docker_compose in PATH. If the executable is not found, it will try to download it from the docker-compose repository. Exits normally if successful, raises ValueError if the executable cannot be downloaded. ''' log = logger.logger_for_me(ensure_docker_package) # check for docker-compose in PATH docker_compose_path = distutils.spawn.find_executable('docker-compose') if not docker_compose_path: # prepare to download it at user HOME server_url = docker_compose_url() output_dir = os.path.expanduser('~/.dcluster/bin') fs.create_dir_dont_complain(output_dir) # ensure download dir docker_compose_path = os.path.join(output_dir, 'docker-compose') # download if this fails then give up download.download_to_file_strict(server_url, docker_compose_path) # make it executable st = os.stat(docker_compose_path) os.chmod(docker_compose_path, st.st_mode | stat.S_IEXEC) # check for docker-compose version cmd = 'docker-compose -v' stdout, stderr, rc = runit.execute(cmd, env=os.environ) if 'docker-compose' not in stdout or rc != 0: err_msg = 'Not able to use docker-compose (rc={}):\n{}\n{}' raise ValueError(err_msg.format(rc, stdout, stderr)) log.info('Found docker-compose at: {}'.format(docker_compose_path))
def show_logs(self): ''' Prints the docker-compose logs to the screen. ''' # run docker-compose logs cmd = 'docker-compose -f docker-cluster.yml logs' run = runit.execute(cmd, cwd=self.compose_path, env=os.environ) print(run[0])
def a_container_has_exited(self): ''' Calls docker-compose ps to check if a container has already exited Returns True iff a container has exited, the output is saved as ps_stdout member variable. ''' # run docker-compose ps, save output cmd = 'docker-compose -f docker-cluster.yml ps' run = runit.execute(cmd, cwd=self.compose_path, env=os.environ) self.ps_stdout = run[0] # look for 'Exit' return 'Exit' in self.ps_stdout
def execute_playbook(playbook_file, inventory_file, extra_vars_list=[]): ''' Run an Ansible playbook using a cluster as the inventory nodes. This will call 'ansible-playbook' command and print the output. ''' logger = logging.getLogger() # the playbook will be run from the user's current directory, this ensures that files # passed at extra-vars will be found cwd = os.path.abspath(os.getcwd()) # build extra-vars as-is, supports a list (subsequent calls) extra_vars_str = '' for extra_vars in extra_vars_list: extra_vars_str = '--extra-vars "%s"' % extra_vars # (playbook_path, playbook_filename) = os.path.split(playbook_file) cmd = 'ansible-playbook -i %s %s %s' % (inventory_file, playbook_file, extra_vars_str) # cwd = playbook_path logger.debug('executing from %s >>%s<<' % (cwd, cmd)) runit.execute(cmd, cwd=cwd, logger=logger, log_level=logging.INFO)