def test_ssh_key_policy(self, mock_sshclient): mock_sshclient.return_value = FakeSSHClient() # create with customized setting sshpool = utils.SSHPool("127.0.0.1", 22, 10, "test", password="******", min_size=1, max_size=1, missing_key_policy=paramiko.RejectPolicy(), hosts_key_file='dummy_host_keyfile') with sshpool.item() as ssh: self.assertTrue(isinstance(ssh.get_policy(), paramiko.RejectPolicy)) self.assertEqual(ssh.hosts_key_file, 'dummy_host_keyfile') # create with default setting sshpool = utils.SSHPool("127.0.0.1", 22, 10, "test", password="******", min_size=1, max_size=1) with sshpool.item() as ssh: self.assertTrue( isinstance(ssh.get_policy(), paramiko.AutoAddPolicy)) self.assertEqual(ssh.system_host_keys, 'system_host_keys')
def test_single_ssh_connect(self, mock_sshclient, mock_pkey): mock_sshclient.return_value = FakeSSHClient() # create with password sshpool = utils.SSHPool("127.0.0.1", 22, 10, "test", password="******", min_size=1, max_size=1) with sshpool.item() as ssh: first_id = ssh.id with sshpool.item() as ssh: second_id = ssh.id self.assertEqual(first_id, second_id) mock_sshclient.connect.assert_called_once() # create with private key sshpool = utils.SSHPool("127.0.0.1", 22, 10, "test", privatekey="test", min_size=1, max_size=1) mock_sshclient.connect.assert_called_once() # attempt to create with no password or private key self.assertRaises(paramiko.SSHException, utils.SSHPool, "127.0.0.1", 22, 10, "test", min_size=1, max_size=1)
def _run_ssh(self, command, check_exit=True, attempts=1): if not self.sshpool: self.sshpool = utils.SSHPool( self.config.san_ip, self.config.san_ssh_port, self.config.ssh_conn_timeout, self.config.san_login, password=self.config.san_password, privatekey=self.config.san_private_key, min_size=self.config.ssh_min_pool_conn, max_size=self.config.ssh_max_pool_conn) try: total_attempts = attempts with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: return self._ssh_execute(ssh, command, check_exit_code=check_exit) except Exception as e: LOG.error(e) greenthread.sleep(randint(20, 500) / 100.0) raise paramiko.SSHException( _("SSH Command failed after " "'%(total_attempts)r' attempts" ": '%(command)s'"), locals()) except Exception as e: LOG.error(_("Error running ssh command: %s") % command) raise e
def _run_ssh(self, cmd_list, check_exit=True, attempts=1): utils.check_ssh_injection(cmd_list) command = ' '.join(cmd_list) if not self.sshpool: self.sshpool = utils.SSHPool( self.config.san_ip, self.config.san_ssh_port, self.config.ssh_conn_timeout, self.config.san_login, password=self.config.san_password, privatekey=self.config.san_private_key, min_size=self.config.ssh_min_pool_conn, max_size=self.config.ssh_max_pool_conn) try: total_attempts = attempts with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: return self._ssh_execute(ssh, command, check_exit_code=check_exit) except Exception as e: LOG.error(e) greenthread.sleep(randint(20, 500) / 100.0) msg = (_("SSH Command failed after '%(total_attempts)r' " "attempts : '%(command)s'") % { 'total_attempts': total_attempts, 'command': command }) raise paramiko.SSHException(msg) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_("Error running ssh command: %s") % command)
def test_closed_reopend_ssh_connections(self): self.setup() sshpool = utils.SSHPool("127.0.0.1", 22, 10, "test", password="******", min_size=1, max_size=2) with sshpool.item() as ssh: first_id = ssh.id with sshpool.item() as ssh: second_id = ssh.id # Close the connection and test for a new connection ssh.get_transport().active = False self.assertEqual(first_id, second_id) # The mox items are not getting setup in a new pool connection, # so had to reset and set again. self.mox.UnsetStubs() self.setup() with sshpool.item() as ssh: third_id = ssh.id self.assertNotEqual(first_id, third_id)
def test_closed_reopend_ssh_connections(self, mock_sshclient): mock_sshclient.return_value = eval('FakeSSHClient')() sshpool = utils.SSHPool("127.0.0.1", 22, 10, "test", password="******", min_size=1, max_size=4) with sshpool.item() as ssh: mock_sshclient.reset_mock() first_id = ssh.id with sshpool.item() as ssh: second_id = ssh.id ssh.get_transport().active = False sshpool.remove(ssh) self.assertEqual(first_id, second_id) # create a new client mock_sshclient.return_value = FakeSSHClient() with sshpool.item() as ssh: third_id = ssh.id self.assertNotEqual(first_id, third_id)
def test_single_ssh_connect(self): self.setup() sshpool = utils.SSHPool("127.0.0.1", 22, 10, "test", password="******", min_size=1, max_size=1) with sshpool.item() as ssh: first_id = ssh.id with sshpool.item() as ssh: second_id = ssh.id self.assertEqual(first_id, second_id)
def _execute_shell_cmd(self, cmd): """Run command over shell for older firmware versions. We invoke shell and issue the command and return the output. This is primarily used for issuing read commands when we are not sure if the firmware supports exec_command. """ utils.check_ssh_injection(cmd) command = ' '. join(cmd) stdout, stderr = None, None if not self.sshpool: self.sshpool = utils.SSHPool(self.switch_ip, self.switch_port, None, self.switch_user, self.switch_pwd, min_size=1, max_size=5) with self.sshpool.item() as ssh: LOG.debug('Running cmd (SSH): %s' % command) channel = ssh.invoke_shell() stdin_stream = channel.makefile('wb') stdout_stream = channel.makefile('rb') stderr_stream = channel.makefile('rb') stdin_stream.write('''%s exit ''' % command) stdin_stream.flush() stdout = stdout_stream.readlines() stderr = stderr_stream.readlines() stdin_stream.close() stdout_stream.close() stderr_stream.close() exit_status = channel.recv_exit_status() # exit_status == -1 if no exit code was returned if exit_status != -1: LOG.debug('Result was %s' % exit_status) if exit_status != 0: msg = "command %s failed" % command LOG.debug(msg) raise processutils.ProcessExecutionError( exit_code=exit_status, stdout=stdout, stderr=stderr, cmd=command) try: channel.close() except Exception as e: LOG.exception(e) LOG.debug("_execute_cmd: stdout to return:%s" % stdout) LOG.debug("_execute_cmd: stderr to return:%s" % stderr) return (stdout, stderr)
def _run_ssh(self, cmd_list, check_exit_code=True, attempts=1): utils.check_ssh_injection(cmd_list) command = ' '. join(cmd_list) if not self.sshpool: password = self.configuration.san_password privatekey = self.configuration.san_private_key min_size = self.configuration.ssh_min_pool_conn max_size = self.configuration.ssh_max_pool_conn self.sshpool = utils.SSHPool(self.configuration.san_ip, self.configuration.san_ssh_port, self.configuration.ssh_conn_timeout, self.configuration.san_login, password=password, privatekey=privatekey, min_size=min_size, max_size=max_size) last_exception = None try: total_attempts = attempts with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: return processutils.ssh_execute( ssh, command, check_exit_code=check_exit_code) except Exception as e: LOG.error(e) last_exception = e greenthread.sleep(random.randint(20, 500) / 100.0) try: raise processutils.ProcessExecutionError( exit_code=last_exception.exit_code, stdout=last_exception.stdout, stderr=last_exception.stderr, cmd=last_exception.cmd) except AttributeError: raise processutils.ProcessExecutionError( exit_code=-1, stdout="", stderr="Error running SSH command", cmd=command) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_("Error running SSH command: %s") % command)
def _run_ssh(self, cmd_list, check_exit_code=True, attempts=1): # TODO(skolathur): Need to implement ssh_injection check # currently, the check will fail for zonecreate command # as zone members are separated by ';'which is a danger char command = ' '. join(cmd_list) if not self.sshpool: self.sshpool = utils.SSHPool(self.switch_ip, self.switch_port, None, self.switch_user, self.switch_pwd, min_size=1, max_size=5) last_exception = None try: with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: return processutils.ssh_execute( ssh, command, check_exit_code=check_exit_code) except Exception as e: LOG.error(e) last_exception = e greenthread.sleep(random.randint(20, 500) / 100.0) try: raise processutils.ProcessExecutionError( exit_code=last_exception.exit_code, stdout=last_exception.stdout, stderr=last_exception.stderr, cmd=last_exception.cmd) except AttributeError: raise processutils.ProcessExecutionError( exit_code=-1, stdout="", stderr="Error running SSH command", cmd=command) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_("Error running SSH command: %s") % command)
def _run_ssh(self, cmd_list, attempts=1): utils.check_ssh_injection(cmd_list) command = ' '.join(cmd_list) if not self.sshpool: password = self.configuration.san_password privatekey = self.configuration.san_private_key min_size = self.configuration.ssh_min_pool_conn max_size = self.configuration.ssh_max_pool_conn self.sshpool = utils.SSHPool(self.configuration.san_ip, self.configuration.san_ssh_port, self.configuration.ssh_conn_timeout, self.configuration.san_login, password=password, privatekey=privatekey, min_size=min_size, max_size=max_size) try: total_attempts = attempts with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: LOG.info(_('EQL-driver: executing "%s"') % command) return self._ssh_execute( ssh, command, timeout=self.configuration.eqlx_cli_timeout) except processutils.ProcessExecutionError: raise except Exception as e: LOG.exception(e) greenthread.sleep(random.randint(20, 500) / 100.0) msg = (_("SSH Command failed after '%(total_attempts)r' " "attempts : '%(command)s'") % { 'total_attempts': total_attempts, 'command': command }) raise exception.VolumeBackendAPIException(data=msg) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_("Error running SSH command: %s") % command)
def _ssh_execute(self, cmd_list, check_exit_code=True, attempts=1): """Execute cli with status update. Executes CLI commands such as cfgsave where status return is expected. """ utils.check_ssh_injection(cmd_list) command = ' '. join(cmd_list) if not self.sshpool: self.sshpool = utils.SSHPool(self.switch_ip, self.switch_port, None, self.switch_user, self.switch_pwd, min_size=1, max_size=5) stdin, stdout, stderr = None, None, None LOG.debug("Executing command via ssh: %s" % command) last_exception = None try: with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: stdin, stdout, stderr = ssh.exec_command(command) greenthread.sleep(random.randint(20, 500) / 100.0) stdin.write("%s\n" % ZoneConstant.YES) channel = stdout.channel exit_status = channel.recv_exit_status() LOG.debug("Exit Status from ssh:%s", exit_status) # exit_status == -1 if no exit code was returned if exit_status != -1: LOG.debug('Result was %s' % exit_status) if check_exit_code and exit_status != 0: raise processutils.ProcessExecutionError( exit_code=exit_status, stdout=stdout, stderr=stderr, cmd=command) else: return True else: return True except Exception as e: LOG.error(e) last_exception = e greenthread.sleep(random.randint(20, 500) / 100.0) LOG.debug("Handling error case after " "SSH:%s", last_exception) try: raise processutils.ProcessExecutionError( exit_code=last_exception.exit_code, stdout=last_exception.stdout, stderr=last_exception.stderr, cmd=last_exception.cmd) except AttributeError: raise processutils.ProcessExecutionError( exit_code=-1, stdout="", stderr="Error running SSH command", cmd=command) except Exception as e: with excutils.save_and_reraise_exception(): LOG.error(_("Error executing command via ssh: %s"), e) finally: if stdin: stdin.flush() stdin.close() if stdout: stdout.close() if stderr: stderr.close()