raas_render.py 50.8 KB
Newer Older
strakpe's avatar
strakpe committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

Milan Jaros's avatar
Milan Jaros committed
19
# (c) 2021 IT4Innovations, VSB-TUO
strakpe's avatar
strakpe committed
20
21
22

import functools
import logging
Milan Jaros's avatar
Milan Jaros committed
23
import tempfile
strakpe's avatar
strakpe committed
24
25
26
27
import os
from pathlib import Path, PurePath
import typing

Milan Jaros's avatar
Milan Jaros committed
28
29
30
31
################################
import time
################################

strakpe's avatar
strakpe committed
32
33
34
35
36
37
38
39
40
41
import bpy
from bpy.types import AddonPreferences, Operator, WindowManager, Scene, PropertyGroup, Panel
from bpy.props import StringProperty, EnumProperty, PointerProperty, BoolProperty, IntProperty

from bpy.types import Header, Menu

from . import async_loop
from . import raas_server
from . import raas_pref

Milan Jaros's avatar
Milan Jaros committed
42
43
44
from . import raas_jobs_barbora
from . import raas_jobs_salomon

strakpe's avatar
strakpe committed
45
46
47
48
49
import pathlib
import json

log = logging.getLogger(__name__)

Milan Jaros's avatar
Milan Jaros committed
50
################################
strakpe's avatar
strakpe committed
51
52
53
54

def redraw(self, context):
    if context.area is None:
        return
Milan Jaros's avatar
Milan Jaros committed
55
56
57
58
59
60
61
62
63
64
    context.area.tag_redraw() 

# def show_message_box(message = "", title = "BHeappe", type = 'ERROR'):

#     def draw(self, context):
#         self.layout.label(message)

#     bpy.context.window_manager.popup_menu(draw, title = title, icon = type)

#     #self.report({type}, message)
strakpe's avatar
strakpe committed
65
66
67
68
69
70
71

################################    

def get_pref_storage_dir():
    pref = raas_pref.preferences()
    return pref.raas_job_storage_path

Milan Jaros's avatar
Milan Jaros committed
72
73
74
75
def get_ssh_key_file():
    ssh_key_local = Path(tempfile.gettempdir()) / 'heappe_key'
    return ssh_key_local 

strakpe's avatar
strakpe committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def get_job_local_storage(job_name):
    local_storage = Path(get_pref_storage_dir()) / job_name
    return local_storage     

def get_job_local_storage_in(job_name):
    local_storage_in = Path(get_pref_storage_dir()) / job_name / 'in'
    return local_storage_in    

def get_job_local_storage_out(job_name):
    local_storage_out = Path(get_pref_storage_dir()) / job_name / 'out'
    return local_storage_out  

def get_job_local_storage_log(job_name):
    local_storage_log = Path(get_pref_storage_dir()) / job_name / 'log'
    return local_storage_log     

def get_job_remote_storage_in(job_name):
    remote_storage_in = Path('in')
    return remote_storage_in   

Milan Jaros's avatar
Milan Jaros committed
96
97
98
99
def get_job_remote_storage(job_name):
    remote_storage_out = Path('.')
    return remote_storage_out

strakpe's avatar
strakpe committed
100
101
102
103
104
105
106
107
108
109
110
111
def get_job_remote_storage_out(job_name):
    remote_storage_out = Path('out')
    return remote_storage_out

def get_job_remote_storage_log(job_name):
    remote_storage_log = Path('log')
    return remote_storage_log    

def convert_path_to_linux(path)->str:
    p = str(path)
    return p.replace("\\","/")

Milan Jaros's avatar
Milan Jaros committed
112
113
114
115
def is_verbose_debug():
    import bpy
    return bpy.app.debug_value == 256

strakpe's avatar
strakpe committed
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
################################

class RaasButtonsPanel:
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "render"

    @classmethod
    def poll(cls, context):
        return (context.engine in cls.COMPAT_ENGINES)

class RAAS_PT_simplify(RaasButtonsPanel, Panel):
    bl_label = "BHeappe"
    bl_options = {'DEFAULT_CLOSED'}
    COMPAT_ENGINES = {'CYCLES'}

    def draw(self, context):
        #pass         
        layout = self.layout
        box = layout.box()
        #box.enabled = False

        row = box.row(align=True)
        row.enabled = False
        row.prop(context.window_manager, 'raas_status', text = 'Status')

        # Show current status of Raas.
        raas_status = context.window_manager.raas_status

        row = box.row(align=True)
        if raas_status in {'IDLE', 'ERROR' ,'DONE'}:
            row.enabled = False
        else:
            row.enabled = True

        row.prop(context.window_manager, 'raas_progress',
                    text=context.window_manager.raas_status_txt)
        row.operator(RAAS_OT_abort.bl_idname, text='', icon='CANCEL')
Milan Jaros's avatar
Milan Jaros committed
154
  
strakpe's avatar
strakpe committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

class AuthenticatedRaasOperatorMixin:
    """Checks credentials, to be used at the start of async_execute().

    Sets self.user_id to the current user's ID, and self.db_user to the user info dict,
    if authentication was succesful; sets both to None if not.
    """

    async def authenticate(self, context) -> bool:
        from . import raas_pref
        resp = await raas_server.get_token(raas_pref.preferences().raas_username, raas_pref.preferences().raas_password)
        if resp:
            self.token = resp
            return True
                    
        return False        

#############################################################################               
####################################JobManagement############################
#############################################################################   
Milan Jaros's avatar
Milan Jaros committed
175
176
177
178
179
180
181
		# Configuring = 1,
		# Submitted = 2,
		# Queued = 4,
		# Running = 8,
		# Finished = 16,
		# Failed = 32,
		# Canceled = 64
strakpe's avatar
strakpe committed
182
183

JobStateExt_items = [
Milan Jaros's avatar
Milan Jaros committed
184
185
186
187
188
189
190
    ("CONFIGURING", "Configuring", "", 1),
    ("SUBMITTED", "Submitted", "", 2),
    ("QUEUED", "Queued", "", 4),
    ("RUNNING", "Running", "", 8),
    ("FINISHED", "Finished", "", 16),
    ("FAILED", "Failed", "", 32),
    ("CANCELED", "Canceled", "", 64),
strakpe's avatar
strakpe committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
]	

JobPriorityExt_items = [
    ("CONFIGURING", "Configuring", "", 0),
    ("VERYLOW", "VeryLow", "", 1),
    ("LOW", "Low", "", 2),
    ("BELOWAVERAGE", "BelowAverage", "", 3),
    ("AVERAGE", "Average", "", 4),
    ("ABOVEAVERAGE", "AboveAverage", "", 5),
    ("HIGH", "High", "", 6),
    ("VERYHIGH", "VeryHigh", "", 7),
    ("CRITICAL", "Critical", "", 8),
]	

TaskStateExt_items = [
Milan Jaros's avatar
Milan Jaros committed
206
207
208
209
210
211
212
    ("CONFIGURING", "Configuring", "", 1),
    ("SUBMITTED", "Submitted", "", 2),
    ("QUEUED", "Queued", "", 4),
    ("RUNNING", "Running", "", 8),
    ("FINISHED", "Finished", "", 16),
    ("FAILED", "Failed", "", 32),
    ("CANCELED", "Canceled", "", 64),
strakpe's avatar
strakpe committed
213
214
215
216
217
218
219
]	

RenderType_items = [
    ("IMAGE", "Image", ""),
    ("ANIMATION", "Animation", ""),
]

Milan Jaros's avatar
Milan Jaros committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
FileType_items = [
    ("DEFAULT", "Default", ""),
    ("OTHER", "Other", ""),
]

Cluster_items = [
    ("SALOMON", "Salomon", ""),
    ("BARBORA", "Barbora", ""),
]

