From cb606f45e3852432787ed895dc55665caa950161 Mon Sep 17 00:00:00 2001 From: Tim Rozet Date: Fri, 8 Sep 2017 16:57:36 -0400 Subject: Migrates clean to python ci/clean.sh will be removed in a future patch after releng is updated to use python. JIRA: APEX-509 JIRA: APEX-319 Change-Id: If890db2fc5a31833ad28ec6f04589e25457bd380 Signed-off-by: Tim Rozet --- apex/tests/config/bad_ifcfg-br-external | 8 + apex/tests/config/bad_nova_output.json | 23 +++ apex/tests/config/ifcfg-br-dummy | 9 + apex/tests/config/ifcfg-br-external | 10 ++ apex/tests/config/ifcfg-dummy | 7 + apex/tests/test_apex_clean.py | 69 +++++++- apex/tests/test_apex_common_parsers.py | 21 ++- apex/tests/test_apex_network_jumphost.py | 276 +++++++++++++++++++++++++++++++ 8 files changed, 417 insertions(+), 6 deletions(-) create mode 100644 apex/tests/config/bad_ifcfg-br-external create mode 100644 apex/tests/config/bad_nova_output.json create mode 100644 apex/tests/config/ifcfg-br-dummy create mode 100644 apex/tests/config/ifcfg-br-external create mode 100644 apex/tests/config/ifcfg-dummy create mode 100644 apex/tests/test_apex_network_jumphost.py (limited to 'apex/tests') diff --git a/apex/tests/config/bad_ifcfg-br-external b/apex/tests/config/bad_ifcfg-br-external new file mode 100644 index 00000000..85b81959 --- /dev/null +++ b/apex/tests/config/bad_ifcfg-br-external @@ -0,0 +1,8 @@ +DEVICE=br-external +DEVICETYPE=ovs +BOOTPROTO=static +ONBOOT=yes +TYPE=OVSBridge +PROMISC=yes +IPADDR=172.30.9.66 +NETMASK=255.255.255.0 diff --git a/apex/tests/config/bad_nova_output.json b/apex/tests/config/bad_nova_output.json new file mode 100644 index 00000000..137750e5 --- /dev/null +++ b/apex/tests/config/bad_nova_output.json @@ -0,0 +1,23 @@ +[ + { + "Status": "ACTIVE", + "Networks": "", + "ID": "a5ff8aeb-5fd0-467f-9d89-791dfbc6267b", + "Image Name": "overcloud-full", + "Name": "test3" + }, + { + "Status": "ACTIVE", + "Networks": "", + "ID": "c8be26ae-6bef-4841-bb03-c7f336cfd785", + "Image Name": "overcloud-full", + "Name": "test2" + }, + { + "Status": "ACTIVE", + "Networks": "", + "ID": "105d1c61-78d3-498f-9191-6b21823b8544", + "Image Name": "overcloud-full", + "Name": "test1" + } +] diff --git a/apex/tests/config/ifcfg-br-dummy b/apex/tests/config/ifcfg-br-dummy new file mode 100644 index 00000000..117ca726 --- /dev/null +++ b/apex/tests/config/ifcfg-br-dummy @@ -0,0 +1,9 @@ +DEVICE=br-dummy +DEVICETYPE=ovs +BOOTPROTO=static +ONBOOT=yes +TYPE=OVSBridge +PROMISC=yes +IPADDR=152.30.9.11 +NETMASK=255.255.255.0 +PEERDNS=no \ No newline at end of file diff --git a/apex/tests/config/ifcfg-br-external b/apex/tests/config/ifcfg-br-external new file mode 100644 index 00000000..9717d6e3 --- /dev/null +++ b/apex/tests/config/ifcfg-br-external @@ -0,0 +1,10 @@ +DEVICE=br-external +DEVICETYPE=ovs +BOOTPROTO=static +ONBOOT=yes +TYPE=OVSBridge +PROMISC=yes +IPADDR=172.30.9.66 +NETMASK=255.255.255.0 +GATEWAY=172.30.9.1 +#DNS1=1.1.1.1 diff --git a/apex/tests/config/ifcfg-dummy b/apex/tests/config/ifcfg-dummy new file mode 100644 index 00000000..f9ca21d4 --- /dev/null +++ b/apex/tests/config/ifcfg-dummy @@ -0,0 +1,7 @@ +DEVICE=enpfakes0 +TYPE=Ethernet +ONBOOT=yes +BOOTPROTO=static +NM_CONTROLLED=no +IPADDR=152.30.9.11 +NETMASK=255.255.255.0 diff --git a/apex/tests/test_apex_clean.py b/apex/tests/test_apex_clean.py index 7b7df512..b6b9d428 100644 --- a/apex/tests/test_apex_clean.py +++ b/apex/tests/test_apex_clean.py @@ -8,12 +8,48 @@ ############################################################################## import mock +import os import pyipmi import pyipmi.chassis from mock import patch -from nose import tools +from nose.tools import ( + assert_raises, + assert_equal +) from apex import clean_nodes +from apex import clean +from apex.tests import constants as con + + +class dummy_domain: + + def isActive(self): + return True + + def destroy(self): + pass + + def undefine(self): + pass + + +class dummy_vol: + + def wipe(self, *args): + pass + + def delete(self, *args): + pass + + +class dummy_pool: + + def storageVolLookupByName(self, *args, **kwargs): + return dummy_vol() + + def refresh(self): + pass class TestClean: @@ -31,11 +67,36 @@ class TestClean: def teardown(self): """This method is run once after _each_ test method is executed""" - def test_clean(self): + def test_clean_nodes(self): with mock.patch.object(pyipmi.Session, 'establish') as mock_method: with patch.object(pyipmi.chassis.Chassis, 'chassis_control_power_down') as mock_method2: clean_nodes('apex/tests/config/inventory.yaml') - tools.assert_equal(mock_method.call_count, 5) - tools.assert_equal(mock_method2.call_count, 5) + assert_equal(mock_method.call_count, 5) + assert_equal(mock_method2.call_count, 5) + + @patch('virtualbmc.manager.VirtualBMCManager.list', + return_value=[{'domain_name': 'dummy1'}, {'domain_name': 'dummy2'}]) + @patch('virtualbmc.manager.VirtualBMCManager.delete') + def test_vmbc_clean(self, vbmc_del_func, vbmc_list_func): + assert clean.clean_vbmcs() is None + + def test_clean_ssh_keys(self): + ssh_file = os.path.join(con.TEST_DUMMY_CONFIG, 'authorized_dummy') + with open(ssh_file, 'w') as fh: + fh.write('ssh-rsa 2LwlofGD8rNUFAlafY2/oUsKOf1mQ1 stack@undercloud') + assert clean.clean_ssh_keys(ssh_file) is None + with open(ssh_file, 'r') as fh: + output = fh.read() + assert 'stack@undercloud' not in output + if os.path.isfile(ssh_file): + os.remove(ssh_file) + + @patch('libvirt.open') + def test_clean_vms(self, mock_libvirt): + ml = mock_libvirt.return_value + ml.storagePoolLookupByName.return_value = dummy_pool() + ml.listDefinedDomains.return_value = ['undercloud'] + ml.lookupByName.return_value = dummy_domain() + assert clean.clean_vms() is None diff --git a/apex/tests/test_apex_common_parsers.py b/apex/tests/test_apex_common_parsers.py index bed2a8c5..d272a749 100644 --- a/apex/tests/test_apex_common_parsers.py +++ b/apex/tests/test_apex_common_parsers.py @@ -11,9 +11,11 @@ import os from apex.tests import constants as con from apex.common import parsers as apex_parsers +from apex.common.exceptions import ApexDeployException from nose.tools import ( assert_is_instance, - assert_dict_equal + assert_dict_equal, + assert_raises ) @@ -41,9 +43,13 @@ class TestCommonParsers: 'overcloud-novacompute-0': '192.30.9.10', 'overcloud-novacompute-1': '192.30.9.9' } - print(output) assert_dict_equal(output, nodes) + def test_negative_parse_nova_output(self): + assert_raises(ApexDeployException, apex_parsers.parse_nova_output, + os.path.join(con.TEST_DUMMY_CONFIG, + 'bad_nova_output.json')) + def test_parse_overcloudrc(self): output = apex_parsers.parse_overcloudrc( os.path.join(con.TEST_DUMMY_CONFIG, 'test_overcloudrc')) @@ -52,3 +58,14 @@ class TestCommonParsers: assert output['OS_AUTH_TYPE'] == 'password' assert 'OS_PASSWORD' in output.keys() assert output['OS_PASSWORD'] == 'Wd8ruyf6qG8cmcms6dq2HM93f' + + def test_parse_ifcfg(self): + output = apex_parsers.parse_ifcfg_file( + os.path.join(con.TEST_DUMMY_CONFIG, 'ifcfg-br-external')) + assert_is_instance(output, dict) + assert 'IPADDR' in output.keys() + assert output['IPADDR'] == '172.30.9.66' + assert 'NETMASK' in output.keys() + assert output['NETMASK'] == '255.255.255.0' + assert 'DNS1' in output.keys() + assert not output['DNS1'] diff --git a/apex/tests/test_apex_network_jumphost.py b/apex/tests/test_apex_network_jumphost.py new file mode 100644 index 00000000..a23f1c56 --- /dev/null +++ b/apex/tests/test_apex_network_jumphost.py @@ -0,0 +1,276 @@ +############################################################################## +# Copyright (c) 2016 Dan Radez (Red Hat) +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import os +import shutil +import subprocess + +from apex import NetworkSettings +from apex.tests import constants as con +from apex.common import constants as apex_constants +from apex.network import jumphost +from apex.common.exceptions import JumpHostNetworkException +from ipaddress import IPv4Interface +from mock import patch +from nose.tools import ( + assert_is_instance, + assert_dict_equal, + assert_raises, + assert_true, + assert_false +) + + +def bridge_show_output(*args, **kwargs): + return b""" + b6f1b54a-b8ba-4e86-9c5b-733ab71b5712 + Bridge br-admin + Port br-admin + Interface br-admin + type: internal + ovs_version: "2.5.0" +""" + + +def bridge_port_list(*args, **kwargs): + return b""" +enp6s0 +vnet1 +""" + + +def subprocess_exception(*args, **kwargs): + raise subprocess.CalledProcessError(returncode=2, cmd='dummy') + + +class TestNetworkJumpHost: + @classmethod + def setup_class(cls): + """This method is run once for each class before any tests are run""" + + @classmethod + def teardown_class(cls): + """This method is run once for each class _after_ all tests are run""" + + def setup(self): + """This method is run once before _each_ test method is executed""" + + def teardown(self): + """This method is run once after _each_ test method is executed""" + + @patch('subprocess.check_output', side_effect=bridge_show_output) + def test_is_ovs_bridge(self, bridge_output_function): + assert_true(jumphost.is_ovs_bridge('br-admin')) + assert_false(jumphost.is_ovs_bridge('br-blah')) + + @patch('subprocess.check_output', side_effect=bridge_port_list) + def test_dump_ovs_ports(self, bridge_function): + output = jumphost.dump_ovs_ports('br-admin') + assert_is_instance(output, list) + assert 'enp6s0' in output + + def test_generate_ifcfg_params(self): + output = jumphost.generate_ifcfg_params( + os.path.join(con.TEST_DUMMY_CONFIG, 'ifcfg-br-external'), + apex_constants.EXTERNAL_NETWORK) + assert_is_instance(output, dict) + assert output['IPADDR'] == '172.30.9.66' + assert output['PEERDNS'] == 'no' + + def test_negative_generate_ifcfg_params(self): + assert_raises(JumpHostNetworkException, jumphost.generate_ifcfg_params, + os.path.join(con.TEST_DUMMY_CONFIG, + 'bad_ifcfg-br-external'), + apex_constants.EXTERNAL_NETWORK) + + @patch('subprocess.check_call') + @patch('apex.network.ip_utils.get_interface', return_value=IPv4Interface( + '10.10.10.2')) + def test_configure_bridges_ip_exists(self, interface_function, + subprocess_func): + ns = NetworkSettings(os.path.join(con.TEST_CONFIG_DIR, + 'network', 'network_settings.yaml')) + assert jumphost.configure_bridges(ns) is None + + @patch('subprocess.check_call') + @patch('apex.network.ip_utils.get_interface', return_value=None) + def test_configure_bridges_no_ip(self, interface_function, + subprocess_func): + ns = NetworkSettings(os.path.join(con.TEST_CONFIG_DIR, + 'network', 'network_settings.yaml')) + assert jumphost.configure_bridges(ns) is None + + @patch('subprocess.check_call', side_effect=subprocess_exception) + @patch('apex.network.ip_utils.get_interface', return_value=None) + def test_negative_configure_bridges(self, interface_function, + subprocess_func): + ns = NetworkSettings(os.path.join(con.TEST_CONFIG_DIR, + 'network', 'network_settings.yaml')) + assert_raises(subprocess.CalledProcessError, + jumphost.configure_bridges, ns) + + @patch('subprocess.check_call') + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=[]) + def test_attach_interface(self, dump_ports_func, is_bridge_func, + subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + shutil.copyfile(os.path.join(ifcfg_dir, 'ifcfg-dummy'), + os.path.join(ifcfg_dir, 'ifcfg-enpfakes0')) + shutil.copyfile(os.path.join(ifcfg_dir, 'ifcfg-br-dummy'), + os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + jumphost.NET_CFG_PATH = ifcfg_dir + output = jumphost.attach_interface_to_ovs('br-admin', 'enpfakes0', + 'admin') + assert output is None + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-enpfakes0')) + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-enpfakes0.orig')) + + for ifcfg in ('ifcfg-enpfakes0', 'ifcfg-enpfakes0.orig', + 'ifcfg-br-admin'): + ifcfg_path = os.path.join(ifcfg_dir, ifcfg) + if os.path.isfile(ifcfg_path): + os.remove(ifcfg_path) + + @patch('subprocess.check_call') + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=['dummy_int']) + def test_already_attached_interface(self, dump_ports_func, is_bridge_func, + subprocess_func): + output = jumphost.attach_interface_to_ovs('br-dummy', 'dummy_int', + 'admin') + assert output is None + + @patch('subprocess.check_call') + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=[]) + def test_negative_attach_interface(self, dump_ports_func, is_bridge_func, + subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + jumphost.NET_CFG_PATH = ifcfg_dir + assert_raises(FileNotFoundError, jumphost.attach_interface_to_ovs, + 'br-dummy', 'dummy_int', 'admin') + + @patch('subprocess.check_call', side_effect=subprocess_exception) + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=[]) + def test_negative_attach_interface_process_error( + self, dump_ports_func, is_bridge_func, subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + shutil.copyfile(os.path.join(ifcfg_dir, 'ifcfg-dummy'), + os.path.join(ifcfg_dir, 'ifcfg-enpfakes0')) + shutil.copyfile(os.path.join(ifcfg_dir, 'ifcfg-br-dummy'), + os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + jumphost.NET_CFG_PATH = ifcfg_dir + assert_raises(subprocess.CalledProcessError, + jumphost.attach_interface_to_ovs, + 'br-admin', 'enpfakes0', 'admin') + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-enpfakes0')) + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-enpfakes0.orig')) + + for ifcfg in ('ifcfg-enpfakes0', 'ifcfg-enpfakes0.orig', + 'ifcfg-br-admin'): + ifcfg_path = os.path.join(ifcfg_dir, ifcfg) + if os.path.isfile(ifcfg_path): + os.remove(ifcfg_path) + + @patch('subprocess.check_call') + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=['enpfakes0']) + def test_detach_interface(self, dump_ports_func, is_bridge_func, + subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + shutil.copyfile(os.path.join(ifcfg_dir, 'ifcfg-br-dummy'), + os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + jumphost.NET_CFG_PATH = ifcfg_dir + output = jumphost.detach_interface_from_ovs('admin') + assert output is None + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-enpfakes0')) + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + + for ifcfg in ('ifcfg-enpfakes0', 'ifcfg-enpfakes0.orig', + 'ifcfg-br-admin'): + ifcfg_path = os.path.join(ifcfg_dir, ifcfg) + if os.path.isfile(ifcfg_path): + os.remove(ifcfg_path) + + @patch('subprocess.check_call') + @patch('apex.network.jumphost.is_ovs_bridge', return_value=False) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=[]) + def test_detach_interface_no_bridge(self, dump_ports_func, + is_bridge_func, subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + jumphost.NET_CFG_PATH = ifcfg_dir + output = jumphost.detach_interface_from_ovs('admin') + assert output is None + + @patch('subprocess.check_call') + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=[]) + def test_detach_interface_no_int_to_remove(self, dump_ports_func, + is_bridge_func, + subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + jumphost.NET_CFG_PATH = ifcfg_dir + output = jumphost.detach_interface_from_ovs('admin') + assert output is None + + @patch('subprocess.check_call') + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=['enpfakes0']) + def test_negative_detach_interface(self, dump_ports_func, is_bridge_func, + subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + jumphost.NET_CFG_PATH = ifcfg_dir + assert_raises(FileNotFoundError, jumphost.detach_interface_from_ovs, + 'admin') + + @patch('subprocess.check_call', side_effect=subprocess_exception) + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + @patch('apex.network.jumphost.dump_ovs_ports', return_value=['enpfakes0']) + def test_negative_detach_interface_process_error( + self, dump_ports_func, is_bridge_func, subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + shutil.copyfile(os.path.join(ifcfg_dir, 'ifcfg-br-dummy'), + os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + jumphost.NET_CFG_PATH = ifcfg_dir + assert_raises(subprocess.CalledProcessError, + jumphost.detach_interface_from_ovs, 'admin') + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-enpfakes0')) + assert os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + + for ifcfg in ('ifcfg-enpfakes0', 'ifcfg-enpfakes0.orig', + 'ifcfg-br-admin'): + ifcfg_path = os.path.join(ifcfg_dir, ifcfg) + if os.path.isfile(ifcfg_path): + os.remove(ifcfg_path) + + @patch('subprocess.check_call') + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + def test_remove_ovs_bridge(self, is_bridge_func, subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + jumphost.NET_CFG_PATH = ifcfg_dir + shutil.copyfile(os.path.join(ifcfg_dir, 'ifcfg-br-dummy'), + os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + assert jumphost.remove_ovs_bridge(apex_constants.ADMIN_NETWORK) is None + assert not os.path.isfile(os.path.join(ifcfg_dir, 'ifcfg-br-admin')) + + # test without file + assert jumphost.remove_ovs_bridge(apex_constants.ADMIN_NETWORK) is None + + @patch('subprocess.check_call', side_effect=subprocess_exception) + @patch('apex.network.jumphost.is_ovs_bridge', return_value=True) + def test_negative_remove_ovs_bridge(self, is_bridge_func, subprocess_func): + ifcfg_dir = con.TEST_DUMMY_CONFIG + jumphost.NET_CFG_PATH = ifcfg_dir + assert_raises(subprocess.CalledProcessError, + jumphost.remove_ovs_bridge, + apex_constants.ADMIN_NETWORK) -- cgit 1.2.3-korg