@@ -98,6 +98,38 @@ def send_post_data(conn: Connection, stop: EventType, url: str):
98
98
break
99
99
100
100
101
+ def send_put_jupyter_url (conn : Connection , stop : EventType , url : str ):
102
+ fail_count = 0
103
+
104
+ http = urllib3 .PoolManager (retries = urllib3 .util .Retry (3 , backoff_factor = 0.25 ))
105
+
106
+ while True :
107
+ if conn .poll (0.1 ):
108
+ next_val : dict [str , Any ] = conn .recv ()
109
+ # TODO - consider using multipart/form-data instead
110
+ try :
111
+ resp = http .request (
112
+ 'PUT' ,
113
+ url ,
114
+ body = json .dumps ({'url' : next_val ['url' ], 'tags' : next_val ['tags' ], 'portal_runid' : next_val ['portal_runid' ]}).encode (),
115
+ headers = {
116
+ 'Content-Type' : 'application/json' ,
117
+ },
118
+ )
119
+ except urllib3 .exceptions .MaxRetryError as e :
120
+ fail_count += 1
121
+ conn .send ((999 , str (e )))
122
+ else :
123
+ conn .send ((resp .status , resp .data .decode ()))
124
+ fail_count = 0
125
+
126
+ if fail_count >= 3 :
127
+ conn .send ((- 1 , 'Too many consecutive failed connections' ))
128
+ break
129
+ elif stop .is_set ():
130
+ break
131
+
132
+
101
133
class PortalBridge (Component ):
102
134
"""
103
135
Framework component to communicate with the SWIM web portal.
@@ -142,6 +174,10 @@ def __init__(self, services, config):
142
174
self .data_childProcess = None
143
175
self .data_childProcessStop = None
144
176
self .data_parent_conn = None
177
+ self .dataurl_first_event = True
178
+ self .dataurl_childProcess = None
179
+ self .dataurl_childProcessStop = None
180
+ self .dataurl_parent_conn = None
145
181
self .mpo = None
146
182
self .mpo_name_counter = defaultdict (lambda : 0 )
147
183
self .counter = 0
@@ -232,6 +268,10 @@ def process_event(self, topicName, theEvent):
232
268
self .send_data (sim_data , portal_data )
233
269
return
234
270
271
+ if portal_data ['eventtype' ] == 'PORTAL_REGISTER_NOTEBOOK' :
272
+ self .send_notebook_url (sim_data , portal_data )
273
+ return
274
+
235
275
if portal_data ['eventtype' ] == 'IPS_SET_MONITOR_URL' :
236
276
sim_data .monitor_url = portal_data ['vizurl' ]
237
277
elif sim_data .monitor_url :
@@ -345,7 +385,7 @@ def send_data(self, sim_data, event_data):
345
385
if self .data_first_event : # First time, launch sendPost.py daemon
346
386
self .data_parent_conn , child_conn = Pipe ()
347
387
self .data_childProcessStop = Event ()
348
- self .data_childProcess = Process (target = send_post_data , args = (child_conn , self .childProcessStop , self .portal_url + '/api/data' ))
388
+ self .data_childProcess = Process (target = send_post_data , args = (child_conn , self .data_childProcessStop , self .portal_url + '/api/data' ))
349
389
self .data_childProcess .start ()
350
390
self .data_first_event = False
351
391
@@ -357,9 +397,9 @@ def send_data(self, sim_data, event_data):
357
397
self .check_data_send_post_responses ()
358
398
359
399
def check_data_send_post_responses (self ):
360
- while self .parent_conn .poll ():
400
+ while self .data_parent_conn .poll ():
361
401
try :
362
- code , msg = self .parent_conn .recv ()
402
+ code , msg = self .data_parent_conn .recv ()
363
403
except (EOFError , OSError ):
364
404
break
365
405
@@ -380,6 +420,49 @@ def check_data_send_post_responses(self):
380
420
else :
381
421
self .services .error ('Portal Error: %d %s' , code , msg )
382
422
423
+ def send_notebook_url (self , sim_data , event_data ):
424
+ """
425
+ Send notebook contents
426
+ """
427
+ if self .portal_url :
428
+ if self .dataurl_first_event : # First time, launch sendPost.py daemon
429
+ self .dataurl_parent_conn , child_conn = Pipe ()
430
+ self .dataurl_childProcessStop = Event ()
431
+ self .dataurl_childProcess = Process (
432
+ target = send_put_jupyter_url , args = (child_conn , self .dataurl_childProcessStop , self .portal_url + '/api/data/add_url' )
433
+ )
434
+ self .dataurl_childProcess .start ()
435
+ self .dataurl_first_event = False
436
+
437
+ try :
438
+ self .dataurl_parent_conn .send (event_data )
439
+ except OSError :
440
+ pass
441
+
442
+ while self .dataurl_parent_conn .poll ():
443
+ try :
444
+ code , msg = self .dataurl_parent_conn .recv ()
445
+ except (EOFError , OSError ):
446
+ break
447
+
448
+ print ('PUT RESPONSE' , code , msg )
449
+ try :
450
+ data = json .loads (msg )
451
+ if 'runid' in data :
452
+ self .services .info ('Run Portal URL = %s/%s' , self .portal_url , data .get ('runid' ))
453
+
454
+ msg = json .dumps (data )
455
+ except (TypeError , json .decoder .JSONDecodeError ):
456
+ pass
457
+ if code == - 1 :
458
+ # disable portal, stop trying to send more data
459
+ self .portal_url = None
460
+ self .services .error ('Disabling portal because: %s' , msg )
461
+ elif code < 400 :
462
+ self .services .debug ('Portal Response: %d %s' , code , msg )
463
+ else :
464
+ self .services .error ('Portal Error: %d %s' , code , msg )
465
+
383
466
def send_mpo_data (self , event_data , sim_data ): # pragma: no cover
384
467
def md5 (fname ):
385
468
"Courtesy of stackoverflow 3431825"
0 commit comments