From 8dcd90fd567c076df2b4c4b324d16332e06c2a05 Mon Sep 17 00:00:00 2001 From: Ksenia Demina Date: Fri, 18 Mar 2016 19:07:55 +0300 Subject: [PATCH] Add base tests for NUMA CPU pinning Add base tests with preparing env for NUMA nodes NUMA nodes will be configuring using fuel-devops for every node in cluster with equal value. If there are no NUMAs on compute node, test will fail. Change-Id: I8d1c7475e848b8df5a7cc05d310dd584a501752d Implements: blueprint test-numa-cpu-pinning --- doc/base_tests.rst | 5 ++ fuelweb_test/helpers/utils.py | 20 ++++++ fuelweb_test/tests/test_cpu_pinning.py | 97 ++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 fuelweb_test/tests/test_cpu_pinning.py diff --git a/doc/base_tests.rst b/doc/base_tests.rst index 4638faab3..23a252d82 100644 --- a/doc/base_tests.rst +++ b/doc/base_tests.rst @@ -322,6 +322,11 @@ Test Support HugePages .. automodule:: fuelweb_test.tests.test_support_hugepages :members: +Test CPU pinning +---------------- +.. automodule:: fuelweb_test.tests.test_cpu_pinning + :members: + Test RH-based computes ---------------------- .. automodule:: fuelweb_test.tests.test_rh_compute diff --git a/fuelweb_test/helpers/utils.py b/fuelweb_test/helpers/utils.py index 8e5781595..4a701efd3 100644 --- a/fuelweb_test/helpers/utils.py +++ b/fuelweb_test/helpers/utils.py @@ -1041,3 +1041,23 @@ def get_file_size(ip, file_name, file_path): " remote node".format(file_path, file_name)) return int(file_size['stdout'][0].rstrip()) + + +@logwrap +def get_quantity_of_numa(ip): + """Get number of NUMA nodes that are contained on remote node + + :param remote: node IP + :return: int, count of available NUMA nodes on the node + """ + + numa = int(SSHManager().check_call( + ip=ip, + cmd="lstopo | grep NUMANode| wc -l" + )['stdout'][0]) + + if not numa: + logger.debug("There are no NUMA nodes on {0}".format(ip)) + else: + logger.debug("There is {0} NUMA node(s) on {1}".format(numa, ip)) + return numa diff --git a/fuelweb_test/tests/test_cpu_pinning.py b/fuelweb_test/tests/test_cpu_pinning.py new file mode 100644 index 000000000..ef0226ee4 --- /dev/null +++ b/fuelweb_test/tests/test_cpu_pinning.py @@ -0,0 +1,97 @@ +# Copyright 2016 Mirantis, Inc. +# +# 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. + +from proboscis import asserts +from proboscis import test + +from fuelweb_test.helpers.decorators import log_snapshot_after_test +from fuelweb_test.helpers import utils +from fuelweb_test import logger +from fuelweb_test import settings +from fuelweb_test.tests.base_test_case import SetupEnvironment +from fuelweb_test.tests.base_test_case import TestBasic + + +@test(groups=["numa_cpu_pinning"]) +class NumaCpuPinning(TestBasic): + """NumaCpuPinning.""" + + @test(depends_on=[SetupEnvironment.prepare_slaves_5], + groups=["numa_cpu_pinning", + "basic_env_for_numa_cpu_pinning"]) + @log_snapshot_after_test + def basic_env_for_numa_cpu_pinning(self): + """Basic environment for NUMA CPU pinning + + Scenario: + 1. Create cluster + 2. Add 2 nodes with compute role + 3. Add 3 nodes with controller role + 4. Verify that quantity of NUMA is equal on node and in Fuel + + Snapshot: basic_env_for_numa_cpu_pinning + """ + snapshot_name = 'basic_env_for_numa_cpu_pinning' + self.check_run(snapshot_name) + self.env.revert_snapshot("ready_with_5_slaves") + + self.show_step(1, initialize=True) + cluster_id = self.fuel_web.create_cluster( + name=self.__class__.__name__, + mode=settings.DEPLOYMENT_MODE, + settings={ + "net_provider": 'neutron', + "net_segment_type": settings.NEUTRON_SEGMENT_TYPE, + "KVM_USE": True + } + ) + self.show_step(2) + self.show_step(3) + + self.fuel_web.update_nodes( + cluster_id, + { + 'slave-01': ['compute'], + 'slave-02': ['compute'], + 'slave-03': ['controller'], + 'slave-04': ['controller'], + 'slave-05': ['controller'] + }) + + self.show_step(4) + + for node in ('slave-01', 'slave-02'): + target_node = self.fuel_web.get_nailgun_node_by_name(node) + numas_from_fuel = len( + target_node['meta']['numa_topology']['numa_nodes']) + numas_on_remote = utils.get_quantity_of_numa(target_node['ip']) + if not numas_on_remote: + # Fuel handle topology without NUMA as 1 NUMA node + asserts.assert_equal(numas_from_fuel, 1, + "No NUMA nodes on {0} " + "while Fuel shows it " + "has {1}".format( + target_node['ip'], numas_from_fuel)) + raise AssertionError("No NUMA nodes on {0}".format( + target_node['ip'])) + else: + asserts.assert_equal(numas_on_remote, numas_from_fuel, + "{0} NUMA nodes on {1} " + "while Fuel shows it " + "has {2}".format( + numas_on_remote, target_node['ip'], + numas_from_fuel)) + logger.info("There is {0} NUMA nodes on node {1}".format( + numas_on_remote, target_node['ip'])) + self.env.make_snapshot(snapshot_name, is_make=True)