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