diff --git a/ironic_staging_drivers/ansible/deploy.py b/ironic_staging_drivers/ansible/deploy.py index f1a2a4f..fc09b39 100644 --- a/ironic_staging_drivers/ansible/deploy.py +++ b/ironic_staging_drivers/ansible/deploy.py @@ -23,8 +23,6 @@ from ironic_lib import utils as irlib_utils from oslo_concurrency import processutils from oslo_config import cfg from oslo_log import log -from oslo_utils import excutils -from oslo_utils import strutils from oslo_utils import units import retrying import six @@ -33,12 +31,10 @@ import yaml from ironic.common import dhcp_factory from ironic.common import exception -from ironic.common.glance_service import service_utils from ironic.common.i18n import _ from ironic.common.i18n import _LE from ironic.common.i18n import _LI from ironic.common.i18n import _LW -from ironic.common import image_service from ironic.common import images from ironic.common import states from ironic.common import utils @@ -137,8 +133,6 @@ OPTIONAL_PROPERTIES = { } COMMON_PROPERTIES = OPTIONAL_PROPERTIES -DISK_LAYOUT_PARAMS = ('root_gb', 'swap_mb', 'ephemeral_gb') - INVENTORY_FILE = os.path.join(CONF.ansible.playbooks_path, 'inventory') @@ -160,37 +154,6 @@ def _get_configdrive_path(basename): return os.path.join(CONF.tempdir, basename + '.cndrive') -# NOTE(yuriyz): this is a copy from agent driver -def build_instance_info_for_deploy(task): - """Build instance_info necessary for deploying to a node.""" - node = task.node - instance_info = node.instance_info - - image_source = instance_info['image_source'] - if service_utils.is_glance_image(image_source): - glance = image_service.GlanceImageService(version=2, - context=task.context) - image_info = glance.show(image_source) - swift_temp_url = glance.swift_temp_url(image_info) - LOG.debug('Got image info: %(info)s for node %(node)s.', - {'info': image_info, 'node': node.uuid}) - instance_info['image_url'] = swift_temp_url - instance_info['image_checksum'] = image_info['checksum'] - instance_info['image_disk_format'] = image_info['disk_format'] - else: - try: - image_service.HttpImageService().validate_href(image_source) - except exception.ImageRefValidationFailed: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Ansible deploy supports only HTTP(S) URLs as " - "instance_info['image_source']. Either %s " - "is not a valid HTTP(S) URL or " - "is not reachable."), image_source) - instance_info['image_url'] = image_source - - return instance_info - - def _get_node_ip(task): api = dhcp_factory.DHCPFactory().provider ip_addrs = api.get_ip_addresses(task) @@ -292,60 +255,32 @@ def _parse_partitioning_info(node): info = node.instance_info i_info = {} - i_info['root_gb'] = info.get('root_gb') - error_msg = _("'root_gb' is missing in node's instance_info") - deploy_utils.check_for_missing_params(i_info, error_msg) - - i_info['swap_mb'] = info.get('swap_mb', 0) - i_info['ephemeral_gb'] = info.get('ephemeral_gb', 0) - err_msg_invalid = _("Cannot validate parameter for deploy. Invalid " - "parameter %(param)s. Reason: %(reason)s") - - for param in DISK_LAYOUT_PARAMS: - try: - i_info[param] = int(i_info[param]) - except ValueError: - reason = _("%s is not an integer value") % i_info[param] - raise exception.InvalidParameterValue(err_msg_invalid % - {'param': param, - 'reason': reason}) - # convert to sizes expected by 'parted' Ansible module - root_mib = 1024 * i_info.pop('root_gb') - swap_mib = i_info.pop('swap_mb') - ephemeral_mib = 1024 * i_info.pop('ephemeral_gb') - partitions = [] root_partition = {'name': 'root', - 'size_mib': root_mib, + 'size_mib': info['root_mb'], 'boot': 'yes', 'swap': 'no'} partitions.append(root_partition) - if swap_mib: + swap_mb = info['swap_mb'] + if swap_mb: swap_partition = {'name': 'swap', - 'size_mib': swap_mib, + 'size_mib': swap_mb, 'boot': 'no', 'swap': 'yes'} partitions.append(swap_partition) - if ephemeral_mib: + ephemeral_mb = info['ephemeral_mb'] + if ephemeral_mb: ephemeral_partition = {'name': 'ephemeral', - 'size_mib': ephemeral_mib, + 'size_mib': ephemeral_mb, 'boot': 'no', 'swap': 'no'} partitions.append(ephemeral_partition) - i_info['ephemeral_format'] = info.get('ephemeral_format') - if not i_info['ephemeral_format']: - i_info['ephemeral_format'] = CONF.pxe.default_ephemeral_format - preserve_ephemeral = info.get('preserve_ephemeral', False) - try: - i_info['preserve_ephemeral'] = ( - strutils.bool_from_string(preserve_ephemeral, strict=True)) - except ValueError as e: - raise exception.InvalidParameterValue( - err_msg_invalid % {'param': 'preserve_ephemeral', 'reason': e}) + + i_info['ephemeral_format'] = info['ephemeral_format'] i_info['preserve_ephemeral'] = ( - 'yes' if i_info['preserve_ephemeral'] else 'no') + 'yes' if info['preserve_ephemeral'] else 'no') i_info['ironic_partitions'] = partitions return i_info @@ -550,7 +485,8 @@ class AnsibleDeploy(base.DeployInterface): manager_utils.node_power_action(task, states.POWER_OFF) task.driver.network.add_provisioning_network(task) if node.provision_state not in [states.ACTIVE, states.ADOPTING]: - node.instance_info = build_instance_info_for_deploy(task) + node.instance_info = deploy_utils.build_instance_info_for_deploy( + task) node.save() boot_opt = deploy_utils.build_agent_options(node) task.driver.boot.prepare_ramdisk(task, boot_opt) diff --git a/ironic_staging_drivers/tests/unit/ansible/test_deploy.py b/ironic_staging_drivers/tests/unit/ansible/test_deploy.py index 67f95a0..c6f774a 100644 --- a/ironic_staging_drivers/tests/unit/ansible/test_deploy.py +++ b/ironic_staging_drivers/tests/unit/ansible/test_deploy.py @@ -15,7 +15,6 @@ import os from ironic.common import dhcp_factory from ironic.common import exception -from ironic.common import image_service from ironic.common import states from ironic.common import utils as com_utils from ironic.conductor import task_manager @@ -40,7 +39,9 @@ INSTANCE_INFO = { 'image_url': 'http://image', 'image_checksum': 'checksum', 'image_disk_format': 'qcow2', - 'root_gb': 5, + 'root_mb': 5120, + 'swap_mb': 0, + 'ephemeral_mb': 0 } DRIVER_INFO = { @@ -80,69 +81,6 @@ class TestAnsibleMethods(db_base.DbTestCase): ansible_deploy._parse_ansible_driver_info, self.node, 'test') - @mock.patch.object(image_service, 'GlanceImageService', autospec=True) - def test_build_instance_info_for_deploy_glance_image(self, glance_mock): - i_info = self.node.instance_info - i_info['image_source'] = '733d1c44-a2ea-414b-aca7-69decf20d810' - self.node.instance_info = i_info - self.node.save() - - image_info = {'checksum': 'aa', 'disk_format': 'qcow2'} - glance_mock.return_value.show = mock.Mock(spec_set=[], - return_value=image_info) - - with task_manager.acquire( - self.context, self.node.uuid) as task: - - ansible_deploy.build_instance_info_for_deploy(task) - - glance_mock.assert_called_once_with(version=2, - context=task.context) - glance_mock.return_value.show.assert_called_once_with( - self.node.instance_info['image_source']) - glance_mock.return_value.swift_temp_url.assert_called_once_with( - image_info) - - @mock.patch.object(image_service.HttpImageService, 'validate_href', - autospec=True) - def test_build_instance_info_for_deploy_nonglance_image( - self, validate_href_mock): - i_info = self.node.instance_info - driver_internal_info = self.node.driver_internal_info - i_info['image_source'] = 'http://image-ref' - i_info['image_checksum'] = 'aa' - i_info['root_gb'] = 10 - driver_internal_info['is_whole_disk_image'] = True - self.node.instance_info = i_info - self.node.driver_internal_info = driver_internal_info - self.node.save() - - with task_manager.acquire(self.context, self.node.uuid) as task: - info = ansible_deploy.build_instance_info_for_deploy(task) - - self.assertEqual(self.node.instance_info['image_source'], - info['image_url']) - validate_href_mock.assert_called_once_with( - mock.ANY, 'http://image-ref') - - @mock.patch.object(image_service.HttpImageService, 'validate_href', - autospec=True) - def test_build_instance_info_for_deploy_nonsupported_image( - self, validate_href_mock): - validate_href_mock.side_effect = iter( - [exception.ImageRefValidationFailed( - image_href='file://img.qcow2', reason='fail')]) - i_info = self.node.instance_info - i_info['image_source'] = 'file://img.qcow2' - i_info['image_checksum'] = 'aa' - self.node.instance_info = i_info - self.node.save() - - with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.ImageRefValidationFailed, - ansible_deploy.build_instance_info_for_deploy, task) - def test__get_node_ip(self): dhcp_provider_mock = mock.Mock() dhcp_factory.DHCPFactory._dhcp_provider = dhcp_provider_mock @@ -233,24 +171,18 @@ class TestAnsibleMethods(db_base.DbTestCase): ansible_deploy.INVENTORY_FILE, '-e', json.dumps(extra_vars), '--tags=wait', '--private-key=/path/to/key', '-vvvv') - @mock.patch.object(deploy_utils, 'check_for_missing_params', - autospec=True) - def test__parse_partitioning_info(self, check_missing_param_mock): + def test__parse_partitioning_info(self): expected_info = { 'ironic_partitions': [{'boot': 'yes', 'swap': 'no', - 'size_mib': 1024 * INSTANCE_INFO['root_gb'], + 'size_mib': INSTANCE_INFO['root_mb'], 'name': 'root'}]} i_info = ansible_deploy._parse_partitioning_info(self.node) - check_missing_param_mock.assert_called_once_with( - expected_info, mock.ANY) self.assertEqual(expected_info, i_info) - @mock.patch.object(deploy_utils, 'check_for_missing_params', - autospec=True) - def test__parse_partitioning_info_swap(self, check_missing_param_mock): + def test__parse_partitioning_info_swap(self): in_info = dict(INSTANCE_INFO) in_info['swap_mb'] = 128 self.node.instance_info = in_info @@ -259,29 +191,37 @@ class TestAnsibleMethods(db_base.DbTestCase): expected_info = { 'ironic_partitions': [{'boot': 'yes', 'swap': 'no', - 'size_mib': 1024 * INSTANCE_INFO['root_gb'], + 'size_mib': INSTANCE_INFO['root_mb'], 'name': 'root'}, {'boot': 'no', 'swap': 'yes', 'size_mib': 128, 'name': 'swap'}]} i_info = ansible_deploy._parse_partitioning_info(self.node) - check_missing_param_mock.assert_called_once_with( - expected_info, mock.ANY) self.assertEqual(expected_info, i_info) - @mock.patch.object(deploy_utils, 'check_for_missing_params', - autospec=True) - def test__parse_partitioning_info_invalid_param(self, - check_missing_param_mock): + def test__parse_partitioning_info_ephemeral(self): in_info = dict(INSTANCE_INFO) - in_info['root_gb'] = 'five' + in_info['ephemeral_mb'] = 128 + in_info['ephemeral_format'] = 'ext4' + in_info['preserve_ephemeral'] = True self.node.instance_info = in_info self.node.save() - self.assertRaises(exception.InvalidParameterValue, - ansible_deploy._parse_partitioning_info, - self.node) + expected_info = { + 'ironic_partitions': + [{'boot': 'yes', 'swap': 'no', + 'size_mib': INSTANCE_INFO['root_mb'], + 'name': 'root'}, + {'boot': 'no', 'swap': 'no', + 'size_mib': 128, 'name': 'ephemeral'}], + 'ephemeral_format': 'ext4', + 'preserve_ephemeral': 'yes' + } + + i_info = ansible_deploy._parse_partitioning_info(self.node) + + self.assertEqual(expected_info, i_info) @mock.patch.object(pxe.PXEBoot, 'clean_up_ramdisk') @mock.patch.object(ansible_deploy, '_reboot_and_finish_deploy', @@ -467,8 +407,9 @@ class TestAnsibleDeploy(db_base.DbTestCase): @mock.patch('ironic.drivers.modules.deploy_utils.build_agent_options', return_value={'op1': 'test1'}, autospec=True) - @mock.patch.object(ansible_deploy, 'build_instance_info_for_deploy', - return_value={'test': 'test'}, autospec=True) + @mock.patch('ironic.drivers.modules.deploy_utils.' + 'build_instance_info_for_deploy', + return_value={'test': 'test'}, autospec=True) @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk') def test_prepare(self, pxe_prepare_ramdisk_mock, build_instance_info_mock, build_options_mock): diff --git a/releasenotes/notes/ansible-new-ironic-12e74f80cd72dbe3.yaml b/releasenotes/notes/ansible-new-ironic-12e74f80cd72dbe3.yaml index 09e9e68..a6d92be 100644 --- a/releasenotes/notes/ansible-new-ironic-12e74f80cd72dbe3.yaml +++ b/releasenotes/notes/ansible-new-ironic-12e74f80cd72dbe3.yaml @@ -1,3 +1,3 @@ --- upgrade: - - Ansible-deploy driver requires ironic of Newton release or newer + - Ansible-deploy driver requires ironic of version >= 7.0.0 (Ocata release).