~ubuntu-branches/ubuntu/vivid/ironic/vivid-updates

« back to all changes in this revision

Viewing changes to ironic/tests/drivers/test_pxe.py

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2015-01-05 12:21:37 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20150105122137-171bqrdpcxqipunk
Tags: 2015.1~b1-0ubuntu1
* New upstream beta release:
  - d/control: Align version requirements with upstream release.
* d/watch: Update uversionmangle to deal with kilo beta versioning
  changes.
* d/control: Bumped Standards-Version to 3.9.6, no changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
"""Test class for PXE driver."""
19
19
 
 
20
import os
 
21
import tempfile
 
22
 
20
23
import fixtures
21
24
import mock
22
 
import os
23
 
import tempfile
24
 
 
25
25
from oslo.config import cfg
 
26
from oslo.serialization import jsonutils as json
26
27
 
27
28
from ironic.common import dhcp_factory
28
29
from ironic.common import exception
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
52
51
 
53
52
class PXEValidateParametersTestCase(db_base.DbTestCase):
54
53
 
55
 
    def setUp(self):
56
 
        super(PXEValidateParametersTestCase, self).setUp()
57
 
        self.dbapi = dbapi.get_instance()
58
 
 
59
54
    def test__parse_deploy_info(self):
60
55
        # make sure we get back the expected things
61
56
        node = obj_utils.create_test_node(self.context,
107
102
              'driver_info': DRV_INFO_DICT,
108
103
        }
109
104
        mgr_utils.mock_the_extension_manager(driver="fake_pxe")
110
 
        self.dbapi = dbapi.get_instance()
111
105
        self.node = obj_utils.create_test_node(self.context, **n)
112
106
 
113
107
    @mock.patch.object(base_image_service.BaseImageService, '_show')
126
120
                                       self.node.uuid,
127
121
                                       'kernel')),
128
122
                         'deploy_ramdisk':
129
 
                         ('deploy_ramdisk_uuid',
 
123
                         (DRV_INFO_DICT['pxe_deploy_ramdisk'],
130
124
                           os.path.join(CONF.pxe.tftp_root,
131
125
                                        self.node.uuid,
132
126
                                        'deploy_ramdisk')),
133
127
                         'deploy_kernel':
134
 
                         ('deploy_kernel_uuid',
 
128
                         (DRV_INFO_DICT['pxe_deploy_kernel'],
135
129
                          os.path.join(CONF.pxe.tftp_root,
136
130
                                       self.node.uuid,
137
131
                                       'deploy_kernel'))}
151
145
        self.assertEqual('instance_ramdisk_uuid',
152
146
                         self.node.instance_info.get('ramdisk'))
153
147
 
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')
162
156
 
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',
 
160
                            'disk': 'fake-disk',
 
161
                            'ironic_api_url': 'fake-api-url'}
 
162
 
 
163
        deploy_opts_mock.return_value = fake_deploy_opts
 
164
 
165
165
        tftp_server = CONF.pxe.tftp_server
166
166
 
167
167
        if ipxe_enabled:
188
188
            root_dir = CONF.pxe.tftp_root
189
189
 
190
190
        expected_options = {
191
 
            'deployment_key': '0123456789ABCDEFGHIJKLMNOPQRSTUV',
192
191
            'ari_path': ramdisk,
193
 
            'iscsi_target_iqn': u'iqn-1be26c0b-03f2-4d2e-ae87-c02d7f33'
194
 
                                    u'c123',
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,
201
 
            'disk': 'sda',
202
196
            'tftp_server': tftp_server
203
197
        }
204
198
 
 
199
        expected_options.update(fake_deploy_opts)
 
200
 
205
201
        image_info = {'deploy_kernel': ('deploy_kernel',
206
202
                                        os.path.join(root_dir,
207
203
                                                     self.node.uuid,
224
220
                                                self.context)
225
221
        self.assertEqual(expected_options, options)
226
222
 
227
 
        random_alnum_mock.assert_called_once_with(32)
228
 
 
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)
233
 
 
234
223
    def test__build_pxe_config_options(self):
235
224
        self._test_build_pxe_config_options(ipxe_enabled=False)
236
225
 
259
248
        mock_fetch_image.assert_called_once_with(None,
260
249
                                                 mock.ANY,
261
250
                                                 [('deploy_kernel',
262
 
                                                   image_path)])
 
251
                                                   image_path)],
 
