Mercurial > repos > rhohensinner > galaxy_irods_interface
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() |