def _ssh_connect(self): """Connect via SSH.""" if self._ssh_client: return self._ssh_client if not self.ssh_ip or not self.ssh_port: raise ValueError client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) private_key = paramiko.RSAKey.from_private_key_file(self.ssh_key_file) retries = 30 while retries: try: client.connect(username=self.ssh_username, hostname=self.ssh_ip, port=self.ssh_port, pkey=private_key, banner_timeout=30) self._ssh_client = client return client except (ConnectionRefusedError, AuthenticationException, BadHostKeyException, ConnectionResetError, SSHException, OSError) as e: retries -= 1 time.sleep(10) ssh_cmd = 'Failed ssh connection to %s@%s:%s after 300 seconds' % ( self.ssh_username, self.ssh_ip, self.ssh_port ) raise util.InTargetExecuteError(b'', b'', 1, ssh_cmd, 'ssh')
def _ssh_connect(self, hostname='localhost', username='******', banner_timeout=120, retry_attempts=30): """Connect via SSH.""" if self._ssh_client: return self._ssh_client private_key = paramiko.RSAKey.from_private_key_file(self.ssh_key_file) client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) while retry_attempts: try: client.connect(hostname=hostname, username=username, port=self.ssh_port, pkey=private_key, banner_timeout=banner_timeout) self._ssh_client = client return client except (paramiko.SSHException, TypeError): time.sleep(1) retry_attempts = retry_attempts - 1 error_desc = 'Failed command to: %s@%s:%s' % (username, hostname, self.ssh_port) raise util.InTargetExecuteError('', '', -1, 'ssh connect', self.name, error_desc)
def execute(self, command, stdout=None, stderr=None, env=None, rcs=None, description=None): """Execute command in instance, recording output, error and exit code. Assumes functional networking and execution as root with the target filesystem being available at /. @param command: the command to execute as root inside the image if command is a string, then it will be executed as: ['sh', '-c', command] @param stdout: file handler to write output @param stderr: file handler to write error @param env: environment variables @param rcs: allowed return codes from command @param description: purpose of command @return_value: tuple containing stdout data, stderr data, exit code """ if env is None: env = {} if isinstance(command, str): command = ['sh', '-c', command] # ensure instance is running and execute the command self.start() res = self.pylxd_container.execute(command, environment=env) # get out, exit and err from pylxd return if hasattr(res, 'exit_code'): # pylxd 2.2 returns ContainerExecuteResult, named tuple of # (exit_code, out, err) (exit, out, err) = res else: # pylxd 2.1.3 and earlier only return out and err, no exit # LOG.warning('using pylxd version < 2.2') (out, err) = res exit = 0 # write data to file descriptors if needed if stdout: stdout.write(out) if stderr: stderr.write(err) # if the command exited with a code not allowed in rcs, then fail if exit not in (rcs if rcs else (0, )): error_desc = ('Failed command to: {}'.format(description) if description else None) raise util.InTargetExecuteError(out, err, exit, command, self.name, error_desc) return (out, err, exit)
def ssh(self, command): """Run a command via SSH.""" client = self._ssh_connect() try: _, out, err = client.exec_command(util.shell_pack(command)) except paramiko.SSHException: raise util.InTargetExecuteError('', '', -1, command, self.name) exit = out.channel.recv_exit_status() out = ''.join(out.readlines()) err = ''.join(err.readlines()) client.close() return out, err, exit
def ssh(self, command, stdin=None): """Run a command via SSH.""" client = self._ssh_connect() cmd = util.shell_pack(command) try: fp_in, fp_out, fp_err = client.exec_command(cmd) channel = fp_in.channel if stdin is not None: fp_in.write(stdin) fp_in.close() channel.shutdown_write() rc = channel.recv_exit_status() return (fp_out.read(), fp_err.read(), rc) except paramiko.SSHException as e: raise util.InTargetExecuteError(b'', b'', -1, command, self.name, reason=e)
def _ssh_connect(self): """Connect via SSH. Attempt to SSH to the client on the specific IP and port. If it fails in some manner, then retry 2 more times for a total of 3 attempts; sleeping a few seconds between attempts. """ if self._ssh_client: return self._ssh_client if not self.ssh_ip or not self.ssh_port: raise ValueError("Cannot ssh_connect, ssh_ip=%s ssh_port=%s" % (self.ssh_ip, self.ssh_port)) client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) private_key = paramiko.RSAKey.from_private_key_file(self.ssh_key_file) retries = 3 while retries: try: client.connect(username=self.ssh_username, hostname=self.ssh_ip, port=self.ssh_port, pkey=private_key) self._ssh_client = client return client except (ConnectionRefusedError, AuthenticationException, BadHostKeyException, ConnectionResetError, SSHException, OSError): retries -= 1 LOG.debug('Retrying ssh connection on connect failure') time.sleep(3) ssh_cmd = 'Failed ssh connection to %s@%s:%s after 3 retries' % ( self.ssh_username, self.ssh_ip, self.ssh_port) raise util.InTargetExecuteError(b'', b'', 1, ssh_cmd, 'ssh')