252
                                                 True)
263
253
 
264
254
    @mock.patch.object(pxe, 'TFTPImageCache', lambda: None)
265
255
    @mock.patch.object(fileutils, 'ensure_tree')
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)
276
266
 
277
267
    @mock.patch.object(pxe, 'TFTPImageCache', lambda: None)
278
268
    @mock.patch.object(fileutils, 'ensure_tree')
286
276
        pxe._cache_ramdisk_kernel(self.context, self.node, fake_pxe_info)
287
277
        mock_ensure_tree.assert_called_with(expected_path)
288
278
        mock_fetch_image.assert_called_once_with(self.context, mock.ANY,
289
 
                                                 fake_pxe_info.values())
 
279
                                                 fake_pxe_info.values(),
 
280
                                                 True)
290
281
 
291
282
 
292
283
class PXEDriverTestCase(db_base.DbTestCase):
305
296
                                               driver='fake_pxe',
306
297
                                               instance_info=instance_info,
307
298
                                               driver_info=DRV_INFO_DICT)
308
 
        self.dbapi = dbapi.get_instance()
309
299
        self.port = obj_utils.create_test_port(self.context,
310
300
                                               node_id=self.node.id)
311
301
        self.config(group='conductor', api_url='http://127.0.0.1:1234/')
366
356
    def test_validate_fail_no_port(self):
367
357
        new_node = obj_utils.create_test_node(
368
358
                self.context,
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)
376
366
 
377
367
    @mock.patch.object(base_image_service.BaseImageService, '_show')
381
371
        mock_glance.return_value = {'properties': {'kernel_id': 'fake-kernel',
382
372
                                                   'ramdisk_id': 'fake-initr'}}
383
373
        # not present in the keystone catalog
384
 
        mock_ks.side_effect = exception.CatalogFailure
 
374
        mock_ks.side_effect = exception.KeystoneFailure
385
375
 
386
376
        with task_manager.acquire(self.context, self.node.uuid,
387
377
                                  shared=True) as task:
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)
412
402
 
489
479
            mock_cache_r_k.assert_called_once_with(self.context,
490
480
                                                   task.node, None)
491
481
 
 
482
    @mock.patch.object(keystone, 'token_expires_soon')
492
483
    @mock.patch.object(deploy_utils, 'get_image_mb')
493
484
    @mock.patch.object(iscsi_deploy, '_get_image_file_path')
494
485
    @mock.patch.object(iscsi_deploy, 'cache_instance_image')
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')
504
497
 
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',
516
510
                                                       persistent=True)
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)
523
517
 
 
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')
 
535
 
 
536
        with task_manager.acquire(self.context,
 
537
                                  self.node.uuid, shared=False) as task:
 
538
            task.driver.deploy.deploy(task)
 
539
 
 
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)
 
546
 
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')
578
601
                fake_deploy))
579
602
 
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')
 
606
 
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)
608
631
                fake_deploy))
609
632
 
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')
 
636
 
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)
634
657
                fake_deploy))
635
658
 
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')
 
663
 
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)
648
671
 
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
652
675
        self.node.save()
653
676
 
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')
 
681
 
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)
662
685
 
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',
669
 
                    key='fake-56789')
 
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')
 
692
 
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.")
673
696
 
 
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))
 
704
 
 
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)
 
711
 
674
712
 
675
713
@mock.patch.object(utils, 'unlink_without_raise')
676
714
@mock.patch.object(iscsi_deploy, 'destroy_images')
732
770
                                               driver='fake_pxe',
733
771
                                               instance_info=instance_info,
734
772
                                               driver_info=DRV_INFO_DICT)
735
 
        self.dbapi = dbapi.get_instance()
736
773
        self.port = obj_utils.create_test_port(self.context,
737
774
                                               node_id=self.node.id)
738
775