• Non ci sono risultati.

Implementazione a livello tecnico della pipeline di ETL

Nel documento Università Politecnica delle Marche (pagine 76-83)

Implementazione del sistema

4.2 Implementazione della pipeline di ETL

4.2.3 Implementazione a livello tecnico della pipeline di ETL

In questa sezione spiegheremo dettagliatamente lŠimplementazione della pipeline di ETL. Per far questo, ripercorreremo i passi implementativi effettuati partendo

dallŠestrazione dei dati dalla sorgente di interesse. Fatto questo, poi, procederemo con la descrizione del caricamento dei dati sul bucket S3 aziendale per poi concludere mostrando come siamo riusciti a prendere i dati da questŠultimo repository e caricarli sulla piattaforma per poter essere analizzati.

E fondamentale sottolineare che il bucket S3 in questione si trova nella stessa‘ Availability zone della nostra VPC (cio‘e Francoforte) che, come spiegato nel capitolo sulla progettazione, ‘e un requisito necessario per risultare visibile alle componenti della VPC che vogliono accedervi.

Lo step iniziale, quindi, ‘e stato quello di capire come estrarre i dati dalla sorgente.

Il primo problema che ‘e stato affrontato, durante questa fase, ‘e stato quello di evitare di dover utilizzare lŠinterfaccia graĄca per il download (e, quindi, lŠestrazione) dei dati. LŠinterfaccia graĄca dei dati Land Cover di Copernicus, infatti, agevola sicuramente la user interface dellŠutente ma va a discapito di chi ha bisogno di costruire strumenti automatici per lŠestrazione dei dati. Per aggirare lŠinterfaccia graĄca che faceva da ponte tra noi e la sorgente, siamo andati ad analizzare quali erano gli URI (Uniform Resource IdentiĄer) ai quali venivamo reindirizzati nella fase di download (che, come avevamo detto, erano dei riferimenti ad oggetti su un bucket S3 pubblico). Quindi, la fase di analisi dei vari URI ci ‘e servita per capire quale fosse la struttura di questi ultimi per poi ricostruirla automaticamente. Il risultato che ne ‘e venuto fuori ‘e il seguente:

• La prima parte dellŠURL ‘e Ąssa ed ‘e formata dalla seguente stringa: Ťs3://

vito.landcover.global/v3.0.1/Ť.

• Alla precedente stringa seguiranno lŠanno (che, come abbiamo detto, ‘e compre-so tra il 2014 ed il 2019), la latitudine e la longitudine nel seguente formato:

Year/LonLat/LonLat.

• Poi, vi ‘e una parte Ąssa: PROBAV LC100 global v3.0.1 .

• Successivamente, ci sar‘a lŠanno seguito da una stringa che varia in base allŠanno:

year-[nrt|base|conso].

• Il tutto termina con una stringa Ąnale che esprime il codice EPSG (EPSG Geo-detic Parameter Dataset) del dato e lŠestensione del dato (TIF); la stringa ‘e la seguente Discrete-Classification-map EPSG-4326.tif.

Al termine della ricostruzione dei vari pattern che compongono lŠURI, la fase successiva ‘e stata quella di effettuare la migrazione del dato dal bucket S3 sorgente al bucket S3 aziendale di Hesplora. Ricordiamo che siamo totalmente in ambito AWS, quindi abbiamo cercato di sfruttare appieno gli strumenti che ci vengono messi a disposizione da questa tecnologia. Il comando che ‘e stato utilizzato per svolgere le attivit‘a di trasferimento del dato da un bucket S3 ad un altro ‘e Şaws s3 cpŤ (disponibile attraverso la AWS CLI2). Ricordiamo che ‘e stato possibile utilizzare questo comando dal momento che il bucket S3 sorgente era pubblico e, nello speciĄco, aveva una concessione sugli accessi in lettura per i suoi oggetti;

questo, in AWS, ‘e possibile speciĄcarlo tramite la conĄgurazione di liste di controllo

2 LŠinterfaccia a riga di comando di AWS, o CLI (Command Line Interface), ‘e uno stru-mento uniĄcato che consente di gestire i servizi AWS. Scaricando e conĄgurando questo unico tool, infatti, ‘e possibile controllare molti servizi AWS da riga di comando, nonch´e automatizzarli mediante script. La CLI di AWS introduce un set di comandi atti a gestire il trasferimento di Ąle in modo efficiente da e verso un bucket S3.

