Dossier de Stockage persistant en dehors du container HassOS (docker)

Ouais autant passer sur une version docker gérée manuellement.

Je ne le conseille pas au débutants mais ça a été mon chox

1 « J'aime »

y a toujours une solution, il suffit de la connaitre :roll_eyes: :grin:
Et je n’aime pas quand ça me résiste ! :exploding_head:

Le problème avec un docker géré manuellement, c’est que j’ai encore moins de backup auto de ma config ? je ne peu plus utiliser les extensions de module HAOS classique ? ( Node REd, Cloudflared, nginx, google drive backup …

Sinon une idée de la raison des id différents ?

Oui bien sûr …

Voici les sources de HAOS : GitHub - home-assistant/operating-system: 🔰 Home Assistant Operating System

1 « J'aime »

pas loin, j’en étais ici :

:wink:

le plugins autoackup est dispo sous docker aussi et à toi la charge de sauvegarder les données de tes conteneurs, un bête tar dans une crontab de mon coté

Bonjour à tous et merci pour vos échanges,

J’ai trouvé ma solution et je l’ai optimisée un peu pour la rendre pratique alors je vous partages cela, certain et trouverons peut-être une solution d’autre des piste dans leur propre recherches … enfin bon si cela peut aider.

En quoi et pourquoi j’ai changé d’objectif: faire un dossier totalement en dehors des dossiers par defaut de HAOS (addon_Configs, addons, backup, media, share contenu dans /mnt/data/supervisor/) il est compliqué et fastidieux de modifier toutes les configs pour pouvoir monter un dossier non prévu et ceux à chaque mise à jour sachant que les fichier de config des conteneur de modules sont géré par HA via un fichier de config spécifique (config.yaml) et non par un fichier de config de container classic (config.v2.json).
Je rappelle mon besoin : stocker les vidéos de surveillance dans un dossier qui n’est pas sauvegarder par les sauvegardes complète… du coup en réfléchissant un peu, j’ai réalisée que le meilleur dossier à utiliser pour l’exclure des sauvegardes est le dossiers sauvegarde lui-même … et que dans le cas ou un module complémentaire ni ai pas accès il faudrait juste modifier le paramètre map de config.yaml (''map": [ …, ''backup:rw", …]).

Quoi qu’il en soit il suffit juste de le monter dans le container homeassistant pour qu’il puisse y avoir accès (car par defaut home assistant n’a pas accès au dossier backup … étonnant).
et ensuite de modifier un peu le config yaml pour donner les droit sur le dossier et aussi l’afficher dans les media.

Voici le petit script bash, à executer après chaque maj core ou os, en se connectant via SSH (en mode root). Perso j’ai mis le script dans le dossier share de home assistant comme cela je peu l’editer facilement via samba sur pc / studio code sur HA,…)
/share/mounts_BackupAndData_to_HomeAssistant_container.sh :

