ogrepository/bin/checkrepo

199 lines
7.4 KiB
Bash

#!/bin/bash
#/**
#@file checkrepo
#@brief Maintain repository information in a JSON file.
#@usage checkrepo
#@warning This script uses "jq" command.
#@version 1.1.0 - Initial version.
#@author Ramón M. Gómez - ETSII Univ. Sevilla
#@date 2017-09-27
#*/ ##
# Global constants definition.
PROG=$(basename "$(realpath "$0")")
OPENGNSYS=/opt/opengnsys
IMAGESDIR=$OPENGNSYS/images
INFOFILE=$OPENGNSYS/etc/repoinfo.json
# Functions.
source $OPENGNSYS/lib/ogfunctions.sh
# Create/edit JSON file about installed ogLive clients.
function addToJson() {
# Parameters and variables.
local IMAGENAME="$1" IMAGETYPE="$2" DATA="$3" JSON i j n m OUNAME OUIND IMGIND
local CLONATOR COMPRESSOR FSTYPE DATASIZE CLIENT
IFS=":" read -r CLONATOR COMPRESSOR FSTYPE DATASIZE CLIENT <<<"$DATA"
# Check if image is restricted to an OU (subdir).
if [[ $IMAGENAME =~ / ]]; then
OUNAME="${IMAGENAME%/*}"
IMAGENAME="${IMAGENAME##*/}"
fi
# Data size must be numeric (in KB).
[[ $DATASIZE =~ ^[0-9]*$ ]] || DATASIZE=0
# JSON-formatted new entry.
JSON=$(cat << EOT | jq .
{
"name":"$IMAGENAME",
"type":"${IMAGETYPE,,}",
"clientname":"$CLIENT",
"clonator":"${CLONATOR,,}",
"compressor":"${COMPRESSOR,,}",
"filesystem":"${FSTYPE^^}",
"datasize":$[ DATASIZE * 1024]
}
EOT
)
# Check JSON file consistency.
if [ "$(jq -c keys $INFOFILE 2>/dev/null)" == '["directory","images","ous"]' ]; then
# Common image.
if [ -z "$OUNAME" ]; then
# Check if the image is defined into JSON file.
n=$(jq ".images | length" $INFOFILE)
for ((i=0; i<n; i++)); do
[ "$(jq ".check=$JSON | .check.name==.images[$i].name" $INFOFILE)" == "true" ] && IMGIND=$i
done
# Check if it needs to update or insert data.
if [ -n "$IMGIND" ]; then
# Update if image data changes and info file exists.
[ -n "$3" -a "$(jq ".check=$JSON | .check==.images[$IMGIND]" $INFOFILE)" == "false" ] && jq ".images[$IMGIND]=$JSON" $INFOFILE | sponge $INFOFILE
else
# Append a new entry.
jq ".images |= (. + [$JSON])" $INFOFILE | sponge $INFOFILE
fi
else # OU image.
# Append a new OU entry if it does not exist.
if [ -z "$(jq -r ".ous[].subdir" $INFOFILE | grep "^$OUNAME$")" ]; then
JSON=$(cat << EOT | jq .
{
"subdir": "$OUNAME",
"images": [ $JSON ]
}
EOT
)
jq ".ous |= (. + [$JSON])" $INFOFILE | sponge $INFOFILE
else
# Check if the image is defined in some OU.
m=$(jq ".ous | length" $INFOFILE)
for ((j=0; j<m; j++)); do
n=$(jq ".ous[$j].images | length" $INFOFILE)
for ((i=0; i<n; i++)); do
[ "$(jq ".check=$JSON | .check.name==.ous[$j].images[$i].name" $INFOFILE)" == "true" ] && OUIND=$j && IMGIND=$i
done
done
# Check if it needs to update or insert data.
if [ -n "$IMGIND" ]; then
# Update if image data changes and info file exists.
[ $# -gt 2 -a "$(jq ".check=$JSON | .check==.ous[$OUIND].images[$IMGIND]" $INFOFILE)" == "false" ] && jq ".ous[$OUIND].images[$IMGIND]=$JSON" $INFOFILE | sponge $INFOFILE
else
# Append a new entry.
jq ".ous[$OUIND].images |= (. + [$JSON])" $INFOFILE | sponge $INFOFILE
fi
fi
fi
else
# Create new JSON file.
echolog "creating new infofile '$INFOFILE'"
if [ -z "$OUNAME" ]; then
cat << EOT | jq . > $INFOFILE
{"directory":"$IMAGESDIR","images":[${IMAGENAME:+$JSON}],"ous":[]}
EOT
else
cat << EOT | jq . > $INFOFILE
{"directory":"$IMAGESDIR","images":[],"ous":[{"subdir":"$OUNAME","images":[$JSON]}]}
EOT
fi
fi
}
# Check for file-based images to update the repository configuration file.
function checkfiles() {
local IMAGES IMG INFO DATA
# File-stored images.
IMAGES=$(find $IMAGESDIR -maxdepth 2 -type f \( -name "*.img" -o -name "*.dsk" \) -print)
for IMG in $IMAGES; do
# Skip locked images.
[ -e "$IMG.lock" ] && continue
# Retrieve image creation data and delete temporary file.
INFO="$IMG.info"
[ -e "$INFO" -a "$INFO" -ot "$IMG" ] && rm -f "$INFO" && echo "Warning: Deleted outdated file $INFO"
DATA=""
[ -r "$INFO" ] && DATA=$(cat "$INFO")
# Add data to configuration file (name, type and data) and remove image info file.
IMG=${IMG#$IMAGESDIR/}
addToJson "${IMG%.*}" "${IMG##*.}" "$DATA" && rm -f "$INFO"
done
}
# Check for directory-based images to update the repository configuration file.
function checkdirs() {
local IMAGES IMG INFO DATA
# Directory-based images.
IMAGES=$(find $IMAGESDIR -maxdepth 3 -type f -name ogimg.info -print)
for INFO in $IMAGES; do
IMG="$(dirname "${INFO#$IMAGESDIR/}")"
# Skip repository root directory and locked images.
[ "$IMG" == "$IMAGESDIR" -o -e "$IMG.lock" ] && continue
DATA=$(awk -F= '$1=="# fstype" {fs=$2} $1=="# sizedata" {sz=$2} END {printf "rsync::%s:%s:",fs,sz}' "$INFO")
# Add data to configuration file (name, type and data).
addToJson "$IMG" "dir" "$DATA"
done
}
# Check if images are removed to update the repository configuration file.
function checkremoved() {
local IMG TYPE OU i j n m
[ ! -w "$INFOFILE" ] && raiseError access "$INFOFILE"
# Check if global images are defined into JSON file.
n=$(jq ".images | length" $INFOFILE)
for ((i=0; i<n; i++)); do
# Image name and type.
IMG="$(jq -r ".images[$i].name" $INFOFILE)"
TYPE="$(jq -r ".images[$i].type" $INFOFILE)"
[ "$TYPE" != "dir" ] && IMG="$IMG.$TYPE"
# Delete entry if image does not exist and it's not locked.
[ ! -e "$IMAGESDIR/$IMG" -a ! -e "$IMAGESDIR/$IMG.lock" ] && jq "del(.images[$i])" $INFOFILE | sponge $INFOFILE
done
# Check if OU images are defined into JSON file.
m=$(jq ".ous | length" $INFOFILE)
for ((j=0; j<m; j++)); do
# OU subdir.
OU="$(jq -r ".ous[$j].subdir" $INFOFILE)"
# Delete OU's entries if its subdir does not exist.
if [ ! -e "$IMAGESDIR/$OU" ]; then
jq "del(.ous[$j])" $INFOFILE | sponge $INFOFILE
else
n=$(jq ".images | length" $INFOFILE)
for ((i=0; i<n; i++)); do
# Image name and type.
IMG="$(jq -r ".ous[$j].images[$i].name" $INFOFILE)"
TYPE="$(jq -r ".ous[$j].images[$i].type" $INFOFILE)"
[ "$TYPE" != "dir" ] && IMG="$IMG.$TYPE"
# Delete entry if image does not exist and it's not locked.
[ ! -e "$IMAGESDIR/$OU/$IMG" -a ! -e "$IMAGESDIR/$OU/$IMG.lock" ] && jq "del(.ous[$j].images[$i])" $INFOFILE | sponge $INFOFILE
done
fi
done
}
# Main progrram.
[ "$*" == "help" ] && help
[ "$*" == "version" ] && version
# Check dependencies.
[ -w "$(dirname "$INFOFILE")" ] || raiseError access "$INFOFILE"
[ -e "$INFOFILE" ] || addToJson
which sponge &>/dev/null || raiseError notfound "Need to install \"moreutils\"."
echolog "calling checkfiles()"; checkfiles
echolog "calling checkdirs()"; checkdirs
echolog "calling checkremoved()"; checkremoved