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