Files
rally/tests/unit/deploy/serverprovider/providers/test_lxc.py
Pavel Boldin 9076679fef unit-tests: fix mocks' naming
Fix mocks' argument/decorator naming.

Partial-Bug: #1462956
Change-Id: I8366736f3bc7088f867eec1fc72630dbe1bcf19e
2015-06-19 22:57:34 +03:00

393 lines
17 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 jsonschema
import mock
import netaddr
from rally.deploy.serverprovider.providers import lxc
from rally import exceptions
from tests.unit import test
MOD_NAME = "rally.deploy.serverprovider.providers.lxc."
class HelperFunctionsTestCase(test.TestCase):
@mock.patch(MOD_NAME + "open", create=True, return_value="fake_script")
def test__get_script(self, mock_open):
script = lxc._get_script("script.sh")
self.assertEqual("fake_script", script)
path = mock_open.mock_calls[0][1][0]
mode = mock_open.mock_calls[0][1][1]
self.assertTrue(path.endswith("rally/deploy/serverprovider/providers"
"/lxc/script.sh"))
self.assertEqual("rb", mode)
@mock.patch(MOD_NAME + "_get_script", return_value="fake_script")
@mock.patch(MOD_NAME + "moves.StringIO")
def test__get_script_from_template(self, mock_string_io, mock__get_script):
mock__get_script.return_value = fake_script = mock.Mock()
fake_script.read.return_value = "fake_data {k1} {k2}"
mock_string_io.return_value = "fake_formatted_script"
script = lxc._get_script_from_template("fake_tpl", k1="v1", k2="v2")
self.assertEqual("fake_formatted_script", script)
mock_string_io.assert_called_once_with("fake_data v1 v2")
class LxcHostTestCase(test.TestCase):
def setUp(self):
super(LxcHostTestCase, self).setUp()
sample_config = {"network": "10.1.1.0/24",
"forward_ssh": True,
"tunnel_to": ["1.1.1.1", "2.2.2.2"]}
self.server = mock.Mock()
self.server.host = "fake_server_ip"
self.server.get_credentials.return_value = {"ip": "3.3.3.3"}
self.host = lxc.LxcHost(self.server, sample_config)
@mock.patch(MOD_NAME + "provider.Server")
def test__get_updated_server(self, mock_server):
server = self.host._get_updated_server(host="4.4.4.4")
new_server = mock_server.from_credentials({"host": "4.4.4.4"})
self.assertEqual(new_server, server)
def test_backingstore_btrfs(self):
self.server.ssh.execute.return_value = [0, "", ""]
self.assertEqual("btrfs", self.host.backingstore)
self.assertEqual("btrfs", self.host.backingstore)
# second call will return cached value
self.assertEqual([mock.call.ssh.execute("df -t btrfs /var/lib/lxc/")],
self.server.mock_calls)
def test_backingstore_none(self):
self.server.ssh.execute.return_value = [-1, "", ""]
self.assertEqual("", self.host.backingstore)
@mock.patch(MOD_NAME + "moves.StringIO")
@mock.patch(MOD_NAME + "_get_script", return_value="fake_script")
def test_prepare(self, mock__get_script, mock_string_io):
mock_string_io.return_value = fake_conf = mock.Mock()
self.host.create_local_tunnels = mock.Mock()
self.host.create_remote_tunnels = mock.Mock()
self.host.prepare()
write_calls = [
mock.call("LXC_DHCP_MAX=\"253\"\n"),
mock.call("LXC_NETMASK=\"255.255.255.0\"\n"),
mock.call("LXC_ADDR=\"10.1.1.1\"\n"),
mock.call("LXC_DHCP_RANGE=\"10.1.1.2,10.1.1.254\"\n"),
mock.call("LXC_NETWORK=\"10.1.1.0/24\"\n"),
mock.call("LXC_BRIDGE=\"lxcbr0\"\n"),
mock.call("USE_LXC_BRIDGE=\"true\"\n")
]
for call in write_calls:
fake_conf.write.assert_has_calls(call)
ssh_calls = [mock.call.run("cat > /tmp/.lxc_default", stdin=fake_conf),
mock.call.run("/bin/sh", stdin="fake_script")]
self.assertEqual(ssh_calls, self.server.ssh.mock_calls)
self.host.create_local_tunnels.assert_called_once_with()
self.host.create_remote_tunnels.assert_called_once_with()
@mock.patch(MOD_NAME + "os.unlink")
@mock.patch(MOD_NAME + "_get_script_from_template")
def test_create_local_tunnels(self, mock__get_script_from_template,
mock_unlink):
mock__get_script_from_template.side_effect = ["s1", "s2"]
self.host.create_local_tunnels()
getscript_calls = [
mock.call("tunnel-local.sh", local="fake_server_ip",
net=netaddr.IPNetwork("10.1.1.0/24"), remote="1.1.1.1"),
mock.call("tunnel-local.sh", local="fake_server_ip",
net=netaddr.IPNetwork("10.1.1.0/24"), remote="2.2.2.2"),
]
self.assertEqual(
getscript_calls, mock__get_script_from_template.mock_calls)
self.assertEqual([mock.call("/bin/sh", stdin="s1"),
mock.call("/bin/sh", stdin="s2")],
self.server.ssh.run.mock_calls)
@mock.patch(MOD_NAME + "_get_script_from_template")
def test_create_remote_tunnels(self, mock__get_script_from_template):
mock__get_script_from_template.side_effect = ["s1", "s2"]
fake_server = mock.Mock()
self.host._get_updated_server = mock.Mock(return_value=fake_server)
self.host.create_remote_tunnels()
self.assertEqual([mock.call("/bin/sh", stdin="s1"),
mock.call("/bin/sh", stdin="s2")],
fake_server.ssh.run.mock_calls)
def test_delete_tunnels(self):
s1 = mock.Mock()
s2 = mock.Mock()
self.host._get_updated_server = mock.Mock(side_effect=[s1, s2])
self.host.delete_tunnels()
s1.ssh.execute.assert_called_once_with("ip tun del t10.1.1.0")
s2.ssh.execute.assert_called_once_with("ip tun del t10.1.1.0")
self.assertEqual([mock.call("ip tun del t1.1.1.1"),
mock.call("ip tun del t2.2.2.2")],
self.server.ssh.execute.mock_calls)
@mock.patch(MOD_NAME + "time.sleep")
def test_get_ip(self, mock_sleep):
s1 = "link/ether fe:54:00:d3:f5:98 brd ff:ff:ff:ff:ff:ff"
s2 = s1 + "\n inet 10.20.0.1/24 scope global br1"
self.host.server.ssh.execute.side_effect = [(0, s1, ""), (0, s2, "")]
ip = self.host.get_ip("name")
self.assertEqual("10.20.0.1", ip)
self.assertEqual([mock.call("lxc-attach -n name ip"
" addr list dev eth0")] * 2,
self.host.server.ssh.execute.mock_calls)
def test_create_container(self):
self.host.configure_container = mock.Mock()
self.host._backingstore = "btrfs"
self.host.create_container("name", "dist")
self.server.ssh.run.assert_called_once_with(
"lxc-create -B btrfs -n name -t dist")
self.assertEqual(["name"], self.host.containers)
self.host.configure_container.assert_called_once_with("name")
# check with no btrfs
self.host._backingstore = ""
self.host.create_container("name", "dist")
self.assertEqual(mock.call("lxc-create -n name -t dist"),
self.server.ssh.run.mock_calls[1])
# check release
self.host.create_container("name", "ubuntu", "raring")
self.host.create_container("name", "debian", "woody")
expected = [mock.call("lxc-create -n name -t ubuntu -- -r raring"),
mock.call("SUITE=woody lxc-create -n name -t debian")]
self.assertEqual(expected, self.server.ssh.run.mock_calls[2:])
def test_create_clone(self):
self.host._backingstore = "btrfs"
self.host.configure_container = mock.Mock()
self.host.create_clone("name", "src")
self.server.ssh.execute.assert_called_once_with("lxc-clone --snapshot"
" -o src -n name")
self.assertEqual(["name"], self.host.containers)
# check with no btrfs
self.host._backingstore = ""
self.host.create_clone("name", "src")
self.assertEqual(mock.call("lxc-clone -o src -n name"),
self.server.ssh.execute.mock_calls[1])
@mock.patch(MOD_NAME + "os.path.join")
@mock.patch(MOD_NAME + "_get_script")
def test_configure_container(self, mock__get_script, mock_join):
mock__get_script.return_value = "fake_script"
mock_join.return_value = "fake_path"
self.server.ssh.execute.return_value = 0, "", ""
self.host.configure_container("name")
self.server.ssh.run.assert_called_once_with(
"/bin/sh -e -s fake_path", stdin="fake_script")
def test_start_containers(self):
self.host.containers = ["c1", "c2"]
self.host.start_containers()
calls = [mock.call("lxc-start -d -n c1"),
mock.call("lxc-start -d -n c2")]
self.assertEqual(calls, self.server.ssh.run.mock_calls)
def test_stop_containers(self):
self.host.containers = ["c1", "c2"]
self.host.stop_containers()
calls = [
mock.call("lxc-stop -n c1"),
mock.call("lxc-stop -n c2"),
]
self.assertEqual(calls, self.server.ssh.run.mock_calls)
def test_destroy_containers(self):
self.host.containers = ["c1", "c2"]
self.host.destroy_containers()
calls = [
mock.call("lxc-stop -n c1"), mock.call("lxc-destroy -n c1"),
mock.call("lxc-stop -n c2"), mock.call("lxc-destroy -n c2"),
]
self.assertEqual(calls, self.server.ssh.run.mock_calls)
def test_get_server_object(self):
fake_server = mock.Mock()
self.host.get_ip = mock.Mock(return_value="ip")
self.host.get_port = mock.Mock(return_value=42)
self.host._get_updated_server = mock.Mock(return_value=fake_server)
so = self.host.get_server_object("c1", wait=False)
self.assertEqual(fake_server, so)
self.host.get_port.assert_called_once_with("ip")
self.host._get_updated_server.assert_called_once_with(port=42)
self.assertFalse(fake_server.ssh.wait.mock_calls)
so = self.host.get_server_object("c1", wait=True)
fake_server.ssh.wait.assert_called_once_with(timeout=300)
@mock.patch(MOD_NAME + "LxcHost.get_server_object")
def test_get_server_objects(self, mock_get_server_object):
mock_get_server_object.side_effect = ["s1", "s2"]
self.host.containers = ["c1", "c2"]
retval = list(self.host.get_server_objects(wait="wait"))
self.assertEqual(["s1", "s2"], retval)
self.assertEqual([mock.call("c1", "wait"), mock.call("c2", "wait")],
mock_get_server_object.mock_calls)
class LxcProviderTestCase(test.TestCase):
def setUp(self):
super(LxcProviderTestCase, self).setUp()
self.config = {
"type": "LxcProvider",
"distribution": "ubuntu",
"start_lxc_network": "10.1.1.0/29",
"containers_per_host": 2,
"tunnel_to": ["10.10.10.10", "20.20.20.20"],
"container_name_prefix": "rally-lxc",
"host_provider": {
"name": "ExistingServers",
"credentials": [{"user": "root", "host": "host1.net"},
{"user": "root", "host": "host2.net"}]}
}
self.deployment = {"uuid": "fake_uuid"}
self.provider = lxc.LxcProvider(self.deployment, self.config)
def test_validate(self):
self.provider.validate()
def test_validate_invalid_tunnel(self):
config = self.config.copy()
config["tunnel_to"] = "ok"
self.assertRaises(jsonschema.ValidationError,
lxc.LxcProvider, self.deployment, config)
def test_validate_required_field(self):
config = self.config.copy()
del(config["host_provider"])
self.assertRaises(jsonschema.ValidationError,
lxc.LxcProvider, self.deployment, config)
def test_validate_too_small_network(self):
config = self.config.copy()
config["containers_per_host"] = 42
self.assertRaises(exceptions.InvalidConfigException,
lxc.LxcProvider, self.deployment, config)
@mock.patch(MOD_NAME + "LxcHost")
@mock.patch(MOD_NAME + "provider.ProviderFactory.get_provider")
def test_create_servers(self, mock_provider_factory_get_provider,
mock_lxc_host):
fake_provider = mock.Mock()
fake_provider.create_servers.return_value = ["server1", "server2"]
fake_hosts = []
fake_sos = []
for i in (1, 2):
fake_host_sos = [mock.Mock(), mock.Mock()]
fake_sos.extend(fake_host_sos)
fake_host = mock.Mock()
fake_host.containers = ["c-%d-1" % i, "c-%d-2" % i]
fake_host._port_cache = {1: i, 2: i}
fake_host.config = {"network": "fake-%d" % i}
fake_host.server.get_credentials.return_value = {"ip": "f%d" % i}
fake_host.get_server_objects.return_value = fake_host_sos
fake_hosts.append(fake_host)
mock_lxc_host.side_effect = fake_hosts
mock_provider_factory_get_provider.return_value = fake_provider
fake_info = [
{"host": {"ip": "f1"},
"config": {"network": "fake-1"},
"forwarded_ports": [(1, 1), (2, 1)],
"container_names": ["c-1-1", "c-1-2"]},
{"host": {"ip": "f2"},
"config": {"network": "fake-2"},
"forwarded_ports": [(1, 2), (2, 2)],
"container_names": ["c-2-1", "c-2-2"]}]
def res_create(actual_info):
expected_info = fake_info.pop(0)
self.assertEqual(expected_info["host"], actual_info["host"])
self.assertEqual(expected_info["config"], actual_info["config"])
self.assertEqual(expected_info["container_names"],
actual_info["container_names"])
self.assertSequenceEqual(expected_info["forwarded_ports"],
actual_info["forwarded_ports"])
fake_res = mock.MagicMock()
fake_res.create = res_create
with mock.patch.object(self.provider, "resources", fake_res):
servers = self.provider.create_servers()
self.assertEqual(fake_sos, servers)
host1_calls = [
mock.call.prepare(),
mock.call.create_container("rally-lxc-000-10-1-1-0",
"ubuntu", None),
mock.call.create_clone("rally-lxc-001-10-1-1-0",
"rally-lxc-000-10-1-1-0"),
mock.call.start_containers(),
mock.call.get_server_objects(),
mock.call.server.get_credentials(),
]
host2_calls = [
mock.call.prepare(),
mock.call.create_container("rally-lxc-000-10-1-1-8",
"ubuntu", None),
mock.call.create_clone("rally-lxc-001-10-1-1-8",
"rally-lxc-000-10-1-1-8"),
mock.call.start_containers(),
mock.call.get_server_objects(),
mock.call.server.get_credentials(),
]
self.assertEqual(host1_calls, fake_hosts[0].mock_calls)
self.assertEqual(host2_calls, fake_hosts[1].mock_calls)
@mock.patch(MOD_NAME + "LxcHost")
@mock.patch(MOD_NAME + "provider.Server.from_credentials")
def test_destroy_servers(self, mock_server_from_credentials,
mock_lxc_host):
fake_resource = {"info": {"config": "fake_config",
"host": "fake_credentials",
"forwarded_ports": [1, 2],
"container_names": ["n1", "n2"]}}
fake_resource["id"] = "fake_res_id"
fake_host = mock.Mock()
mock_server_from_credentials.return_value = "fake_server"
mock_lxc_host.return_value = fake_host
self.provider.resources = mock.Mock()
self.provider.resources.get_all.return_value = [fake_resource]
with mock.patch.object(self.provider, "get_host_provider") as ghp:
ghp.return_value = fake_host_provider = mock.Mock()
self.provider.destroy_servers()
mock_lxc_host.assert_called_once_with("fake_server", "fake_config")
host_calls = [mock.call.destroy_containers(),
mock.call.destroy_ports([1, 2]),
mock.call.delete_tunnels()]
self.assertEqual(host_calls, fake_host.mock_calls)
self.provider.resources.delete.assert_called_once_with("fake_res_id")
fake_host_provider.destroy_servers.assert_called_once_with()