#!/bin/bash
# copier le script dans l'un des dossiers [addon_Configs,addons,backup,media,share]
# 
#
# bash /mnt/data/supervisor/share/mounts_BackupAndData_to_HomeAssistant_container.sh
#
#
#
#==================================================
# SETTINGS:
# indiquer le dossier du script  au choix : [addon_Configs,addons,backup,media,share] : 
_folder="share"
#indiquer le sous dossier pour enregistrer les fichiers et logs
_subFolder="mounts"
#choississez les dossier à monter
_mountBackup=true
_mountData=true
#==================================================
# ADVANCED settings
_supervisorPath="/mnt/data/supervisor/"
_containersPath="/var/lib/docker/containers/"
_containersSecondaryPath="/mnt/data/docker/containers/"
_haContainerName="homeassistant"
_logFile="_mounts_BackupAndData.log"
_objName="MountPoints"
_objBackupName="/backup"
_objBackup='{"Source":"/mnt/data/supervisor/backup","Destination":"/backup","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/mnt/data/supervisor/backup","Target":"/backup"},"SkipMountpointCreation":true}'
_objDataName="/data"
_objData='{"Source":"/mnt/data/supervisor","Destination":"/data","RW":true,"Name":"","Driver":"","Type":"bind","Relabel":"rw,slave","Propagation":"slave","Spec":{"Type":"bind","Source":"/mnt/data/supervisor","Target":"/data","BindOptions":{"Propagation":"slave"}},"SkipMountpointCreation":true}'
#
#==================================================
#==================================================
#folder creation
_destFolder="${_supervisorPath}${_folder}/${_subFolder}/"
mkdir "${_destFolder}" 2>/dev/null
#==================================================
#==================================================
clear
{
echo -e "\n\n"
echo "===================================================="
echo ">> config.v2.json add BACKUPS & DATA mount points <<"
echo "===================================================="
_date=$(date +"%Y-%m-%d_%H-%M-%S") 
echo "${_date}"
#
# Verif module jq requis (jq --version)  ( https://jqlang.github.io/jq/manual/ )
#
_jq=$(jq --version 2>/dev/null)
if [ -z "${_jq}" ]	
then
	echo -e "\n!!! jq tools not found : ABORTING...\n" && exit 0
else
	echo "jq tools OK : ${_jq}"
fi
#
#recup et veif container ID
#
container="docker ps --no-trunc -aqf name=${_haContainerName}"
_id=$($container 2>/dev/null)
if [ -z "${_id}" ]	
then
	echo -e "\n!!! Container ID not found for homeassistant : ABORTING...\n" && exit 0
else
	echo "Container ID => ${_id}"
fi
#
# copy et backup du fichier dans share
#
_srcJson="${_containersPath}$_id/config.v2.json"
echo "Source JSON path => ${_srcJson}"
_wipJson="${_destFolder}config.v2.json"
echo "WIP Json path => ${_wipJson}"
cp ${_srcJson}  ${_wipJson}".backup.original_"${_date}"_.json"
cp ${_srcJson}  ${_wipJson}
chmod 777 -R ${_destFolder}
echo -e "\n=> config.v2.json and backup create in ${_folder}/${_subFolder} folder\n"
#
# check json et presence object mount
#
_mountObject=$(cat ${_wipJson} | jq ".${_objName}")
if [ "${_mountObject}" == "null" ]
then
	echo -e "\n!!! ${_objName} not found in json : ABORTING...\n"
	exit 0
else
	echo "=> ${_objName} OK ..."
fi
#
echo -e "\nSTARTING update ...\n"
#
# Verif et ajout BACKUP obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo "------ BACKUP: ------"
if [ "${_mountBackup}" == true ]
then
	_bkpObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objBackupName}\"]")	
	tmp=$(mktemp)
	if [ "${_bkpObj}" == "null" ]
	then
		echo ">> ${_objName}.[\"${_objBackupName}\"] not found in json : CREATING..."
		#---creation et verif 
		_jqCreate=$(jq ".${_objName} += {\"${_objBackupName}\":${_objBackup}}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) ||  _jqCreate="jq_ERROR"		
		if [ "${_jqCreate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > creation ERROR : ABORTING...\n" &&  exit 1
		else
			echo "     > creation OK"			
		fi
		#-----
	else
		echo ">> ${_objName}.[\"${_objBackupName}\"] in json : UPDATING..."
		#---update et verif		
		_jqUpdate=$(jq ".${_objName}.[\"${_objBackupName}\"] = ${_objBackup}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson}  ) ||  _jqUpdate="jq_ERROR"
		if [ "${_jqUpdate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > update ERROR : ABORTING...\n"	&& exit 1
		else
			echo "     > update OK"			
		fi		
		#-----
	fi
else
	echo "(!) Mount of ${_objName}.[\"${_objBackupName}\"] diseabled by user > skipping"
fi
#
#
# Verif et ajout DATA obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo -e "\n------ DATA: ------"
if [ "${_mountData}" == true ]
then
	_dataObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objDataName}\"]")
	tmpB=$(mktemp)
	if [ "${_dataObj}" == "null" ]	
	then
		echo ">> ${_objName}.[\"${_objDataName}\"] not found in json : CREATING..."	
		#gerer creation ici
		_jqCreate=$(jq ".${_objName} += {\"${_objDataName}\":${_objData}}" ${_wipJson} > "$tmpB" && mv "$tmpB" ${_wipJson} ) ||  _jqCreate="jq_ERROR"		
		if [ "${_jqCreate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > creation ERROR : ABORTING...\n" &&  exit 1
		else
			echo "     > creation OK"			
		fi
		#-----
	else
		echo ">> ${_objName}.[\"${_objDataName}\"] in json : UPDATING..."
		#gérer update ici		
		_jqUpdate=$(jq ".${_objName}.[\"${_objDataName}\"] = ${_objData}" ${_wipJson} > "$tmpB" && mv "$tmpB" ${_wipJson} ) ||  _jqUpdate="jq_ERROR"
		if [ "${_jqUpdate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > update ERROR : ABORTING...\n"	&& exit 1
		else
			echo "     > update OK"			
		fi		
		#-----
	fi
else
	echo "(!) Mount of ${_objName}.[\"${_objDataName}\"] diseabled by user > skipping"
fi
#
#---------------------------------------------------------------------------------------------------------------------------
#
# Minify JSON
#
echo -e "\n>> Update COMPLETED\n>> JSon Minification"
tmpC=$(mktemp)
jq -r tostring ${_wipJson} > "$tmpC" && mv "$tmpC" ${_wipJson}
#
# JSON validation
#
echo ">> Validating JSON..."
jsonString=$(jq -r tostring ${_wipJson})
if jq empty ${_wipJson}
then
  echo "     > JSON is valid !"
else
  echo -e "\n     (!) JSON is invalid > ABORTING...\n" && exit 1
fi
#
# Query user for final operation
#
echo ""
while true; do
    read -p "Do you wish to override original HA container config with new one ? " yn
    case $yn in
        [Yy]* ) break;;
        [Nn]* ) echo -e "\n(!) Process CANCELED by user ...\n" && exit;;
        * ) echo "Please answer (y)yes or (n)no.";;
    esac
done
echo -e "\nApply updated config...\n"
echo "3..."
docker stop ${_id}
echo "2..."
cp ${_wipJson} ${_srcJson}
_secondSrcJson="${_containersSecondaryPath}$_id/config.v2.json"
echo "1..."
cp ${_wipJson} ${_secondSrcJson}
sleep 3
while true; do
    read -p "original HA container config file overrided , REBOOT ? " yn
    case $yn in
        [Yy]* ) reboot; break;;
        [Nn]* ) echo -e "\n(!) Reboot CANCELED by user ...\n" && exit;;
        * ) echo "Please answer (y)yes or (n)no.";;
    esac