JobQueueSalomon_items = [
    ("ORIGCPU", "Blender2.91 CPU", ""),
#    ("MPP", "CyclesPhi CPU", ""),        
#    ("MIC", "CyclesPhi MIC", ""),
#    ("MICBUFFER", "CyclesPhi MIC + RenderBuffer", ""),
#    ("MPPBUFFER", "CyclesPhi MPP + RenderBuffer", ""),
#    ("MICINTERACTIVE", "CyclesPhi MIC + Interactive", ""),
]

JobQueueBarbora_items = [
    ("ORIGCPU", "Blender2.91 CPU", ""),    
    ("ORIGCUDA", "Blender2.91 CUDA", ""),
#    ("ORIGOPTIX", "Blender2.91 OPTIX", ""),        
#    ("GPU", "CyclesPhi GPU", ""),
#    ("GPUUNIMEM", "CyclesPhi GPU + UNIMEM", ""),    
    #("GPUBUFFER", "CyclesPhi GPU + RenderBuffer", ""),
    #("GPUINTERACTIVE", "CyclesPhi GPU + Interactive", ""),
strakpe's avatar
strakpe committed
247
248
249
250
]
  
####################################ListJobsForCurrentUser####################
class RAAS_PG_BlenderJobInfo(PropertyGroup):
Milan Jaros's avatar
Milan Jaros committed
251
    #job_id : bpy.props.IntProperty(name="JobId")
strakpe's avatar
strakpe committed
252
    job_name : bpy.props.StringProperty(name="JobName")
Milan Jaros's avatar
Milan Jaros committed
253
    job_email : bpy.props.StringProperty(name="Email")
Milan Jaros's avatar
Milan Jaros committed
254
    #job_priority : bpy.props.EnumProperty(items=JobPriorityExt_items,name="JobPriority",default='AVERAGE')
Milan Jaros's avatar
Milan Jaros committed
255
256
257
    job_project : bpy.props.StringProperty(name="Project Name",maxlen=25)
    job_walltime : bpy.props.IntProperty(name="Walltime [minutes]",default=30,min=1,max=2880)
    job_walltime_pre : bpy.props.IntProperty(name="Walltime Preprocessing [minutes]",default=10,min=1,max=2880)
Milan Jaros's avatar
Milan Jaros committed
258
259
260
261
262
263
    job_walltime_post : bpy.props.IntProperty(name="Walltime Postprocessing [minutes]",default=10,min=1,max=2880)    
    job_nodes : bpy.props.IntProperty(name="Nodes",default=1,min=1,max=8)          

    job_queue_salomon : bpy.props.EnumProperty(items=JobQueueSalomon_items,name="Queue")
    job_queue_barbora : bpy.props.EnumProperty(items=JobQueueBarbora_items,name="Queue")

strakpe's avatar
strakpe committed
264
265
266
    frame_start : bpy.props.IntProperty(name="FrameStart")
    frame_end : bpy.props.IntProperty(name="FrameEnd")
    frame_current : bpy.props.IntProperty(name="FrameCurrent")
Milan Jaros's avatar
Milan Jaros committed
267
    frame_step : bpy.props.IntProperty(name="FrameStep")
strakpe's avatar
strakpe committed
268

Milan Jaros's avatar
Milan Jaros committed
269
270
271
272
    render_type : bpy.props.EnumProperty(items=RenderType_items,name="Type")  
    cluster_type : bpy.props.EnumProperty(items=Cluster_items,name="Cluster")
    file_type : bpy.props.EnumProperty(items=FileType_items,name="File")
    blendfile_path : bpy.props.StringProperty(name="Blend", subtype='FILE_PATH')
strakpe's avatar
strakpe committed
273

Milan Jaros's avatar
Milan Jaros committed
274
275
276
277
class RAAS_PG_SubmittedTaskInfoExt(PropertyGroup):
    Id : bpy.props.IntProperty(name="Id")
    Name : bpy.props.StringProperty(name="Name")    

strakpe's avatar
strakpe committed
278
class RAAS_PG_SubmittedJobInfoExt(PropertyGroup):
Milan Jaros's avatar
Milan Jaros committed
279
280
281
282
283
284
285
286
287
288
289
290
291
    Id : bpy.props.IntProperty(name="Id")
    Name : bpy.props.StringProperty(name="Name")
    State : bpy.props.EnumProperty(items=JobStateExt_items,name="State")
    Priority : bpy.props.EnumProperty(items=JobPriorityExt_items,name="Priority",default='AVERAGE')
    Project : bpy.props.StringProperty(name="Project Name")
    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")
    Tasks: bpy.props.StringProperty(name="Tasks")

Milan Jaros's avatar
Milan Jaros committed
292
293
294
    #statePre : bpy.props.StringProperty(name="State Pre")
    #stateRen : bpy.props.StringProperty(name="State Ren")
    #statePost : bpy.props.StringProperty(name="State Post")
strakpe's avatar
strakpe committed
295
296
297

class RAAS_UL_SubmittedJobInfoExt(bpy.types.UIList):
    def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
Milan Jaros's avatar
Milan Jaros committed
298
299
300
301
        layout.label(text=('%d' % item.Id))
        #layout.label(text=item.Name)
        layout.label(text=item.Project)
        layout.label(text=item.State)     
strakpe's avatar
strakpe committed
302
303
304
        

            
Milan Jaros's avatar
Milan Jaros committed
305
306
307
308
309
310
311
312
313
314
315
316
#############################################################################    
async def _ssh(key_file, destination, port1, port2):
        """ Execute an ssh command """
        cmd = [
            'ssh',
            '-N',
            '-i', key_file,            
            '-L', port1,
            '-L', port2,
            destination,
            '&',
        ]
Milan Jaros's avatar
Milan Jaros committed
317
        #             '-q',             '-o', 'StrictHostKeyChecking=no',
Milan Jaros's avatar
Milan Jaros committed
318
319
320

        import asyncio
        loop = asyncio.get_event_loop()
Milan Jaros's avatar
Milan Jaros committed
321
        #, stdin=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
Milan Jaros's avatar
Milan Jaros committed
322
323
324
325
326
327
328
329
330
331
332
333
334
335
        process = await asyncio.create_subprocess_exec(*cmd, loop=loop)
        await process.wait()

        if process.returncode != 0 and is_verbose_debug() == True:
            print("ssh command failed: %s" % cmd)

async def connect_to_client(context, fileTransfer, job_id: int, token: str) -> None:
    """connect_to_client"""       

    data = {
        "SubmittedJobInfoId": job_id,
        "SessionCode": token
    }

Milan Jaros's avatar
Milan Jaros committed
336
    #allocated_nodes_ips = await raas_server.post("JobManagement/GetAllocatedNodesIPs", data)
Milan Jaros's avatar
Milan Jaros committed
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
    info_job = await raas_server.post("JobManagement/GetCurrentInfoForJob", data)
    all_params = info_job['AllParameters']
    allocated_nodes_ips = ''
    for line in all_params.split('\n'):
        if "exec_vnode" in line:
            allocated_nodes_ips = line.split('(')
            allocated_nodes_ips = allocated_nodes_ips[1].split(':')
            break

    print(allocated_nodes_ips)

    serverHostname = fileTransfer['ServerHostname']
    sharedBasepath = fileTransfer['SharedBasepath']
    credentials = fileTransfer['Credentials']
    username = credentials['UserName']

    key_file = str(get_ssh_key_file())
    destination = '%s@%s' % (username, serverHostname)
    print('connect to server')

    allocated_nodes_ips = allocated_nodes_ips[0]
    if 'mic' in allocated_nodes_ips:
        allocated_nodes_ips = '%s.head' % allocated_nodes_ips
    port1 = '7000:%s:7000' % (allocated_nodes_ips)
    port2 = '7001:%s:7001' % (allocated_nodes_ips)

    await _ssh(key_file, destination, port1, port2)

strakpe's avatar
strakpe committed
365
366
367
####################################FileTransfer#############################
#############################################################################  

