diff --git a/devstack/lib/ironic b/devstack/lib/ironic index a54c5f9255..5daae4327e 100644 --- a/devstack/lib/ironic +++ b/devstack/lib/ironic @@ -194,7 +194,7 @@ IRONIC_DRIVER_INTERFACE_TYPES="bios boot power management deploy console inspect IRONIC_ENABLED_BIOS_INTERFACES=${IRONIC_ENABLED_BIOS_INTERFACES:-"fake,no-bios"} IRONIC_ENABLED_BOOT_INTERFACES=${IRONIC_ENABLED_BOOT_INTERFACES:-"fake,ipxe"} IRONIC_ENABLED_CONSOLE_INTERFACES=${IRONIC_ENABLED_CONSOLE_INTERFACES:-"fake,no-console"} -IRONIC_ENABLED_DEPLOY_INTERFACES=${IRONIC_ENABLED_DEPLOY_INTERFACES:-"fake,iscsi,direct,ramdisk"} +IRONIC_ENABLED_DEPLOY_INTERFACES=${IRONIC_ENABLED_DEPLOY_INTERFACES:-"fake,direct,ramdisk"} IRONIC_ENABLED_INSPECT_INTERFACES=${IRONIC_ENABLED_INSPECT_INTERFACES:-"fake,no-inspect"} IRONIC_ENABLED_MANAGEMENT_INTERFACES=${IRONIC_ENABLED_MANAGEMENT_INTERFACES:-"fake,ipmitool,noop"} IRONIC_ENABLED_NETWORK_INTERFACES=${IRONIC_ENABLED_NETWORK_INTERFACES:-"flat,noop"} @@ -754,7 +754,8 @@ function is_ironic_enabled { } function is_deployed_by_agent { - [[ -z "${IRONIC_DEPLOY_DRIVER%%agent*}" || "$IRONIC_DEFAULT_DEPLOY_INTERFACE" == "direct" ]] && return 0 + [[ "$IRONIC_DEFAULT_DEPLOY_INTERFACE" == "direct" + || "$IRONIC_DEFAULT_DEPLOY_INTERFACE" == "" ]] && return 0 return 1 } @@ -815,6 +816,12 @@ function is_ansible_with_tinyipa { return 1 } +function is_http_server_required { + [[ "$IRONIC_IPXE_ENABLED" == "True" ]] && return 0 + is_deployed_by_agent && [[ "$IRONIC_AGENT_IMAGE_DOWNLOAD_SOURCE" != "swift" ]] && return 0 + return 1 +} + function is_glance_configuration_required { # Always configure if we're asked to [[ "$IRONIC_CONFIGURE_GLANCE_WITH_SWIFT" == "True" ]] && return 0 @@ -1085,7 +1092,7 @@ function install_ironic { setup_develop $IRONIC_DIR - if [[ "$IRONIC_USE_WSGI" == "True" || "$IRONIC_IPXE_ENABLED" == "True" ]]; then + if [[ "$IRONIC_USE_WSGI" == "True" ]] || is_http_server_required; then install_apache_wsgi fi @@ -1148,9 +1155,9 @@ function install_ironicclient { # _cleanup_ironic_apache_additions() - Remove uwsgi files, disable and remove apache vhost file function _cleanup_ironic_apache_additions { - - if [[ "$IRONIC_IPXE_ENABLED" == "True" ]]; then + if is_http_server_required; then sudo rm -rf $IRONIC_HTTP_DIR + # TODO(dtantsur): rename the site, it's also used for direct deploy disable_apache_site ipxe-ironic sudo rm -f $(apache_site_config_for ipxe-ironic) fi @@ -1160,8 +1167,8 @@ function _cleanup_ironic_apache_additions { restart_apache_server } -# _config_ironic_apache_ipxe() - Configure ironic IPXE site -function _config_ironic_apache_ipxe { +# _config_ironic_apache_additions() - Configure ironic IPXE site +function _config_ironic_apache_additions { local ipxe_apache_conf ipxe_apache_conf=$(apache_site_config_for ipxe-ironic) sudo cp $IRONIC_DEVSTACK_FILES_DIR/apache-ipxe-ironic.template $ipxe_apache_conf @@ -1185,7 +1192,7 @@ function cleanup_ironic { cleanup_ironic_config_files # Cleanup additions made to Apache - if [[ "$IRONIC_USE_WSGI" == "True" || "$IRONIC_IPXE_ENABLED" == "True" ]]; then + if [[ "$IRONIC_USE_WSGI" == "True" ]] || is_http_server_required; then _cleanup_ironic_apache_additions fi @@ -1204,7 +1211,7 @@ function configure_ironic_dirs { $IRONIC_STATE_PATH $IRONIC_TFTPBOOT_DIR $IRONIC_TFTPBOOT_DIR/pxelinux.cfg sudo chown -R $STACK_USER:$STACK_USER $IRONIC_TFTPBOOT_DIR - if [[ "$IRONIC_IPXE_ENABLED" == "True" ]]; then + if is_http_server_required; then sudo install -d -o $STACK_USER -g $STACK_USER $IRONIC_HTTP_DIR fi @@ -1456,9 +1463,9 @@ function configure_ironic { # Format logging setup_logging $IRONIC_CONF_FILE - # Adds ironic site for IPXE - if [[ "$IRONIC_IPXE_ENABLED" == "True" ]]; then - _config_ironic_apache_ipxe + # Adds ironic site for IPXE and direct deploy + if is_http_server_required; then + _config_ironic_apache_additions fi # Adds uWSGI for Ironic API @@ -1728,14 +1735,17 @@ function configure_ironic_conductor { # step because it is too slow to run in the gate. iniset $IRONIC_CONF_FILE deploy erase_devices_priority 0 + if is_http_server_required; then + iniset $IRONIC_CONF_FILE deploy http_root $IRONIC_HTTP_DIR + iniset $IRONIC_CONF_FILE deploy http_url "http://$([[ $IRONIC_HTTP_SERVER =~ : ]] && echo "[$IRONIC_HTTP_SERVER]" || echo $IRONIC_HTTP_SERVER):$IRONIC_HTTP_PORT" + fi + if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then local pxebin pxebin=`basename $IRONIC_PXE_BOOT_IMAGE` uefipxebin=`basename $(get_uefi_ipxe_boot_file)` iniset $IRONIC_CONF_FILE pxe ipxe_bootfile_name $pxebin iniset $IRONIC_CONF_FILE pxe uefi_ipxe_bootfile_name $uefipxebin - iniset $IRONIC_CONF_FILE deploy http_root $IRONIC_HTTP_DIR - iniset $IRONIC_CONF_FILE deploy http_url "http://$([[ $IRONIC_HTTP_SERVER =~ : ]] && echo "[$IRONIC_HTTP_SERVER]" || echo $IRONIC_HTTP_SERVER):$IRONIC_HTTP_PORT" if [[ "$IRONIC_IPXE_USE_SWIFT" == "True" ]]; then iniset $IRONIC_CONF_FILE pxe ipxe_use_swift True fi @@ -1836,8 +1846,8 @@ function start_ironic { start_ironic_conductor fi - # Start Apache if iPXE is enabled - if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then + # Start Apache if iPXE or agent+http is enabled + if is_http_server_required; then restart_apache_server fi } @@ -2589,7 +2599,7 @@ function configure_iptables { sudo iptables -I INPUT -d $HOST_IP -p tcp --dport $GLANCE_SERVICE_PORT -j ACCEPT || true fi - if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then + if is_http_server_required; then sudo iptables -I INPUT -d $IRONIC_HTTP_SERVER -p tcp --dport $IRONIC_HTTP_PORT -j ACCEPT || true sudo ip6tables -I INPUT -d $IRONIC_HOST_IPV6 -p tcp --dport $IRONIC_HTTP_PORT -j ACCEPT || true fi @@ -2918,7 +2928,7 @@ function prepare_baremetal_basic_ops { return 0 fi - if ! is_service_enabled nova && [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then + if ! is_service_enabled nova && is_http_server_required; then local image_file_path if [[ ${IRONIC_WHOLEDISK_IMAGE_NAME} =~ \.img$ ]]; then image_file_path=$FILES/${IRONIC_WHOLEDISK_IMAGE_NAME} diff --git a/ironic/cmd/dbsync.py b/ironic/cmd/dbsync.py index 81524aa969..071d06a540 100644 --- a/ironic/cmd/dbsync.py +++ b/ironic/cmd/dbsync.py @@ -64,6 +64,8 @@ dbapi = db_api.get_instance() # object, in case it is lazy loaded. The attribute will be accessed when needed # by doing getattr on the object ONLINE_MIGRATIONS = ( + # Added in Victoria, remove when removing iscsi deploy. + (dbapi, 'migrate_from_iscsi_deploy'), # NOTE(rloo): Don't remove this; it should always be last (dbapi, 'update_to_latest_versions'), ) diff --git a/ironic/conf/default.py b/ironic/conf/default.py index 0e8a957c83..5cee6be310 100644 --- a/ironic/conf/default.py +++ b/ironic/conf/default.py @@ -111,7 +111,7 @@ driver_opts = [ cfg.StrOpt('default_console_interface', help=_DEFAULT_IFACE_HELP.format('console')), cfg.ListOpt('enabled_deploy_interfaces', - default=['iscsi', 'direct'], + default=['direct'], help=_ENABLED_IFACE_HELP.format('deploy')), cfg.StrOpt('default_deploy_interface', help=_DEFAULT_IFACE_HELP.format('deploy')), diff --git a/ironic/db/api.py b/ironic/db/api.py index 33561296e1..48228773fd 100644 --- a/ironic/db/api.py +++ b/ironic/db/api.py @@ -950,6 +950,18 @@ class Connection(object, metaclass=abc.ABCMeta): of migrated objects. """ + @abc.abstractmethod + def migrate_from_iscsi_deploy(self, context, max_count): + """Tries to migrate away from the iscsi deploy interface. + + :param context: the admin context + :param max_count: The maximum number of objects to migrate. Must be + >= 0. If zero, all the objects will be migrated. + :returns: A 2-tuple, 1. the total number of objects that need to be + migrated (at the beginning of this call) and 2. the number + of migrated objects. + """ + @abc.abstractmethod def set_node_traits(self, node_id, traits, version): """Replace all of the node traits with specified list of traits. diff --git a/ironic/db/sqlalchemy/api.py b/ironic/db/sqlalchemy/api.py index 374898bdb0..3e859226cb 100644 --- a/ironic/db/sqlalchemy/api.py +++ b/ironic/db/sqlalchemy/api.py @@ -1527,6 +1527,53 @@ class Connection(api.Connection): return total_to_migrate, total_migrated + @oslo_db_api.retry_on_deadlock + def migrate_from_iscsi_deploy(self, context, max_count, force=False): + """Tries to migrate away from the iscsi deploy interface. + + :param context: the admin context + :param max_count: The maximum number of objects to migrate. Must be + >= 0. If zero, all the objects will be migrated. + :returns: A 2-tuple, 1. the total number of objects that need to be + migrated (at the beginning of this call) and 2. the number + of migrated objects. + """ + # TODO(dtantsur): maybe change to force=True by default in W? + if not force: + if 'direct' not in CONF.enabled_deploy_interfaces: + LOG.warning('The direct deploy interface is not enabled, will ' + 'not migrate nodes to it. Run with --option ' + 'force=true to override.') + return 0, 0 + + if CONF.agent.image_download_source == 'swift': + LOG.warning('The direct deploy interface is using swift, will ' + 'not migrate nodes to it. Run with --option ' + 'force=true to override.') + return 0, 0 + + total_to_migrate = (model_query(models.Node) + .filter_by(deploy_interface='iscsi') + .count()) + if not total_to_migrate: + return 0, 0 + + max_to_migrate = max_count or total_to_migrate + + with _session_for_write(): + query = (model_query(models.Node.id) + .filter_by(deploy_interface='iscsi') + .slice(0, max_to_migrate)) + ids = [row[0] for row in query] + + num_migrated = (model_query(models.Node) + .filter_by(deploy_interface='iscsi') + .filter(models.Node.id.in_(ids)) + .update({'deploy_interface': 'direct'}, + synchronize_session=False)) + + return total_to_migrate, num_migrated + @staticmethod def _verify_max_traits_per_node(node_id, num_traits): """Verify that an operation would not exceed the per-node trait limit. diff --git a/ironic/drivers/generic.py b/ironic/drivers/generic.py index 599e1139cf..956119df8f 100644 --- a/ironic/drivers/generic.py +++ b/ironic/drivers/generic.py @@ -49,7 +49,7 @@ class GenericHardware(hardware_type.AbstractHardwareType): @property def supported_deploy_interfaces(self): """List of supported deploy interfaces.""" - return [iscsi_deploy.ISCSIDeploy, agent.AgentDeploy, + return [agent.AgentDeploy, iscsi_deploy.ISCSIDeploy, ansible_deploy.AnsibleDeploy, pxe.PXERamdiskDeploy] @property diff --git a/ironic/drivers/modules/iscsi_deploy.py b/ironic/drivers/modules/iscsi_deploy.py index c1f15d990b..7e36873065 100644 --- a/ironic/drivers/modules/iscsi_deploy.py +++ b/ironic/drivers/modules/iscsi_deploy.py @@ -604,6 +604,8 @@ class ISCSIDeploy(agent_base.AgentDeployMixin, agent_base.AgentBaseMixin, has_decomposed_deploy_steps = True + supported = False + def get_properties(self): return agent_base.VENDOR_PROPERTIES diff --git a/ironic/tests/unit/common/test_driver_factory.py b/ironic/tests/unit/common/test_driver_factory.py index 682622eecd..f63c0ee6a1 100644 --- a/ironic/tests/unit/common/test_driver_factory.py +++ b/ironic/tests/unit/common/test_driver_factory.py @@ -282,22 +282,22 @@ class DefaultInterfaceTestCase(db_base.DbTestCase): def test_calculated_with_one(self): self.config(default_deploy_interface=None) - self.config(enabled_deploy_interfaces=['direct']) + self.config(enabled_deploy_interfaces=['ansible']) iface = driver_factory.default_interface(self.driver, 'deploy') - self.assertEqual('direct', iface) + self.assertEqual('ansible', iface) def test_calculated_with_two(self): self.config(default_deploy_interface=None) - self.config(enabled_deploy_interfaces=['iscsi', 'direct']) + self.config(enabled_deploy_interfaces=['ansible', 'direct']) iface = driver_factory.default_interface(self.driver, 'deploy') - self.assertEqual('iscsi', iface) + self.assertEqual('direct', iface) def test_calculated_with_unsupported(self): self.config(default_deploy_interface=None) # manual-management doesn't support fake deploy - self.config(enabled_deploy_interfaces=['fake', 'direct']) + self.config(enabled_deploy_interfaces=['fake', 'ansible']) iface = driver_factory.default_interface(self.driver, 'deploy') - self.assertEqual('direct', iface) + self.assertEqual('ansible', iface) def test_calculated_no_answer(self): # manual-management supports no power interfaces diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py index 93e6585685..a45fb82197 100644 --- a/ironic/tests/unit/conductor/test_manager.py +++ b/ironic/tests/unit/conductor/test_manager.py @@ -5777,29 +5777,38 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): super(ManagerTestProperties, self).setUp() self.service = manager.ConductorManager('test-host', 'test-topic') - def _check_driver_properties(self, hw_type, expected): + def _check_driver_properties(self, hw_type, expected, agent_common=True, + pxe_common=True): self._start_service() properties = self.service.get_driver_properties(self.context, hw_type) - self.assertEqual(sorted(expected), sorted(properties)) + if agent_common: + expected.extend(['agent_verify_ca', + 'deploy_kernel', 'deploy_ramdisk', + 'deploy_forces_oob_reboot', + 'image_download_source', + 'image_http_proxy', 'image_https_proxy', + 'image_no_proxy']) + if pxe_common: + expected.extend(['force_persistent_boot_device', + 'rescue_kernel', 'rescue_ramdisk']) + self.assertCountEqual(expected, properties) def test_driver_properties_fake(self): expected = ['B1', 'B2'] - self._check_driver_properties("fake-hardware", expected) + self._check_driver_properties("fake-hardware", expected, + agent_common=False, pxe_common=False) def test_driver_properties_ipmi(self): self.config(enabled_hardware_types='ipmi', enabled_power_interfaces=['ipmitool'], enabled_management_interfaces=['ipmitool'], enabled_console_interfaces=['ipmitool-socat']) - expected = ['agent_verify_ca', 'ipmi_address', 'ipmi_terminal_port', + expected = ['ipmi_address', 'ipmi_terminal_port', 'ipmi_password', 'ipmi_port', 'ipmi_priv_level', 'ipmi_username', 'ipmi_bridging', 'ipmi_transit_channel', 'ipmi_transit_address', 'ipmi_target_channel', 'ipmi_target_address', 'ipmi_local_address', - 'deploy_kernel', 'deploy_ramdisk', - 'force_persistent_boot_device', 'ipmi_protocol_version', - 'ipmi_force_boot_device', 'deploy_forces_oob_reboot', - 'rescue_kernel', 'rescue_ramdisk', + 'ipmi_protocol_version', 'ipmi_force_boot_device', 'ipmi_disable_boot_timeout', 'ipmi_hex_kg_key', 'ipmi_cipher_suite'] self._check_driver_properties("ipmi", expected) @@ -5807,18 +5816,14 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): def test_driver_properties_snmp(self): self.config(enabled_hardware_types='snmp', enabled_power_interfaces=['snmp']) - expected = ['agent_verify_ca', 'deploy_kernel', 'deploy_ramdisk', - 'force_persistent_boot_device', - 'rescue_kernel', 'rescue_ramdisk', - 'snmp_driver', 'snmp_address', 'snmp_port', 'snmp_version', + expected = ['snmp_driver', 'snmp_address', 'snmp_port', 'snmp_version', 'snmp_community', 'snmp_community_read', 'snmp_community_write', 'snmp_security', 'snmp_outlet', 'snmp_user', 'snmp_context_engine_id', 'snmp_context_name', 'snmp_auth_key', 'snmp_auth_protocol', - 'snmp_priv_key', 'snmp_priv_protocol', - 'deploy_forces_oob_reboot'] + 'snmp_priv_key', 'snmp_priv_protocol'] self._check_driver_properties("snmp", expected) def test_driver_properties_ilo(self): @@ -5828,14 +5833,17 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): enabled_boot_interfaces=['ilo-virtual-media'], enabled_inspect_interfaces=['ilo'], enabled_console_interfaces=['ilo']) - expected = ['agent_verify_ca', 'ilo_address', 'ilo_username', + expected = ['ilo_address', 'ilo_username', 'ilo_password', 'client_port', 'client_timeout', 'ilo_deploy_iso', 'console_port', 'ilo_change_password', 'ca_file', 'snmp_auth_user', 'snmp_auth_prot_password', 'snmp_auth_priv_password', 'snmp_auth_protocol', - 'snmp_auth_priv_protocol', 'deploy_forces_oob_reboot', - 'ilo_verify_ca'] - self._check_driver_properties("ilo", expected) + 'snmp_auth_priv_protocol', 'ilo_verify_ca'] + self._check_driver_properties("ilo", expected, pxe_common=False) + + def test_driver_properties_manual_management(self): + self.config(enabled_hardware_types=['manual-management']) + self._check_driver_properties('manual-management', []) def test_driver_properties_fail(self): self.service.init_host() @@ -5846,25 +5854,6 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): self.assertEqual(exception.DriverNotFound, exc.exc_info[0]) -@mgr_utils.mock_record_keepalive -class ManagerTestHardwareTypeProperties(mgr_utils.ServiceSetUpMixin, - db_base.DbTestCase): - - def _check_hardware_type_properties(self, hardware_type, expected): - self.config(enabled_hardware_types=[hardware_type]) - self.hardware_type = driver_factory.get_hardware_type(hardware_type) - self._start_service() - properties = self.service.get_driver_properties(self.context, - hardware_type) - self.assertEqual(sorted(expected), sorted(properties)) - - def test_hardware_type_properties_manual_management(self): - expected = ['agent_verify_ca', 'deploy_kernel', 'deploy_ramdisk', - 'force_persistent_boot_device', 'deploy_forces_oob_reboot', - 'rescue_kernel', 'rescue_ramdisk'] - self._check_hardware_type_properties('manual-management', expected) - - @mock.patch.object(waiters, 'wait_for_all', autospec=True) @mock.patch.object(manager.ConductorManager, '_spawn_worker', autospec=True) @mock.patch.object(manager.ConductorManager, '_sync_power_state_nodes_task', diff --git a/ironic/tests/unit/db/test_api.py b/ironic/tests/unit/db/test_api.py index f855e9c91b..9252e1d59b 100644 --- a/ironic/tests/unit/db/test_api.py +++ b/ironic/tests/unit/db/test_api.py @@ -237,3 +237,65 @@ class UpdateToLatestVersionsTestCase(base.DbTestCase): for uuid in nodes: node = self.dbapi.get_node_by_uuid(uuid) self.assertEqual(self.node_ver, node.version) + + +class MigrateFromIscsiTestCase(base.DbTestCase): + + def setUp(self): + super(MigrateFromIscsiTestCase, self).setUp() + self.context = context.get_admin_context() + self.dbapi = db_api.get_instance() + self.config(enabled_deploy_interfaces='direct') + + def test_empty_db(self): + self.assertEqual( + (0, 0), self.dbapi.migrate_from_iscsi_deploy(self.context, 10)) + + def test_already_direct_exists(self): + utils.create_test_node(deploy_interface='direct') + self.assertEqual( + (0, 0), self.dbapi.update_to_latest_versions(self.context, 10)) + + def test_migrate_by_2(self): + utils.create_test_node(deploy_interface='direct') + for _i in range(3): + uuid = uuidutils.generate_uuid() + utils.create_test_node(uuid=uuid, deploy_interface='iscsi') + self.assertEqual( + (3, 2), self.dbapi.migrate_from_iscsi_deploy(self.context, 2)) + self.assertEqual( + (1, 1), self.dbapi.migrate_from_iscsi_deploy(self.context, 2)) + + def test_migrate_all(self): + utils.create_test_node(deploy_interface='direct') + for _i in range(3): + uuid = uuidutils.generate_uuid() + utils.create_test_node(uuid=uuid, deploy_interface='iscsi') + self.assertEqual( + (3, 3), self.dbapi.migrate_from_iscsi_deploy(self.context, 0)) + + def test_migration_impossible(self): + self.config(enabled_deploy_interfaces='iscsi') + for _i in range(3): + uuid = uuidutils.generate_uuid() + utils.create_test_node(uuid=uuid, deploy_interface='iscsi') + self.assertEqual( + (0, 0), self.dbapi.migrate_from_iscsi_deploy(self.context, 0)) + + def test_migration_impossible2(self): + self.config(image_download_source='swift', group='agent') + for _i in range(3): + uuid = uuidutils.generate_uuid() + utils.create_test_node(uuid=uuid, deploy_interface='iscsi') + self.assertEqual( + (0, 0), self.dbapi.migrate_from_iscsi_deploy(self.context, 0)) + + def test_force_migration(self): + self.config(enabled_deploy_interfaces='iscsi') + utils.create_test_node(deploy_interface='direct') + for _i in range(3): + uuid = uuidutils.generate_uuid() + utils.create_test_node(uuid=uuid, deploy_interface='iscsi') + self.assertEqual( + (3, 3), self.dbapi.migrate_from_iscsi_deploy(self.context, 0, + force=True)) diff --git a/ironic/tests/unit/drivers/modules/intel_ipmi/test_intel_ipmi.py b/ironic/tests/unit/drivers/modules/intel_ipmi/test_intel_ipmi.py index 199bc7a397..2668839738 100644 --- a/ironic/tests/unit/drivers/modules/intel_ipmi/test_intel_ipmi.py +++ b/ironic/tests/unit/drivers/modules/intel_ipmi/test_intel_ipmi.py @@ -14,7 +14,6 @@ from ironic.conductor import task_manager from ironic.drivers.modules import agent from ironic.drivers.modules.intel_ipmi import management as intel_management from ironic.drivers.modules import ipmitool -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import noop from ironic.drivers.modules import pxe from ironic.drivers.modules.storage import cinder @@ -47,7 +46,7 @@ class IntelIPMIHardwareTestCase(db_base.DbTestCase): kwargs.get('boot', pxe.PXEBoot)) self.assertIsInstance( task.driver.deploy, - kwargs.get('deploy', iscsi_deploy.ISCSIDeploy)) + kwargs.get('deploy', agent.AgentDeploy)) self.assertIsInstance( task.driver.console, kwargs.get('console', noop.NoConsole)) diff --git a/ironic/tests/unit/drivers/test_drac.py b/ironic/tests/unit/drivers/test_drac.py index 8a551070b9..a53bb76cac 100644 --- a/ironic/tests/unit/drivers/test_drac.py +++ b/ironic/tests/unit/drivers/test_drac.py @@ -19,7 +19,6 @@ from ironic.drivers.modules import agent from ironic.drivers.modules import drac from ironic.drivers.modules import inspector from ironic.drivers.modules import ipxe -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules.network import flat as flat_net from ironic.drivers.modules import noop from ironic.drivers.modules.storage import noop as noop_storage @@ -56,7 +55,7 @@ class IDRACHardwareTestCase(db_base.DbTestCase): kwargs.get('boot', ipxe.iPXEBoot)) self.assertIsInstance( driver.deploy, - kwargs.get('deploy', iscsi_deploy.ISCSIDeploy)) + kwargs.get('deploy', agent.AgentDeploy)) self.assertIsInstance( driver.management, kwargs.get('management', drac.management.DracWSManManagement)) @@ -100,15 +99,6 @@ class IDRACHardwareTestCase(db_base.DbTestCase): self._validate_interfaces(task.driver, inspect=inspector.Inspector) - def test_override_with_agent(self): - node = obj_utils.create_test_node(self.context, driver='idrac', - deploy_interface='direct', - inspect_interface='inspector') - with task_manager.acquire(self.context, node.id) as task: - self._validate_interfaces(task.driver, - deploy=agent.AgentDeploy, - inspect=inspector.Inspector) - def test_override_with_raid(self): for iface, impl in [('agent', agent.AgentRAID), ('no-raid', noop.NoRAID)]: diff --git a/ironic/tests/unit/drivers/test_generic.py b/ironic/tests/unit/drivers/test_generic.py index d1acb59b88..f2bc2623fc 100644 --- a/ironic/tests/unit/drivers/test_generic.py +++ b/ironic/tests/unit/drivers/test_generic.py @@ -21,7 +21,6 @@ from ironic.drivers import base as driver_base from ironic.drivers.modules import agent from ironic.drivers.modules import fake from ironic.drivers.modules import inspector -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import noop from ironic.drivers.modules import noop_mgmt from ironic.drivers.modules import pxe @@ -45,7 +44,7 @@ class ManualManagementHardwareTestCase(db_base.DbTestCase): noop_mgmt.NoopManagement) self.assertIsInstance(task.driver.power, fake.FakePower) self.assertIsInstance(task.driver.boot, pxe.PXEBoot) - self.assertIsInstance(task.driver.deploy, iscsi_deploy.ISCSIDeploy) + self.assertIsInstance(task.driver.deploy, agent.AgentDeploy) self.assertIsInstance(task.driver.inspect, noop.NoInspect) self.assertIsInstance(task.driver.raid, noop.NoRAID) @@ -70,10 +69,12 @@ class ManualManagementHardwareTestCase(db_base.DbTestCase): expected_prop_keys = [ 'agent_verify_ca', 'deploy_forces_oob_reboot', 'deploy_kernel', 'deploy_ramdisk', + 'image_download_source', 'image_http_proxy', + 'image_https_proxy', 'image_no_proxy', 'force_persistent_boot_device', 'rescue_kernel', 'rescue_ramdisk'] hardware_type = driver_factory.get_hardware_type("manual-management") properties = hardware_type.get_properties() - self.assertEqual(sorted(expected_prop_keys), sorted(properties)) + self.assertCountEqual(expected_prop_keys, properties) @mock.patch.object(driver_factory, 'default_interface', autospec=True) def test_get_properties_none(self, mock_def_iface): diff --git a/ironic/tests/unit/drivers/test_ibmc.py b/ironic/tests/unit/drivers/test_ibmc.py index 7e1a9fe30e..019b50be6f 100644 --- a/ironic/tests/unit/drivers/test_ibmc.py +++ b/ironic/tests/unit/drivers/test_ibmc.py @@ -14,12 +14,12 @@ # Version 1.0.0 from ironic.conductor import task_manager +from ironic.drivers.modules import agent from ironic.drivers.modules.ibmc import management as ibmc_mgmt from ironic.drivers.modules.ibmc import power as ibmc_power from ironic.drivers.modules.ibmc import raid as ibmc_raid from ironic.drivers.modules.ibmc import vendor as ibmc_vendor from ironic.drivers.modules import inspector -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import noop from ironic.drivers.modules import pxe from ironic.tests.unit.db import base as db_base @@ -46,7 +46,7 @@ class IBMCHardwareTestCase(db_base.DbTestCase): ibmc_power.IBMCPower) self.assertIsInstance(task.driver.boot, pxe.PXEBoot) self.assertIsInstance(task.driver.console, noop.NoConsole) - self.assertIsInstance(task.driver.deploy, iscsi_deploy.ISCSIDeploy) + self.assertIsInstance(task.driver.deploy, agent.AgentDeploy) self.assertIsInstance(task.driver.raid, ibmc_raid.IbmcRAID) self.assertIsInstance(task.driver.vendor, ibmc_vendor.IBMCVendor) self.assertIsInstance(task.driver.inspect, inspector.Inspector) diff --git a/ironic/tests/unit/drivers/test_ilo.py b/ironic/tests/unit/drivers/test_ilo.py index 3e85264363..1b2e10dae5 100644 --- a/ironic/tests/unit/drivers/test_ilo.py +++ b/ironic/tests/unit/drivers/test_ilo.py @@ -23,7 +23,6 @@ from ironic.drivers import ilo from ironic.drivers.modules import agent from ironic.drivers.modules.ilo import raid from ironic.drivers.modules import inspector -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import noop from ironic.tests.unit.db import base as db_base from ironic.tests.unit.objects import utils as obj_utils @@ -37,7 +36,7 @@ class IloHardwareTestCase(db_base.DbTestCase): enabled_boot_interfaces=['ilo-virtual-media', 'ilo-pxe'], enabled_bios_interfaces=['no-bios', 'ilo'], enabled_console_interfaces=['ilo'], - enabled_deploy_interfaces=['iscsi', 'direct'], + enabled_deploy_interfaces=['ansible', 'direct'], enabled_inspect_interfaces=['ilo'], enabled_management_interfaces=['ilo'], enabled_power_interfaces=['ilo'], @@ -56,7 +55,7 @@ class IloHardwareTestCase(db_base.DbTestCase): self.assertIsInstance(task.driver.console, ilo.console.IloConsoleInterface) self.assertIsInstance(task.driver.deploy, - iscsi_deploy.ISCSIDeploy) + agent.AgentDeploy) self.assertIsInstance(task.driver.inspect, ilo.inspect.IloInspect) self.assertIsInstance(task.driver.management, @@ -74,7 +73,6 @@ class IloHardwareTestCase(db_base.DbTestCase): self.config(enabled_inspect_interfaces=['inspector', 'ilo']) node = obj_utils.create_test_node( self.context, driver='ilo', - deploy_interface='direct', inspect_interface='inspector', raid_interface='agent', vendor_interface='no-vendor') @@ -109,7 +107,7 @@ class IloHardwareTestCase(db_base.DbTestCase): self.assertIsInstance(task.driver.console, ilo.console.IloConsoleInterface) self.assertIsInstance(task.driver.deploy, - iscsi_deploy.ISCSIDeploy) + agent.AgentDeploy) self.assertIsInstance(task.driver.inspect, ilo.inspect.IloInspect) self.assertIsInstance(task.driver.management, @@ -127,7 +125,6 @@ class IloHardwareTestCase(db_base.DbTestCase): self.config(enabled_inspect_interfaces=['inspector', 'ilo']) node = obj_utils.create_test_node( self.context, driver='ilo', - deploy_interface='direct', rescue_interface='agent', raid_interface='agent') with task_manager.acquire(self.context, node.id) as task: @@ -155,7 +152,6 @@ class IloHardwareTestCase(db_base.DbTestCase): self.context, driver='ilo', boot_interface='ilo-pxe', bios_interface='no-bios', - deploy_interface='direct', raid_interface='agent') with task_manager.acquire(self.context, node.id) as task: self.assertIsInstance(task.driver.boot, @@ -177,7 +173,7 @@ class Ilo5HardwareTestCase(db_base.DbTestCase): self.config(enabled_hardware_types=['ilo5'], enabled_boot_interfaces=['ilo-virtual-media', 'ilo-pxe'], enabled_console_interfaces=['ilo'], - enabled_deploy_interfaces=['iscsi', 'direct'], + enabled_deploy_interfaces=['ansible', 'direct'], enabled_inspect_interfaces=['ilo'], enabled_management_interfaces=['ilo5'], enabled_power_interfaces=['ilo'], @@ -193,7 +189,7 @@ class Ilo5HardwareTestCase(db_base.DbTestCase): self.assertIsInstance(task.driver.console, ilo.console.IloConsoleInterface) self.assertIsInstance(task.driver.deploy, - iscsi_deploy.ISCSIDeploy) + agent.AgentDeploy) self.assertIsInstance(task.driver.inspect, ilo.inspect.IloInspect) self.assertIsInstance(task.driver.management, diff --git a/ironic/tests/unit/drivers/test_ipmi.py b/ironic/tests/unit/drivers/test_ipmi.py index 9676949717..88cab808fd 100644 --- a/ironic/tests/unit/drivers/test_ipmi.py +++ b/ironic/tests/unit/drivers/test_ipmi.py @@ -13,7 +13,6 @@ from ironic.conductor import task_manager from ironic.drivers.modules import agent from ironic.drivers.modules import ipmitool -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import noop from ironic.drivers.modules import noop_mgmt from ironic.drivers.modules import pxe @@ -46,7 +45,7 @@ class IPMIHardwareTestCase(db_base.DbTestCase): kwargs.get('boot', pxe.PXEBoot)) self.assertIsInstance( task.driver.deploy, - kwargs.get('deploy', iscsi_deploy.ISCSIDeploy)) + kwargs.get('deploy', agent.AgentDeploy)) self.assertIsInstance( task.driver.console, kwargs.get('console', noop.NoConsole)) @@ -73,14 +72,12 @@ class IPMIHardwareTestCase(db_base.DbTestCase): 'ipmitool-socat']) node = obj_utils.create_test_node( self.context, driver='ipmi', - deploy_interface='direct', raid_interface='agent', console_interface='ipmitool-shellinabox', vendor_interface='no-vendor') with task_manager.acquire(self.context, node.id) as task: self._validate_interfaces( task, - deploy=agent.AgentDeploy, console=ipmitool.IPMIShellinaboxConsole, raid=agent.AgentRAID, vendor=noop.NoVendor) diff --git a/ironic/tests/unit/drivers/test_irmc.py b/ironic/tests/unit/drivers/test_irmc.py index b5f15246fd..64cd5b9640 100644 --- a/ironic/tests/unit/drivers/test_irmc.py +++ b/ironic/tests/unit/drivers/test_irmc.py @@ -27,7 +27,6 @@ from ironic.drivers.modules import ipxe from ironic.drivers.modules.irmc import bios as irmc_bios from ironic.drivers.modules.irmc import boot as irmc_boot from ironic.drivers.modules.irmc import raid -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import noop from ironic.tests.unit.db import base as db_base from ironic.tests.unit.objects import utils as obj_utils @@ -43,7 +42,7 @@ class IRMCHardwareTestCase(db_base.DbTestCase): self.config(enabled_hardware_types=['irmc'], enabled_boot_interfaces=['irmc-virtual-media', 'ipxe'], enabled_console_interfaces=['ipmitool-socat'], - enabled_deploy_interfaces=['iscsi', 'direct'], + enabled_deploy_interfaces=['ansible', 'direct'], enabled_inspect_interfaces=['irmc'], enabled_management_interfaces=['irmc'], enabled_power_interfaces=['irmc', 'ipmitool'], @@ -59,7 +58,7 @@ class IRMCHardwareTestCase(db_base.DbTestCase): self.assertIsInstance(task.driver.console, ipmitool.IPMISocatConsole) self.assertIsInstance(task.driver.deploy, - iscsi_deploy.ISCSIDeploy) + agent.AgentDeploy) self.assertIsInstance(task.driver.inspect, irmc.inspect.IRMCInspect) self.assertIsInstance(task.driver.management, @@ -77,7 +76,6 @@ class IRMCHardwareTestCase(db_base.DbTestCase): self.config(enabled_inspect_interfaces=['inspector', 'irmc']) node = obj_utils.create_test_node( self.context, driver='irmc', - deploy_interface='direct', inspect_interface='inspector', raid_interface='agent') with task_manager.acquire(self.context, node.id) as task: @@ -101,7 +99,6 @@ class IRMCHardwareTestCase(db_base.DbTestCase): def test_override_with_agent_rescue(self, check_share_fs_mounted_mock): node = obj_utils.create_test_node( self.context, driver='irmc', - deploy_interface='direct', rescue_interface='agent', raid_interface='agent') with task_manager.acquire(self.context, node.id) as task: @@ -131,7 +128,7 @@ class IRMCHardwareTestCase(db_base.DbTestCase): self.assertIsInstance(task.driver.console, ipmitool.IPMISocatConsole) self.assertIsInstance(task.driver.deploy, - iscsi_deploy.ISCSIDeploy) + agent.AgentDeploy) self.assertIsInstance(task.driver.inspect, irmc.inspect.IRMCInspect) self.assertIsInstance(task.driver.management, @@ -147,7 +144,6 @@ class IRMCHardwareTestCase(db_base.DbTestCase): check_share_fs_mounted_mock): node = obj_utils.create_test_node( self.context, driver='irmc', - deploy_interface='direct', rescue_interface='agent', raid_interface='irmc') with task_manager.acquire(self.context, node.id) as task: @@ -172,7 +168,6 @@ class IRMCHardwareTestCase(db_base.DbTestCase): check_share_fs_mounted_mock): node = obj_utils.create_test_node( self.context, driver='irmc', - deploy_interface='direct', rescue_interface='agent', bios_interface='no-bios') with task_manager.acquire(self.context, node.id) as task: diff --git a/ironic/tests/unit/drivers/test_redfish.py b/ironic/tests/unit/drivers/test_redfish.py index f2675b5c6d..b692c6167c 100644 --- a/ironic/tests/unit/drivers/test_redfish.py +++ b/ironic/tests/unit/drivers/test_redfish.py @@ -14,7 +14,7 @@ # under the License. from ironic.conductor import task_manager -from ironic.drivers.modules import iscsi_deploy +from ironic.drivers.modules import agent from ironic.drivers.modules import noop from ironic.drivers.modules.redfish import boot as redfish_boot from ironic.drivers.modules.redfish import inspect as redfish_inspect @@ -46,6 +46,6 @@ class RedfishHardwareTestCase(db_base.DbTestCase): redfish_power.RedfishPower) self.assertIsInstance(task.driver.boot, redfish_boot.RedfishVirtualMediaBoot) - self.assertIsInstance(task.driver.deploy, iscsi_deploy.ISCSIDeploy) + self.assertIsInstance(task.driver.deploy, agent.AgentDeploy) self.assertIsInstance(task.driver.console, noop.NoConsole) self.assertIsInstance(task.driver.raid, noop.NoRAID) diff --git a/ironic/tests/unit/drivers/test_snmp.py b/ironic/tests/unit/drivers/test_snmp.py index 10692383cd..385714b33a 100644 --- a/ironic/tests/unit/drivers/test_snmp.py +++ b/ironic/tests/unit/drivers/test_snmp.py @@ -16,8 +16,8 @@ from unittest import mock from ironic.conductor import task_manager +from ironic.drivers.modules import agent from ironic.drivers.modules import fake -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import noop from ironic.drivers.modules import noop_mgmt from ironic.drivers.modules import pxe @@ -39,7 +39,7 @@ class SNMPHardwareTestCase(db_base.DbTestCase): with task_manager.acquire(self.context, node.id) as task: self.assertIsInstance(task.driver.power, snmp.SNMPPower) self.assertIsInstance(task.driver.boot, pxe.PXEBoot) - self.assertIsInstance(task.driver.deploy, iscsi_deploy.ISCSIDeploy) + self.assertIsInstance(task.driver.deploy, agent.AgentDeploy) self.assertIsInstance(task.driver.management, noop_mgmt.NoopManagement) self.assertIsInstance(task.driver.console, noop.NoConsole) diff --git a/ironic/tests/unit/drivers/test_xclarity.py b/ironic/tests/unit/drivers/test_xclarity.py index e43eeec7b9..9d7f9e207f 100644 --- a/ironic/tests/unit/drivers/test_xclarity.py +++ b/ironic/tests/unit/drivers/test_xclarity.py @@ -18,7 +18,6 @@ Test class for XClarity Driver from ironic.conductor import task_manager from ironic.drivers.modules import agent -from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import pxe from ironic.drivers.xclarity import management as xc_management from ironic.drivers.xclarity import power as xc_power @@ -40,7 +39,6 @@ class XClarityHardwareTestCase(db_base.DbTestCase): self.assertIsInstance(task.driver.boot, pxe.PXEBoot) self.assertIsInstance(task.driver.deploy, - iscsi_deploy.ISCSIDeploy, agent.AgentDeploy) self.assertIsInstance(task.driver.management, xc_management.XClarityManagement) diff --git a/releasenotes/notes/iscsi-deprecation-eb184141f88e7182.yaml b/releasenotes/notes/iscsi-deprecation-eb184141f88e7182.yaml new file mode 100644 index 0000000000..b2d8924534 --- /dev/null +++ b/releasenotes/notes/iscsi-deprecation-eb184141f88e7182.yaml @@ -0,0 +1,16 @@ +--- +upgrade: + - | + The deprecated ``iscsi`` deploy interface is no longer enabled by default, + set ``enabled_deploy_interfaces`` to override. It is also no longer + the first in the list of deploy interface priorities, so it has to be + requested explicitly if the ``direct`` deploy is also enabled. + - | + Since the ``direct`` deploy interface is now used by default, you need to + configure ``[deploy]http_url`` and ``[deploy]http_root`` to point at a + local HTTP server or configure access to Swift. +deprecations: + - | + The ``iscsi`` deploy interface is now deprecated, ``direct`` or ``ansible`` + deploy should be used instead. We expected the complete removal of the + ``iscsi`` deploy code to happen in the "X" release. diff --git a/zuul.d/ironic-jobs.yaml b/zuul.d/ironic-jobs.yaml index f42e1e465c..ef5a2765de 100644 --- a/zuul.d/ironic-jobs.yaml +++ b/zuul.d/ironic-jobs.yaml @@ -53,7 +53,6 @@ # each of them. For don't need all 10 GiB for CirrOS anyway. IRONIC_VM_SPECS_DISK: 4 IRONIC_VM_SPECS_CPU: 2 - IRONIC_DEFAULT_DEPLOY_INTERFACE: iscsi Q_AGENT: openvswitch Q_ML2_TENANT_NETWORK_TYPE: vxlan @@ -114,10 +113,10 @@ FORCE_CONFIG_DRIVE: False IRONIC_AGENT_IMAGE_DOWNLOAD_SOURCE: http IRONIC_AUTOMATED_CLEAN_ENABLED: False - IRONIC_DEFAULT_DEPLOY_INTERFACE: direct IRONIC_DEFAULT_RESCUE_INTERFACE: agent + IRONIC_ENABLED_HARDWARE_TYPES: ipmi IRONIC_ENABLED_DEPLOY_INTERFACES: "iscsi,direct,ramdisk" - IRONIC_ENABLED_RESCUE_INTERFACES: "fake,agent,no-rescue" + IRONIC_ENABLED_RESCUE_INTERFACES: "agent,no-rescue" IRONIC_JSON_RPC_AUTH_STRATEGY: 'http_basic' IRONIC_RAMDISK_TYPE: tinyipa IRONIC_RPC_TRANSPORT: json-rpc @@ -177,7 +176,6 @@ IRONIC_ENABLED_HARDWARE_TYPES: redfish IRONIC_ENABLED_POWER_INTERFACES: redfish IRONIC_ENABLED_MANAGEMENT_INTERFACES: redfish - IRONIC_DEFAULT_DEPLOY_INTERFACE: direct IRONIC_ENABLED_DEPLOY_INTERFACES: "iscsi,direct,ansible,ramdisk" IRONIC_RPC_TRANSPORT: json-rpc IRONIC_RAMDISK_TYPE: tinyipa @@ -285,7 +283,6 @@ parent: ironic-base vars: devstack_localrc: - IRONIC_DEFAULT_DEPLOY_INTERFACE: direct IRONIC_DEFAULT_RESCUE_INTERFACE: agent IRONIC_ENABLED_RESCUE_INTERFACES: "fake,agent,no-rescue" IRONIC_TEMPEST_WHOLE_DISK_IMAGE: True @@ -344,7 +341,6 @@ IRONIC_STORAGE_INTERFACE: cinder IRONIC_ENABLED_BOOT_INTERFACES: ipxe,pxe,fake IRONIC_DEFAULT_BOOT_INTERFACE: ipxe - IRONIC_DEFAULT_DEPLOY_INTERFACE: direct IRONIC_TEMPEST_WHOLE_DISK_IMAGE: True IRONIC_VM_EPHEMERAL_DISK: 0 IRONIC_VM_COUNT: 3 @@ -367,7 +363,6 @@ vars: tempest_test_regex: InspectorBasicTest devstack_localrc: - IRONIC_DEFAULT_DEPLOY_INTERFACE: direct IRONIC_INSPECTOR_MANAGE_FIREWALL: True IRONIC_TEMPEST_WHOLE_DISK_IMAGE: True IRONIC_VM_EPHEMERAL_DISK: 0 @@ -465,7 +460,6 @@ IRONIC_BAREMETAL_BASIC_OPS: True IRONIC_BUILD_DEPLOY_RAMDISK: False IRONIC_CALLBACK_TIMEOUT: 600 - IRONIC_DEFAULT_DEPLOY_INTERFACE: direct IRONIC_DEFAULT_BOOT_OPTION: local IRONIC_DEPLOY_DRIVER: ipmi IRONIC_ENABLED_NETWORK_INTERFACES: flat,neutron @@ -656,7 +650,6 @@ s-object: True s-proxy: True devstack_localrc: - IRONIC_DEFAULT_DEPLOY_INTERFACE: direct IRONIC_DIB_RAMDISK_OS: centos8 IRONIC_TEMPEST_WHOLE_DISK_IMAGE: True IRONIC_VM_EPHEMERAL_DISK: 0 @@ -704,7 +697,6 @@ TENANT_VLAN_RANGE: 100:150 IRONIC_ENABLED_NETWORK_INTERFACES: flat,neutron IRONIC_NETWORK_INTERFACE: neutron - IRONIC_DEFAILT_DEPLOY_INTERFACE: direct IRONIC_DEFAILT_RESCUE_INTERFACE: no-rescue IRONIC_USE_LINK_LOCAL: True IRONIC_TEMPEST_WHOLE_DISK_IMAGE: True @@ -734,7 +726,6 @@ parent: ironic-base vars: devstack_localrc: - IRONIC_DEFAULT_DEPLOY_INTERFACE: direct IRONIC_DEFAULT_RESCUE_INTERFACE: agent IRONIC_ENABLED_RESCUE_INTERFACES: "fake,agent,no-rescue" IRONIC_RAMDISK_TYPE: tinyipa