done

#
} 2>&1 | tee -a ${_destFolder}${_logFile}

pour le lancer il faudra donc exécuter en ssh (vrai ssh en mode root pas l’extension) :

bash /mnt/data/supervisor/share/mounts_BackupAndData_to_HomeAssistant_container.sh

Il est plus ou moins configurable, testé en l’état. Il monte /backup et /data dans homeassistant mais vous pouvez les activer séparément et même rajouter des dossier autres … Il est écrit pour valider les modif et ne rien copier avant validation du json et encore moins sans votre confirmation final en fin de process. De plus il créer un log et un backup du fichier d’origine dans un sous dossier /share/mounts/.

Et ensuite il faut juste créer un dossier dans backup , perso j’ai opté pour /backup/not_saved_area/ et un sous dossier /backup/not_saved_area/ _CamVideoRecords
et les intégrer dans le configuration.yaml:

homeassistant:
  # chemin authorisés :
  allowlist_external_dirs:    
    - /backup/
    - /backup/_not_saved_area_/
    - /backup/_not_saved_area_/_CamVideoRecords/	
	
  #additionnal media directories
  media_dirs:
	local: /media   #pour conserver le dossier original
	video_records: /backup/_not_saved_area_/_CamVideoRecords/

Seul point important il faut commenter les lignes avant la mise à jour et les décommenter après sinon HA redémarrera en safe_mode tant que le script de montage de dossier n’a pas été executé

homeassistant:
  # chemin authorisés :
  allowlist_external_dirs:    
    #- /backup/
    #- /backup/_not_saved_area_/
    #- /backup/_not_saved_area_/_CamVideoRecords/	
	
  #additionnal media directories
  media_dirs:
	local: /media   #pour conserver le dossier original
	#video_records: /backup/_not_saved_area_/_CamVideoRecords/

