summaryrefslogtreecommitdiff
path: root/ironic_python_agent/tests/unit/test_hardware.py
diff options
context:
space:
mode:
Diffstat (limited to 'ironic_python_agent/tests/unit/test_hardware.py')
-rw-r--r--ironic_python_agent/tests/unit/test_hardware.py429
1 files changed, 426 insertions, 3 deletions
diff --git a/ironic_python_agent/tests/unit/test_hardware.py b/ironic_python_agent/tests/unit/test_hardware.py
index 0d6d28f7..cc39d833 100644
--- a/ironic_python_agent/tests/unit/test_hardware.py
+++ b/ironic_python_agent/tests/unit/test_hardware.py
@@ -1542,6 +1542,54 @@ class TestGenericHardwareManager(base.IronicAgentTest):
ignore_raid=True)],
list_mock.call_args_list)
+ def test_get_skip_list_from_node_block_devices_with_skip_list(self):
+ block_devices = [
+ hardware.BlockDevice('/dev/sdj', 'big', 1073741824, True),
+ hardware.BlockDevice('/dev/hdaa', 'small', 65535, False),
+ ]
+ expected_skip_list = {'/dev/sdj'}
+ node = self.node
+
+ node['properties'] = {
+ 'skip_block_devices': [{
+ 'name': '/dev/sdj'
+ }]
+ }
+
+ skip_list = self.hardware.get_skip_list_from_node(node,
+ block_devices)
+
+ self.assertEqual(expected_skip_list, skip_list)
+
+ def test_get_skip_list_from_node_block_devices_just_raids(self):
+ expected_skip_list = {'large'}
+ node = self.node
+
+ node['properties'] = {
+ 'skip_block_devices': [{
+ 'name': '/dev/sdj'
+ }, {
+ 'volume_name': 'large'
+ }]
+ }
+
+ skip_list = self.hardware.get_skip_list_from_node(node,
+ just_raids=True)
+
+ self.assertEqual(expected_skip_list, skip_list)
+
+ def test_get_skip_list_from_node_block_devices_no_skip_list(self):
+ block_devices = [
+ hardware.BlockDevice('/dev/sdj', 'big', 1073741824, True),
+ hardware.BlockDevice('/dev/hdaa', 'small', 65535, False),
+ ]
+ node = self.node
+
+ skip_list = self.hardware.get_skip_list_from_node(node,
+ block_devices)
+
+ self.assertIsNone(skip_list)
+
@mock.patch.object(hardware.GenericHardwareManager,
'list_block_devices', autospec=True)
def test_list_block_devices_check_skip_list_with_skip_list(self,
@@ -4369,6 +4417,294 @@ class TestGenericHardwareManager(base.IronicAgentTest):
self.hardware.create_configuration,
self.node, [])
+ @mock.patch.object(raid_utils, 'get_volume_name_of_raid_device',
+ autospec=True)
+ @mock.patch.object(raid_utils, '_get_actual_component_devices',
+ autospec=True)
+ @mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
+ @mock.patch.object(disk_utils, 'list_partitions', autospec=True)
+ @mock.patch.object(il_utils, 'execute', autospec=True)
+ def test_create_configuration_with_skip_list(
+ self, mocked_execute, mock_list_parts, mocked_list_all_devices,
+ mocked_actual_comp, mocked_get_volume_name):
+ node = self.node
+
+ raid_config = {
+ "logical_disks": [
+ {
+ "size_gb": "10",
+ "raid_level": "1",
+ "controller": "software",
+ "volume_name": "small"
+ },
+ {
+ "size_gb": "MAX",
+ "raid_level": "0",
+ "controller": "software",
+ "volume_name": "large"
+ },
+ ]
+ }
+ node['target_raid_config'] = raid_config
+ node['properties'] = {'skip_block_devices': [{'volume_name': 'large'}]}
+ device1 = hardware.BlockDevice('/dev/sda', 'sda', 107374182400, True)
+ device2 = hardware.BlockDevice('/dev/sdb', 'sdb', 107374182400, True)
+ raid_device1 = hardware.BlockDevice('/dev/md0', 'RAID-1',
+ 107374182400, True)
+ self.hardware.list_block_devices = mock.Mock()
+ self.hardware.list_block_devices.return_value = [device1, device2]
+ hardware.list_all_block_devices.side_effect = [
+ [raid_device1], # block_type raid
+ [] # block type md
+ ]
+ mocked_get_volume_name.return_value = "large"
+
+ mocked_execute.side_effect = [
+ None, # examine md0
+ None, # mklabel sda
+ ('42', None), # sgdisk -F sda
+ None, # mklabel sda
+ ('42', None), # sgdisk -F sdb
+ None, None, None, # parted + partx + udevadm_settle sda
+ None, None, None, # parted + partx + udevadm_settle sdb
+ None, None, None, # parted + partx + udevadm_settle sda
+ None, None, None, # parted + partx + udevadm_settle sdb
+ None, None # mdadms
+ ]
+
+ mocked_actual_comp.side_effect = [
+ ('/dev/sda1', '/dev/sdb1'),
+ ('/dev/sda2', '/dev/sdb2'),
+ ]
+
+ result = self.hardware.create_configuration(node, [])
+ mocked_execute.assert_has_calls([
+ mock.call('mdadm', '--examine', '/dev/md0',
+ use_standard_locale=True),
+ mock.call('parted', '/dev/sda', '-s', '--', 'mklabel', 'msdos'),
+ mock.call('sgdisk', '-F', '/dev/sda'),
+ mock.call('parted', '/dev/sdb', '-s', '--', 'mklabel', 'msdos'),
+ mock.call('sgdisk', '-F', '/dev/sdb'),
+ mock.call('parted', '/dev/sda', '-s', '-a', 'optimal', '--',
+ 'mkpart', 'primary', '42s', '10GiB'),
+ mock.call('partx', '-av', '/dev/sda', attempts=3,
+ delay_on_retry=True),
+ mock.call('udevadm', 'settle'),
+ mock.call('parted', '/dev/sdb', '-s', '-a', 'optimal', '--',
+ 'mkpart', 'primary', '42s', '10GiB'),
+ mock.call('partx', '-av', '/dev/sdb', attempts=3,
+ delay_on_retry=True),
+ mock.call('udevadm', 'settle'),
+ mock.call('mdadm', '--create', '/dev/md0', '--force', '--run',
+ '--metadata=1', '--level', '1', '--name', 'small',
+ '--raid-devices', 2, '/dev/sda1', '/dev/sdb1')])
+ self.assertEqual(raid_config, result)
+
+ self.assertEqual(0, mock_list_parts.call_count)
+
+ @mock.patch.object(raid_utils, 'get_volume_name_of_raid_device',
+ autospec=True)
+ @mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
+ @mock.patch.object(il_utils, 'execute', autospec=True)
+ def test_create_configuration_skip_list_existing_device_does_not_match(
+ self, mocked_execute, mocked_list_all_devices,
+ mocked_get_volume_name):
+ node = self.node
+
+ raid_config = {
+ "logical_disks": [
+ {
+ "size_gb": "10",
+ "raid_level": "1",
+ "controller": "software",
+ "volume_name": "small"
+ },
+ {
+ "size_gb": "MAX",
+ "raid_level": "0",
+ "controller": "software",
+ "volume_name": "large"
+ },
+ ]
+ }
+ node['target_raid_config'] = raid_config
+ node['properties'] = {'skip_block_devices': [{'volume_name': 'large'}]}
+ device1 = hardware.BlockDevice('/dev/sda', 'sda', 107374182400, True)
+ device2 = hardware.BlockDevice('/dev/sdb', 'sdb', 107374182400, True)
+ raid_device1 = hardware.BlockDevice('/dev/md0', 'RAID-1',
+ 107374182400, True)
+ self.hardware.list_block_devices = mock.Mock()
+ self.hardware.list_block_devices.return_value = [device1, device2]
+ hardware.list_all_block_devices.side_effect = [
+ [raid_device1], # block_type raid
+ [] # block type md
+ ]
+ mocked_get_volume_name.return_value = "small"
+
+ error_regex = "Existing Software RAID device detected that should not"
+ mocked_execute.side_effect = [
+ processutils.ProcessExecutionError]
+ self.assertRaisesRegex(errors.SoftwareRAIDError, error_regex,
+ self.hardware.create_configuration,
+ self.node, [])
+
+ mocked_execute.assert_called_once_with(
+ 'mdadm', '--examine', '/dev/md0', use_standard_locale=True)
+
+ @mock.patch.object(raid_utils, '_get_actual_component_devices',
+ autospec=True)
+ @mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
+ @mock.patch.object(disk_utils, 'list_partitions', autospec=True)
+ @mock.patch.object(il_utils, 'execute', autospec=True)
+ def test_create_configuration_with_skip_list_no_existing_device(
+ self, mocked_execute, mock_list_parts,
+ mocked_list_all_devices, mocked_actual_comp):
+ node = self.node
+
+ raid_config = {
+ "logical_disks": [
+ {
+ "size_gb": "10",
+ "raid_level": "1",
+ "controller": "software",
+ "volume_name": "small"
+ },
+ {
+ "size_gb": "MAX",
+ "raid_level": "0",
+ "controller": "software",
+ "volume_name": "large"
+ },
+ ]
+ }
+ node['target_raid_config'] = raid_config
+ node['properties'] = {'skip_block_devices': [{'volume_name': 'large'}]}
+ device1 = hardware.BlockDevice('/dev/sda', 'sda', 107374182400, True)
+ device2 = hardware.BlockDevice('/dev/sdb', 'sdb', 107374182400, True)
+ self.hardware.list_block_devices = mock.Mock()
+ self.hardware.list_block_devices.return_value = [device1, device2]
+ mock_list_parts.side_effect = [
+ [],
+ processutils.ProcessExecutionError
+ ]
+ hardware.list_all_block_devices.side_effect = [
+ [], # block_type raid
+ [] # block type md
+ ]
+
+ mocked_execute.side_effect = [
+ None, # mklabel sda
+ ('42', None), # sgdisk -F sda
+ None, # mklabel sda
+ ('42', None), # sgdisk -F sdb
+ None, None, None, # parted + partx + udevadm_settle sda
+ None, None, None, # parted + partx + udevadm_settle sdb
+ None, None, None, # parted + partx + udevadm_settle sda
+ None, None, None, # parted + partx + udevadm_settle sdb
+ None, None # mdadms
+ ]
+
+ mocked_actual_comp.side_effect = [
+ ('/dev/sda1', '/dev/sdb1'),
+ ('/dev/sda2', '/dev/sdb2'),
+ ]
+
+ result = self.hardware.create_configuration(node, [])
+ mocked_execute.assert_has_calls([
+ mock.call('parted', '/dev/sda', '-s', '--', 'mklabel', 'msdos'),
+ mock.call('sgdisk', '-F', '/dev/sda'),
+ mock.call('parted', '/dev/sdb', '-s', '--', 'mklabel', 'msdos'),
+ mock.call('sgdisk', '-F', '/dev/sdb'),
+ mock.call('parted', '/dev/sda', '-s', '-a', 'optimal', '--',
+ 'mkpart', 'primary', '42s', '10GiB'),
+ mock.call('partx', '-av', '/dev/sda', attempts=3,
+ delay_on_retry=True),
+ mock.call('udevadm', 'settle'),
+ mock.call('parted', '/dev/sdb', '-s', '-a', 'optimal', '--',
+ 'mkpart', 'primary', '42s', '10GiB'),
+ mock.call('partx', '-av', '/dev/sdb', attempts=3,
+ delay_on_retry=True),
+ mock.call('udevadm', 'settle'),
+ mock.call('parted', '/dev/sda', '-s', '-a', 'optimal', '--',
+ 'mkpart', 'primary', '10GiB', '-1'),
+ mock.call('partx', '-av', '/dev/sda', attempts=3,
+ delay_on_retry=True),
+ mock.call('udevadm', 'settle'),
+ mock.call('parted', '/dev/sdb', '-s', '-a', 'optimal', '--',
+ 'mkpart', 'primary', '10GiB', '-1'),
+ mock.call('partx', '-av', '/dev/sdb', attempts=3,
+ delay_on_retry=True),
+ mock.call('udevadm', 'settle'),
+ mock.call('mdadm', '--create', '/dev/md0', '--force', '--run',
+ '--metadata=1', '--level', '1', '--name', 'small',
+ '--raid-devices', 2, '/dev/sda1', '/dev/sdb1'),
+ mock.call('mdadm', '--create', '/dev/md1', '--force', '--run',
+ '--metadata=1', '--level', '0', '--name', 'large',
+ '--raid-devices', 2, '/dev/sda2', '/dev/sdb2')])
+
+ self.assertEqual(raid_config, result)
+
+ self.assertEqual(2, mock_list_parts.call_count)
+ mock_list_parts.assert_has_calls([
+ mock.call(x) for x in ['/dev/sda', '/dev/sdb']
+ ])
+
+ @mock.patch.object(raid_utils, 'get_volume_name_of_raid_device',
+ autospec=True)
+ @mock.patch.object(raid_utils, '_get_actual_component_devices',
+ autospec=True)
+ @mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
+ @mock.patch.object(il_utils, 'execute', autospec=True)
+ def test_create_configuration_with_complete_skip_list(
+ self, mocked_execute, mocked_ls_all_devs,
+ mocked_actual_comp, mocked_get_volume_name):
+ node = self.node
+
+ raid_config = {
+ "logical_disks": [
+ {
+ "size_gb": "10",
+ "raid_level": "1",
+ "controller": "software",
+ "volume_name": "small"
+ },
+ {
+ "size_gb": "MAX",
+ "raid_level": "0",
+ "controller": "software",
+ "volume_name": "large"
+ },
+ ]
+ }
+ node['target_raid_config'] = raid_config
+ node['properties'] = {'skip_block_devices': [{'volume_name': 'small'},
+ {'volume_name': 'large'}]}
+ raid_device0 = hardware.BlockDevice('/dev/md0', 'RAID-1',
+ 2147483648, True)
+ raid_device1 = hardware.BlockDevice('/dev/md1', 'RAID-0',
+ 107374182400, True)
+ device1 = hardware.BlockDevice('/dev/sda', 'sda', 107374182400, True)
+ device2 = hardware.BlockDevice('/dev/sdb', 'sdb', 107374182400, True)
+ hardware.list_all_block_devices.side_effect = [
+ [raid_device0, raid_device1], # block_type raid
+ [] # block type md
+ ]
+ self.hardware.list_block_devices = mock.Mock()
+ self.hardware.list_block_devices.return_value = [device1, device2]
+ mocked_get_volume_name.side_effect = [
+ "small",
+ "large",
+ ]
+
+ self.hardware.create_configuration(node, [])
+ mocked_execute.assert_has_calls([
+ mock.call('mdadm', '--examine', '/dev/md0',
+ use_standard_locale=True),
+ mock.call('mdadm', '--examine', '/dev/md1',
+ use_standard_locale=True),
+ ])
+ self.assertEqual(2, mocked_execute.call_count)
+
@mock.patch.object(il_utils, 'execute', autospec=True)
def test__get_md_uuid(self, mocked_execute):
mocked_execute.side_effect = [(hws.MDADM_DETAIL_OUTPUT, '')]
@@ -4462,12 +4798,15 @@ class TestGenericHardwareManager(base.IronicAgentTest):
holder_disks = hardware.get_holder_disks('/dev/md0')
self.assertEqual(['/dev/vda', '/dev/vdb'], holder_disks)
+ @mock.patch.object(raid_utils, 'get_volume_name_of_raid_device',
+ autospec=True)
@mock.patch.object(hardware, 'get_holder_disks', autospec=True)
@mock.patch.object(hardware, 'get_component_devices', autospec=True)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
@mock.patch.object(il_utils, 'execute', autospec=True)
def test_delete_configuration(self, mocked_execute, mocked_list,
- mocked_get_component, mocked_get_holder):
+ mocked_get_component, mocked_get_holder,
+ mocked_get_volume_name):
raid_device1 = hardware.BlockDevice('/dev/md0', 'RAID-1',
107374182400, True)
raid_device2 = hardware.BlockDevice('/dev/md1', 'RAID-0',
@@ -4490,6 +4829,9 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mocked_get_holder.side_effect = [
["/dev/sda", "/dev/sdb"],
["/dev/sda", "/dev/sdb"]]
+ mocked_get_volume_name.side_effect = [
+ "/dev/md0", "/dev/md1"
+ ]
mocked_execute.side_effect = [
None, # mdadm --assemble --scan
None, # wipefs md0
@@ -4551,11 +4893,14 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mock.call('mdadm', '--assemble', '--scan', check_exit_code=False),
])
+ @mock.patch.object(raid_utils, 'get_volume_name_of_raid_device',
+ autospec=True)
@mock.patch.object(hardware, 'get_component_devices', autospec=True)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
@mock.patch.object(il_utils, 'execute', autospec=True)
def test_delete_configuration_partition(self, mocked_execute, mocked_list,
- mocked_get_component):
+ mocked_get_component,
+ mocked_get_volume_name):
# This test checks that if no components are returned for a given
# raid device, then it must be a nested partition and so it gets
# skipped
@@ -4569,6 +4914,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
[], # list_all_block_devices raid
[], # list_all_block_devices raid (md)
]
+ mocked_get_volume_name.return_value = None
mocked_get_component.return_value = []
self.assertIsNone(self.hardware.delete_configuration(self.node, []))
mocked_execute.assert_has_calls([
@@ -4576,11 +4922,14 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mock.call('mdadm', '--assemble', '--scan', check_exit_code=False),
])
+ @mock.patch.object(raid_utils, 'get_volume_name_of_raid_device',
+ autospec=True)
@mock.patch.object(hardware, 'get_component_devices', autospec=True)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
@mock.patch.object(il_utils, 'execute', autospec=True)
def test_delete_configuration_failure_blocks_remaining(
- self, mocked_execute, mocked_list, mocked_get_component):
+ self, mocked_execute, mocked_list, mocked_get_component,
+ mocked_get_volume_name):
# This test checks that, if after two raid clean passes there still
# remain softraid hints on drives, then the delete_configuration call
@@ -4601,6 +4950,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
[], # list_all_block_devices raid (type md)
]
mocked_get_component.return_value = []
+ mocked_get_volume_name.return_value = "/dev/md0"
self.assertRaisesRegex(
errors.SoftwareRAIDError,
@@ -4614,6 +4964,79 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mock.call('mdadm', '--assemble', '--scan', check_exit_code=False),
])
+ @mock.patch.object(raid_utils, 'get_volume_name_of_raid_device',
+ autospec=True)
+ @mock.patch.object(hardware.GenericHardwareManager,
+ 'get_skip_list_from_node', autospec=True)
+ @mock.patch.object(hardware, 'get_holder_disks', autospec=True)
+ @mock.patch.object(hardware, 'get_component_devices', autospec=True)
+ @mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
+ @mock.patch.object(il_utils, 'execute', autospec=True)
+ def test_delete_configuration_skip_list(self, mocked_execute, mocked_list,
+ mocked_get_component,
+ mocked_get_holder,
+ mocked_get_skip_list,
+ mocked_get_volume_name):
+ raid_device1 = hardware.BlockDevice('/dev/md0', 'RAID-1',
+ 107374182400, True)
+ raid_device2 = hardware.BlockDevice('/dev/md1', 'RAID-0',
+ 2147483648, True)
+ sda = hardware.BlockDevice('/dev/sda', 'model12', 21, True)
+ sdb = hardware.BlockDevice('/dev/sdb', 'model12', 21, True)
+ sdc = hardware.BlockDevice('/dev/sdc', 'model12', 21, True)
+
+ partitions = [
+ hardware.BlockDevice('/dev/sdb1', 'raid-member', 32767, False),
+ hardware.BlockDevice('/dev/sdb2', 'raid-member', 32767, False),
+ hardware.BlockDevice('/dev/sda1', 'raid_member', 32767, False),
+ hardware.BlockDevice('/dev/sda2', 'raid-member', 32767, False),
+ ]
+
+ hardware.list_all_block_devices.side_effect = [
+ [raid_device1, raid_device2], # list_all_block_devices raid
+ [], # list_all_block_devices raid (md)
+ [sda, sdb, sdc], # list_all_block_devices disks
+ partitions, # list_all_block_devices parts
+ [], # list_all_block_devices raid
+ [], # list_all_block_devices raid (md)
+ ]
+ mocked_get_component.side_effect = [
+ ["/dev/sda1", "/dev/sdb1"],
+ ["/dev/sda2", "/dev/sdb2"]]
+ mocked_get_holder.side_effect = [
+ ["/dev/sda", "/dev/sdb"],
+ ["/dev/sda", "/dev/sdb"]]
+ mocked_get_volume_name.side_effect = [
+ "/dev/md0", "small"
+ ]
+ mocked_get_skip_list.return_value = ["small"]
+
+ self.hardware.delete_configuration(self.node, [])
+
+ mocked_execute.assert_has_calls([
+ mock.call('mdadm', '--assemble', '--scan', check_exit_code=False),
+ mock.call('wipefs', '-af', '/dev/md0'),
+ mock.call('mdadm', '--stop', '/dev/md0'),
+ mock.call('mdadm', '--examine', '/dev/sda1',
+ use_standard_locale=True),
+ mock.call('mdadm', '--zero-superblock', '/dev/sda1'),
+ mock.call('mdadm', '--examine', '/dev/sdb1',
+ use_standard_locale=True),
+ mock.call('mdadm', '--zero-superblock', '/dev/sdb1'),
+ mock.call('mdadm', '--examine', '/dev/sda1',
+ use_standard_locale=True),
+ mock.call('mdadm', '--zero-superblock', '/dev/sda1'),
+ mock.call('mdadm', '--examine', '/dev/sdb1',
+ use_standard_locale=True),
+ mock.call('mdadm', '--zero-superblock', '/dev/sdb1'),
+ mock.call('mdadm', '--examine', '/dev/sdc',
+ use_standard_locale=True),
+ mock.call('mdadm', '--zero-superblock', '/dev/sdc'),
+ mock.call('parted', '/dev/sda', 'rm', '1'),
+ mock.call('parted', '/dev/sdb', 'rm', '1'),
+ mock.call('mdadm', '--assemble', '--scan', check_exit_code=False),
+ ])
+
@mock.patch.object(il_utils, 'execute', autospec=True)
def test_validate_configuration_valid_raid1(self, mocked_execute):
raid_config = {