mirror of
https://github.com/Steffo99/sophon.git
synced 2024-12-22 14:54:22 +00:00
🎓 Some progress in some places
This commit is contained in:
parent
ffb4cab002
commit
e789bfd158
3 changed files with 200 additions and 78 deletions
|
@ -260,7 +260,7 @@ Viene creato il modello che rappresenta un :ref:`gruppo di ricerca <Gruppi di ri
|
||||||
|
|
||||||
.. attribute:: slug: SlugField
|
.. attribute:: slug: SlugField
|
||||||
|
|
||||||
L'identificatore del gruppo di ricerca.
|
L'identificatore del gruppo di ricerca, usato nei percorsi dell'API.
|
||||||
|
|
||||||
.. attribute:: name: CharField
|
.. attribute:: name: CharField
|
||||||
|
|
||||||
|
@ -471,8 +471,78 @@ Vengono infine registrati nella pagina di amministrazione i modelli concreti def
|
||||||
|
|
||||||
Testing in Sophon Core
|
Testing in Sophon Core
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
.. module:: sophon.core.tests
|
||||||
|
|
||||||
.. todo:: Testing in Sophon Core
|
Per verificare che i `modelli <Modello base astratto>` e `viewset <Viewset astratti>` funzionassero correttamente e non avessero problemi di `sicurezza <Sicurezza>`, sono stati realizzati degli unit test in grado di rilevare la presenza di errori all'interno dell'app.
|
||||||
|
|
||||||
|
Test case generici
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Vengono definiti alcuni test case generici per facilitare le interazioni tra ``APITestCase`` e viewset.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
I nomi delle funzioni usano nomi con capitalizzazione inconsistente, in quanto lo stesso modulo `unittest` non rispetta lo stile suggerito in :pep:`8`.
|
||||||
|
|
||||||
|
.. class:: BetterAPITestCase(APITestCase)
|
||||||
|
|
||||||
|
.. method:: as_user(self, username: str, password: str = None) -> typing.ContextManager[None]
|
||||||
|
|
||||||
|
Context manager che permette di effettuare richieste all'API come uno specifico utente, effettuando il logout quando sono state effettuate le richieste necessarie.
|
||||||
|
|
||||||
|
.. method:: assertData(self, data: ReturnDict, expected: dict)
|
||||||
|
|
||||||
|
Asserzione che permette di verificare che l'oggetto restituito da una richiesta all'API contenga almeno le chiavi e i valori contenuti nel dizionario ``expected``.
|
||||||
|
|
||||||
|
.. class:: ReadSophonTestCase(BetterAPITestCase, metaclass=abc.ABCMeta)
|
||||||
|
|
||||||
|
Classe **astratta** che implementa metodi per testare rapidamente le azioni di un `.views.ReadSophonViewSet`.
|
||||||
|
|
||||||
|
.. classmethod:: get_basename(cls) -> str
|
||||||
|
|
||||||
|
Metodo **astratto** che deve restituire il basename del viewset da testare.
|
||||||
|
|
||||||
|
.. classmethod:: get_url(cls, kind: str, *args, **kwargs) -> str
|
||||||
|
|
||||||
|
Metodo utilizzato dal test case per trovare gli URL ai quali possono essere effettuate le varie azioni.
|
||||||
|
|
||||||
|
I seguenti metodi permettono di effettuare azioni sul viewset:
|
||||||
|
|
||||||
|
.. method:: list(self) -> rest_framework.response.Response
|
||||||
|
.. method:: retrieve(self, pk) -> rest_framework.response.Response
|
||||||
|
.. method:: custom_list(self, method: str, action: str, data: dict = None) -> rest_framework.response.Response
|
||||||
|
.. method:: custom_detail(self, method: str, action: str, pk, data: dict = None) -> rest_framework.response.Response
|
||||||
|
|
||||||
|
I seguenti metodi asseriscono che una determinata azione con determinati parametri risponderà con il codice di stato ``code``, e restituiscono i dati contenuti nella risposta se l'azione è riuscita (``200 <= code < 300``)
|
||||||
|
|
||||||
|
.. method:: assertActionList(self, code: int = 200) -> typing.Optional[ReturnDict]
|
||||||
|
.. method:: assertActionRetrieve(self, pk, code: int = 200) -> typing.Optional[ReturnDict]
|
||||||
|
.. method:: assertActionCustomList(self, method: str, action: str, data: dict = None, code: int = 200) -> typing.Optional[ReturnDict]
|
||||||
|
.. method:: assertActionCustomDetail(self, method: str, action: str, pk, data: dict = None, code: int = 200) -> typing.Optional[ReturnDict]
|
||||||
|
|
||||||
|
|
||||||
|
.. class:: WriteSophonTestCase(ReadSophonTestCase, metaclass=abc.ABCMeta)
|
||||||
|
|
||||||
|
Classe **astratta** che estende `.ReadSophonTestCase` con le azioni di un `.views.WriteSophonViewSet`.
|
||||||
|
|
||||||
|
.. method:: create(self, data) -> rest_framework.response.Response
|
||||||
|
.. method:: update(self, pk, data) -> rest_framework.response.Response
|
||||||
|
.. method:: destroy(self, pk) -> rest_framework.response.Response
|
||||||
|
|
||||||
|
.. method:: assertActionCreate(self, data, code: int = 201) -> typing.Optional[ReturnDict]
|
||||||
|
.. method:: assertActionUpdate(self, pk, data, code: int = 200) -> typing.Optional[ReturnDict]
|
||||||
|
.. method:: assertActionDestroy(self, pk, code: int = 200) -> typing.Optional[ReturnDict]
|
||||||
|
|
||||||
|
|
||||||
|
Test case concreti
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Vengono testate tutte le view dell'app tramite `.BetterAPITestCase` e tutti i viewset dell'app tramite `.ReadSophonTestCase` e `WriteSophonTestCase`.
|
||||||
|
|
||||||
|
.. class:: UsersByIdTestCase(ReadSophonTestCase)
|
||||||
|
.. class:: UsersByUsernameTestCase(ReadSophonTestCase)
|
||||||
|
.. class:: ResearchGroupTestCase(WriteSophonTestCase)
|
||||||
|
.. class:: SophonInstanceDetailsTestCase(BetterAPITestCase)
|
||||||
|
|
||||||
|
|
||||||
L'app Sophon Projects
|
L'app Sophon Projects
|
||||||
|
@ -482,27 +552,45 @@ L'app Sophon Projects
|
||||||
.. default-role:: obj
|
.. default-role:: obj
|
||||||
.. module:: sophon.projects
|
.. module:: sophon.projects
|
||||||
|
|
||||||
L'app `sophon.projects` è un app secondaria che dipende da `sophon.core` che introduce in Sophon il concetto di :ref:`progetto di ricerca`.
|
L'app `sophon.projects` è un app secondaria che dipende da `sophon.core` che introduce in Sophon il concetto di `progetto di ricerca <Progetti di ricerca in Sophon>`.
|
||||||
|
|
||||||
.. caution::
|
.. note::
|
||||||
|
|
||||||
Anche se l'app `sophon.projects` è opzionale (il progetto può funzionare senza di essa), si sconsiglia di disattivarla, in quanto il :ref:`modulo frontend` si aspetta che l'app sia attiva e solleverà un errore nel caso che i viewset forniti da questa app non siano disponibile.
|
L'app `sophon.projects` teoricamente è opzionale, in quanto il modulo backend può funzionare senza di essa, e può essere rimossa dal modulo `sophon.settings`.
|
||||||
|
|
||||||
|
Non è però possibile rimuoverla nella versione finale distribuita, in quanto il modulo `sophon.settings` non è modificabile dall'esterno, e in quanto il `modulo frontend <Modulo frontend>` non prevede questa funzionalità e si aspetta che i percorsi API relativi all'app siano disponibili.
|
||||||
|
|
||||||
|
Inoltre, rimuovendo l'app `sophon.projects` non sarà più possibile usare l'app `sophon.notebooks`, in quanto dipende da essa.
|
||||||
|
|
||||||
|
|
||||||
Modello del progetto di ricerca
|
Modello del progetto di ricerca
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
.. module:: sophon.projects.models
|
.. module:: sophon.projects.models
|
||||||
|
|
||||||
Viene introdotto un modello concreto che rappresenta un :ref:`progetto di ricerca`.
|
Viene introdotto un modello concreto che rappresenta un `progetto di ricerca <Progetti di ricerca in Sophon>`.
|
||||||
|
|
||||||
.. class:: ResearchProject(SophonGroupModel)
|
.. class:: ResearchProject(SophonGroupModel)
|
||||||
|
|
||||||
.. attribute:: slug: SlugField
|
.. attribute:: slug: SlugField
|
||||||
|
|
||||||
|
L'identificatore del progetto di ricerca, usato nei percorsi dell'API.
|
||||||
|
|
||||||
.. attribute:: group: ForeignKey → sophon.core.models.ResearchGroup
|
.. attribute:: group: ForeignKey → sophon.core.models.ResearchGroup
|
||||||
|
|
||||||
|
Lo `~sophon.core.models.ResearchGroup.slug` del gruppo di ricerca al quale appartiene il progetto.
|
||||||
|
|
||||||
.. attribute:: name: CharField
|
.. attribute:: name: CharField
|
||||||
|
|
||||||
|
Il nome completo del progetto di ricerca.
|
||||||
|
|
||||||
.. attribute:: description: TextField
|
.. attribute:: description: TextField
|
||||||
|
|
||||||
|
La descrizione del progetto di ricerca, da visualizzare in un riquadro "A proposito del progetto".
|
||||||
|
|
||||||
.. attribute:: visibility: CharField ["PUBLIC", "INTERNAL", "PRIVATE"]
|
.. attribute:: visibility: CharField ["PUBLIC", "INTERNAL", "PRIVATE"]
|
||||||
|
|
||||||
|
La `visibilità del progetto <Visibilità dei progetti>`.
|
||||||
|
|
||||||
|
|
||||||
Viewset del gruppo di ricerca
|
Viewset del gruppo di ricerca
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -547,27 +635,31 @@ L'app Sophon Notebooks
|
||||||
.. module:: sophon.notebooks
|
.. module:: sophon.notebooks
|
||||||
|
|
||||||
|
|
||||||
L'app `sophon.notebooks` è un app secondaria che dipende da `sophon.projects` che introduce in Sophon il concetto di :ref:`notebook`.
|
L'app `sophon.notebooks` è un app secondaria che dipende da `sophon.projects` che introduce in Sophon il concetto di `notebook <Notebook in Sophon>`.
|
||||||
|
|
||||||
.. caution::
|
.. note::
|
||||||
|
|
||||||
Anche se l'app `sophon.notebooks` è opzionale (il progetto può funzionare senza di essa), si sconsiglia di disattivarla, in quanto il :ref:`modulo frontend` si aspetta che l'app sia attiva e solleverà un errore nel caso che i viewset forniti da questa app non siano disponibile.
|
L'app `sophon.notebooks` teoricamente è opzionale, in quanto il modulo backend può funzionare senza di essa, e può essere rimossa dal modulo `sophon.settings`.
|
||||||
|
|
||||||
|
Non è però possibile rimuoverla nella versione finale distribuita, in quanto il modulo `sophon.settings` non è modificabile dall'esterno, e in quanto il `modulo frontend <Modulo frontend>` non prevede questa funzionalità e si aspetta che i percorsi API relativi all'app siano disponibili.
|
||||||
|
|
||||||
|
|
||||||
Funzionamento di un notebook
|
Funzionamento di un notebook
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Internamente, un notebook non è altro che un container Docker accessibile ad un determinato indirizzo il cui stato è sincronizzato con un oggetto del database del :ref:`modulo backend`.
|
Internamente, un notebook non è altro che un container `Docker` accessibile ad un determinato indirizzo il cui stato è sincronizzato con un oggetto del database del `modulo backend <Modulo backend>`.
|
||||||
|
|
||||||
|
|
||||||
Modalità sviluppo
|
Modalità sviluppo
|
||||||
"""""""""""""""""
|
"""""""""""""""""
|
||||||
|
|
||||||
Per facilitare lo sviluppo di Sophon, sono previste due modalità di operazione di quest'ultimo:
|
Per facilitare lo sviluppo di Sophon, sono state realizzate due modalità di operazione di quest'ultimo.
|
||||||
|
|
||||||
- nella prima, la **modalità sviluppo**, il :ref:`modulo proxy` non è in esecuzione, ed è possibile collegarsi direttamente ai container attraverso collegamenti a ``localhost``;
|
* Nella prima, la **modalità sviluppo**, il `modulo proxy <Modulo proxy>` non è in esecuzione, ed è possibile collegarsi direttamente ai container all'indirizzo IP locale ``127.0.0.1``.
|
||||||
|
|
||||||
- nella seconda, la **modalità produzione**, il :ref:`modulo proxy` è in esecuzione all'interno di un container Docker, e si collega agli altri container attraverso i rispettivi network Docker agli indirizzi comunicatogli dal :ref:`modulo backend`.
|
Il `modulo frontend <Modulo frontend>` non supporta questa modalità, in quanto intesa solamente per lo sviluppo del modulo backend.
|
||||||
|
|
||||||
|
* Nella seconda, la **modalità produzione**, il `modulo proxy <Modulo proxy>` è in esecuzione all'interno di un container Docker, e si collega ai `moduli Jupyter <Modulo Jupyter>` attraverso i relativi network Docker tramite indirizzi presenti all'interno .
|
||||||
|
|
||||||
.. image:: notebooks_diagram.png
|
.. image:: notebooks_diagram.png
|
||||||
|
|
||||||
|
@ -578,7 +670,7 @@ Gestione della rubrica del proxy
|
||||||
|
|
||||||
Viene creata una classe per la gestione della rubrica del proxy, utilizzando il modulo `dbm.gnu`, supportato da HTTPd.
|
Viene creata una classe per la gestione della rubrica del proxy, utilizzando il modulo `dbm.gnu`, supportato da HTTPd.
|
||||||
|
|
||||||
La rubrica mappa gli URL pubblici dei notebook a URL privati relativi al :ref:`modulo proxy`, in modo da effettuare reverse proxying **dinamico**.
|
La rubrica mappa gli URL pubblici dei notebook a URL privati relativi al `modulo proxy <Modulo proxy>`, in modo da effettuare reverse proxying **dinamico**.
|
||||||
|
|
||||||
.. class:: ApacheDB
|
.. class:: ApacheDB
|
||||||
|
|
||||||
|
@ -603,7 +695,7 @@ Connessione al daemon Docker
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
.. module:: sophon.notebooks.docker
|
.. module:: sophon.notebooks.docker
|
||||||
|
|
||||||
Per facilitare l'utilizzo del daemon Docker per la gestione dei container dei notebook, viene utilizzato il modulo `docker`.
|
Per facilitare l'utilizzo del daemon Docker per la gestione dei container dei notebook, viene utilizzato il modulo :mod:`docker`.
|
||||||
|
|
||||||
.. function:: get_docker_client() -> docker.DockerClient
|
.. function:: get_docker_client() -> docker.DockerClient
|
||||||
|
|
||||||
|
@ -617,7 +709,7 @@ Per facilitare l'utilizzo del daemon Docker per la gestione dei container dei no
|
||||||
Controllo dello stato di salute
|
Controllo dello stato di salute
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Il modulo `docker` viene esteso implementando supporto per l'istruzione ``HEALTHCHECK`` dei ``Dockerfile``.
|
Il modulo :mod:`docker` viene esteso implementando supporto per l'istruzione ``HEALTHCHECK`` dei ``Dockerfile``.
|
||||||
|
|
||||||
.. class:: HealthState(enum.IntEnum)
|
.. class:: HealthState(enum.IntEnum)
|
||||||
|
|
||||||
|
@ -648,11 +740,19 @@ Il modulo `docker` viene esteso implementando supporto per l'istruzione ``HEALTH
|
||||||
|
|
||||||
Funzione bloccante che restituisce solo quando lo stato del container specificato non è `HealthState.STARTING`.
|
Funzione bloccante che restituisce solo quando lo stato del container specificato non è `HealthState.STARTING`.
|
||||||
|
|
||||||
|
.. danger::
|
||||||
|
|
||||||
|
L'implementazione di questa funzione potrebbe causare rallentamenti nella risposta alle pagine web per via di una chiamata al metodo `time.sleep` al suo interno.
|
||||||
|
|
||||||
|
Ciò è dovuto al mancato supporto alle funzioni asincrone nella versione attuale di `rest_framework`.
|
||||||
|
|
||||||
|
Si è deciso di mantenere comunque la funzionalità a scopi dimostrativi e per compatibilità futura.
|
||||||
|
|
||||||
|
|
||||||
Generazione di token sicuri
|
Generazione di token sicuri
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Si è scelto di rendere completamente trasparente all'utente il meccanismo di autenticazione a JupyterLab.
|
Per rendere l'interfaccia grafica più `intuibile <intuibile>`, si è scelto di rendere trasparente all'utente il meccanismo di autenticazione a JupyterLab.
|
||||||
|
|
||||||
Pertanto, si è verificata la necessità di generare token crittograficamente sicuri da richiedere per l'accesso a JupyterLab.
|
Pertanto, si è verificata la necessità di generare token crittograficamente sicuri da richiedere per l'accesso a JupyterLab.
|
||||||
|
|
||||||
|
@ -665,7 +765,7 @@ Modello dei notebook
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
.. module:: sophon.notebooks.models
|
.. module:: sophon.notebooks.models
|
||||||
|
|
||||||
Viene definito il modello rappresentante un :ref:`notebook`.
|
Viene definito il modello rappresentante un `notebook <Notebook in Sophon>`.
|
||||||
|
|
||||||
.. class:: Notebook(SophonGroupModel)
|
.. class:: Notebook(SophonGroupModel)
|
||||||
|
|
||||||
|
@ -673,22 +773,30 @@ Viene definito il modello rappresentante un :ref:`notebook`.
|
||||||
|
|
||||||
Lo slug dei notebook prevede ulteriori restrizioni oltre a quelle previste dallo `django.db.models.SlugField`:
|
Lo slug dei notebook prevede ulteriori restrizioni oltre a quelle previste dallo `django.db.models.SlugField`:
|
||||||
|
|
||||||
- non può essere uno dei seguenti valori: ``api``, ``static``, ``proxy``, ``backend``, ``frontend``, ``src``;
|
* non può essere uno dei seguenti valori: ``api``, ``static``, ``proxy``, ``backend``, ``frontend``, ``src``;
|
||||||
- non può iniziare o finire con un trattino ``-``.
|
* non può iniziare o finire con un trattino ``-``.
|
||||||
|
|
||||||
.. attribute:: project: ForeignKey → sophon.projects.models.ResearchProject
|
.. attribute:: project: ForeignKey → sophon.projects.models.ResearchProject
|
||||||
|
|
||||||
|
Il `progetto <Progetti di ricerca in Sophon>` che include questo notebook.
|
||||||
|
|
||||||
.. attribute:: name: CharField
|
.. attribute:: name: CharField
|
||||||
|
|
||||||
|
Il nome del notebook.
|
||||||
|
|
||||||
.. attribute:: locked_by: ForeignKey → django.contrib.auth.models.User
|
.. attribute:: locked_by: ForeignKey → django.contrib.auth.models.User
|
||||||
|
|
||||||
|
L'`utente <Utenti in Sophon>` che ha richiesto il blocco del notebook, o `None` in caso il notebook non sia bloccato.
|
||||||
|
|
||||||
.. attribute:: container_image: CharField ["ghcr.io/steffo99/sophon-jupyter"]
|
.. attribute:: container_image: CharField ["ghcr.io/steffo99/sophon-jupyter"]
|
||||||
|
|
||||||
Campo che specifica l'immagine che il client Docker dovrà avviare per questo notebook.
|
Campo che specifica l'immagine che il client `Docker` dovrà avviare per questo notebook.
|
||||||
|
|
||||||
Al momento ne è configurata una sola per semplificare l'esperienza utente, ma altre possono essere specificate per permettere agli utenti più scelta.
|
Al momento ne è supportata una sola per semplificare l'esperienza utente, ma altre possono essere aggiunte al file che definisce il modello per permettere agli utenti di scegliere tra più immagini.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Al momento, le immagini specificate devono esporre un server web sulla porta ``8888``, e supportare il protocollo di connessione di Jupyter, ovvero :samp:`{PROTOCOLLO}://immagine:8888/lab?token={TOKEN}` e :samp:`{PROTOCOLLO}://immagine:8888/tree?token={TOKEN}`.
|
Al momento, Sophon si aspetta che tutte le immagini specificate espongano un server web sulla porta ``8888``, e supportino il protocollo di autenticazione di Jupyter, ovvero che sia possibile raggiungere il container ai seguenti indirizzi: :samp:`{PROTOCOLLO}://immagine:8888/lab?token={TOKEN}` e :samp:`{PROTOCOLLO}://immagine:8888/tree?token={TOKEN}`.
|
||||||
|
|
||||||
.. attribute:: jupyter_token: CharField
|
.. attribute:: jupyter_token: CharField
|
||||||
|
|
||||||
|
@ -702,11 +810,11 @@ Viene definito il modello rappresentante un :ref:`notebook`.
|
||||||
|
|
||||||
.. attribute:: port: IntegerField
|
.. attribute:: port: IntegerField
|
||||||
|
|
||||||
La porta assegnata al container Docker dell'oggetto nel caso in cui Sophon sia avviato in "modalità sviluppo", ovvero con il :ref:`modulo proxy` in esecuzione sul sistema host.
|
La porta TCP locale assegnata al container Docker dell'oggetto nel caso in cui Sophon sia avviato in `modalità sviluppo <Modalità sviluppo>`.
|
||||||
|
|
||||||
.. attribute:: internal_url: CharField
|
.. attribute:: internal_url: CharField
|
||||||
|
|
||||||
L'URL a cui è accessibile il container Docker dell'oggetto nel caso in cui Sophon non sia avviato in "modalità sviluppo", ovvero con il :ref:`modulo proxy` in esecuzione all'interno di un container.
|
L'URL a cui è accessibile il container Docker dell'oggetto nel caso in cui Sophon non sia avviato in `modalità sviluppo <Modalità sviluppo>`.
|
||||||
|
|
||||||
.. method:: log(self) -> logging.Logger
|
.. method:: log(self) -> logging.Logger
|
||||||
:property:
|
:property:
|
||||||
|
@ -717,23 +825,23 @@ Viene definito il modello rappresentante un :ref:`notebook`.
|
||||||
|
|
||||||
.. method:: enable_proxying(self) -> None
|
.. method:: enable_proxying(self) -> None
|
||||||
|
|
||||||
Aggiunge l'indirizzo del notebook alla rubrica del proxy.
|
Aggiunge l'indirizzo del notebook alla `rubrica del proxy <Gestione della rubrica del proxy>`.
|
||||||
|
|
||||||
.. method:: disable_proxying(self) -> None
|
.. method:: disable_proxying(self) -> None
|
||||||
|
|
||||||
Rimuove l'indirizzo del notebook dalla rubrica del proxy.
|
Rimuove l'indirizzo del notebook dalla `rubrica del proxy <Gestione della rubrica del proxy>`.
|
||||||
|
|
||||||
.. method:: sync_container(self) -> t.Optional[docker.models.containers.Container]
|
.. method:: sync_container(self) -> t.Optional[docker.models.containers.Container]
|
||||||
|
|
||||||
Sincronizza lo stato dell'oggetto nel database con lo stato del container Docker nel sistema.
|
Sincronizza lo stato dell'oggetto nel database con lo stato del container `Docker` nel sistema.
|
||||||
|
|
||||||
.. method:: create_container(self) -> docker.models.containers.Container
|
.. method:: create_container(self) -> docker.models.containers.Container
|
||||||
|
|
||||||
Crea e configura un container Docker per l'oggetto, con l'immagine specificata in `.container_image`.
|
Crea e configura un container `Docker` per l'oggetto, con l'immagine specificata in `.container_image`.
|
||||||
|
|
||||||
.. method:: start(self) -> None
|
.. method:: start(self) -> None
|
||||||
|
|
||||||
Tenta di creare e avviare un container Docker per l'oggetto, bloccando fino a quando esso non sarà avviato con `~.docker.sleep_until_container_has_started`.
|
Tenta di creare e avviare un container `Docker` per l'oggetto, bloccando fino a quando esso non sarà avviato con `~.docker.sleep_until_container_has_started`.
|
||||||
|
|
||||||
.. method:: stop(self) -> None
|
.. method:: stop(self) -> None
|
||||||
|
|
||||||
|
@ -783,20 +891,30 @@ Come per il modulo `sophon.projects`, vengono creati due viewset per interagire
|
||||||
Accessibile all'URL :samp:`/api/notebooks/by-project/{PROJECT_SLUG}/{NOTEBOOK_SLUG}/`.
|
Accessibile all'URL :samp:`/api/notebooks/by-project/{PROJECT_SLUG}/{NOTEBOOK_SLUG}/`.
|
||||||
|
|
||||||
|
|
||||||
Dockerizzazione del modulo backend
|
Containerizzazione del modulo backend
|
||||||
----------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
.. todo:: Dockerizzazione
|
Il modulo backend è incapsulato in un'immagine `Docker` basata sull'immagine ufficiale `python:3.9.7-bullseye <https://hub.docker.com/_/python>`_.
|
||||||
|
|
||||||
Modulo frontend
|
L'immagine utilizza `Poetry` per installare le dipendenze, poi esegue il file ``docker_start.sh`` riportato sotto che effettua le migrazioni, prepara i file statici di Django e `prova a creare un superutente <Aggiunta di un nuovo comando di gestione>`, per poi avviare il progetto Django attraverso :mod:`gunicorn` sulla porta 8000.
|
||||||
===============
|
|
||||||
|
|
||||||
.. todo:: Modulo frontend
|
.. code-block:: bash
|
||||||
|
|
||||||
|
poetry run python -O ./manage.py migrate --no-input
|
||||||
|
poetry run python -O ./manage.py collectstatic --no-input
|
||||||
|
poetry run python -O ./manage.py initsuperuser
|
||||||
|
poetry run python -O -m gunicorn sophon.wsgi:application --workers=4 --bind=0.0.0.0:8000
|
||||||
|
|
||||||
|
|
||||||
|
Realizzazione del modulo frontend
|
||||||
|
=================================
|
||||||
|
.. default-domain:: js
|
||||||
|
|
||||||
|
Il modulo frontend è stato realizzato come un package `Node.js` denominato ``@steffo/sophon-frontend``, e poi `containerizzato <Containerizzazione del modulo frontend>`, creando un'immagine `Docker` standalone, esattamente come per il `modulo backend <Containerizzazione del modulo backend>`.
|
||||||
|
|
||||||
|
|
||||||
Struttura delle directory
|
Struttura delle directory
|
||||||
-------------------------
|
-------------------------
|
||||||
.. default-domain:: js
|
|
||||||
|
|
||||||
Le directory di :mod:`@steffo45/sophon-frontend` sono strutturate nella seguente maniera:
|
Le directory di :mod:`@steffo45/sophon-frontend` sono strutturate nella seguente maniera:
|
||||||
|
|
||||||
|
@ -821,8 +939,6 @@ public
|
||||||
|
|
||||||
Comunicazione con il server
|
Comunicazione con il server
|
||||||
---------------------------
|
---------------------------
|
||||||
.. default-domain:: js
|
|
||||||
|
|
||||||
|
|
||||||
Axios
|
Axios
|
||||||
^^^^^
|
^^^^^
|
||||||
|
@ -938,7 +1054,7 @@ Contesti innestati
|
||||||
------------------
|
------------------
|
||||||
.. default-domain:: js
|
.. default-domain:: js
|
||||||
|
|
||||||
Per minimizzare i rerender, l'applicazione è organizzata a "contesti innestati".
|
Per minimizzare i re-render, l'applicazione è organizzata a "contesti innestati".
|
||||||
|
|
||||||
|
|
||||||
I contesti
|
I contesti
|
||||||
|
@ -1015,6 +1131,35 @@ Viene definita una funzione in grado di comprendere gli URL contestuali:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Componenti contestuali
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Per ciascun contesto sono stati realizzati vari componenti.
|
||||||
|
|
||||||
|
I più significativi comuni a tutti i contesti sono i `ResourcePanel` e le `ListBox`.
|
||||||
|
|
||||||
|
.. function:: ResourcePanel({...})
|
||||||
|
|
||||||
|
Panello che rappresenta un'`entità di Sophon <Entità di Sophon>`, diviso in quattro parti:
|
||||||
|
|
||||||
|
* icona (a sinistra)
|
||||||
|
* nome della risorsa (a destra dell'icona)
|
||||||
|
* bottoni (a destra)
|
||||||
|
* testo (a sinistra dei bottoni)
|
||||||
|
|
||||||
|
.. figure:: resource_panel.png
|
||||||
|
|
||||||
|
Un `ResourcePanel` rappresentante un `gruppo di ricerca <Gruppi di ricerca in Sophon>`.
|
||||||
|
|
||||||
|
.. function:: ListBox({...})
|
||||||
|
|
||||||
|
Riquadro che mostra le risorse di un `useManagedViewSet` raffigurandole come tanti `ResourcePanel`.
|
||||||
|
|
||||||
|
.. figure:: list_box.png
|
||||||
|
|
||||||
|
Un `ListBox` che mostra l'elenco di notebook in un progetto.
|
||||||
|
|
||||||
|
|
||||||
Routing basato sui contesti
|
Routing basato sui contesti
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -1098,42 +1243,26 @@ Cache
|
||||||
Viene salvato l'elenco di tutti i membri dell':ref:`istanza` in uno speciale contesto :data:`CacheContext` in modo da poter risolvere gli id degli utenti al loro username senza dover effettuare ulteriori richieste.
|
Viene salvato l'elenco di tutti i membri dell':ref:`istanza` in uno speciale contesto :data:`CacheContext` in modo da poter risolvere gli id degli utenti al loro username senza dover effettuare ulteriori richieste.
|
||||||
|
|
||||||
|
|
||||||
Dockerizzazione del modulo frontend
|
Containerizzazione del modulo frontend
|
||||||
-----------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
.. todo:: Dockerizzazione del modulo frontend
|
Il modulo frontend è incapsulato in un'immagine `Docker` basata sull'immagine ufficiale `node:16.11.1-bullseye <https://hub.docker.com/_/node>`_.
|
||||||
|
|
||||||
|
L'immagine installa le dipendenze del modulo con `Yarn`, per poi eseguire il comando ``yarn run serve``, che avvia la procedura di preparazione della pagina e la rende disponibile su un webserver locale alla porta 3000.
|
||||||
|
|
||||||
|
|
||||||
Modulo proxy
|
Modulo proxy
|
||||||
============
|
============
|
||||||
|
|
||||||
Il *modulo proxy* consiste in un webserver che riceve tutte le richieste HTTP dirette ad uno degli altri moduli e le smista in base a regole statiche e dinamiche.
|
Il modulo proxy consiste in un file di configurazione di `Apache HTTP Server`.
|
||||||
|
|
||||||
È collocato all'interno del repository in ``/proxy``.
|
Il file di configurazione abilita i moduli httpd `rewrite`_, `proxy`_, `proxy_wstunnel`_ e `proxy_http`_, impostando quest'ultimo per inoltrare l'header `Host`_ alle pagine verso cui viene effettuato reverse proxying.
|
||||||
|
|
||||||
|
|
||||||
Tecnologie utilizzate
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
- Il server web `Apache HTTPd`_
|
|
||||||
- Il modulo `rewrite`_
|
|
||||||
- Il modulo `proxy`_
|
|
||||||
- Il modulo `proxy_http`_
|
|
||||||
- Il modulo `proxy_wstunnel`_
|
|
||||||
|
|
||||||
.. _Apache HTTPd: https://httpd.apache.org/
|
|
||||||
.. _rewrite: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
|
.. _rewrite: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
|
||||||
.. _proxy: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
|
.. _proxy: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
|
||||||
.. _proxy_http: https://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html
|
.. _proxy_http: https://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html
|
||||||
.. _proxy_wstunnel: https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html
|
.. _proxy_wstunnel: https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html
|
||||||
|
.. _Host: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host
|
||||||
|
|
||||||
Funzionamento del modulo
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
Il modulo proxy è composto da un file di configurazione di `Apache HTTPd`_ e di un ``Dockerfile`` che lo copia all'interno dell'immagine Docker ufficiale ``httpd:2.4``.
|
|
||||||
|
|
||||||
Il file di configurazione abilita i moduli `rewrite`_, `proxy`_, `proxy_wstunnel`_ e `proxy_http`_, impostando quest'ultimo per inoltrare l'header `Host <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host>`_ alle pagine verso cui viene effettuato reverse proxying.
|
|
||||||
|
|
||||||
Inoltre, nel file di configurazione viene abilitato il ``RewriteEngine``, che viene utilizzato per effettuare reverse proxying secondo le seguenti regole:
|
Inoltre, nel file di configurazione viene abilitato il ``RewriteEngine``, che viene utilizzato per effettuare reverse proxying secondo le seguenti regole:
|
||||||
|
|
||||||
|
@ -1198,17 +1327,11 @@ Inoltre, nel file di configurazione viene abilitato il ``RewriteEngine``, che vi
|
||||||
|
|
||||||
Tutte le regole usano il flag ``L`` di ``RewriteRule``, che porta il motore di rewriting a ignorare tutte le regole successive, come il ``return`` di una funzione di un linguaggio di programmazione imperativo.
|
Tutte le regole usano il flag ``L`` di ``RewriteRule``, che porta il motore di rewriting a ignorare tutte le regole successive, come il ``return`` di una funzione di un linguaggio di programmazione imperativo.
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
I blocchi di codice all'interno di questa sezione sono stati inseriti manualmente e potrebbero non essere interamente aggiornati alla versione più recente del file.
|
|
||||||
|
|
||||||
Si consiglia di consultare il file ``httpd.conf`` in caso si necessiti di informazioni aggiornate.
|
|
||||||
|
|
||||||
|
|
||||||
Dockerizzazione del modulo proxy
|
Dockerizzazione del modulo proxy
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
.. todo:: Dockerizzazione del modulo proxy
|
Il modulo proxy è incapsulato in un'immagine `Docker` basata sull'immagine ufficiale `httpd:2.4 <https://hub.docker.com/_/httpd>`_, che si limita ad applicare la configurazione personalizzata.
|
||||||
|
|
||||||
|
|
||||||
Modulo Jupyter
|
Modulo Jupyter
|
||||||
|
@ -1218,13 +1341,6 @@ Il *modulo Jupyter* consiste in un ambiente `Jupyter <https://jupyter.org/>`_ e
|
||||||
|
|
||||||
È collocato all'interno del repository in ``/jupyter``.
|
È collocato all'interno del repository in ``/jupyter``.
|
||||||
|
|
||||||
Progetti utilizzati
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Le immagini Docker ufficiali di Jupyter `jupyter/docker-stacks <https://github.com/jupyter/docker-stacks>`_
|
|
||||||
- Il tema `JupyterLab Sophon <https://github.com/Steffo99/jupyterlab-theme-sophon>`_ (realizzato durante il tirocinio)
|
|
||||||
- Il tool per il trasferimento dati `curl <https://curl.se/>`_
|
|
||||||
|
|
||||||
|
|
||||||
Sviluppo del tema per Jupyter
|
Sviluppo del tema per Jupyter
|
||||||
=============================
|
=============================
|
||||||
|
|
BIN
thesis/source/docs/5_implementazione/list_box.png
(Stored with Git LFS)
Normal file
BIN
thesis/source/docs/5_implementazione/list_box.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
thesis/source/docs/5_implementazione/resource_panel.png
(Stored with Git LFS)
Normal file
BIN
thesis/source/docs/5_implementazione/resource_panel.png
(Stored with Git LFS)
Normal file
Binary file not shown.
Loading…
Reference in a new issue