From f4d388ea508ba00771e43a219ac64e0d430b73bd Mon Sep 17 00:00:00 2001 From: Tim Rozet Date: Sun, 25 Jun 2017 21:25:36 -0400 Subject: Migrates Apex to Python Removes all bash libraries and converts almost all of the code to a mixture of Python and Ansible. utils.sh and clean.sh still exist. clean.sh will be migrated fully to clean.py in another patch. The Apex Python package is now built into the opnfv-apex-common RPM. To install locally do 'pip3 install .'. To deploy: opnfv-deploy -d -n --image-dir /root/apex/.build -v --debug Non-python files (THT yaml, settings files, ansible playbooks) are all installed into /usr/share/opnfv-apex/. The RPM will copy settings files into /etc/opnfv-apex/. JIRA: APEX-317 Change-Id: I3232f0329bcd13bce5a28da6a8c9c84d0b048024 Signed-off-by: Tim Rozet --- apex/tests/__init__.py | 0 apex/tests/config/inventory.yaml | 57 +++++++++ apex/tests/constants.py | 12 ++ apex/tests/playbooks/test_playbook.yaml | 5 + apex/tests/smoke_tests/execute_smoke_tests.sh | 3 + apex/tests/smoke_tests/execute_tests.yml | 11 ++ apex/tests/smoke_tests/prepare_undercloud.yml | 9 ++ apex/tests/smoke_tests/smoke_tests.yml | 3 + apex/tests/test_apex_clean.py | 41 +++++++ apex/tests/test_apex_common_utils.py | 59 +++++++++ apex/tests/test_apex_deploy_settings.py | 101 +++++++++++++++ apex/tests/test_apex_inventory.py | 69 +++++++++++ apex/tests/test_apex_ip_utils.py | 132 ++++++++++++++++++++ apex/tests/test_apex_network_environment.py | 169 ++++++++++++++++++++++++++ apex/tests/test_apex_network_settings.py | 156 ++++++++++++++++++++++++ 15 files changed, 827 insertions(+) create mode 100644 apex/tests/__init__.py create mode 100644 apex/tests/config/inventory.yaml create mode 100644 apex/tests/constants.py create mode 100644 apex/tests/playbooks/test_playbook.yaml create mode 100755 apex/tests/smoke_tests/execute_smoke_tests.sh create mode 100644 apex/tests/smoke_tests/execute_tests.yml create mode 100644 apex/tests/smoke_tests/prepare_undercloud.yml create mode 100644 apex/tests/smoke_tests/smoke_tests.yml create mode 100644 apex/tests/test_apex_clean.py create mode 100644 apex/tests/test_apex_common_utils.py create mode 100644 apex/tests/test_apex_deploy_settings.py create mode 100644 apex/tests/test_apex_inventory.py create mode 100644 apex/tests/test_apex_ip_utils.py create mode 100644 apex/tests/test_apex_network_environment.py create mode 100644 apex/tests/test_apex_network_settings.py (limited to 'apex/tests') diff --git a/apex/tests/__init__.py b/apex/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apex/tests/config/inventory.yaml b/apex/tests/config/inventory.yaml new file mode 100644 index 00000000..2abe0fc9 --- /dev/null +++ b/apex/tests/config/inventory.yaml @@ -0,0 +1,57 @@ +--- +nodes: + node1: + mac_address: "00:25:B5:cc:00:1e" + ipmi_ip: 72.30.8.69 + ipmi_user: admin + ipmi_pass: octopus + pm_type: "pxe_ipmitool" + cpus: 2 + memory: 8192 + disk: 40 + arch: "x86_64" + capabilities: "profile:control" + node2: + mac_address: "00:25:B5:cc:00:5d" + ipmi_ip: 72.30.8.78 + ipmi_user: admin + ipmi_pass: octopus + pm_type: "pxe_ipmitool" + cpus: 2 + memory: 8192 + disk: 40 + arch: "x86_64" + capabilities: "profile:control" + node3: + mac_address: "00:25:B5:cc:00:1d" + ipmi_ip: 72.30.8.67 + ipmi_user: admin + ipmi_pass: octopus + pm_type: "pxe_ipmitool" + cpus: 2 + memory: 8192 + disk: 40 + arch: "x86_64" + capabilities: "profile:control" + node4: + mac_address: "00:25:B5:cc:00:3c" + ipmi_ip: 72.30.8.76 + ipmi_user: admin + ipmi_pass: octopus + pm_type: "pxe_ipmitool" + cpus: 2 + memory: 8192 + disk: 40 + arch: "x86_64" + capabilities: "profile:compute" + node5: + mac_address: "00:25:B5:cc:00:5b" + ipmi_ip: 72.30.8.71 + ipmi_user: admin + ipmi_pass: octopus + pm_type: "pxe_ipmitool" + cpus: 2 + memory: 8192 + disk: 40 + arch: "x86_64" + capabilities: "profile:compute" diff --git a/apex/tests/constants.py b/apex/tests/constants.py new file mode 100644 index 00000000..47e63e2c --- /dev/null +++ b/apex/tests/constants.py @@ -0,0 +1,12 @@ +############################################################################## +# Copyright (c) 2017 Tim Rozet (trozet@redhat.com) and others. +# +# 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 +############################################################################## + +TEST_CONFIG_DIR = 'config' +TEST_BUILD_DIR = 'build' +TEST_PLAYBOOK_DIR = 'playbooks' diff --git a/apex/tests/playbooks/test_playbook.yaml b/apex/tests/playbooks/test_playbook.yaml new file mode 100644 index 00000000..800d8fde --- /dev/null +++ b/apex/tests/playbooks/test_playbook.yaml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + tasks: + - debug: + msg: "Test playbook" diff --git a/apex/tests/smoke_tests/execute_smoke_tests.sh b/apex/tests/smoke_tests/execute_smoke_tests.sh new file mode 100755 index 00000000..27f95251 --- /dev/null +++ b/apex/tests/smoke_tests/execute_smoke_tests.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +python ~/snaps/snaps/test_runner.py -e ~stack/overcloudrc -n external -c -a -i -f -k -l INFO &> ~stack/smoke-tests.out \ No newline at end of file diff --git a/apex/tests/smoke_tests/execute_tests.yml b/apex/tests/smoke_tests/execute_tests.yml new file mode 100644 index 00000000..5042d230 --- /dev/null +++ b/apex/tests/smoke_tests/execute_tests.yml @@ -0,0 +1,11 @@ +--- +- hosts: all + become: yes + become_method: sudo + become_user: root + + tasks: + - name: Copy execute_smoke_tests.sh + copy: src=execute_smoke_tests.sh dest=~/execute_smoke_tests.sh mode=0755 + - name: Execute Tests + command: sh ~/execute_smoke_tests.sh | tee ~/unit_tests.out \ No newline at end of file diff --git a/apex/tests/smoke_tests/prepare_undercloud.yml b/apex/tests/smoke_tests/prepare_undercloud.yml new file mode 100644 index 00000000..7ad769c0 --- /dev/null +++ b/apex/tests/smoke_tests/prepare_undercloud.yml @@ -0,0 +1,9 @@ +--- +- hosts: all + become: yes + become_method: sudo + become_user: root + + tasks: + - git: repo=https://gerrit.opnfv.org/gerrit/snaps dest=~/snaps + - command: pip install -e ~/snaps/ diff --git a/apex/tests/smoke_tests/smoke_tests.yml b/apex/tests/smoke_tests/smoke_tests.yml new file mode 100644 index 00000000..b67c194f --- /dev/null +++ b/apex/tests/smoke_tests/smoke_tests.yml @@ -0,0 +1,3 @@ +--- +- include: prepare_undercloud.yml +- include: execute_tests.yml \ No newline at end of file diff --git a/apex/tests/test_apex_clean.py b/apex/tests/test_apex_clean.py new file mode 100644 index 00000000..d0b87917 --- /dev/null +++ b/apex/tests/test_apex_clean.py @@ -0,0 +1,41 @@ +############################################################################## +# Copyright (c) 2016 Tim Rozet (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 mock +import pyipmi +import pyipmi.chassis +from mock import patch +from nose import tools + +from apex import clean_nodes + + +class TestClean(object): + @classmethod + def setup_class(klass): + """This method is run once for each class before any tests are run""" + + @classmethod + def teardown_class(klass): + """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""" + + def test_clean(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) diff --git a/apex/tests/test_apex_common_utils.py b/apex/tests/test_apex_common_utils.py new file mode 100644 index 00000000..357ad1b0 --- /dev/null +++ b/apex/tests/test_apex_common_utils.py @@ -0,0 +1,59 @@ +############################################################################## +# 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 ipaddress +import nose.tools +import os + +from apex.common import utils +from apex.settings.network_settings import NetworkSettings +from apex.tests.constants import ( + TEST_CONFIG_DIR, + TEST_PLAYBOOK_DIR) + +NET_SETS = os.path.join(TEST_CONFIG_DIR, 'network', 'network_settings.yaml') + + +class TestCommonUtils(object): + @classmethod + def setup_class(klass): + """This method is run once for each class before any tests are run""" + + @classmethod + def teardown_class(klass): + """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""" + + def test_str2bool(self): + nose.tools.assert_equal(utils.str2bool(True), True) + nose.tools.assert_equal(utils.str2bool(False), False) + nose.tools.assert_equal(utils.str2bool("True"), True) + nose.tools.assert_equal(utils.str2bool("YES"), True) + + def test_parse_yaml(self): + nose.tools.assert_is_instance(utils.parse_yaml(NET_SETS), dict) + + def test_dict_to_string(self): + net_settings = NetworkSettings(NET_SETS) + output = utils.dict_objects_to_str(net_settings) + nose.tools.assert_is_instance(output, dict) + for k, v in output.items(): + nose.tools.assert_is_instance(k, str) + nose.tools.assert_not_is_instance(v, ipaddress.IPv4Address) + + def test_run_ansible(self): + playbook = 'apex/tests/playbooks/test_playbook.yaml' + nose.tools.assert_equal( + utils.run_ansible(None, os.path.join(playbook), + dry_run=True), None) diff --git a/apex/tests/test_apex_deploy_settings.py b/apex/tests/test_apex_deploy_settings.py new file mode 100644 index 00000000..312c1f3a --- /dev/null +++ b/apex/tests/test_apex_deploy_settings.py @@ -0,0 +1,101 @@ +############################################################################## +# 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 +############################################################################## + +# https://docs.python.org/3/library/io.html +import os +import tempfile + +from nose.tools import assert_equal +from nose.tools import assert_is_instance +from nose.tools import assert_raises + +from apex.settings.deploy_settings import DeploySettings +from apex.settings.deploy_settings import DeploySettingsException +from apex.tests.constants import TEST_CONFIG_DIR + +deploy_files = ('deploy_settings.yaml', + 'os-nosdn-nofeature-noha.yaml', + 'os-nosdn-ovs_dpdk-noha.yaml', + 'os-ocl-nofeature-ha.yaml', + 'os-odl-bgpvpn-ha.yaml', + 'os-odl-bgpvpn-noha.yaml', + 'os-odl-nofeature-ha.yaml', + 'os-nosdn-nofeature-ha.yaml', + 'os-nosdn-ovs_dpdk-ha.yaml', + 'os-nosdn-performance-ha.yaml', + 'os-odl-nofeature-ha.yaml', + 'os-onos-nofeature-ha.yaml', + 'os-onos-sfc-ha.yaml') + +test_deploy_content = ( + 'global_params:', + 'deploy_options: string', + """deploy_options: string +global_params:""", + """global_params: +deploy_options: + error: error +""", + """global_params: +deploy_options: + performance: string +""", + """global_params: +deploy_options: + dataplane: invalid +""", + """global_params: +deploy_options: + performance: + Controller: + error: error +""", + """global_params: +deploy_options: + performance: + InvalidRole: + error: error +""",) + + +class TestIpUtils(object): + @classmethod + def setup_class(klass): + """This method is run once for each class before any tests are run""" + + @classmethod + def teardown_class(klass): + """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""" + + def test_init(self): + for f in deploy_files: + ds = DeploySettings(os.path.join(TEST_CONFIG_DIR, 'deploy', f)) + ds = DeploySettings(ds) + + def test__validate_settings(self): + for c in test_deploy_content: + try: + f = tempfile.NamedTemporaryFile(mode='w') + f.write(c) + f.flush() + assert_raises(DeploySettingsException, + DeploySettings, f.name) + finally: + f.close() + + def test_exception(self): + e = DeploySettingsException("test") + print(e) + assert_is_instance(e, DeploySettingsException) diff --git a/apex/tests/test_apex_inventory.py b/apex/tests/test_apex_inventory.py new file mode 100644 index 00000000..ed95c53c --- /dev/null +++ b/apex/tests/test_apex_inventory.py @@ -0,0 +1,69 @@ +############################################################################## +# 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 sys +from io import StringIO + +from nose.tools import assert_equal +from nose.tools import assert_is_instance +from nose.tools import assert_raises +from nose.tools import assert_regexp_matches + +from apex import Inventory +from apex.inventory.inventory import InventoryException +from apex.tests.constants import TEST_CONFIG_DIR + +inventory_files = ('intel_pod2_settings.yaml', + 'nokia_pod1_settings.yaml', + 'pod_example_settings.yaml') + +files_dir = os.path.join(TEST_CONFIG_DIR, 'inventory') + + +class TestInventory(object): + @classmethod + def setup_class(klass): + """This method is run once for each class before any tests are run""" + + @classmethod + def teardown_class(klass): + """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""" + + def test_init(self): + for f in inventory_files: + i = Inventory(os.path.join(files_dir, f)) + assert_equal(i.dump_instackenv_json(), None) + + # test virtual + i = Inventory(i, virtual=True) + assert_equal(i.dump_instackenv_json(), None) + + # Remove nodes to violate HA node count + while len(i['nodes']) >= 5: + i['nodes'].pop() + assert_raises(InventoryException, + Inventory, i) + + # Remove nodes to violate non-HA node count + while len(i['nodes']) >= 2: + i['nodes'].pop() + assert_raises(InventoryException, + Inventory, i, ha=False) + + def test_exception(self): + e = InventoryException("test") + print(e) + assert_is_instance(e, InventoryException) diff --git a/apex/tests/test_apex_ip_utils.py b/apex/tests/test_apex_ip_utils.py new file mode 100644 index 00000000..04a1b2bb --- /dev/null +++ b/apex/tests/test_apex_ip_utils.py @@ -0,0 +1,132 @@ +############################################################################## +# 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 ipaddress +import re +from ipaddress import IPv4Address +from ipaddress import ip_network + +from nose.tools import assert_equal +from nose.tools import assert_false +from nose.tools import assert_is_instance +from nose.tools import assert_raises +from nose.tools import assert_regexp_matches +from nose.tools import assert_true + +from apex.network.ip_utils import IPUtilsException +from apex.network.ip_utils import _validate_ip_range +from apex.network.ip_utils import find_gateway +from apex.network.ip_utils import get_interface +from apex.network.ip_utils import get_ip +from apex.network.ip_utils import get_ip_range + +ip4_pattern = re.compile('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}') +ip4_range_pattern = re.compile('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3},\d{1,' + '3}\.\d{1,3}\.\d{1,3}\.\d{1,3}') + + +def get_default_gateway_linux(): + """Read the default gateway directly from /proc.""" + with open("/proc/net/route") as fh: + for line in fh: + fields = line.strip().split() + if fields[2] not in ('00000000', 'Gateway'): + return fields[0] + + +class TestIpUtils(object): + @classmethod + def setup_class(klass): + """This method is run once for each class before any tests are run""" + klass.iface_name = get_default_gateway_linux() + iface = get_interface(klass.iface_name) + klass.iface = iface + + @classmethod + def teardown_class(klass): + """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""" + + def test_get_interface(self): + assert_equal(get_interface(''), None) + assert_equal(get_interface('notreal'), None) + assert_is_instance(get_interface(self.iface_name, + address_family=4), + IPv4Address) + # can't enable this until there's a v6 address on the ci hosts + # assert_is_instance(get_interface( + # self.iface_name, + # address_family=6), IPv6Address) + assert_raises(IPUtilsException, + get_interface, self.iface_name, 0) + + def test_find_gateway(self): + assert_is_instance(find_gateway(self.iface), str) + iface_virbr0 = get_interface('virbr0') + assert_equal(find_gateway(iface_virbr0), None) + + def test_get_ip(self): + cidr = ipaddress.ip_network("10.10.10.0/24") + assert_equal(get_ip(1, cidr=cidr), "10.10.10.1") + assert_raises(IPUtilsException, get_ip, 1000, interface=self.iface) + assert_regexp_matches(get_ip(1, interface=self.iface), ip4_pattern) + assert_raises(IPUtilsException, get_ip, 1) + + def test_get_ip_range_raises(self): + assert_raises(IPUtilsException, get_ip_range) + assert_raises(IPUtilsException, get_ip_range, interface=self.iface) + + def test_get_ip_range_with_interface(self): + assert_regexp_matches(get_ip_range(interface=self.iface, + start_offset=1, end_offset=20), + ip4_range_pattern) + assert_regexp_matches(get_ip_range(interface=self.iface, + start_offset=1, count=10), + ip4_range_pattern) + assert_regexp_matches(get_ip_range(interface=self.iface, end_offset=20, + count=10), ip4_range_pattern) + + def test_get_ip_range_with_cidr(self): + cidr = ip_network('10.10.10.0/24') + assert_raises(IPUtilsException, get_ip_range, cidr=cidr) + assert_regexp_matches(get_ip_range(cidr=cidr, start_offset=1, + end_offset=20), ip4_pattern) + assert_regexp_matches(get_ip_range(cidr=cidr, start_offset=1, + count=10), ip4_pattern) + assert_regexp_matches(get_ip_range(cidr=cidr, end_offset=20, + count=10), ip4_pattern) + + def test__validate_ip_range(self): + cidr = ip_network('10.10.10.0/24') + assert_true(_validate_ip_range( + start_ip=ipaddress.IPv4Address('10.10.10.1'), + end_ip=ipaddress.IPv4Address('10.10.10.10'), + cidr=cidr)) + assert_false(_validate_ip_range( + start_ip=ipaddress.IPv4Address('10.10.10.10'), + end_ip=ipaddress.IPv4Address('10.10.10.1'), + cidr=cidr)) + assert_false(_validate_ip_range( + start_ip=ipaddress.IPv4Address('10.10.0.1'), + end_ip=ipaddress.IPv4Address('10.10.10.10'), + cidr=cidr)) + assert_false(_validate_ip_range( + start_ip=ipaddress.IPv4Address('10.10.10.1'), + end_ip=ipaddress.IPv4Address('10.10.11.10'), + cidr=cidr)) + + def test_exception(self): + e = IPUtilsException("test") + print(e) + assert_is_instance(e, IPUtilsException) diff --git a/apex/tests/test_apex_network_environment.py b/apex/tests/test_apex_network_environment.py new file mode 100644 index 00000000..5047adbb --- /dev/null +++ b/apex/tests/test_apex_network_environment.py @@ -0,0 +1,169 @@ +############################################################################## +# 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 + +from copy import copy + +from nose.tools import assert_equal +from nose.tools import assert_is_instance +from nose.tools import assert_not_equal +from nose.tools import assert_raises + +from apex.common.constants import ( + EXTERNAL_NETWORK, + TENANT_NETWORK, + STORAGE_NETWORK, + API_NETWORK, + NET_ENV_FILE) +from apex import NetworkEnvironment +from apex.network.network_environment import NetworkEnvException +from apex import NetworkSettings +from apex.tests.constants import TEST_CONFIG_DIR +from apex.tests.constants import TEST_BUILD_DIR + + +class TestNetworkEnvironment(object): + @classmethod + def setup_class(klass): + """This method is run once for each class before any tests are run""" + klass.ns = NetworkSettings( + os.path.join(TEST_CONFIG_DIR, 'network/network_settings.yaml')) + klass.ns_vlans = NetworkSettings( + os.path.join(TEST_CONFIG_DIR, + 'network/network_settings_vlans.yaml')) + klass.ns_ipv6 = NetworkSettings( + os.path.join(TEST_CONFIG_DIR, 'network/network_settings_v6.yaml')) + + @classmethod + def teardown_class(klass): + """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""" + + def test_init(self): + assert_raises(NetworkEnvException, NetworkEnvironment, + None, os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + + def test_netenv_settings_external_network_vlans(self): + # test vlans + ne = NetworkEnvironment(self.ns_vlans, + os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + assert_equal(ne['parameter_defaults']['NeutronExternalNetworkBridge'], + '""') + assert_equal(ne['parameter_defaults']['ExternalNetworkVlanID'], 501) + + def test_netenv_settings_external_network_ipv6(self): + # Test IPv6 + ne = NetworkEnvironment(self.ns_ipv6, + os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + regstr = ne['resource_registry']['OS::TripleO::Network::External'] + assert_equal(regstr.split('/')[-1], 'external_v6.yaml') + + def test_netenv_settings_external_network_removed(self): + ns = copy(self.ns) + # Test removing EXTERNAL_NETWORK + ns.enabled_network_list.remove(EXTERNAL_NETWORK) + ne = NetworkEnvironment(ns, os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + regstr = ne['resource_registry']['OS::TripleO::Network::External'] + assert_equal(regstr.split('/')[-1], 'OS::Heat::None') + + def test_netenv_settings_tenant_network_vlans(self): + # test vlans + ne = NetworkEnvironment(self.ns_vlans, + os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + assert_equal(ne['parameter_defaults']['TenantNetworkVlanID'], 401) + +# Apex is does not support v6 tenant networks +# Though there is code that would fire if a +# v6 cidr was passed in, just uncomment this to +# cover that code +# def test_netenv_settings_tenant_network_v6(self): +# # Test IPv6 +# ne = NetworkEnvironment(self.ns_ipv6, +# '../build/network-environment.yaml') +# regstr = ne['resource_registry'][next(iter(TENANT_RESOURCES.keys()))] +# assert_equal(regstr.split('/')[-1], 'tenant_v6.yaml') + + def test_netenv_settings_tenant_network_removed(self): + ns = copy(self.ns) + # Test removing TENANT_NETWORK + ns.enabled_network_list.remove(TENANT_NETWORK) + ne = NetworkEnvironment(ns, os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + regstr = ne['resource_registry']['OS::TripleO::Network::Tenant'] + assert_equal(regstr.split('/')[-1], 'OS::Heat::None') + + def test_netenv_settings_storage_network_vlans(self): + # test vlans + ne = NetworkEnvironment(self.ns_vlans, + os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + assert_equal(ne['parameter_defaults']['StorageNetworkVlanID'], 201) + + def test_netenv_settings_storage_network_v6(self): + # Test IPv6 + ne = NetworkEnvironment(self.ns_ipv6, + os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + regstr = ne['resource_registry']['OS::TripleO::Network::Storage'] + assert_equal(regstr.split('/')[-1], 'storage_v6.yaml') + + def test_netenv_settings_storage_network_removed(self): + ns = copy(self.ns) + # Test removing STORAGE_NETWORK + ns.enabled_network_list.remove(STORAGE_NETWORK) + ne = NetworkEnvironment(ns, os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + regstr = ne['resource_registry']['OS::TripleO::Network::Storage'] + assert_equal(regstr.split('/')[-1], 'OS::Heat::None') + + def test_netenv_settings_api_network_v4(self): + ns = copy(self.ns_vlans) + ns['networks'][API_NETWORK]['enabled'] = True + ns['networks'][API_NETWORK]['cidr'] = '10.11.12.0/24' + ns = NetworkSettings(ns) + # test vlans + ne = NetworkEnvironment(ns, os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + assert_equal(ne['parameter_defaults']['InternalApiNetworkVlanID'], 101) + + def test_netenv_settings_api_network_vlans(self): + ns = copy(self.ns_vlans) + ns['networks'][API_NETWORK]['enabled'] = True + ns = NetworkSettings(ns) + # test vlans + ne = NetworkEnvironment(ns, os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + assert_equal(ne['parameter_defaults']['InternalApiNetworkVlanID'], 101) + + def test_netenv_settings_api_network_v6(self): + # Test IPv6 + ne = NetworkEnvironment(self.ns_ipv6, + os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + regstr = ne['resource_registry']['OS::TripleO::Network::InternalApi'] + assert_equal(regstr.split('/')[-1], 'internal_api_v6.yaml') + + def test_netenv_settings_api_network_removed(self): + ns = copy(self.ns) + # API_NETWORK is not in the default network settings file + ne = NetworkEnvironment(ns, os.path.join(TEST_BUILD_DIR, NET_ENV_FILE)) + regstr = ne['resource_registry']['OS::TripleO::Network::InternalApi'] + assert_equal(regstr.split('/')[-1], 'OS::Heat::None') + + def test_numa_configs(self): + ne = NetworkEnvironment(self.ns, + os.path.join(TEST_BUILD_DIR, NET_ENV_FILE), + compute_pre_config=True, + controller_pre_config=True) + assert_is_instance(ne, dict) + assert_not_equal(ne, {}) + + def test_exception(self): + e = NetworkEnvException("test") + print(e) + assert_is_instance(e, NetworkEnvException) diff --git a/apex/tests/test_apex_network_settings.py b/apex/tests/test_apex_network_settings.py new file mode 100644 index 00000000..adff8cff --- /dev/null +++ b/apex/tests/test_apex_network_settings.py @@ -0,0 +1,156 @@ +############################################################################## +# 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 + +from nose.tools import ( + assert_equal, + assert_is_instance, + assert_raises +) + +from apex.common.constants import ( + EXTERNAL_NETWORK, + STORAGE_NETWORK, + ADMIN_NETWORK, +) +from apex import NetworkSettings +from apex.settings.network_settings import NetworkSettingsException +from apex.tests.constants import TEST_CONFIG_DIR + +files_dir = os.path.join(TEST_CONFIG_DIR, 'network') + + +class TestNetworkSettings(object): + @classmethod + def setup_class(klass): + """This method is run once for each class before any tests are run""" + + @classmethod + def teardown_class(klass): + """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""" + + def test_init(self): + assert_is_instance( + NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')), + NetworkSettings) + + def test_init_vlans(self): + assert_is_instance( + NetworkSettings(os.path.join(files_dir, + 'network_settings_vlans.yaml')), + NetworkSettings) + +# TODO, v6 test is stuck + # def test_init_v6(self): + # assert_is_instance( + # NetworkSettings(files_dir+'network_settings_v6.yaml', True), + # NetworkSettings) + + def test_init_admin_disabled_or_missing(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + # remove admin, apex section will re-add it + ns['networks'].pop('admin', None) + assert_raises(NetworkSettingsException, NetworkSettings, ns) + # remove admin and apex + ns.pop('apex', None) + ns['networks'].pop('admin', None) + assert_raises(NetworkSettingsException, NetworkSettings, ns) + + def test_init_collapse_storage(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + # remove storage + ns['networks'].pop('storage', None) + assert_is_instance(NetworkSettings(ns), NetworkSettings) + + def test_init_missing_dns_domain(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + # remove storage + ns.pop('dns-domain', None) + assert_is_instance(NetworkSettings(ns), NetworkSettings) + + def test_get_network_settings(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + assert_is_instance(ns, NetworkSettings) + for role in ['controller', 'compute']: + nic_index = 0 + print(ns.nics) + for network in ns.enabled_network_list: + nic = 'eth' + str(nic_index) + assert_equal(ns.nics[role][network], nic) + nic_index += 1 + + def test_get_enabled_networks(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + assert_is_instance(ns.enabled_network_list, list) + + def test_invalid_nic_members(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + storage_net_nicmap = ns['networks'][STORAGE_NETWORK]['nic_mapping'] + # set duplicate nic + storage_net_nicmap['controller']['members'][0] = 'eth0' + assert_raises(NetworkSettingsException, NetworkSettings, ns) + # remove nic members + storage_net_nicmap['controller']['members'] = [] + assert_raises(NetworkSettingsException, NetworkSettings, ns) + + def test_missing_vlan(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + storage_net_nicmap = ns['networks'][STORAGE_NETWORK]['nic_mapping'] + # remove vlan from storage net + storage_net_nicmap['compute'].pop('vlan', None) + assert_is_instance(NetworkSettings(ns), NetworkSettings) + +# TODO +# need to manipulate interfaces some how +# maybe for ip_utils to return something to pass this +# def test_admin_auto_detect(self): +# ns = NetworkSettings(files_dir+'network_settings.yaml') +# # remove cidr to force autodetection +# ns['networks'][ADMIN_NETWORK].pop('cidr', None) +# assert_is_instance(NetworkSettings(ns), NetworkSettings) + + def test_admin_fail_auto_detect(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + # remove cidr and installer_vm to fail autodetect + ns['networks'][ADMIN_NETWORK].pop('cidr', None) + ns['networks'][ADMIN_NETWORK].pop('installer_vm', None) + assert_raises(NetworkSettingsException, NetworkSettings, ns) + + def test_exception(self): + e = NetworkSettingsException("test") + print(e) + assert_is_instance(e, NetworkSettingsException) + + def test_config_ip(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + # set the provisioner ip to None to force _gen_ip to generate one + ns['networks'][ADMIN_NETWORK]['installer_vm']['ip'] = None + ns['networks'][EXTERNAL_NETWORK][0]['installer_vm']['ip'] = None + # Now rebuild network settings object and check for repopulated values + ns = NetworkSettings(ns) + assert_equal(ns['networks'][ADMIN_NETWORK]['installer_vm']['ip'], + '192.0.2.1') + assert_equal(ns['networks'][EXTERNAL_NETWORK][0]['installer_vm']['ip'], + '192.168.37.1') + + def test_config_gateway(self): + ns = NetworkSettings(os.path.join(files_dir, 'network_settings.yaml')) + # set the gateway ip to None to force _config_gateway to generate one + ns['networks'][EXTERNAL_NETWORK][0]['gateway'] = None + # Now rebuild network settings object and check for a repopulated value + ns = NetworkSettings(ns) + assert_equal(ns['networks'][EXTERNAL_NETWORK][0]['gateway'], + '192.168.37.1') -- cgit 1.2.3-korg