source: server/bin/oglivecli @ 2f9cd767

918-git-images-111dconfigfileconfigure-oglivegit-imageslgromero-new-oglivemainmaint-cronmount-efivarfsmultivmmultivm-ogboot-installerogClonningEngineogboot-installer-jenkinsoglive-ipv6test-python-scriptsticket-301ticket-50ticket-50-oldticket-577ticket-585ticket-611ticket-612ticket-693ticket-700ubu24tplunification2use-local-agent-oglivevarios-instalacionwebconsole3
Last change on this file since 2f9cd767 was b6e2f16, checked in by ramon <ramongomez@…>, 8 years ago

#768: Comparación de objetos JSON para inserción o actualización.

git-svn-id: https://opengnsys.es/svn/branches/version1.1@5164 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100755
File size: 17.2 KB
Line 
1#!/bin/bash
2
3#/**
4#         oglivecli command [options ...]
5#@file    oglivecli
6#@brief   Command line tool to manage ogLive clients.
7#@param   $1 command  Command to execute.
8#@param   $2 options  Parameters and options.
9#@warning This script uses "jq" command.
10#@version 1.1.0 - Initial version.
11#@author  Ramón M. Gómez - ETSII Univ. Sevilla
12#@date    2016-12-05
13#*/ ##
14
15
16# Auxiliar functions.
17
18# Metafunction to check if JSON result exists.
19function jq() {
20    local OUTPUT
21    OUTPUT=$($JQ "$@") || return $?
22    [[ "$OUTPUT" = "null" ]] && return 1
23    echo "$OUTPUT"
24}
25
26# Create/edit JSON file about installed ogLive clients.
27function addToJson() {
28    local DATA OGLIVEDIST="$1" OGLIVEKRNL="$2" OGLIVEREV="$3"
29    local OGLIVEDIR="$(basename $4)" OGLIVEISO="$(basename $5)"
30    # JSON data for installed ogLive.
31    DATA=$(cat << EOT | jq .
32{"distribution":"$OGLIVEDIST","kernel":"$OGLIVEKRNL","revision":"$OGLIVEREV","directory":"$OGLIVEDIR","iso":"$OGLIVEISO"}
33EOT
34    )
35    # Check JSON file consistency.
36    if [ "$(jq -c keys $INFOFILE 2>/dev/null)" == "[\"default\",\"oglive\"]" ]; then
37        # Check if ogLive is defined into JSON file.
38        n=$(jq ".oglive | length" $INFOFILE)
39        for ((i=0; i<n; i++)); do
40            [ "$(jq ".check=$DATA | .check==.oglive[$i]" $INFOFILE)" ] && INDEX=$i
41        done
42        # Check if it needs to insert data.
43        if [ -z "$INDEX" ]; then
44            INDEX=$n
45            jq ".oglive |= (. + [$DATA])" $INFOFILE | sponge $INFOFILE
46        fi
47        # Update dafault index.
48        jq ".default=$INDEX" $INFOFILE | sponge $INFOFILE
49        jq ".oglive[$INDEX]" $INFOFILE
50    else
51        # Create new JSON file.
52        cat << EOT | jq . | tee $INFOFILE
53{"oglive":[$DATA],"default":0}
54EOT
55    fi
56}
57
58# Show an error message.
59function raiseError() {
60    case "$1" in
61        usage)
62            echo "$PROG: Usage error: Type \"$PROG help\"" >&2
63            exit 1 ;;
64        notfound)
65            echo "$PROG: Resource not found: $2" >&2
66            exit 2 ;;
67        access)
68            echo "$PROG: Access error: $2" >&2
69            exit 3 ;;
70        download)
71            echo "$PROG: Download error: $2" >&2
72            exit 4 ;;
73        *)
74            echo "$PROG: Unknown error" >&2
75            exit 1 ;;
76    esac
77}
78
79# Command functions.
80
81# Show help message.
82function help() {
83    cat << EOT
84$PROG: manage ogLive cleints.
85Usage: $PROG command [options]
86Commands:
87  help                show this help
88  config              show configuration parameters
89  check               check system consistency
90  convert             convert old default ogclient to default ogLive client
91  list                list installed ogLive clients
92  show all            show JSON information about all installed ogLive clients
93  show default        show JSON information about ogLive client marked as default
94  show Index|Dir      show JSON information about an installed ogLive client
95  search Index|Dir    show corresponding index or directory
96  download            show a menu to download an ogLive ISO image from the OpenGnsys website
97  download Iso        download an specific ogLive ISO image from the OpenGnsys website
98  install Iso         install a new ogLive client from a downloaded ISO image
99  uninstall Iso       remove ISO image and uninstall its ogLive client
100  uninstall Index|Dir uninstall an ogLive client
101  get-default         get index value for default ogLive client
102  set-default Index   set default ogLive client
103  assign Iso Index    assign an ISO file to a JSON entry
104Parameters:
105  Index   a number, starting by 0
106  Dir     directory (relative to installation directory)
107  Iso     ISO file name (relative to download URL or download directory)
108EOT
109}
110
111# Convert default ogclient to a new ogLive format.
112function convert() {
113    local OGCLIENT=ogclient OLDINFOFILE=$OPENGNSYS/doc/veroglive.txt
114    local OGLIVEKRNL OGLIVEDIR OGLIVEISO
115    [ $# -ne 0 ] && raiseError usage
116    [ ! -w $(dirname $INFOFILE) ] && raiseError access "Configuration file."
117    [ -n "$(stat -c "%N" $TFTPDIR/ogclient | awk '$3~/'$DEFOGLIVE'/ {print}')" ] && raiseError access "ogLive is already converted."
118    pushd $TFTPDIR >/dev/null || raiseError access "Installation directory."
119    [ ! -f $OGCLIENT/ogvmlinuz ] && raiseError notfound "ogclient"
120    # Add entry to JSON file using ogclient kernel version.
121    OGLIVEKRNL=$(file -bkr $OGCLIENT/ogvmlinuz | awk '/Linux/ {for(i=1;i<=NF;i++) if($i~/version/) {v=$(i+1);sub(/-.*/,"",v);print v}}')
122    OGLIVEDIR=$DEFOGLIVE-$OGLIVEKRNL
123    [ -r $OLDINFOFILE ] && OGLIVEISO=$(head -1 $OLDINFOFILE).iso
124    addToJson "" "$OGLIVEKRNL" "" "$OGLIVEDIR" "$OGLIVEISO"
125    # Rename directory, link to default and clean old files.
126    mv -v $OGCLIENT $OGLIVEDIR
127    ln -vfs $OGLIVEDIR $DEFOGLIVE
128    ln -vfs $DEFOGLIVE $OGCLIENT
129    mv -v $OGCLIENT.old $OGLIVEDIR.old 2>/dev/null
130    rm -fv {ogvmlinuz,oginitrd.img}{,.sum} $OLDINFOFILE
131    popd >/dev/null
132}
133
134# Show script configuration parameters.
135function config() {
136    case $# in
137        0)  # Show all parameters.
138            cat << EOT
139Configuration file:             $INFOFILE
140ogLive download URL:            $DOWNLOADURL
141ogLive download directory:      $DOWNLOADDIR
142ogLive installation directory:  $TFTPDIR
143Default ogLive name:            $DEFOGLIVE
144EOT
145            ;;
146        1)  # Show specified parameter.
147            case "$1" in
148                config-file)    echo "$INFOFILE" ;;
149                download-url)   echo "$DOWNLOADURL" ;;
150                download-dir)   echo "$DOWNLOADDIR" ;;
151                install-dir)    echo "$TFTPDIR" ;;
152                default-name)   echo "$DEFOGLIVE" ;;
153                *)              raiseError notfound "$1" ;;
154            esac
155            ;;
156        *)  # Usage error.
157            raiseError usage
158            ;;
159esac
160}
161
162# Check consistency, showing configuration problems.
163function check() {
164    local ERR=0 AUX INST DEF
165    [ $# -ne 0 ] && raiseError usage
166    # Check for old system that needs conversion.
167    if [ -z "$(stat -c "%N" $TFTPDIR/ogclient | awk '$3~/'$DEFOGLIVE'/ {print}')" ]; then
168         echo "This server uses old ogclient, please run \"$PROG convert\" to update."
169         let ERR++
170         [ ! -f $INFOFILE ] && exit $ERR
171    fi
172    # Check for other problems.
173    [ ! -f $INFOFILE ] && echo "Configuration file does not exist: $INFOFILE" && let ERR++
174    [ "$(jq -c keys $INFOFILE 2>/dev/null)" != "[\"default\",\"oglive\"]" ] && echo "Format error in configuration file: $INFOFILE" && let ERR++
175    [ ! -e $TFTPDIR ] && echo "TFTP directory does not exist: $TFTPDIR." && let ERR++
176    # Check for installed ogLives.
177    INST=( $(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort) )
178    [[ ${#INST[@]} -eq 0 ]] && echo "No ogLive clients are installed." && let ERR++
179    DEF=( $(jq -r .oglive[].directory $INFOFILE 2>/dev/null | sort) )
180    # Compare installed and defined ogLive clients.
181    AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
182    [ -n "$AUX" ] && echo "Some ogLive are installed but not defined: ${AUX//$'\n'/, }" && let ERR++
183    AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
184    [ -n "$AUX" ] && echo "Some ogLive are defined but not installed: ${AUX//$'\n'/, }" && let ERR++
185    # Compare downloaded and defined ISO images.
186    INST=( $(find $DOWNLOADDIR/ -type f -name "$DEFOGLIVE-*.iso" -printf "%f\n" | sort) )
187    DEF=( $(jq -r .oglive[].iso $INFOFILE 2>/dev/null | sort) )
188    AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
189    [ -n "$AUX" ] && echo "Some ISOs are downloaded but not defined: ${AUX//$'\n'/, }" && let ERR++
190    AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
191    [ -n "$AUX" ] && echo "Some ISOs are defined but not downloaded: ${AUX//$'\n'/, }" && let ERR++
192    # Print result.
193    [ $ERR -eq 0 ] && echo "OK!" || echo "Problems detected: $ERR"
194    return $ERR
195}
196
197# List installed ogLive clients.
198function list() {
199    [ $# -ne 0 ] && raiseError usage
200    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
201    # List all defined indexes, directories and check if missing.
202    jq -r .oglive[].directory $INFOFILE | nl -v 0 | \
203            awk '{system("echo -n "$0"; test -d '$TFTPDIR'/"$2" || echo -n \" (missing)\"; echo")}' | column -t
204}
205
206# Show information about an installed ogLive client.
207function show() {
208    local INDEX
209    [ $# -ne 1 ] && raiseError usage
210    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
211    # Show JSON entries.
212    case "$1" in
213        default)    # Default index.
214            INDEX="[$(jq -r .default $INFOFILE)]" ;;
215        all)        # All intries.
216            ;;
217        [0-9]*)     # Index.
218            INDEX="[$1]" ;;
219        *)          # Directory.
220            INDEX="[$(search "$1" 2>/dev/null)]" || raiseError notfound "Directory \"$1\"."
221            ;;
222    esac
223    jq ".oglive$INDEX" $INFOFILE || raiseError notfound "Index \"$1\"."
224}
225
226# Show index or directory corresponding to searching parameter.
227function search() {
228    [ $# -ne 1 ] && raiseError usage
229    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
230    # Show corresponding index or directory.
231    list | awk -v d="$1" '{if ($2==d) print $1; if ($1==d) print $2}' | grep . || raiseError notfound "Index/Directory \"$1\""
232}
233
234# Show a menu to select and download an ogLive ISO image from the OpenGnsys website.
235function download() {
236    local OGLIVE NISOS i SOURCELENGTH TARGETFILE
237    [ $# -gt 1 ] && raiseError usage
238    [ ! -d $DOWNLOADDIR ] && raiseError notfound "Download directory"
239    [ ! -w $DOWNLOADDIR ] && raiseError access "Download directory"
240    # Check parameter.
241    if [ -n "$1" ]; then
242        # ogLive to download.
243        OGLIVEFILE="$1"
244    else
245        # Show download menu.
246        OGLIVE=( $(wget $DOWNLOADURL -O - 2>/dev/null | grep $DEFOGLIVE.*iso) )
247        NISOS=${#OGLIVE[@]}
248        echo "Available downloads (+- = installed):"
249        for i in $(seq 1 $NISOS); do
250            [ -e $DOWNLOADDIR/${OGLIVE[i-1]} ] && OGLIVE[i-1]="+-${OGLIVE[i-1]}"
251        done
252        select opt in ${OGLIVE[@]}; do
253            [ -n "$opt" ] && OGLIVEFILE=${opt/+-/} && break
254        done
255    fi
256    # Get download size.
257    SOURCELENGTH=$(LANG=C wget --spider $DOWNLOADURL/$OGLIVEFILE 2>&1 | awk '/Length:/ {print $2}')
258    [ -n "$SOURCELENGTH" ] || raiseError download "$OGLIVEFILE"
259    # Download ogLive.
260    TARGETFILE=$DOWNLOADDIR/$OGLIVEFILE
261    trap "rm -f $TARGETFILE" 1 2 3 6 9 15
262    wget $DOWNLOADURL/$OGLIVEFILE -O $TARGETFILE || raiseError download "$OGLIVEFILE"
263}
264
265# Install an ogLive client from a previously downloaded ISO image.
266function install() {
267    local OGLIVEFILE OGLIVEDIST OGLIVEREV OGLIVEKRNL OGLIVEDIR OGINITRD OGSQFS
268    local SAMBAPASS TMPDIR RSYNCSERV RSYNCCLNT
269    [ $# -ne 1 ] && raiseError usage
270    OGLIVEFILE=$DOWNLOADDIR/"$1"
271    [ ! -f $OGLIVEFILE ] && raiseError notfound "Downloaded file: \"$1\"."
272    [ ! -r $OGLIVEFILE ] && raiseError access "Downloaded file: \"$1\"."
273    [ ! -w $(dirname $INFOFILE) ] && raiseError access "Configuration directory."
274    [ ! -w $TFTPDIR ] && raiseError access "Installation directory."
275    [ -z "$(file -b $OGLIVEFILE | grep "ISO.*ogClient")" ] && raiseError access "File is not an ogLive ISO image."
276    # Working directory (ogLive-Distribution-KernelVersion-CodeRevision).
277    OGLIVEDIST="$(echo $OGLIVEFILE|cut -f2 -d-)"
278    OGLIVEREV="${OGLIVEFILE##*-}"; OGLIVEREV="${OGLIVEREV%.*}"
279    OGLIVEKRNL="$(echo $OGLIVEFILE|cut -f3- -d-)"; OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEREV.*}"
280    OGLIVEDIR="$TFTPDIR/$DEFOGLIVE-$OGLIVEDIST-${OGLIVEKRNL%%-*}-$OGLIVEREV"
281    # Get current or default Samba key.
282    OGINITRD=$OGLIVEDIR/oginitrd.img
283    [ ! -r $OGINITRD ] && OGINITRD=$TFTPDIR/$DEFOGLIVE/oginitrd.img
284    if [ -r $OGINITRD ]; then
285    SAMBAPASS=$(gzip -dc $OGINITRD | \
286    cpio -i --to-stdout scripts/ogfunctions 2>&1 | \
287            grep "^[    ].*OPTIONS=" | \
288            sed 's/\(.*\)pass=\(\w*\)\(.*\)/\2/')
289    fi
290    # Make ogLive backup.
291    rm -fr ${OGLIVEDIR}.old
292    mv -fv $OGLIVEDIR ${OGLIVEDIR}.old 2>/dev/null
293    # Mount ogLive ISO image, update its files, unmount it and set as default.
294    TMPDIR=/tmp/${OGLIVEFILE%.iso}
295    mkdir -p $OGLIVEDIR $TMPDIR
296    trap "umount $TMPDIR; rm -fr $TMPDIR" 1 2 3 6 9 15
297    mount -o loop,ro $OGLIVEFILE $TMPDIR
298    cp -va $TMPDIR/ogclient/* $OGLIVEDIR || exit 2
299    umount $TMPDIR
300    rm -f $TFTPDIR/$DEFOGLIVE
301    ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE
302    # Recover or ask for a new Samba access key.
303    if [ -n "$SAMBAPASS" ]; then
304        echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | $OPENGNSYS/bin/setsmbpass
305    else
306        $OPENGNSYS/bin/setsmbpass
307    fi
308    # Set permissions.
309    find -L $OGLIVEDIR -type d -exec chmod 755 {} \;
310    find -L $OGLIVEDIR -type f -exec chmod 644 {} \;
311    chown -R :opengnsys $OGLIVEDIR
312    # Mount SquashFS and check Rsync version.
313    OGSQFS=$OGLIVEDIR/ogclient.sqfs
314    mount -o loop,ro $OGSQFS $TMPDIR
315    # If Rsync server version > client version, link to compiled file.
316    RSYNCSERV=$(rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
317    RSYNCCLNT=$(chroot $TMPDIR /usr/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
318    if [ -z "$RSYNCSERV" -o ${RSYNCSERV:-0} -gt ${RSYNCCLNT:-1} ]; then
319        [ -e $OPENGNSYS/client/bin/rsync-$RSYNCSERV ] && mv -f $OPENGNSYS/client/bin/rsync-$RSYNCSERV $OPENGNSYS/client/bin/rsync
320    else
321        # Else, rename compiled file using Rsync protocol number.
322        [ -e $OPENGNSYS/client/bin/rsync ] && mv -f $OPENGNSYS/client/bin/rsync $OPENGNSYS/client/bin/rsync-$($OPENGNSYS/client/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
323    fi
324    # Unmount SquashFS.
325    umount $TMPDIR
326    rmdir $TMPDIR
327    # Update JSON file.
328    addToJson "$OGLIVEDIST" "$OGLIVEKRNL" "$OGLIVEREV" "$OGLIVEDIR" "$OGLIVEFILE"
329}
330
331# Uninstall an ogLive client.
332function uninstall() {
333    local ISO DIR INDEX DEFINDEX
334    [ $# -ne 1 ] && raiseError usage
335    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
336    [ ! -w $TFTPDIR ] && raiseError access "Installation directory."
337    # Get index and directory for the entry.
338    case "$1" in
339        */*)    # Error (access to other directory).
340            raiseError access "Cannot access outside installation directory."
341            ;;
342        $DEFOGLIVE-*.iso)  # ISO file.
343            ISO="$1"
344            # Working directory (ogLive-Distribution-KernelVersion-CodeRevision).
345            DIR="$(echo $ISO|cut -f1,3 -d-)-${ISO##*-}"; DIR=${DIR%.*}
346            INDEX=$(search $DIR 2>/dev/null)
347            ;;
348        [0-9]*) # Index.
349            INDEX=$1; DIR=$(search $INDEX 2>/dev/null)
350            ;;
351        *)      # Directory.
352            DIR="$1"; INDEX=$(search $DIR 2>/dev/null)
353            ;;
354    esac
355    DEFINDEX=$(getdefault)
356    [[ $INDEX = $DEFINDEX ]] && raiseError access "Cannot uninstall default ogLive."
357    # Remove files and delete index entry.
358    rm -vfr ${ISO:+$DOWNLOADDIR/$ISO} ${DIR:+$TFTPDIR/$DIR}    ### Remove $TFTPDIR/$DIR.old ?
359    if [ -n "$INDEX" ]; then
360        jq "del(.oglive[$INDEX])" $INFOFILE | sponge $INFOFILE
361        # Decrement default index if needed (removed < default).
362        [[ $INDEX < $DEFINDEX ]] && jq ".default=$[DEFINDEX-1]" $INFOFILE | sponge $INFOFILE
363    fi
364}
365
366# Get default ogLive index.
367function getdefault() {
368    [ $# -ne 0 ] && raiseError usage
369    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
370    # Read default parameter.
371    jq -r .default $INFOFILE || raiseError notfound "Undefined default index."
372}
373
374# Set default ogLive index.
375function setdefault() {
376    local INDEX OGLIVEDIR
377    [ $# -ne 1 ] && raiseError usage
378    [ ! -w $INFOFILE ] && raiseError access "Configuration file."
379    INDEX=$1
380    # Check if index entry exists.
381    jq ".oglive[$INDEX]" $INFOFILE || raiseError notfound "Index \"$INDEX\"."
382    # Get ogLive directory.
383    OGLIVEDIR=$(jq -r ".oglive[$INDEX].directory" $INFOFILE) || raiseError notfound "Directory for index \"$INDEX\"."
384    # Update default parameter.
385    jq ".default=$INDEX" $INFOFILE | sponge $INFOFILE
386exit
387    # Link to default directory.
388    rm -f $TFTPDIR/$DEFOGLIVE
389    ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE
390}
391
392# Assign an ISO file to a JSON entry.
393function assign() {
394local ISOFILE DIR
395    [ $# -ne 2 ] && raiseError usage
396    [ ! -w $INFOFILE ] && raiseError access "Configuration file."
397    # Check if exist ISO file and index directory.
398    ISOFILE=$DOWNLOADFILE/$1
399    [ ! -f $DOWNLOADDIR/$ISOFILE ] && raiseError notfound "ISO file \"$1\"."
400    DIR=$(search $2 2>/dev/null)
401    [ ! -d $TFTPDIR/$DIR ] && raiseError notfound "Directory for index \"$2\"."
402    # Assign ISO file to JSON entry.
403    jq ".oglive[$2].iso=\"$1\"" $INFOFILE | sponge $INFOFILE && jq ".oglive[$2]" $INFOFILE
404}
405
406
407# Main progrram.
408
409# Global constants definition.
410PROG=$(basename $0)
411OPENGNSYS=/opt/opengnsys
412DOWNLOADDIR=$OPENGNSYS/lib
413DOWNLOADURL="http://opengnsys.es/downloads"
414TFTPDIR=$OPENGNSYS/tftpboot
415DEFOGLIVE=ogLive
416INFOFILE=$OPENGNSYS/etc/ogliveinfo.json
417
418# Access control.
419if [ "$USER" != "root" ]; then
420    raiseError access "Need to be root."
421fi
422# Check dependencies.
423JQ=$(which jq 2>/dev/null) || raiseError notfound "Need to install \"jq\"."
424which sponge &>/dev/null || raiseError notfound "Need to install \"moreutils\"."
425# Commands control.
426case "$1" in
427    help|convert|config|check|list|show|search|download|install|uninstall|get-default|set-default|assign)
428        COMMAND="${1/-/}"; shift; $COMMAND "$@" ;;
429    *)  raiseError usage ;;
430esac
431
432exit $?
433
Note: See TracBrowser for help on using the repository browser.