def test_wait_for_onie_rescue_exception(mock_pxssh, mock_post_dev, mock_exit_results): error = 'Super weird error youve never seen before' mock_pxssh.return_value.login.side_effect = ExceptionPxssh(error) countdown = 1 poll_delay = 1 user = '******' target = cli_args().target mock_post_dev_calls = [ mock.call( message= 'Cumulus installation in progress. Waiting for boot to ONIE rescue mode. ' 'Timeout remaining: 1 seconds', state='AWAIT-ONLINE') ] local_cb = cumulus_bootstrap.CumulusBootstrap(args['server'], cli_args()) with pytest.raises(SystemExit): local_cb.wait_for_onie_rescue(countdown, poll_delay, user=user) mock_post_dev.assert_has_calls(mock_post_dev_calls) mock_exit_results.assert_called_with( results={ 'message': 'Error accessing {target} in ONIE rescue' ' mode: {error}.'.format(target=target, error=error), 'error_type': 'login', 'ok': False })
def test_wait_for_onie_rescue_pxsshexception(mock_pxssh, mock_post_dev, mock_exit_results, mock_time): mock_pxssh.return_value.login.side_effect = ExceptionPxssh( 'Could not establish connection to host') countdown = 1 poll_delay = 1 user = '******' mock_post_dev_calls = [ mock.call( message= 'Cumulus installation in progress. Waiting for boot to ONIE rescue mode. ' 'Timeout remaining: 1 seconds', state='AWAIT-ONLINE'), mock.call( message= 'Cumulus installation in progress. Waiting for boot to ONIE rescue mode. ' 'Timeout remaining: 0 seconds', state='AWAIT-ONLINE') ] local_cb = cumulus_bootstrap.CumulusBootstrap(args['server'], cli_args()) with pytest.raises(SystemExit): local_cb.wait_for_onie_rescue(countdown, poll_delay, user=user) mock_post_dev.assert_has_calls(mock_post_dev_calls) mock_exit_results.assert_called_with( results={ 'message': 'Device 1.1.1.1 not reachable in ONIE rescue mode within reload countdown.', 'error_type': 'login', 'ok': False })
def test_get_device_exception(mock_pxssh, mock_ssh): exception_msg = 'Test Exception Message' mock_pxssh.return_value.login.side_effect = ExceptionPxssh(exception_msg) with pytest.raises(TargetError) as e: dev = get_device(target=dev_info['target'], user=dev_info['user'], passwd=dev_info['passwd']) assert e.value.message == 'Error logging in to {target} : {error}'.format( target=dev_info['target'], error=exception_msg)
def test_onie_install_pxssh_exception(mock_pxssh, mock_exit_results, cb_obj, device): cb_obj.dev = device exc = ExceptionPxssh('Could not establish connection to host') mock_pxssh.return_value.login.side_effect = exc with pytest.raises(SystemExit): cb_obj.do_onie_install() mock_exit_results.assert_called_with(results={'ok': False, 'error_type': 'install', 'message': exc})
def login (self, server, username, password='', terminal_type='ansi', original_prompt=r"[#$]", login_timeout=10, port=None, auto_prompt_reset=True, ssh_key=None, quiet=True, sync_multiplier=1, check_local_ip=True): # cp ssh doesn't have an options field so ignore ALL options ssh_options = '' if port is not None: ssh_options = ssh_options + ' -p %s'%(str(port)) cmd = "ssh %s -l %s %s" % (ssh_options, username, server) # This does not distinguish between a remote server 'password' prompt # and a local ssh 'passphrase' prompt (for unlocking a private key). spawn._spawn(self, cmd) i = self.expect(["(?i)Do you trust the host key", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT, "(?i)connection closed by remote host", EOF], timeout=login_timeout) # First phase if i==0: # New certificate -- always accept it. # This is what you get if SSH does not have the remote host's # public key stored in the 'known_hosts' cache. self.sendline("yes") i = self.expect(["(?i)Do you trust the host key", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT]) if i==2: # password or passphrase self.sendline(password) i = self.expect(["(?i)Do you trust the host key", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT]) if i==4: self.sendline(terminal_type) i = self.expect(["(?i)Do you trust the host key", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT]) if i==7: self.close() raise ExceptionPxssh('Could not establish connection to host') # Second phase if i==0: # This is weird. This should not happen twice in a row. self.close() raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.') elif i==1: # can occur if you have a public key pair set to authenticate. ### TODO: May NOT be OK if expect() got tricked and matched a false prompt. pass elif i==2: # password prompt again # For incorrect passwords, some ssh servers will # ask for the password again, others return 'denied' right away. # If we get the password prompt again then this means # we didn't get the password right the first time. self.close() raise ExceptionPxssh('password refused') elif i==3: # permission denied -- password was bad. self.close() raise ExceptionPxssh('permission denied') elif i==4: # terminal type again? WTF? self.close() raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.') elif i==5: # Timeout #This is tricky... I presume that we are at the command-line prompt. #It may be that the shell_sample prompt was so weird that we couldn't match #it. Or it may be that we couldn't log in for some other reason. I #can't be sure, but it's safe to guess that we did login because if #I presume wrong and we are not logged in then this should be caught #later when I try to set the shell_sample prompt. pass elif i==6: # Connection closed by remote host self.close() raise ExceptionPxssh('connection closed') else: # Unexpected self.close() raise ExceptionPxssh('unexpected login response') return True
def goto(iphost, username, password='', terminal_type='ansi', original_prompt=r"[#$]", login_timeout=10, port=None, auto_prompt_reset=True, ssh_key=None, quiet=True, sync_multiplier=1, check_local_ip=True, callback=None, dimensions=None): ssh_options = '' if quiet: ssh_options = ssh_options + ' -q' if not check_local_ip: ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'" if port is not None: ssh_options = ssh_options + ' -p %s' % (str(port)) if ssh_key is not None: try: os.path.isfile(ssh_key) except: raise ExceptionPxssh('private ssh key does not exist') ssh_options = ssh_options + ' -i %s' % (ssh_key) cmd = "ssh %s -l %s %s" % (ssh_options, username, iphost) # This does not distinguish between a remote server 'password' prompt # and a local ssh 'passphrase' prompt (for unlocking a private key). child = pexpect.spawn(cmd, dimensions=dimensions) i = child.expect([ "(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", pexpect.TIMEOUT, "(?i)connection closed by remote host" ], timeout=login_timeout) # First phase if i == 0: # New certificate -- always accept it. # This is what you get if SSH does not have the remote host's # public key stored in the 'known_hosts' cache. child.sendline("yes") i = child.expect([ "(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", pexpect.TIMEOUT ]) if i == 2: # password or passphrase child.sendline(password) i = child.expect([ "(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", pexpect.TIMEOUT ]) if i == 4: child.sendline(terminal_type) i = child.expect([ "(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", pexpect.TIMEOUT ]) # Second phase if i == 0: # This is weird. This should not happen twice in a row. child.close() raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.') elif i == 1: # can occur if you have a public key pair set to authenticate. ### TODO: May NOT be OK if expect() got tricked and matched a false prompt. pass elif i == 2: # password prompt again # For incorrect passwords, some ssh servers will # ask for the password again, others return 'denied' right away. # If we get the password prompt again then this means # we didn't get the password right the first time. child.close() raise ExceptionPxssh('password refused') elif i == 3: # permission denied -- password was bad. child.close() raise ExceptionPxssh('permission denied') elif i == 4: # terminal type again? WTF? child.close() raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.') elif i == 5: # Timeout #This is tricky... I presume that we are at the command-line prompt. #It may be that the shell prompt was so weird that we couldn't match #it. Or it may be that we couldn't log in for some other reason. I #can't be sure, but it's safe to guess that we did login because if #I presume wrong and we are not logged in then this should be caught #later when I try to set the shell prompt. raise ExceptionPxssh('timeout') elif i == 6: # Connection closed by remote host child.close() raise ExceptionPxssh('connection closed') else: # Unexpected child.close() raise ExceptionPxssh('unexpected login response') if type(callback) == types.FunctionType: callback() child.sendline() child.interact()