Perso j’utilise un script python (via l’extension pyscript) avec 2 petit boutons avant /après :


      type: horizontal-stack
      cards:
        - show_name: true
          show_icon: true
          type: button
          tap_action:
            action: perform-action
            perform_action: pyscript.manage_configuration_yaml_for_update
            data:
                new_state: true
            target: {}
          name: Prepare Config.YAML BEFORE update
          icon_height: 50px
          icon: mdi:pound-box
          card_mod:
            style: |
              ha-card {
                font-size: 1em !important;
                padding: 0.5% !important;
              }
              span {
                margin-top: 0 !important;
              }
        - show_name: true
          show_icon: true
          type: button
          tap_action:
            action: perform-action
            perform_action: pyscript.manage_configuration_yaml_for_update
            data:
                new_state: true
            target: {}
          icon_height: 50px
          icon: mdi:pound-box
          name: Restore Config.YAML changes AFTER update
          card_mod:
            style: |
              ha-card {
                font-size: 1em !important;
                padding: 0.5% !important;
              }
              span {
                margin-top: 0 !important;
              }

et le script python qui va avec : ( j’ai enlevé la fonction de log car lié à d’autre scripts)
il génère un backup du fichier configuration.yaml avant modif

# script python pour modifier le fichier configuration.yaml
# et désactiver les dossiers faisant appel à /backup ou autre

#
#exemple :
#action: pyscript.prepare_configuration_yaml_for_update
#data: 
#  new_state: True
#
# True desactive les dossiers montés // False les réactives

import sys

if "/config/pyscript_modules" not in sys.path:
    sys.path.append("/config/pyscript_modules")

import yaml
import os
import string
import datetime
from random import randrange

@service
def manage_configuration_yaml_for_update (new_state=None):

# Set du fichier à traiter
    config_file = '/config/configuration.yaml' 

# préparation des règles à commenter [0] > [1] pour desactiver et [1] > [0] pour réactiver
    modifE = ['    - /backup/','#- /backup/']
    modifF = ['    - /backup/_not_saved_area_/','#- /backup/_not_saved_area_/']
    modifG = ['    - /backup/_not_saved_area_/_CamVideoRecords/','#- /backup/_not_saved_area_/_CamVideoRecords/']
    modifH = ['    video_records: /backup/_not_saved_area_/_CamVideoRecords/','#video_records: /backup/_not_saved_area_/_CamVideoRecords/']

    toSet = [modifE,modifF,modifG,modifH]

# prepa nom de backup
    modifiedTime = os.path.getmtime(config_file)
    timeStamp =  datetime.datetime.fromtimestamp(modifiedTime).strftime("%Y-%m-%d_%Hh%Mm%S")
    fileNameExt = os.path.splitext(config_file)
    backupName = fileNameExt[0]+'_BACKUP_'+timeStamp+fileNameExt[1]

    if new_state == None:
        logger.warning("===== comment boolean required in data to proceed...")
    else:
# backup 
        os.system('cp '+config_file+' '+backupName )

# Load the configuration file and get content as string
        fileDesc = os.open(config_file, os.O_RDONLY)
        f_size = os.path.getsize(config_file)
        f_str = os.read(fileDesc, f_size)
        os.close( fileDesc )

# modification du content (du string)
        n_str = f_str
        for _updt in toSet:
            if new_state == True:
                n_str = n_str.replace(_updt[0].encode(), _updt[1].encode())
            else:
                n_str = n_str.replace(_updt[1].encode(), _updt[0].encode())

# clear file content
        fileClear = os.open(config_file, os.O_TRUNC )
        os.close(fileClear)

# reecriture dans fichier de la config modifiée
        fileDescB = os.open(config_file, os.O_WRONLY )
        os.write(fileDescB, n_str)
        os.close(fileDescB)

En espérant que cela puisse apporter des piste ou soluce à qu’un d’autre :wink:

