comparison main.py @ 0:7d8912d20007 draft

"planemo upload commit b2a00d9c24285fef0fb131d1832ecf4c337e5038-dirty"
author rhohensinner
date Fri, 21 May 2021 09:51:30 +0000
parents
children 19c1cecdfdfd
comparison
equal deleted inserted replaced
-1:000000000000 0:7d8912d20007
1 ___author___ = "Richard Hohensinner"
2 ___created___ = "04.02.2021"
3 ___last_modified___ = "20.05.2021"
4
5 # general imports
6 import os, sys, json
7 from shutil import copyfile
8 from datetime import datetime
9
10 # irods-client imports
11 from irods.session import iRODSSession
12 from irods.models import Collection, DataObject
13 from irods.query import SpecificQuery
14
15 # Tkinter imports
16 from tkinter import messagebox, Label, Button, Entry, Listbox, Tk, PhotoImage, Grid
17
18 # global variables
19 session = None
20 file_path_list = []
21 selected_file = ""
22 session_success = False
23 selection_success = False
24 iRODSCredentials = {"host": "", "port": "", "user": "", "pw": "", "zone": ""}
25
26
27 ########################################################################################################################
28 # Main function of the iRODS tools
29 #
30 # IN:
31 # JSON Object params (argv[1])
32 # OUT:
33 #
34 ########################################################################################################################
35 def main():
36
37 # check input parameters
38 if len(sys.argv) == 2:
39 params = json.loads(sys.argv[1])
40 else:
41 raise Exception("Invalid Parameters submitted!")
42
43 tool_type = params["tool_type"]
44
45 try:
46 if params["tool_type"] != "up" and params["tool_type"] != "down":
47 raise Exception("Invalid tool-type parameter submitted!")
48 except:
49 raise Exception("No tool-type parameter submitted!")
50 is_download_call = True
51 if tool_type == "up":
52 is_download_call = False
53
54 # check params for integrity
55 result_string, params_faulty = check_params(params)
56
57 if params_faulty:
58 raise Exception(result_string)
59
60 global iRODSCredentials, session_success, selected_file, selection_success
61 iRODSCredentials["host"] = params["irods_host"]
62 iRODSCredentials["port"] = params["irods_port"]
63 iRODSCredentials["zone"] = params["irods_zone"]
64
65 # create login window
66 make_login_window()
67 # check tool settings and start tool execution
68 if session_success:
69 # initialize download tool
70 if params["tool_type"] == "down":
71
72 if params["selection_type"] == "explorer":
73 make_file_select_window()
74 else:
75 if (params["file_path"] != ""): #and ("/" in params["file_path"]):
76 selected_file = params["file_path"]
77 else:
78 raise Exception("Invalid File Path submitted!")
79
80 if selection_success or params["selection_type"] == "path":
81 params["user"] = iRODSCredentials["pw"]
82 params["password"] = iRODSCredentials["user"]
83 # start download routine
84 handle_download_call(params)
85 else:
86 raise Exception("File Selection failed (No file selected)")
87
88 # initialize upload tool
89 elif params["tool_type"] == "up":
90
91 if session_success:
92 params["user"] = iRODSCredentials["pw"]
93 params["password"] = iRODSCredentials["user"]
94 # start upload routine
95 handle_upload_call(params)
96 else:
97 raise Exception("Logging into iRODS failed")
98 else:
99 raise Exception("Logging into iRODS failed")
100 # -------------------------------------------------------------------------------------------------------------------- #
101
102
103 ########################################################################################################################
104 # Login Window class for Tkinter
105 #
106 # IN:
107 # Tk Window win
108 # OUT:
109 # (sets global variables iRODSCredentials, session and session_success)
110 #
111 ########################################################################################################################
112 class LoginWindow:
113 def __init__(self, win):
114 self.window = win
115 self.lbl1 = Label(win, text='iRODS Username:')
116 self.lbl2 = Label(win, text='iRODS Password:')
117 self.t1 = Entry(bd=3)
118 self.t2 = Entry(show="*")
119 self.b1 = Button(win, text='Login', command=self.login)
120
121 self.window.grid()
122 Grid.rowconfigure(self.window, 0, weight=1)
123 Grid.rowconfigure(self.window, 1, weight=1)
124 Grid.rowconfigure(self.window, 2, weight=1)
125 Grid.rowconfigure(self.window, 3, weight=1)
126 Grid.rowconfigure(self.window, 4, weight=1)
127 Grid.columnconfigure(self.window, 0, weight=1)
128
129 self.lbl1.grid(row=0, column=0, padx="20", pady="1", sticky="w")
130 self.t1.grid(row=1, column=0, padx="10", pady="1", sticky="nsew")
131 self.lbl2.grid(row=2, column=0, padx="20", pady="1", sticky="w")
132 self.t2.grid(row=3, column=0, padx="10", pady="1", sticky="nsew")
133 self.b1.grid(row=4, column=0, padx="50", pady="10", sticky="nsew")
134
135 def login(self):
136 global iRODSCredentials
137 user = str(self.t1.get())
138 password = str(self.t2.get())
139 if user == "" or password == "":
140 self.window.iconify()
141 messagebox.showerror("Error", "Username or Password empty!")
142 self.window.deiconify()
143 return
144 else:
145 iRODSCredentials["user"] = user
146 iRODSCredentials["pw"] = password
147
148 get_irods_session(self.window)
149 if not session_success:
150 return
151
152 self.window.destroy()
153 # -------------------------------------------------------------------------------------------------------------------- #
154
155
156 ########################################################################################################################
157 # File Selection Window class for Tkinter
158 #
159 # IN:
160 # Tk Window win
161 # OUT:
162 # (sets global variables selected_file and selection_success)
163 #
164 ########################################################################################################################
165 class FileSelectWindow:
166 def __init__(self, win):
167 global session, iRODSCredentials
168 self.session = session
169 self.window = win
170 self.b1 = Button(win, text='Select', command=self.select)
171 self.lb1 = Listbox(win)
172
173 self.window.grid()
174 Grid.rowconfigure(self.window, 0, weight=1)
175 Grid.rowconfigure(self.window, 1, weight=1)
176 Grid.columnconfigure(self.window, 0, weight=1)
177
178 self.lb1.grid(row=0, column=0, padx="20", pady="1", sticky="nswe")
179 self.b1.grid(row=1, column=0, padx="50", pady="1", sticky="ew")
180
181 coll = session.collections.get("/" + iRODSCredentials["zone"] + "/" + "home" + "/" + iRODSCredentials["user"])
182 file_list = []
183
184 self.get_files_from_collections(coll, file_list)
185
186 for counter in range(len(file_list)):
187 self.lb1.insert(counter, file_list[counter])
188
189 def get_files_from_collections(self, coll, file_list):
190 for obj in coll.data_objects:
191 file_list.append(obj.path)
192
193 for col in coll.subcollections:
194 self.get_files_from_collections(col, file_list)
195
196 def select(self):
197 global session, selected_file, selection_success
198 try:
199 selection = self.lb1.get(self.lb1.curselection())
200 except:
201 self.window.iconify()
202 messagebox.showerror("Error", "No file selected!")
203 self.window.deiconify()
204 return
205
206 selected_file = selection
207 selection_success = True
208 self.window.destroy()
209 # -------------------------------------------------------------------------------------------------------------------- #
210
211
212 ########################################################################################################################
213 # Creates an iRODS session and sets the global session variable
214 #
215 # IN:
216 # Tk Window window
217 #
218 # OUT:
219 #
220 ########################################################################################################################
221 def get_irods_session(window):
222 global iRODSCredentials
223 host = iRODSCredentials["host"]
224 port = iRODSCredentials["port"]
225 user = iRODSCredentials["user"]
226 password = iRODSCredentials["pw"]
227 zone = iRODSCredentials["zone"]
228
229 iRODSsession = get_iRODS_connection(host=host, port=port, user=user, password=password, zone=zone)
230 global session, session_success
231 try:
232 coll = iRODSsession.collections.get("/" + zone + "/" + "home" + "/" + user)
233 except Exception:
234 window.iconify()
235 messagebox.showerror("Error", "Invalid Authentification")
236 window.deiconify()
237 return
238
239 if coll:
240 session = iRODSsession
241 session_success = True
242 # -------------------------------------------------------------------------------------------------------------------- #
243
244
245 ########################################################################################################################
246 # Helper function to initialize Login Window classes and Tk windows
247 #
248 # IN:
249 #
250 # OUT:
251 #
252 ########################################################################################################################
253 def make_login_window():
254 window = Tk()
255 LoginWindow(window)
256 window.title('iRODS Login')
257 window.geometry("450x225+10+10")
258 window.minsize(450, 225)
259 window.tk.call('wm', 'iconphoto', window._w, PhotoImage(file='/home/richard/git/galaxy_irods_tools/login.png'))
260 # alternative options:
261 # window.iconphoto(False, PhotoImage(file='/path/to/ico/icon.png'))
262 # window.iconbitmap("/home/richard/git/galaxy_irods_tools/login.ico")
263 window.mainloop()
264 # -------------------------------------------------------------------------------------------------------------------- #
265
266
267 ########################################################################################################################
268 # Helper function to initialize File Selection Window classes and Tk windows
269 #
270 # IN:
271 #
272 # OUT:
273 #
274 ########################################################################################################################
275 def make_file_select_window():
276 window = Tk()
277 FileSelectWindow(window)
278 window.title('iRODS File Select')
279 window.geometry("450x225+10+10")
280 window.minsize(450, 225)
281 window.mainloop()
282 # -------------------------------------------------------------------------------------------------------------------- #
283
284
285 ########################################################################################################################
286 # Checks whether arguments are valid and returns true/false depending on params
287 #
288 # IN:
289 # Dict params
290 #
291 # OUT:
292 # String res_string
293 # Bool res_bool
294 ########################################################################################################################
295 def check_params(params):
296 res_string = ""
297 res_bool = False
298
299 try:
300 if params["irods_host"] == "":
301 res_string += "Host empty!\n"
302 res_bool = True
303 if params["irods_port"] == "":
304 res_string += "Port empty!\n"
305 res_bool = True
306 if params["irods_zone"] == "":
307 res_string += "Zone empty!\n"
308 res_bool = True
309 if params["selection_type"] == "path" and params["file_path"] == "":
310 res_string += "Missing file path!\n"
311 res_bool = True
312 except:
313 raise Exception("Invalid/Missing Parameters")
314
315 return res_string, res_bool
316 # -------------------------------------------------------------------------------------------------------------------- #
317
318
319 ########################################################################################################################
320 # Function to handle iRODS download calls
321 #
322 # IN:
323 # Dict params
324 #
325 # OUT:
326 #
327 ########################################################################################################################
328 def handle_download_call(params):
329
330 global session, selected_file
331
332 # check if /ZONE/USER/...FILE... pattern is valid
333 if len(selected_file.split("/")) < 2:
334 raise Exception("Path to file is not valid in iRODS")
335
336 file_list = []
337
338 # check if file is a directory
339 if "." not in selected_file:
340 try:
341 coll = session.collections.get(selected_file)
342 for file in coll.data_objects:
343 file_list.append(file.path)
344 except:
345 raise Exception("Invalid directory path specified!")
346 else:
347 file_list.append(selected_file)
348
349 # get registry file
350 reg_file = ""
351 for dirpath, dirnames, filenames in os.walk(params["galaxy_root"]):
352 for fn in filenames:
353 if fn == "irods_galaxy_registry.xml":
354 reg_file = os.path.join(dirpath, fn)
355 if reg_file != "":
356 break
357 if reg_file != "":
358 break
359
360 # handle download for all files in file_list
361 for file in file_list:
362
363 file_to_get = file
364
365 # handle path and file name
366 name_file_to_get = file_to_get.split("/")[-1]
367 path_file_to_get = "/".join(file_to_get.split("/")[0:len(file_to_get.split("/")) - 1])
368
369 # check iRODS filesystem
370 check_iRODS_destination(session, path_file_to_get, name_file_to_get)
371
372 # get file object from iRODS
373 iRODS_file_object = session.data_objects.get(path_file_to_get + "/" + name_file_to_get)
374 input_file = iRODS_file_object.open("r+")
375 output_file = open(name_file_to_get, "wb")
376 output_file.write(input_file.read())
377
378 input_file.close()
379 output_file.close()
380
381 abs_file_path = os.path.abspath(name_file_to_get)
382
383 file_type = str(name_file_to_get.split(".")[-1])
384
385 file_content = {"uuid": None,
386 "file_type": "auto",
387 "space_to_tab": False,
388 "dbkey": "?",
389 "to_posix_lines": True,
390 "ext": file_type,
391 "path": abs_file_path,
392 "in_place": True,
393 "dataset_id": params["job_id"],
394 "type": "file",
395 "is_binary": False,
396 "link_data_only": "copy_files",
397 "name": name_file_to_get
398 }
399
400 with open("temporal.json", "w") as fileParams:
401 fileParams.write(json.dumps(file_content))
402 fileParams.close()
403
404 # load file into Galaxy by using the integrated upload tool - Preparation
405 python_command = params["galaxy_root"] + "/tools/data_source/upload.py"
406 arg1 = params["galaxy_root"]
407 arg2 = params["galaxy_datatypes"]
408 arg3 = os.path.abspath(fileParams.name)
409 arg4 = params["job_id"] + ":" + params["out_dir"] + ":" + params["out_file"]
410
411 # copy sample registry.xml to working directory
412 copyfile(reg_file, params["galaxy_datatypes"])
413
414 # activate environment for new process call and call the python upload command either both with
415 sys.path.append(params["galaxy_root"] + "/lib")
416 os.system("python -c \'import sys;sys.path.append(\"" + params["galaxy_root"] + "/lib\")\'" + " python " +
417 python_command + " " + arg1 + " " + arg2 + " " + arg3 + " " + arg4)
418
419 # close connection
420 session.cleanup()
421 # -------------------------------------------------------------------------------------------------------------------- #
422
423
424 ########################################################################################################################
425 # Function to handle iRODS upload calls
426 #
427 # IN:
428 # Dict params
429 #
430 # OUT:
431 #
432 ########################################################################################################################
433 def handle_upload_call(params):
434
435 global session, iRODSCredentials
436
437 path_to_file = params["up_file_path"]
438 name_of_file = params["up_file"]
439
440 coll_path = "/" + iRODSCredentials["zone"] + "/home/" + iRODSCredentials["user"] + "/galaxyupload"
441 try:
442 coll = session.collections.get(coll_path)
443 except:
444 coll = session.collections.create(coll_path)
445
446 now = datetime.now()
447
448 # dd/mm/YY
449 day = now.strftime("%d%m%Y")
450 time = now.strftime("%H%M%S")
451
452 coll_path = coll_path + "/" + day
453
454 try:
455 coll = session.collections.get(coll_path)
456 except:
457 coll = session.collections.create(coll_path)
458
459 irods_file_name = time + "_" + name_of_file
460 iRODS_file_object = session.data_objects.create(coll_path + "/" + irods_file_name)
461 iRODS_file_object = session.data_objects.get(coll_path + "/" + irods_file_name)
462
463 irods_file = iRODS_file_object.open("w")
464 galaxy_file = open(path_to_file, "rb")
465 content = galaxy_file.read()
466 irods_file.write(content)
467
468 # TODO can't close session without writing process finished - but reading/writing happens async.
469 # session.cleanup()
470
471 pass
472 # -------------------------------------------------------------------------------------------------------------------- #
473
474
475 ########################################################################################################################
476 # Function to initialize an iRODS Session - will raise an Exception if timeout is longer than 2 seconds
477 #
478 # IN:
479 # String host
480 # String port
481 # String user
482 # String password
483 # String zone
484 #
485 # OUT:
486 # iRODSSession-object session
487 ########################################################################################################################
488 def get_iRODS_connection(host, port, user, password, zone):
489
490 # initialize timeout checker - fires after 2 secs
491 import signal
492 signal.signal(signal.SIGALRM, timeout_checker)
493 signal.alarm(2)
494
495 try:
496 session = iRODSSession(host=host, port=port, user=user, password=password, zone=zone)
497 except Exception:
498 raise Exception("There was a timeout creating the iRODS session")
499
500 # void/reset alarm
501 signal.alarm(0)
502
503 return session
504 # -------------------------------------------------------------------------------------------------------------------- #
505
506
507 ########################################################################################################################
508 # Helper function to raise timeout exception when SIGALRM fires
509 #
510 # IN:
511 #
512 # OUT:
513 #
514 ########################################################################################################################
515 def timeout_checker():
516
517 raise Exception("iRODS session timeout")
518 # -------------------------------------------------------------------------------------------------------------------- #
519
520
521 ########################################################################################################################
522 # Function to check if file exists in iRODS
523 #
524 # IN:
525 # String path
526 #
527 # OUT:
528 # Bool ret_bool
529 #
530 ########################################################################################################################
531 def check_if_file_exists(path):
532
533 if os.path.isfile(path):
534 ret_bool = True
535 else:
536 ret_bool = False
537
538 return ret_bool
539 # -------------------------------------------------------------------------------------------------------------------- #
540
541
542 ########################################################################################################################
543 # Function to check iRODS destination
544 #
545 # IN:
546 # iRODSSession-object session
547 # String path
548 # String name
549 #
550 # OUT:
551 # Bool ret_bool
552 #
553 ########################################################################################################################
554 def check_iRODS_destination(session, path, name):
555
556 try:
557 session.collections.get(path.rstrip("/"))
558 except Exception:
559 raise Exception("Collection doesn't exist in iRODS file system")
560
561 try:
562 session.data_objects.get(path.rstrip("/") + "/" + name)
563 except Exception:
564 raise Exception("File doesn't exist in iRODS file system")
565 # -------------------------------------------------------------------------------------------------------------------- #
566
567
568 if __name__ == "__main__":
569 main()