python-tripleoclient/tripleoclient/tests/v1/baremetal/test_baremetal.py

1036 lines
38 KiB
Python

# Copyright 2015 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 tempfile
import json
import mock
import os
from ironic_discoverd import client as discoverd_client
from tripleoclient import exceptions
from tripleoclient.tests.v1.baremetal import fakes
from tripleoclient.v1 import baremetal
class TestValidateInstackEnv(fakes.TestBaremetal):
def setUp(self):
super(TestValidateInstackEnv, self).setUp()
self.instack_json = tempfile.NamedTemporaryFile(mode='w', delete=False)
# Get the command object to test
self.cmd = baremetal.ValidateInstackEnv(self.app, None)
def mock_instackenv_json(self, instackenv_data):
json.dump(instackenv_data, self.instack_json)
self.instack_json.close()
def tearDown(self):
super(TestValidateInstackEnv, self).tearDown()
os.unlink(self.instack_json.name)
def test_success(self):
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "SOME SSH KEY",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:59"
],
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(0, self.cmd.error_count)
def test_empty_password(self):
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:59"
],
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
def test_no_password(self):
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:59"
],
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
def test_empty_user(self):
self.mock_instackenv_json({
"nodes": [{
"pm_user": "",
"pm_addr": "192.168.122.1",
"pm_password": "SOME SSH KEY",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:59"
],
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
def test_no_user(self):
self.mock_instackenv_json({
"nodes": [{
"pm_addr": "192.168.122.1",
"pm_password": "SOME SSH KEY",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:59"
],
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
def test_empty_mac(self):
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "SOME SSH KEY",
"pm_type": "pxe_ssh",
"mac": [],
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
def test_no_mac(self):
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "SOME SSH KEY",
"pm_type": "pxe_ssh",
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
def test_duplicated_mac(self):
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "KEY1",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:58"
],
}, {
"arch": "x86_64",
"pm_user": "stack",
"pm_addr": "192.168.122.2",
"pm_password": "KEY2",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:58"
]
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
@mock.patch('tripleoclient.utils.run_shell')
def test_ipmitool_success(self, mock_run_shell):
mock_run_shell.return_value = 0
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "KEY1",
"pm_type": "pxe_ipmitool",
"mac": [
"00:0b:d0:69:7e:59"
],
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(0, self.cmd.error_count)
@mock.patch('tripleoclient.utils.run_shell')
def test_ipmitool_failure(self, mock_run_shell):
mock_run_shell.return_value = 1
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "KEY1",
"pm_type": "pxe_ipmitool",
"mac": [
"00:0b:d0:69:7e:59"
],
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
@mock.patch('tripleoclient.utils.run_shell')
def test_duplicated_baremetal_ip(self, mock_run_shell):
mock_run_shell.return_value = 0
self.mock_instackenv_json({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "KEY1",
"pm_type": "pxe_ipmitool",
"mac": [
"00:0b:d0:69:7e:59"
],
}, {
"arch": "x86_64",
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "KEY2",
"pm_type": "pxe_ipmitool",
"mac": [
"00:0b:d0:69:7e:58"
]
}]
})
arglist = ['-f', self.instack_json.name]
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, self.cmd.error_count)
class TestImportBaremetal(fakes.TestBaremetal):
def setUp(self):
super(TestImportBaremetal, self).setUp()
# Get the command object to test
self.cmd = baremetal.ImportBaremetal(self.app, None)
self.csv_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
self.json_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
self.instack_json = tempfile.NamedTemporaryFile(mode='w', delete=False)
self.csv_file.write("""\
pxe_ssh,192.168.122.1,root,"KEY1",00:d0:28:4c:e8:e8
pxe_ssh,192.168.122.1,root,"KEY2",00:7c:ef:3d:eb:60""")
json.dump([{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "KEY1",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:59"
],
}, {
"arch": "x86_64",
"pm_user": "stack",
"pm_addr": "192.168.122.2",
"pm_password": "KEY2",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:58"
]
}], self.json_file)
json.dump({
"nodes": [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "KEY1",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:59"
],
}, {
"arch": "x86_64",
"pm_user": "stack",
"pm_addr": "192.168.122.2",
"pm_password": "KEY2",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:58"
]
}]
}, self.instack_json)
self.csv_file.close()
self.json_file.close()
self.instack_json.close()
def tearDown(self):
super(TestImportBaremetal, self).tearDown()
os.unlink(self.csv_file.name)
os.unlink(self.json_file.name)
os.unlink(self.instack_json.name)
@mock.patch('os_cloud_config.nodes.register_all_nodes', autospec=True)
def test_json_import(self, mock_register_nodes):
arglist = [self.json_file.name, '--json', '-s', 'http://localhost']
verifylist = [
('csv', False),
('json', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_register_nodes.assert_called_with(
'http://localhost',
[
{
'pm_password': 'KEY1',
'pm_type': 'pxe_ssh',
'pm_user': 'stack',
'pm_addr': '192.168.122.1',
'mac': ['00:0b:d0:69:7e:59']
}, {
'pm_user': 'stack',
'pm_password': 'KEY2',
'pm_addr': '192.168.122.2',
'arch': 'x86_64',
'pm_type': 'pxe_ssh',
'mac': ['00:0b:d0:69:7e:58']
}
],
client=self.app.client_manager.tripleoclient.baremetal(),
keystone_client=None)
@mock.patch('os_cloud_config.nodes.register_all_nodes', autospec=True)
def test_instack_json_import(self, mock_register_nodes):
arglist = [self.instack_json.name, '--json', '-s', 'http://localhost']
verifylist = [
('csv', False),
('json', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_register_nodes.assert_called_with(
'http://localhost',
[
{
'pm_password': 'KEY1',
'pm_type': 'pxe_ssh',
'pm_user': 'stack',
'pm_addr': '192.168.122.1',
'mac': ['00:0b:d0:69:7e:59']
}, {
'pm_user': 'stack',
'pm_password': 'KEY2',
'pm_addr': '192.168.122.2',
'arch': 'x86_64',
'pm_type': 'pxe_ssh',
'mac': ['00:0b:d0:69:7e:58']
}
],
client=self.app.client_manager.tripleoclient.baremetal(),
keystone_client=None)
@mock.patch('os_cloud_config.nodes.register_all_nodes', autospec=True)
def test_csv_import(self, mock_register_nodes):
arglist = [self.csv_file.name, '--csv', '-s', 'http://localhost']
verifylist = [
('csv', True),
('json', False),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
mock_register_nodes.assert_called_with(
'http://localhost',
[
{
'pm_password': 'KEY1',
'pm_user': 'root',
'pm_type': 'pxe_ssh',
'pm_addr': '192.168.122.1',
'mac': ['00:d0:28:4c:e8:e8']
}, {
'pm_password': 'KEY2',
'pm_user': 'root',
'pm_type': 'pxe_ssh',
'pm_addr': '192.168.122.1',
'mac': ['00:7c:ef:3d:eb:60']
}
],
client=self.app.client_manager.tripleoclient.baremetal(),
keystone_client=None)
@mock.patch('time.sleep', lambda sec: None)
class TestStartBaremetalIntrospectionBulk(fakes.TestBaremetal):
def setUp(self):
super(TestStartBaremetalIntrospectionBulk, self).setUp()
# Get the command object to test
self.cmd = baremetal.StartBaremetalIntrospectionBulk(self.app, None)
@mock.patch('ironic_discoverd.client.get_status', autospec=True)
@mock.patch('ironic_discoverd.client.introspect', autospec=True)
def test_introspect_bulk_one(self, introspect_mock, get_status_mock,):
client = self.app.client_manager.tripleoclient.baremetal()
client.node.list.return_value = [
mock.Mock(uuid="ABCDEFGH", provision_state="manageable")
]
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
introspect_mock.assert_called_once_with(
'ABCDEFGH', base_url=None, auth_token='TOKEN')
@mock.patch('tripleoclient.utils.wait_for_node_discovery',
autospec=True)
@mock.patch('tripleoclient.utils.wait_for_provision_state',
autospec=True)
@mock.patch('ironic_discoverd.client.get_status', autospec=True)
@mock.patch('ironic_discoverd.client.introspect', autospec=True)
def test_introspect_bulk(self, introspect_mock, get_status_mock,
wait_for_state_mock, wait_for_discover_mock):
wait_for_discover_mock.return_value = []
wait_for_state_mock.return_value = True
get_status_mock.return_value = {'finished': True, 'error': None}
client = self.app.client_manager.tripleoclient.baremetal()
client.node.list.return_value = [
mock.Mock(uuid="ABCDEFGH", provision_state="available"),
mock.Mock(uuid="IJKLMNOP", provision_state="manageable"),
mock.Mock(uuid="QRSTUVWX", provision_state="available"),
]
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
# The nodes that are available are set to "manageable" state.
client.node.set_provision_state.assert_has_calls([
mock.call('ABCDEFGH', 'manage'),
mock.call('QRSTUVWX', 'manage'),
])
# Since everything is mocked, the node states doesn't change.
# Therefore only the node originally in manageable state is
# introspected:
introspect_mock.assert_has_calls([
mock.call('IJKLMNOP', base_url=None, auth_token='TOKEN'),
])
wait_for_discover_mock.assert_called_once_with(
discoverd_client, 'TOKEN', None,
['IJKLMNOP'])
# And lastly it will be set to available:
client.node.set_provision_state.assert_has_calls([
mock.call('IJKLMNOP', 'provide'),
])
class TestStatusBaremetalIntrospectionBulk(fakes.TestBaremetal):
def setUp(self):
super(TestStatusBaremetalIntrospectionBulk, self).setUp()
# Get the command object to test
self.cmd = baremetal.StatusBaremetalIntrospectionBulk(self.app, None)
@mock.patch('ironic_discoverd.client.get_status', autospec=True)
def test_status_bulk_one(self, discoverd_mock):
client = self.app.client_manager.tripleoclient.baremetal()
client.node.list.return_value = [
mock.Mock(uuid="ABCDEFGH")
]
discoverd_mock.return_value = {
'finished': False, 'error': None
}
parsed_args = self.check_parser(self.cmd, [], [])
result = self.cmd.take_action(parsed_args)
discoverd_mock.assert_called_once_with(
'ABCDEFGH', base_url=None, auth_token='TOKEN')
self.assertEqual(result, (
('Node UUID', 'Finished', 'Error'),
[('ABCDEFGH', False, None)]))
@mock.patch('ironic_discoverd.client.get_status', autospec=True)
def test_status_bulk(self, discoverd_mock):
client = self.app.client_manager.tripleoclient.baremetal()
client.node.list.return_value = [
mock.Mock(uuid="ABCDEFGH"),
mock.Mock(uuid="IJKLMNOP"),
mock.Mock(uuid="QRSTUVWX"),
]
discoverd_mock.return_value = {
'finished': False, 'error': None
}
parsed_args = self.check_parser(self.cmd, [], [])
result = self.cmd.take_action(parsed_args)
discoverd_mock.assert_has_calls([
mock.call('ABCDEFGH', base_url=None, auth_token='TOKEN'),
mock.call('IJKLMNOP', base_url=None, auth_token='TOKEN'),
mock.call('QRSTUVWX', base_url=None, auth_token='TOKEN'),
])
self.assertEqual(result, (
('Node UUID', 'Finished', 'Error'),
[
('ABCDEFGH', False, None),
('IJKLMNOP', False, None),
('QRSTUVWX', False, None)
]
))
class TestConfigureReadyState(fakes.TestBaremetal):
def setUp(self):
super(TestConfigureReadyState, self).setUp()
self.cmd = baremetal.ConfigureReadyState(self.app, None)
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_configure_bios')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_configure_root_raid_volumes')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_configure_nonroot_raid_volumes')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_wait_for_drac_config_jobs')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_delete_raid_volumes')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_change_power_state')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_run_introspection')
def test_configure_ready_state(self, mock_run_introspection,
mock_change_power_state,
mock_delete_raid_volumes,
mock_wait_for_drac_config_jobs,
mock_configure_nonroot_raid_volumes,
mock_configure_root_raid_volumes,
mock_configure_bios):
nodes = [mock.Mock(uuid='foo', driver='drac'),
mock.Mock(uuid='bar', driver='ilo'),
mock.Mock(uuid='baz', driver='drac')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.list.return_value = nodes
argslist = ['--delete-existing-raid-volumes']
verifylist = [('delete_raid_volumes', True)]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self.cmd.take_action(parsed_args)
drac_nodes = [node for node in nodes if 'drac' in node.driver]
mock_configure_bios.assert_called_once_with(drac_nodes)
mock_configure_root_raid_volumes.assert_called_once_with(drac_nodes)
mock_configure_nonroot_raid_volumes.assert_called_once_with(drac_nodes)
mock_wait_for_drac_config_jobs.assert_called_with(drac_nodes)
mock_delete_raid_volumes.assert_called_with(drac_nodes)
mock_change_power_state.assert_has_calls(([
mock.call(drac_nodes, 'reboot'),
mock.call(drac_nodes, 'reboot'),
mock.call(drac_nodes, 'off'),
]))
mock_run_introspection.assert_called_once_with(drac_nodes)
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_configure_bios')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_configure_root_raid_volumes')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_configure_nonroot_raid_volumes')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_wait_for_drac_config_jobs')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_change_power_state')
@mock.patch('tripleoclient.v1.baremetal.ConfigureReadyState.'
'_run_introspection')
def test_configure_ready_state_with_delete_existing_raid_volumes(
self, mock_run_introspection, mock_change_power_state,
mock_wait_for_drac_config_jobs,
mock_configure_nonroot_raid_volumes,
mock_configure_root_raid_volumes, mock_configure_bios):
nodes = [mock.Mock(uuid='foo', driver='drac'),
mock.Mock(uuid='bar', driver='ilo'),
mock.Mock(uuid='baz', driver='drac')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.list.return_value = nodes
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
drac_nodes = [node for node in nodes if 'drac' in node.driver]
mock_configure_bios.assert_called_once_with(drac_nodes)
mock_configure_root_raid_volumes.assert_called_once_with(drac_nodes)
mock_configure_nonroot_raid_volumes.assert_called_once_with(drac_nodes)
mock_wait_for_drac_config_jobs.assert_called_with(drac_nodes)
mock_change_power_state.assert_has_calls(([
mock.call(drac_nodes, 'reboot'),
mock.call(drac_nodes, 'reboot'),
mock.call(drac_nodes, 'off'),
]))
mock_run_introspection.assert_called_once_with(drac_nodes)
@mock.patch.object(baremetal.ConfigureReadyState, 'sleep_time',
new_callable=mock.PropertyMock,
return_value=0)
def test__configure_bios(self, mock_sleep_time):
nodes = [mock.Mock(uuid='foo')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
self.cmd.bm_client = bm_client
self.cmd._configure_bios(nodes)
bm_client.node.vendor_passthru.assert_called_once_with(
'foo', 'configure_bios_settings', http_method='POST')
@mock.patch.object(baremetal.ConfigureReadyState, 'sleep_time',
new_callable=mock.PropertyMock,
return_value=0)
def test__configure_root_raid_volumes(self, mock_sleep_time):
nodes = [mock.Mock(uuid='foo')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
self.cmd.bm_client = bm_client
self.cmd._configure_root_raid_volumes(nodes)
bm_client.node.vendor_passthru.assert_called_once_with(
'foo', 'create_raid_configuration',
{'create_nonroot_volumes': False,
'create_root_volume': True},
'POST')
@mock.patch.object(baremetal.ConfigureReadyState, 'sleep_time',
new_callable=mock.PropertyMock,
return_value=0)
def test__configure_nonroot_raid_volumes(self, mock_sleep_time):
nodes = [mock.Mock(uuid='foo')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
self.cmd.bm_client = bm_client
self.cmd._configure_nonroot_raid_volumes(nodes)
bm_client.node.vendor_passthru.assert_called_once_with(
'foo', 'create_raid_configuration',
{'create_nonroot_volumes': True,
'create_root_volume': False},
'POST')
@mock.patch.object(baremetal.ConfigureReadyState, 'sleep_time',
new_callable=mock.PropertyMock,
return_value=0)
def test__wait_for_drac_config_jobs(self, mock_sleep_time):
nodes = [mock.Mock(uuid='foo')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.vendor_passthru.side_effect = [
mock.Mock(unfinished_jobs={'percent_complete': '34',
'id': 'JID_343938731947',
'name': 'ConfigBIOS:BIOS.Setup.1-1'}),
mock.Mock(unfinished_jobs={}),
]
self.cmd.bm_client = bm_client
self.cmd._wait_for_drac_config_jobs(nodes)
self.assertEqual(2, bm_client.node.vendor_passthru.call_count)
bm_client.node.vendor_passthru.assert_has_calls(
mock.call('foo', 'list_unfinished_jobs', http_method='GET'),
)
@mock.patch.object(baremetal.ConfigureReadyState, 'sleep_time',
new_callable=mock.PropertyMock,
return_value=0)
def test__wait_for_drac_config_jobs_times_out(self, mock_sleep_time):
nodes = [mock.Mock(uuid='foo')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.vendor_passthru.return_value = mock.Mock(
unfinished_jobs={'percent_complete': '34',
'id': 'JID_343938731947',
'name': 'ConfigBIOS:BIOS.Setup.1-1'})
self.cmd.bm_client = bm_client
self.assertRaises(exceptions.Timeout,
self.cmd._wait_for_drac_config_jobs,
nodes)
@mock.patch.object(baremetal.ConfigureReadyState, 'sleep_time',
new_callable=mock.PropertyMock,
return_value=0)
def test__delete_raid_volumes(self, mock_sleep_time):
node_with_raid_volume = mock.Mock(uuid='foo')
nodes = [node_with_raid_volume, mock.Mock(uuid='bar')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.vendor_passthru.side_effect = [
mock.Mock(virtual_disks=[
{'controller': 'RAID.Integrated.1-1',
'id': 'Disk.Virtual.0:RAID.Integrated.1-1'},
{'controller': 'RAID.Integrated.1-1',
'id': 'Disk.Virtual.0:RAID.Integrated.1-2'}]),
True, True, True,
mock.Mock(virtual_disks=[])
]
self.cmd.bm_client = bm_client
nodes_to_restart = self.cmd._delete_raid_volumes(nodes)
bm_client.node.vendor_passthru.assert_has_calls([
mock.call('foo', 'list_virtual_disks', http_method='GET'),
mock.call('foo', 'delete_virtual_disk',
{'virtual_disk': 'Disk.Virtual.0:RAID.Integrated.1-1'},
'POST'),
mock.call('foo', 'delete_virtual_disk',
{'virtual_disk': 'Disk.Virtual.0:RAID.Integrated.1-2'},
'POST'),
mock.call('foo', 'apply_pending_raid_config',
{'raid_controller': 'RAID.Integrated.1-1'}, 'POST'),
])
self.assertEqual(set([node_with_raid_volume]), nodes_to_restart)
def test__change_power_state(self):
nodes = [mock.Mock(uuid='foo')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
self.cmd.bm_client = bm_client
self.cmd._change_power_state(nodes, 'reboot')
bm_client.node.set_power_state.assert_called_once_with('foo', 'reboot')
@mock.patch('ironic_discoverd.client.introspect', autospec=True)
@mock.patch('tripleoclient.utils.wait_for_node_discovery',
autospec=True)
def test__run_introspection(self, mock_wait_for_node_discovery,
mock_introspect):
nodes = [mock.Mock(uuid='foo')]
bm_client = self.app.client_manager.tripleoclient.baremetal()
self.cmd.bm_client = bm_client
self.cmd.discoverd_url = None
self.cmd._run_introspection(nodes)
mock_introspect.assert_called_once_with('foo', base_url=None,
auth_token='TOKEN')
mock_wait_for_node_discovery.assert_called_once_with(mock.ANY, 'TOKEN',
None, ['foo'])
class TestConfigureBaremetalBoot(fakes.TestBaremetal):
def setUp(self):
super(TestConfigureBaremetalBoot, self).setUp()
# Get the command object to test
self.cmd = baremetal.ConfigureBaremetalBoot(self.app, None)
@mock.patch('openstackclient.common.utils.find_resource', autospec=True)
def test_configure_boot(self, find_resource_mock):
find_resource_mock.return_value = mock.Mock(id="IDIDID")
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.list.return_value = [
mock.Mock(uuid="ABCDEFGH"),
mock.Mock(uuid="IJKLMNOP"),
]
bm_client.node.get.side_effect = [
mock.Mock(uuid="ABCDEFGH", properties={}),
mock.Mock(uuid="IJKLMNOP", properties={}),
]
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
self.assertEqual(find_resource_mock.call_count, 2)
self.assertEqual(bm_client.node.update.call_count, 2)
self.assertEqual(bm_client.node.update.mock_calls, [
mock.call('ABCDEFGH', [{
'op': 'add', 'value': 'boot_option:local',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
mock.call('IJKLMNOP', [{
'op': 'add', 'value': 'boot_option:local',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}])
])
@mock.patch('openstackclient.common.utils.find_resource', autospec=True)
@mock.patch.object(baremetal.ConfigureBaremetalBoot, 'sleep_time',
new_callable=mock.PropertyMock,
return_value=0)
def test_configure_boot_in_transition(self, _, find_resource_mock):
find_resource_mock.return_value = mock.Mock(id="IDIDID")
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.list.return_value = [mock.Mock(uuid="ABCDEFGH",
power_state=None),
]
bm_client.node.get.side_effect = [mock.Mock(uuid="ABCDEFGH",
power_state=None,
properties={}),
mock.Mock(uuid="ABCDEFGH",
power_state='available',
properties={}),
mock.Mock(uuid="ABCDEFGH",
power_state='available',
properties={}),
]
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, bm_client.node.list.call_count)
self.assertEqual(3, bm_client.node.get.call_count)
self.assertEqual(1, bm_client.node.update.call_count)
@mock.patch('openstackclient.common.utils.find_resource', autospec=True)
@mock.patch.object(baremetal.ConfigureBaremetalBoot, 'sleep_time',
new_callable=mock.PropertyMock,
return_value=0)
def test_configure_boot_timeout(self, _, find_resource_mock):
find_resource_mock.return_value = mock.Mock(id="IDIDID")
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.list.return_value = [mock.Mock(uuid="ABCDEFGH",
power_state=None),
]
bm_client.node.get.return_value = mock.Mock(uuid="ABCDEFGH",
power_state=None)
parsed_args = self.check_parser(self.cmd, [], [])
self.assertRaises(exceptions.Timeout,
self.cmd.take_action,
parsed_args)
@mock.patch('openstackclient.common.utils.find_resource', autospec=True)
def test_configure_boot_skip_maintenance(self, find_resource_mock):
find_resource_mock.return_value = mock.Mock(id="IDIDID")
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.list.return_value = [
mock.Mock(uuid="ABCDEFGH", maintenance=False),
]
bm_client.node.get.return_value = mock.Mock(uuid="ABCDEFGH",
maintenance=False,
properties={})
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
self.assertEqual(bm_client.node.list.mock_calls, [mock.call(
maintenance=False)])
@mock.patch('openstackclient.common.utils.find_resource', autospec=True)
def test_configure_boot_existing_properties(self, find_resource_mock):
find_resource_mock.return_value = mock.Mock(id="IDIDID")
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.list.return_value = [
mock.Mock(uuid="ABCDEFGH"),
mock.Mock(uuid="IJKLMNOP"),
mock.Mock(uuid="QRSTUVWX"),
mock.Mock(uuid="YZABCDEF"),
]
bm_client.node.get.side_effect = [
mock.Mock(uuid="ABCDEFGH", properties={
'capabilities': 'existing:cap'
}),
mock.Mock(uuid="IJKLMNOP", properties={
'capabilities': 'boot_option:local'
}),
mock.Mock(uuid="QRSTUVWX", properties={
'capabilities': 'boot_option:remote'
}),
mock.Mock(uuid="YZABCDEF", properties={}),
]
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
self.assertEqual(find_resource_mock.call_count, 2)
self.assertEqual(bm_client.node.update.call_count, 4)
self.assertEqual(bm_client.node.update.mock_calls, [
mock.call('ABCDEFGH', [{
'op': 'add', 'value': 'boot_option:local,existing:cap',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
mock.call('IJKLMNOP', [{
'op': 'add', 'value': 'boot_option:local',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
mock.call('QRSTUVWX', [{
'op': 'add', 'value': 'boot_option:remote',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
mock.call('YZABCDEF', [{
'op': 'add', 'value': 'boot_option:local',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
])
class TestShowNodeCapabilities(fakes.TestBaremetal):
def setUp(self):
super(TestShowNodeCapabilities, self).setUp()
# Get the command object to test
self.cmd = baremetal.ShowNodeCapabilities(self.app, None)
def test_success(self):
bm_client = self.app.client_manager.tripleoclient.baremetal()
bm_client.node.list.return_value = [
mock.Mock(uuid='UUID1'),
mock.Mock(uuid='UUID2'),
]
bm_client.node.get.return_value = mock.Mock(
properties={'capabilities': 'boot_option:local'})
arglist = []
parsed_args = self.check_parser(self.cmd, arglist, [])
result = self.cmd.take_action(parsed_args)
self.assertEqual((
('Node UUID', 'Node Capabilities'),
[('UUID1', 'boot_option:local'), ('UUID2', 'boot_option:local')]
), result)