accessi (ACL), policy del bucket e/o policy dellŠaccess point. CŠ‘e da notare, inoltre, che ‘e stato necessario deĄnire anche le policy di sicurezza del nostro bucket S3 per far s‘ı che potessero essere caricati dati al suo interno. Questo servizio, infatti, prevede delle policy di sicurezza relative agli accessi al bucket che possono essere conĄgurate per garantire sicurezza a qualsiasi livello (non solo in lettura, quindi, ma anche in scrittura). Rimanendo sempre sul tema della sicurezza e sulla gestione dellŠaccesso ai dati, nel momento in cui abbiamo lanciato il comando sopracitato per trasferire il Ąle sul nostro bucket S3 (esprimendo Ąle sorgente e bucket di destinazione attraverso corrispettive URI) ‘e stato speciĄcato il parametro Ş--acl public-readŤ per settare un accesso pubblico al Ąle; questŠultimo ‘e stato impostato sullo stato Şaccessibile in letturaŤ perch´e questa conĄgurazione sar‘a necessaria sia durante la creazione dei cataloghi STAC che durante lŠindicizzazione nella piattaforma IT.

Arrivati a questo punto, dunque, abbiamo il dato caricato nel nostro repository S3. Ora, dobbiamo creare il Ąle STAC che ci permetter‘a di indicizzare il dato sulla piattaforma Open Data Cube. Per far questo vi sono svariati tool open source (rio-stac, PySTAC, STAC Server, pygeoapi, etc.), ciascuno dei quali offre allŠutente diverse implementazioni. Il metodo che ‘e stato utilizzato ‘e Şrio-stacŤ (plug-in di ŞrasterioŤ), una libreria dellŠecosistema Python per la creazione di elementi STAC validi a partire da un set di dati raster. Grazie allŠapplicazione di rio-stac, dunque, riusciamo a creare un catalogo STAC a partire dal dato presente nel bucket S3. Un esempio di un possibile Ąle STAC, in formato JSON, risultante dallŠelaborazione del suddetto dato da parte di rio-stac viene mostrato in Figura 4.7.

Figura 4.7.Catalogo STAC creato attraverso rio-stac

Una volta creato questo Ąle in formato JSON, ‘e necessario caricarlo nel nostro bucket S3 nella stessa location del dato al quale si riferisce. ‘E indispensabile, inoltre, che anche per il Ąle STAC impostiamo un accesso pubblico in lettura (come ‘e stato anche per il dato a cui esso si riferisce) dal momento che deve essere raggiungibile per il metodo di indicizzazione su ODC (che introdurremo a breve).

In questo momento, dunque, abbiamo soltanto la necessit‘a di caricare il dato nella piattaforma Open Data Cube andandolo a prendere dal nostro bucket S3. Per far questo, come abbiamo detto nella sezione riguardante le tecnologie utilizzate, sfrutteremo la libreria Şodc.stacŤ che ci permetter‘a di indicizzare i dati su Open Data Cube sfruttando lo STAC catalog del dato stesso. Per lanciare lo script Python che contiene il comando odc.stac abbiamo bisogno soltanto di un notebook Jupyter e dellŠURL relativo allo STAC Ąle (in formato JSON). In Figura 4.8 viene mostrato un possibile esempio di indicizzazione del dato in questione direttamente dal nostro bucket S3 utilizzando odc.stac.

Figura 4.8.Esempio di indicizzazione di dati satellitari su Jupyter Notebook attraverso odc.stac

Arrivati a questo punto abbiamo terminato la pipeline di ETL e abbiamo caricato il dato sulla piattaforma; questŠultimo, ora, ‘e pronto per essere analizzato dai data analyst e dai data scientist attraverso lŠapplicazione di algoritmi di intelligenza artiĄciale e deep learning.

Nel listato 4.1 presenteremo il listato del codice realizzato.

#!/bin/bash

#This script allows, by specifying 4 parameters, to extract the Land Cover data belonging to the Copernicus source.

Once the data has been extracted, the script allows you to load them on the s3 bucket and to create the STAC catalog (in json format) which will be loaded together with the data.

#INPUT: ./ETL_script.sh --year <YEAR> --hemi <HEMISPHERE> --lat <LATITUDE> --lon <LONGITUDE>

#OUTPUT: <STAC catalog URL on s3 bucket>

#Note: to set the AWS credentials the command is the following: aws configure

# Prints how the script works and its flags function usage {

echo "usage: ./landcover_auto [--year year] [--hemi hemisphere] [--lat latitude] [--lon longitude]"

echo " --year year specify the year of interest"

echo " choices: 2015, 2016, 2017, 2018, 2019"

echo " --hemi hesmisphere specify in which hemisphere the scene is located"

echo " choices: NW, NE, SW, SE"

echo " --lat lat specify the minimum latitude (unsigned) of the scene"

echo " choices: 80, 60, ..., 00 for north"

echo " choices: 40, 20, 00 for south"

echo " --lon lon specify the minimum longitude (unsigned) of the scene"

echo " choices: 180, 160, ..., 020, 000 for west"

echo " choices: 160, 140, ..., 020, 000 for east"

exit 1 }

# If no argument is given, prints the usage if [[ $# -eq 0 ]] ; then

usage exit 1 fi

# Translates the long flags given in input into shor flags in order to let getopts understand them for arg in "$@"; do

