265a072b72
Have our unit tests derive from the base unit test class in ironic_python_agent/tests/unit/base: IronicAgentTest This is so if we add additional global common features to our base test class, all of our tests will get those common features. Change-Id: I5188112f06dcfda4f5b0fd41fa9b9dd270cde8d7
351 lines
18 KiB
Python
351 lines
18 KiB
Python
# Copyright 2017 Red Hat, 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.
|
|
|
|
import os
|
|
|
|
import mock
|
|
|
|
from ironic_python_agent import errors
|
|
from ironic_python_agent import numa_inspector as numa_insp
|
|
from ironic_python_agent.tests.unit import base
|
|
from ironic_python_agent import utils
|
|
|
|
|
|
class TestCollectNumaTopologyInfo(base.IronicAgentTest):
|
|
def setUp(self):
|
|
super(TestCollectNumaTopologyInfo, self).setUp()
|
|
self.data = {}
|
|
self.failures = utils.AccumulatedFailures()
|
|
|
|
@mock.patch.object(numa_insp, 'get_nodes_nics_info', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_nodes_cores_info', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_nodes_memory_info', autospec=True)
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
def test_collect_success(self, mock_listdir, mock_isdir, mock_memory_info,
|
|
mock_cores_info, mock_nics_info):
|
|
numa_node_dirs = ['node0', 'node1']
|
|
mock_listdir.return_value = numa_node_dirs
|
|
mock_isdir.return_value = True
|
|
mock_memory_info.return_value = [{'numa_node': 0, 'size_kb': 1560000},
|
|
{'numa_node': 1, 'size_kb': 1200000}]
|
|
mock_cores_info.return_value = [{'cpu': 0, 'numa_node': 0,
|
|
'thread_siblings': [0, 1, 2, 3]},
|
|
{'cpu': 1, 'numa_node': 0,
|
|
'thread_siblings': [4, 5, 6]},
|
|
{'cpu': 0, 'numa_node': 1,
|
|
'thread_siblings': [16, 17]},
|
|
{'cpu': 1, 'numa_node': 1,
|
|
'thread_siblings': [18, 19]}]
|
|
mock_nics_info.return_value = [{'name': 'enp0s01', 'numa_node': 0},
|
|
{'name': 'enp0s02', 'numa_node': 1}]
|
|
expected_numa_info = {"ram": [{'numa_node': 0, 'size_kb': 1560000},
|
|
{'numa_node': 1, 'size_kb': 1200000}],
|
|
"cpus": [{'cpu': 0, 'numa_node': 0,
|
|
'thread_siblings': [0, 1, 2, 3]},
|
|
{'cpu': 1, 'numa_node': 0,
|
|
'thread_siblings': [4, 5, 6]},
|
|
{'cpu': 0, 'numa_node': 1,
|
|
'thread_siblings': [16, 17]},
|
|
{'cpu': 1, 'numa_node': 1,
|
|
'thread_siblings': [18, 19]}],
|
|
"nics": [{'name': 'enp0s01', 'numa_node': 0},
|
|
{'name': 'enp0s02', 'numa_node': 1}]}
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
numa_insp.collect_numa_topology_info(self.data, self.failures)
|
|
self.assertEqual(expected_numa_info, self.data["numa_topology"])
|
|
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
def test_collect_no_numa_dirs(self, mock_isdir):
|
|
mock_isdir.return_value = False
|
|
numa_insp.collect_numa_topology_info(self.data, self.failures)
|
|
self.assertNotIn("numa_topology", self.data)
|
|
|
|
@mock.patch.object(numa_insp, 'get_nodes_nics_info', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_nodes_cores_info', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_nodes_memory_info', autospec=True)
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
def test_collect_no_nics_dirs(self, mock_listdir, mock_isdir,
|
|
mock_memory_info, mock_cores_info,
|
|
mock_nics_info):
|
|
numa_node_dirs = ['node0', 'node1']
|
|
mock_listdir.return_value = numa_node_dirs
|
|
mock_isdir.return_value = True
|
|
mock_memory_info.return_value = [{'numa_node': 0, 'size_kb': 1560000},
|
|
{'numa_node': 1, 'size_kb': 1200000}]
|
|
mock_cores_info.return_value = [{'cpu': 0, 'numa_node': 0,
|
|
'thread_siblings': [0, 1, 2, 3]},
|
|
{'cpu': 1, 'numa_node': 1,
|
|
'thread_siblings': [4, 5, 6]}]
|
|
mock_nics_info.side_effect = errors.IncompatibleNumaFormatError("")
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
numa_insp.collect_numa_topology_info(self.data, self.failures)
|
|
self.assertNotIn("numa_topology", self.data)
|
|
|
|
@mock.patch.object(numa_insp, 'get_nodes_nics_info', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_nodes_cores_info', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_nodes_memory_info', autospec=True)
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
def test_collect_failure(self, mock_listdir, mock_isdir, mock_memory_info,
|
|
mock_cores_info, mock_nics_info):
|
|
numa_node_dirs = ['node0', 'node1']
|
|
mock_listdir.return_value = numa_node_dirs
|
|
mock_isdir.return_value = True
|
|
mock_memory_info.side_effect = errors.IncompatibleNumaFormatError("")
|
|
mock_cores_info.side_effect = errors.IncompatibleNumaFormatError("")
|
|
mock_nics_info.side_effect = errors.IncompatibleNumaFormatError("")
|
|
numa_insp.collect_numa_topology_info(self.data, self.failures)
|
|
self.assertNotIn("numa_topology", self.data)
|
|
self.assertFalse(self.failures)
|
|
|
|
|
|
class TestGetNumaTopologyInfo(base.IronicAgentTest):
|
|
def setUp(self):
|
|
super(TestGetNumaTopologyInfo, self).setUp()
|
|
self.data = {}
|
|
self.failures = utils.AccumulatedFailures()
|
|
|
|
def test_get_numa_node_id_valid_format(self):
|
|
numa_node_dir = '/sys/devices/system/node/node0'
|
|
expected_numa_node_id = 0
|
|
numa_node_id = numa_insp.get_numa_node_id(numa_node_dir)
|
|
self.assertEqual(expected_numa_node_id, numa_node_id)
|
|
|
|
def test_get_numa_node_id_invalid_format(self):
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_numa_node_id,
|
|
'/sys/devices/system/node/node-*0')
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_numa_node_id,
|
|
'/sys/devices/system/node/nod')
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_numa_node_id,
|
|
'')
|
|
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_get_nodes_memory_info(self, mock_node_id):
|
|
numa_node_dirs = ['/sys/devices/system/node/node0',
|
|
'/sys/devices/system/node/node1']
|
|
mock_node_id.side_effect = [0, 1]
|
|
reads = [['Node 0 Ignored Line',
|
|
'Node 0 MemTotal: 1560000 kB'],
|
|
['Node 1 MemTotal: 1200000 kB',
|
|
'Node 1 Ignored Line']]
|
|
expected_meminfo = [{'numa_node': 0, 'size_kb': 1560000},
|
|
{'numa_node': 1, 'size_kb': 1200000}]
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_meminfo_file = mock.MagicMock()
|
|
mock_meminfo_file.__enter__.side_effect = reads
|
|
mock_open.return_value = mock_meminfo_file
|
|
ram = numa_insp.get_nodes_memory_info(numa_node_dirs)
|
|
self.assertListEqual(expected_meminfo, ram)
|
|
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_bad_nodes_memory_info(self, mock_node_id):
|
|
numa_node_dirs = ['/sys/devices/system/node/node0',
|
|
'/sys/devices/system/node/node1']
|
|
mock_node_id.side_effect = [0, 1]
|
|
reads = [['Node 0 MemTotal: 1560000 kB'], IOError]
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_meminfo_file = mock.MagicMock()
|
|
mock_meminfo_file.__enter__.side_effect = reads
|
|
mock_open.return_value = mock_meminfo_file
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_memory_info,
|
|
numa_node_dirs)
|
|
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_nodes_invalid_numa_format_memory_info(self, mock_node_id):
|
|
numa_node_dirs = ['/sys/devices/system/node/node0',
|
|
'/sys/devices/system/node/node1']
|
|
mock_node_id.side_effect = [0, 1]
|
|
reads = [['Node 0: MemTotal: 1560000 kB'],
|
|
['Node 1 MemTotal: 1200000 kB']]
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_meminfo_file = mock.MagicMock()
|
|
mock_meminfo_file.__enter__.side_effect = reads
|
|
mock_open.return_value = mock_meminfo_file
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_memory_info,
|
|
numa_node_dirs)
|
|
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_nodes_invalid_memory_unit(self, mock_node_id):
|
|
numa_node_dirs = ['/sys/devices/system/node/node0',
|
|
'/sys/devices/system/node/node1']
|
|
mock_node_id.side_effect = [0, 1]
|
|
reads = [['Node 0 MemTotal: 1560000 TB'],
|
|
['Node 1 MemTotal: 1200000 kB']]
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_meminfo_file = mock.MagicMock()
|
|
mock_meminfo_file.__enter__.side_effect = reads
|
|
mock_open.return_value = mock_meminfo_file
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_memory_info,
|
|
numa_node_dirs)
|
|
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_get_numa_node_id_invalid_format_memory_info(self,
|
|
mock_node_id):
|
|
numa_node_dirs = ['/sys/devices/system/node/node-*0',
|
|
'/sys/devices/system/node/node1']
|
|
mock_node_id.side_effect = errors.IncompatibleNumaFormatError
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_memory_info,
|
|
numa_node_dirs)
|
|
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_get_nodes_cores_info(self, mock_node_id,
|
|
mock_listdir, mock_isdir):
|
|
numa_node_dirs = ['/sys/devices/system/node/node0',
|
|
'/sys/devices/system/node/node1']
|
|
mock_node_id.side_effect = [0, 1]
|
|
mock_listdir.side_effect = [['cpu0', 'cpu1', 'cpu2',
|
|
'cpu3', 'cpu4'],
|
|
['cpu5', 'cpu6', 'cpu7']]
|
|
mock_isdir.return_value = True
|
|
reads = ['0', '0', '1', '1', '1', '0', '0', '0']
|
|
expected_cores_info = [{'cpu': 0, 'numa_node': 0,
|
|
'thread_siblings': [0, 1]},
|
|
{'cpu': 1, 'numa_node': 0,
|
|
'thread_siblings': [2, 3, 4]},
|
|
{'cpu': 0, 'numa_node': 1,
|
|
'thread_siblings': [5, 6, 7]}]
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_core_id_file = mock_open.return_value.read
|
|
mock_core_id_file.side_effect = reads
|
|
cpus = numa_insp.get_nodes_cores_info(numa_node_dirs)
|
|
self.assertEqual(len(cpus), len(expected_cores_info))
|
|
for cpu in cpus:
|
|
self.assertIn(cpu, expected_cores_info)
|
|
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_bad_nodes_cores_info(self, mock_node_id,
|
|
mock_listdir, mock_isdir):
|
|
numa_node_dirs = ['/sys/devices/system/node/node0']
|
|
mock_node_id.return_value = 0
|
|
thread_dirs = ['cpu0', 'cpu1', 'cpu2', 'cpu3', 'cpu4', 'cpu5']
|
|
mock_listdir.return_value = thread_dirs
|
|
mock_isdir.return_value = True
|
|
reads = ['0', '0', '1', '1', '1', IOError]
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_core_id_file = mock_open.return_value.read
|
|
mock_core_id_file.side_effect = reads
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_cores_info,
|
|
numa_node_dirs)
|
|
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_get_numa_node_id_invalid_format_cores_info(self,
|
|
mock_node_id):
|
|
numa_node_dirs = ['/sys/devices/system/node/nodeid0']
|
|
mock_node_id.side_effect = errors.IncompatibleNumaFormatError
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_cores_info,
|
|
numa_node_dirs)
|
|
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_nodes_invalid_threaddir_format_cores_info(self, mock_node_id,
|
|
mock_listdir,
|
|
mock_isdir):
|
|
numa_node_dirs = ['/sys/devices/system/node/node0']
|
|
mock_node_id.return_value = 0
|
|
thread_dirs = ['cpuid0', 'cpu1', 'cpu2', 'cpu3', 'cpu4', 'cpu5']
|
|
mock_listdir.return_value = thread_dirs
|
|
mock_isdir.return_value = True
|
|
reads = ['0', '0', '1', '1', '1', '2']
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_core_id_file = mock_open.return_value.read
|
|
mock_core_id_file.side_effect = reads
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_cores_info,
|
|
numa_node_dirs)
|
|
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
@mock.patch.object(numa_insp, 'get_numa_node_id', autospec=True)
|
|
def test_bad_nodes_thread_dirs(self, mock_node_id,
|
|
mock_listdir, mock_isdir):
|
|
numa_node_dirs = ['/sys/devices/system/node/node0']
|
|
mock_node_id.return_value = 0
|
|
mock_listdir.side_effect = errors.IncompatibleNumaFormatError("")
|
|
mock_isdir.return_value = True
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_cores_info,
|
|
numa_node_dirs)
|
|
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
def test_get_nodes_nics_info(self, mock_listdir, mock_isdir):
|
|
nic_dirs = ['enp0s01', 'enp0s02']
|
|
mock_listdir.return_value = nic_dirs
|
|
mock_isdir.return_value = True
|
|
reads = ['0', '1']
|
|
expected_nicsinfo = [{'name': 'enp0s01', 'numa_node': 0},
|
|
{'name': 'enp0s02', 'numa_node': 1}]
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_nicsinfo_file = mock_open.return_value.read
|
|
mock_nicsinfo_file.side_effect = reads
|
|
nics = numa_insp.get_nodes_nics_info('/sys/class/net/')
|
|
self.assertListEqual(expected_nicsinfo, nics)
|
|
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
def test_bad_nodes_nics_info(self, mock_listdir, mock_isdir):
|
|
nic_dirs = ['enp0s01', 'enp0s02']
|
|
mock_listdir.return_value = nic_dirs
|
|
mock_isdir.return_value = True
|
|
reads = ['0', IOError]
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_nicsinfo_file = mock_open.return_value.read
|
|
mock_nicsinfo_file.side_effect = reads
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_nics_info,
|
|
'/sys/class/net/')
|
|
|
|
@mock.patch.object(os, 'listdir', autospec=True)
|
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
|
def test_no_nics_dir(self, mock_isdir, mock_listdir):
|
|
mock_isdir.return_value = False
|
|
nic_dirs = ['enp0s01', 'enp0s02']
|
|
mock_listdir.return_value = nic_dirs
|
|
reads = ['0', '1']
|
|
mock_open = mock.mock_open()
|
|
with mock.patch('six.moves.builtins.open', mock_open):
|
|
mock_nicsinfo_file = mock_open.return_value.read
|
|
mock_nicsinfo_file.side_effect = reads
|
|
self.assertRaises(errors.IncompatibleNumaFormatError,
|
|
numa_insp.get_nodes_nics_info,
|
|
'/sys/class/net/')
|