Pas étonnant, avec une faille, tu pourrais mettre HA en vrac et en plus supprimer les backups. Il faudrait pouvoir y accéder depuis HA uniquement en read-only mais bon c’est certainement plus simple de bloquer l’accès.

Hello,

Bien vu, je ne l’avais pas envisagé ce risque du coup voici le script revue pour monter un sous dossier dans le dossier backup :
(le nouveaux script contient toujours les commandes pour monter backup et data, mais elles sont désactivées)

résultats :

  • les module ayant accès à /backup on accès à ce sous-dossier
  • ce sous dossier est naturellement exclu des sauvegardes pour les data encombrantes ou superflu
  • HA (les utilisateurs) ne peuvent pas remonter dans /backup

en plus un script pour restaurer un config.v2.json modifié

ADD_mountPoints.sh

#!/bin/bash
#
# Script automatisant la montée d'un dossier (mount point) dans le fichier config.v2.json 
# de configuration du container (docker) home assistant
#
# copier le script dans l'un des dossiers [addon_Configs,addons,backup,media,share]
# 
#
# bash /mnt/data/supervisor/share/mounts_BackupAndData_to_HomeAssistant_container.sh
#
# mounts_BackupAndData_to_HomeAssistant_container.sh	change to 	ADD_mountPoints.sh
#  >>	bash /mnt/data/supervisor/share/ADD_mountPoints.sh
#
#==================================================
# SETTINGS:
# indiquer le dossier du script  au choix : [addon_Configs,addons,backup,media,share] : 
_folder="share"
#indiquer le sous dossier pour enregistrer les fichiers et logs
_subFolder="mounts"
#choississez les dossiers à monter : 
_mountBackup=false		#/backup
_mountData=false		#/data
_mountSubBackup=true	#/backup/_not_saved_area_/
#==================================================
# ADVANCED settings
_supervisorPath="/mnt/data/supervisor/"
_containersPath="/var/lib/docker/containers/"
_containersSecondaryPath="/mnt/data/docker/containers/"
_haContainerName="homeassistant"
_logFile="_mounts_BackupAndData.log"
_objName="MountPoints"
_objBackupName="/backup"
_objBackup='{"Source":"/mnt/data/supervisor/backup","Destination":"/backup","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/mnt/data/supervisor/backup","Target":"/backup"},"SkipMountpointCreation":true}'
_objDataName="/data"
_objData='{"Source":"/mnt/data/supervisor","Destination":"/data","RW":true,"Name":"","Driver":"","Type":"bind","Relabel":"rw,slave","Propagation":"slave","Spec":{"Type":"bind","Source":"/mnt/data/supervisor","Target":"/data","BindOptions":{"Propagation":"slave"}},"SkipMountpointCreation":true}'
_objSubBackupName="/_not_saved_area_"
_objSubBackup='{"Source":"/mnt/data/supervisor/backup/_not_saved_area_","Destination":"/_not_saved_area_","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/mnt/data/supervisor/backup/_not_saved_area_","Target":"/_not_saved_area_"},"SkipMountpointCreation":false}'
#
#==================================================
#==================================================
#folder creation
_destFolder="${_supervisorPath}${_folder}/${_subFolder}/"
mkdir "${_destFolder}" 2>/dev/null
#==================================================
#==================================================
clear
{
echo -e "\n\n"
echo "================================================================="
echo ">> HA container config.v2.json add BACKUPS & DATA mount points <<"
echo "================================================================="
_date=$(date +"%Y-%m-%d_%H-%M-%S") 
echo "${_date}"
#
# Verif module jq requis (jq --version)  ( https://jqlang.github.io/jq/manual/ )
#
_jq=$(jq --version 2>/dev/null)
if [ -z "${_jq}" ]	
then
	echo -e "\n!!! jq tools not found : ABORTING...\n" && exit 0
else
	echo "jq tools OK : ${_jq}"
fi
#
#recup et verif container ID
#
container="docker ps --no-trunc -aqf name=${_haContainerName}"
_id=$($container 2>/dev/null)
if [ -z "${_id}" ]	
then
	echo -e "\n!!! Container ID not found for homeassistant : ABORTING...\n" && exit 0
else
	echo "Container ID => ${_id}"
fi
#
# copy et backup du fichier dans share
#
_srcJson="${_containersPath}$_id/config.v2.json"
echo "Source JSON path => ${_srcJson}"
_wipJson="${_destFolder}config.v2.json"
echo "WIP Json path => ${_wipJson}"
cp ${_srcJson}  ${_wipJson}".backup.original_"${_date}"_.json"
cp ${_srcJson}  ${_wipJson}
chmod 777 -R ${_destFolder}
echo -e "\n=> config.v2.json and backup create in ${_folder}/${_subFolder} folder\n"
#
# check json et presence object mount
#
_mountObject=$(cat ${_wipJson} | jq ".${_objName}")
if [ "${_mountObject}" == "null" ]
then
	echo -e "\n!!! ${_objName} not found in json : ABORTING...\n"
	exit 0
else
	echo "=> ${_objName} OK ..."
fi
#
echo -e "\nSTARTING update ...\n"
#
# Verif et ajout BACKUP obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo "------ BACKUP: ------"
if [ "${_mountBackup}" == true ]
then
	_bkpObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objBackupName}\"]")	
	tmp=$(mktemp)
	if [ "${_bkpObj}" == "null" ]
	then
		echo ">> ${_objName}.[\"${_objBackupName}\"] not found in json : CREATING..."
		#---creation et verif 
		_jqCreate=$(jq ".${_objName} += {\"${_objBackupName}\":${_objBackup}}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) ||  _jqCreate="jq_ERROR"		
		if [ "${_jqCreate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > creation ERROR : ABORTING...\n" &&  exit 1
		else
			echo "     > creation OK"			
		fi
		#-----
	else
		echo ">> ${_objName}.[\"${_objBackupName}\"] in json : UPDATING..."
		#---update et verif		
		_jqUpdate=$(jq ".${_objName}.[\"${_objBackupName}\"] = ${_objBackup}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson}  ) ||  _jqUpdate="jq_ERROR"
		if [ "${_jqUpdate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > update ERROR : ABORTING...\n"	&& exit 1
		else
			echo "     > update OK"			
		fi		
		#-----
	fi
else
	echo "(!) Mount of ${_objName}.[\"${_objBackupName}\"] diseabled by user > skipping"
fi
#
# Verif et ajout SubBACKUP () obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo -e "\n------ SubBACKUP (/backup/_not_saved_area_): ------"
if [ "${_mountSubBackup}" == true ]
then
	mkdir /mnt/data/supervisor/backup/_not_saved_area_
	_subBkpObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objSubBackupName}\"]")	
	tmp=$(mktemp)
	if [ "${_subBkpObj}" == "null" ]
	then
		echo ">> ${_objName}.[\"${_objSubBackupName}\"] not found in json : CREATING..."
		#---creation et verif 
		_jqCreate=$(jq ".${_objName} += {\"${_objSubBackupName}\":${_objSubBackup}}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson} ) ||  _jqCreate="jq_ERROR"		
		if [ "${_jqCreate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > creation ERROR : ABORTING...\n" &&  exit 1
		else
			echo "     > creation OK"			
		fi
		#-----
	else
		echo ">> ${_objName}.[\"${_objSubBackupName}\"] in json : UPDATING..."
		#---update et verif		
		_jqUpdate=$(jq ".${_objName}.[\"${_objSubBackupName}\"] = ${_objSubBackup}" ${_wipJson} > "$tmp" && mv "$tmp" ${_wipJson}  ) ||  _jqUpdate="jq_ERROR"
		if [ "${_jqUpdate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > update ERROR : ABORTING...\n"	&& exit 1
		else
			echo "     > update OK"			
		fi		
		#-----
	fi
else
	echo "(!) Mount of ${_objName}.[\"${_objSubBackupName}\"] diseabled by user > skipping"
fi
#
#
# Verif et ajout DATA obj to json ---------------------------------------------------------------------------------------------------------------------------
#
echo -e "\n------ DATA: ------"
if [ "${_mountData}" == true ]
then
	_dataObj=$(cat ${_wipJson} | jq ".${_objName}.[\"${_objDataName}\"]")
	tmpB=$(mktemp)
	if [ "${_dataObj}" == "null" ]	
	then
		echo ">> ${_objName}.[\"${_objDataName}\"] not found in json : CREATING..."	
		#gerer creation ici
		_jqCreate=$(jq ".${_objName} += {\"${_objDataName}\":${_objData}}" ${_wipJson} > "$tmpB" && mv "$tmpB" ${_wipJson} ) ||  _jqCreate="jq_ERROR"		
		if [ "${_jqCreate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > creation ERROR : ABORTING...\n" &&  exit 1
		else
			echo "     > creation OK"			
		fi
		#-----
	else
		echo ">> ${_objName}.[\"${_objDataName}\"] in json : UPDATING..."
		#gérer update ici		
		_jqUpdate=$(jq ".${_objName}.[\"${_objDataName}\"] = ${_objData}" ${_wipJson} > "$tmpB" && mv "$tmpB" ${_wipJson} ) ||  _jqUpdate="jq_ERROR"
		if [ "${_jqUpdate}" == "jq_ERROR" ]		
		then			
			echo -e "\n!!!  > update ERROR : ABORTING...\n"	&& exit 1
		else
			echo "     > update OK"			
		fi		
		#-----
	fi
else
	echo "(!) Mount of ${_objName}.[\"${_objDataName}\"] diseabled by user > skipping"
fi

#
#---------------------------------------------------------------------------------------------------------------------------
#
# Minify JSON
#
echo -e "\n>> Update COMPLETED\n>> JSon Minification"
tmpC=$(mktemp)
jq -r tostring ${_wipJson} > "$tmpC" && mv "$tmpC" ${_wipJson}
#
# JSON validation
#
echo ">> Validating JSON..."
jsonString=$(jq -r tostring ${_wipJson})
if jq empty ${_wipJson}
then
  echo "     > JSON is valid !"
else
  echo -e "\n     (!) JSON is invalid > ABORTING...\n" && exit 1
fi
#
# Query user for final operation
#
echo ""
while true; do
    read -p "Do you wish to override original HA container config with new one ? " yn
    case $yn in
        [Yy]* ) break;;
        [Nn]* ) echo -e "\n(!) Process CANCELED by user ...\n" && exit;;
        * ) echo "Please answer (y)yes or (n)no.";;
    esac
done
echo -e "\nApply updated config...\n"
echo "Stopping HA Container ..."
docker stop ${_id}
echo "HA Container stopped"
cp ${_wipJson} ${_srcJson}
_secondSrcJson="${_containersSecondaryPath}$_id/config.v2.json"
echo "Config File restored"
cp ${_wipJson} ${_secondSrcJson}
sleep 1
while true; do
    read -p "original HA container config file overrided , REBOOT ? " yn
    case $yn in
        [Yy]* ) reboot; break;;
        [Nn]* ) echo -e "\n(!) Reboot CANCELED by user ...\n" && exit;;
        * ) echo "Please answer (y)yes or (n)no.";;
    esac
