rally/tests/unit/common/test_sshutils.py
jacobliberman 3498071401 Replace ' with " in tests/unit/[common,deploy,doc,fixtures]
Partial bug: 1405884

Change-Id: I0100649c32bb911dab345c40492aa148ed1832c6
2015-02-03 10:48:15 -06:00

257 lines
11 KiB
Python

# Copyright 2013: Mirantis Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
from rally.common import sshutils
from tests.unit import test
class FakeParamikoException(Exception):
pass
class SSHTestCase(test.TestCase):
"""Test all small SSH methods."""
def setUp(self):
super(SSHTestCase, self).setUp()
self.ssh = sshutils.SSH("root", "example.net")
@mock.patch("rally.common.sshutils.SSH._get_pkey")
def test_construct(self, m_pkey):
m_pkey.return_value = "pkey"
ssh = sshutils.SSH("root", "example.net", port=33, pkey="key",
key_filename="kf", password="secret")
m_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 test_construct_default(self):
self.assertEqual("root", self.ssh.user)
self.assertEqual("example.net", self.ssh.host)
self.assertEqual(22, self.ssh.port)
self.assertIsNone(self.ssh.pkey)
self.assertIsNone(self.ssh.key_filename)
self.assertIsNone(self.ssh.password)
@mock.patch("rally.common.sshutils.paramiko")
def test__get_pkey_invalid(self, m_paramiko):
m_paramiko.SSHException = FakeParamikoException
rsa = m_paramiko.rsakey.RSAKey
dss = m_paramiko.dsskey.DSSKey
rsa.from_private_key.side_effect = m_paramiko.SSHException
dss.from_private_key.side_effect = m_paramiko.SSHException
self.assertRaises(sshutils.SSHError, self.ssh._get_pkey, "key")
@mock.patch("rally.common.sshutils.six.moves")
@mock.patch("rally.common.sshutils.paramiko")
def test__get_pkey_dss(self, m_paramiko, m_stringio):
m_paramiko.SSHException = FakeParamikoException
m_stringio.StringIO.return_value = "string_key"
m_paramiko.dsskey.DSSKey.from_private_key.return_value = "dss_key"
rsa = m_paramiko.rsakey.RSAKey
rsa.from_private_key.side_effect = m_paramiko.SSHException
key = self.ssh._get_pkey("key")
dss_calls = m_paramiko.dsskey.DSSKey.from_private_key.mock_calls
self.assertEqual([mock.call("string_key")], dss_calls)
self.assertEqual(key, "dss_key")
m_stringio.StringIO.assert_called_once_with("key")
@mock.patch("rally.common.sshutils.six.moves")
@mock.patch("rally.common.sshutils.paramiko")
def test__get_pkey_rsa(self, m_paramiko, m_stringio):
m_paramiko.SSHException = FakeParamikoException
m_stringio.StringIO.return_value = "string_key"
m_paramiko.rsakey.RSAKey.from_private_key.return_value = "rsa_key"
dss = m_paramiko.dsskey.DSSKey
dss.from_private_key.side_effect = m_paramiko.SSHException
key = self.ssh._get_pkey("key")
rsa_calls = m_paramiko.rsakey.RSAKey.from_private_key.mock_calls
self.assertEqual([mock.call("string_key")], rsa_calls)
self.assertEqual(key, "rsa_key")
m_stringio.StringIO.assert_called_once_with("key")
@mock.patch("rally.common.sshutils.SSH._get_pkey")
@mock.patch("rally.common.sshutils.paramiko")
def test__get_client(self, m_paramiko, m_pkey):
m_pkey.return_value = "key"
fake_client = mock.Mock()
m_paramiko.SSHClient.return_value = fake_client
m_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="admin",
port=22, pkey="key", key_filename=None,
password=None, timeout=1),
]
self.assertEqual(client_calls, client.mock_calls)
def test_close(self):
with mock.patch.object(self.ssh, "_client") as m_client:
self.ssh.close()
m_client.close.assert_called_once_with()
self.assertFalse(self.ssh._client)
@mock.patch("rally.common.sshutils.six.moves")
def test_execute(self, m_stringio):
m_stringio.StringIO.side_effect = stdio = [mock.Mock(), mock.Mock()]
stdio[0].read.return_value = "stdout fake data"
stdio[1].read.return_value = "stderr fake data"
with mock.patch.object(self.ssh, "run", return_value=0) as m_run:
status, stdout, stderr = self.ssh.execute("cmd",
stdin="fake_stdin",
timeout=43)
m_run.assert_called_once_with("cmd", stdin="fake_stdin",
stdout=stdio[0],
stderr=stdio[1], timeout=43,
raise_on_error=False)
self.assertEqual(0, status)
self.assertEqual("stdout fake data", stdout)
self.assertEqual("stderr fake data", stderr)
@mock.patch("rally.common.sshutils.time")
def test_wait_timeout(self, m_time):
m_time.time.side_effect = [1, 50, 150]
self.ssh.execute = mock.Mock(side_effect=[sshutils.SSHError,
sshutils.SSHError,
0])
self.assertRaises(sshutils.SSHTimeout, self.ssh.wait)
self.assertEqual([mock.call("uname")] * 2, self.ssh.execute.mock_calls)
@mock.patch("rally.common.sshutils.time")
def test_wait(self, m_time):
m_time.time.side_effect = [1, 50, 100]
self.ssh.execute = mock.Mock(side_effect=[sshutils.SSHError,
sshutils.SSHError,
0])
self.ssh.wait()
self.assertEqual([mock.call("uname")] * 3, self.ssh.execute.mock_calls)
class SSHRunTestCase(test.TestCase):
"""Test SSH.run method in different aspects.
Also tested method "execute".
"""
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)
@mock.patch("rally.common.sshutils.select")
def test_execute(self, m_select):
m_select.select.return_value = ([], [], [])
self.fake_session.recv_ready.side_effect = [1, 0, 0]
self.fake_session.recv_stderr_ready.side_effect = [1, 0]
self.fake_session.recv.return_value = "ok"
self.fake_session.recv_stderr.return_value = "error"
self.fake_session.exit_status_ready.return_value = 1
self.fake_session.recv_exit_status.return_value = 127
self.assertEqual((127, "ok", "error"), self.ssh.execute("cmd"))
self.fake_session.exec_command.assert_called_once_with("cmd")
@mock.patch("rally.common.sshutils.select")
def test_run(self, m_select):
m_select.select.return_value = ([], [], [])
self.assertEqual(0, self.ssh.run("cmd"))
@mock.patch("rally.common.sshutils.select")
def test_run_nonzero_status(self, m_select):
m_select.select.return_value = ([], [], [])
self.fake_session.recv_exit_status.return_value = 1
self.assertRaises(sshutils.SSHError, self.ssh.run, "cmd")
self.assertEqual(1, self.ssh.run("cmd", raise_on_error=False))
@mock.patch("rally.common.sshutils.select")
def test_run_stdout(self, m_select):
m_select.select.return_value = ([], [], [])
self.fake_session.recv_ready.side_effect = [True, True, False]
self.fake_session.recv.side_effect = ["ok1", "ok2"]
stdout = mock.Mock()
self.ssh.run("cmd", stdout=stdout)
self.assertEqual([mock.call("ok1"), mock.call("ok2")],
stdout.write.mock_calls)
@mock.patch("rally.common.sshutils.select")
def test_run_stderr(self, m_select):
m_select.select.return_value = ([], [], [])
self.fake_session.recv_stderr_ready.side_effect = [True, False]
self.fake_session.recv_stderr.return_value = "error"
stderr = mock.Mock()
self.ssh.run("cmd", stderr=stderr)
stderr.write.assert_called_once_with("error")
@mock.patch("rally.common.sshutils.select")
def test_run_stdin(self, m_select):
"""Test run method with stdin.
Third send call was called with "e2" because only 3 bytes was sent
by second call. So remainig 2 bytes of "line2" was sent by third call.
"""
m_select.select.return_value = ([], [], [])
self.fake_session.exit_status_ready.side_effect = [0, 0, 0, True]
self.fake_session.send_ready.return_value = True
self.fake_session.send.side_effect = [5, 3, 2]
fake_stdin = mock.Mock()
fake_stdin.read.side_effect = ["line1", "line2", ""]
fake_stdin.closed = False
def close():
fake_stdin.closed = True
fake_stdin.close = mock.Mock(side_effect=close)
self.ssh.run("cmd", stdin=fake_stdin)
call = mock.call
send_calls = [call("line1"), call("line2"), call("e2")]
self.assertEqual(send_calls, self.fake_session.send.mock_calls)
@mock.patch("rally.common.sshutils.select")
def test_run_select_error(self, m_select):
self.fake_session.exit_status_ready.return_value = False
m_select.select.return_value = ([], [], [True])
self.assertRaises(sshutils.SSHError, self.ssh.run, "cmd")
@mock.patch("rally.common.sshutils.time")
@mock.patch("rally.common.sshutils.select")
def test_run_timemout(self, m_select, m_time):
m_time.time.side_effect = [1, 3700]
m_select.select.return_value = ([], [], [])
self.fake_session.exit_status_ready.return_value = False
self.assertRaises(sshutils.SSHTimeout, self.ssh.run, "cmd")