Skip to content
Snippets Groups Projects
server.py 6.65 KiB
Newer Older
  • Learn to ignore specific revisions
  • Swen Vermeul's avatar
    Swen Vermeul committed
    from notebook.utils import url_path_join
    from notebook.base.handlers import IPythonHandler
    from pybis import Openbis
    
    import json
    import os
    import urllib
    from subprocess import check_output
    from urllib.parse import urlsplit, urlunsplit
    import yaml
    
    openbis_connections = {}
    
    
    def _jupyter_server_extension_paths():
        return [{'module': 'jupyter-openbis-extension.server'}]
    
    def _load_configuration(filename='openbis-connections.yaml'):
        
        home = os.path.expanduser("~")
        abs_filename = os.path.join(home, '.jupyter', filename)
    
        with open(abs_filename, 'r') as stream:
            try:
                config = yaml.safe_load(stream)
                return config
            except yaml.YAMLexception as exc:
                print(exc)
                return None
            
    
    def load_jupyter_server_extension(nb_server_app):
        """Call when the extension is loaded.
        :param nb_server_app: Handle to the Notebook webserver instance.
        """
    
        # load the configuration file
        config = _load_configuration()
        if config is not None:
            for conn in config['connections']:
                try:
                    register_connection(conn)
                except Exception as exc:
                    print(exc)
                
    
        web_app = nb_server_app.web_app
        host_pattern = '.*$'
    
        base_url = web_app.settings['base_url']
    
        web_app.add_handlers(
            host_pattern, 
            [(url_path_join(
                base_url,
                '/openbis/dataset/(?P<connection_name>.*)?/(?P<permId>.*)'), 
                DataSetHandler
            )]
        ) 
        web_app.add_handlers(
            host_pattern, 
            [(url_path_join(
                base_url,
                '/openbis/sample/(?P<connection_name>.*)?/(?P<permId>.*)'), 
                SampleHandler
            )]
        ) 
        web_app.add_handlers(
            host_pattern, 
            [(url_path_join(base_url, '/openbis/conn'), OpenBISHandler)]
        )
    
    
        print("pybis loaded: {}".format(Openbis))
    
    
    def register_connection(connection_info):
        
        conn = OpenBISConnection(
            name           = connection_info['name'],
            url            = connection_info['url'],
            verify_certificates = connection_info['verify_certificates'],
            username       = connection_info['username'],
            password       = connection_info['password'],
            status         = 'not connected',
        )
        openbis_connections[conn.name] = conn
    
        openbis = Openbis(
            url = conn.url,
            verify_certificates = conn.verify_certificates
        )
        conn.openbis = openbis
    
        try:
            openbis.login(
                username = conn.username,
                password = conn.password
            )
            conn.status  = 'connected'
        except Exception as exc:
            conn.status  = 'FAILED: {}'.format(exc)
            raise exc
    
    
    def check_connection(connection_name):
        """Checks whether connection is valid and session is still active
        and tries to reconnect, if possible. Returns the active session
        """
        
        if connection_name not in openbis_connections:
            return None
            
        conn = openbis_connections[connection_name]
        if not conn.openbis.isSessionActive():
            conn.openbis.login(conn.username, conn.password)
             
    
    class OpenBISConnection:
        """register an openBIS connection
        """
    
        def __init__(self, **kwargs):
            for key in kwargs:
                setattr(self, key, kwargs[key])
    
        def is_session_active(self):
            return self.openbis.is_session_active()
    
        def reconnect(self):
            openbis.login(self.username, self.password)
    
    
    class OpenBISHandler(IPythonHandler):
        """Handle the requests to /openbis/conn
        """
    
        def get(self):
            """returns all available openBIS connections
            """
            connections= []
            for conn in openbis_connections.values():
                connections.append({
                    'name': conn.name,
                    'url' : conn.url
                })
    
            self.write({
                'connections': connections 
            })
            return
    
    class SampleHandler(IPythonHandler):
        """Handle the requests for /openbis/sample/connection/permId"""
    
        def get_datasets(self, conn, permId):
            sample = None
            try:
                sample = conn.openbis.get_sample(permId)
            except Exception:
                self.send_error(
                    reason = 'No such sample found: {}'.format(permId)
                )
                return
    
            datasets = sample.get_datasets().df
            dataset_records = datasets.to_dict(orient='records')
            self.write({'dataSets': dataset_records })
            return
    
        def get(self, **params):
            """Handle a request to /openbis/sample/connection_name/permId
            download the data and return a message
            """
            try:
                conn = openbis_connections[params['connection_name']]
            except KeyError:
                self.send_error(
                    reason = 'connection {} was not found'.format(params['connection_name'])
                )
                return
            
            results = self.get_datasets(conn, params['permId'])
    
    
    class DataSetHandler(IPythonHandler):
        """Handle the requests for /openbis/dataset/connection/permId"""
    
    
        def download_data(self, conn, permId):
            if not conn.is_session_active():
                try:
                    conn.reconnect()
                except Exception as exc:
                    self.send_error(
                        reason = 'connection to {} could not be established: {}'.format(conn.name, exc)
                    )
                    return
    
            try:
                dataset = conn.openbis.get_dataset(permId)
            except Exception as exc:
                self.send_error(
                    reason = 'No such dataSet found: {}'.format(permId)
                )
                return
    
            # dataset was found, download the data to the disk
            try: 
                destination = dataset.download()
            except Exception as exc:
                print(exc)
                self.send_error(
                    reason = 'Data for DataSet {} could not be downloaded: {}'.format(permId, exc)
                )
                return
                
            # return success message
            path = os.path.join(destination, dataset.permId)
            self.write({
                'permId'    : dataset.permId,
                'statusText': 'Data for DataSet {} was successfully downloaded to {}.'.format(dataset.permId, path)
            })
    
        def get(self, **params):
            """Handle a request to /openbis/dataset/connection_name/permId
            download the data and return a message
            """
            try:
                conn = openbis_connections[params['connection_name']]
            except KeyError:
                self.send_error(
                    reason = 'connection {} was not found'.format(params['connection_name'])
                )
                return
            
            results = self.download_data(conn, params['permId'])