From ebf2458545bc8de623ef9b138cfae13809ab8f8c Mon Sep 17 00:00:00 2001 From: Milan Jaros <milan.jaros@vsb.cz> Date: Wed, 4 Jan 2023 10:59:36 +0100 Subject: [PATCH] add v3.9.0 (supports Blender v3.3 and v3.4), add settings of queues to preferences --- bheappe/__init__.py | 6 +- bheappe/raas_config.py | 121 ++-- bheappe/raas_jobs.py | 1256 ++++++++++++++++++++-------------------- bheappe/raas_pref.py | 799 +++++++++++++++++-------- bheappe/raas_render.py | 42 +- bheappe/raas_server.py | 5 +- builds/bheappe.zip | Bin 43014 -> 43829 bytes 7 files changed, 1322 insertions(+), 907 deletions(-) diff --git a/bheappe/__init__.py b/bheappe/__init__.py index 6d7da49..494677b 100644 --- a/bheappe/__init__.py +++ b/bheappe/__init__.py @@ -15,10 +15,10 @@ bl_info = { "name" : "bheappe", - "author" : "Milan Jaros, Petr Strakos", + "author" : "Milan Jaros, Petr Strakos, Lubomir Riha", "description" : "Rendering-as-a-Service", - "blender" : (3, 2, 0), - "version" : (3, 8, 2), + "blender" : (3, 3, 0), + "version" : (3, 9, 0), "location" : "Addon Preferences panel", "wiki_url" : "https://blender.it4i.cz/", "category" : "System", diff --git a/bheappe/raas_config.py b/bheappe/raas_config.py index 3b21ff7..4c97c1d 100644 --- a/bheappe/raas_config.py +++ b/bheappe/raas_config.py @@ -27,42 +27,17 @@ Cluster_items = [ ("KAROLINA", "Karolina", ""), ] -if bpy.app.version < (2, 90, 0): - JobQueue_items = [ - ("ORIGCPU283", "Blender2.83 CPU", ""), - ("ORIGCUDA283", "Blender2.83 CUDA", ""), - ("ORIGEEVEE283", "Blender2.83 Eevee", ""), - ] -elif bpy.app.version < (3, 0, 0): - JobQueue_items = [ - ("ORIGCPU293", "Blender2.93 CPU", ""), - ("ORIGCUDA293", "Blender2.93 CUDA", ""), - ("ORIGEEVEE293", "Blender2.93 Eevee", ""), - ] -elif bpy.app.version < (3, 1, 0): - JobQueue_items = [ - ("ORIGCPU30", "Blender3.0 CPU", ""), - ("ORIGCUDA30", "Blender3.0 CUDA", ""), - ("ORIGEEVEE30", "Blender3.0 Eevee", ""), - ] -elif bpy.app.version < (3, 2, 0): - JobQueue_items = [ - ("ORIGCPU31", "Blender3.1 CPU", ""), - ("ORIGCUDA31", "Blender3.1 CUDA", ""), - ("ORIGEEVEE31", "Blender3.1 Eevee", ""), - ] -else: - JobQueue_items = [ - ("ORIGCPU32", "Blender3.2 CPU", ""), - ("ORIGCUDA32", "Blender3.2 CUDA", ""), - ("ORIGEEVEE32", "Blender3.2 Eevee", ""), - ] +JobQueue_items = [ + ("ORIGCPU", "CPU", ""), + ("ORIGCUDA", "CUDA", ""), + ("ORIGEEVEE", "Eevee", ""), +] from . import raas_jobs ################################################################## ssh_library_items = [ ("PARAMIKO", "Paramiko", ""), - ("SYSTEM", "System", ""), + #("SYSTEM", "System", ""), ] account_types_items = [ @@ -79,8 +54,12 @@ def GetBlenderClusterVersion(): return '3.0.1-GCC-10.3.0' elif bpy.app.version < (3, 2, 0): return '3.1.0-GCC-10.3.0' + elif bpy.app.version < (3, 3, 0): + return '3.2.2-GCC-10.3.0' + elif bpy.app.version < (3, 4, 0): + return '3.3.1-GCC-10.3.0' else: - return '3.2.2-GCC-10.3.0' + return '3.4.0-GCC-10.3.0' ################################################################## # async def CreateJobSimple(context, token, job_nodes, ClusterNodeTypeId, CommandTemplateId, FileTransferMethodId, ClusterId) # async def CreateJobTask2Dep(context, token, job_nodes, ClusterNodeTypeId1, CommandTemplateId1, ClusterNodeTypeId2, CommandTemplateId2, FileTransferMethodId, ClusterId) @@ -151,57 +130,101 @@ def GetDAQueueMPIProcs(CommandTemplateId): return 0 # return cores,queue,script -def GetDAQueueScript(ClusterId, ClusterNodeTypeId, CommandTemplateId, project_dir, pid): +def GetDAQueueScript(ClusterId, CommandTemplateId): # BARBORA if ClusterId == 1: if CommandTemplateId == 10: - return 36,'qprod','~/bheappe/scripts/job_init.sh' + return 36,'~/bheappe/scripts/job_init.sh' if CommandTemplateId == 11: - return 36,'qprod','~/bheappe/scripts/run_blender_cpu.sh' + return 36,'~/bheappe/scripts/run_blender_cpu.sh' if CommandTemplateId == 12: - return 36,'qprod','~/bheappe/scripts/job_finish.sh' + return 36,'~/bheappe/scripts/job_finish.sh' if CommandTemplateId == 13: - return 24,'qnvidia','~/bheappe/scripts/job_init.sh' + return 24,'~/bheappe/scripts/job_init.sh' if CommandTemplateId == 14: - return 24,'qnvidia','~/bheappe/scripts/run_blender_cuda.sh' + return 24,'~/bheappe/scripts/run_blender_cuda.sh' if CommandTemplateId == 15: - return 24,'qnvidia','~/bheappe/scripts/job_finish.sh' + return 24,'~/bheappe/scripts/job_finish.sh' if CommandTemplateId == 16: - return 24,'qnvidia','~/bheappe/scripts/run_blender_eevee.sh' + return 24,'~/bheappe/scripts/run_blender_eevee.sh' # KAROLINA if ClusterId == 2: if CommandTemplateId == 20: - return 128,'qprod','~/bheappe/scripts/job_init.sh' + return 128,'~/bheappe/scripts/job_init.sh' if CommandTemplateId == 21: - return 128,'qprod','~/bheappe/scripts/run_blender_cpu.sh' + return 128,'~/bheappe/scripts/run_blender_cpu.sh' if CommandTemplateId == 22: - return 128,'qprod','~/bheappe/scripts/job_finish.sh' + return 128,'~/bheappe/scripts/job_finish.sh' if CommandTemplateId == 23: - return 128,'qnvidia','~/bheappe/scripts/job_init.sh' + return 128,'~/bheappe/scripts/job_init.sh' if CommandTemplateId == 24: - return 128,'qnvidia','~/bheappe/scripts/run_blender_cuda.sh' + return 128,'~/bheappe/scripts/run_blender_cuda.sh' if CommandTemplateId == 25: - return 128,'qnvidia','~/bheappe/scripts/job_finish.sh' + return 128,'~/bheappe/scripts/job_finish.sh' if CommandTemplateId == 26: - return 128,'qnvidia','~/bheappe/scripts/run_blender_eevee.sh' + return 128,'~/bheappe/scripts/run_blender_eevee.sh' - return None,None,None + return None,None #def GetGitAddonRepository(): # return 'https://code.it4i.cz/raas/bheappe.git' def GetGitAddonCommand(repository, branch): - return 'if [ -d ~/bheappe ] ; then rm -rf ~/bheappe ; fi ; git clone -q -b ' + branch + ' ' + repository \ No newline at end of file + return 'if [ -d ~/bheappe ] ; then rm -rf ~/bheappe ; fi ; git clone -q -b ' + branch + ' ' + repository + + +def GetCurrentPidInfo(context, preferences): + blender_job_info_new = context.scene.raas_blender_job_info_new + + name = '' + queue = '' + dir = '' + + if blender_job_info_new.cluster_type == 'BARBORA': + + if 'ORIGCPU' in blender_job_info_new.job_queue: + name = preferences.raas_pid_name_barbora_cpu + queue = preferences.raas_pid_queue_barbora_cpu + dir = preferences.raas_pid_dir_barbora_cpu + + if 'ORIGCUDA' in blender_job_info_new.job_queue: + name = preferences.raas_pid_name_barbora_gpu + queue = preferences.raas_pid_queue_barbora_gpu + dir = preferences.raas_pid_dir_barbora_gpu + + if 'ORIGEEVEE' in blender_job_info_new.job_queue: + name = preferences.raas_pid_name_barbora_gpu + queue = preferences.raas_pid_queue_barbora_gpu + dir = preferences.raas_pid_dir_barbora_gpu + + if blender_job_info_new.cluster_type == 'KAROLINA': + + if 'ORIGCPU' in blender_job_info_new.job_queue: + name = preferences.raas_pid_name_karolina_cpu + queue = preferences.raas_pid_queue_karolina_cpu + dir = preferences.raas_pid_dir_karolina_cpu + + if 'ORIGCUDA' in blender_job_info_new.job_queue: + name = preferences.raas_pid_name_karolina_gpu + queue = preferences.raas_pid_queue_karolina_gpu + dir = preferences.raas_pid_dir_karolina_gpu + + if 'ORIGEEVEE' in blender_job_info_new.job_queue: + name = preferences.raas_pid_name_karolina_gpu + queue = preferences.raas_pid_queue_karolina_gpu + dir = preferences.raas_pid_dir_karolina_gpu + + return name, queue, dir diff --git a/bheappe/raas_jobs.py b/bheappe/raas_jobs.py index 4dc1f8c..a319fe3 100644 --- a/bheappe/raas_jobs.py +++ b/bheappe/raas_jobs.py @@ -52,625 +52,638 @@ from . import raas_render log = logging.getLogger(__name__) ################################ -async def CreateJobSimple(context, token, job_nodes, ClusterNodeTypeId, CommandTemplateId, FileTransferMethodId, ClusterId): - - blender_job_info_new = context.scene.raas_blender_job_info_new - #filenamext = os.path.basename(blender_job_info_new.blendfile_path) - #filename = os.path.splitext(filenamext) - #filename = filename[0] - - job = None - username = raas_pref.preferences().raas_username - use_xorg = str(raas_pref.preferences().raas_use_xorg) - use_mpi = raas_config.GetDAQueueMPIProcs(CommandTemplateId) +async def CreateJobSimple(context, token, job_nodes, ClusterNodeTypeId, CommandTemplateId, FileTransferMethodId, ClusterId): - if blender_job_info_new.render_type == 'IMAGE': - job_arrays = None - frame_start = str(blender_job_info_new.frame_current) - frame_end = str(blender_job_info_new.frame_current) - frame_step = str(blender_job_info_new.frame_step) + blender_job_info_new = context.scene.raas_blender_job_info_new + + # filenamext = os.path.basename(blender_job_info_new.blendfile_path) + # filename = os.path.splitext(filenamext) + # filename = filename[0] + + job = None + username = raas_pref.preferences().raas_username + use_xorg = str(raas_pref.preferences().raas_use_xorg) + use_mpi = raas_config.GetDAQueueMPIProcs(CommandTemplateId) + + if blender_job_info_new.render_type == 'IMAGE': + job_arrays = None + frame_start = str(blender_job_info_new.frame_current) + frame_end = str(blender_job_info_new.frame_current) + frame_step = str(blender_job_info_new.frame_step) + else: + if use_mpi == 0: + job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, + blender_job_info_new.frame_end, blender_job_info_new.frame_step) else: - if use_mpi == 0: - job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, blender_job_info_new.frame_end, blender_job_info_new.frame_step) - else: - job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, blender_job_info_new.frame_end, blender_job_info_new.frame_step * use_mpi) - - frame_start = str(blender_job_info_new.frame_start) - frame_end = str(blender_job_info_new.frame_end) - frame_step = str(blender_job_info_new.frame_step) - - #blender_param = str(filename) + '.blend' - blender_param = raas_render.convert_path_to_linux(blender_job_info_new.blendfile) - blender_version = raas_config.GetBlenderClusterVersion() - - job_walltime = blender_job_info_new.job_walltime * 60 - - task = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes, - "MaxCores": job_nodes, - "WalltimeLimit": job_walltime, - "StandardOutputFile": 'stdout', - "StandardErrorFile": 'stderr', - "ProgressFile": 'stdprog', - "LogFile": 'stdlog', - "ClusterNodeTypeId": ClusterNodeTypeId, - "CommandTemplateId": CommandTemplateId, - "Priority": 4, - "JobArrays": job_arrays, - "EnvironmentVariables": [ - { - "Name": "job_project", - "Value": blender_job_info_new.job_project - }, - { - "Name": "job_email", - "Value": blender_job_info_new.job_email - }, - { - "Name": "frame_start", - "Value": frame_start - }, - { - "Name": "frame_end", - "Value": frame_end - }, - { - "Name": "frame_step", - "Value": frame_step - }, - { - "Name": "username", - "Value": username - }, - { - "Name": "blender_version", - "Value": blender_version - }, - { - "Name": "use_xorg", - "Value": use_xorg - }, - { - "Name": "use_mpi", - "Value": str(use_mpi) - } - ], - "TemplateParameterValues": [ - { - "CommandParameterIdentifier": "inputParam", - "ParameterValue": blender_param - } - ] - } - - job = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes, - "MaxCores": job_nodes, - "Priority": 4, - "Project": blender_job_info_new.job_project, - "FileTransferMethodId": FileTransferMethodId, - "ClusterId": ClusterId, - "EnvironmentVariables": None, - "WaitingLimit": 0, - "WalltimeLimit": job_walltime, - "Tasks": [ - task - ] - } - - data = { - "JobSpecification": job, - "SessionCode": token - } - - item = context.scene.raas_submitted_job_info_ext_new - - if raas_pref.preferences().raas_use_direct_access == False: - resp_json = await raas_server.post("JobManagement/CreateJob", data) - raas_server.fill_items(item, resp_json) - else: - # Id : bpy.props.IntProperty(name="Id") - item.Id = 0 - # Name : bpy.props.StringProperty(name="Name") - item.Name = blender_job_info_new.job_name - # State : bpy.props.EnumProperty(items=JobStateExt_items,name="State") - item.State = "CONFIGURING" - # Priority : bpy.props.EnumProperty(items=JobPriorityExt_items,name="Priority",default='AVERAGE') - item.Priority = "AVERAGE" - # Project : bpy.props.StringProperty(name="Project Name") - item.Project = blender_job_info_new.job_project - # CreationTime : bpy.props.StringProperty(name="Creation Time") - # SubmitTime : bpy.props.StringProperty(name="Submit Time") - # StartTime : bpy.props.StringProperty(name="Start Time") - # EndTime : bpy.props.StringProperty(name="End Time") - # TotalAllocatedTime : bpy.props.FloatProperty(name="totalAllocatedTime") - # AllParameters : bpy.props.StringProperty(name="allParameters") - item.AllParameters = raas_server.json_dumps(data) - # Tasks: bpy.props.StringProperty(name="Tasks") - -async def CreateJobTask2Dep(context, token, job_nodes1, ClusterNodeTypeId1, CommandTemplateId1, job_nodes2, ClusterNodeTypeId2, CommandTemplateId2, FileTransferMethodId, ClusterId): + job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, + blender_job_info_new.frame_end, blender_job_info_new.frame_step * use_mpi) + + frame_start = str(blender_job_info_new.frame_start) + frame_end = str(blender_job_info_new.frame_end) + frame_step = str(blender_job_info_new.frame_step) + + # blender_param = str(filename) + '.blend' + blender_param = raas_render.convert_path_to_linux( + blender_job_info_new.blendfile) + blender_version = raas_config.GetBlenderClusterVersion() + + job_walltime = blender_job_info_new.job_walltime * 60 + + task = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes, + "MaxCores": job_nodes, + "WalltimeLimit": job_walltime, + "StandardOutputFile": 'stdout', + "StandardErrorFile": 'stderr', + "ProgressFile": 'stdprog', + "LogFile": 'stdlog', + "ClusterNodeTypeId": ClusterNodeTypeId, + "CommandTemplateId": CommandTemplateId, + "Priority": 4, + "JobArrays": job_arrays, + "EnvironmentVariables": [ + { + "Name": "job_project", + "Value": blender_job_info_new.job_project + }, + { + "Name": "job_email", + "Value": blender_job_info_new.job_email + }, + { + "Name": "frame_start", + "Value": frame_start + }, + { + "Name": "frame_end", + "Value": frame_end + }, + { + "Name": "frame_step", + "Value": frame_step + }, + { + "Name": "username", + "Value": username + }, + { + "Name": "blender_version", + "Value": blender_version + }, + { + "Name": "use_xorg", + "Value": use_xorg + }, + { + "Name": "use_mpi", + "Value": str(use_mpi) + } + ], + "TemplateParameterValues": [ + { + "CommandParameterIdentifier": "inputParam", + "ParameterValue": blender_param + } + ] + } + + job = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes, + "MaxCores": job_nodes, + "Priority": 4, + "Project": blender_job_info_new.job_project, + "FileTransferMethodId": FileTransferMethodId, + "ClusterId": ClusterId, + "EnvironmentVariables": None, + "WaitingLimit": 0, + "WalltimeLimit": job_walltime, + "Tasks": [ + task + ] + } + + data = { + "JobSpecification": job, + "SessionCode": token + } - blender_job_info_new = context.scene.raas_blender_job_info_new + item = context.scene.raas_submitted_job_info_ext_new - #filenamext = os.path.basename(blender_job_info_new.blendfile_path) - #filename = os.path.splitext(filenamext) - #filename = filename[0] + if raas_pref.preferences().raas_use_direct_access == False: + resp_json = await raas_server.post("JobManagement/CreateJob", data) + raas_server.fill_items(item, resp_json) + else: + # Id : bpy.props.IntProperty(name="Id") + item.Id = 0 + # Name : bpy.props.StringProperty(name="Name") + item.Name = blender_job_info_new.job_name + # State : bpy.props.EnumProperty(items=JobStateExt_items,name="State") + item.State = "CONFIGURING" + # Priority : bpy.props.EnumProperty(items=JobPriorityExt_items,name="Priority",default='AVERAGE') + item.Priority = "AVERAGE" + # Project : bpy.props.StringProperty(name="Project Name") + item.Project = blender_job_info_new.job_project + # CreationTime : bpy.props.StringProperty(name="Creation Time") + # SubmitTime : bpy.props.StringProperty(name="Submit Time") + # StartTime : bpy.props.StringProperty(name="Start Time") + # EndTime : bpy.props.StringProperty(name="End Time") + # TotalAllocatedTime : bpy.props.FloatProperty(name="totalAllocatedTime") + # AllParameters : bpy.props.StringProperty(name="allParameters") + item.AllParameters = raas_server.json_dumps(data) + # Tasks: bpy.props.StringProperty(name="Tasks") - job = None - username = raas_pref.preferences().raas_username - use_xorg = str(raas_pref.preferences().raas_use_xorg) - use_mpi1 = raas_config.GetDAQueueMPIProcs(CommandTemplateId1) - use_mpi2 = raas_config.GetDAQueueMPIProcs(CommandTemplateId2) - if blender_job_info_new.render_type == 'IMAGE': - job_arrays = None - frame_start = str(blender_job_info_new.frame_current) - frame_end = str(blender_job_info_new.frame_current) - frame_step = str(blender_job_info_new.frame_step) - else: - if use_mpi2 == 0: - job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, blender_job_info_new.frame_end, blender_job_info_new.frame_step) - else: - job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, blender_job_info_new.frame_end, blender_job_info_new.frame_step * use_mpi2) - - frame_start = str(blender_job_info_new.frame_start) - frame_end = str(blender_job_info_new.frame_end) - frame_step = str(blender_job_info_new.frame_step) - - #blender_param = str(filename) + '.blend' - blender_param = raas_render.convert_path_to_linux(blender_job_info_new.blendfile) - blender_version = raas_config.GetBlenderClusterVersion() - - job_walltime = blender_job_info_new.job_walltime * 60 - - task1 = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes1, - "MaxCores": job_nodes1, - "WalltimeLimit": 1800, - "StandardOutputFile": 'stdout', - "StandardErrorFile": 'stderr', - "ProgressFile": 'stdprog', - "LogFile": 'stdlog', - "ClusterNodeTypeId": ClusterNodeTypeId1, - "CommandTemplateId": CommandTemplateId1, - "Priority": 4, - "EnvironmentVariables": [ - { - "Name": "job_project", - "Value": blender_job_info_new.job_project - }, - { - "Name": "job_email", - "Value": blender_job_info_new.job_email - }, - { - "Name": "frame_start", - "Value": frame_start - }, - { - "Name": "frame_end", - "Value": frame_end - }, - { - "Name": "frame_step", - "Value": frame_step - }, - { - "Name": "username", - "Value": username - }, - { - "Name": "blender_version", - "Value": blender_version - }, - { - "Name": "use_xorg", - "Value": use_xorg - }, - { - "Name": "use_mpi", - "Value": str(use_mpi1) - } - ], - "TemplateParameterValues": [ - { - "CommandParameterIdentifier": "inputParam", - "ParameterValue": blender_param - } - ] - } - - task2 = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes2, - "MaxCores": job_nodes2, - "WalltimeLimit": job_walltime, - "StandardOutputFile": 'stdout', - "StandardErrorFile": 'stderr', - "ProgressFile": 'stdprog', - "LogFile": 'stdlog', - "ClusterNodeTypeId": ClusterNodeTypeId2, - "CommandTemplateId": CommandTemplateId2, - "Priority": 4, - "JobArrays": job_arrays, - "DependsOn" : [ - task1 - ], - "EnvironmentVariables": [ - { - "Name": "job_project", - "Value": blender_job_info_new.job_project - }, - { - "Name": "job_email", - "Value": blender_job_info_new.job_email - }, - { - "Name": "frame_start", - "Value": frame_start - }, - { - "Name": "frame_end", - "Value": frame_end - }, - { - "Name": "frame_step", - "Value": frame_step - }, - { - "Name": "blender_version", - "Value": blender_version - }, - { - "Name": "use_xorg", - "Value": use_xorg - }, - { - "Name": "use_mpi", - "Value": str(use_mpi2) - } - ], - "TemplateParameterValues": [ - { - "CommandParameterIdentifier": "inputParam", - "ParameterValue": blender_param - } - ] - } - - job = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes1, - "MaxCores": job_nodes1, - "Priority": 4, - "Project": blender_job_info_new.job_project, - "FileTransferMethodId": FileTransferMethodId, - "ClusterId": ClusterId, - "EnvironmentVariables": None, - "WaitingLimit": 0, - "WalltimeLimit": job_walltime, - "Tasks": [ - task1, - task2 - ] - } - - data = { - "JobSpecification": job, - "SessionCode": token - } - - item = context.scene.raas_submitted_job_info_ext_new - - if raas_pref.preferences().raas_use_direct_access == False: - resp_json = await raas_server.post("JobManagement/CreateJob", data) - raas_server.fill_items(item, resp_json) +async def CreateJobTask2Dep(context, token, job_nodes1, ClusterNodeTypeId1, CommandTemplateId1, job_nodes2, ClusterNodeTypeId2, CommandTemplateId2, FileTransferMethodId, ClusterId): + blender_job_info_new = context.scene.raas_blender_job_info_new + + # filenamext = os.path.basename(blender_job_info_new.blendfile_path) + # filename = os.path.splitext(filenamext) + # filename = filename[0] + + job = None + username = raas_pref.preferences().raas_username + use_xorg = str(raas_pref.preferences().raas_use_xorg) + use_mpi1 = raas_config.GetDAQueueMPIProcs(CommandTemplateId1) + use_mpi2 = raas_config.GetDAQueueMPIProcs(CommandTemplateId2) + + if blender_job_info_new.render_type == 'IMAGE': + job_arrays = None + frame_start = str(blender_job_info_new.frame_current) + frame_end = str(blender_job_info_new.frame_current) + frame_step = str(blender_job_info_new.frame_step) + else: + if use_mpi2 == 0: + job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, + blender_job_info_new.frame_end, blender_job_info_new.frame_step) else: - # Id : bpy.props.IntProperty(name="Id") - item.Id = 0 - # Name : bpy.props.StringProperty(name="Name") - item.Name = blender_job_info_new.job_name - # State : bpy.props.EnumProperty(items=JobStateExt_items,name="State") - item.State = "CONFIGURING" - # Priority : bpy.props.EnumProperty(items=JobPriorityExt_items,name="Priority",default='AVERAGE') - item.Priority = "AVERAGE" - # Project : bpy.props.StringProperty(name="Project Name") - item.Project = blender_job_info_new.job_project - # CreationTime : bpy.props.StringProperty(name="Creation Time") - # SubmitTime : bpy.props.StringProperty(name="Submit Time") - # StartTime : bpy.props.StringProperty(name="Start Time") - # EndTime : bpy.props.StringProperty(name="End Time") - # TotalAllocatedTime : bpy.props.FloatProperty(name="totalAllocatedTime") - # AllParameters : bpy.props.StringProperty(name="allParameters") - item.AllParameters = raas_server.json_dumps(data) - # Tasks: bpy.props.StringProperty(name="Tasks") + job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, + blender_job_info_new.frame_end, blender_job_info_new.frame_step * use_mpi2) + + frame_start = str(blender_job_info_new.frame_start) + frame_end = str(blender_job_info_new.frame_end) + frame_step = str(blender_job_info_new.frame_step) + + # blender_param = str(filename) + '.blend' + blender_param = raas_render.convert_path_to_linux( + blender_job_info_new.blendfile) + blender_version = raas_config.GetBlenderClusterVersion() + + job_walltime = blender_job_info_new.job_walltime * 60 + + task1 = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes1, + "MaxCores": job_nodes1, + "WalltimeLimit": 1800, + "StandardOutputFile": 'stdout', + "StandardErrorFile": 'stderr', + "ProgressFile": 'stdprog', + "LogFile": 'stdlog', + "ClusterNodeTypeId": ClusterNodeTypeId1, + "CommandTemplateId": CommandTemplateId1, + "Priority": 4, + "EnvironmentVariables": [ + { + "Name": "job_project", + "Value": blender_job_info_new.job_project + }, + { + "Name": "job_email", + "Value": blender_job_info_new.job_email + }, + { + "Name": "frame_start", + "Value": frame_start + }, + { + "Name": "frame_end", + "Value": frame_end + }, + { + "Name": "frame_step", + "Value": frame_step + }, + { + "Name": "username", + "Value": username + }, + { + "Name": "blender_version", + "Value": blender_version + }, + { + "Name": "use_xorg", + "Value": use_xorg + }, + { + "Name": "use_mpi", + "Value": str(use_mpi1) + } + ], + "TemplateParameterValues": [ + { + "CommandParameterIdentifier": "inputParam", + "ParameterValue": blender_param + } + ] + } + + task2 = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes2, + "MaxCores": job_nodes2, + "WalltimeLimit": job_walltime, + "StandardOutputFile": 'stdout', + "StandardErrorFile": 'stderr', + "ProgressFile": 'stdprog', + "LogFile": 'stdlog', + "ClusterNodeTypeId": ClusterNodeTypeId2, + "CommandTemplateId": CommandTemplateId2, + "Priority": 4, + "JobArrays": job_arrays, + "DependsOn": [ + task1 + ], + "EnvironmentVariables": [ + { + "Name": "job_project", + "Value": blender_job_info_new.job_project + }, + { + "Name": "job_email", + "Value": blender_job_info_new.job_email + }, + { + "Name": "frame_start", + "Value": frame_start + }, + { + "Name": "frame_end", + "Value": frame_end + }, + { + "Name": "frame_step", + "Value": frame_step + }, + { + "Name": "blender_version", + "Value": blender_version + }, + { + "Name": "use_xorg", + "Value": use_xorg + }, + { + "Name": "use_mpi", + "Value": str(use_mpi2) + } + ], + "TemplateParameterValues": [ + { + "CommandParameterIdentifier": "inputParam", + "ParameterValue": blender_param + } + ] + } + + job = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes1, + "MaxCores": job_nodes1, + "Priority": 4, + "Project": blender_job_info_new.job_project, + "FileTransferMethodId": FileTransferMethodId, + "ClusterId": ClusterId, + "EnvironmentVariables": None, + "WaitingLimit": 0, + "WalltimeLimit": job_walltime, + "Tasks": [ + task1, + task2 + ] + } + + data = { + "JobSpecification": job, + "SessionCode": token + } -async def CreateJobTask3Dep(context, token, job_nodes1, ClusterNodeTypeId1, CommandTemplateId1, job_nodes2, ClusterNodeTypeId2, CommandTemplateId2, job_nodes3, ClusterNodeTypeId3, CommandTemplateId3, FileTransferMethodId, ClusterId): + item = context.scene.raas_submitted_job_info_ext_new - blender_job_info_new = context.scene.raas_blender_job_info_new + if raas_pref.preferences().raas_use_direct_access == False: + resp_json = await raas_server.post("JobManagement/CreateJob", data) + raas_server.fill_items(item, resp_json) + + else: + # Id : bpy.props.IntProperty(name="Id") + item.Id = 0 + # Name : bpy.props.StringProperty(name="Name") + item.Name = blender_job_info_new.job_name + # State : bpy.props.EnumProperty(items=JobStateExt_items,name="State") + item.State = "CONFIGURING" + # Priority : bpy.props.EnumProperty(items=JobPriorityExt_items,name="Priority",default='AVERAGE') + item.Priority = "AVERAGE" + # Project : bpy.props.StringProperty(name="Project Name") + item.Project = blender_job_info_new.job_project + # CreationTime : bpy.props.StringProperty(name="Creation Time") + # SubmitTime : bpy.props.StringProperty(name="Submit Time") + # StartTime : bpy.props.StringProperty(name="Start Time") + # EndTime : bpy.props.StringProperty(name="End Time") + # TotalAllocatedTime : bpy.props.FloatProperty(name="totalAllocatedTime") + # AllParameters : bpy.props.StringProperty(name="allParameters") + item.AllParameters = raas_server.json_dumps(data) + # Tasks: bpy.props.StringProperty(name="Tasks") - #filenamext = os.path.basename(blender_job_info_new.blendfile_path) - #filename = os.path.splitext(filenamext) - #filename = filename[0] - job = None - username = raas_pref.preferences().raas_username - use_xorg = str(raas_pref.preferences().raas_use_xorg) - use_mpi1 = raas_config.GetDAQueueMPIProcs(CommandTemplateId1) - use_mpi2 = raas_config.GetDAQueueMPIProcs(CommandTemplateId2) - use_mpi3 = raas_config.GetDAQueueMPIProcs(CommandTemplateId3) +async def CreateJobTask3Dep(context, token, job_nodes1, ClusterNodeTypeId1, CommandTemplateId1, job_nodes2, ClusterNodeTypeId2, CommandTemplateId2, job_nodes3, ClusterNodeTypeId3, CommandTemplateId3, FileTransferMethodId, ClusterId): - if blender_job_info_new.render_type == 'IMAGE': - job_arrays = None - frame_start = str(blender_job_info_new.frame_current) - frame_end = str(blender_job_info_new.frame_current) - frame_step = str(blender_job_info_new.frame_step) + blender_job_info_new = context.scene.raas_blender_job_info_new + + # filenamext = os.path.basename(blender_job_info_new.blendfile_path) + # filename = os.path.splitext(filenamext) + # filename = filename[0] + + job = None + username = raas_pref.preferences().raas_username + use_xorg = str(raas_pref.preferences().raas_use_xorg) + use_mpi1 = raas_config.GetDAQueueMPIProcs(CommandTemplateId1) + use_mpi2 = raas_config.GetDAQueueMPIProcs(CommandTemplateId2) + use_mpi3 = raas_config.GetDAQueueMPIProcs(CommandTemplateId3) + + if blender_job_info_new.render_type == 'IMAGE': + job_arrays = None + frame_start = str(blender_job_info_new.frame_current) + frame_end = str(blender_job_info_new.frame_current) + frame_step = str(blender_job_info_new.frame_step) + else: + if use_mpi2 == 0: + job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, + blender_job_info_new.frame_end, blender_job_info_new.frame_step) else: - if use_mpi2 == 0: - job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, blender_job_info_new.frame_end, blender_job_info_new.frame_step) - else: - job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, blender_job_info_new.frame_end, blender_job_info_new.frame_step * use_mpi2) - - frame_start = str(blender_job_info_new.frame_start) - frame_end = str(blender_job_info_new.frame_end) - frame_step = str(blender_job_info_new.frame_step) - - #blender_param = str(filename) + '.blend' - blender_param = raas_render.convert_path_to_linux(blender_job_info_new.blendfile) - blender_version = raas_config.GetBlenderClusterVersion() - - job_walltime = blender_job_info_new.job_walltime * 60 - - task1 = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes1, - "MaxCores": job_nodes1, - "WalltimeLimit": 1800, - "StandardOutputFile": 'stdout', - "StandardErrorFile": 'stderr', - "ProgressFile": 'stdprog', - "LogFile": 'stdlog', - "ClusterNodeTypeId": ClusterNodeTypeId1, - "CommandTemplateId": CommandTemplateId1, - "Priority": 4, - "EnvironmentVariables": [ - { - "Name": "job_project", - "Value": blender_job_info_new.job_project - }, - { - "Name": "job_email", - "Value": blender_job_info_new.job_email - }, - { - "Name": "frame_start", - "Value": frame_start - }, - { - "Name": "frame_end", - "Value": frame_end - }, - { - "Name": "frame_step", - "Value": frame_step - }, - { - "Name": "username", - "Value": username - }, - { - "Name": "blender_version", - "Value": blender_version - }, - { - "Name": "use_xorg", - "Value": use_xorg - }, - { - "Name": "use_mpi", - "Value": str(use_mpi1) - } - ], - "TemplateParameterValues": [ - { - "CommandParameterIdentifier": "inputParam", - "ParameterValue": blender_param - } - ] - } - - task2 = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes2, - "MaxCores": job_nodes2, - "WalltimeLimit": job_walltime, - "StandardOutputFile": 'stdout', - "StandardErrorFile": 'stderr', - "ProgressFile": 'stdprog', - "LogFile": 'stdlog', - "ClusterNodeTypeId": ClusterNodeTypeId2, - "CommandTemplateId": CommandTemplateId2, - "Priority": 4, - "JobArrays": job_arrays, - "DependsOn" : [ - task1 - ], - "EnvironmentVariables": [ - { - "Name": "job_project", - "Value": blender_job_info_new.job_project - }, - { - "Name": "job_email", - "Value": blender_job_info_new.job_email - }, - { - "Name": "frame_start", - "Value": frame_start - }, - { - "Name": "frame_end", - "Value": frame_end - }, - { - "Name": "frame_step", - "Value": frame_step - }, - { - "Name": "blender_version", - "Value": blender_version - }, - { - "Name": "use_xorg", - "Value": use_xorg - }, - { - "Name": "use_mpi", - "Value": str(use_mpi2) - } - ], - "TemplateParameterValues": [ - { - "CommandParameterIdentifier": "inputParam", - "ParameterValue": blender_param - } - ] - } - - task3 = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes3, - "MaxCores": job_nodes3, - "WalltimeLimit": job_walltime, - "StandardOutputFile": 'stdout', - "StandardErrorFile": 'stderr', - "ProgressFile": 'stdprog', - "LogFile": 'stdlog', - "ClusterNodeTypeId": ClusterNodeTypeId3, - "CommandTemplateId": CommandTemplateId3, - "Priority": 4, - "DependsOn" : [ - task2 - ], - "EnvironmentVariables": [ - { - "Name": "job_project", - "Value": blender_job_info_new.job_project - }, - { - "Name": "job_email", - "Value": blender_job_info_new.job_email - }, - { - "Name": "frame_start", - "Value": frame_start - }, - { - "Name": "frame_end", - "Value": frame_end - }, - { - "Name": "frame_step", - "Value": frame_step - }, - { - "Name": "blender_version", - "Value": blender_version - }, - { - "Name": "use_xorg", - "Value": use_xorg - }, - { - "Name": "use_mpi", - "Value": str(use_mpi3) - } - ], - "TemplateParameterValues": [ - { - "CommandParameterIdentifier": "inputParam", - "ParameterValue": blender_param - } - ] - } - - job = { - "Name": blender_job_info_new.job_name, - "MinCores": job_nodes1, - "MaxCores": job_nodes1, - "Priority": 4, - "Project": blender_job_info_new.job_project, - "FileTransferMethodId": FileTransferMethodId, - "ClusterId": ClusterId, - "EnvironmentVariables": None, - "WaitingLimit": 0, - "WalltimeLimit": job_walltime, - "Tasks": [ - task1, - task2, - task3 - ] - } - - data = { - "JobSpecification": job, - "SessionCode": token - } - - item = context.scene.raas_submitted_job_info_ext_new - - if raas_pref.preferences().raas_use_direct_access == False: - resp_json = await raas_server.post("JobManagement/CreateJob", data) - raas_server.fill_items(item, resp_json) + job_arrays = '%d-%d:%d' % (blender_job_info_new.frame_start, + blender_job_info_new.frame_end, blender_job_info_new.frame_step * use_mpi2) + + frame_start = str(blender_job_info_new.frame_start) + frame_end = str(blender_job_info_new.frame_end) + frame_step = str(blender_job_info_new.frame_step) + + # blender_param = str(filename) + '.blend' + blender_param = raas_render.convert_path_to_linux( + blender_job_info_new.blendfile) + blender_version = raas_config.GetBlenderClusterVersion() + + job_walltime = blender_job_info_new.job_walltime * 60 + + task1 = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes1, + "MaxCores": job_nodes1, + "WalltimeLimit": 1800, + "StandardOutputFile": 'stdout', + "StandardErrorFile": 'stderr', + "ProgressFile": 'stdprog', + "LogFile": 'stdlog', + "ClusterNodeTypeId": ClusterNodeTypeId1, + "CommandTemplateId": CommandTemplateId1, + "Priority": 4, + "EnvironmentVariables": [ + { + "Name": "job_project", + "Value": blender_job_info_new.job_project + }, + { + "Name": "job_email", + "Value": blender_job_info_new.job_email + }, + { + "Name": "frame_start", + "Value": frame_start + }, + { + "Name": "frame_end", + "Value": frame_end + }, + { + "Name": "frame_step", + "Value": frame_step + }, + { + "Name": "username", + "Value": username + }, + { + "Name": "blender_version", + "Value": blender_version + }, + { + "Name": "use_xorg", + "Value": use_xorg + }, + { + "Name": "use_mpi", + "Value": str(use_mpi1) + } + ], + "TemplateParameterValues": [ + { + "CommandParameterIdentifier": "inputParam", + "ParameterValue": blender_param + } + ] + } + + task2 = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes2, + "MaxCores": job_nodes2, + "WalltimeLimit": job_walltime, + "StandardOutputFile": 'stdout', + "StandardErrorFile": 'stderr', + "ProgressFile": 'stdprog', + "LogFile": 'stdlog', + "ClusterNodeTypeId": ClusterNodeTypeId2, + "CommandTemplateId": CommandTemplateId2, + "Priority": 4, + "JobArrays": job_arrays, + "DependsOn": [ + task1 + ], + "EnvironmentVariables": [ + { + "Name": "job_project", + "Value": blender_job_info_new.job_project + }, + { + "Name": "job_email", + "Value": blender_job_info_new.job_email + }, + { + "Name": "frame_start", + "Value": frame_start + }, + { + "Name": "frame_end", + "Value": frame_end + }, + { + "Name": "frame_step", + "Value": frame_step + }, + { + "Name": "blender_version", + "Value": blender_version + }, + { + "Name": "use_xorg", + "Value": use_xorg + }, + { + "Name": "use_mpi", + "Value": str(use_mpi2) + } + ], + "TemplateParameterValues": [ + { + "CommandParameterIdentifier": "inputParam", + "ParameterValue": blender_param + } + ] + } + + task3 = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes3, + "MaxCores": job_nodes3, + "WalltimeLimit": job_walltime, + "StandardOutputFile": 'stdout', + "StandardErrorFile": 'stderr', + "ProgressFile": 'stdprog', + "LogFile": 'stdlog', + "ClusterNodeTypeId": ClusterNodeTypeId3, + "CommandTemplateId": CommandTemplateId3, + "Priority": 4, + "DependsOn": [ + task2 + ], + "EnvironmentVariables": [ + { + "Name": "job_project", + "Value": blender_job_info_new.job_project + }, + { + "Name": "job_email", + "Value": blender_job_info_new.job_email + }, + { + "Name": "frame_start", + "Value": frame_start + }, + { + "Name": "frame_end", + "Value": frame_end + }, + { + "Name": "frame_step", + "Value": frame_step + }, + { + "Name": "blender_version", + "Value": blender_version + }, + { + "Name": "use_xorg", + "Value": use_xorg + }, + { + "Name": "use_mpi", + "Value": str(use_mpi3) + } + ], + "TemplateParameterValues": [ + { + "CommandParameterIdentifier": "inputParam", + "ParameterValue": blender_param + } + ] + } + + job = { + "Name": blender_job_info_new.job_name, + "MinCores": job_nodes1, + "MaxCores": job_nodes1, + "Priority": 4, + "Project": blender_job_info_new.job_project, + "FileTransferMethodId": FileTransferMethodId, + "ClusterId": ClusterId, + "EnvironmentVariables": None, + "WaitingLimit": 0, + "WalltimeLimit": job_walltime, + "Tasks": [ + task1, + task2, + task3 + ] + } + + data = { + "JobSpecification": job, + "SessionCode": token + } - else: - # Id : bpy.props.IntProperty(name="Id") - item.Id = 0 - # Name : bpy.props.StringProperty(name="Name") - item.Name = blender_job_info_new.job_name - # State : bpy.props.EnumProperty(items=JobStateExt_items,name="State") - item.State = "CONFIGURING" - # Priority : bpy.props.EnumProperty(items=JobPriorityExt_items,name="Priority",default='AVERAGE') - item.Priority = "AVERAGE" - # Project : bpy.props.StringProperty(name="Project Name") - item.Project = blender_job_info_new.job_project - # CreationTime : bpy.props.StringProperty(name="Creation Time") - # SubmitTime : bpy.props.StringProperty(name="Submit Time") - # StartTime : bpy.props.StringProperty(name="Start Time") - # EndTime : bpy.props.StringProperty(name="End Time") - # TotalAllocatedTime : bpy.props.FloatProperty(name="totalAllocatedTime") - # AllParameters : bpy.props.StringProperty(name="allParameters") - item.AllParameters = raas_server.json_dumps(data) - # Tasks: bpy.props.StringProperty(name="Tasks") - -# _19=$(echo ' cd /mnt/proj3/open-18-15/heappe/executions/salomon/7; /.key_script/nodefile.sh; cd /mnt/proj3/open-18-15/heappe/executions/salomon/7/19; -# /mnt/proj3/open-18-15/bheappe/salomon/run_blender_mic_pre.sh raas_test\.blend; 1>> /mnt/proj3/open-18-15/heappe/executions/salomon/7/19/stdout 2>> -# /mnt/proj3/open-18-15/heappe/executions/salomon/7/19/stderr ' | qsub -P "test_salo" -A OPEN-18-15 -v frame_end=1,frame_start=1,job_email=milan.jaros@vsb.cz,job_project=test_salo -# -l select=1:ncpus=24 -N 19 -l walltime=0:10:0 -e /mnt/proj3/open-18-15/heappe/executions/salomon/7/19/stderr -o /mnt/proj3/open-18-15/heappe/executions/salomon/7/19/stdout + item = context.scene.raas_submitted_job_info_ext_new + + if raas_pref.preferences().raas_use_direct_access == False: + resp_json = await raas_server.post("JobManagement/CreateJob", data) + raas_server.fill_items(item, resp_json) + + else: + # Id : bpy.props.IntProperty(name="Id") + item.Id = 0 + # Name : bpy.props.StringProperty(name="Name") + item.Name = blender_job_info_new.job_name + # State : bpy.props.EnumProperty(items=JobStateExt_items,name="State") + item.State = "CONFIGURING" + # Priority : bpy.props.EnumProperty(items=JobPriorityExt_items,name="Priority",default='AVERAGE') + item.Priority = "AVERAGE" + # Project : bpy.props.StringProperty(name="Project Name") + item.Project = blender_job_info_new.job_project + # CreationTime : bpy.props.StringProperty(name="Creation Time") + # SubmitTime : bpy.props.StringProperty(name="Submit Time") + # StartTime : bpy.props.StringProperty(name="Start Time") + # EndTime : bpy.props.StringProperty(name="End Time") + # TotalAllocatedTime : bpy.props.FloatProperty(name="totalAllocatedTime") + # AllParameters : bpy.props.StringProperty(name="allParameters") + item.AllParameters = raas_server.json_dumps(data) + # Tasks: bpy.props.StringProperty(name="Tasks") + +# _19=$(echo ' cd /mnt/proj3/open-18-15/heappe/executions/salomon/7; /.key_script/nodefile.sh; cd /mnt/proj3/open-18-15/heappe/executions/salomon/7/19; +# /mnt/proj3/open-18-15/bheappe/salomon/run_blender_mic_pre.sh raas_test\.blend; 1>> /mnt/proj3/open-18-15/heappe/executions/salomon/7/19/stdout 2>> +# /mnt/proj3/open-18-15/heappe/executions/salomon/7/19/stderr ' | qsub -P "test_salo" -A OPEN-18-15 -v frame_end=1,frame_start=1,job_email=milan.jaros@vsb.cz,job_project=test_salo +# -l select=1:ncpus=24 -N 19 -l walltime=0:10:0 -e /mnt/proj3/open-18-15/heappe/executions/salomon/7/19/stderr -o /mnt/proj3/open-18-15/heappe/executions/salomon/7/19/stdout # -r n -q qprod -l cpu_hyper_threading=true);echo $_19; -# -# _20=$(echo ' cd /mnt/proj3/open-18-15/heappe/executions/salomon/7; /.key_script/nodefile.sh; -# cd /mnt/proj3/open-18-15/heappe/executions/salomon/7/20; ln -s ../19/ .; rm /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stdout; -# rm /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stderr;/mnt/proj3/open-18-15/bheappe/salomon/run_blender_mpp.sh raas_test\.blend; -# 1>> /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stdout 2>> /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stderr ' -# | qsub -P "test_salo" -A OPEN-18-15 -W depend=afterok:$_19 -v frame_end=1,frame_start=1,job_email=milan.jaros@vsb.cz,job_project=test_salo -# -l select=1:ncpus=24 -N 20 -l walltime=0:30:0 -e /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stderr +# +# _20=$(echo ' cd /mnt/proj3/open-18-15/heappe/executions/salomon/7; /.key_script/nodefile.sh; +# cd /mnt/proj3/open-18-15/heappe/executions/salomon/7/20; ln -s ../19/ .; rm /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stdout; +# rm /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stderr;/mnt/proj3/open-18-15/bheappe/salomon/run_blender_mpp.sh raas_test\.blend; +# 1>> /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stdout 2>> /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stderr ' +# | qsub -P "test_salo" -A OPEN-18-15 -W depend=afterok:$_19 -v frame_end=1,frame_start=1,job_email=milan.jaros@vsb.cz,job_project=test_salo +# -l select=1:ncpus=24 -N 20 -l walltime=0:30:0 -e /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stderr # -o /mnt/proj3/open-18-15/heappe/executions/salomon/7/20/stdout -r n -q qmpp -l cpu_hyper_threading=true); # echo $_20; -# -# _21=$(echo ' cd /mnt/proj3/open-18-15/heappe/executions/salomon/7; ~/.key_script/nodefile.sh; -# cd /mnt/proj3/open-18-15/heappe/executions/salomon/7/21; ln -s ../20/ .; -# rm /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stdout; +# +# _21=$(echo ' cd /mnt/proj3/open-18-15/heappe/executions/salomon/7; ~/.key_script/nodefile.sh; +# cd /mnt/proj3/open-18-15/heappe/executions/salomon/7/21; ln -s ../20/ .; +# rm /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stdout; # rm /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stderr; -# /mnt/proj3/open-18-15/bheappe/salomon/run_blender_mic_post.sh raas_test\.blend; 1>> /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stdout 2>> -# /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stderr ' | qsub -P "test_salo" -A OPEN-18-15 -W depend=afterok:$_20 -v frame_start=1,job_email=milan.jaros@vsb.cz,job_project=test_salo,frame_end=1 +# /mnt/proj3/open-18-15/bheappe/salomon/run_blender_mic_post.sh raas_test\.blend; 1>> /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stdout 2>> +# /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stderr ' | qsub -P "test_salo" -A OPEN-18-15 -W depend=afterok:$_20 -v frame_start=1,job_email=milan.jaros@vsb.cz,job_project=test_salo,frame_end=1 # -l select=1:ncpus=24 -N 21 -l walltime=0:10:0 -e /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stderr -o /mnt/proj3/open-18-15/heappe/executions/salomon/7/21/stdout -# -r n -q qprod -l cpu_hyper_threading=true);echo $_21; +# -r n -q qprod -l cpu_hyper_threading=true);echo $_21; + def CmdCreatePBSJob(context): item = context.scene.raas_submitted_job_info_ext_new @@ -687,11 +700,15 @@ def CmdCreatePBSJob(context): for task in tasks: cluster_node_type_id = task['ClusterNodeTypeId'] command_template_id = task['CommandTemplateId'] - cores,queue,script = raas_config.GetDAQueueScript(cluster_id, cluster_node_type_id, command_template_id, raas_pref.preferences().raas_pid_dir, raas_pref.preferences().raas_pid.lower()) + cores, script = raas_config.GetDAQueueScript( + cluster_id, command_template_id) + pid_name, pid_queue, pid_dir = raas_config.GetCurrentPidInfo( + context, raas_pref.preferences()) + file = task['TemplateParameterValues'][0]['ParameterValue'] - ncpus = int(cores) - nodes = 1 #int(task['MaxCores'] / cores) + # ncpus = int(cores) + nodes = 1 # int(task['MaxCores'] / cores) envs = task['EnvironmentVariables'] job_env = '' @@ -700,13 +717,14 @@ def CmdCreatePBSJob(context): for env in envs: job_env = job_env + env['Name'] + '=' + env['Value'] + ',' - work_dir = raas_render.get_direct_access_remote_storage(context) + '/' + job_name + work_dir = raas_render.get_direct_access_remote_storage( + context) + '/' + job_name work_dir_stderr = work_dir + '/' + task['StandardErrorFile'] - work_dir_stdout = work_dir + '/' + task['StandardOutputFile'] + work_dir_stdout = work_dir + '/' + task['StandardOutputFile'] mm, ss = divmod(task['WalltimeLimit'], 60) - hh, mm= divmod(mm, 60) + hh, mm = divmod(mm, 60) walltime = str(hh) + ':' + str(mm) + ':' + str(ss) @@ -719,19 +737,28 @@ def CmdCreatePBSJob(context): if 'DependsOn' in task: depends_on = ' -W depend=afterany:$_' + str(task_id - 1) job_env = job_env + 'depends_on=\"$_' + str(task_id - 1) + '\",' - + job_env = job_env + 'work_dir=' + work_dir xorg_true = '' if raas_pref.preferences().raas_use_xorg == True: xorg_true = ' -l xorg=True ' - cmd = cmd + '_' + str(task_id) + '=$(echo \' ' + script + ' ' + file + ' \' | qsub -P \"' + job_project + '\" -A ' + raas_config.GetDAOpenCallProject(raas_pref.preferences().raas_pid.upper()) + ' -v ' + job_env + ' -l select=' + str(nodes) + ':ncpus=' + str(ncpus) + ' -N \"' + job_project + '\" -l walltime=' + walltime + ' -e ' + work_dir_stderr + ' -o ' + work_dir_stdout + ' -q ' + queue + job_array + depends_on + xorg_true + ');echo $_' + str(task_id) + ';' + # cmd = cmd + '_' + str(task_id) + '=$(echo \' ' + script + ' ' + file + ' \' | qsub -P \"' + job_project + '\" -A ' + raas_config.GetDAOpenCallProject(pid_name.upper()) + ' -v ' + job_env + ' -l select=' + str(nodes) + \ + # ':ncpus=' + str(ncpus) + ' -N \"' + job_project + '\" -l walltime=' + walltime + ' -e ' + work_dir_stderr + \ + # ' -o ' + work_dir_stdout + ' -q ' + pid_queue + job_array + \ + # depends_on + xorg_true + ');echo $_' + str(task_id) + ';' + + cmd = cmd + '_' + str(task_id) + '=$(echo \' ' + script + ' ' + file + ' \' | qsub -P \"' + job_project + '\" -A ' + raas_config.GetDAOpenCallProject(pid_name.upper()) + ' -v ' + job_env + ' -l select=' + str(nodes) + \ + ' -N \"' + job_project + '\" -l walltime=' + walltime + ' -e ' + work_dir_stderr + \ + ' -o ' + work_dir_stdout + ' -q ' + pid_queue + job_array + \ + depends_on + xorg_true + ');echo $_' + str(task_id) + ';' task_id = task_id + 1 return cmd + def CmdCreateStatPBSJobFile(context, pbs_jobs): item = context.scene.raas_submitted_job_info_ext_new data = json.loads(item.AllParameters) @@ -745,7 +772,8 @@ def CmdCreateStatPBSJobFile(context, pbs_jobs): pbs_job = pbs_jobs[1] if len(pbs_job) > 0: - job_log = raas_render.get_direct_access_remote_storage(context) + '/' + job_name + '.job' + job_log = raas_render.get_direct_access_remote_storage( + context) + '/' + job_name + '.job' cmd = cmd + 'qstat -fx ' + pbs_job + ' > ' + job_log + ';' # for pbs_job in pbs_jobs: @@ -755,16 +783,20 @@ def CmdCreateStatPBSJobFile(context, pbs_jobs): return cmd + def CmdCreateProjectGroupFolder(context): cmd = 'mkdir -p ' + raas_render.get_direct_access_remote_storage(context) return cmd + def CmdGetStatPBSJobFile(context, job_name): - job_log = raas_render.get_direct_access_remote_storage(context) + '/' + job_name + '.job' - cmd = 'cat ' + job_log - + job_log = raas_render.get_direct_access_remote_storage( + context) + '/' + job_name + '.job' + cmd = 'cat ' + job_log + return cmd + def CmdGetPidDir(pid): - cmd = 'it4i-get-project-dir ' + pid - return cmd \ No newline at end of file + cmd = 'it4i-get-project-dir ' + pid + return cmd diff --git a/bheappe/raas_pref.py b/bheappe/raas_pref.py index b2b5018..c9cd2e3 100644 --- a/bheappe/raas_pref.py +++ b/bheappe/raas_pref.py @@ -18,6 +18,10 @@ # (c) IT4Innovations, VSB-TUO +import importlib +import sys +import subprocess +from collections import namedtuple import functools import logging import os.path @@ -41,6 +45,7 @@ ADDON_NAME = 'bheappe' log = logging.getLogger(__name__) + @functools.lru_cache() def factor(factor: float) -> dict: """Construct keyword argument for UILayout.split(). @@ -53,25 +58,28 @@ def factor(factor: float) -> dict: return {'factor': factor} ################################################## -def show_message_box(message = "", title = "BHeappe", icon = 'INFO'): + + +def show_message_box(message="", title="BHeappe", icon='INFO'): def draw(self, context): self.layout.label(text=message) - bpy.context.window_manager.popup_menu(draw, title = title, icon = icon) + bpy.context.window_manager.popup_menu(draw, title=title, icon=icon) + ################################################## -from collections import namedtuple -import subprocess, sys, importlib Dependency = namedtuple("Dependency", ["module", "package", "name"]) python_dependencies = (Dependency(module="paramiko", package="paramiko", name=None), - Dependency(module="scp", package="scp", name=None), - Dependency(module="blender_asset_tracer", package="blender_asset_tracer", name=None), - ) + Dependency(module="scp", package="scp", name=None), + Dependency(module="blender_asset_tracer", + package="blender_asset_tracer", name=None), + ) internal_dependencies = [] + def import_module(module_name, global_name=None, reload=True): if global_name is None: global_name = module_name @@ -83,6 +91,7 @@ def import_module(module_name, global_name=None, reload=True): # the given name, just like the regular import would. globals()[global_name] = importlib.import_module(module_name) + def install_pip(): try: if bpy.app.version < (2, 90, 0): @@ -94,7 +103,8 @@ def install_pip(): subprocess.run([python_exe, "-m", "pip", "--version"], check=True) # Upgrade - subprocess.run([python_exe, "-m", "pip", "install", "--upgrade", "pip"], check=True) + subprocess.run([python_exe, "-m", "pip", "install", + "--upgrade", "pip"], check=True) except subprocess.CalledProcessError: import ensurepip @@ -102,6 +112,7 @@ def install_pip(): ensurepip.bootstrap() os.environ.pop("PIP_REQ_TRACKER", None) + def install_and_import_module(module_name, package_name=None, global_name=None): if package_name is None: package_name = module_name @@ -118,23 +129,27 @@ def install_and_import_module(module_name, package_name=None, global_name=None): else: python_exe = sys.executable - subprocess.run([python_exe, "-m", "pip", "install", package_name], check=True, env=environ_copy) + subprocess.run([python_exe, "-m", "pip", "install", + package_name], check=True, env=environ_copy) # The installation succeeded, attempt to import the module again - import_module(module_name, global_name) + import_module(module_name, global_name) + +################################################################ + -################################################################ def _paramiko_generate_ssh_key(private_filepath, public_filepath, password): - import paramiko - key = paramiko.RSAKey.generate(2048) - key.write_private_key_file(private_filepath, password) - - public_key = "%s %s" % (key.get_name(), key.get_base64()) - with open(public_filepath,"w") as f: - f.write(public_key) - - f.close() + import paramiko + key = paramiko.RSAKey.generate(2048) + key.write_private_key_file(private_filepath, password) + + public_key = "%s %s" % (key.get_name(), key.get_base64()) + with open(public_filepath, "w") as f: + f.write(public_key) + + f.close() + class RAAS_OT_generate_sshkey(Operator): bl_idname = 'raas.generate_sshkey' @@ -147,23 +162,28 @@ class RAAS_OT_generate_sshkey(Operator): return {"CANCELLED"} if len(preferences().raas_gen_public_key_path) == 0: - preferences().raas_gen_public_key_path = preferences().raas_job_storage_path + '/raas_gen.public.key' + preferences().raas_gen_public_key_path = preferences( + ).raas_job_storage_path + '/raas_gen.public.key' if len(preferences().raas_gen_private_key_path) == 0: - preferences().raas_gen_private_key_path = preferences().raas_job_storage_path + '/raas_gen.private.key' + preferences().raas_gen_private_key_path = preferences( + ).raas_job_storage_path + '/raas_gen.private.key' - _paramiko_generate_ssh_key(preferences().raas_gen_private_key_path, preferences().raas_gen_public_key_path, preferences().raas_gen_password) + _paramiko_generate_ssh_key(preferences().raas_gen_private_key_path, preferences( + ).raas_gen_public_key_path, preferences().raas_gen_password) except Exception as e: import traceback traceback.print_exc() - self.report({'ERROR'}, "Problem with %s: %s: %s" % (self.bl_label, e.__class__, e)) + self.report({'ERROR'}, "Problem with %s: %s: %s" % + (self.bl_label, e.__class__, e)) return {"CANCELLED"} self.report({'INFO'}, "'%s' finished" % (self.bl_label)) return {"FINISHED"} + class RAAS_OT_upload_sshkey(Operator): bl_idname = 'raas.upload_sshkey' bl_label = 'Upload public key' @@ -177,113 +197,265 @@ class RAAS_OT_upload_sshkey(Operator): if len(preferences().raas_gen_public_key_path) > 0: with open(preferences().raas_gen_public_key_path) as f: public_key = f.readlines() - + bpy.context.window_manager.clipboard = public_key[0] import webbrowser - if preferences().raas_account_type == "EDUID": - webbrowser.open('https://signup.e-infra.cz/fed/registrar/?vo=IT4Innovations', new=2) - else: - webbrowser.open('https://extranet.it4i.cz/ssp/?action=changesshkey&login=%s' % preferences().raas_gen_username, new=2) + if preferences().raas_account_type == "EDUID": + webbrowser.open( + 'https://signup.e-infra.cz/fed/registrar/?vo=IT4Innovations', new=2) + else: + webbrowser.open('https://extranet.it4i.cz/ssp/?action=changesshkey&login=%s' % + preferences().raas_gen_username, new=2) except Exception as e: import traceback traceback.print_exc() - self.report({'ERROR'}, "Problem with %s: %s: %s" % (self.bl_label, e.__class__, e)) + self.report({'ERROR'}, "Problem with %s: %s: %s" % + (self.bl_label, e.__class__, e)) return {"CANCELLED"} self.report({'INFO'}, "'%s' finished" % (self.bl_label)) return {"FINISHED"} -class RAAS_OT_setup_sshkey(Operator): - bl_idname = 'raas.setup_sshkey' - bl_label = 'Setup' - bl_description = ("Setup") + +# class RAAS_OT_setup_sshkey(Operator): +# bl_idname = 'raas.setup_sshkey' +# bl_label = 'Setup' +# bl_description = ("Setup") + +# def execute(self, context): +# try: +# pref = preferences() + +# if not pref.check_valid_settings_gen(): +# return {"CANCELLED"} + +# pref.raas_da_username = pref.raas_gen_username +# pref.raas_private_key_path = pref.raas_gen_private_key_path +# pref.raas_da_password = pref.raas_gen_password +# pref.raas_pid = pref.raas_gen_pid +# pref.raas_project_group = pref.raas_da_username + +# # TODO +# if not pref.check_valid_settings(type='PROJECT_DIR'): +# return {"CANCELLED"} + +# cmd = raas_jobs.CmdGetPidDir(pref.raas_pid.upper()) +# if len(cmd) > 0: +# server = raas_config.GetDAServer(context) +# res = raas_render.ssh_command_sync(server, cmd) +# pref.raas_pid_dir = res.strip() + +# except Exception as e: +# import traceback +# traceback.print_exc() + +# self.report({'ERROR'}, "Problem with %s: %s: %s" % +# (self.bl_label, e.__class__, e)) +# return {"CANCELLED"} + +# self.report({'INFO'}, "'%s' finished" % (self.bl_label)) +# return {"FINISHED"} + + +# class RAAS_OT_find_pid_dir(Operator): +# bl_idname = 'raas.find_pid_dir' +# bl_label = 'Find Project Dir' +# bl_description = ("Find Project Dir") + +# def execute(self, context): +# # success = True + +# for cl in raas_config.Cluster_items: +# try: +# if not preferences().check_valid_settings(type='PROJECT_DIR'): +# return {"CANCELLED"} + +# cmd = raas_jobs.CmdGetPidDir(preferences().raas_pid.upper()) +# if len(cmd) > 0: +# # server = raas_config.GetDAServer(context) +# server = raas_config.GetServerFromType(cl[0]) +# res = raas_render.ssh_command_sync(server, cmd) +# preferences().raas_pid_dir = res.strip() + +# break + +# except Exception as e: +# import traceback +# traceback.print_exc() + +# self.report({'ERROR'}, "Problem with %s: %s: %s" % +# (self.bl_label, e.__class__, e)) +# # return {"CANCELLED"} +# # success = False + +# self.report({'INFO'}, "'%s' finished" % (self.bl_label)) +# return {"FINISHED"} + +class RAAS_OT_find_pid_dir_barbora_cpu(Operator): + bl_idname = 'raas.find_pid_dir_barbora_cpu' + bl_label = 'Find Dir' + bl_description = ("Find") def execute(self, context): + # success = True + + #for cl in raas_config.Cluster_items: try: - pref = preferences() + if not preferences().check_valid_settings(type='PROJECT_DIR'): + return {"CANCELLED"} - if not pref.check_valid_settings_gen(): + cmd = raas_jobs.CmdGetPidDir( + preferences().raas_pid_name_barbora_cpu.upper()) + if len(cmd) > 0: + # server = raas_config.GetDAServer(context) + server = raas_config.GetServerFromType("BARBORA") + res = raas_render.ssh_command_sync(server, cmd) + preferences().raas_pid_dir_barbora_cpu = res.strip() + + #break + + except Exception as e: + import traceback + traceback.print_exc() + + self.report({'ERROR'}, "Problem with %s: %s: %s" % + (self.bl_label, e.__class__, e)) + # return {"CANCELLED"} + # success = False + + self.report({'INFO'}, "'%s' finished" % (self.bl_label)) + return {"FINISHED"} + + +class RAAS_OT_find_pid_dir_barbora_gpu(Operator): + bl_idname = 'raas.find_pid_dir_barbora_gpu' + bl_label = 'Find Dir' + bl_description = ("Find") + + def execute(self, context): + # success = True + + # for cl in raas_config.Cluster_items: + try: + if not preferences().check_valid_settings(type='PROJECT_DIR'): return {"CANCELLED"} - pref.raas_da_username = pref.raas_gen_username - pref.raas_private_key_path = pref.raas_gen_private_key_path - pref.raas_da_password = pref.raas_gen_password - pref.raas_pid = pref.raas_gen_pid - pref.raas_project_group = pref.raas_da_username + cmd = raas_jobs.CmdGetPidDir( + preferences().raas_pid_name_barbora_gpu.upper()) + if len(cmd) > 0: + # server = raas_config.GetDAServer(context) + server = raas_config.GetServerFromType("BARBORA") + res = raas_render.ssh_command_sync(server, cmd) + preferences().raas_pid_dir_barbora_gpu = res.strip() + + # break + + except Exception as e: + import traceback + traceback.print_exc() - # TODO - if not pref.check_valid_settings(type='PROJECT_DIR'): - return {"CANCELLED"} + self.report({'ERROR'}, "Problem with %s: %s: %s" % + (self.bl_label, e.__class__, e)) + # return {"CANCELLED"} + # success = False + + self.report({'INFO'}, "'%s' finished" % (self.bl_label)) + return {"FINISHED"} - cmd = raas_jobs.CmdGetPidDir(pref.raas_pid.upper()) + +class RAAS_OT_find_pid_dir_karolina_cpu(Operator): + bl_idname = 'raas.find_pid_dir_karolina_cpu' + bl_label = 'Find Dir' + bl_description = ("Find") + + def execute(self, context): + # success = True + + # for cl in raas_config.Cluster_items: + try: + if not preferences().check_valid_settings(type='PROJECT_DIR'): + return {"CANCELLED"} + + cmd = raas_jobs.CmdGetPidDir( + preferences().raas_pid_name_karolina_cpu.upper()) if len(cmd) > 0: - server = raas_config.GetDAServer(context) + # server = raas_config.GetDAServer(context) + server = raas_config.GetServerFromType("KAROLINA") res = raas_render.ssh_command_sync(server, cmd) - pref.raas_pid_dir = res.strip() + preferences().raas_pid_dir_karolina_cpu = res.strip() + + # break except Exception as e: import traceback traceback.print_exc() - self.report({'ERROR'}, "Problem with %s: %s: %s" % (self.bl_label, e.__class__, e)) - return {"CANCELLED"} + self.report({'ERROR'}, "Problem with %s: %s: %s" % + (self.bl_label, e.__class__, e)) + # return {"CANCELLED"} + # success = False self.report({'INFO'}, "'%s' finished" % (self.bl_label)) - return {"FINISHED"} + return {"FINISHED"} + -class RAAS_OT_find_pid_dir(Operator): - bl_idname = 'raas.find_pid_dir' - bl_label = 'Find Project Dir' - bl_description = ("Find Project Dir") +class RAAS_OT_find_pid_dir_karolina_gpu(Operator): + bl_idname = 'raas.find_pid_dir_karolina_gpu' + bl_label = 'Find Dir' + bl_description = ("Find") def execute(self, context): - #success = True + # success = True - for cl in raas_config.Cluster_items: - try: - if not preferences().check_valid_settings(type='PROJECT_DIR'): - return {"CANCELLED"} + # for cl in raas_config.Cluster_items: + try: + if not preferences().check_valid_settings(type='PROJECT_DIR'): + return {"CANCELLED"} - cmd = raas_jobs.CmdGetPidDir(preferences().raas_pid.upper()) - if len(cmd) > 0: - #server = raas_config.GetDAServer(context) - server = raas_config.GetServerFromType(cl[0]) - res = raas_render.ssh_command_sync(server, cmd) - preferences().raas_pid_dir = res.strip() + cmd = raas_jobs.CmdGetPidDir( + preferences().raas_pid_name_karolina_gpu.upper()) + if len(cmd) > 0: + # server = raas_config.GetDAServer(context) + server = raas_config.GetServerFromType("KAROLINA") + res = raas_render.ssh_command_sync(server, cmd) + preferences().raas_pid_dir_karolina_gpu = res.strip() - break + # break - except Exception as e: - import traceback - traceback.print_exc() + except Exception as e: + import traceback + traceback.print_exc() - self.report({'ERROR'}, "Problem with %s: %s: %s" % (self.bl_label, e.__class__, e)) - #return {"CANCELLED"} - #success = False + self.report({'ERROR'}, "Problem with %s: %s: %s" % + (self.bl_label, e.__class__, e)) + # return {"CANCELLED"} + # success = False self.report({'INFO'}, "'%s' finished" % (self.bl_label)) return {"FINISHED"} + class RAAS_OT_install_scripts(Operator): bl_idname = 'raas.install_scripts' bl_label = 'Install scripts on the cluster' bl_description = ("Install scripts") def execute(self, context): - #success = True + # success = True for cl in raas_config.Cluster_items: try: if not preferences().check_valid_settings(type='INSTALL_SCRIPTS'): - return {"CANCELLED"} + return {"CANCELLED"} - cmd = raas_config.GetGitAddonCommand(preferences().raas_scripts_repository, preferences().raas_scripts_repository_branch) + cmd = raas_config.GetGitAddonCommand(preferences( + ).raas_scripts_repository, preferences().raas_scripts_repository_branch) if len(cmd) > 0: - #raas_render.ssh_command_sync('barbora.it4i.cz', cmd) - #raas_render.ssh_command_sync('karolina.it4i.cz', cmd) + # raas_render.ssh_command_sync('barbora.it4i.cz', cmd) + # raas_render.ssh_command_sync('karolina.it4i.cz', cmd) server = raas_config.GetServerFromType(cl[0]) raas_render.ssh_command_sync(server, cmd) preferences().raas_scripts_installed = True @@ -292,9 +464,10 @@ class RAAS_OT_install_scripts(Operator): import traceback traceback.print_exc() - self.report({'ERROR'}, "Problem with %s: %s: %s" % (self.bl_label, e.__class__, e)) - #return {"CANCELLED"} - #success = False + self.report({'ERROR'}, "Problem with %s: %s: %s" % + (self.bl_label, e.__class__, e)) + # return {"CANCELLED"} + # success = False self.report({'INFO'}, "'%s' finished" % (self.bl_label)) return {"FINISHED"} @@ -319,12 +492,14 @@ class RAAS_OT_install_scripts(Operator): # import traceback # traceback.print_exc() -# self.report({'ERROR'}, "Problem with %s: %s: %s" % (self.bl_label, e.__class__, e)) +# self.report({'ERROR'}, "Problem with %s: %s: %s" % (self.bl_label, e.__class__, e)) # return {"CANCELLED"} # self.report({'INFO'}, "'%s' finished" % (self.bl_label)) -# return {"FINISHED"} +# return {"FINISHED"} ################################################################## + + class RAAS_OT_install_dependencies(Operator): bl_idname = 'raas.install_dependencies' bl_label = 'Install dependencies' @@ -339,9 +514,9 @@ class RAAS_OT_install_dependencies(Operator): install_and_import_module(module_name=dependency.module, package_name=dependency.package, global_name=dependency.name) - - #enable_internal_addons() - #install_external_addons() + + # enable_internal_addons() + # install_external_addons() except (subprocess.CalledProcessError, ImportError) as err: self.report({"ERROR"}, str(err)) @@ -350,12 +525,13 @@ class RAAS_OT_install_dependencies(Operator): preferences().dependencies_installed = True # Register the panels, operators, etc. since dependencies are installed - #from . import sim_scene - #sim_scene.register() + # from . import sim_scene + # sim_scene.register() self.report({'INFO'}, "'%s' finished" % (self.bl_label)) return {"FINISHED"} + class RAAS_OT_update_dependencies(Operator): bl_idname = 'raas.update_dependencies' bl_label = 'Update dependencies' @@ -370,9 +546,9 @@ class RAAS_OT_update_dependencies(Operator): install_and_import_module(module_name=dependency.module, package_name=dependency.package, global_name=dependency.name) - - #enable_internal_addons() - #install_external_addons() + + # enable_internal_addons() + # install_external_addons() except (subprocess.CalledProcessError, ImportError) as err: self.report({"ERROR"}, str(err)) @@ -381,12 +557,13 @@ class RAAS_OT_update_dependencies(Operator): preferences().dependencies_installed = True # Register the panels, operators, etc. since dependencies are installed - #from . import sim_scene - #sim_scene.register() + # from . import sim_scene + # sim_scene.register() self.report({'INFO'}, "'%s' finished" % (self.bl_label)) - return {"FINISHED"} -################################################## + return {"FINISHED"} +################################################## + class RaasPreferences(AddonPreferences): bl_idname = ADDON_NAME @@ -410,7 +587,7 @@ class RaasPreferences(AddonPreferences): # raas_server: StringProperty( # name='RaaS Server', # default='' - # ) + # ) raas_username: StringProperty( name='Username', @@ -425,18 +602,84 @@ class RaasPreferences(AddonPreferences): subtype='PASSWORD' ) - raas_pid: StringProperty( + ####################### BARBORA###################################### + + raas_pid_name_barbora_cpu: StringProperty( + name='Project ID', + description='IT4Innovations computing resource allocated by the project allocation committee to the primary investigator, e.g. OPEN-XX-XX, DD-XX-XX', + default='' + ) + + raas_pid_queue_barbora_cpu: StringProperty( + name='Project Queue', + description='The queue for running the job on the cluster, e.g. qcpu, qgpu', + default='qcpu' + ) + + raas_pid_dir_barbora_cpu: StringProperty( + name='Project Dir', + description='The PROJECT data storage is a central storage for projects/users data on IT4Innovations, e.g. /mnt/projX/OPEN-XX-XX, /mnt/projX/DD-XX-XX', + default='' + ) + + raas_pid_name_barbora_gpu: StringProperty( name='Project ID', description='IT4Innovations computing resource allocated by the project allocation committee to the primary investigator, e.g. OPEN-XX-XX, DD-XX-XX', default='' ) - raas_pid_dir: StringProperty( + raas_pid_queue_barbora_gpu: StringProperty( + name='Project Queue', + description='The queue for running the job on the cluster, e.g. qcpu, qgpu', + default='qgpu' + ) + + raas_pid_dir_barbora_gpu: StringProperty( name='Project Dir', description='The PROJECT data storage is a central storage for projects/users data on IT4Innovations, e.g. /mnt/projX/OPEN-XX-XX, /mnt/projX/DD-XX-XX', default='' ) + ####################### KAROLINA###################################### + + raas_pid_name_karolina_cpu: StringProperty( + name='Project ID', + description='IT4Innovations computing resource allocated by the project allocation committee to the primary investigator, e.g. OPEN-XX-XX, DD-XX-XX', + default='' + ) + + raas_pid_queue_karolina_cpu: StringProperty( + name='Project Queue', + description='The queue for running the job on the cluster, e.g. qcpu, qgpu', + default='qcpu' + ) + + raas_pid_dir_karolina_cpu: StringProperty( + name='Project Dir', + description='The PROJECT data storage is a central storage for projects/users data on IT4Innovations, e.g. /mnt/projX/OPEN-XX-XX, /mnt/projX/DD-XX-XX', + default='' + ) + + raas_pid_name_karolina_gpu: StringProperty( + name='Project ID', + description='IT4Innovations computing resource allocated by the project allocation committee to the primary investigator, e.g. OPEN-XX-XX, DD-XX-XX', + default='' + ) + + raas_pid_queue_karolina_gpu: StringProperty( + name='Project Queue', + description='The queue for running the job on the cluster, e.g. qcpu, qgpu', + default='qgpu' + ) + + raas_pid_dir_karolina_gpu: StringProperty( + name='Project Dir', + description='The PROJECT data storage is a central storage for projects/users data on IT4Innovations, e.g. /mnt/projX/OPEN-XX-XX, /mnt/projX/DD-XX-XX', + default='' + ) + + ############################################################# + raas_job_storage_path: StringProperty( name='Local Storage Path', description='Path where to store job files', @@ -453,15 +696,15 @@ class RaasPreferences(AddonPreferences): # default=True # ) - raas_ssh_library : EnumProperty( + raas_ssh_library: EnumProperty( name='SSH Library', - items=raas_config.ssh_library_items - ) + items=raas_config.ssh_library_items + ) - raas_account_type : EnumProperty( + raas_account_type: EnumProperty( name='Account Type', items=raas_config.account_types_items - ) + ) raas_use_direct_access: BoolProperty( name='Use Direct Access', @@ -471,8 +714,8 @@ class RaasPreferences(AddonPreferences): raas_use_xorg: BoolProperty( name='Use Xorg', default=False - ) - + ) + raas_private_key_path: StringProperty( name='Private Key Path', description='Private Key Path', @@ -501,7 +744,7 @@ class RaasPreferences(AddonPreferences): description='Gen. Private Key Path', subtype='FILE_PATH', default='' - ) + ) raas_gen_public_key_path: StringProperty( name='Gen. Public Key Path', @@ -509,7 +752,7 @@ class RaasPreferences(AddonPreferences): subtype='FILE_PATH', default='' ) - + raas_scripts_repository: StringProperty( name='Repository', default='https://code.it4i.cz/raas/bheappe.git' @@ -524,11 +767,11 @@ class RaasPreferences(AddonPreferences): default=False ) - raas_gen_pid: StringProperty( - name='Project ID', - default='' - ) - + # raas_gen_pid: StringProperty( + # name='Project ID', + # default='' + # ) + raas_gen_username: StringProperty( name='Username', default='' @@ -540,81 +783,97 @@ class RaasPreferences(AddonPreferences): subtype='PASSWORD' ) - def check_valid_settings(self, type = 'NONE'): - if len(self.raas_pid) == 0: - show_message_box(message='Project ID is not set in preferences', icon='ERROR') - return False + def check_valid_settings(self, type='NONE'): + # if len(self.raas_pid) == 0: + # show_message_box( + # message='Project ID is not set in preferences', icon='ERROR') + # return False if self.raas_use_direct_access: if self.raas_ssh_library == 'PARAMIKO': if len(self.raas_da_username) == 0: - show_message_box(message='Username is not set in preferences', icon='ERROR') + show_message_box( + message='Username is not set in preferences', icon='ERROR') return False if len(self.raas_private_key_path) == 0: - show_message_box(message='Private Key File is not set in preferences', icon='ERROR') + show_message_box( + message='Private Key File is not set in preferences', icon='ERROR') return False - if len(self.raas_da_password) == 0: - show_message_box(message='Key Passphrase is not set in preferences', icon='ERROR') - return False + # if len(self.raas_da_password) == 0: + # show_message_box(message='Key Passphrase is not set in preferences', icon='ERROR') + # return False + + # if len(self.raas_pid_dir) == 0 and type != 'PROJECT_DIR' and type != 'INSTALL_SCRIPTS': + # show_message_box( + # message='Project Dir is not set in preferences', icon='ERROR') + # return False - if len(self.raas_pid_dir) == 0 and type != 'PROJECT_DIR' and type != 'INSTALL_SCRIPTS': - show_message_box(message='Project Dir is not set in preferences', icon='ERROR') - return False - if not self.raas_scripts_installed and type != 'PROJECT_DIR' and type != 'INSTALL_SCRIPTS': - show_message_box(message='Scripts are not installed', icon='ERROR') + show_message_box( + message='Scripts are not installed', icon='ERROR') return False if len(self.raas_scripts_repository) == 0 or len(self.raas_scripts_repository_branch) == 0: - show_message_box(message='Git repository is not set in preferences', icon='ERROR') + show_message_box( + message='Git repository is not set in preferences', icon='ERROR') return False else: if len(self.raas_username) == 0: - show_message_box(message='Username is not set in preferences', icon='ERROR') + show_message_box( + message='Username is not set in preferences', icon='ERROR') return False if len(self.raas_password) == 0: - show_message_box(message='Password is not set in preferences', icon='ERROR') + show_message_box( + message='Password is not set in preferences', icon='ERROR') return False - + if not self.dependencies_installed: - show_message_box(message='Dependencies are not installed', icon='ERROR') + show_message_box( + message='Dependencies are not installed', icon='ERROR') return False if not self.raas_job_storage_path and type != 'PROJECT_DIR' and type != 'INSTALL_SCRIPTS': - show_message_box(message='Local Storage Path is not set in preferences', icon='ERROR') - return False + show_message_box( + message='Local Storage Path is not set in preferences', icon='ERROR') + return False return True - def check_valid_settings_gen(self, type = 'NONE'): + def check_valid_settings_gen(self, type='NONE'): if not self.dependencies_installed: - show_message_box(message='Dependencies are not installed', icon='ERROR') + show_message_box( + message='Dependencies are not installed', icon='ERROR') return False - if len(self.raas_gen_pid) == 0: - show_message_box(message='Project ID is not set in the generate SSH keys section', icon='ERROR') - return False + # if len(self.raas_gen_pid) == 0: + # show_message_box( + # message='Project ID is not set in the generate SSH keys section', icon='ERROR') + # return False if len(self.raas_gen_username) == 0: - show_message_box(message='Username is not set in the generate SSH keys section', icon='ERROR') + show_message_box( + message='Username is not set in the generate SSH keys section', icon='ERROR') return False if len(self.raas_gen_public_key_path) == 0 and type != 'GENERATE': - show_message_box(message='Public Key File is not set in the generate SSH keys section', icon='ERROR') + show_message_box( + message='Public Key File is not set in the generate SSH keys section', icon='ERROR') return False if len(self.raas_gen_private_key_path) == 0 and type != 'GENERATE': - show_message_box(message='Private Key File is not set in the generate SSH keys section', icon='ERROR') + show_message_box( + message='Private Key File is not set in the generate SSH keys section', icon='ERROR') return False if len(self.raas_gen_password) == 0: - show_message_box(message='Key Passphrase is not set in the generate SSH keys section', icon='ERROR') - return False + show_message_box( + message='Key Passphrase is not set in the generate SSH keys section', icon='ERROR') + return False - return True + return True def reset_messages(self): self.ok_message = '' @@ -625,49 +884,49 @@ class RaasPreferences(AddonPreferences): box = layout.box() - raas_pid = box.split(**factor(0.25), align=True) - raas_pid.label(text='Project ID:') - pid_box = raas_pid.row(align=True) - pid_box.prop(self, 'raas_pid', text='') + # raas_pid = box.split(**factor(0.25), align=True) + # raas_pid.label(text='Project ID:') + # pid_box = raas_pid.row(align=True) + # pid_box.prop(self, 'raas_pid', text='') if self.raas_use_direct_access == True: if self.raas_ssh_library == 'PARAMIKO': auth_split = box.split(**factor(0.25), align=True) auth_split.label(text='Username:') - user_box = auth_split.row(align=True) + user_box = auth_split.row(align=True) user_box.prop(self, 'raas_da_username', text='') pkey_split = box.split(**factor(0.25), align=True) pkey_split.label(text='Private Key File:') - user_box = pkey_split.row(align=True) + user_box = pkey_split.row(align=True) user_box.prop(self, 'raas_private_key_path', text='') auth_split = box.split(**factor(0.25), align=True) auth_split.label(text='Key Passphrase:') - user_box = auth_split.row(align=True) - user_box.prop(self, 'raas_da_password', text='') - - raas_pid_dir = box.split(**factor(0.25), align=True) - raas_pid_dir.label(text='Project Dir:') - pid_dir_box = raas_pid_dir.row(align=True) - pid_dir_box.prop(self, 'raas_pid_dir', text='') - pid_dir_box.operator(RAAS_OT_find_pid_dir.bl_idname, icon="CONSOLE") - else: + user_box = auth_split.row(align=True) + user_box.prop(self, 'raas_da_password', text='') + + # raas_pid_dir = box.split(**factor(0.25), align=True) + # raas_pid_dir.label(text='Project Dir:') + # pid_dir_box = raas_pid_dir.row(align=True) + # pid_dir_box.prop(self, 'raas_pid_dir', text='') + # pid_dir_box.operator(RAAS_OT_find_pid_dir.bl_idname, icon="CONSOLE") + else: # raas_server = box.split(**factor(0.25), align=True) # raas_server.label(text='Server:') - # user_box = raas_server.row(align=True) + # user_box = raas_server.row(align=True) # user_box.prop(self, 'raas_server', text='') auth_split = box.split(**factor(0.25), align=True) auth_split.label(text='Username:') - user_box = auth_split.row(align=True) + user_box = auth_split.row(align=True) user_box.prop(self, 'raas_username', text='') auth_split = box.split(**factor(0.25), align=True) auth_split.label(text='Password:') - user_box = auth_split.row(align=True) - user_box.prop(self, 'raas_password', text='') + user_box = auth_split.row(align=True) + user_box.prop(self, 'raas_password', text='') box.operator('raas_auth.validate') @@ -678,8 +937,67 @@ class RaasPreferences(AddonPreferences): if self.ok_message: sub = layout.row() - sub.label(text=self.ok_message, icon='FILE_TICK') - + sub.label(text=self.ok_message, icon='FILE_TICK') + + box = layout.box() + + # BARBORA + # box = box.box() + # box.label("Barbora") + + # raas_pid_name_barbora_cpu + # raas_pid_queue_barbora_cpu + # raas_pid_dir_barbora_cpu + raas_pid = box.split(**factor(0.25), align=True) + raas_pid.label(text='Barbora CPU:') + pid_box = raas_pid.row(align=True) + pid_box.prop(self, 'raas_pid_name_barbora_cpu', text='Name') + pid_box.prop(self, 'raas_pid_queue_barbora_cpu', text='Queue') + pid_box.prop(self, 'raas_pid_dir_barbora_cpu', text='Dir') + pid_box.operator(RAAS_OT_find_pid_dir_barbora_cpu.bl_idname, icon="CONSOLE") + + # raas_pid_name_barbora_gpu + # raas_pid_queue_barbora_gpu + # raas_pid_dir_barbora_gpu + raas_pid = box.split(**factor(0.25), align=True) + raas_pid.label(text='Barbora GPU:') + pid_box = raas_pid.row(align=True) + pid_box.prop(self, 'raas_pid_name_barbora_gpu', text='Name') + pid_box.prop(self, 'raas_pid_queue_barbora_gpu', text='Queue') + pid_box.prop(self, 'raas_pid_dir_barbora_gpu', text='Dir') + pid_box.operator( + RAAS_OT_find_pid_dir_barbora_gpu.bl_idname, icon="CONSOLE") + + # KAROLINA + # box = box.box() + # box.label("Karolina") + + # raas_pid_name_karolina_cpu + # raas_pid_queue_karolina_cpu + # raas_pid_dir_karolina_cpu + raas_pid = box.split(**factor(0.25), align=True) + raas_pid.label(text='Karolina CPU:') + pid_box = raas_pid.row(align=True) + pid_box.prop(self, 'raas_pid_name_karolina_cpu', text='Name') + pid_box.prop(self, 'raas_pid_queue_karolina_cpu', text='Queue') + pid_box.prop(self, 'raas_pid_dir_karolina_cpu', text='Dir') + pid_box.operator( + RAAS_OT_find_pid_dir_karolina_cpu.bl_idname, icon="CONSOLE") + + # raas_pid_name_karolina_gpu + # raas_pid_queue_karolina_gpu + # raas_pid_dir_karolina_gpu + raas_pid = box.split(**factor(0.25), align=True) + raas_pid.label(text='Karolina GPU:') + pid_box = raas_pid.row(align=True) + pid_box.prop(self, 'raas_pid_name_karolina_gpu', text='Name') + pid_box.prop(self, 'raas_pid_queue_karolina_gpu', text='Queue') + pid_box.prop(self, 'raas_pid_dir_karolina_gpu', text='Dir') + pid_box.operator( + RAAS_OT_find_pid_dir_karolina_gpu.bl_idname, icon="CONSOLE") + + ### + box = layout.box() raas_box = box.column() @@ -687,116 +1005,123 @@ class RaasPreferences(AddonPreferences): path_split.label(text='Local Storage Path:') path_box = path_split.row(align=True) path_box.prop(self, 'raas_job_storage_path', text='') - props = path_box.operator('raas.explore_file_path', text='', icon='DISK_DRIVE') + props = path_box.operator( + 'raas.explore_file_path', text='', icon='DISK_DRIVE') props.path = self.raas_job_storage_path if self.raas_use_direct_access == True: raas_pgroup = box.split(**factor(0.25), align=True) raas_pgroup.label(text='Working Group:') - pgroup_box = raas_pgroup.row(align=True) + pgroup_box = raas_pgroup.row(align=True) pgroup_box.prop(self, 'raas_project_group', text='') raas_xorg = box.split(**factor(0.25), align=True) raas_xorg.label(text='Use Xorg:') - xorg_box = raas_xorg.row(align=True) - xorg_box.prop(self, 'raas_use_xorg', text='') + xorg_box = raas_xorg.row(align=True) + xorg_box.prop(self, 'raas_use_xorg', text='') - boxD = layout.box() + boxD = layout.box() boxD.label(text='Dependencies:') dependencies_installed = preferences().dependencies_installed if not dependencies_installed: boxD.label(text='Dependencies are not installed', icon='ERROR') - + if not dependencies_installed: - boxD.operator(RAAS_OT_install_dependencies.bl_idname, icon="CONSOLE") + boxD.operator(RAAS_OT_install_dependencies.bl_idname, + icon="CONSOLE") else: - boxD.operator(RAAS_OT_update_dependencies.bl_idname, icon="CONSOLE") + boxD.operator(RAAS_OT_update_dependencies.bl_idname, + icon="CONSOLE") - box = layout.box() + # box = layout.box() - par_split = box.split(**factor(0.25), align=True) - par_split.label(text='SSH Library:') - user_box = par_split.row(align=True) - user_box.prop(self, 'raas_ssh_library', text='') + # par_split = box.split(**factor(0.25), align=True) + # par_split.label(text='SSH Library:') + # user_box = par_split.row(align=True) + # user_box.prop(self, 'raas_ssh_library', text='') box = layout.box() da_split = box.split(**factor(0.25), align=True) da_split.label(text='Use Direct Access:') - user_box = da_split.row(align=True) - user_box.prop(self, 'raas_use_direct_access', text='') + user_box = da_split.row(align=True) + user_box.prop(self, 'raas_use_direct_access', text='') if self.raas_use_direct_access == True: - boxG = box.box() + boxG = box.box() boxG.label(text='Install scripts:') rep_split = boxG.split(**factor(0.25), align=True) rep_split.label(text='Git Repository:') rep_box1 = rep_split.row(align=True) - rep_box = rep_box1.row(align=True) - #rep_box.enabled = False + rep_box = rep_box1.row(align=True) + # rep_box.enabled = False rep_box.prop(self, 'raas_scripts_repository', text='') - rep_box = rep_box1.row(align=True) - #rep_box.enabled = True + rep_box = rep_box1.row(align=True) + # rep_box.enabled = True rep_box.prop(self, 'raas_scripts_repository_branch', text='') - + if self.raas_scripts_installed == False: if not self.raas_scripts_installed: boxG.label(text='Scripts are not installed', icon='ERROR') - boxG.operator(RAAS_OT_install_scripts.bl_idname, icon="CONSOLE", text="Install scripts on the cluster") + boxG.operator(RAAS_OT_install_scripts.bl_idname, + icon="CONSOLE", text="Install scripts on the cluster") else: - boxG.operator(RAAS_OT_install_scripts.bl_idname, icon="CONSOLE", text="Update scripts") + boxG.operator(RAAS_OT_install_scripts.bl_idname, + icon="CONSOLE", text="Update scripts") boxG = box.box() show_gen_split = boxG.split(**factor(0.25), align=True) show_gen_split.label(text='Generate SSH keys:') - user_box = show_gen_split.row(align=True) - user_box.prop(self, 'show_ssh_gen', text='') + user_box = show_gen_split.row(align=True) + user_box.prop(self, 'show_ssh_gen', text='') - if self.raas_ssh_library == 'PARAMIKO' and self.show_ssh_gen == True: - - #boxG.label(text='Generate SSH keys:') + if self.raas_ssh_library == 'PARAMIKO' and self.show_ssh_gen == True: - raas_pid = boxG.split(**factor(0.25), align=True) - raas_pid.label(text='Project ID:') - pid_box = raas_pid.row(align=True) - pid_box.prop(self, 'raas_gen_pid', text='') + # boxG.label(text='Generate SSH keys:') + + # raas_pid = boxG.split(**factor(0.25), align=True) + # raas_pid.label(text='Project ID:') + # pid_box = raas_pid.row(align=True) + # pid_box.prop(self, 'raas_gen_pid', text='') auth_split = boxG.split(**factor(0.25), align=True) auth_split.label(text='Username:') - user_box = auth_split.row(align=True) - user_box.prop(self, 'raas_gen_username', text='') + user_box = auth_split.row(align=True) + user_box.prop(self, 'raas_gen_username', text='') pkey_split = boxG.split(**factor(0.25), align=True) pkey_split.label(text='Public Key File:') - user_box = pkey_split.row(align=True) + user_box = pkey_split.row(align=True) user_box.prop(self, 'raas_gen_public_key_path', text='') pkey_split = boxG.split(**factor(0.25), align=True) pkey_split.label(text='Private Key File:') - user_box = pkey_split.row(align=True) + user_box = pkey_split.row(align=True) user_box.prop(self, 'raas_gen_private_key_path', text='') auth_split = boxG.split(**factor(0.25), align=True) auth_split.label(text='Key Passphrase:') - user_box = auth_split.row(align=True) - user_box.prop(self, 'raas_gen_password', text='') + user_box = auth_split.row(align=True) + user_box.prop(self, 'raas_gen_password', text='') - boxG.operator(RAAS_OT_generate_sshkey.bl_idname, icon="CONSOLE") + boxG.operator(RAAS_OT_generate_sshkey.bl_idname, + icon="CONSOLE") acc_split = boxG.split(**factor(0.25), align=True) acc_split.label(text='Account Type:') - acc_box = acc_split.row(align=True) - acc_box.prop(self, 'raas_account_type', text='') + acc_box = acc_split.row(align=True) + acc_box.prop(self, 'raas_account_type', text='') boxG.operator(RAAS_OT_upload_sshkey.bl_idname, icon="URL") - boxG = boxG.column() - boxG.label(text='Please wait a minute for the public key to install on all clusters before running Setup.') - boxG.operator(RAAS_OT_setup_sshkey.bl_idname, icon="COPY_ID") - - + # boxG = boxG.column() + # boxG.label( + # text='Please wait a minute for the public key to install on all clusters before running Setup.') + # boxG.operator(RAAS_OT_setup_sshkey.bl_idname, icon="COPY_ID") + + def ctx_preferences(): """Returns bpy.context.preferences in a 2.79-compatible way.""" try: @@ -804,16 +1129,18 @@ def ctx_preferences(): except AttributeError: return bpy.context.user_preferences + def preferences() -> RaasPreferences: - return ctx_preferences().addons[ADDON_NAME].preferences + return ctx_preferences().addons[ADDON_NAME].preferences + class RaasAuthValidate(async_loop.AsyncModalOperatorMixin, Operator): bl_idname = 'raas_auth.validate' bl_label = 'Validate' - #def execute(self, context): + # def execute(self, context): async def async_execute(self, context): - #from . import raas_pref + # from . import raas_pref addon_prefs = preferences() addon_prefs.reset_messages() @@ -823,41 +1150,45 @@ class RaasAuthValidate(async_loop.AsyncModalOperatorMixin, Operator): except: resp = None - #resp = await raas_server.get_token(addon_prefs.raas_username, addon_prefs.raas_password) + # resp = await raas_server.get_token(addon_prefs.raas_username, addon_prefs.raas_password) if resp and len(resp) == 36: addon_prefs.ok_message = 'Authentication token is valid.' else: addon_prefs.error_message = 'Authentication token is not valid!' - #return {'FINISHED'} - self.quit() + # return {'FINISHED'} + self.quit() + def register(): """register.""" bpy.utils.register_class(RaasPreferences) - bpy.utils.register_class(RaasAuthValidate) - bpy.utils.register_class(RAAS_OT_install_dependencies) + bpy.utils.register_class(RaasAuthValidate) + bpy.utils.register_class(RAAS_OT_install_dependencies) bpy.utils.register_class(RAAS_OT_update_dependencies) bpy.utils.register_class(RAAS_OT_generate_sshkey) bpy.utils.register_class(RAAS_OT_upload_sshkey) - bpy.utils.register_class(RAAS_OT_setup_sshkey) - - bpy.utils.register_class(RAAS_OT_find_pid_dir) + #bpy.utils.register_class(RAAS_OT_setup_sshkey) + + bpy.utils.register_class(RAAS_OT_find_pid_dir_barbora_cpu) + bpy.utils.register_class(RAAS_OT_find_pid_dir_barbora_gpu) + bpy.utils.register_class(RAAS_OT_find_pid_dir_karolina_cpu) + bpy.utils.register_class(RAAS_OT_find_pid_dir_karolina_gpu) bpy.utils.register_class(RAAS_OT_install_scripts) - #bpy.utils.register_class(RAAS_OT_update_scripts) - + # bpy.utils.register_class(RAAS_OT_update_scripts) try: for dependency in python_dependencies: - import_module(module_name=dependency.module, global_name=dependency.name) + import_module(module_name=dependency.module, + global_name=dependency.name) - #check_internal_addons() - #check_external_addons() + # check_internal_addons() + # check_external_addons() preferences().dependencies_installed = True except ModuleNotFoundError: - preferences().dependencies_installed = False + preferences().dependencies_installed = False return @@ -867,14 +1198,18 @@ def unregister(): bpy.utils.unregister_class(RaasAuthValidate) bpy.utils.unregister_class(RaasPreferences) - bpy.utils.unregister_class(RAAS_OT_install_dependencies) + bpy.utils.unregister_class(RAAS_OT_install_dependencies) bpy.utils.unregister_class(RAAS_OT_update_dependencies) bpy.utils.unregister_class(RAAS_OT_generate_sshkey) bpy.utils.unregister_class(RAAS_OT_upload_sshkey) - bpy.utils.unregister_class(RAAS_OT_setup_sshkey) - - bpy.utils.unregister_class(RAAS_OT_find_pid_dir) + #bpy.utils.unregister_class(RAAS_OT_setup_sshkey) + + bpy.utils.unregister_class(RAAS_OT_find_pid_dir_barbora_cpu) + bpy.utils.unregister_class(RAAS_OT_find_pid_dir_barbora_gpu) + bpy.utils.unregister_class(RAAS_OT_find_pid_dir_karolina_cpu) + bpy.utils.unregister_class(RAAS_OT_find_pid_dir_karolina_gpu) + bpy.utils.unregister_class(RAAS_OT_install_scripts) - #bpy.utils.unregister_class(RAAS_OT_update_scripts) + # bpy.utils.unregister_class(RAAS_OT_update_scripts) return diff --git a/bheappe/raas_render.py b/bheappe/raas_render.py index 7bfd835..81c731e 100644 --- a/bheappe/raas_render.py +++ b/bheappe/raas_render.py @@ -123,7 +123,10 @@ def get_direct_access_remote_storage(context): if len(project_group) == 0: project_group = pref.raas_da_username - return raas_config.GetDAClusterPath(context, pref.raas_pid_dir, pref.raas_pid.lower()) + '/' + project_group + pid_name, pid_queue, pid_dir = raas_config.GetCurrentPidInfo( + context, raas_pref.preferences()) + + return raas_config.GetDAClusterPath(context, pid_dir, pid_name.lower()) + '/' + project_group ################################ @@ -166,11 +169,12 @@ class RAAS_PT_simplify(RaasButtonsPanel, Panel): # check values pref = raas_pref.preferences() if pref.raas_use_direct_access: + pid_name, pid_queue, pid_dir = raas_config.GetCurrentPidInfo(context, raas_pref.preferences()) if pref.raas_ssh_library == 'PARAMIKO': - if len(pref.raas_pid) == 0 or len(pref.raas_da_username) == 0 or len(pref.raas_private_key_path) == 0 or len(pref.raas_da_password) == 0 or len(pref.raas_pid_dir) == 0 or not pref.raas_scripts_installed: + if len(pid_name) == 0 or len(pid_queue) == 0 or len(pref.raas_da_username) == 0 or len(pref.raas_private_key_path) == 0 or len(pid_dir) == 0 or not pref.raas_scripts_installed: box.label(text='BHeappe is not set in preferences', icon='ERROR') else: - if len(pref.raas_pid) == 0 or len(pref.raas_pid_dir) == 0 or not pref.raas_scripts_installed: + if len(pid_name) == 0 or len(pid_queue) == 0 or len(pid_dir) == 0 or not pref.raas_scripts_installed: box.label(text='BHeappe is not set in preferences', icon='ERROR') if not pref.dependencies_installed: @@ -906,7 +910,7 @@ class RAAS_OT_dash_barbora( Operator): """dash_barbora""" bl_idname = 'raas.dash_barbora' - bl_label = 'Dashborard of the Barbora cluster' + bl_label = 'Dashboard of the Barbora cluster' async def async_execute(self, context): import webbrowser @@ -920,13 +924,28 @@ class RAAS_OT_dash_karolina( Operator): """dash_karolina""" bl_idname = 'raas.dash_karolina' - bl_label = 'Dashborard of the Karolina cluster' + bl_label = 'Dashboard of the Karolina cluster' async def async_execute(self, context): import webbrowser webbrowser.open('https://extranet.it4i.cz/dash/karolina', new=2) - self.quit() + self.quit() + + +class RAAS_OT_dash_grafana( + async_loop.AsyncModalOperatorMixin, + AuthenticatedRaasOperatorMixin, + Operator): + """dash_grafana""" + bl_idname = 'raas.dash_grafana' + bl_label = 'Dashboard of the clusters' + + async def async_execute(self, context): + import webbrowser + webbrowser.open('https://extranet.it4i.cz/grafana', new=2) + + self.quit() class RAAS_OT_submit_job( async_loop.AsyncModalOperatorMixin, @@ -1244,11 +1263,14 @@ class RAAS_PT_MessageOfTheDay(RaasButtonsPanel, Panel): layout = self.layout box = layout.box() - box.operator(RAAS_OT_dash_barbora.bl_idname, - text='Barbora', icon='WORLD') + # box.operator(RAAS_OT_dash_barbora.bl_idname, + # text='Barbora', icon='WORLD') + + # box.operator(RAAS_OT_dash_karolina.bl_idname, + # text='Karolina', icon='WORLD') - box.operator(RAAS_OT_dash_karolina.bl_idname, - text='Karolina', icon='WORLD') + box.operator(RAAS_OT_dash_grafana.bl_idname, + text='Grafana', icon='WORLD') # class RAAS_PT_Report(RaasButtonsPanel, Panel): # bl_label = "Report" diff --git a/bheappe/raas_server.py b/bheappe/raas_server.py index 676315a..408dadb 100644 --- a/bheappe/raas_server.py +++ b/bheappe/raas_server.py @@ -28,6 +28,7 @@ import asyncio #import aiohttp import json import requests +import bpy log = logging.getLogger(__name__) @@ -42,7 +43,9 @@ def get_endpoint(endpoint_path=None): import urllib.parse import functools - base_url = raas_config.GetHEAPPEServer(raas_pref.preferences().raas_pid.lower()) + #base_url = raas_config.GetHEAPPEServer(raas_pref.preferences().raas_pid.lower()) + pid_name, pid_queue, pid_dir = raas_config.GetCurrentPidInfo(bpy.context, raas_pref.preferences()) + base_url = raas_config.GetHEAPPEServer(pid_name.lower()) # urljoin() is None-safe for the 2nd parameter. return urllib.parse.urljoin(base_url, endpoint_path) diff --git a/builds/bheappe.zip b/builds/bheappe.zip index 545ac2bd75dce272b496b7697561fdf4545f14f3..5c42942166bd62595634ccd9b2aab6ae1745bbdf 100644 GIT binary patch delta 37193 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 CZt))g delta 36417 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 -- GitLab