Milan Jaros's avatar
Milan Jaros committed
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
async def _scp(key_file, source, destination):
        """ Execute an scp command """
        cmd = [
            'scp',
            '-i',  key_file,
            '-o', 'StrictHostKeyChecking=no',
            '-q',
            '-B',
            '-r',
            source, destination
        ]

        import asyncio
        loop = asyncio.get_event_loop()
        process = await asyncio.create_subprocess_exec(*cmd, loop=loop)
        await process.wait()

        if process.returncode != 0:
            if is_verbose_debug() == True:
Milan Jaros's avatar
Milan Jaros committed
387
                raise Exception("scp command failed: %s" % cmd)
Milan Jaros's avatar
Milan Jaros committed
388
            else:
Milan Jaros's avatar
Milan Jaros committed
389
                raise Exception("scp command failed: %s -> %s" % (source, destination))
Milan Jaros's avatar
Milan Jaros committed
390
391

async def start_transfer_files(context, job_id: int, token: str) -> None:
Milan Jaros's avatar
Milan Jaros committed
392
    """Start Transfer files."""   
strakpe's avatar
strakpe committed
393
394

    data = {
Milan Jaros's avatar
Milan Jaros committed
395
396
        "SubmittedJobInfoId": job_id,
        "SessionCode": token
strakpe's avatar
strakpe committed
397
398
399
400
    }

    fileTransfer = await raas_server.post("FileTransfer/GetFileTransferMethod", data)

Milan Jaros's avatar
Milan Jaros committed
401
402
    credentials = fileTransfer[raas_server.local_to_server_map["Credentials"]]
    pkey = credentials[raas_server.local_to_server_map["PrivateKey"]]
Milan Jaros's avatar
Milan Jaros committed
403
404
405
406
407
408
409
410
411
412
413
414
415
416
    key_file = str(get_ssh_key_file())
    with open(key_file, "w+") as fh:
        fh.write(pkey)

    import os
    os.chmod(key_file, 0o700)

    return fileTransfer


async def end_transfer_files(context, fileTransfer, job_id: int, token: str) -> None:
    """End Transfer files."""        
    
    key_file = str(get_ssh_key_file())
Milan Jaros's avatar
Milan Jaros committed
417
    #os.remove(key_file)
strakpe's avatar
strakpe committed
418
419

    data = {
Milan Jaros's avatar
Milan Jaros committed
420
421
422
        "SubmittedJobInfoId": job_id,
        "UsedTransferMethod": fileTransfer,
        "SessionCode": token
strakpe's avatar
strakpe committed
423
    }
Milan Jaros's avatar
Milan Jaros committed
424
425
    
    #import json
Milan Jaros's avatar
Milan Jaros committed
426
    data_json = raas_server.json_dumps(data)
Milan Jaros's avatar
Milan Jaros committed
427
    await raas_server.post_json("FileTransfer/EndFileTransfer", data_json)    
strakpe's avatar
strakpe committed
428

Milan Jaros's avatar
Milan Jaros committed
429
async def transfer_files(context, fileTransfer, job_local_dir: str, job_remote_dir: str, job_id: int, token: str, to_cluster) -> None:
strakpe's avatar
strakpe committed
430
431
    """Transfer files."""

Milan Jaros's avatar
Milan Jaros committed
432
433
434
435
    serverHostname = fileTransfer[raas_server.local_to_server_map["ServerHostname"]]
    sharedBasepath = fileTransfer[raas_server.local_to_server_map["SharedBasepath"]]
    credentials = fileTransfer[raas_server.local_to_server_map["Credentials"]]
    username = credentials[raas_server.local_to_server_map["UserName"]]
strakpe's avatar
strakpe committed
436

Milan Jaros's avatar
Milan Jaros committed
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
    key_file = str(get_ssh_key_file())
    
    if to_cluster == True:
        source = job_local_dir
        destination = '%s@%s:%s/%s' % (username, serverHostname, str(sharedBasepath), job_remote_dir)
        print('copy from %s to server' % (job_local_dir))
    else:
        destination = job_local_dir
        source = '%s@%s:%s/%s' % (username, serverHostname, str(sharedBasepath), job_remote_dir)
        print('copy from server to: %s' % (job_local_dir))

    await _scp(key_file, source, destination)    

async def transfer_files_to_cluster(context, fileTransfer, job_local_dir: str, job_remote_dir: str, job_id: int, token: str) -> None:
    """Transfer files."""

    await transfer_files(context, fileTransfer, job_local_dir, job_remote_dir, job_id, token, True)

async def transfer_files_from_cluster(context, fileTransfer, job_remote_dir: str, job_local_dir: str, job_id: int, token: str) -> None:
    """Transfer files."""

    await transfer_files(context, fileTransfer, job_local_dir, job_remote_dir, job_id, token, False)

strakpe's avatar
strakpe committed
460
461
462
463
464
##################################################################################  
class RAAS_OT_download_files(
                        async_loop.AsyncModalOperatorMixin,
                        AuthenticatedRaasOperatorMixin,                         
                        Operator):
Milan Jaros's avatar
Milan Jaros committed
465
    """download_files"""
strakpe's avatar
strakpe committed
466
467
468
469
470
471
472
473
474
475
476
477
478
479
    bl_idname = 'raas.download_files'
    bl_label = 'Download Files'

    #stop_upon_exception = True
    log = logging.getLogger('%s.RAAS_OT_download_files' % __name__)

    async def async_execute(self, context):

        if not await self.authenticate(context):
            return 

        idx = context.scene.raas_list_jobs_index 

        if idx != -1:
Milan Jaros's avatar
Milan Jaros committed
480
481
482
483
            try:
                item = context.scene.raas_list_jobs[idx]

                remote_storage_out = convert_path_to_linux(get_job_remote_storage(item.Name))
Milan Jaros's avatar
Milan Jaros committed
484
                #local_storage_out = get_job_local_storage_out(item.Name)
Milan Jaros's avatar
Milan Jaros committed
485
486
487
488
                local_storage_out = get_job_local_storage(item.Name)

                fileTransfer = await start_transfer_files(context, item.Id, self.token)
                
Milan Jaros's avatar
Milan Jaros committed
489
490
                #await transfer_files_from_cluster(context, fileTransfer, remote_storage_out, str(local_storage_out), item.Id, self.token)
                
Milan Jaros's avatar
Milan Jaros committed
491
                remote_storage_out = convert_path_to_linux(get_job_remote_storage_out(item.Name))
Milan Jaros's avatar
Milan Jaros committed
492
                #local_storage_out = get_job_local_storage_out(item.Name)
Milan Jaros's avatar
Milan Jaros committed
493
494
495
496
497
                local_storage_out = get_job_local_storage(item.Name)
                
                await transfer_files_from_cluster(context, fileTransfer, remote_storage_out, str(local_storage_out), item.Id, self.token)    

                remote_storage_log = convert_path_to_linux(get_job_remote_storage_log(item.Name))
Milan Jaros's avatar
Milan Jaros committed
498
                #local_storage_log = get_job_local_storage_log(item.Name)
Milan Jaros's avatar
Milan Jaros committed
499
500
501
502
503
                local_storage_log = get_job_local_storage(item.Name)
                
                await transfer_files_from_cluster(context, fileTransfer, remote_storage_log, str(local_storage_log), item.Id, self.token)  

                await end_transfer_files(context, fileTransfer, item.Id, self.token)
strakpe's avatar
strakpe committed
504
            
Milan Jaros's avatar
Milan Jaros committed
505
506
507
            except Exception: # as e:
                #print('Problem with downloading files:')
                #print(e)
Milan Jaros's avatar
Milan Jaros committed
508
509
                import traceback
                traceback.print_exc()
strakpe's avatar
strakpe committed
510

Milan Jaros's avatar
Milan Jaros committed
511
512
                self.report({'ERROR'}, "Problem with downloading files")

