Topic #409: checkrepo

File checkrepo, 7.8 KB (added by acodoner, 4 years ago)

/opt/opengnsys/bin/checkrepo

Line 
1#!/bin/bash
2
3#/**
4#@file    checkrepo
5#@brief   Maintain repository information in a JSON file.
6#@usage   checkrepo
7#@warning This script uses "jq" command.
8#@version 1.1.0 - Initial version.
9#@author  Ramón M. Gómez - ETSII Univ. Sevilla
10#@date    2017-09-27
11#*/ ##
12
13
14# Global constants definition.
15PROG=$(basename "$(realpath "$0")")
16OPENGNSYS=/opt/opengnsys
17IMAGESDIR=$OPENGNSYS/images
18INFOFILE=$OPENGNSYS/etc/repoinfo.json
19
20
21# Functions.
22source $OPENGNSYS/lib/ogfunctions.sh
23
24# Create/edit JSON file about installed ogLive clients.
25function addToJson() {
26    # Parameters and variables.
27    local IMAGENAME="$1" IMAGETYPE="$2" DATA="$3" JSON i j n m OUNAME OUIND IMGIND
28    local CLONATOR COMPRESSOR FSTYPE DATASIZE CLIENT
29    IFS=":" read -r CLONATOR COMPRESSOR FSTYPE DATASIZE CLIENT <<<"$DATA"
30    # Check if image is restricted to an OU (subdir).
31    if [[ $IMAGENAME =~ / ]]; then
32        OUNAME="${IMAGENAME%/*}"
33        IMAGENAME="${IMAGENAME##*/}"
34    fi
35    # Data size must be numeric (in KB).
36    [[ $DATASIZE =~ ^[0-9]*$ ]] || DATASIZE=0
37    # JSON-formatted new entry.
38    JSON=$(cat << EOT | jq .
39{
40  "name":"$IMAGENAME",
41  "type":"${IMAGETYPE,,}",
42  "clientname":"$CLIENT",
43  "clonator":"${CLONATOR,,}",
44  "compressor":"${COMPRESSOR,,}",
45  "filesystem":"${FSTYPE^^}",
46  "datasize":$[ DATASIZE * 1024]
47}
48EOT
49    )
50    # Check JSON file consistency.
51    if [ "$(jq -c keys $INFOFILE 2>/dev/null)" == '["directory","images","ous"]' ]; then
52        # Common image.
53        if [ -z "$OUNAME" ]; then
54            # Check if the image is defined into JSON file.
55            n=$(jq ".images | length" $INFOFILE)
56            for ((i=0; i<n; i++)); do
57                [ "$(jq ".check=$JSON | .check.name==.images[$i].name" $INFOFILE)" == "true" ] && IMGIND=$i
58            done
59            # Check if it needs to update or insert data.
60            if [ -n "$IMGIND" ]; then
61                # Update if image data changes and info file exists.
62                [ -n "$3" -a "$(jq ".check=$JSON | .check==.images[$IMGIND]" $INFOFILE)" == "false" ] && jq ".images[$IMGIND]=$JSON" $INFOFILE | sponge $INFOFILE
63            else
64                # Append a new entry.
65                jq ".images |= (. + [$JSON])" $INFOFILE | sponge $INFOFILE
66            fi
67        else    # OU image.
68            # Append a new OU entry if it does not exist.
69            if [ -z "$(jq -r ".ous[].subdir" $INFOFILE | grep "^$OUNAME$")" ]; then
70                JSON=$(cat << EOT | jq .
71{
72  "subdir": "$OUNAME",
73  "images": [ $JSON ]
74}
75EOT
76                )
77                jq ".ous |= (. + [$JSON])" $INFOFILE | sponge $INFOFILE
78            else
79                # Check if the image is defined in some OU.
80                m=$(jq ".ous | length" $INFOFILE)
81                for ((j=0; j<m; j++)); do
82                    n=$(jq ".ous[$j].images | length" $INFOFILE)
83                    for ((i=0; i<n; i++)); do
84                        [ "$(jq ".check=$JSON | .check.name==.ous[$j].images[$i].name" $INFOFILE)" == "true" ] && OUIND=$j && IMGIND=$i
85                    done
86                done
87                # Check if it needs to update or insert data.
88                if [ -n "$IMGIND" ]; then
89                    # Update if image data changes and info file exists.
90                    [ $# -gt 2 -a "$(jq ".check=$JSON | .check==.ous[$OUIND].images[$IMGIND]" $INFOFILE)" == "false" ] && jq ".ous[$OUIND].images[$IMGIND]=$JSON" $INFOFILE | sponge $INFOFILE
91                else
92                    # Obtener el índice de la UO donde añadir la nueva entrada. Por acodoner
93                    m=$(jq ".ous | length" $INFOFILE)
94                    for ((j=0; j<m; j++)); do
95                        [ $(jq ".ous[$j].subdir" $INFOFILE | sed s/\"//g) == $OUNAME ] && OUIND=$j 
96                    done
97                    # Append a new entry.
98                    jq ".ous[$OUIND].images |= (. + [$JSON])" $INFOFILE | sponge $INFOFILE
99                fi
100            fi
101        fi
102    else
103        # Create new JSON file.
104        if [ -z "$OUNAME" ]; then
105            cat << EOT | jq . > $INFOFILE
106{"directory":"$IMAGESDIR","images":[${IMAGENAME:+$JSON}],"ous":[]}
107EOT
108        else
109            cat << EOT | jq . > $INFOFILE
110{"directory":"$IMAGESDIR","images":[],"ous":[{"subdir":"$OUNAME","images":[$JSON]}]}
111EOT
112        fi
113    fi
114}
115
116# Check for file-based images to update the repository configuration file.
117function checkfiles() {
118    local IMAGES IMG INFO DATA
119    # File-stored images.
120    IMAGES=$(find $IMAGESDIR -maxdepth 2 -type f \( -name "*.img" -o -name "*.dsk" \) -print)
121    for IMG in $IMAGES; do
122        # Skip locked images.
123        [ -e "$IMG.lock" ] && continue
124        # Retrieve image creation data and delete temporary file.
125        INFO="$IMG.info"
126        [ ! -e "$INFO" ] && continue # Si no existe fichero .info, no hacer nada y pasar al siguiente. Por acodoner
127        [ "$INFO" -ot "$IMG" ] && rm -f "$INFO" && echo "Warning: Deleted outdated file $INFO" && continue # Si el fichero .info es obsoleto, borralo, no hacer nada y pasar al siguiente. Por acodoner
128        DATA=""
129        [ -r "$INFO" ] && DATA=$(cat "$INFO")
130        # Add data to configuration file (name, type and data) and remove image info file.
131        IMG=${IMG#$IMAGESDIR/}
132        addToJson "${IMG%.*}" "${IMG##*.}" "$DATA" && rm -f "$INFO"
133    done
134}
135
136
137# Check for directory-based images to update the repository configuration file.
138function checkdirs() {
139    local IMAGES IMG INFO DATA
140
141    # Directory-based images.
142    IMAGES=$(find $IMAGESDIR -maxdepth 3 -type f -name ogimg.info -print)
143    for INFO in $IMAGES; do
144        IMG="$(dirname "${INFO#$IMAGESDIR/}")"
145        # Skip repository root directory and locked images.
146        [ "$IMG" == "$IMAGESDIR" -o -e "$IMG.lock" ] && continue
147        DATA=$(awk -F= '$1=="# fstype" {fs=$2} $1=="# sizedata" {sz=$2} END {printf "rsync::%s:%s:",fs,sz}' "$INFO")
148        # Add data to configuration file (name, type and data).
149        addToJson "$IMG" "dir" "$DATA"
150    done
151}
152
153# Check if images are removed to update the repository configuration file.
154function checkremoved() {
155    local IMG TYPE OU i j n m
156    [ ! -w "$INFOFILE" ] && raiseError access "$INFOFILE"
157
158    # Check if global images are defined into JSON file.
159    n=$(jq ".images | length" $INFOFILE)
160    for ((i=0; i<n; i++)); do
161        # Image name and type.
162        IMG="$(jq -r ".images[$i].name" $INFOFILE)"
163        TYPE="$(jq -r ".images[$i].type" $INFOFILE)"
164        [ "$TYPE" != "dir" ] && IMG="$IMG.$TYPE"
165        # Delete entry if image does not exist and it's not locked.
166        [ ! -e "$IMAGESDIR/$IMG" -a ! -e "$IMAGESDIR/$IMG.lock" ] && jq "del(.images[$i])" $INFOFILE | sponge $INFOFILE
167    done
168    # Check if OU images are defined into JSON file.
169    m=$(jq ".ous | length" $INFOFILE)
170    for ((j=0; j<m; j++)); do
171        # OU subdir.
172        OU="$(jq -r ".ous[$j].subdir" $INFOFILE)"
173        # Delete OU's entries if its subdir does not exist.
174        if [ ! -e "$IMAGESDIR/$OU" ]; then
175            jq "del(.ous[$j])" $INFOFILE | sponge $INFOFILE
176        else
177            #n=$(jq ".images | length" $INFOFILE)
178            n=$(jq ".ous[$j].images | length" $INFOFILE) #corregido por acodoner
179            for ((i=0; i<n; i++)); do
180                # Image name and type.
181                IMG="$(jq -r ".ous[$j].images[$i].name" $INFOFILE)"
182                TYPE="$(jq -r ".ous[$j].images[$i].type" $INFOFILE)"
183                [ "$TYPE" != "dir" ] && IMG="$IMG.$TYPE"
184                # Delete entry if image does not exist and it's not locked.
185                [ ! -e "$IMAGESDIR/$OU/$IMG" -a ! -e "$IMAGESDIR/$OU/$IMG.lock" ] && jq "del(.ous[$j].images[$i])" $INFOFILE | sponge $INFOFILE
186            done
187        fi
188    done
189}
190
191
192# Main program.
193
194# Comprobar si el proceso ya está en ejecución.
195[ "$(pgrep "$PROG")" != "$$" ] &&  exit
196
197# Check dependencies.
198[ -w "$(dirname "$INFOFILE")" ] || raiseError access "$INFOFILE"
199[ -e "$INFOFILE" ] || addToJson
200which sponge &>/dev/null || raiseError notfound "Need to install \"moreutils\"."
201
202checkfiles
203checkdirs
204checkremoved
205
206