a #e#@sddlmZddlmZddlmZddlmZddlm Z ddl m Z ddl m Z ddl mZdd lmZdd lZdd lmZdd lmZdd lmZddlmZdd lZedZGdddejZe ejeddddZ Gddde Z!Gddde Z"d S))unicode_literals)models)fields)timezone)receiver)GroupObjectPermissionBase)UserObjectPermissionBase) gettext_lazy)settingsN)Node) exceptionssignals) timedeltaz app.loggercseZdZejeddeddZejededdZejedd d ed d Z ej ed d eddZ ejeddeddZ e jedeeddZejeddd deddZejededd d dZejedd d edd Zejed ddd ed!d"Zejed#dd ed$d ZGd%d&d&Zd'd(Zed)d*Zd+d,Zd-d.ZdId0d1ZdJd3d4Zgfd5d6Zd7gd7fd8d9ZdKd:d;Z dd?Z"d@dAZ#dLdCdDZ$dMdEdFZ%dNfdGdH Z&Z'S)OProcessingNodeZHostnameaHostname or IP address where the node is located (can be an internal hostname as well). If you are using Docker, this is never 127.0.0.1 or localhost. Find the IP address of your host machine by running ifconfig on Linux or by checking your network settings.) verbose_name max_length help_textPortz$Port that connects to the node's API)rrz API Version TzAPI version used by the node)rrnullrzLast Refreshedz8When was the information about this node last retrieved?)rrrz Queue CountrzWNumber of tasks currently being processed by this node (as reported by the node itself))rdefaultrzAvailable Optionsz:Description of the options that can be used for processingTokeniziToken to use for authentication. If the node doesn't have authentication, you can leave this field blank.)rrblankrrz Max Imagesz/Maximum number of images accepted by this node.)rrrrzEngine Versionz Engine version used by the node.ZLabelzcOptional label for this node. When set, this label will be shown instead of the hostname:port name.)rrrrrEnginezEngine used by the node.c@seZdZedZedZdS)zProcessingNode.MetazProcessing NodezProcessing NodesN)__name__ __module__ __qualname___rverbose_name_pluralr"r"/webodm/nodeodm/models.pyMeta#sr$cCs$|jdkr|jSd|j|jSdS)Nrz{}:{})labelformathostnameportselfr"r"r#__str__'s zProcessingNode.__str__cCs(tjjtttjddd S)z Attempts to find an available node (seen in the last 5 minutes, and with lowest queue count) :return: ProcessingNode | None minutes)Zlast_refreshed__gte queue_count) robjectsfilterrnowrr NODE_OFFLINE_MINUTESorder_byfirstr"r"r"r#find_best_available_node-sz'ProcessingNode.find_best_available_nodecCs.tjr dS|jduo,|jtttjdkS)NTr,)r NODE_OPTIMISTIC_MODElast_refreshedrr1rr2r)r"r"r# is_online6s  zProcessingNode.is_onlinecCs|jdd}zd|}|j|_|j|_|j|_|j|_|j|_t t dd| }||_ t |_|WdStjyYdS0dS)z Retrieves information and options from the node API and saves it into the database. :returns: True if information could be updated, False otherwise )timeoutcSs|jSN)__dict__)or"r"r#Nz1ProcessingNode.update_node_info..TFN) api_clientinfoversion api_versiontask_queue_countr. max_imagesengine_versionenginelistmapoptionsavailable_optionsrr1r7saver OdmError)r*r@rArJr"r"r#update_node_info=s  zProcessingNode.update_node_infocCst|j|j|j|Sr;)r r'r(token)r*r:r"r"r#r@VszProcessingNode.api_clientFcCs*|rtdddnt}tj|jfi|S)zB :returns available options in JSON string format ),z: )indent separators)dictjsondumpsrK)r*prettykwargsr"r"r#get_available_options_jsonYsz)ProcessingNode.get_available_options_jsoncCs*i}|dur&|D]}|d||d<q|S)z Convers options formatted as a list ([{'name': optionName, 'value': optionValue}, ...]) to a dictionary {optionName: optionValue, ...} :param options: options :return: dict Nvaluenamer")r*rJoptsr=r"r"r#options_list_to_dict`s z#ProcessingNode.options_list_to_dictNcCs>t|dkrtd|}||}|||||}|jS)a Sends a set of images (and optional GCP file) via the API to start processing. :param images: list of path images :param name: name of the task :param options: options to be used for processing ([{'name': optionName, 'value': optionValue}, ...]) :param progress_callback: optional callback invoked during the upload images process to be used to report status. :returns UUID of the newly created task zNeed at least 1 file)lenr NodeServerErrorr@r^ create_taskuuid)r*imagesr\rJprogress_callbackr@r]taskr"r"r#process_new_taskns  zProcessingNode.process_new_taskcCs<|}||}||}|ds8|r8||||_|S)z Gets information about this task, such as name, creation date, processing time, status, command line options and number of images being processed. z1.5.1)r@get_taskrAversion_greater_or_equal_thanget_task_console_outputoutput)r*rc with_outputr@rfZ task_infor"r"r# get_task_infos   zProcessingNode.get_task_infocCs|}||}||S)z Retrieves the console output of the OpenDroneMap's process. Useful for monitoring execution and to provide updates to the user. )r@rhrk)r*rcliner@rfr"r"r#rjs z&ProcessingNode.get_task_console_outputcCs|}||}|S)zZ Cancels a task (stops its execution, or prevents it from being executed) )r@rhcancelr*rcr@rfr"r"r# cancel_tasks zProcessingNode.cancel_taskcCs|}||}|S)z> Removes a task and deletes all of its assets )r@rhremoverpr"r"r# remove_tasks zProcessingNode.remove_taskcCs"|}||}|j|||dS)z( Downloads a task asset )parallel_downloads)r@rh download_zip)r*rc destinationrerur@rfr"r"r#download_task_assetss z#ProcessingNode.download_task_assetscCs"|}||}|||S)z\ Restarts a task that was previously canceled or that had failed to process )r@rhrestartr^)r*rcrJr@rfr"r"r# restart_tasks zProcessingNode.restart_taskcs:|j}tt|||ddlm}|jj|j|ddS)Nrr )senderZprocessing_node_id) idsuperrdelete app.pluginsrZprocessing_node_removed send_robust __class__)r*using keep_parentsZpnode_idplugin_signalsrr"r#r~s zProcessingNode.delete)rO)F)N)rt)N)NF)(rrrr CharFieldr r'PositiveIntegerFieldr(rC DateTimeFieldr7r.r JSONFieldrUrKrPrErFr%rGr$r+ staticmethodr5r8rNr@rZr^rgrmrjrqrsrxrzr~ __classcell__r"r"rr#rs8        rZupdate_processing_node_info)r{ dispatch_uidc Ks^|rZz |WnHtjy$Yn6tyX}ztdt|WYd}~n d}~00dS)Nzauto_update_node_info: )rNr rM Exceptionloggerwarningstr)r{instancecreatedrYer"r"r#auto_update_node_infos rc@seZdZejeejdZdS)"ProcessingNodeUserObjectPermission on_deleteNrrrr ForeignKeyrCASCADEcontent_objectr"r"r"r#rsrc@seZdZejeejdZdS)#ProcessingNodeGroupObjectPermissionrNrr"r"r"r#rsr)# __future__r django.dbrdjango.contrib.postgresr django.utilsrdjango.dispatchrguardian.modelsrrdjango.utils.translationr r webodmr rVpyodmr r django.db.modelsrdatetimerlogging getLoggerrModelr post_saverrrr"r"r"r#s*              1