Milan Jaros's avatar
Milan Jaros committed
513
        self.quit()
strakpe's avatar
strakpe committed
514

Milan Jaros's avatar
Milan Jaros committed
515
516
517
518
519
520
521
class RAAS_OT_connect_to_client(
                        async_loop.AsyncModalOperatorMixin,
                        AuthenticatedRaasOperatorMixin,                         
                        Operator):
    """connect_to_client"""
    bl_idname = 'raas.connect_to_client'
    bl_label = 'Connect to client'
strakpe's avatar
strakpe committed
522

Milan Jaros's avatar
Milan Jaros committed
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
    #stop_upon_exception = True
    log = logging.getLogger('%s.RAAS_OT_connect_to_client' % __name__)

    async def async_execute(self, context):

        if not await self.authenticate(context):
            return 

        idx = context.scene.raas_list_jobs_index 

        if idx != -1:
            try:
                item = context.scene.raas_list_jobs[idx]

                fileTransfer = await start_transfer_files(context, item.Id, self.token)
                
                await connect_to_client(context, fileTransfer, item.Id, self.token)
strakpe's avatar
strakpe committed
540

Milan Jaros's avatar
Milan Jaros committed
541
542
543
            except Exception: # as e:
                #print('Problem with downloading files:')
                #print(e)
Milan Jaros's avatar
Milan Jaros committed
544
545
546
                import traceback
                traceback.print_exc()

Milan Jaros's avatar
Milan Jaros committed
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
                self.report({'ERROR'}, "Problem with connecting to the client")

        self.quit()  


class RAAS_OT_MessageOfTheDay(
                        async_loop.AsyncModalOperatorMixin,
                        AuthenticatedRaasOperatorMixin,                         
                        Operator):
    """Message of the day"""
    bl_idname = 'raas.message_of_the_day'
    bl_label = 'Message of the day'

    async def async_execute(self, context):
        import webbrowser
        webbrowser.open('https://www.it4i.cz/en/for-users/message-of-the-day', new=2)

        self.quit()      
strakpe's avatar
strakpe committed
565
566
567
568
569
570
571
572
573

class RAAS_OT_prepare_files(
                        async_loop.AsyncModalOperatorMixin,
                        AuthenticatedRaasOperatorMixin,                         
                        Operator):
    """prepare_files"""
    bl_idname = 'raas.prepare_files'
    bl_label = 'Prepare Files'

Milan Jaros's avatar
Milan Jaros committed
574
    #stop_upon_exception = True
strakpe's avatar
strakpe committed
575
576
    log = logging.getLogger('%s.RAAS_OT_prepare_files' % __name__)

Milan Jaros's avatar
Milan Jaros committed
577
    # quit_after_submit = BoolProperty()
strakpe's avatar
strakpe committed
578

Milan Jaros's avatar
Milan Jaros committed
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
    async def async_execute(self, context):  
        try:
            # Refuse to start if the file hasn't been saved. It's okay if
            # it's dirty, but we do need a filename and a location.
            if context.scene.raas_blender_job_info_new.file_type == 'DEFAULT':
                if not os.path.exists(context.blend_data.filepath):
                    self.report({'ERROR'}, 'Please save your Blend file before using '
                                        'the bheappe addon.')
                    self.quit()
                    return

                context.scene.raas_blender_job_info_new.blendfile_path = context.blend_data.filepath
            else:
                if not os.path.exists(context.scene.raas_blender_job_info_new.blendfile_path):
                    self.report({'ERROR'}, 'Please choose your Blend file.')
                    self.quit()
                    return
strakpe's avatar
strakpe committed
596

Milan Jaros's avatar
Milan Jaros committed
597
598
            if not await self.authenticate(context):
                return            
strakpe's avatar
strakpe committed
599

Milan Jaros's avatar
Milan Jaros committed
600
601
            #from ..blender import preferences
            scene = context.scene
strakpe's avatar
strakpe committed
602

Milan Jaros's avatar
Milan Jaros committed
603
604
605
606
607
608
            if context.scene.raas_blender_job_info_new.file_type == 'DEFAULT':
                # Save to a different file, specifically for Raas.
                context.window_manager.raas_status = 'SAVING'
                filepath = await self._save_blendfile(context)
            else: #OTHER
                filepath = Path(context.scene.raas_blender_job_info_new.blendfile_path).with_suffix('.blend')
strakpe's avatar
strakpe committed
609

Milan Jaros's avatar
Milan Jaros committed
610
611
612
613
            prefs = raas_pref.preferences()
            
            if context.scene.raas_blender_job_info_new.job_project is None or len(context.scene.raas_blender_job_info_new.job_project) == 0 :
                context.scene.raas_blender_job_info_new.job_project = filepath.stem            
strakpe's avatar
strakpe committed
614

Milan Jaros's avatar
Milan Jaros committed
615
616
617
618
619
620
621
622
623
624
            if context.scene.raas_blender_job_info_new.file_type == 'DEFAULT':
                # BAT-pack the files to the destination directory.
                #job_id = '%d' % context.scene.raas_list_jobs[context.scene.raas_list_jobs_index].id
                outdir, outfile, missing_sources, unique_dir, filepath_stem = await self.bat_pack(filepath, context.scene.raas_blender_job_info_new.job_project)
            else:
                from datetime import datetime
                dt = datetime.now().isoformat('-').replace(':', '').replace('.', '')
                unique_dir = '%s-%s' % (dt[0:19], context.scene.raas_blender_job_info_new.job_project)
                outdir = Path(prefs.raas_job_storage_path) / unique_dir / 'in'
                missing_sources = None
strakpe's avatar
strakpe committed
625

Milan Jaros's avatar
Milan Jaros committed
626
627
                from distutils.dir_util import copy_tree
                copy_tree(str(filepath.parent), str(outdir))
strakpe's avatar
strakpe committed
628

Milan Jaros's avatar
Milan Jaros committed
629
630
631
632
            context.scene.raas_blender_job_info_new.frame_step = context.scene.frame_step
            context.scene.raas_blender_job_info_new.frame_start = context.scene.frame_start
            context.scene.raas_blender_job_info_new.frame_end = context.scene.frame_end
            context.scene.raas_blender_job_info_new.frame_current = context.scene.frame_current
strakpe's avatar
strakpe committed
633

Milan Jaros's avatar
Milan Jaros committed
634
            context.scene.raas_blender_job_info_new.job_name = unique_dir       
Milan Jaros's avatar
Milan Jaros committed
635
636


Milan Jaros's avatar
Milan Jaros committed
637
638
            if context.scene.raas_blender_job_info_new.job_queue_salomon == 'MICINTERACTIVE' or context.scene.raas_blender_job_info_new.job_queue_barbora == 'GPUINTERACTIVE':
                context.scene.raas_blender_job_info_new.job_project = 'INTERACTIVE'    
strakpe's avatar
strakpe committed
639

Milan Jaros's avatar
Milan Jaros committed
640
641
642
643
644
645
646
647
            # Do a final report.
            if missing_sources:
                names = (ms.name for ms in missing_sources)
                self.report({'WARNING'}, 'Raas job created with missing files: %s' %
                            '; '.join(names
                            ))
            # else:
            #     self.report({'INFO'}, 'Raas job created.')
strakpe's avatar
strakpe committed
648
649


Milan Jaros's avatar
Milan Jaros committed
650
651
652
            await CreateJob(context, self.token)
            
            blender_job_info_new = context.scene.raas_blender_job_info_new
strakpe's avatar
strakpe committed
653

Milan Jaros's avatar
Milan Jaros committed
654
655
            local_storage_in = str(get_job_local_storage_in(blender_job_info_new.job_name))
            remote_storage_in = convert_path_to_linux(get_job_remote_storage_in(blender_job_info_new.job_name))
strakpe's avatar
strakpe committed
656

