.. _dataStorage:

Stockage des données
####################

.. seealso:: Cette section s'appuie fortement sur :doc:`la description de l'architecture des données </archi-applicative/11-data-architecture-multisite>`, en particulier en ce qui concerne les données d'archive.

Les offres de stockage :term:`VITAM` portent la référence des données concernant les archives hébergées par le système :term:`VITAM` : leur contenu binaire (:term:`BDO`), mais également les métadonnées associées au sens large (:term:`AU`, :term:`GOT`, journaux).

:term:`VITAM` possède trois implémentations possibles d'offres de stockage "classiques" : l'implémentation basée sur un système de fichiers, l'implémentation Swift et l'implémentation S3.
En complément, une implémentation *Tape-library*, aussi désignée Offre froide, permet l'usage de robotique de cartouches magnétiques.

:term:`VITAM` peut stocker les données dans plusieurs offres de stockage en parallèle afin de se parer contre la perte de données. Les deux types d'offres peuvent être utilisées seuls ou ensemble sur des offres de stockage différentes : ainsi, on peut configurer :term:`VITAM` pour déposer les données dans 2 offres de stockage filesystem disjointes, ou dans une offre de stockage filesystem et une offre :term:`Swift`, ou encore dans une offre de stockage filesystem et 2 offres :term:`Swift` différentes (se basant sur 2 *clusters* :term:`Swift` distincts) ; tout dépend des contraintes de non-perte de données, de scalabilité et de résilience à la panne qui sont abordés dans la description des types d'offres ci-dessous. C'est la configuration des stratégies qui permet de définir les offres sur lesquelles vont être stockées les données.

.. note:: Un mécanisme de resynchronisation d'une offre de stockage avec une autre, migrant de fait les données entre offres, est disponible en mode complet (la procédure est décrite dans le :term:`DEX`).

.. important:: Dans le but d'assurer au maximum la pérennité des données conservées dans le système :term:`VITAM`, il est très fortement conseillé de stocker les données dans au moins 2 technologies de stockage différentes (ex: 2 stockages objets de constructeurs et technologies différentes, un stockage objet et un stockage bloc, 2 stockages bloc de constructeurs et technologies différentes, ...)


Stratégies de stockage
======================

VITAM permet de définir plusieurs stratégies de stockage sur une plateforme VITAM.

Plusieurs règles :

* une stratégie de plateforme VITAM est obligatoire
* la stratégie de plateforme VITAM est utilisée par défaut
* la définition d'une stratégie sur une donnée est immutable : on ne peut changer la stratégie d'un objet stocké


Offre filesystem
================

L'offre filesystem permet de stocker les données sur un système de fichiers accessible localement par le composant "storage-offer".

Points positifs :

* facile à mettre en place
* facile à exploiter
* facile à sauvegarder

Points négatifs :

* pour une offre de stockage, seule une seule instance du service storage-offer peut être active à un instant donné, ce qui implique que cette offre :

    - n'est pas scalable par multi-instanciation (i.e. horizontalement) ;
    - ne possède pas de solution de haute disponibilité portée par la solution logicielle.

Par conséquent, elle est particulièrement adaptée pour les déploiements de test ou de petite taille (ordre de grandeur : < 10 To), mais est à déconseiller pour les déploiements sur des volumétries importantes.

.. caution:: L'offre filesystem nécessite un système de fichiers acceptant les attributs étendus (ex: XFS) ; en particulier, il n'est donc pas possible d'héberger les données sur un montage NFS (NFS ne supportant pas les attributs étendus).


Offre Swift
===========

L'offre Swift permet de stocker les données sur un stockage objet implémentant l':term:`API` :term:`Swift`.

Points positifs :

* scalable : storage-offer se comporte dans ce scénario comme une passerelle vers l':term:`API` :term:`Swift` ; il est donc multi-instanciable au sein d'une offre de stockage.
* consomme une :term:`API` normalisée : elle est donc compatible avec un grand nombre d'implémentations différentes de :term:`Swift`.

Points négatifs :

* nécessite la mise en place et l'exploitation d'un stockage objet, ce qui est potentiellement plus complexe et moins courant que la mise à disposition d'un simple stockage bloc ou fichier.

Par conséquent, elle est particulièrement adaptée pour les déploiements en production de forte volumétrie.

.. note:: Dans cette version de la solution logicielle :term:`VITAM`, l'implémentation :term:`Swift` n'est en théorie pas obligée de permettre l'*upload* de fichiers de taille non connue par avance (mode *chunk encoding*) ; cependant, aucun test pertinent n'a pu être effectué faute d'implémentation disponible. Merci de remonter à l'équipe support tout bug associé à ce comportement.

.. warning:: Seule l':term:`API` d'authentification *keystone* v3 est aujourd'hui officiellement supportées par la solution logicielle :term:`VITAM`. Les :term:`API` d'authentification *keystone* v1 et v2 sont dépréciées.

.. note:: L'activation de la configuration de headers spécifiques Vitam lors des appels vers le stockage Swift est gérée par la variable :term:`enableCustomHeaders` (boolean). Si activé, il faut éditer la variable :term:`customHeaders` avec une liste de clé/valeur pour définir la liste des headers à envoyer au niveau des appels HTTP de l'offre vers le serveur de stockage Swift.

.. note:: :term:`VITAM` utilise par défaut des connections HTTP persistantes (keep-alive) vers le serveur de stockage Swift si ce dernier les supporte. Si l'infrastructure réseau ou des Reverse-Proxy intermédiaires sont susceptibles de couper occasionnellement les connexions réseau, ceci peut causer des erreurs d'accès au serveur Swift distant. Il peut alors être pertinent de désactiver la persistance des connexions HTTP via le paramètre :term:`swiftDisableKeepAlive` (peut avoir des impacts sur les performances d'accès à l'offre).

.. note:: Par tenant :term:`VITAM` utilisé, jusqu'à 17 *containers* sont créés.

La liste des *containers* est :

.. literalinclude:: ../../exploitation/topics/data/container_list.txt


Offre S3
========

L'offre S3 permet de stocker les données sur un stockage objet implémentant l':term:`API` S3.

Les points positifs et négatifs sont les mêmes que pour l'offre :term:`Swift`.

L'offre S3 utilise le client java S3 du SDK Amazon V1. De ce fait la compatibilité du stockage avec l':term:`API` S3 sera limitée à sa compatibilité avec le client logiciel sélectionné.
Pour que :term:`VITAM` soit compatible avec l':term:`API` S3 les noms de conteneurs sont transformés pour obtenir des noms de *bucket* valides :

* remplacement de tous les caractères non alphanumériques par des '.'
* suppression des '.' au début et à la fin
* passage de tous les caractères en minuscule

.. note:: Dans le cas où l'implémentation S3 sous-jacente supporte le versioning des buckets ou la suppression logique des fichiers (aussi connue sous les appellations "soft delete" ou "delete markers"), ces fonctionnalités doivent alors être désactivées. En effet, l'activation des ces fonctionnalités cause une démultiplication de l'espace de stockage et la non suppression des données éliminées.

.. note:: Dans cette version de la solution logicielle :term:`VITAM`, l'implémentation S3 fournie par :term:`VITAM` nécessite la taille du fichier pour l'envoyer dans le stockage S3.

.. note:: Par tenant VITAM utilisé, jusqu'à 17 *containers* (et donc **buckets**) sont créés.

La liste des *containers* est :

.. literalinclude:: ../../exploitation/topics/data/container_list.txt

.. warning:: Par défaut, le fournisseur Amazon définit une limite à 100 *buckets* ; il convient de revoir ce paramétrage dans le cas où la solution logicielle :term:`VITAM` doit gérer plus de **5** *tenants*.

La liste des API S3 utilisées par :term:`VITAM` est :


**Buckets**

- API : GET Bucket acl

Exemple :

.. code-block:: text

  [REQUEST (objectAPIHandlers).GetBucketACLHandler-fm] [160087199.728184] [2020-09-23 14:39:57 +0000]
  GET /5.dbxuwfvoes/?acl
  Host: 127.0.0.1:9999
  X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  X-Amz-Date: 20200923T143957Z
  Content-Length: 0
  Connection: Keep-Alive
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=640458e964fd2caa14b0ffb4808ee99fdf5d232808a4a8e397c121ea77b00a74
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  Amz-Sdk-Retry: 0/0/500
  Content-Type: application/octet-stream
  Amz-Sdk-Invocation-Id: 8db9bb54-6dcf-c5d8-579a-c3dbd293f165
  ---

- API : PUT Bucket

Exemple :

.. code-block:: text

  [REQUEST (objectAPIHandlers).PutBucketHandler-fm] [160087200.043971] [2020-09-23 14:40:00 +0000]
  PUT /5.dbxuwfvoes/
  Host: 127.0.0.1:9999
  Amz-Sdk-Invocation-Id: 9d77b44d-8d52-7065-1872-ac9975a63425
  Amz-Sdk-Retry: 0/0/500
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=e03a2feaaff4538887a06ca53a7c4c9609effc6dbd34d9191ec461f3b5e43918
  Connection: Keep-Alive
  Content-Type: application/octet-stream
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  X-Amz-Date: 20200923T144000Z
  Content-Length: 0
  ---

- API : GET Bucket (List Objects)Version 2

Exemple 1 :

.. code-block:: text

  [REQUEST (objectAPIHandlers).ListObjectsV2Handler-fm] [160087204.792921] [2020-09-23 14:40:47 +0000]
  GET /7.hvybpdxfsm/?list-type=2&max-keys=1000&fetch-owner=false
  Host: 127.0.0.1:9999
  Content-Type: application/octet-stream
  Amz-Sdk-Invocation-Id: df03b558-11b5-1ce6-a69c-f1086718ee0b
  Amz-Sdk-Retry: 0/0/500
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  X-Amz-Date: 20200923T144047Z
  Content-Length: 0
  Connection: Keep-Alive
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=3331501246aee47854132b6d9deec6dce68468e6c70363d2901434f7753673c3

Exemple 2 :

.. code-block:: text

  [REQUEST (objectAPIHandlers).ListObjectsV2Handler-fm] [160087204.796455] [2020-09-23 14:40:47 +0000]
  GET /7.hvybpdxfsm/?list-type=2&continuation-token=aeaaaaaaaabe6it7abvtgaluxnunfjqaaaaq188&max-keys=1000&fetch-owner=false
  Host: 127.0.0.1:9999
  Amz-Sdk-Retry: 0/0/500
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=c482925c51dcaa4fa8ab65ade329fc1e968726edb2c2fe0313345aeced2ea1e6
  Content-Type: application/octet-stream
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  Content-Length: 0
  Amz-Sdk-Invocation-Id: 8f314f3e-fde9-b341-6bc1-8c0b3a830ef3
  X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  X-Amz-Date: 20200923T144047Z
  Connection: Keep-Alive


**Objects**


- API : HEAD Object

Exemple :

.. code-block:: text

  [REQUEST (objectAPIHandlers).HeadObjectHandler-fm] [160087199.737232] [2020-09-23 14:39:57 +0000]
  HEAD /5.dbxuwfvoes/aeaaaaaaaabe6it7abu44aluxnubyjiaaaaq
  Host: 127.0.0.1:9999
  Content-Type: application/octet-stream
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  X-Amz-Date: 20200923T143957Z
  Connection: Keep-Alive
  X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  Amz-Sdk-Invocation-Id: 3b849433-402b-b1fe-da13-d6d7ed267ff5
  Amz-Sdk-Retry: 0/0/500
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=4a465630ac0523e27bb3dfaa6a573ee3a3516cc884ff037b11f947b309095041
  ---


- API : Delete Object

Exemple :

.. code-block:: text

  [REQUEST (objectAPIHandlers).DeleteObjectHandler-fm] [160087199.737773] [2020-09-23 14:39:57 +0000]
  DELETE /5.dbxuwfvoes/aeaaaaaaaabe6it7abu44aluxnubyjiaaaaq
  Host: 127.0.0.1:9999
  Amz-Sdk-Invocation-Id: 7920dbea-9ac8-8928-8f48-b0a587738f24
  X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  X-Amz-Date: 20200923T143957Z
  Connection: Keep-Alive
  Amz-Sdk-Retry: 0/0/500
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=1b5243ccfc2f43518d70a0a71fdc96971b8b16ab4ff2721648ad38b77ea48048
  Content-Type: application/octet-stream
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  ---


- API : GET Object

Exemple :

.. code-block:: text

  [REQUEST (objectAPIHandlers).GetObjectHandler-fm] [160087200.042941] [2020-09-23 14:40:00 +0000]
  GET /5.dbxuwfvoes/aeaaaaaaaabe6it7abu44aluxnubyjiaaaaq
  Host: 127.0.0.1:9999
  X-Amz-Date: 20200923T144000Z
  Content-Length: 0
  Amz-Sdk-Invocation-Id: e146fb12-0283-af0d-83ef-fbcf01ad589d
  Amz-Sdk-Retry: 0/0/500
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-type;host;user-agent;x-amz-content-sha256;x-amz-date, Signature=687b0e4098bced5f3fb99bf9a7bb1a994532f65bb66a101889892fa1a55ed925
  Content-Type: application/octet-stream
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  Connection: Keep-Alive

  <BODY>
  ---


- API : PUT Object

Exemple :

.. code-block:: text

  [REQUEST (objectAPIHandlers).PutObjectHandler-fm] [160087199.739414] [2020-09-23 14:39:57 +0000]
  PUT /5.dbxuwfvoes/aeaaaaaaaabe6it7abu44aluxnubyjiaaaaq
  Host: 127.0.0.1:9999
  Amz-Sdk-Retry: 0/0/500
  X-Amz-Content-Sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
  X-Amz-Date: 20200923T143957Z
  Content-Length: 7081
  Connection: Keep-Alive
  Expect: 100-continue
  Amz-Sdk-Invocation-Id: f7ce7617-0563-19ea-1187-33811dc527ac
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-length;content-type;host;user-agent;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length, Signature=02c10a4598ae8804e416c69249c6e214a100e145b9ec02f3ff3925a73f6b085f
  Content-Type: application/octet-stream
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  X-Amz-Decoded-Content-Length: 6906

  <BODY>
  ---


- API :  PUT Object - Copy

Exemple :

.. code-block:: text

  [REQUEST (objectAPIHandlers).CopyObjectHandler-fm] [160087200.056875] [2020-09-23 14:40:00 +0000]
  PUT /5.dbxuwfvoes/aeaaaaaaaabe6it7abu44aluxnubyjiaaaaq
  Host: 127.0.0.1:9999
  X-Amz-Meta-Digest: 9ba9ef903b46798c83d46bcbd42805eb69ad1b6a8b72e929f87d72f5263a05ade47d8e2f860aece8b9e3acb948364fedf75a3367515cd912965ed22a246ea418
  X-Amz-Date: 20200923T144000Z
  Content-Length: 0
  Content-Type: application/octet-stream
  Amz-Sdk-Invocation-Id: a3de1f75-d08d-b7d6-ad23-7c16e23c4e4f
  User-Agent: aws-sdk-java/1.11.720 Linux/4.15.0-117-generic OpenJDK_64-Bit_Server_VM/11.0.8+10-post-Ubuntu-0ubuntu118.04.1 java/11.0.8 vendor/Ubuntu
  X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  X-Amz-Copy-Source: /5.dbxuwfvoes/aeaaaaaaaabe6it7abu44aluxnubyjiaaaaq
  X-Amz-Meta-Digest-Type: SHA-512
  X-Amz-Metadata-Directive: REPLACE
  Connection: Keep-Alive
  Amz-Sdk-Retry: 0/0/500
  Authorization: AWS4-HMAC-SHA256 Credential=MKU4HW1K9HSST78MDY3T/20200923//s3/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-retry;content-length;content-type;host;user-agent;x-amz-content-sha256;x-amz-copy-source;x-amz-date;x-amz-meta-digest;x-amz-meta-digest-type;x-amz-metadata-directive, Signature=6a366171c7f83a9fed12402e9984aaab8148bb7f438cbf43465ee7ed8ae7b7dc
  ---



Offre Tape-library
==================

L'offre *Tape-library*, aussi désignée **Offre Froide**, permet de stocker les données sur des librairies de cartouches magnétiques.

Elle s'appuie sur des commandes linux standard pour manipuler les éléments robotiques. Elle est donc à priori compatible avec tous les matériels compatibles Linux.


Points positifs :

* Froide : à contrario des offres disques déjà utilisables dans :term:`VITAM` (FS ou Objet), l'accès aux données sur les cartouches n'est pas immédiat. Il nécessite le montage des cartouches dans des lecteurs, qui sont en nombre limités. En cas de corruption des données des offres disques (par exemple, attaque de type *ransomware*), sa répercussion vers les données archivées sur cartouches serait très lente. C'est une garantie de sécurité supplémentaire.
* Peu onéreuse pour le stockage des grands volumes : comparée à un stockage disque, un stockage bande est moins onéreux: 1 To de stockage sur LTO revient à 10€ HT.
* Durabilité des bandes : 15-30 ans contre 5 ans pour les HDD/SSD, avec 20000 cycles de chargements/déchargements.
* Possibilité de blocage physique des réécritures (WORM), de compression et de chiffrement natifs des données.
* Externalisable : les cartouches peuvent être extraites de la librairie une fois les données inscrites, et stockées dans un local sécurisé tiers.

.. note:: Dans sa version actuelle, :term:`VITAM` ne prend pas en charge les opérations d'externalisation. Ce process ne peut être réalisé que manuellement.

Points négatifs :

* N'est pas multi-instantiable : Pour une offre de stockage, seule une seule instance du service storage-offer peut être active à un instant donné (i.e. ne peut être déployée en haute disponibilité)
* Nécessite une infrastructure lourde (hardware, hébergement…), coûteuse à installer et compliquée à exploiter.
* Nécessite un espace de stockage disque local ``/vitam/data/offer`` conséquent (espace "tampon" pour écriture rapide + espace "cache" pour relecture des données).

L'offre Tape-library utilise les commandes standard ``mt``, ``mtx`` et ``dd`` pour manipuler les lecteurs de bandes et la librairie. Ces outils sont installés sur le serveur où est déployée l'offre froide.
Cette même machine doit également avoir accès à la librairie soit par attachement direct, soit par le biais d'un accès distant ( ex: iscsi )

.. note:: L'usage des commandes ``mt`` et ``mtx`` nécessite des droits spécifiques. L'utilisateur vitam est automatiquement ajouté au groupe unix "tape" sur le serveur où est déployée l'offre froide.

.. note:: Le dossier ``/vitam/data/offer/`` doit correspondre à une seule partition de système de fichiers (i.e. tout le contenu du dossier ``/vitam/data/offer`` doit appartenir au même point de montage). Le système de fichiers doit supporter les opérations de atomiques (type atomic rename / move) et la création de liens symboliques (ex. XFS, EXT4...)

.. seealso:: Les principes de fonctionnement de l'offre froide sont décrits dans la documentation externe dédiée ("Archivage sur Offre Froide").