shift case "$arg" in

"--year") set -- "$@" "-y" ;;

"--hemi") set -- "$@" "-h" ;;

"--lat") set -- "$@" "-a" ;;

"--lon") set -- "$@" "-o" ;;

*) set -- "$@" "$arg"

esac done

# Maps the flags to variables while getopts ’y:h:a:o:’ flag

# Formats the latitude and longitude variables if [[ "$hemi" == "NW" ]]

then

#read -p "Please enter the north latitude: " lat

#read -p "Please enter the west longitude: " lon llat="${lat}"

llon="-${lon}"

lat="N${lat}"

lon="W${lon}"

elif [[ "$hemi" == "NE" ]]

then

#read -p "Please enter the north latitude: " lat

#read -p "Please enter the east longitude: " lon llat="${lat}"

llon="${lon}"

lat="N${lat}"

lon="E${lon}"

elif [[ "$hemi" == "SW" ]]

then

#read -p "Please enter the south latitude: " lat

#read -p "Please enter the west longitude: " lon llat="-${lat}"

llon="-${lon}"

lat="S${lat}"

lon="W${lon}"

elif [[ "$hemi" == "SE" ]]

then

#read -p "Please enter the south latitude: " lat

#read -p "Please enter the east longitude: " lon llat="-${lat}"

llon="${lon}"

lat="S${lat}"

lon="E${lon}"

else

echo "Please enter NW, NE, SW or SE."

exit 1 fi

# setting source URI, destination bucket URL and destination URI.

source_uri="s3://vito.landcover.global/v3.0.1/${year}/${lon}${lat}/"

url_destination_bucket="https://forestry-luca.s3.eu-central-1.amazonaws.com/"

mybucket="s3://forestry-luca"

# Formats the file name, which varies based on the year if [[ "$year" == "2019" ]]

then

filetype="nrt"

elif [[ "$year" == "2015" ]]

then

# check if file already exist in s3 bucket aws s3 ls ${mybucket}/${year}/${filename}

if [[ $? -ne 0 ]];

then

# upload file on s3 bucket

aws s3 cp ${source_uri}${filename} ${mybucket}/${year}/ --acl public-read aws s3 ls ${mybucket}/${year}/${filename}

if [[ ! $? -ne 0 ]];

then echo

echo "File was uploaded on s3 bucket."

# create STAC catalog

rio stac -o tmp.json --datetime ${year}-01-01 "${mybucket}/${year}/${filename}"

echo

# upload STAC catalog on s3 bucket

aws s3 cp tmp.json ${mybucket}/${year}/"${filename:0:-4}.json" --acl public-read echo

rm tmp.json

# output STAC catalog URL

echo "Your STAC file is on ${url_destination_bucket}${year}/${filename:0:-4}.json"

else echo

echo "ERROR: file does not exist!"

fi else

echo

echo "File already exists in the s3 bucket!"

fi

✝ ✆✌

Listato 4.1. Script per la realizzazione della pipeline di ETL

Le domande che potrebbero sorgere in questo contesto sono le seguenti:

• Perch´e facciamo lŠindicizzazione dei dati e non una pi‘u intuitiva ingestion degli stessi?

• Perch´e non salviamo i dati sulla stessa VM che poi li utilizza (cio‘e quella che contiene il servizio Jupyter Notebook)?

Per rispondere alla prima domanda ci affidiamo sia ad un fattore pratico che alle dichiarazioni ufficiali degli sviluppatori di Open Data Cube. La prima moti-vazione delle due riguarda il fatto che, facendo lŠingestion del dato, aumenter‘a lo spazio di memoria occupato sul database PostgreSQL; affidandoci ad una tecnica di indicizzazione, invece, lŠoccupazione del database sar‘a minima e i dati veri e propri persisteranno solamente in cloud. La seconda motivazione, pi‘u relativa allo stato dellŠarte della piattaforma IT, deriva direttamente dagli sviluppatori di questŠulti-ma dal momento che sconsigliano lŠoperazione di ingestion sia perch´e lŠemergere di formati di archiviazione ottimizzati per il cloud ha portato gli utilizzatori a spo-starsi verso una soluzione basata sul repository in cloud, e sia perch´e lŠimportazione porta alla duplicazione dei dati: si avr‘a, dunque, un dato replicato senza un effettivo beneĄcio computazionale aggiungendo, inoltre, il rischio della perdita di coerenza dei dati.

Per rispondere alla seconda domanda, che ai pi‘u potrebbe sorgere spontanea, oltre ai vari beneĄci che il cloud si porta con s´e, si osserva che sarebbe necessario uno spazio di archiviazione davvero enorme, dove, in questo caso, la VM perderebbe il suo iniziale compito di servizio per Jupyter ed assumerebbe tutto un altro ruolo.

Nel documento Università Politecnica delle Marche (pagine 76-83)