def _run_command(self, server_ip, port, username, password, command, pkey=None, timeout=120, interval=1): """Run command via SSH on server. Create SSH connection for server, wait for server to become available (there is a delay between server being set to ACTIVE and sshd being available). Then call run_command_over_ssh to actually execute the command. :param server_ip: server ip address :param port: ssh port for SSH connection :param username: str. ssh username for server :param password: Password for SSH authentication :param command: Dictionary specifying command to execute. See `rally info find VMTasks.boot_runcommand_delete' parameter `command' docstring for explanation. :param pkey: key for SSH authentication :param timeout: wait for ssh timeout. Default is 120 seconds :param interval: ssh retry interval. Default is 1 second :returns: tuple (exit_status, stdout, stderr) """ pkey = pkey if pkey else self.context["user"]["keypair"]["private"] ssh = sshutils.SSH(username, server_ip, port=port, pkey=pkey, password=password) try: self._wait_for_ssh(ssh, timeout, interval) return self._run_command_over_ssh(ssh, command) finally: try: ssh.close() except AttributeError: pass
def test__get_pkey_rsa(self): private_rsa_key = io.StringIO() private_rsa_key_obj = paramiko.RSAKey.generate(1024) private_rsa_key_obj.write_private_key(private_rsa_key) private_rsa_key.seek(0) ssh = sshutils.SSH("root", "example.net") self.assertIsInstance(ssh._get_pkey(private_rsa_key), paramiko.RSAKey) private_rsa_key.seek(0) self.assertIsInstance(ssh._get_pkey(private_rsa_key.getvalue()), paramiko.RSAKey)
def test_construct(self, mock_ssh__get_pkey): mock_ssh__get_pkey.return_value = "pkey" ssh = sshutils.SSH("root", "example.net", port=33, pkey="key", key_filename="kf", password="******") mock_ssh__get_pkey.assert_called_once_with("key") self.assertEqual("root", ssh.user) self.assertEqual("example.net", ssh.host) self.assertEqual(33, ssh.port) self.assertEqual("pkey", ssh.pkey) self.assertEqual("kf", ssh.key_filename) self.assertEqual("secret", ssh.password)
def setUp(self): super(SSHRunTestCase, self).setUp() self.fake_client = mock.Mock() self.fake_session = mock.Mock() self.fake_transport = mock.Mock() self.fake_transport.open_session.return_value = self.fake_session self.fake_client.get_transport.return_value = self.fake_transport self.fake_session.recv_ready.return_value = False self.fake_session.recv_stderr_ready.return_value = False self.fake_session.send_ready.return_value = False self.fake_session.exit_status_ready.return_value = True self.fake_session.recv_exit_status.return_value = 0 self.ssh = sshutils.SSH("admin", "example.net") self.ssh._get_client = mock.Mock(return_value=self.fake_client)
def test__get_client(self, mock_paramiko, mock_ssh__get_pkey): mock_ssh__get_pkey.return_value = "key" fake_client = mock.Mock() mock_paramiko.SSHClient.return_value = fake_client mock_paramiko.AutoAddPolicy.return_value = "autoadd" ssh = sshutils.SSH("admin", "example.net", pkey="key") client = ssh._get_client() self.assertEqual(fake_client, client) client_calls = [ mock.call.set_missing_host_key_policy("autoadd"), mock.call.connect("example.net", username="******", port=22, pkey="key", key_filename=None, password=None, timeout=1), ] self.assertEqual(client_calls, client.mock_calls)
def setUp(self): super(SSHTestCase, self).setUp() self.ssh = sshutils.SSH("root", "example.net")
def run(self, workload, template, files, parameters): """Run workload on stack deployed by heat. Workload can be either file or resource: .. code-block:: json {"file": "/path/to/file.sh"} {"resource": ["package.module", "workload.py"]} Also it should contain "username" key. Given file will be uploaded to `gate_node` and started. This script should print `key` `value` pairs separated by colon. These pairs will be presented in results. Gate node should be accessible via ssh with keypair `key_name`, so heat template should accept parameter `key_name`. :param workload: workload to run :param template: path to heat template file :param files: additional template files :param parameters: parameters for heat template """ keypair = self.context["user"]["keypair"] parameters["key_name"] = keypair["name"] network = self.context["tenant"]["networks"][0] parameters["router_id"] = network["router_id"] self.stack = heat.main.Stack(self, self.task, template, files=files, parameters=parameters) self.stack.create() for output in self.stack.stack.outputs: if output["output_key"] == "gate_node": ip = output["output_value"] break ssh = sshutils.SSH(workload["username"], ip, pkey=keypair["private"]) ssh.wait() script = workload.get("resource") if script: script = pkgutil.get_data(*script) else: script = open(workload["file"]).read() ssh.execute("cat > /tmp/.rally-workload", stdin=script) ssh.execute("chmod +x /tmp/.rally-workload") with atomic.ActionTimer(self, "runcommand_heat.workload"): status, out, err = ssh.execute("/tmp/.rally-workload", stdin=json.dumps( self.stack.stack.outputs)) rows = [] for line in out.splitlines(): row = line.split(":") if len(row) != 2: raise exceptions.ScriptError("Invalid data '%s'" % line) rows.append(row) if not rows: raise exceptions.ScriptError("No data returned. Original error " "message is %s" % err) self.add_output( complete={ "title": "Workload summary", "description": "Data generated by workload", "chart_plugin": "Table", "data": { "cols": ["key", "value"], "rows": rows } })