done

#
} 2>&1 | tee -a ${_destFolder}${_logFile}

RESTORE_mountPoints.sh

#!/bin/bash

# copier le script dans l'un des dossiers [addon_Configs,addons,backup,media,share]
# 
#
# Script permettant de restaurer un fichier de configuration généré 
# par le script  ADD_mountPoints.sh
#
# 
#  >>	bash /mnt/data/supervisor/share/RESTORE_mountPoints.sh
#
#==================================================
# SETTINGS:
# indiquer le dossier du script  au choix : [addon_Configs,addons,backup,media,share] : 
_folder="share"
#indiquer le sous dossier pour enregistrer les fichiers et logs
_subFolder="mounts"
#==================================================
# ADVANCED settings
_supervisorPath="/mnt/data/supervisor/"
_containersPath="/var/lib/docker/containers/"
_containersSecondaryPath="/mnt/data/docker/containers/"
_haContainerName="homeassistant"
_logFile="_mounts_BackupAndData.log"
#
#==================================================
#==================================================
#folder creation
_destFolder="${_supervisorPath}${_folder}/${_subFolder}/"
#mkdir "${_destFolder}" 2>/dev/null
#==================================================
#==================================================
clear
{
echo -e "\n\n"
echo "=========================================="
echo ">> RESTORE HA Container config.v2.json  <<"
echo "=========================================="
_date=$(date +"%Y-%m-%d_%H-%M-%S") 
echo "${_date}"

# Verif existance dossier de backup
if [ ! -d "${_destFolder}" ]
then
  echo -e "config backup folder not found > aborting restore process...\n(${_destFolder})"&& exit 0
else 
  echo -e "config backup folder OK > start scanning files...\n(${_destFolder})\n"
fi
#
#recup des fichier de backup  (https://unix.stackexchange.com/questions/511127/bash-list-possible-files-and-select-one)
# + selection utilisateur
#
_backupBaseName="config.v2.json.backup.original_"
_backupsFiles="${_destFolder}${_backupBaseName}*.json"
for img in ${_backupsFiles}
do
    n=$((n+1))
	_basename=$(basename "$img")
    printf "[%s] %s\n" "$n" "$_basename"
    eval "img${n}=\$img"
done
if [ "$n" -eq 0 ]
then
    echo >&2 "No ${_backupBaseName}*.json found  > aborting restore process... "
    exit
fi
printf '\nEnter File Index ID (1 to %s) (0 to cancel): ' "$n"
read -r num
num=$(printf '%s\n' "$num" | tr -dc '[:digit:]')
if [ "$num" -le 0 ] || [ "$num" -gt "$n" ] || [ "$num" -eq 0 ]
then
    #echo >&2 Wrong selection.
	# wrong select
	if [ "$num" -eq 0 ] 
	then
		#abort by user
		echo -e "(!) Process CANCELED by user ...\n";exit 0
	else
		#bad answer restart script 
		exec "/mnt/data/supervisor/share/RESTORE_mountPoints.sh"
	fi
else
    eval "_selectedFile=\$img${num}"
	_selectedFileName=$(basename "$_selectedFile")
    echo "Selected image is: ${_selectedFileName}"
fi
#
# Confirmation
#
echo -e "\nContinuer avec ce fichier ?\n (y)(n)(c) : yes / no / change"

while true; do
    read -p "     >> " ync
    case $ync in
        [Yy]* ) break;;		
        [Nn]* ) echo -e "\n(!) Process CANCELED by user ...\n" && exit;;
		[Cc]* ) exec "/mnt/data/supervisor/share/RESTORE_mountPoints.sh";;
        * ) echo -e "Please answer (y)yes or (n)no or (c)change.\n";;
    esac