Milan Jaros's avatar
Milan Jaros committed
657
            submitted_job_info_ext_new = context.scene.raas_submitted_job_info_ext_new
Milan Jaros's avatar
Milan Jaros committed
658

Milan Jaros's avatar
Milan Jaros committed
659
660
661
            fileTransfer = await start_transfer_files(context, submitted_job_info_ext_new.Id, self.token)
            await transfer_files_to_cluster(context, fileTransfer, local_storage_in, remote_storage_in, submitted_job_info_ext_new.Id, self.token)
            await end_transfer_files(context, fileTransfer, submitted_job_info_ext_new.Id, self.token)
strakpe's avatar
strakpe committed
662

Milan Jaros's avatar
Milan Jaros committed
663
664
665
666
667
668
669
670
671
672
673
            await SubmitJob(context, self.token)
            await ListJobsForCurrentUser(context, self.token)

        except Exception: # as e:
            
            #print('Problem with downloading files:')
            #print(e)
            import traceback
            traceback.print_exc()

            self.report({'ERROR'}, "Problem with submitting of job")           
strakpe's avatar
strakpe committed
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728

        self.quit()

    async def _save_blendfile(self, context):
        """Save to a different file, specifically for Raas.

        We shouldn't overwrite the artist's file.
        We can compress, since this file won't be managed by SVN and doesn't need diffability.
        """

        render = context.scene.render

        # Remember settings we need to restore after saving.
        old_use_file_extension = render.use_file_extension
        old_use_overwrite = render.use_overwrite
        old_use_placeholder = render.use_placeholder

        disable_denoiser = False
        if disable_denoiser:
            use_denoising = [layer.cycles.use_denoising
                             for layer in context.scene.view_layers]
        else:
            use_denoising = []

        try:

            # The file extension should be determined by the render settings, not necessarily
            # by the setttings in the output panel.
            render.use_file_extension = True

            # Rescheduling should not overwrite existing frames.
            render.use_overwrite = False
            render.use_placeholder = False

            if disable_denoiser:
                for layer in context.scene.view_layers:
                    layer.cycles.use_denoising = False

            filepath = Path(context.blend_data.filepath).with_suffix('.blend')
            self.log.info('Saving copy to temporary file %s', filepath)
            bpy.ops.wm.save_as_mainfile(filepath=str(filepath),
                                        compress=True,
                                        copy=True)
        finally:
            # Restore the settings we changed, even after an exception.
            render.use_file_extension = old_use_file_extension
            render.use_overwrite = old_use_overwrite
            render.use_placeholder = old_use_placeholder

            if disable_denoiser:
                for denoise, layer in zip(use_denoising, context.scene.view_layers):
                    layer.cycles.use_denoising = denoise

        return filepath

Milan Jaros's avatar
Milan Jaros committed
729
    async def bat_pack(self, filepath: Path, project) \
strakpe's avatar
strakpe committed
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
            -> typing.Tuple[typing.Optional[Path], typing.Optional[PurePath], typing.List[Path]]:
        """BAT-packs the blendfile to the destination directory.

        Returns the path of the destination blend file.

        :param job_id: the job ID given to us by Raas Server.
        :param filepath: the blend file to pack (i.e. the current blend file)
        :returns: A tuple of:
            - The destination directory, or None if it does not exist on a
              locally-reachable filesystem (for example when sending files to
              a Shaman server).
            - The destination blend file, or None if there were errors BAT-packing,
            - A list of missing paths.
        """

        from datetime import datetime
        from . import bat_interface

        prefs = raas_pref.preferences()

Milan Jaros's avatar
Milan Jaros committed
750
        #proj_abspath = bpy.path.abspath(prefs.raas_project_local_path)
strakpe's avatar
strakpe committed
751
752
        proj_abspath = bpy.path.abspath('//./')
        projdir = Path(proj_abspath).resolve()
Milan Jaros's avatar
Milan Jaros committed
753
754
        exclusion_filter = '' #(prefs.raas_exclude_filter or '').strip()
        relative_only = False #prefs.raas_relative_only
strakpe's avatar
strakpe committed
755
756
757

        self.log.debug('projdir: %s', projdir)

Milan Jaros's avatar
Milan Jaros committed
758
759
760
761
        dt = datetime.now().isoformat('-').replace(':', '').replace('.', '')

        unique_dir = '%s-%s' % (dt[0:19], project)

strakpe's avatar
strakpe committed
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
        outdir = Path(prefs.raas_job_storage_path) / unique_dir / 'in'

        self.log.debug('outdir : %s', outdir)

        try:
            outdir.mkdir(parents=True)
        except Exception as ex:
            self.log.exception('Unable to create output path %s', outdir)
            self.report({'ERROR'}, 'Unable to create output path: %s' % ex)
            self.quit()
            return outdir, None, []

        try:
            outfile, missing_sources = await bat_interface.copy(
                bpy.context, filepath, projdir, outdir, exclusion_filter,
                relative_only=relative_only)
        except bat_interface.FileTransferError as ex:
            self.log.error('Could not transfer %d files, starting with %s',
                           len(ex.files_remaining), ex.files_remaining[0])
            self.report({'ERROR'}, 'Unable to transfer %d files' % len(ex.files_remaining))
            self.quit()
            return outdir, None, []
        except bat_interface.Aborted:
            self.log.warning('BAT Pack was aborted')
            self.report({'WARNING'}, 'Aborted Raas file packing/transferring')
            self.quit()
            return outdir, None, []

        bpy.context.window_manager.raas_status = 'PARTIAL_DONE'
        return outdir, outfile, missing_sources, unique_dir, filepath.stem

class RAAS_OT_abort(Operator):
    """Aborts a running Raas file packing/transfer operation.
    """
    bl_idname = 'raas.abort'
    bl_label = 'Abort'

    @classmethod
    def poll(cls, context):
        return context.window_manager.raas_status != 'ABORTING'

    def execute(self, context):
        context.window_manager.raas_status = 'ABORTING'
        bat_interface.abort()
        return {'FINISHED'}


class RAAS_OT_explore_file_path(Operator):
    """Opens the Raas job storage path in a file explorer.

    If the path cannot be found, this operator tries to open its parent.
    """

    bl_idname = 'raas.explore_file_path'
    bl_label = 'Open in file explorer'

    path: StringProperty(name='Path', description='Path to explore', subtype='DIR_PATH')

    def execute(self, context):
        import platform
        import pathlib

        # Possibly open a parent of the path
        to_open = pathlib.Path(self.path)
        while to_open.parent != to_open:  # while we're not at the root
            if to_open.exists():
                break
            to_open = to_open.parent
        else:
            self.report({'ERROR'}, 'Unable to open %s or any of its parents.' % self.path)
            return {'CANCELLED'}
        to_open = str(to_open)

        if platform.system() == "Windows":
            import os
            os.startfile(to_open)

        elif platform.system() == "Darwin":
            import subprocess
            subprocess.Popen(["open", to_open])

        else:
            import subprocess
            subprocess.Popen(["xdg-open", to_open])

        return {'FINISHED'}
Milan Jaros's avatar
Milan Jaros committed
848
849
850
851
852
853
854
855
856
857
858
859
860

class RAAS_PT_MessageOfTheDay(RaasButtonsPanel, Panel):
    bl_label = "Message of the day"
    bl_parent_id = "RAAS_PT_simplify"
    COMPAT_ENGINES = {'CYCLES'}

    def draw(self, context):
        layout = self.layout
        box = layout.box()

        box.operator(RAAS_OT_MessageOfTheDay.bl_idname,
                            text='Message of the day',
                            icon='WORLD')  
strakpe's avatar
strakpe committed
861
862
863
864
865
866
867
868
869
870
871
872
873
874

