#NEWLINE# @ base . passthru ( [ 'POST' ] ) #NEWLINE# @ task_manager . require_exclusive_lock #NEWLINE# def heartbeat( self , task , **kwargs ) : #NEWLINE# #INDENT# "Method for agent to periodically check in.\n\n        The agent should be sending its agent_url (so Ironic can talk back)\n        as a kwarg. kwargs should have the following format::\n\n         {\n             'agent_url': 'http://AGENT_HOST:AGENT_PORT'\n         }\n\n        AGENT_PORT defaults to 9999.\n        " #NEWLINE# node = task . node #NEWLINE# driver_internal_info = node . driver_internal_info #NEWLINE# LOG . debug ( 'Heartbeat from %(node)s, last heartbeat at %(heartbeat)s.' , { #NEWLINE# #INDENT# 'node' : node . uuid , #NEWLINE# 'heartbeat' : driver_internal_info . get ( 'agent_last_heartbeat' ) , #NEWLINE# #UNINDENT# } ) #NEWLINE# driver_internal_info [ 'agent_last_heartbeat' ] = int ( time . time ( ) ) #NEWLINE# try : #NEWLINE# #INDENT# driver_internal_info [ 'agent_url' ] = kwargs [ 'agent_url' ] #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# raise exception . MissingParameterValue ( _ ( 'For heartbeat operation, "agent_url" must be specified.' ) ) #NEWLINE# #UNINDENT# node . driver_internal_info = driver_internal_info #NEWLINE# node . save ( ) #NEWLINE# msg = _ ( 'Failed checking if deploy is done.' ) #NEWLINE# try : #NEWLINE# #INDENT# if node . maintenance : #NEWLINE# #INDENT# LOG . debug ( 'Heartbeat from node %(node)s in maintenance mode; not taking any action.' , { #NEWLINE# #INDENT# 'node' : node . uuid , #NEWLINE# #UNINDENT# } ) #NEWLINE# return #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( node . provision_state == states . DEPLOYWAIT ) and ( not self . deploy_has_started ( task ) ) ) : #NEWLINE# #INDENT# msg = _ ( 'Node failed to get image for deploy.' ) #NEWLINE# self . continue_deploy ( task , ** kwargs ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( node . provision_state == states . DEPLOYWAIT ) and self . deploy_is_done ( task ) ) : #NEWLINE# #INDENT# msg = _ ( 'Node failed to move to active state.' ) #NEWLINE# self . reboot_to_instance ( task , ** kwargs ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( node . provision_state == states . DEPLOYWAIT ) and self . deploy_has_started ( task ) ) : #NEWLINE# #INDENT# node . touch_provisioning ( ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( node . provision_state == states . CLEANWAIT ) : #NEWLINE# #INDENT# node . touch_provisioning ( ) #NEWLINE# try : #NEWLINE# #INDENT# if ( not last_error . clean_step ) : #NEWLINE# #INDENT# LOG . debug ( 'Node %s just booted to start cleaning.' , node . uuid ) #NEWLINE# msg = _ ( 'Node failed to start the first cleaning step.' ) #NEWLINE# self . _refresh_clean_steps ( task ) #NEWLINE# manager_utils . set_node_cleaning_steps ( task ) #NEWLINE# self . notify_conductor_resume_clean ( task ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# msg = _ ( 'Node failed to check cleaning progress.' ) #NEWLINE# self . continue_cleaning ( task , ** kwargs ) #NEWLINE# #UNINDENT# #UNINDENT# except exception . NoFreeConductorWorker : #NEWLINE# #INDENT# pass #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# except Exception as e : #NEWLINE# #INDENT# err_info = { #NEWLINE# #INDENT# 'node' : node . uuid , #NEWLINE# 'msg' : msg , #NEWLINE# 'e' : e , #NEWLINE# #UNINDENT# } #NEWLINE# last_error = ( _ ( 'Asynchronous exception for node %(node)s: %(msg)s Exception: %(e)s' ) % err_info ) #NEWLINE# LOG . exception ( last_error ) #NEWLINE# if ( node . provision_state in ( states . CLEANING , states . CLEANWAIT ) ) : #NEWLINE# #INDENT# manager_utils . cleaning_error_handler ( task , last_error ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( node . provision_state in ( states . DEPLOYING , states . DEPLOYWAIT ) ) : #NEWLINE# #INDENT# deploy_utils . set_failed_state ( task , last_error )