done
#
#
#recup et verif container ID ( même si off)
#
container="docker ps -a --no-trunc -aqf name=${_haContainerName}"
_id=$($container 2>/dev/null)
if [ -z "${_id}" ]	
then
	echo -e "\n!!! Container ID not found for homeassistant : ABORTING...\n" && exit 0
else
	echo "Container ID found => ${_id}"
fi

#
# copy et backup du fichier dans share
#
_srcJson="${_containersPath}$_id/config.v2.json"
_secondSrcJson="${_containersSecondaryPath}$_id/config.v2.json"

echo "JSON to replace A => ${_srcJson}"
echo "JSON to replace B => ${_secondSrcJson}"

cp ${_srcJson}  "${_destFolder}config.v2.json.backup.original_"${_date}"_BeforeRestore.json"
chmod 777 -R ${_destFolder}
echo -e "\n=> current config.v2.json backuped in ${_folder}/${_subFolder} folder\n"

#
# Query user to process
#
while true; do
    read -p "Ok to restore file and reboot ? " yn
    case $yn in
        [Yy]* ) break;;
        [Nn]* ) echo -e "\n(!) CANCELED by user ...\n" && exit;;
        * ) echo "Please answer (y)yes or (n)no.";;
    esac
done

#
# Process
#
echo "Stopping HA Container ..."
docker stop ${_id}
echo "HA Container stopped"
sleep 1
cp ${_selectedFile} ${_srcJson}
cp ${_selectedFile} ${_secondSrcJson}
echo "Config File restored"
echo "rebooting..."
sleep 1
reboot
} 2>&1 | tee -a ${_destFolder}${_logFile}

Bonne soirée

1 « J'aime »