class RAAS_PT_NewJob(RaasButtonsPanel, Panel):
    bl_label = "New Job"
    bl_parent_id = "RAAS_PT_simplify"
    COMPAT_ENGINES = {'CYCLES'}

    def draw(self, context):
        layout = self.layout

        if context.window_manager.raas_status in {'IDLE', 'ERROR',  'DONE'}:
            layout.enabled = True
        else:
            layout.enabled = False          

Milan Jaros's avatar
Milan Jaros committed
875
876
        #prefs = raas_pref.preferences()

strakpe's avatar
strakpe committed
877
878
879
880
881
882
883
884
885
886
887
        #################################################

        box = layout.box()

        paths_layout = box.column(align=True)
        blender_job_info_new = context.scene.raas_blender_job_info_new        

        blender_job_info_new = context.scene.raas_blender_job_info_new

        job_info_col = paths_layout.column()

Milan Jaros's avatar
Milan Jaros committed
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
        job_info_col.prop(blender_job_info_new, 'cluster_type')

        if blender_job_info_new.cluster_type == 'SALOMON':
            job_info_col.prop(blender_job_info_new, 'job_queue_salomon')

            if blender_job_info_new.job_queue_salomon == 'MIC' or blender_job_info_new.job_queue_salomon == 'MICBUFFER':
                job_info_col.prop(blender_job_info_new, 'job_project')
                job_info_col.prop(blender_job_info_new, 'job_email')
                job_info_col.prop(blender_job_info_new, 'render_type')

                col = job_info_col.column(align=True)
                job_info_col.prop(blender_job_info_new, 'file_type')
                if blender_job_info_new.file_type == 'OTHER':
                    job_info_col.prop(blender_job_info_new, 'blendfile_path')

                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_nodes', text='MICs')
                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_walltime_pre')
                col.prop(blender_job_info_new, 'job_walltime', text="Walltime Rendering [minutes]")
                col.prop(blender_job_info_new, 'job_walltime_post')              
            elif blender_job_info_new.job_queue_salomon == 'MPP' or blender_job_info_new.job_queue_salomon == 'MPPBUFFER':
                job_info_col.prop(blender_job_info_new, 'job_project')
                job_info_col.prop(blender_job_info_new, 'job_email')
                job_info_col.prop(blender_job_info_new, 'render_type')

                col = job_info_col.column(align=True)
                job_info_col.prop(blender_job_info_new, 'file_type')
                if blender_job_info_new.file_type == 'OTHER':
                    job_info_col.prop(blender_job_info_new, 'blendfile_path')

                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_nodes')
                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_walltime_pre')
                col.prop(blender_job_info_new, 'job_walltime', text="Walltime Rendering [minutes]")
                col.prop(blender_job_info_new, 'job_walltime_post')
            elif blender_job_info_new.job_queue_salomon == 'MICINTERACTIVE':
                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_nodes')
                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_walltime')               
            elif blender_job_info_new.job_queue_salomon == 'ORIGCPU':
                job_info_col.prop(blender_job_info_new, 'job_project')
                job_info_col.prop(blender_job_info_new, 'job_email')
                job_info_col.prop(blender_job_info_new, 'render_type')

Milan Jaros's avatar
Milan Jaros committed
935
936
                col = job_info_col.column(align=True)
                job_info_col.prop(blender_job_info_new, 'file_type')
Milan Jaros's avatar
Milan Jaros committed
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
                if blender_job_info_new.file_type == 'OTHER':
                    job_info_col.prop(blender_job_info_new, 'blendfile_path')

                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_walltime')

        if blender_job_info_new.cluster_type == 'BARBORA':
            job_info_col.prop(blender_job_info_new, 'job_queue_barbora')

            if blender_job_info_new.job_queue_barbora == 'GPU' or blender_job_info_new.job_queue_barbora == 'GPUUNIMEM':
                job_info_col.prop(blender_job_info_new, 'job_project')
                job_info_col.prop(blender_job_info_new, 'job_email')
                job_info_col.prop(blender_job_info_new, 'render_type')

                col = job_info_col.column(align=True)
                job_info_col.prop(blender_job_info_new, 'file_type')
                if blender_job_info_new.file_type == 'OTHER':
                    job_info_col.prop(blender_job_info_new, 'blendfile_path')

                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_nodes')
                col = job_info_col.column(align=True)
                # col.prop(blender_job_info_new, 'job_walltime_pre')
                # col.prop(blender_job_info_new, 'job_walltime', text="Walltime Rendering [minutes]")
                # col.prop(blender_job_info_new, 'job_walltime_post')  
                
                col.prop(blender_job_info_new, 'job_walltime') 

            elif blender_job_info_new.job_queue_barbora == 'GPUINTERACTIVE':
                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_nodes')
                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_walltime')               
            elif blender_job_info_new.job_queue_barbora == 'ORIGCUDA' or blender_job_info_new.job_queue_barbora == 'ORIGOPTIX' or blender_job_info_new.job_queue_barbora == 'ORIGCPU':
                job_info_col.prop(blender_job_info_new, 'job_project')
                job_info_col.prop(blender_job_info_new, 'job_email')
                job_info_col.prop(blender_job_info_new, 'render_type')

Milan Jaros's avatar
Milan Jaros committed
975
976
                col = job_info_col.column(align=True)
                job_info_col.prop(blender_job_info_new, 'file_type')
Milan Jaros's avatar
Milan Jaros committed
977
978
979
980
981
                if blender_job_info_new.file_type == 'OTHER':
                    job_info_col.prop(blender_job_info_new, 'blendfile_path')

                col = job_info_col.column(align=True)
                col.prop(blender_job_info_new, 'job_walltime')           
strakpe's avatar
strakpe committed
982
983
984
985
986
987

        if blender_job_info_new.render_type == 'IMAGE':
            col = job_info_col.column(align=True)            
            col.prop(context.scene, 'frame_current')                            
        else:
            col = job_info_col.column(align=True)   
Milan Jaros's avatar
Milan Jaros committed
988
989
990
            col.prop(context.scene, "frame_start")
            col.prop(context.scene, "frame_end")    
            col.prop(context.scene, "frame_step")
strakpe's avatar
strakpe committed
991
992
993
994
995

        box.operator(RAAS_OT_prepare_files.bl_idname,
                            text='Submit Job',
                            icon='RENDER_ANIMATION')            

Milan Jaros's avatar
Milan Jaros committed
996

strakpe's avatar
strakpe committed
997
##########################################################################
Milan Jaros's avatar
Milan Jaros committed
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
async def GetCurrentInfoForJob(context, job_id: int, token: str) -> None:
    """GetCurrentInfoForJob"""       

    data = {
        "SubmittedJobInfoId": job_id,
        "SessionCode": token
    }

    info_job = await raas_server.post("JobManagement/GetCurrentInfoForJob", data)

    return  info_job  

class RAAS_OT_GetCurrentInfoForJob(
                        async_loop.AsyncModalOperatorMixin,
                        AuthenticatedRaasOperatorMixin,                         
                        Operator):  
    """GetCurrentInfoForJob"""
    bl_idname = 'raas.get_current_info_for_job'
    bl_label = 'GetCurrentInfoForJob'

    async def async_execute(self, context):

        if not await self.authenticate(context):
            return        

        await GetCurrentInfoForJob(context, self.token)

        self.quit()     
##########################################################################
strakpe's avatar
strakpe committed
1027
1028
async def ListJobsForCurrentUser(context, token):
        data = {
Milan Jaros's avatar
Milan Jaros committed
1029
                "SessionCode" : token
strakpe's avatar
strakpe committed
1030
1031
1032
1033
        }

        resp_json = await raas_server.post("JobManagement/ListJobsForCurrentUser", data)

Milan Jaros's avatar
Milan Jaros committed
1034
        #context.scene.raas_list_jobs_index = -1
strakpe's avatar
strakpe committed
1035
1036
1037
        context.scene.raas_list_jobs.clear()
        for key in resp_json:
            item = context.scene.raas_list_jobs.add()
