957
974
self.assertIsNone(node.last_error)
958
975
# Verify reservation has been cleared.
959
976
self.assertIsNone(node.reservation)
977
mock_iwdi.assert_called_once_with(self.context, node.instance_info)
978
self.assertNotIn('is_whole_disk_image', node.driver_internal_info)
961
980
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.validate')
962
def test_do_node_deploy_validate_fail(self, mock_validate):
963
self._test_do_node_deploy_validate_fail(mock_validate)
981
def test_do_node_deploy_validate_fail(self, mock_validate, mock_iwdi):
982
self._test_do_node_deploy_validate_fail(mock_validate, mock_iwdi)
965
984
@mock.patch('ironic.drivers.modules.fake.FakePower.validate')
966
def test_do_node_deploy_power_validate_fail(self, mock_validate):
967
self._test_do_node_deploy_validate_fail(mock_validate)
969
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
970
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.prepare')
971
def test__do_node_deploy_driver_raises_prepare_error(self, mock_prepare,
973
self._start_service()
974
# test when driver.deploy.prepare raises an exception
975
mock_prepare.side_effect = exception.InstanceDeployFailure('test')
976
node = obj_utils.create_test_node(self.context, driver='fake',
977
provision_state=states.DEPLOYING,
978
target_provision_state=states.ACTIVE)
979
task = task_manager.TaskManager(self.context, node.uuid)
981
self.assertRaises(exception.InstanceDeployFailure,
982
manager.do_node_deploy, task,
983
self.service.conductor.id)
985
self.assertEqual(states.DEPLOYFAIL, node.provision_state)
986
# NOTE(deva): failing a deploy does not clear the target state
987
# any longer. Instead, it is cleared when the instance
989
self.assertEqual(states.ACTIVE, node.target_provision_state)
990
self.assertIsNotNone(node.last_error)
991
self.assertTrue(mock_prepare.called)
992
self.assertFalse(mock_deploy.called)
994
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
995
def test__do_node_deploy_driver_raises_error(self, mock_deploy):
996
self._start_service()
997
# test when driver.deploy.deploy raises an exception
998
mock_deploy.side_effect = exception.InstanceDeployFailure('test')
999
node = obj_utils.create_test_node(self.context, driver='fake',
1000
provision_state=states.DEPLOYING,
1001
target_provision_state=states.ACTIVE)
1002
task = task_manager.TaskManager(self.context, node.uuid)
1004
self.assertRaises(exception.InstanceDeployFailure,
1005
manager.do_node_deploy, task,
1006
self.service.conductor.id)
1008
self.assertEqual(states.DEPLOYFAIL, node.provision_state)
1009
# NOTE(deva): failing a deploy does not clear the target state
1010
# any longer. Instead, it is cleared when the instance
1012
self.assertEqual(states.ACTIVE, node.target_provision_state)
1013
self.assertIsNotNone(node.last_error)
1014
mock_deploy.assert_called_once_with(mock.ANY)
1016
@mock.patch.object(manager, '_store_configdrive')
1017
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1018
def test__do_node_deploy_ok(self, mock_deploy, mock_store):
1019
self._start_service()
1020
# test when driver.deploy.deploy returns DEPLOYDONE
1021
mock_deploy.return_value = states.DEPLOYDONE
1022
node = obj_utils.create_test_node(self.context, driver='fake',
1023
provision_state=states.DEPLOYING,
1024
target_provision_state=states.ACTIVE)
1025
task = task_manager.TaskManager(self.context, node.uuid)
1027
manager.do_node_deploy(task, self.service.conductor.id)
1029
self.assertEqual(states.ACTIVE, node.provision_state)
1030
self.assertEqual(states.NOSTATE, node.target_provision_state)
1031
self.assertIsNone(node.last_error)
1032
mock_deploy.assert_called_once_with(mock.ANY)
1033
# assert _store_configdrive wasn't invoked
1034
self.assertFalse(mock_store.called)
1036
@mock.patch.object(manager, '_store_configdrive')
1037
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1038
def test__do_node_deploy_ok_configdrive(self, mock_deploy, mock_store):
1039
self._start_service()
1040
# test when driver.deploy.deploy returns DEPLOYDONE
1041
mock_deploy.return_value = states.DEPLOYDONE
1042
node = obj_utils.create_test_node(self.context, driver='fake',
1043
provision_state=states.DEPLOYING,
1044
target_provision_state=states.ACTIVE)
1045
task = task_manager.TaskManager(self.context, node.uuid)
1048
manager.do_node_deploy(task, self.service.conductor.id,
1049
configdrive=configdrive)
1051
self.assertEqual(states.ACTIVE, node.provision_state)
1052
self.assertEqual(states.NOSTATE, node.target_provision_state)
1053
self.assertIsNone(node.last_error)
1054
mock_deploy.assert_called_once_with(mock.ANY)
1055
mock_store.assert_called_once_with(task.node, configdrive)
1057
@mock.patch.object(swift, 'SwiftAPI')
1058
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1059
def test__do_node_deploy_configdrive_swift_error(self, mock_deploy,
1061
CONF.set_override('configdrive_use_swift', True, group='conductor')
1062
self._start_service()
1063
# test when driver.deploy.deploy returns DEPLOYDONE
1064
mock_deploy.return_value = states.DEPLOYDONE
1065
node = obj_utils.create_test_node(self.context, driver='fake',
1066
provision_state=states.DEPLOYING,
1067
target_provision_state=states.ACTIVE)
1068
task = task_manager.TaskManager(self.context, node.uuid)
1070
mock_swift.side_effect = exception.SwiftOperationError('error')
1071
self.assertRaises(exception.SwiftOperationError,
1072
manager.do_node_deploy, task,
1073
self.service.conductor.id,
1074
configdrive='fake config drive')
1076
self.assertEqual(states.DEPLOYFAIL, node.provision_state)
1077
self.assertEqual(states.ACTIVE, node.target_provision_state)
1078
self.assertIsNotNone(node.last_error)
1079
self.assertFalse(mock_deploy.called)
1081
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1082
def test__do_node_deploy_ok_2(self, mock_deploy):
1083
# NOTE(rloo): a different way of testing for the same thing as in
1084
# test__do_node_deploy_ok()
1085
self._start_service()
1086
# test when driver.deploy.deploy returns DEPLOYDONE
1087
mock_deploy.return_value = states.DEPLOYDONE
1088
node = obj_utils.create_test_node(self.context, driver='fake')
1089
task = task_manager.TaskManager(self.context, node.uuid)
1090
task.process_event('deploy')
1092
manager.do_node_deploy(task, self.service.conductor.id)
1094
self.assertEqual(states.ACTIVE, node.provision_state)
1095
self.assertEqual(states.NOSTATE, node.target_provision_state)
1096
self.assertIsNone(node.last_error)
1097
mock_deploy.assert_called_once_with(mock.ANY)
985
def test_do_node_deploy_power_validate_fail(self, mock_validate,
987
self._test_do_node_deploy_validate_fail(mock_validate, mock_iwdi)
1099
989
@mock.patch('ironic.conductor.task_manager.TaskManager.process_event')
1100
def test_deploy_with_nostate_converts_to_available(self, mock_pe):
990
def test_deploy_with_nostate_converts_to_available(self, mock_pe,
1101
992
# expressly create a node using the Juno-era NOSTATE state
1102
993
# and assert that it does not result in an error, and that the state
1103
994
# is converted to the new AVAILABLE state.
1104
995
# Mock the process_event call, because the transitions from
1105
996
# AVAILABLE are tested thoroughly elsewhere
1106
997
# NOTE(deva): This test can be deleted after Kilo is released
998
mock_iwdi.return_value = False
1107
999
self._start_service()
1108
1000
node = obj_utils.create_test_node(self.context, driver='fake',
1109
1001
provision_state=states.NOSTATE)
1251
1170
self.assertIsNone(node.last_error)
1252
1171
# Verify reservation has been cleared.
1253
1172
self.assertIsNone(node.reservation)
1173
mock_iwdi.assert_called_once_with(self.context, node.instance_info)
1174
self.assertNotIn('is_whole_disk_image', node.driver_internal_info)
1176
def test_do_node_deploy_worker_pool_full(self, mock_iwdi):
1177
mock_iwdi.return_value = False
1178
prv_state = states.AVAILABLE
1179
tgt_prv_state = states.NOSTATE
1180
node = obj_utils.create_test_node(self.context,
1181
provision_state=prv_state,
1182
target_provision_state=tgt_prv_state,
1183
last_error=None, driver='fake')
1184
self._start_service()
1186
with mock.patch.object(self.service, '_spawn_worker') as mock_spawn:
1187
mock_spawn.side_effect = exception.NoFreeConductorWorker()
1189
exc = self.assertRaises(messaging.rpc.ExpectedException,
1190
self.service.do_node_deploy,
1191
self.context, node.uuid)
1192
# Compare true exception hidden by @messaging.expected_exceptions
1193
self.assertEqual(exception.NoFreeConductorWorker, exc.exc_info[0])
1194
self.service._worker_pool.waitall()
1196
# Make sure things were rolled back
1197
self.assertEqual(prv_state, node.provision_state)
1198
self.assertEqual(tgt_prv_state, node.target_provision_state)
1199
self.assertIsNotNone(node.last_error)
1200
# Verify reservation has been cleared.
1201
self.assertIsNone(node.reservation)
1202
mock_iwdi.assert_called_once_with(self.context, node.instance_info)
1203
self.assertFalse(node.driver_internal_info['is_whole_disk_image'])
1206
@_mock_record_keepalive
1207
class DoNodeDeployTearDownTestCase(_ServiceSetUpMixin,
1208
tests_db_base.DbTestCase):
1209
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1210
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.prepare')
1211
def test__do_node_deploy_driver_raises_prepare_error(self, mock_prepare,
1213
self._start_service()
1214
# test when driver.deploy.prepare raises an exception
1215
mock_prepare.side_effect = exception.InstanceDeployFailure('test')
1216
node = obj_utils.create_test_node(self.context, driver='fake',
1217
provision_state=states.DEPLOYING,
1218
target_provision_state=states.ACTIVE)
1219
task = task_manager.TaskManager(self.context, node.uuid)
1221
self.assertRaises(exception.InstanceDeployFailure,
1222
manager.do_node_deploy, task,
1223
self.service.conductor.id)
1225
self.assertEqual(states.DEPLOYFAIL, node.provision_state)
1226
# NOTE(deva): failing a deploy does not clear the target state
1227
# any longer. Instead, it is cleared when the instance
1229
self.assertEqual(states.ACTIVE, node.target_provision_state)
1230
self.assertIsNotNone(node.last_error)
1231
self.assertTrue(mock_prepare.called)
1232
self.assertFalse(mock_deploy.called)
1234
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1235
def test__do_node_deploy_driver_raises_error(self, mock_deploy):
1236
self._start_service()
1237
# test when driver.deploy.deploy raises an exception
1238
mock_deploy.side_effect = exception.InstanceDeployFailure('test')
1239
node = obj_utils.create_test_node(self.context, driver='fake',
1240
provision_state=states.DEPLOYING,
1241
target_provision_state=states.ACTIVE)
1242
task = task_manager.TaskManager(self.context, node.uuid)
1244
self.assertRaises(exception.InstanceDeployFailure,
1245
manager.do_node_deploy, task,
1246
self.service.conductor.id)
1248
self.assertEqual(states.DEPLOYFAIL, node.provision_state)
1249
# NOTE(deva): failing a deploy does not clear the target state
1250
# any longer. Instead, it is cleared when the instance
1252
self.assertEqual(states.ACTIVE, node.target_provision_state)
1253
self.assertIsNotNone(node.last_error)
1254
mock_deploy.assert_called_once_with(mock.ANY)
1256
@mock.patch.object(manager, '_store_configdrive')
1257
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1258
def test__do_node_deploy_ok(self, mock_deploy, mock_store):
1259
self._start_service()
1260
# test when driver.deploy.deploy returns DEPLOYDONE
1261
mock_deploy.return_value = states.DEPLOYDONE
1262
node = obj_utils.create_test_node(self.context, driver='fake',
1263
provision_state=states.DEPLOYING,
1264
target_provision_state=states.ACTIVE)
1265
task = task_manager.TaskManager(self.context, node.uuid)
1267
manager.do_node_deploy(task, self.service.conductor.id)
1269
self.assertEqual(states.ACTIVE, node.provision_state)
1270
self.assertEqual(states.NOSTATE, node.target_provision_state)
1271
self.assertIsNone(node.last_error)
1272
mock_deploy.assert_called_once_with(mock.ANY)
1273
# assert _store_configdrive wasn't invoked
1274
self.assertFalse(mock_store.called)
1276
@mock.patch.object(manager, '_store_configdrive')
1277
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1278
def test__do_node_deploy_ok_configdrive(self, mock_deploy, mock_store):
1279
self._start_service()
1280
# test when driver.deploy.deploy returns DEPLOYDONE
1281
mock_deploy.return_value = states.DEPLOYDONE
1282
node = obj_utils.create_test_node(self.context, driver='fake',
1283
provision_state=states.DEPLOYING,
1284
target_provision_state=states.ACTIVE)
1285
task = task_manager.TaskManager(self.context, node.uuid)
1288
manager.do_node_deploy(task, self.service.conductor.id,
1289
configdrive=configdrive)
1291
self.assertEqual(states.ACTIVE, node.provision_state)
1292
self.assertEqual(states.NOSTATE, node.target_provision_state)
1293
self.assertIsNone(node.last_error)
1294
mock_deploy.assert_called_once_with(mock.ANY)
1295
mock_store.assert_called_once_with(task.node, configdrive)
1297
@mock.patch.object(swift, 'SwiftAPI')
1298
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1299
def test__do_node_deploy_configdrive_swift_error(self, mock_deploy,
1301
CONF.set_override('configdrive_use_swift', True, group='conductor')
1302
self._start_service()
1303
# test when driver.deploy.deploy returns DEPLOYDONE
1304
mock_deploy.return_value = states.DEPLOYDONE
1305
node = obj_utils.create_test_node(self.context, driver='fake',
1306
provision_state=states.DEPLOYING,
1307
target_provision_state=states.ACTIVE)
1308
task = task_manager.TaskManager(self.context, node.uuid)
1310
mock_swift.side_effect = exception.SwiftOperationError('error')
1311
self.assertRaises(exception.SwiftOperationError,
1312
manager.do_node_deploy, task,
1313
self.service.conductor.id,
1314
configdrive='fake config drive')
1316
self.assertEqual(states.DEPLOYFAIL, node.provision_state)
1317
self.assertEqual(states.ACTIVE, node.target_provision_state)
1318
self.assertIsNotNone(node.last_error)
1319
self.assertFalse(mock_deploy.called)
1321
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.deploy')
1322
def test__do_node_deploy_ok_2(self, mock_deploy):
1323
# NOTE(rloo): a different way of testing for the same thing as in
1324
# test__do_node_deploy_ok()
1325
self._start_service()
1326
# test when driver.deploy.deploy returns DEPLOYDONE
1327
mock_deploy.return_value = states.DEPLOYDONE
1328
node = obj_utils.create_test_node(self.context, driver='fake')
1329
task = task_manager.TaskManager(self.context, node.uuid)
1330
task.process_event('deploy')
1332
manager.do_node_deploy(task, self.service.conductor.id)
1334
self.assertEqual(states.ACTIVE, node.provision_state)
1335
self.assertEqual(states.NOSTATE, node.target_provision_state)
1336
self.assertIsNone(node.last_error)
1337
mock_deploy.assert_called_once_with(mock.ANY)
1255
1339
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.clean_up')
1256
1340
def test__check_deploy_timeouts(self, mock_cleanup):
1411
1478
self.assertEqual(exception.NoFreeConductorWorker, exc.exc_info[0])
1412
1479
self.service._worker_pool.waitall()
1414
# Assert instance_info was not touched
1481
# Assert instance_info/driver_internal_info was not touched
1415
1482
self.assertEqual(fake_instance_info, node.instance_info)
1416
# Make sure things were rolled back
1417
self.assertEqual(prv_state, node.provision_state)
1418
self.assertEqual(tgt_prv_state, node.target_provision_state)
1419
self.assertIsNotNone(node.last_error)
1420
# Verify reservation has been cleared.
1421
self.assertIsNone(node.reservation)
1424
@_mock_record_keepalive
1425
class MiscTestCase(_ServiceSetUpMixin, tests_db_base.DbTestCase):
1483
self.assertEqual(driver_internal_info, node.driver_internal_info)
1484
# Make sure things were rolled back
1485
self.assertEqual(prv_state, node.provision_state)
1486
self.assertEqual(tgt_prv_state, node.target_provision_state)
1487
self.assertIsNotNone(node.last_error)
1488
# Verify reservation has been cleared.
1489
self.assertIsNone(node.reservation)
1491
@mock.patch('ironic.conductor.manager.ConductorManager._spawn_worker')
1492
def test_do_provisioning_action_worker_pool_full(self, mock_spawn):
1493
prv_state = states.MANAGEABLE
1494
tgt_prv_state = states.CLEANING
1495
node = obj_utils.create_test_node(self.context, driver='fake',
1496
provision_state=prv_state,
1497
target_provision_state=tgt_prv_state,
1499
self._start_service()
1501
mock_spawn.side_effect = exception.NoFreeConductorWorker()
1503
exc = self.assertRaises(messaging.rpc.ExpectedException,
1504
self.service.do_provisioning_action,
1505
self.context, node.uuid, 'provide')
1506
# Compare true exception hidden by @messaging.expected_exceptions
1507
self.assertEqual(exception.NoFreeConductorWorker, exc.exc_info[0])
1508
self.service._worker_pool.waitall()
1510
# Make sure things were rolled back
1511
self.assertEqual(prv_state, node.provision_state)
1512
self.assertEqual(tgt_prv_state, node.target_provision_state)
1513
self.assertIsNotNone(node.last_error)
1514
# Verify reservation has been cleared.
1515
self.assertIsNone(node.reservation)
1517
@mock.patch('ironic.conductor.manager.ConductorManager._spawn_worker')
1518
def test_do_provision_action_provide(self, mock_spawn):
1519
# test when a node is cleaned going from manageable to available
1520
node = obj_utils.create_test_node(
1521
self.context, driver='fake',
1522
provision_state=states.MANAGEABLE,
1523
target_provision_state=states.AVAILABLE)
1525
self._start_service()
1526
self.service.do_provisioning_action(self.context, node.uuid, 'provide')
1528
# Node will be moved to AVAILABLE after cleaning, not tested here
1529
self.assertEqual(states.CLEANING, node.provision_state)
1530
self.assertEqual(states.AVAILABLE, node.target_provision_state)
1531
self.assertIsNone(node.last_error)
1532
mock_spawn.assert_called_with(self.service._do_node_clean, mock.ANY)
1535
@_mock_record_keepalive
1536
class DoNodeCleanTestCase(_ServiceSetUpMixin, tests_db_base.DbTestCase):
1538
super(DoNodeCleanTestCase, self).setUp()
1539
self.config(clean_nodes=True, group='conductor')
1540
self.power_update = {
1541
'step': 'update_firmware', 'priority': 10, 'interface': 'power'}
1542
self.deploy_update = {
1543
'step': 'update_firmware', 'priority': 10, 'interface': 'deploy'}
1544
self.deploy_erase = {
1545
'step': 'erase_disks', 'priority': 20, 'interface': 'deploy'}
1546
# Cleaning should be executed in this order
1547
self.clean_steps = [self.deploy_erase, self.power_update,
1550
self.deploy_raid = {
1551
'step': 'build_raid', 'priority': 0, 'interface': 'deploy'}
1553
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.get_clean_steps')
1554
@mock.patch('ironic.drivers.modules.fake.FakePower.get_clean_steps')
1555
def test__get_cleaning_steps(self, mock_power_steps, mock_deploy_steps):
1556
# Test getting cleaning steps, with one driver returning None, two
1557
# conflicting priorities, and asserting they are ordered properly.
1558
node = obj_utils.create_test_node(
1559
self.context, driver='fake',
1560
provision_state=states.CLEANING,
1561
target_provision_state=states.AVAILABLE)
1563
mock_power_steps.return_value = [self.power_update]
1564
mock_deploy_steps.return_value = [self.deploy_erase,
1567
with task_manager.acquire(
1568
self.context, node['id'], shared=False) as task:
1569
steps = manager._get_cleaning_steps(task, enabled=False)
1571
self.assertEqual(self.clean_steps, steps)
1573
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.get_clean_steps')
1574
@mock.patch('ironic.drivers.modules.fake.FakePower.get_clean_steps')
1575
def test__get_cleaning_steps_only_enabled(self, mock_power_steps,
1577
# Test getting only cleaning steps, with one driver returning None, two
1578
# conflicting priorities, and asserting they are ordered properly.
1579
# Should discard zap step
1580
node = obj_utils.create_test_node(
1581
self.context, driver='fake',
1582
provision_state=states.CLEANING,
1583
target_provision_state=states.AVAILABLE)
1585
mock_power_steps.return_value = [self.power_update]
1586
mock_deploy_steps.return_value = [self.deploy_erase,
1590
with task_manager.acquire(
1591
self.context, node['id'], shared=True) as task:
1592
steps = manager._get_cleaning_steps(task, enabled=True)
1594
self.assertEqual(self.clean_steps, steps)
1596
@mock.patch('ironic.conductor.manager.ConductorManager._spawn_worker')
1597
def test_continue_node_clean_worker_pool_full(self, mock_spawn):
1598
# Test the appropriate exception is raised if the worker pool is full
1599
prv_state = states.CLEANING
1600
tgt_prv_state = states.AVAILABLE
1601
node = obj_utils.create_test_node(self.context, driver='fake',
1602
provision_state=prv_state,
1603
target_provision_state=tgt_prv_state,
1605
self._start_service()
1607
mock_spawn.side_effect = exception.NoFreeConductorWorker()
1609
exc = self.assertRaises(messaging.rpc.ExpectedException,
1610
self.service.continue_node_clean,
1611
self.context, node.uuid)
1612
# Compare true exception hidden by @messaging.expected_exceptions
1613
self.assertEqual(exception.NoFreeConductorWorker, exc.exc_info[0])
1615
self.service._worker_pool.waitall()
1617
# Make sure things were rolled back
1618
self.assertEqual(prv_state, node.provision_state)
1619
self.assertEqual(tgt_prv_state, node.target_provision_state)
1621
@mock.patch('ironic.conductor.manager.ConductorManager._spawn_worker')
1622
def test_continue_node_clean_wrong_state(self, mock_spawn):
1623
# Test the appropriate exception is raised if node isn't already
1625
prv_state = states.DELETING
1626
tgt_prv_state = states.AVAILABLE
1627
node = obj_utils.create_test_node(self.context, driver='fake',
1628
provision_state=prv_state,
1629
target_provision_state=tgt_prv_state,
1631
self._start_service()
1633
exc = self.assertRaises(messaging.rpc.ExpectedException,
1634
self.service.continue_node_clean,
1635
self.context, node.uuid)
1636
# Compare true exception hidden by @messaging.expected_exceptions
1637
self.assertEqual(exception.InvalidStateRequested, exc.exc_info[0])
1639
self.service._worker_pool.waitall()
1641
# Make sure things were rolled back
1642
self.assertEqual(prv_state, node.provision_state)
1643
self.assertEqual(tgt_prv_state, node.target_provision_state)
1644
# Verify reservation has been cleared.
1645
self.assertIsNone(node.reservation)
1647
@mock.patch('ironic.conductor.manager.ConductorManager._spawn_worker')
1648
def test_continue_node_clean(self, mock_spawn):
1649
# test a node can continue cleaning via RPC
1650
prv_state = states.CLEANING
1651
tgt_prv_state = states.AVAILABLE
1652
driver_info = {'clean_steps': self.clean_steps}
1653
node = obj_utils.create_test_node(self.context, driver='fake',
1654
provision_state=prv_state,
1655
target_provision_state=tgt_prv_state,
1657
driver_internal_info=driver_info,
1658
clean_step=self.clean_steps[1])
1659
self._start_service()
1660
self.service.continue_node_clean(self.context, node.uuid)
1661
self.service._worker_pool.waitall()
1663
mock_spawn.assert_called_with(self.service._do_next_clean_step,
1664
mock.ANY, self.clean_steps,
1665
self.clean_steps[1])
1667
@mock.patch('ironic.drivers.modules.fake.FakePower.validate')
1668
def test__do_node_clean_validate_fail(self, mock_validate):
1669
# InvalidParameterValue should be cause node to go to CLEANFAIL
1670
self.config(clean_nodes=True, group='conductor')
1671
mock_validate.side_effect = exception.InvalidParameterValue('error')
1672
node = obj_utils.create_test_node(
1673
self.context, driver='fake',
1674
provision_state=states.CLEANING,
1675
target_provision_state=states.AVAILABLE)
1676
with task_manager.acquire(
1677
self.context, node['id'], shared=False) as task:
1678
self.service._do_node_clean(task)
1680
self.assertEqual(states.CLEANFAIL, node.provision_state)
1682
@mock.patch('ironic.drivers.modules.fake.FakePower.validate')
1683
def test__do_node_clean_disabled(self, mock_validate):
1684
self.config(clean_nodes=False, group='conductor')
1685
node = obj_utils.create_test_node(
1686
self.context, driver='fake',
1687
provision_state=states.CLEANING,
1688
target_provision_state=states.AVAILABLE,
1691
self._start_service()
1692
with task_manager.acquire(
1693
self.context, node['id'], shared=False) as task:
1694
self.service._do_node_clean(task)
1695
self.service._worker_pool.waitall()
1698
# Assert that the node was moved to available without cleaning
1699
mock_validate.assert_not_called()
1700
self.assertEqual(states.AVAILABLE, node.provision_state)
1701
self.assertEqual(states.NOSTATE, node.target_provision_state)
1702
self.assertEqual({}, node.clean_step)
1703
self.assertIsNone(node.driver_internal_info.get('clean_steps'))
1705
@mock.patch('ironic.conductor.manager.set_node_cleaning_steps')
1706
@mock.patch('ironic.conductor.manager.ConductorManager.'
1707
'_do_next_clean_step')
1708
@mock.patch('ironic.drivers.modules.fake.FakePower.validate')
1709
def test__do_node_clean(self, mock_validate, mock_next_step, mock_steps):
1710
node = obj_utils.create_test_node(
1711
self.context, driver='fake',
1712
provision_state=states.CLEANING,
1713
target_provision_state=states.AVAILABLE,
1715
power_state=states.POWER_OFF,
1716
driver_internal_info={'clean_steps': []})
1718
mock_steps.return_value = self.clean_steps
1720
self._start_service()
1721
with task_manager.acquire(
1722
self.context, node['id'], shared=False) as task:
1723
self.service._do_node_clean(task)
1725
self.service._worker_pool.waitall()
1728
mock_validate.assert_called_once()
1729
mock_next_step.assert_called_once_with(mock.ANY, [], {})
1730
mock_steps.assert_called_once()
1732
# Check that state didn't change
1733
self.assertEqual(states.CLEANING, node.provision_state)
1734
self.assertEqual(states.AVAILABLE, node.target_provision_state)
1736
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.execute_clean_step')
1737
def test__do_next_clean_step_first_step_async(self, mock_execute):
1738
# Execute the first async clean step on a node
1739
node = obj_utils.create_test_node(
1740
self.context, driver='fake',
1741
provision_state=states.CLEANING,
1742
target_provision_state=states.AVAILABLE,
1745
mock_execute.return_value = states.CLEANING
1747
self._start_service()
1749
with task_manager.acquire(
1750
self.context, node['id'], shared=False) as task:
1751
self.service._do_next_clean_step(task, self.clean_steps,
1754
self.service._worker_pool.waitall()
1757
self.assertEqual(states.CLEANING, node.provision_state)
1758
self.assertEqual(self.clean_steps[0], node.clean_step)
1759
mock_execute.assert_called_once_with(mock.ANY, self.clean_steps[0])
1761
@mock.patch('ironic.drivers.modules.fake.FakePower.execute_clean_step')
1762
def test__do_next_clean_step_continue_from_last_step(self, mock_execute):
1763
# Resume an in-progress cleaning after the first async step
1764
node = obj_utils.create_test_node(
1765
self.context, driver='fake',
1766
provision_state=states.CLEANING,
1767
target_provision_state=states.AVAILABLE,
1769
clean_step=self.clean_steps[0])
1770
mock_execute.return_value = states.CLEANING
1772
self._start_service()
1774
with task_manager.acquire(
1775
self.context, node['id'], shared=False) as task:
1776
self.service._do_next_clean_step(task, self.clean_steps,
1777
self.clean_steps[0])
1779
self.service._worker_pool.waitall()
1782
self.assertEqual(states.CLEANING, node.provision_state)
1783
self.assertEqual(self.clean_steps[1], node.clean_step)
1784
mock_execute.assert_called_once_with(mock.ANY, self.clean_steps[1])
1786
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.execute_clean_step')
1787
def test__do_next_clean_step_last_step_noop(self, mock_execute):
1788
# Resume where last_step is the last cleaning step, should be noop
1789
node = obj_utils.create_test_node(
1790
self.context, driver='fake',
1791
provision_state=states.CLEANING,
1792
target_provision_state=states.AVAILABLE,
1794
clean_step=self.clean_steps[-1])
1796
self._start_service()
1798
with task_manager.acquire(
1799
self.context, node['id'], shared=False) as task:
1800
self.service._do_next_clean_step(
1801
task, self.clean_steps, self.clean_steps[-1])
1803
self.service._worker_pool.waitall()
1806
# Cleaning should be complete without calling additional steps
1807
self.assertEqual(states.AVAILABLE, node.provision_state)
1808
self.assertEqual({}, node.clean_step)
1809
mock_execute.assert_not_called()
1811
@mock.patch('ironic.drivers.modules.fake.FakePower.execute_clean_step')
1812
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.execute_clean_step')
1813
def test__do_next_clean_step_all(self, mock_deploy_execute,
1814
mock_power_execute):
1815
# Run all steps from start to finish (all synchronous)
1816
node = obj_utils.create_test_node(
1817
self.context, driver='fake',
1818
provision_state=states.CLEANING,
1819
target_provision_state=states.AVAILABLE,
1822
mock_deploy_execute.return_value = None
1823
mock_power_execute.return_value = None
1825
self._start_service()
1827
with task_manager.acquire(
1828
self.context, node['id'], shared=False) as task:
1829
self.service._do_next_clean_step(
1830
task, self.clean_steps, node.clean_step)
1832
self.service._worker_pool.waitall()
1835
# Cleaning should be complete
1836
self.assertEqual(states.AVAILABLE, node.provision_state)
1837
self.assertEqual({}, node.clean_step)
1838
mock_power_execute.assert_called_once_with(mock.ANY,
1839
self.clean_steps[1])
1840
mock_deploy_execute.assert_has_calls = [
1841
mock.call(self.clean_steps[0]),
1842
mock.call(self.clean_steps[2])
1845
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.execute_clean_step')
1846
def test__do_next_clean_step_bad_last_step(self, mock_execute):
1847
# Make sure cleaning fails if last_step is incorrect
1848
node = obj_utils.create_test_node(
1849
self.context, driver='fake',
1850
provision_state=states.CLEANING,
1851
target_provision_state=states.AVAILABLE,
1855
self._start_service()
1857
with task_manager.acquire(
1858
self.context, node['id'], shared=False) as task:
1859
self.service._do_next_clean_step(
1860
task, self.clean_steps, {'interface': 'deploy',
1861
'step': 'not_a_clean_step',
1864
self.service._worker_pool.waitall()
1867
# Node should have failed without executing anything
1868
self.assertEqual(states.CLEANFAIL, node.provision_state)
1869
self.assertEqual({}, node.clean_step)
1870
self.assertIsNotNone(node.last_error)
1871
self.assertTrue(node.maintenance)
1872
mock_execute.assert_not_called()
1874
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.execute_clean_step')
1875
def test__do_next_clean_step_fail(self, mock_execute):
1876
# When a clean step fails, go to CLEANFAIL
1877
node = obj_utils.create_test_node(
1878
self.context, driver='fake',
1879
provision_state=states.CLEANING,
1880
target_provision_state=states.AVAILABLE,
1883
mock_execute.side_effect = Exception()
1885
self._start_service()
1887
with task_manager.acquire(
1888
self.context, node['id'], shared=False) as task:
1889
self.service._do_next_clean_step(
1890
task, self.clean_steps, node.clean_step)
1892
self.service._worker_pool.waitall()
1895
# Make sure we go to CLEANFAIL, clear clean_steps
1896
self.assertEqual(states.CLEANFAIL, node.provision_state)
1897
self.assertEqual({}, node.clean_step)
1898
self.assertIsNotNone(node.last_error)
1899
self.assertTrue(node.maintenance)
1900
mock_execute.assert_not_called()
1901
mock_execute.assert_called_once_with(mock.ANY, self.clean_steps[0])
1903
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.execute_clean_step')
1904
def test__do_next_clean_step_no_steps(self, mock_execute):
1905
# Resume where there are no steps, should be a noop
1906
node = obj_utils.create_test_node(
1907
self.context, driver='fake',
1908
provision_state=states.CLEANING,
1909
target_provision_state=states.AVAILABLE,
1913
self._start_service()
1915
with task_manager.acquire(
1916
self.context, node['id'], shared=False) as task:
1917
self.service._do_next_clean_step(
1918
task, [], node.clean_step)
1920
self.service._worker_pool.waitall()
1923
# Cleaning should be complete without calling additional steps
1924
self.assertEqual(states.AVAILABLE, node.provision_state)
1925
self.assertEqual({}, node.clean_step)
1926
mock_execute.assert_not_called()
1928
@mock.patch('ironic.drivers.modules.fake.FakePower.execute_clean_step')
1929
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.execute_clean_step')
1930
def test__do_next_clean_step_bad_step_return_value(
1931
self, deploy_exec_mock, power_exec_mock):
1932
# When a clean step fails, go to CLEANFAIL
1933
node = obj_utils.create_test_node(
1934
self.context, driver='fake',
1935
provision_state=states.CLEANING,
1936
target_provision_state=states.AVAILABLE,
1939
deploy_exec_mock.return_value = "foo"
1941
self._start_service()
1943
with task_manager.acquire(
1944
self.context, node['id'], shared=False) as task:
1945
self.service._do_next_clean_step(
1946
task, self.clean_steps, node.clean_step)
1948
self.service._worker_pool.waitall()
1951
# Make sure we go to CLEANFAIL, clear clean_steps
1952
self.assertEqual(states.CLEANFAIL, node.provision_state)
1953
self.assertEqual({}, node.clean_step)
1954
self.assertIsNotNone(node.last_error)
1955
self.assertTrue(node.maintenance)
1956
deploy_exec_mock.assert_called_once_with(mock.ANY,
1957
self.clean_steps[0])
1958
# Make sure we don't execute any other step and return
1959
self.assertFalse(power_exec_mock.called)
1961
@mock.patch('ironic.conductor.manager._get_cleaning_steps')
1962
def test_set_node_cleaning_steps(self, mock_steps):
1963
mock_steps.return_value = self.clean_steps
1965
node = obj_utils.create_test_node(
1966
self.context, driver='fake',
1967
provision_state=states.CLEANING,
1968
target_provision_state=states.AVAILABLE,
1972
with task_manager.acquire(
1973
self.context, node['id'], shared=False) as task:
1974
manager.set_node_cleaning_steps(task)
1976
self.assertEqual(self.clean_steps,
1977
task.node.driver_internal_info['clean_steps'])
1978
self.assertEqual({}, node.clean_step)
1981
@_mock_record_keepalive
1982
class MiscTestCase(_ServiceSetUpMixin, _CommonMixIn, tests_db_base.DbTestCase):
1426
1983
def test_get_driver_known(self):
1427
1984
self._start_service()
1428
1985
driver = self.service._get_driver('fake')
2986
3588
mock_swift.return_value.get_temp_url.assert_called_once_with(
2987
3589
container_name, expected_obj_name, timeout)
2988
3590
self.assertEqual(expected_instance_info, self.node.instance_info)
3593
@_mock_record_keepalive
3594
class NodeInspectHardware(_ServiceSetUpMixin,
3595
tests_db_base.DbTestCase):
3597
@mock.patch('ironic.drivers.modules.fake.FakeInspect.inspect_hardware')
3598
def test_inspect_hardware_ok(self, mock_inspect):
3599
self._start_service()
3600
node = obj_utils.create_test_node(self.context, driver='fake',
3601
provision_state=states.INSPECTING)
3602
task = task_manager.TaskManager(self.context, node.uuid)
3603
mock_inspect.return_value = states.MANAGEABLE
3604
manager._do_inspect_hardware(task)
3606
self.assertEqual(states.MANAGEABLE, node.provision_state)
3607
self.assertEqual(states.NOSTATE, node.target_provision_state)
3608
self.assertIsNone(node.last_error)
3609
mock_inspect.assert_called_once_with(mock.ANY)
3611
@mock.patch('ironic.drivers.modules.fake.FakeInspect.inspect_hardware')
3612
def test_inspect_hardware_return_inspecting(self, mock_inspect):
3613
self._start_service()
3614
node = obj_utils.create_test_node(self.context, driver='fake',
3615
provision_state=states.INSPECTING)
3616
task = task_manager.TaskManager(self.context, node.uuid)
3617
mock_inspect.return_value = states.INSPECTING
3618
manager._do_inspect_hardware(task)
3620
self.assertEqual(states.INSPECTING, node.provision_state)
3621
self.assertEqual(states.NOSTATE, node.target_provision_state)
3622
self.assertIsNone(node.last_error)
3623
mock_inspect.assert_called_once_with(mock.ANY)
3625
@mock.patch.object(manager, 'LOG')
3626
@mock.patch('ironic.drivers.modules.fake.FakeInspect.inspect_hardware')
3627
def test_inspect_hardware_return_other_state(self, mock_inspect, log_mock):
3628
self._start_service()
3629
node = obj_utils.create_test_node(self.context, driver='fake',
3630
provision_state=states.INSPECTING)
3631
task = task_manager.TaskManager(self.context, node.uuid)
3632
mock_inspect.return_value = None
3633
self.assertRaises(exception.HardwareInspectionFailure,
3634
manager._do_inspect_hardware, task)
3636
self.assertEqual(states.INSPECTFAIL, node.provision_state)
3637
self.assertEqual(states.MANAGEABLE, node.target_provision_state)
3638
self.assertIsNotNone(node.last_error)
3639
mock_inspect.assert_called_once_with(mock.ANY)
3640
self.assertTrue(log_mock.error.called)
3642
def test__check_inspect_timeouts(self):
3643
self._start_service()
3644
CONF.set_override('inspect_timeout', 1, group='conductor')
3645
node = obj_utils.create_test_node(self.context, driver='fake',
3646
provision_state=states.INSPECTING,
3647
target_provision_state=states.MANAGEABLE,
3648
provision_updated_at=datetime.datetime(2000, 1, 1, 0, 0),
3649
inspection_started_at=datetime.datetime(2000, 1, 1, 0, 0))
3651
self.service._check_inspect_timeouts(self.context)
3652
self.service._worker_pool.waitall()
3654
self.assertEqual(states.INSPECTFAIL, node.provision_state)
3655
self.assertEqual(states.MANAGEABLE, node.target_provision_state)
3656
self.assertIsNotNone(node.last_error)
3658
@mock.patch('ironic.conductor.manager.ConductorManager._spawn_worker')
3659
def test_inspect_hardware_worker_pool_full(self, mock_spawn):
3660
prv_state = states.MANAGEABLE
3661
tgt_prv_state = states.NOSTATE
3662
node = obj_utils.create_test_node(self.context,
3663
provision_state=prv_state,
3664
target_provision_state=tgt_prv_state,
3665
last_error=None, driver='fake')
3666
self._start_service()
3668
mock_spawn.side_effect = exception.NoFreeConductorWorker()
3670
exc = self.assertRaises(messaging.rpc.ExpectedException,
3671
self.service.inspect_hardware,
3672
self.context, node.uuid)
3673
# Compare true exception hidden by @messaging.expected_exceptions
3674
self.assertEqual(exception.NoFreeConductorWorker, exc.exc_info[0])
3675
self.service._worker_pool.waitall()
3677
# Make sure things were rolled back
3678
self.assertEqual(prv_state, node.provision_state)
3679
self.assertEqual(tgt_prv_state, node.target_provision_state)
3680
self.assertIsNotNone(node.last_error)
3681
# Verify reservation has been cleared.
3682
self.assertIsNone(node.reservation)
3684
def _test_inspect_hardware_validate_fail(self, mock_validate):
3685
mock_validate.side_effect = exception.InvalidParameterValue('error')
3686
node = obj_utils.create_test_node(self.context, driver='fake')
3687
exc = self.assertRaises(messaging.rpc.ExpectedException,
3688
self.service.inspect_hardware,
3689
self.context, node.uuid)
3690
# Compare true exception hidden by @messaging.expected_exceptions
3691
self.assertEqual(exception.HardwareInspectionFailure, exc.exc_info[0])
3692
# This is a sync operation last_error should be None.
3693
self.assertIsNone(node.last_error)
3694
# Verify reservation has been cleared.
3695
self.assertIsNone(node.reservation)
3697
@mock.patch('ironic.drivers.modules.fake.FakeInspect.validate')
3698
def test_inspect_hardware_validate_fail(self, mock_validate):
3699
self._test_inspect_hardware_validate_fail(mock_validate)
3701
@mock.patch('ironic.drivers.modules.fake.FakePower.validate')
3702
def test_inspect_hardware_power_validate_fail(self, mock_validate):
3703
self._test_inspect_hardware_validate_fail(mock_validate)
3705
@mock.patch('ironic.drivers.modules.fake.FakeInspect.inspect_hardware')
3706
def test_inspect_hardware_raises_error(self, mock_inspect):
3707
self._start_service()
3708
mock_inspect.side_effect = exception.HardwareInspectionFailure('test')
3709
state = states.MANAGEABLE
3710
node = obj_utils.create_test_node(self.context, driver='fake',
3711
provision_state=states.INSPECTING,
3712
target_provision_state=state)
3713
task = task_manager.TaskManager(self.context, node.uuid)
3715
self.assertRaises(exception.HardwareInspectionFailure,
3716
manager._do_inspect_hardware, task)
3718
self.assertEqual(states.INSPECTFAIL, node.provision_state)
3719
self.assertEqual(states.MANAGEABLE, node.target_provision_state)
3720
self.assertIsNotNone(node.last_error)
3721
self.assertTrue(mock_inspect.called)
3724
@mock.patch.object(task_manager, 'acquire')
3725
@mock.patch.object(manager.ConductorManager, '_mapped_to_this_conductor')
3726
@mock.patch.object(dbapi.IMPL, 'get_nodeinfo_list')
3727
class ManagerCheckInspectTimeoutsTestCase(_CommonMixIn,
3728
tests_db_base.DbTestCase):
3730
super(ManagerCheckInspectTimeoutsTestCase, self).setUp()
3731
self.config(inspect_timeout=300, group='conductor')
3732
self.service = manager.ConductorManager('hostname', 'test-topic')
3733
self.service.dbapi = self.dbapi
3735
self.node = self._create_node(provision_state=states.INSPECTING,
3736
target_provision_state=states.MANAGEABLE)
3737
self.task = self._create_task(node=self.node)
3739
self.node2 = self._create_node(provision_state=states.INSPECTING,
3740
target_provision_state=states.MANAGEABLE)
3741
self.task2 = self._create_task(node=self.node2)
3743
self.filters = {'reserved': False,
3744
'inspection_started_before': 300,
3745
'provision_state': states.INSPECTING}
3746
self.columns = ['uuid', 'driver']
3748
def _assert_get_nodeinfo_args(self, get_nodeinfo_mock):
3749
get_nodeinfo_mock.assert_called_once_with(sort_dir='asc',
3750
columns=self.columns, filters=self.filters,
3751
sort_key='inspection_started_at')
3753
def test__check_inspect_timeouts_disabled(self, get_nodeinfo_mock,
3754
mapped_mock, acquire_mock):
3755
self.config(inspect_timeout=0, group='conductor')
3757
self.service._check_inspect_timeouts(self.context)
3759
self.assertFalse(get_nodeinfo_mock.called)
3760
self.assertFalse(mapped_mock.called)
3761
self.assertFalse(acquire_mock.called)
3763
def test__check_inspect_timeouts_not_mapped(self, get_nodeinfo_mock,
3764
mapped_mock, acquire_mock):
3765
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response()
3766
mapped_mock.return_value = False
3768
self.service._check_inspect_timeouts(self.context)
3770
self._assert_get_nodeinfo_args(get_nodeinfo_mock)
3771
mapped_mock.assert_called_once_with(self.node.uuid, self.node.driver)
3772
self.assertFalse(acquire_mock.called)
3774
def test__check_inspect_timeout(self, get_nodeinfo_mock,
3775
mapped_mock, acquire_mock):
3776
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response()
3777
mapped_mock.return_value = True
3778
acquire_mock.side_effect = self._get_acquire_side_effect(self.task)
3780
self.service._check_inspect_timeouts(self.context)
3782
self._assert_get_nodeinfo_args(get_nodeinfo_mock)
3783
mapped_mock.assert_called_once_with(self.node.uuid, self.node.driver)
3784
acquire_mock.assert_called_once_with(self.context, self.node.uuid)
3785
self.task.process_event.assert_called_with('fail')
3787
def test__check_inspect_timeouts_acquire_node_disappears(self,
3791
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response()
3792
mapped_mock.return_value = True
3793
acquire_mock.side_effect = exception.NodeNotFound(node='fake')
3796
self.service._check_inspect_timeouts(self.context)
3798
self._assert_get_nodeinfo_args(get_nodeinfo_mock)
3799
mapped_mock.assert_called_once_with(
3800
self.node.uuid, self.node.driver)
3801
acquire_mock.assert_called_once_with(self.context,
3803
self.assertFalse(self.task.process_event.called)
3805
def test__check_inspect_timeouts_acquire_node_locked(self,
3809
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response()
3810
mapped_mock.return_value = True
3811
acquire_mock.side_effect = exception.NodeLocked(node='fake',
3815
self.service._check_inspect_timeouts(self.context)
3817
self._assert_get_nodeinfo_args(get_nodeinfo_mock)
3818
mapped_mock.assert_called_once_with(
3819
self.node.uuid, self.node.driver)
3820
acquire_mock.assert_called_once_with(self.context,
3822
self.assertFalse(self.task.process_event.called)
3824
def test__check_inspect_timeouts_no_acquire_after_lock(self,
3828
task = self._create_task(
3829
node_attrs=dict(provision_state=states.AVAILABLE,
3830
uuid=self.node.uuid))
3831
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response()
3832
mapped_mock.return_value = True
3833
acquire_mock.side_effect = self._get_acquire_side_effect(task)
3835
self.service._check_inspect_timeouts(self.context)
3837
self._assert_get_nodeinfo_args(get_nodeinfo_mock)
3838
mapped_mock.assert_called_once_with(
3839
self.node.uuid, self.node.driver)
3840
acquire_mock.assert_called_once_with(self.context,
3842
self.assertFalse(task.process_event.called)
3844
def test__check_inspect_timeouts_to_maintenance_after_lock(self,
3848
task = self._create_task(
3849
node_attrs=dict(provision_state=states.INSPECTING,
3850
target_provision_state=states.MANAGEABLE,
3852
uuid=self.node.uuid))
3853
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response(
3854
[task.node, self.node2])
3855
mapped_mock.return_value = True
3856
acquire_mock.side_effect = self._get_acquire_side_effect(
3859
self.service._check_inspect_timeouts(self.context)
3861
self._assert_get_nodeinfo_args(get_nodeinfo_mock)
3862
self.assertEqual([mock.call(self.node.uuid, task.node.driver),
3863
mock.call(self.node2.uuid, self.node2.driver)],
3864
mapped_mock.call_args_list)
3865
self.assertEqual([mock.call(self.context, self.node.uuid),
3866
mock.call(self.context, self.node2.uuid)],
3867
acquire_mock.call_args_list)
3868
# First node skipped
3869
self.assertFalse(task.process_event.called)
3870
# Second node spawned
3871
self.task2.process_event.assert_called_with('fail')
3873
def test__check_inspect_timeouts_exiting_no_worker_avail(self,
3877
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response(
3878
[self.node, self.node2])
3879
mapped_mock.return_value = True
3880
acquire_mock.side_effect = self._get_acquire_side_effect(
3881
[(self.task, exception.NoFreeConductorWorker()), self.task2])
3883
# Exception should be nuked
3884
self.service._check_inspect_timeouts(self.context)
3886
self._assert_get_nodeinfo_args(get_nodeinfo_mock)
3887
# mapped should be only called for the first node as we should
3888
# have exited the loop early due to NoFreeConductorWorker
3889
mapped_mock.assert_called_once_with(
3890
self.node.uuid, self.node.driver)
3891
acquire_mock.assert_called_once_with(self.context,
3893
self.task.process_event.assert_called_with('fail')
3895
def test__check_inspect_timeouts_exit_with_other_exception(self,
3899
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response(
3900
[self.node, self.node2])
3901
mapped_mock.return_value = True
3902
acquire_mock.side_effect = self._get_acquire_side_effect(
3903
[(self.task, exception.IronicException('foo')), self.task2])
3906
self.assertRaises(exception.IronicException,
3907
self.service._check_inspect_timeouts,
3910
self._assert_get_nodeinfo_args(get_nodeinfo_mock)
3911
# mapped should be only called for the first node as we should
3912
# have exited the loop early due to unknown exception
3913
mapped_mock.assert_called_once_with(
3914
self.node.uuid, self.node.driver)
3915
acquire_mock.assert_called_once_with(self.context,
3917
self.task.process_event.assert_called_with('fail')
3919
def test__check_inspect_timeouts_worker_limit(self, get_nodeinfo_mock,
3920
mapped_mock, acquire_mock):
3921
self.config(periodic_max_workers=2, group='conductor')
3923
# Use the same nodes/tasks to make life easier in the tests
3926
get_nodeinfo_mock.return_value = self._get_nodeinfo_list_response(
3928
mapped_mock.return_value = True
3929
acquire_mock.side_effect = self._get_acquire_side_effect(
3932
self.service._check_inspect_timeouts(self.context)
3934
# Should only have ran 2.
3935
self.assertEqual([mock.call(self.node.uuid, self.node.driver)] * 2,
3936
mapped_mock.call_args_list)
3937
self.assertEqual([mock.call(self.context, self.node.uuid)] * 2,
3938
acquire_mock.call_args_list)
3939
process_event_call = mock.call('fail')
3940
self.assertEqual([process_event_call] * 2,
3941
self.task.process_event.call_args_list)
3944
@_mock_record_keepalive
3945
class DestroyPortTestCase(_ServiceSetUpMixin, tests_db_base.DbTestCase):
3946
def test_destroy_port(self):
3947
node = obj_utils.create_test_node(self.context, driver='fake')
3949
port = obj_utils.create_test_port(self.context,
3951
self.service.destroy_port(self.context, port)
3952
self.assertRaises(exception.PortNotFound, port.refresh)
3954
def test_destroy_port_node_locked(self):
3955
node = obj_utils.create_test_node(self.context, driver='fake',
3956
reservation='fake-reserv')
3958
port = obj_utils.create_test_port(self.context, node_id=node.id)
3959
exc = self.assertRaises(messaging.rpc.ExpectedException,
3960
self.service.destroy_port,
3962
# Compare true exception hidden by @messaging.expected_exceptions
3963
self.assertEqual(exception.NodeLocked, exc.exc_info[0])