Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jhancock/use elisa microservice #277

Merged
merged 15 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions src/nanorc/__main_np04__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
from nanorc.cli import CONTEXT_SETTINGS, loglevels, updateLogLevel
from nanorc.nano_context import NanoContext

from .logbook import ElisaLogbook

# ------------------------------------------------------------------------------
@click_shell.shell(prompt='anonymous@np04rc> ', chain=True, context_settings=CONTEXT_SETTINGS)
@click.version_option(__version__)
Expand Down Expand Up @@ -121,6 +119,9 @@ def np04cli(ctx, obj, traceback, loglevel, elisa_conf, log_path, cfg_dumpdir, do
logger.error(f"Can't find apparatus \'{apparatus_id}\' in dotnanorc, reverting to file logbook!")
elisa_conf_data = 'file'

if elisa_conf_data != 'file':
elisa_socket = elisa_conf_data['socket']
logger.info("ELisA socket "+elisa_socket)

from nanorc.credmgr import CERNSessionHandler
cern_auth = CERNSessionHandler(
Expand Down Expand Up @@ -268,9 +269,6 @@ def is_authenticated(rc):
rc.log.error(f'\'{rc.session_handler.nanorc_user.username}\' does not have a valid kerberos ticket, use \'kinit\', or \'change_user\' to create a ticket, [bold]inside nanorc![/]', extra={"markup": True})
return False

if not rc.session_handler.elisa_user_is_authenticated() and (type(rc.logbook) == ElisaLogbook):
rc.session_handler.authenticate_elisa_user()

return True


Expand Down
14 changes: 5 additions & 9 deletions src/nanorc/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .cfgsvr import FileConfigSaver, DBConfigSaver
from .credmgr import credentials
from .node_render import print_node, print_status
from .logbook import ElisaLogbook, FileLogbook
from .logbook import ElisaHandler, FileLogbook
import importlib
from . import confdata
from rich.traceback import Traceback
Expand Down Expand Up @@ -100,11 +100,7 @@ def __init__(

if logbook_type != 'file':
try:
self.logbook = ElisaLogbook(
configuration = logbook_type,
console = console,
session_handler = self.session_handler,
)
self.logbook = ElisaHandler(socket = logbook_type['socket'], session_handler = self.session_handler)
except Exception as e:
self.log.error(f"Couldn't initialise ELisA, reverting to file logbook! {str(e)}")
logbook_type = 'file'
Expand Down Expand Up @@ -379,7 +375,7 @@ def start(self, run_type:str, trigger_rate:float, disable_data_storage:bool, ign
run_type = run_type,
)
except Exception as e:
self.log.error(f"Couldn't make an entry to the logbook, do it yourself manually at {self.logbook.website}\nError text:\n{str(e)}")
self.log.error(f"Couldn't make an entry to the logbook, do it yourself manually. \nError text:\n{str(e)}")

cfg_save_dir = None
if self.cfgsvr:
Expand Down Expand Up @@ -443,7 +439,7 @@ def message(self, message:str) -> NoReturn:
)

except Exception as e:
self.log.error(f"Couldn't make an entry to the logbook, do it yourself manually at {self.logbook.website}\nError text:\n{str(e)}")
self.log.error(f"Couldn't make an entry to the logbook, do it yourself manually. \nError text:\n{str(e)}")

def stop(self, force:bool, timeout:int, **kwargs) -> NoReturn:
"""
Expand Down Expand Up @@ -518,7 +514,7 @@ def drain_dataflow(self, timeout:int, force:bool, message:str, ignore_run_regist
session = self.partition,
)
except Exception as e:
self.log.error(f"Couldn't make an entry to the logbook, do it yourself manually at {self.logbook.website}\nError text:\n{str(e)}")
self.log.error(f"Couldn't make an entry to the logbook, do it yourself manually. \nError text:\n{str(e)}")

if self.cfgsvr and self.runs:
try:
Expand Down
54 changes: 0 additions & 54 deletions src/nanorc/credmgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,6 @@ def __init__(self, console, apparatus_id:str, session_number:int, username:str,
self.log.error(f'User \'{username}\' cannot authenticate, exiting...')
exit(1)

if not self.elisa_user_is_authenticated() and authenticate_elisa_user:
self.authenticate_elisa_user()

@staticmethod
def __get_session_kerberos_cache_path(session_name:str, session_number:int):
import os
Expand All @@ -262,15 +259,6 @@ def __get_session_kerberos_cache_path(session_name:str, session_number:int):
os.path.expanduser(f'~/.nanorc_userkerbcache_{session_name}_session_{session_number}')
)

@staticmethod
def __get_elisa_kerberos_cache_path():
import os
from pathlib import Path

return Path(
os.path.expanduser(f'~/.nanorc_elisakerbcache')
)

@staticmethod
def session_is_active(session_name:str, session_number:int):
cache_path = CERNSessionHandler.__get_session_kerberos_cache_path(
Expand Down Expand Up @@ -356,48 +344,6 @@ def nanorc_user_is_authenticated(self):
ticket_dir = session_kerb_cache,
)

def elisa_user_is_authenticated(self):
elisa_user = credentials.get_login('elisa')

return check_kerberos_credentials(
against_user = elisa_user.username,
silent = True,
ticket_dir = CERNSessionHandler.__get_elisa_kerberos_cache_path(),
)


def authenticate_elisa_user(self):
elisa_user = credentials.get_login('elisa')
elisa_kerb_cache = CERNSessionHandler.__get_elisa_kerberos_cache_path()
import os

if not os.path.isdir(elisa_kerb_cache):
os.mkdir(elisa_kerb_cache)

if self.elisa_user_is_authenticated():
# we're authenticated, stop here
return True

return new_kerberos_ticket(
user = elisa_user.username,
realm = elisa_user.realm,
password = elisa_user.password,
ticket_dir = elisa_kerb_cache,
)

def generate_elisa_cern_cookie(self, website, cookie_dir):
elisa_user = credentials.get_login('elisa')
elisa_kerb_cache = CERNSessionHandler.__get_elisa_kerberos_cache_path()

self.authenticate_elisa_user()

return elisa_user.generate_cern_sso_cookie(
website,
elisa_kerb_cache,
cookie_dir,
)


def stop_session(self):
import os
session_active_marker = CERNSessionHandler.__get_session_kerberos_cache_path(self.session_name, self.session_number)/'active_session'
Expand Down
84 changes: 31 additions & 53 deletions src/nanorc/logbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import subprocess
import copy
import time
import requests
from .credmgr import credentials

class FileLogbook:
Expand Down Expand Up @@ -47,15 +48,15 @@ def message_on_stop(self, messages:str, session:str):



class ElisaLogbook:
def __init__(self, console, configuration, session_handler):
self.console = console
class ElisaHandler:
def __init__(self, socket, session_handler):
self.socket = socket
self.session_handler = session_handler
self.elisa_arguments = {"connection": configuration['connection']}
self.website = configuration['website']
self.message_attributes = configuration['attributes']
self.log = logging.getLogger(self.__class__.__name__)
self.log.info(f'ELisA logbook connection: {configuration["website"]} (API: {configuration["connection"]})')
self.log.info(f'Connected to ELisA logbook at {self.socket}')
auth = credentials.get_login("elisa_logbook")
self.API_USER=auth.username
self.API_PSWD=auth.password

def _start_new_message_thread(self):
self.log.info("ELisA logbook: Next message will be a new thread")
Expand All @@ -66,58 +67,35 @@ def _start_new_message_thread(self):

def _send_message(self, subject:str, body:str, command:str):
user = self.session_handler.nanorc_user.username

elisa_arg = copy.deepcopy(self.elisa_arguments)

elisa_user = credentials.get_login('elisa')

import tempfile
with tempfile.NamedTemporaryFile() as tf:
try:
sso = {"ssocookie": self.session_handler.generate_elisa_cern_cookie(self.website, tf.name)}
elisa_arg.update(sso)
elisa_inst = Elisa(**elisa_arg)
answer = None
if not self.current_id:
self.log.info("ELisA logbook: Creating a new message thread")
message = MessageInsert()
message.author = user
message.subject = subject
for attr_name, attr_data in self.message_attributes[command].items():
if attr_data['set_on_new_thread']:
setattr(message, attr_name, attr_data['value'])
message.systemsAffected = ["DAQ"]
message.body = body
answer = elisa_inst.insertMessage(message)

else:
self.log.info(f"ELisA logbook: Answering to message ID{self.current_id}")
message = MessageReply(self.current_id)
message.author = user
message.systemsAffected = ["DAQ"]
for attr_name, attr_data in self.message_attributes[command].items():
if attr_data['set_on_reply']:
setattr(message, attr_name, attr_data['value'])
message.body = body
answer = elisa_inst.replyToMessage(message)
self.current_id = answer.id

except ElisaError as ex:
self.log.error(f"ELisA logbook: {str(ex)}")
self.log.error(answer)
raise ex

except Exception as e:
data = {'author':user, 'title':subject, 'body':body, 'command':command, 'systems':["daq"]}
try:
if not self.current_id:
r = requests.post(f'{self.socket}/v1/elisaLogbook/new_message/', auth=(self.API_USER, self.API_PSWD), json=data)
else:
data["id"] = self.current_id
r = requests.put(f'{self.socket}/v1/elisaLogbook/reply_to_message/', auth=(self.API_USER, self.API_PSWD), json=data)
r.raise_for_status()
response = r.json()
if r.status_code != 201:
self.log.error(f'Exception thrown while inserting data in elisa:')
e = (response['response'])
self.log.error(e)
import logging
if logging.DEBUG >= logging.root.level:
JonathanHancock0 marked this conversation as resolved.
Show resolved Hide resolved
self.console.print_exception()
raise e

self.log.info(f"ELisA logbook: Sent message (ID{self.current_id})")


else:
self.current_id = response['thread_id']
self.log.info(f"ELisA logbook: Sent message (ID{self.current_id})")
except requests.HTTPError as exc:
error = f"of HTTP Error (maybe failed auth, maybe ill-formed post message, ...)"
self.log.error(error)
except requests.ConnectionError as exc:
error = f"connection to {self.API_SOCKET} wasn't successful"
self.log.error(error)
except requests.Timeout as exc:
error = f"connection to {self.API_SOCKET} timed out"
self.log.error(error)

def message_on_start(self, messages:[str], session:str, run_num:int, run_type:str):
self._start_new_message_thread()
Expand Down