def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule login` and return a tuple. :param exit: (Unused) Provided to complete method signature. :return: Return a tuple of None, otherwise sys.exit on command failure. """ # get list of running hosts from state if self.molecule.state.hosts: hosts = [k for k, v in self.molecule.state.hosts.iteritems()] else: hosts = [] try: # Nowhere to login to if there is no running host. if len(hosts) == 0: raise base.InvalidHost('There are no running hosts.') # Check whether a host was specified. if self.command_args.get('host') is None: # One running host is perfect. Login to it. if len(hosts) == 1: hostname = hosts[0] # But too many hosts is trouble as well. else: message = ('There are {} running hosts. You can only ' 'login to one at a time.\n\n' 'Available hosts:\n{}'.format( len(hosts), '\n'.join(sorted(hosts)))) raise base.InvalidHost(message) else: # If the host was specified, try to use it. hostname = self.command_args.get('host') match = [x for x in hosts if x.startswith(hostname)] if len(match) == 0: raise subprocess.CalledProcessError(1, None) elif len(match) != 1: # If there are multiple matches, but one of them is an # exact string match, assume this is the one they're # looking for and use it if hostname in match: match = [ hostname, ] else: message = ("There are {} hosts that match '{}'. You " 'can only login to one at a time.\n\n' 'Available hosts:\n{}'.format( len(match), hostname, '\n'.join(sorted(hosts)))) raise base.InvalidHost(message) hostname = match[0] except subprocess.CalledProcessError: msg = "Unknown host '{}'.\n\nAvailable hosts:\n{}" LOG.error( msg.format(self.command_args.get('host'), '\n'.join(hosts))) util.sysexit() except base.InvalidHost as e: LOG.error(e.message) util.sysexit() self._get_login(hostname) return None, None
def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule login` and return a tuple. :param exit: (Unused) Provided to complete method signature. :return: Return a tuple of None, otherwise sys.exit on command failure. """ # get list of running hosts from state if self.molecule.state.hosts: hosts = [k for k, v in self.molecule.state.hosts.iteritems()] else: hosts = [] try: # Nowhere to login to if there is no running host. if len(hosts) == 0: raise base.InvalidHost("There are no running hosts.") # Check whether a host was specified. if self.molecule.args['<host>'] is None: # One running host is perfect. Login to it. if len(hosts) == 1: hostname = hosts[0] # But too many hosts is trouble as well. else: raise base.InvalidHost( "There are {} running hosts. You can only login to one at a time.\n\n" "Available hosts:\n{}".format( len(hosts), "\n".join(hosts))) else: # If the host was specified, try to use it. hostname = self.molecule.args['<host>'] match = [x for x in hosts if x.startswith(hostname)] if len(match) == 0: raise subprocess.CalledProcessError(1, None) elif len(match) != 1: # If there are multiple matches, but one of them is an # exact string match, assume this is the one they're # looking for and use it if hostname in match: match = [hostname, ] else: raise base.InvalidHost( "There are {} hosts that match '{}'. You can only login to one at a time.\n\n" "Available hosts:\n{}".format( len(match), hostname, "\n".join(hosts))) hostname = match[0] login_cmd = self.molecule.driver.login_cmd(hostname) login_args = self.molecule.driver.login_args(hostname) except subprocess.CalledProcessError: msg = "Unknown host '{}'.\n\nAvailable hosts:\n{}" LOG.error( msg.format(self.molecule.args['<host>'], "\n".join(hosts))) util.sysexit() except base.InvalidHost as e: LOG.error(e.message) util.sysexit() lines, columns = os.popen('stty size', 'r').read().split() dimensions = (int(lines), int(columns)) self.molecule._pt = pexpect.spawn( '/usr/bin/env ' + login_cmd.format(*login_args), dimensions=dimensions) signal.signal(signal.SIGWINCH, self._sigwinch_passthrough) self.molecule._pt.interact() return None, None