Merge "Untie the ramdisk deploy from AgentDeploy"
This commit is contained in:
commit
438381d61c
@ -19,7 +19,6 @@ from oslo_log import log
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import units
|
||||
|
||||
from ironic.common import dhcp_factory
|
||||
from ironic.common import exception
|
||||
from ironic.common.glance_service import service_utils
|
||||
from ironic.common.i18n import _
|
||||
@ -380,7 +379,8 @@ class AgentDeployMixin(agent_base.AgentDeployMixin):
|
||||
self.reboot_and_finish_deploy(task)
|
||||
|
||||
|
||||
class AgentDeploy(AgentDeployMixin, base.DeployInterface):
|
||||
class AgentDeploy(AgentDeployMixin, agent_base.AgentBaseMixin,
|
||||
base.DeployInterface):
|
||||
"""Interface for deploy-related actions."""
|
||||
|
||||
def get_properties(self):
|
||||
@ -390,6 +390,10 @@ class AgentDeploy(AgentDeployMixin, base.DeployInterface):
|
||||
"""
|
||||
return COMMON_PROPERTIES
|
||||
|
||||
def should_manage_boot(self, task):
|
||||
"""Whether agent boot is managed by ironic."""
|
||||
return CONF.agent.manage_agent_boot
|
||||
|
||||
@METRICS.timer('AgentDeploy.validate')
|
||||
def validate(self, task):
|
||||
"""Validate the driver-specific Node deployment info.
|
||||
@ -508,31 +512,6 @@ class AgentDeploy(AgentDeployMixin, base.DeployInterface):
|
||||
LOG.info('Deployment to node %s done', task.node.uuid)
|
||||
return None
|
||||
|
||||
@METRICS.timer('AgentDeploy.tear_down')
|
||||
@task_manager.require_exclusive_lock
|
||||
def tear_down(self, task):
|
||||
"""Tear down a previous deployment on the task's node.
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
:returns: status of the deploy. One of ironic.common.states.
|
||||
:raises: NetworkError if the cleaning ports cannot be removed.
|
||||
:raises: InvalidParameterValue when the wrong power state is specified
|
||||
or the wrong driver info is specified for power management.
|
||||
:raises: StorageError when the storage interface attached volumes fail
|
||||
to detach.
|
||||
:raises: other exceptions by the node's power driver if something
|
||||
wrong occurred during the power action.
|
||||
"""
|
||||
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||
task.driver.storage.detach_volumes(task)
|
||||
deploy_utils.tear_down_storage_configuration(task)
|
||||
with manager_utils.power_state_for_network_configuration(task):
|
||||
task.driver.network.unconfigure_tenant_networks(task)
|
||||
# NOTE(mgoddard): If the deployment was unsuccessful the node may
|
||||
# have ports on the provisioning network which were not deleted.
|
||||
task.driver.network.remove_provisioning_network(task)
|
||||
return states.DELETED
|
||||
|
||||
@METRICS.timer('AgentDeploy.prepare')
|
||||
@task_manager.require_exclusive_lock
|
||||
def prepare(self, task):
|
||||
@ -658,46 +637,10 @@ class AgentDeploy(AgentDeployMixin, base.DeployInterface):
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
"""
|
||||
if CONF.agent.manage_agent_boot:
|
||||
task.driver.boot.clean_up_ramdisk(task)
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
provider = dhcp_factory.DHCPFactory()
|
||||
provider.clean_dhcp(task)
|
||||
super(AgentDeploy, self).clean_up(task)
|
||||
if CONF.agent.image_download_source == 'http':
|
||||
deploy_utils.destroy_http_instance_images(task.node)
|
||||
|
||||
def take_over(self, task):
|
||||
"""Take over management of this node from a dead conductor.
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
"""
|
||||
pass
|
||||
|
||||
@METRICS.timer('AgentDeploy.prepare_cleaning')
|
||||
def prepare_cleaning(self, task):
|
||||
"""Boot into the agent to prepare for cleaning.
|
||||
|
||||
:param task: a TaskManager object containing the node
|
||||
:raises: NodeCleaningFailure, NetworkError if the previous cleaning
|
||||
ports cannot be removed or if new cleaning ports cannot be created.
|
||||
:raises: InvalidParameterValue if cleaning network UUID config option
|
||||
has an invalid value.
|
||||
:returns: states.CLEANWAIT to signify an asynchronous prepare
|
||||
"""
|
||||
return deploy_utils.prepare_inband_cleaning(
|
||||
task, manage_boot=CONF.agent.manage_agent_boot)
|
||||
|
||||
@METRICS.timer('AgentDeploy.tear_down_cleaning')
|
||||
def tear_down_cleaning(self, task):
|
||||
"""Clean up the PXE and DHCP files after cleaning.
|
||||
|
||||
:param task: a TaskManager object containing the node
|
||||
:raises: NodeCleaningFailure, NetworkError if the cleaning ports cannot
|
||||
be removed
|
||||
"""
|
||||
deploy_utils.tear_down_inband_cleaning(
|
||||
task, manage_boot=CONF.agent.manage_agent_boot)
|
||||
|
||||
|
||||
class AgentRAID(base.RAIDInterface):
|
||||
"""Implementation of RAIDInterface which uses agent ramdisk."""
|
||||
|
@ -25,12 +25,14 @@ from oslo_utils import timeutils
|
||||
import retrying
|
||||
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import dhcp_factory
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import image_service
|
||||
from ironic.common import states
|
||||
from ironic.common import utils
|
||||
from ironic.conductor import steps as conductor_steps
|
||||
from ironic.conductor import task_manager
|
||||
from ironic.conductor import utils as manager_utils
|
||||
from ironic.conf import CONF
|
||||
from ironic.drivers.modules import agent_client
|
||||
@ -657,6 +659,88 @@ class HeartbeatMixin(object):
|
||||
task.process_event('done')
|
||||
|
||||
|
||||
class AgentBaseMixin(object):
|
||||
"""Mixin with base methods not relying on any deploy steps."""
|
||||
|
||||
def should_manage_boot(self, task):
|
||||
"""Whether agent boot is managed by ironic."""
|
||||
return True
|
||||
|
||||
@METRICS.timer('AgentBaseMixin.tear_down')
|
||||
@task_manager.require_exclusive_lock
|
||||
def tear_down(self, task):
|
||||
"""Tear down a previous deployment on the task's node.
|
||||
|
||||
Power off the node. All actual clean-up is done in the clean_up()
|
||||
method which should be called separately.
|
||||
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
:returns: deploy state DELETED.
|
||||
:raises: NetworkError if the cleaning ports cannot be removed.
|
||||
:raises: InvalidParameterValue when the wrong state is specified
|
||||
or the wrong driver info is specified.
|
||||
:raises: StorageError when volume detachment fails.
|
||||
:raises: other exceptions by the node's power driver if something
|
||||
wrong occurred during the power action.
|
||||
"""
|
||||
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||
task.driver.storage.detach_volumes(task)
|
||||
deploy_utils.tear_down_storage_configuration(task)
|
||||
with manager_utils.power_state_for_network_configuration(task):
|
||||
task.driver.network.unconfigure_tenant_networks(task)
|
||||
# NOTE(mgoddard): If the deployment was unsuccessful the node may
|
||||
# have ports on the provisioning network which were not deleted.
|
||||
task.driver.network.remove_provisioning_network(task)
|
||||
return states.DELETED
|
||||
|
||||
@METRICS.timer('AgentBaseMixin.clean_up')
|
||||
def clean_up(self, task):
|
||||
"""Clean up the deployment environment for the task's node.
|
||||
|
||||
Unlinks TFTP and instance images and triggers image cache cleanup.
|
||||
Removes the TFTP configuration files for this node.
|
||||
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
"""
|
||||
if self.should_manage_boot(task):
|
||||
task.driver.boot.clean_up_ramdisk(task)
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
provider = dhcp_factory.DHCPFactory()
|
||||
provider.clean_dhcp(task)
|
||||
|
||||
def take_over(self, task):
|
||||
"""Take over management of this node from a dead conductor.
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
"""
|
||||
pass
|
||||
|
||||
@METRICS.timer('AgentDeployMixin.prepare_cleaning')
|
||||
def prepare_cleaning(self, task):
|
||||
"""Boot into the agent to prepare for cleaning.
|
||||
|
||||
:param task: a TaskManager object containing the node
|
||||
:raises: NodeCleaningFailure, NetworkError if the previous cleaning
|
||||
ports cannot be removed or if new cleaning ports cannot be created.
|
||||
:raises: InvalidParameterValue if cleaning network UUID config option
|
||||
has an invalid value.
|
||||
:returns: states.CLEANWAIT to signify an asynchronous prepare
|
||||
"""
|
||||
return deploy_utils.prepare_inband_cleaning(
|
||||
task, manage_boot=self.should_manage_boot(task))
|
||||
|
||||
@METRICS.timer('AgentDeployMixin.tear_down_cleaning')
|
||||
def tear_down_cleaning(self, task):
|
||||
"""Clean up the PXE and DHCP files after cleaning.
|
||||
|
||||
:param task: a TaskManager object containing the node
|
||||
:raises: NodeCleaningFailure, NetworkError if the cleaning ports cannot
|
||||
be removed
|
||||
"""
|
||||
deploy_utils.tear_down_inband_cleaning(
|
||||
task, manage_boot=self.should_manage_boot(task))
|
||||
|
||||
|
||||
class AgentDeployMixin(HeartbeatMixin):
|
||||
"""Mixin with deploy methods."""
|
||||
|
||||
|
@ -25,7 +25,6 @@ from oslo_concurrency import processutils
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from ironic.common import dhcp_factory
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import states
|
||||
@ -599,38 +598,8 @@ def validate(task):
|
||||
deploy_utils.parse_instance_info(task.node)
|
||||
|
||||
|
||||
class AgentDeployMixin(agent_base.AgentDeployMixin):
|
||||
|
||||
@METRICS.timer('AgentDeployMixin.continue_deploy')
|
||||
@task_manager.require_exclusive_lock
|
||||
def continue_deploy(self, task):
|
||||
"""Method invoked when deployed using iSCSI.
|
||||
|
||||
This method is invoked during a heartbeat from an agent when
|
||||
the node is in wait-call-back state. This deploys the image on
|
||||
the node and then configures the node to boot according to the
|
||||
desired boot option (netboot or localboot).
|
||||
|
||||
:param task: a TaskManager object containing the node.
|
||||
:param kwargs: the kwargs passed from the heartbeat method.
|
||||
:raises: InstanceDeployFailure, if it encounters some error during
|
||||
the deploy.
|
||||
"""
|
||||
task.process_event('resume')
|
||||
node = task.node
|
||||
LOG.debug('Continuing the deployment on node %s', node.uuid)
|
||||
|
||||
uuid_dict_returned = do_agent_iscsi_deploy(task, self._client)
|
||||
root_uuid = uuid_dict_returned.get('root uuid')
|
||||
efi_sys_uuid = uuid_dict_returned.get('efi system partition uuid')
|
||||
prep_boot_part_uuid = uuid_dict_returned.get(
|
||||
'PrEP Boot partition uuid')
|
||||
self.prepare_instance_to_boot(task, root_uuid, efi_sys_uuid,
|
||||
prep_boot_part_uuid=prep_boot_part_uuid)
|
||||
self.reboot_and_finish_deploy(task)
|
||||
|
||||
|
||||
class ISCSIDeploy(AgentDeployMixin, base.DeployInterface):
|
||||
class ISCSIDeploy(agent_base.AgentDeployMixin, agent_base.AgentBaseMixin,
|
||||
base.DeployInterface):
|
||||
"""iSCSI Deploy Interface for deploy-related actions."""
|
||||
|
||||
def get_properties(self):
|
||||
@ -717,32 +686,33 @@ class ISCSIDeploy(AgentDeployMixin, base.DeployInterface):
|
||||
|
||||
return None
|
||||
|
||||
@METRICS.timer('ISCSIDeploy.tear_down')
|
||||
@METRICS.timer('AgentDeployMixin.continue_deploy')
|
||||
@task_manager.require_exclusive_lock
|
||||
def tear_down(self, task):
|
||||
"""Tear down a previous deployment on the task's node.
|
||||
def continue_deploy(self, task):
|
||||
"""Method invoked when deployed using iSCSI.
|
||||
|
||||
Power off the node. All actual clean-up is done in the clean_up()
|
||||
method which should be called separately.
|
||||
This method is invoked during a heartbeat from an agent when
|
||||
the node is in wait-call-back state. This deploys the image on
|
||||
the node and then configures the node to boot according to the
|
||||
desired boot option (netboot or localboot).
|
||||
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
:returns: deploy state DELETED.
|
||||
:raises: NetworkError if the cleaning ports cannot be removed.
|
||||
:raises: InvalidParameterValue when the wrong state is specified
|
||||
or the wrong driver info is specified.
|
||||
:raises: StorageError when volume detachment fails.
|
||||
:raises: other exceptions by the node's power driver if something
|
||||
wrong occurred during the power action.
|
||||
:param task: a TaskManager object containing the node.
|
||||
:param kwargs: the kwargs passed from the heartbeat method.
|
||||
:raises: InstanceDeployFailure, if it encounters some error during
|
||||
the deploy.
|
||||
"""
|
||||
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||
task.driver.storage.detach_volumes(task)
|
||||
deploy_utils.tear_down_storage_configuration(task)
|
||||
with manager_utils.power_state_for_network_configuration(task):
|
||||
task.driver.network.unconfigure_tenant_networks(task)
|
||||
# NOTE(mgoddard): If the deployment was unsuccessful the node may
|
||||
# have ports on the provisioning network which were not deleted.
|
||||
task.driver.network.remove_provisioning_network(task)
|
||||
return states.DELETED
|
||||
task.process_event('resume')
|
||||
node = task.node
|
||||
LOG.debug('Continuing the deployment on node %s', node.uuid)
|
||||
|
||||
uuid_dict_returned = do_agent_iscsi_deploy(task, self._client)
|
||||
root_uuid = uuid_dict_returned.get('root uuid')
|
||||
efi_sys_uuid = uuid_dict_returned.get('efi system partition uuid')
|
||||
prep_boot_part_uuid = uuid_dict_returned.get(
|
||||
'PrEP Boot partition uuid')
|
||||
self.prepare_instance_to_boot(task, root_uuid, efi_sys_uuid,
|
||||
prep_boot_part_uuid=prep_boot_part_uuid)
|
||||
self.reboot_and_finish_deploy(task)
|
||||
|
||||
@METRICS.timer('ISCSIDeploy.prepare')
|
||||
@task_manager.require_exclusive_lock
|
||||
@ -817,33 +787,4 @@ class ISCSIDeploy(AgentDeployMixin, base.DeployInterface):
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
"""
|
||||
deploy_utils.destroy_images(task.node.uuid)
|
||||
task.driver.boot.clean_up_ramdisk(task)
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
provider = dhcp_factory.DHCPFactory()
|
||||
provider.clean_dhcp(task)
|
||||
|
||||
def take_over(self, task):
|
||||
pass
|
||||
|
||||
@METRICS.timer('ISCSIDeploy.prepare_cleaning')
|
||||
def prepare_cleaning(self, task):
|
||||
"""Boot into the agent to prepare for cleaning.
|
||||
|
||||
:param task: a TaskManager object containing the node
|
||||
:raises NodeCleaningFailure: if the previous cleaning ports cannot
|
||||
be removed or if new cleaning ports cannot be created
|
||||
:returns: states.CLEANWAIT to signify an asynchronous prepare.
|
||||
"""
|
||||
return deploy_utils.prepare_inband_cleaning(
|
||||
task, manage_boot=True)
|
||||
|
||||
@METRICS.timer('ISCSIDeploy.tear_down_cleaning')
|
||||
def tear_down_cleaning(self, task):
|
||||
"""Clean up the PXE and DHCP files after cleaning.
|
||||
|
||||
:param task: a TaskManager object containing the node
|
||||
:raises NodeCleaningFailure: if the cleaning ports cannot be
|
||||
removed
|
||||
"""
|
||||
deploy_utils.tear_down_inband_cleaning(
|
||||
task, manage_boot=True)
|
||||
super(ISCSIDeploy, self).clean_up(task)
|
||||
|
@ -24,7 +24,7 @@ from ironic.common import states
|
||||
from ironic.conductor import task_manager
|
||||
from ironic.conductor import utils as manager_utils
|
||||
from ironic.drivers import base
|
||||
from ironic.drivers.modules import agent
|
||||
from ironic.drivers.modules import agent_base
|
||||
from ironic.drivers.modules import deploy_utils
|
||||
from ironic.drivers.modules import pxe_base
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -37,7 +37,10 @@ class PXEBoot(pxe_base.PXEBaseMixin, base.BootInterface):
|
||||
capabilities = ['ramdisk_boot', 'pxe_boot']
|
||||
|
||||
|
||||
class PXERamdiskDeploy(agent.AgentDeploy):
|
||||
class PXERamdiskDeploy(agent_base.AgentBaseMixin, base.DeployInterface):
|
||||
|
||||
def get_properties(self, task):
|
||||
return {}
|
||||
|
||||
def validate(self, task):
|
||||
if 'ramdisk_boot' not in task.driver.boot.capabilities:
|
||||
|
Loading…
x
Reference in New Issue
Block a user