strakpe's avatar
update    
strakpe committed
1038
            raas_server.fill_items(item, key)         
Milan Jaros's avatar
Milan Jaros committed
1039

strakpe's avatar
strakpe committed
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
        if context.scene.raas_list_jobs_index > len(context.scene.raas_list_jobs) - 1:
            context.scene.raas_list_jobs_index = len(context.scene.raas_list_jobs) - 1
        

class RAAS_OT_ListJobsForCurrentUser(
                        async_loop.AsyncModalOperatorMixin,
                        AuthenticatedRaasOperatorMixin,                         
                        Operator):  
    """returns a list of basic information describing all user jobs"""
    bl_idname = 'raas.list_jobs_for_current_user'
    bl_label = 'ListJobsForCurrentUser'

    async def async_execute(self, context):

        if not await self.authenticate(context):
            return        

        await ListJobsForCurrentUser(context, self.token)

        self.quit() 

Milan Jaros's avatar
Milan Jaros committed
1061
##########################################################################        
Milan Jaros's avatar
Milan Jaros committed
1062

Milan Jaros's avatar
Milan Jaros committed
1063
1064
async def CreateJob(context, token):
        blender_job_info_new = context.scene.raas_blender_job_info_new
Milan Jaros's avatar
Milan Jaros committed
1065

Milan Jaros's avatar
Milan Jaros committed
1066
1067
1068
1069
1070
1071
1072
        if blender_job_info_new.cluster_type == 'SALOMON':       
        
            if blender_job_info_new.job_queue_salomon == 'ORIGCPU':
                await raas_jobs_salomon.CreateJobCPU(context, token)
        
            # if blender_job_info_new.job_queue_salomon == 'MPP':
            #     await raas_jobs_salomon.CreateJobMPP(context, token)
Milan Jaros's avatar
Milan Jaros committed
1073

Milan Jaros's avatar
Milan Jaros committed
1074
1075
            # if blender_job_info_new.job_queue_salomon == 'MIC':
            #     await raas_jobs_salomon.CreateJobMIC(context, token)
Milan Jaros's avatar
Milan Jaros committed
1076

Milan Jaros's avatar
Milan Jaros committed
1077
1078
            # if blender_job_info_new.job_queue_salomon == 'MICBUFFER':
            #     await raas_jobs_salomon.CreateJobMICBUFFER(context, token)        
strakpe's avatar
strakpe committed
1079

Milan Jaros's avatar
Milan Jaros committed
1080
1081
            # if blender_job_info_new.job_queue_salomon == 'MPPBUFFER':
            #     await raas_jobs_salomon.CreateJobMPPBUFFER(context, token)                   
strakpe's avatar
strakpe committed
1082

Milan Jaros's avatar
Milan Jaros committed
1083
1084
            # if blender_job_info_new.job_queue_salomon == 'MICINTERACTIVE':
            #     await raas_jobs_salomon.CreateJobMICINTERACTIVE(context, token)
strakpe's avatar
strakpe committed
1085

Milan Jaros's avatar
Milan Jaros committed
1086
        if blender_job_info_new.cluster_type == 'BARBORA':    
strakpe's avatar
strakpe committed
1087

Milan Jaros's avatar
Milan Jaros committed
1088
1089
            if blender_job_info_new.job_queue_barbora == 'ORIGCPU':
                await raas_jobs_barbora.CreateJobCPU(context, token)               
strakpe's avatar
strakpe committed
1090
        
Milan Jaros's avatar
Milan Jaros committed
1091
1092
1093
1094
1095
            if blender_job_info_new.job_queue_barbora == 'ORIGCUDA':
                await raas_jobs_barbora.CreateJobCUDA(context, token)

            # if blender_job_info_new.job_queue_barbora == 'ORIGOPTIX':
            #     await raas_jobs_barbora.CreateJobOPTIX(context, token)
strakpe's avatar
strakpe committed
1096
        
Milan Jaros's avatar
Milan Jaros committed
1097
1098
            # if blender_job_info_new.job_queue_barbora == 'GPU':
            #     await raas_jobs_barbora.CreateJobGPU(context, token)
Milan Jaros's avatar
Milan Jaros committed
1099

Milan Jaros's avatar
Milan Jaros committed
1100
1101
            # if blender_job_info_new.job_queue_barbora == 'GPUUNIMEM':
            #     await raas_jobs_barbora.CreateJobGPUUNIMEM(context, token)                
Milan Jaros's avatar
Milan Jaros committed
1102

Milan Jaros's avatar
Milan Jaros committed
1103
1104
            # if blender_job_info_new.job_queue_barbora == 'GPUBUFFER':
            #     await raas_jobs_barbora.CreateJobGPUBUFFER(context, token)                          
Milan Jaros's avatar
Milan Jaros committed
1105

Milan Jaros's avatar
Milan Jaros committed
1106
1107
            # if blender_job_info_new.job_queue_barbora == 'GPUINTERACTIVE':
            #     await raas_jobs_barbora.CreateJobGPUINTERACTIVE(context, token)                     
Milan Jaros's avatar
Milan Jaros committed
1108

Milan Jaros's avatar
Milan Jaros committed
1109
##########################################################################
strakpe's avatar
strakpe committed
1110
1111

async def SubmitJob(context, token):
Milan Jaros's avatar
Milan Jaros committed
1112
1113
1114
1115
        #idx = context.scene.raas_list_jobs_index 
        #try:
            #item = context.scene.raas_list_jobs[idx]

strakpe's avatar
strakpe committed
1116
1117
1118
        item = context.scene.raas_submitted_job_info_ext_new

        data = {
Milan Jaros's avatar
Milan Jaros committed
1119
1120
                    "CreatedJobInfoId": item.Id,
                    "SessionCode" : token
strakpe's avatar
strakpe committed
1121
1122
1123
        }            

        resp_json = await raas_server.post("JobManagement/SubmitJob", data)
Milan Jaros's avatar
Milan Jaros committed
1124
     
strakpe's avatar
strakpe committed
1125
1126
1127

async def CancelJob(context, token):
        idx = context.scene.raas_list_jobs_index 
Milan Jaros's avatar
Milan Jaros committed
1128
        #try:
strakpe's avatar
strakpe committed
1129
1130
1131
        item = context.scene.raas_list_jobs[idx]

        data = {
Milan Jaros's avatar
Milan Jaros committed
1132
1133
                "SubmittedJobInfoId": item.Id,
                "SessionCode" : token
strakpe's avatar
strakpe committed
1134
1135
1136
1137
        }

        resp_json = await raas_server.post("JobManagement/CancelJob", data)

Milan Jaros's avatar
Milan Jaros committed
1138
1139
        #except IndexError:
        #    pass      
strakpe's avatar
strakpe committed
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159

class RAAS_OT_CancelJob(
                        async_loop.AsyncModalOperatorMixin,
                        AuthenticatedRaasOperatorMixin,                         
                        Operator):

    """cancels a running job"""
    bl_idname = 'raas.cancel_job'
    bl_label = 'CancelJob'

    async def async_execute(self, context):

        if not await self.authenticate(context):
            return     

        await CancelJob(context, self.token)
        await ListJobsForCurrentUser(context, self.token)     

        self.quit()                 

Milan Jaros's avatar
Milan Jaros committed
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
async def DeleteJob(context, token):
        idx = context.scene.raas_list_jobs_index 
        #try:
        item = context.scene.raas_list_jobs[idx]

        data = {
                "SubmittedJobInfoId": item.Id,
                "SessionCode" : token
        }

        resp_json = await raas_server.post("JobManagement/DeleteJob", data)

        #except IndexError:
        #    pass      

class RAAS_OT_DeleteJob(
                        async_loop.AsyncModalOperatorMixin,
                        AuthenticatedRaasOperatorMixin,                         
                        Operator):

    """delete a running job"""
    bl_idname = 'raas.delete_job'
    bl_label = 'deleteJob'

    async def async_execute(self, context):

        if not await self.authenticate(context):
            return     

        await DeleteJob(context, self.token)
        await ListJobsForCurrentUser(context, self.token)     

        self.quit()

