33
34
from ironic.common import utils
34
35
from ironic.conductor import task_manager
35
36
from ironic.conductor import utils as manager_utils
36
from ironic.db import api as dbapi
37
37
from ironic.drivers.modules import deploy_utils
38
38
from ironic.drivers.modules import iscsi_deploy
39
39
from ironic.drivers.modules import pxe
40
40
from ironic.openstack.common import fileutils
41
from ironic.openstack.common import jsonutils as json
42
41
from ironic.tests.conductor import utils as mgr_utils
43
42
from ironic.tests.db import base as db_base
44
43
from ironic.tests.db import utils as db_utils
151
145
self.assertEqual('instance_ramdisk_uuid',
152
146
self.node.instance_info.get('ramdisk'))
154
@mock.patch.object(utils, 'random_alnum')
148
@mock.patch.object(iscsi_deploy, 'build_deploy_ramdisk_options')
155
149
@mock.patch.object(pxe_utils, '_build_pxe_config')
156
def _test_build_pxe_config_options(self, build_pxe_mock, random_alnum_mock,
150
def _test_build_pxe_config_options(self, build_pxe_mock, deploy_opts_mock,
157
151
ipxe_enabled=False):
158
152
self.config(pxe_append_params='test_param', group='pxe')
159
153
# NOTE: right '/' should be removed from url string
160
154
self.config(api_url='http://192.168.122.184:6385/', group='conductor')
161
155
self.config(disk_devices='sda', group='pxe')
163
fake_key = '0123456789ABCDEFGHIJKLMNOPQRSTUV'
164
random_alnum_mock.return_value = fake_key
157
fake_deploy_opts = {'iscsi_target_iqn': 'fake-iqn',
158
'deployment_id': 'fake-deploy-id',
159
'deployment_key': 'fake-deploy-key',
161
'ironic_api_url': 'fake-api-url'}
163
deploy_opts_mock.return_value = fake_deploy_opts
165
165
tftp_server = CONF.pxe.tftp_server
188
188
root_dir = CONF.pxe.tftp_root
190
190
expected_options = {
191
'deployment_key': '0123456789ABCDEFGHIJKLMNOPQRSTUV',
192
191
'ari_path': ramdisk,
193
'iscsi_target_iqn': u'iqn-1be26c0b-03f2-4d2e-ae87-c02d7f33'
195
192
'deployment_ari_path': deploy_ramdisk,
196
193
'pxe_append_params': 'test_param',
197
194
'aki_path': kernel,
198
'deployment_id': u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
199
'ironic_api_url': 'http://192.168.122.184:6385',
200
195
'deployment_aki_path': deploy_kernel,
202
196
'tftp_server': tftp_server
199
expected_options.update(fake_deploy_opts)
205
201
image_info = {'deploy_kernel': ('deploy_kernel',
206
202
os.path.join(root_dir,
225
221
self.assertEqual(expected_options, options)
227
random_alnum_mock.assert_called_once_with(32)
229
# test that deploy_key saved
230
db_node = self.dbapi.get_node_by_uuid(self.node.uuid)
231
db_key = db_node.instance_info.get('deploy_key')
232
self.assertEqual(fake_key, db_key)
234
223
def test__build_pxe_config_options(self):
235
224
self._test_build_pxe_config_options(ipxe_enabled=False)
272
262
pxe._cache_ramdisk_kernel(self.context, self.node, fake_pxe_info)
273
263
mock_ensure_tree.assert_called_with(expected_path)
274
264
mock_fetch_image.assert_called_once_with(self.context, mock.ANY,
275
fake_pxe_info.values())
265
fake_pxe_info.values(), True)
277
267
@mock.patch.object(pxe, 'TFTPImageCache', lambda: None)
278
268
@mock.patch.object(fileutils, 'ensure_tree')
366
356
def test_validate_fail_no_port(self):
367
357
new_node = obj_utils.create_test_node(
369
id=321, uuid='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',
359
uuid='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',
370
360
driver='fake_pxe', instance_info=INST_INFO_DICT,
371
361
driver_info=DRV_INFO_DICT)
372
362
with task_manager.acquire(self.context, new_node.uuid,
373
363
shared=True) as task:
374
self.assertRaises(exception.InvalidParameterValue,
364
self.assertRaises(exception.MissingParameterValue,
375
365
task.driver.deploy.validate, task)
377
367
@mock.patch.object(base_image_service.BaseImageService, '_show')
406
396
@mock.patch.object(keystone, 'get_service_url')
407
397
def test_validate_fail_no_api_url(self, mock_ks):
408
398
# not present in the keystone catalog
409
mock_ks.side_effect = exception.CatalogFailure
399
mock_ks.side_effect = exception.KeystoneFailure
410
400
# not present in the config file
411
401
self.config(group='conductor', api_url=None)
497
488
@mock.patch.object(manager_utils, 'node_set_boot_device')
498
489
def test_deploy(self, mock_node_set_boot, mock_node_power_action,
499
490
mock_update_dhcp, mock_cache_instance_image,
500
mock_get_image_file_path, mock_get_image_mb):
491
mock_get_image_file_path, mock_get_image_mb, mock_expire):
501
492
fake_img_path = '/test/path/test.img'
502
493
mock_get_image_file_path.return_value = fake_img_path
503
494
mock_get_image_mb.return_value = 1
495
mock_expire.return_value = False
496
self.config(deploy_callback_timeout=600, group='conductor')
505
498
with task_manager.acquire(self.context,
506
499
self.node.uuid, shared=False) as task:
512
505
mock_get_image_file_path.assert_called_once_with(task.node.uuid)
513
506
mock_get_image_mb.assert_called_once_with(fake_img_path)
514
507
mock_update_dhcp.assert_called_once_with(task, dhcp_opts)
508
mock_expire.assert_called_once_with(self.context.auth_token, 600)
515
509
mock_node_set_boot.assert_called_once_with(task, 'pxe',
517
511
mock_node_power_action.assert_called_once_with(task, states.REBOOT)
521
515
token = open(t_path, 'r').read()
522
516
self.assertEqual(self.context.auth_token, token)
518
@mock.patch.object(keystone, 'get_admin_auth_token')
519
@mock.patch.object(keystone, 'token_expires_soon')
520
@mock.patch.object(deploy_utils, 'get_image_mb')
521
@mock.patch.object(iscsi_deploy, '_get_image_file_path')
522
@mock.patch.object(iscsi_deploy, 'cache_instance_image')
523
@mock.patch.object(dhcp_factory.DHCPFactory, 'update_dhcp')
524
@mock.patch.object(manager_utils, 'node_power_action')
525
@mock.patch.object(manager_utils, 'node_set_boot_device')
526
def test_deploy_token_near_expiration(self, mock_node_set_boot,
527
mock_node_power_action, mock_update_dhcp,
528
mock_cache_instance_image, mock_get_image_file_path,
529
mock_get_image_mb, mock_expire, mock_admin_token):
530
mock_get_image_mb.return_value = 1
531
mock_expire.return_value = True
532
new_token = 'new_admin_token'
533
mock_admin_token.return_value = new_token
534
self.config(deploy_callback_timeout=600, group='conductor')
536
with task_manager.acquire(self.context,
537
self.node.uuid, shared=False) as task:
538
task.driver.deploy.deploy(task)
540
mock_expire.assert_called_once_with(self.context.auth_token, 600)
541
mock_admin_token.assert_called_once_with()
542
# ensure token file created with new token
543
t_path = pxe._get_token_file_path(self.node.uuid)
544
token = open(t_path, 'r').read()
545
self.assertEqual(new_token, token)
524
547
@mock.patch.object(deploy_utils, 'get_image_mb')
525
548
@mock.patch.object(iscsi_deploy, '_get_image_file_path')
526
549
@mock.patch.object(iscsi_deploy, 'cache_instance_image')
580
603
with task_manager.acquire(self.context, self.node.uuid) as task:
581
task.driver.vendor.vendor_passthru(
582
task, method='pass_deploy_info', address='123456',
583
iqn='aaa-bbb', key='fake-56789')
604
task.driver.vendor._continue_deploy(
605
task, address='123456', iqn='aaa-bbb', key='fake-56789')
584
607
self.node.refresh()
585
608
self.assertEqual(states.ACTIVE, self.node.provision_state)
586
609
self.assertEqual(states.POWER_ON, self.node.power_state)
610
633
with task_manager.acquire(self.context, self.node.uuid) as task:
611
task.driver.vendor.vendor_passthru(
612
task, method='pass_deploy_info', address='123456',
613
iqn='aaa-bbb', key='fake-56789')
634
task.driver.vendor._continue_deploy(
635
task, address='123456', iqn='aaa-bbb', key='fake-56789')
614
637
self.node.refresh()
615
638
self.assertEqual(states.DEPLOYFAIL, self.node.provision_state)
616
639
self.assertEqual(states.POWER_OFF, self.node.power_state)
636
659
with task_manager.acquire(self.context, self.node.uuid) as task:
637
task.driver.vendor.vendor_passthru(
638
task, method='pass_deploy_info', address='123456',
639
iqn='aaa-bbb', key='fake-56789',
640
error='test ramdisk error')
660
task.driver.vendor._continue_deploy(
661
task, address='123456', iqn='aaa-bbb',
662
key='fake-56789', error='test ramdisk error')
641
664
self.node.refresh()
642
665
self.assertEqual(states.DEPLOYFAIL, self.node.provision_state)
643
666
self.assertEqual(states.POWER_OFF, self.node.power_state)
649
672
def test_continue_deploy_invalid(self):
650
673
self.node.power_state = states.POWER_ON
651
self.node.provision_state = 'FAKE'
674
self.node.provision_state = states.NOSTATE
654
677
with task_manager.acquire(self.context, self.node.uuid) as task:
655
task.driver.vendor.vendor_passthru(
656
task, method='pass_deploy_info', address='123456',
657
iqn='aaa-bbb', key='fake-56789',
658
error='test ramdisk error')
678
task.driver.vendor._continue_deploy(
679
task, address='123456', iqn='aaa-bbb',
680
key='fake-56789', error='test ramdisk error')
659
682
self.node.refresh()
660
self.assertEqual('FAKE', self.node.provision_state)
683
self.assertEqual(states.NOSTATE, self.node.provision_state)
661
684
self.assertEqual(states.POWER_ON, self.node.power_state)
663
686
def test_lock_elevated(self):
664
687
with task_manager.acquire(self.context, self.node.uuid) as task:
665
with mock.patch.object(task.driver.vendor, '_continue_deploy') \
666
as _continue_deploy_mock:
667
task.driver.vendor.vendor_passthru(task,
668
method='pass_deploy_info', address='123456', iqn='aaa-bbb',
688
with mock.patch.object(task.driver.vendor,
689
'_continue_deploy') as _cont_deploy_mock:
690
task.driver.vendor._continue_deploy(
691
task, address='123456', iqn='aaa-bbb', key='fake-56789')
670
693
# lock elevated w/o exception
671
self.assertEqual(1, _continue_deploy_mock.call_count,
694
self.assertEqual(1, _cont_deploy_mock.call_count,
672
695
"_continue_deploy was not called once.")
697
def test_vendor_routes(self):
698
expected = ['pass_deploy_info']
699
with task_manager.acquire(self.context, self.node.uuid,
700
shared=True) as task:
701
vendor_routes = task.driver.vendor.vendor_routes
702
self.assertIsInstance(vendor_routes, dict)
703
self.assertEqual(expected, list(vendor_routes))
705
def test_driver_routes(self):
706
with task_manager.acquire(self.context, self.node.uuid,
707
shared=True) as task:
708
driver_routes = task.driver.vendor.driver_routes
709
self.assertIsInstance(driver_routes, dict)
710
self.assertEqual({}, driver_routes)
675
713
@mock.patch.object(utils, 'unlink_without_raise')
676
714
@mock.patch.object(iscsi_deploy, 'destroy_images')