def try_ssh(virtual_machine: VirtualMachine, retries: int = 10): """ Try to connect to a virtual machine using ssh :param virtual_machine: the virtual machine :param retries: the maximum of retries """ retry = 0 connected = False ssh = SSHClient() ssh.set_missing_host_key_policy(AutoAddPolicy()) ssh.load_system_host_keys() while retry < retries and not connected: try: logger.debug('Trying ssh connection to %s %s out of %s retries', virtual_machine.hostname, retry, retries) ssh.connect(virtual_machine.hostname, port=virtual_machine.ssh_port, username=virtual_machine.ssh_username, password=virtual_machine.ssh_password) connected = True except (BadHostKeyException, AuthenticationException, SSHException, socket.error): time.sleep(10) retry += 1 if not connected: raise Exception( '[{}] Unable to connect to the machine after {} tries'.format( virtual_machine.hostname, retry)) logger.info('Connection established to %s after %d out of %d retries', virtual_machine.name, retry, retries)
def _exec_command(command: str, path: str = '.'): """ Execute the command :param command: execute the given command in the project folder :return: """ logger.info("Execution of %s command", command) os.system("{} {}".format(command, path))
def invoke(self, ctx: click.Context): type_name = ctx.params.get('project_type') name = ctx.params.get('project') vcs_type = ctx.params.get('vcs') template = ctx.params.get('template') CreateCommand.validate_project_type(type_name) CreateCommand.validate_vcs_type(vcs_type) project_type = config.get('project_type').get(type_name) if vcs_type is None: vcs_config = None else: vcs_config = config.get('vcs').get(vcs_type) project = Project(name, project_type, vcs_config) self._create_folder(project=project) if template is not None: self._copy_template(project=project, template_name=template) repo_url = None repo_name = None vcs = None if vcs_config is not None: vcs = get_vcs(vcs_config=vcs_config) if vcs is not None: repo_url = vcs.create_project(project) repo_name = vcs.get_repository_name(project) gitignore_content = vcs.get_gitignore_template(project) if gitignore_content is not None: project.add_file('.gitignore', gitignore_content) project.add_file('README.md', '\n'.join([ repo_name, '===', 'This project have been generated with [darkanakin41/project-toolbox]' '(https://github.com/darkanakin41/project-toolbox)' ])) if repo_url is not None: self._init_git(project, repo_url) if vcs is not None and repo_name is not None: webbrowser.open('/'.join([vcs.get_base_url(), repo_name])) if project.type.virtual_machine is not None: self.start_virtual_machine(project.type.virtual_machine) if project.type.is_mutagened(): logger.info("Mutagen configuration detected") mutagen_helper = Manager() mutagen_helper.up(path=project.type.get_folder(), project=name) project.type.exec_commands(path=project.get_path())
def _create_folder(project: Project): """ Create the folder for the given project :param project: the project """ if project.exists(): logger.info('Project already exist, no need to create the folder') else: pathlib.Path(project.get_path()).mkdir(parents=True, exist_ok=True) logger.info('Project folder %s created', project.get_path())
def stop(self): if not self.status(output=False): logger.info('VM %s is down, nothing to do here', self.virtual_machine.name) return if not os.path.isfile(self.virtual_machine.path): logger.error('VM %s is not found on drive', self.virtual_machine.path) return os.popen('cd {} && "{}" halt'.format(self.virtual_machine.exec, self.virtual_machine.path)) logger.info('VM %s is now stopped', self.virtual_machine.name)
def status(self, output: bool = True): stream = os.popen('"{}" list nogui'.format(self.virtual_machine.exec)) command_output = stream.read() rows = command_output.split('\n') if output: if self.virtual_machine.path in rows: logger.info('VM %s is up', self.virtual_machine.name) else: logger.info('VM %s is down', self.virtual_machine.name) return self.virtual_machine.path in rows
def status(self, output: bool = True): stream = os.popen('"{}" global-status nogui'.format(self.virtual_machine.exec)) command_output = stream.read() rows = command_output.split('\n') status = filter(lambda row: self.virtual_machine.path.replace('\\', '/') in row and 'running' in row, rows) if output: if len(list(status)) == 1: logger.info('VM %s is up', self.virtual_machine.name) else: logger.info('VM %s is down', self.virtual_machine.name) return len(list(status)) == 1
def start(self): if self.status(output=False): logger.info('VM %s is up, nothing to do here', self.virtual_machine.name) return if not os.path.isfile(self.virtual_machine.path): logger.error('VM %s is not found on drive', self.virtual_machine.path) return os.popen('"{}" start "{}" nogui'.format(self.virtual_machine.exec, self.virtual_machine.path)) logger.info('VM %s is now started', self.virtual_machine.name)
def invoke(self, ctx: click.Context): name: str = ctx.params.get('project') virtual_machine: bool = ctx.params.get('vm') if not self.exists(name): logger.error('Unable to find %s path', name) sys.exit(1) project_type = self.detect_project_type() if project_type is None: logger.error('Unable to determine %s project type', name) sys.exit(1) logger.info('Project type detected for %s is %s', name, project_type.name) if project_type.is_mutagened(): logger.info("Mutagen configuration detected") mutagen_helper = Manager() mutagen_helper.down(path=project_type.get_folder(), project=name) logger.debug("Project virtual machine is %s", project_type.virtual_machine) if project_type.virtual_machine and virtual_machine: self.stop_virtual_machine(project_type.virtual_machine)
def invoke(self, ctx: click.Context): name: str = ctx.params.get('project') noexec: bool = ctx.params.get('noexec') if not StartCommand.exists(name): logger.error("Unable to find %s path", name) sys.exit(1) project_type = self.detect_project_type() if project_type is None: logger.error("Unable to determine %s project type", name) sys.exit(1) logger.debug("Project virtual machine is %s", project_type.virtual_machine) if project_type.virtual_machine: self.start_virtual_machine(project_type.virtual_machine) logger.info("Project type detected for %s is %s", name, project_type.name) if project_type.is_mutagened(): logger.info("Mutagen configuration detected") mutagen_helper = Manager() mutagen_helper.up(path=project_type.get_folder(), project=name) if not noexec: project_type.exec_commands(self.path(name))
def _init_git(project: Project, repo_url: str = None): """ Init the git repository in the folder :param repo_url: the url of the repository :return: """ try: Repo(project.get_path()) logger.info('This is already a git repository') return except InvalidGitRepositoryError: repo = Repo.init(project.get_path()) logger.info('Initialization of git repository') CreateCommand._update_git_config(project, repo) origin = None if repo_url is not None: try: origin = repo.remote('origin') logger.info('Retrieving the origin remote') except NoSectionError: origin = repo.create_remote('origin', repo_url) logger.info('Adding the remote origin %s', repo_url) if len(repo.untracked_files) > 0: repo.git.add('.') logger.info('Staging new files') if repo.is_dirty(): logger.info('Initial commit') repo.git.commit('-m "Initial commit"') if origin is not None: logger.info('Pushing files to remote') repo.git.push("--set-upstream", origin, repo.head.ref)