strakpe's avatar
strakpe committed
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
class RAAS_PT_ListJobs(RaasButtonsPanel, Panel):
    bl_label = "Jobs"
    bl_parent_id = "RAAS_PT_simplify"
    COMPAT_ENGINES = {'CYCLES'}    

    def draw(self, context):
        layout = self.layout

        if context.window_manager.raas_status in {'IDLE', 'ERROR', 'DONE'}:
            layout.enabled = True
        else:
            layout.enabled = False        

Milan Jaros's avatar
Milan Jaros committed
1207
        #header
strakpe's avatar
strakpe committed
1208
1209
1210
1211
1212
1213
        box = layout.box()

        row = box.row()   

        col = row.column()        
        col.label(text="Id")
Milan Jaros's avatar
Milan Jaros committed
1214
1215
        # col = row.column()        
        # col.label(text="Name")
strakpe's avatar
strakpe committed
1216
1217
1218
1219
        col = row.column()
        col.label(text="Project")        
        col = row.column()
        col.label(text="State")        
Milan Jaros's avatar
Milan Jaros committed
1220
1221
1222
1223
1224
1225
        # col = row.column()
        # box = col.box()
        # box = col.box()
        #box.separator_spacer()
        # col = row.column()
        # col.separator_spacer()
strakpe's avatar
strakpe committed
1226
1227
1228
1229
1230
        
        #table
        row = layout.row()
        row.template_list("RAAS_UL_SubmittedJobInfoExt", "", context.scene, "raas_list_jobs", context.scene, "raas_list_jobs_index")

Milan Jaros's avatar
Milan Jaros committed
1231
1232
1233
1234
1235
        # col = row.column(align=True)
        # col.operator("raas.list_jobs_for_current_user_actions", icon='ADD', text="").action = 'ADD'
        # col.operator("raas.list_jobs_for_current_user_actions", icon='X', text="").action = 'CANCEL'        
        # col.operator("raas.list_jobs_for_current_user_actions", icon='REMOVE', text="").action = 'REMOVE'

strakpe's avatar
strakpe committed
1236
1237
1238
        #button
        row = layout.row()
        row.operator(RAAS_OT_ListJobsForCurrentUser.bl_idname, text='Refresh')
Milan Jaros's avatar
Milan Jaros committed
1239
1240
        #row.operator(RAAS_OT_NewJob.bl_idname, text='New')
        #row.operator(RAAS_OT_SubmitJob.bl_idname, text='Submit')
strakpe's avatar
strakpe committed
1241
        row.operator(RAAS_OT_CancelJob.bl_idname, text='Cancel')
Milan Jaros's avatar
Milan Jaros committed
1242
        #row.operator(RAAS_OT_DeleteJob.bl_idname, text='Delete')
strakpe's avatar
strakpe committed
1243
1244
1245
1246
1247
1248
1249
1250
1251

        idx = context.scene.raas_list_jobs_index        

        if idx != -1:

            item = context.scene.raas_list_jobs[idx]   
            box = layout.box()
            box.enabled = False

Milan Jaros's avatar
Milan Jaros committed
1252
1253
            box.label(text=('Job: %d' % item.Id))
            box.prop(item, "Name")
Milan Jaros's avatar
Milan Jaros committed
1254
            #box.prop(item, "Priority")
Milan Jaros's avatar
Milan Jaros committed
1255
            box.prop(item, "Project")
Milan Jaros's avatar
Milan Jaros committed
1256
            #box.prop(item, "creationTime")
Milan Jaros's avatar
Milan Jaros committed
1257
1258
1259
1260
1261
1262
1263
            box.prop(item, "SubmitTime")
            box.prop(item, "StartTime")
            box.prop(item, "EndTime")

            row = box.column()            
            row.prop(item, "State")

Milan Jaros's avatar
Milan Jaros committed
1264
1265
1266
1267
1268
            #if len(item.endTime) == 0:
            #    row.prop(item, "statePre")
            #    row.prop(item, "stateRen")
            #    row.prop(item, "statePost")

strakpe's avatar
strakpe committed
1269
1270
            box = layout.box()

Milan Jaros's avatar
Milan Jaros committed
1271
            local_storage = str(get_job_local_storage(item.Name))
strakpe's avatar
strakpe committed
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
            paths_layout = box.column(align=True)
            labeled_row = paths_layout.split(**raas_pref.factor(0.25), align=True)
            labeled_row.label(text='Storage Path:')
            prop_btn_row = labeled_row.row(align=True)
            prop_btn_row.label(text=local_storage)
            props = prop_btn_row.operator(RAAS_OT_explore_file_path.bl_idname,
                                        text='', icon='DISK_DRIVE')
            props.path = local_storage

            row = box.row()
            row.operator(RAAS_OT_download_files.bl_idname, text='Download results')

#################################################  

# RaasManagerGroup needs to be registered before classes that use it.
_rna_classes = []
_rna_classes.extend(
    cls for cls in locals().values()
    if (isinstance(cls, type)
        and cls.__name__.startswith('RAAS')
        and cls not in _rna_classes)
)


def register():
    #from ..utils import redraw

    for cls in _rna_classes:
        bpy.utils.register_class(cls)

    scene = bpy.types.Scene

    ################JobManagement#################
Milan Jaros's avatar
Milan Jaros committed
1305
1306
1307
1308
    scene.raas_list_jobs = bpy.props.CollectionProperty(type=RAAS_PG_SubmittedJobInfoExt, options={'SKIP_SAVE'})
    scene.raas_list_jobs_index = bpy.props.IntProperty(default=-1, options={'SKIP_SAVE'})
    scene.raas_blender_job_info_new = bpy.props.PointerProperty(type=RAAS_PG_BlenderJobInfo, options={'SKIP_SAVE'})
    scene.raas_submitted_job_info_ext_new = bpy.props.PointerProperty(type=RAAS_PG_SubmittedJobInfoExt, options={'SKIP_SAVE'})
strakpe's avatar
strakpe committed
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
    #################################       

    bpy.types.WindowManager.raas_status = EnumProperty(
        items=[
            ('IDLE', 'IDLE', 'Not doing anything.'),
            ('SAVING', 'SAVING', 'Saving your file.'),
            ('INVESTIGATING', 'INVESTIGATING', 'Finding all dependencies.'),
            ('TRANSFERRING', 'TRANSFERRING', 'Transferring all dependencies.'),
            ('COMMUNICATING', 'COMMUNICATING', 'Communicating with Raas Server.'),
            ('DONE', 'DONE', 'Not doing anything, but doing something earlier.'),
            ('ERROR', 'ERROR', 'Something is wrong.'),
            ('PARTIAL_DONE', 'PARTIAL_DONE', 'Partial done.'),
            ('ABORTING', 'ABORTING', 'User requested we stop doing something.'),
            #('ABORTED', 'ABORTED', 'We stopped doing something.'),
        ],
        name='raas_status',
        default='IDLE',
        description='Current status of the Raas add-on',
        update=redraw
        )

    bpy.types.WindowManager.raas_status_txt = StringProperty(
        name='Raas Status',
        default='',
        description='Textual description of what Raas is doing',
        update=redraw)

    bpy.types.WindowManager.raas_progress = IntProperty(
        name='Raas Progress',
        default=0,
        description='File transfer progress',
        subtype='PERCENTAGE',
        min=0,
        max=100,
        update=redraw)


def unregister():
    for cls in _rna_classes:
        try:
            bpy.utils.unregister_class(cls)
        except RuntimeError:
            log.warning('Unable to unregister class %r, probably already unregistered', cls)

    try:
        del bpy.types.WindowManager.raas_status
    except AttributeError:
        pass