source: server/bin/oglivecli @ 5cdd988

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 5cdd988 was d244d7f, checked in by ramon <ramongomez@…>, 8 years ago

#774: Script oglivecli registra arquitectura del ogLive.

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

  • Property mode set to 100755
File size: 17.6 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" OGLIVEARCH="$3" OGLIVEREV="$4"
29    local OGLIVEDIR="$(basename $5)" OGLIVEISO="$(basename $6)"
30    # JSON data for installed ogLive.
31    DATA=$(cat << EOT | jq .
32{"distribution":"$OGLIVEDIST","kernel":"$OGLIVEKRNL","architecture":"$OGLIVEARCH","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)" == "true" ] && 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 ogclient to new 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 "$(echo $OGLIVEISO|cut -f2 -d-)" "$OGLIVEKRNL" "i386" "${OGLIVEISO##*-}" "$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    # Delete old config file.
133    rm -f $OLDINFOFILE
134}
135
136# Show script configuration parameters.
137function config() {
138    case $# in
139        0)  # Show all parameters.
140            cat << EOT
141Configuration file:             $INFOFILE
142ogLive download URL:            $DOWNLOADURL
143ogLive download directory:      $DOWNLOADDIR
144ogLive installation directory:  $TFTPDIR
145Default ogLive name:            $DEFOGLIVE
146EOT
147            ;;
148        1)  # Show specified parameter.
149            case "$1" in
150                config-file)    echo "$INFOFILE" ;;
151                download-url)   echo "$DOWNLOADURL" ;;
152                download-dir)   echo "$DOWNLOADDIR" ;;
153                install-dir)    echo "$TFTPDIR" ;;
154                default-name)   echo "$DEFOGLIVE" ;;
155                *)              raiseError notfound "$1" ;;
156            esac
157            ;;
158        *)  # Usage error.
159            raiseError usage
160            ;;
161esac
162}
163
164# Check consistency, showing configuration problems.
165function check() {
166    local ERR=0 AUX INST DEF
167    [ $# -ne 0 ] && raiseError usage
168    # Check for old system that needs conversion.
169    if [ -z "$(stat -c "%N" $TFTPDIR/ogclient | awk '$3~/'$DEFOGLIVE'/ {print}')" ]; then
170         echo "This server uses old ogclient, please run \"$PROG convert\" to update."
171         let ERR++
172         [ ! -f $INFOFILE ] && exit $ERR
173    fi
174    # Check for other problems.
175    [ ! -f $INFOFILE ] && echo "Configuration file does not exist: $INFOFILE" && let ERR++
176    [ "$(jq -c keys $INFOFILE 2>/dev/null)" != "[\"default\",\"oglive\"]" ] && echo "Format error in configuration file: $INFOFILE" && let ERR++
177    [ ! -e $TFTPDIR ] && echo "TFTP directory does not exist: $TFTPDIR." && let ERR++
178    # Check for installed ogLives.
179    INST=( $(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort) )
180    [[ ${#INST[@]} -eq 0 ]] && echo "No ogLive clients are installed." && let ERR++
181    DEF=( $(jq -r .oglive[].directory $INFOFILE 2>/dev/null | sort) )
182    # Compare installed and defined ogLive clients.
183    AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
184    [ -n "$AUX" ] && echo "Some ogLive are installed but not defined: ${AUX//$'\n'/, }" && let ERR++
185    AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
186    [ -n "$AUX" ] && echo "Some ogLive are defined but not installed: ${AUX//$'\n'/, }" && let ERR++
187    # Compare downloaded and defined ISO images.
188    INST=( $(find $DOWNLOADDIR/ -type f -name "$DEFOGLIVE-*.iso" -printf "%f\n" | sort) )
189    DEF=( $(jq -r .oglive[].iso $INFOFILE 2>/dev/null | sort) )
190    AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
191    [ -n "$AUX" ] && echo "Some ISOs are downloaded but not defined: ${AUX//$'\n'/, }" && let ERR++
192    AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
193    [ -n "$AUX" ] && echo "Some ISOs are defined but not downloaded: ${AUX//$'\n'/, }" && let ERR++
194    # Print result.
195    [ $ERR -eq 0 ] && echo "OK!" || echo "Problems detected: $ERR"
196    return $ERR
197}
198
199# List installed ogLive clients.
200function list() {
201    [ $# -ne 0 ] && raiseError usage
202    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
203    # List all defined indexes, directories and check if missing.
204    jq -r .oglive[].directory $INFOFILE | nl -v 0 | \
205            awk '{system("echo -n "$0"; test -d '$TFTPDIR'/"$2" || echo -n \" (missing)\"; echo")}' | column -t
206}
207
208# Show information about an installed ogLive client.
209function show() {
210    local INDEX
211    [ $# -ne 1 ] && raiseError usage
212    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
213    # Show JSON entries.
214    case "$1" in
215        default)    # Default index.
216            INDEX="[$(jq -r .default $INFOFILE)]" ;;
217        all)        # All intries.
218            ;;
219        [0-9]*)     # Index.
220            INDEX="[$1]" ;;
221        *)          # Directory.
222            INDEX="[$(search "$1" 2>/dev/null)]" || raiseError notfound "Directory \"$1\"."
223            ;;
224    esac
225    jq ".oglive$INDEX" $INFOFILE || raiseError notfound "Index \"$1\"."
226}
227
228# Show index or directory corresponding to searching parameter.
229function search() {
230    [ $# -ne 1 ] && raiseError usage
231    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
232    # Show corresponding index or directory.
233    list | awk -v d="$1" '{if ($2==d) print $1; if ($1==d) print $2}' | grep . || raiseError notfound "Index/Directory \"$1\""
234}
235
236# Show a menu to select and download an ogLive ISO image from the OpenGnsys website.
237function download() {
238    local OGLIVE NISOS i SOURCELENGTH TARGETFILE
239    [ $# -gt 1 ] && raiseError usage
240    [ ! -d $DOWNLOADDIR ] && raiseError notfound "Download directory"
241    [ ! -w $DOWNLOADDIR ] && raiseError access "Download directory"
242    # Check parameter.
243    if [ -n "$1" ]; then
244        # ogLive to download.
245        OGLIVEFILE="$1"
246    else
247        # Show download menu.
248        OGLIVE=( $(wget $DOWNLOADURL -O - 2>/dev/null | grep $DEFOGLIVE.*iso) )
249        NISOS=${#OGLIVE[@]}
250        echo "Available downloads (+- = installed):"
251        for i in $(seq 1 $NISOS); do
252            [ -e $DOWNLOADDIR/${OGLIVE[i-1]} ] && OGLIVE[i-1]="+-${OGLIVE[i-1]}"
253        done
254        select opt in ${OGLIVE[@]}; do
255            [ -n "$opt" ] && OGLIVEFILE=${opt/+-/} && break
256        done
257    fi
258    # Get download size.
259    SOURCELENGTH=$(LANG=C wget --spider $DOWNLOADURL/$OGLIVEFILE 2>&1 | awk '/Length:/ {print $2}')
260    [ -n "$SOURCELENGTH" ] || raiseError download "$OGLIVEFILE"
261    # Download ogLive.
262    TARGETFILE=$DOWNLOADDIR/$OGLIVEFILE
263    trap "rm -f $TARGETFILE" 1 2 3 6 9 15
264    wget $DOWNLOADURL/$OGLIVEFILE -O $TARGETFILE || raiseError download "$OGLIVEFILE"
265}
266
267# Install an ogLive client from a previously downloaded ISO image.
268function install() {
269    local OGLIVEFILE OGLIVEDIST OGLIVEREV OGLIVEKRNL OGLIVEDIR OGINITRD OGSQFS
270    local SAMBAPASS TMPDIR RSYNCSERV RSYNCCLNT
271    [ $# -ne 1 ] && raiseError usage
272    OGLIVEFILE=$DOWNLOADDIR/"$1"
273    [ ! -f $OGLIVEFILE ] && raiseError notfound "Downloaded file: \"$1\"."
274    [ ! -r $OGLIVEFILE ] && raiseError access "Downloaded file: \"$1\"."
275    [ ! -w $(dirname $INFOFILE) ] && raiseError access "Configuration directory."
276    [ ! -w $TFTPDIR ] && raiseError access "Installation directory."
277    [ -z "$(file -b $OGLIVEFILE | grep "ISO.*ogClient")" ] && raiseError access "File is not an ogLive ISO image."
278    # Working directory (ogLive-Distribution-KernelVersion-CodeRevision).
279    OGLIVEDIST="$(echo $OGLIVEFILE|cut -f2 -d-)"
280    OGLIVEREV="${OGLIVEFILE##*-}"; OGLIVEREV="${OGLIVEREV%.*}"
281    OGLIVEKRNL="$(echo $OGLIVEFILE|cut -f3- -d-)"; OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEREV.*}"
282    OGLIVEARCH="$(echo $OGLIVEFILE|awk -F- '{print $(NF-1)}')"
283    case "$OGLIVEARCH" in
284        i386|amd64)
285            OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEARCH}" ;;
286        *)
287            OGLIVEARCH="i386" ;;
288    esac
289    OGLIVEDIR="$TFTPDIR/$DEFOGLIVE-$OGLIVEDIST-${OGLIVEKRNL%%-*}-$OGLIVEARCH-$OGLIVEREV"
290    # Get current or default Samba key.
291    OGINITRD=$OGLIVEDIR/oginitrd.img
292    [ ! -r $OGINITRD ] && OGINITRD=$TFTPDIR/$DEFOGLIVE/oginitrd.img
293    if [ -r $OGINITRD ]; then
294    SAMBAPASS=$(gzip -dc $OGINITRD | \
295    cpio -i --to-stdout scripts/ogfunctions 2>&1 | \
296            grep "^[    ].*OPTIONS=" | \
297            sed 's/\(.*\)pass=\(\w*\)\(.*\)/\2/')
298    fi
299    # Make ogLive backup.
300    rm -fr ${OGLIVEDIR}.old
301    mv -fv $OGLIVEDIR ${OGLIVEDIR}.old 2>/dev/null
302    # Mount ogLive ISO image, update its files, unmount it and set as default.
303    TMPDIR=/tmp/${OGLIVEFILE%.iso}
304    mkdir -p $OGLIVEDIR $TMPDIR
305    trap "umount $TMPDIR; rm -fr $TMPDIR" 1 2 3 6 9 15
306    mount -o loop,ro $OGLIVEFILE $TMPDIR
307    cp -va $TMPDIR/ogclient/* $OGLIVEDIR || exit 2
308    umount $TMPDIR
309    rm -f $TFTPDIR/$DEFOGLIVE
310    ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE
311    # Recover or ask for a new Samba access key.
312    if [ -n "$SAMBAPASS" ]; then
313        echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | $OPENGNSYS/bin/setsmbpass
314    else
315        $OPENGNSYS/bin/setsmbpass
316    fi
317    # Set permissions.
318    find -L $OGLIVEDIR -type d -exec chmod 755 {} \;
319    find -L $OGLIVEDIR -type f -exec chmod 644 {} \;
320    chown -R :opengnsys $OGLIVEDIR
321    # Mount SquashFS and check Rsync version.
322    OGSQFS=$OGLIVEDIR/ogclient.sqfs
323    mount -o loop,ro $OGSQFS $TMPDIR
324    # If Rsync server version > client version, link to compiled file.
325    RSYNCSERV=$(rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
326    RSYNCCLNT=$(chroot $TMPDIR /usr/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
327    if [ -z "$RSYNCSERV" -o ${RSYNCSERV:-0} -gt ${RSYNCCLNT:-1} ]; then
328        [ -e $OPENGNSYS/client/bin/rsync-$RSYNCSERV ] && mv -f $OPENGNSYS/client/bin/rsync-$RSYNCSERV $OPENGNSYS/client/bin/rsync
329    else
330        # Else, rename compiled file using Rsync protocol number.
331        [ -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}')
332    fi
333    # Unmount SquashFS.
334    umount $TMPDIR
335    rmdir $TMPDIR
336    # Update JSON file.
337    addToJson "$OGLIVEDIST" "$OGLIVEKRNL" "$OGLIVEARCH" "$OGLIVEREV" "$OGLIVEDIR" "$OGLIVEFILE"
338}
339
340# Uninstall an ogLive client.
341function uninstall() {
342    local ISO DIR INDEX DEFINDEX
343    [ $# -ne 1 ] && raiseError usage
344    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
345    [ ! -w $TFTPDIR ] && raiseError access "Installation directory."
346    # Get index and directory for the entry.
347    case "$1" in
348        */*)    # Error (access to other directory).
349            raiseError access "Cannot access outside installation directory."
350            ;;
351        $DEFOGLIVE-*.iso)  # ISO file.
352            ISO="$1"
353            # Working directory (ogLive-Distribution-KernelVersion-CodeRevision).
354            DIR="$(echo $ISO|cut -f1,3 -d-)-${ISO##*-}"; DIR=${DIR%.*}
355            INDEX=$(search $DIR 2>/dev/null)
356            ;;
357        [0-9]*) # Index.
358            INDEX=$1; DIR=$(search $INDEX 2>/dev/null)
359            ;;
360        *)      # Directory.
361            DIR="$1"; INDEX=$(search $DIR 2>/dev/null)
362            ;;
363    esac
364    DEFINDEX=$(getdefault)
365    [[ $INDEX = $DEFINDEX ]] && raiseError access "Cannot uninstall default ogLive."
366    # Remove files and delete index entry.
367    rm -vfr ${ISO:+$DOWNLOADDIR/$ISO} ${DIR:+$TFTPDIR/$DIR}    ### Remove $TFTPDIR/$DIR.old ?
368    if [ -n "$INDEX" ]; then
369        jq "del(.oglive[$INDEX])" $INFOFILE | sponge $INFOFILE
370        # Decrement default index if needed (removed < default).
371        [[ $INDEX < $DEFINDEX ]] && jq ".default=$[DEFINDEX-1]" $INFOFILE | sponge $INFOFILE
372    fi
373}
374
375# Get default ogLive index.
376function getdefault() {
377    [ $# -ne 0 ] && raiseError usage
378    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
379    # Read default parameter.
380    jq -r .default $INFOFILE || raiseError notfound "Undefined default index."
381}
382
383# Set default ogLive index.
384function setdefault() {
385    local INDEX OGLIVEDIR
386    [ $# -ne 1 ] && raiseError usage
387    [ ! -w $INFOFILE ] && raiseError access "Configuration file."
388    INDEX=$1
389    # Check if index entry exists.
390    jq ".oglive[$INDEX]" $INFOFILE || raiseError notfound "Index \"$INDEX\"."
391    # Get ogLive directory.
392    OGLIVEDIR=$(jq -r ".oglive[$INDEX].directory" $INFOFILE) || raiseError notfound "Directory for index \"$INDEX\"."
393    # Update default parameter.
394    jq ".default=$INDEX" $INFOFILE | sponge $INFOFILE
395exit
396    # Link to default directory.
397    rm -f $TFTPDIR/$DEFOGLIVE
398    ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE
399}
400
401# Assign an ISO file to a JSON entry.
402function assign() {
403local ISOFILE DIR
404    [ $# -ne 2 ] && raiseError usage
405    [ ! -w $INFOFILE ] && raiseError access "Configuration file."
406    # Check if exist ISO file and index directory.
407    ISOFILE=$DOWNLOADFILE/$1
408    [ ! -f $DOWNLOADDIR/$ISOFILE ] && raiseError notfound "ISO file \"$1\"."
409    DIR=$(search $2 2>/dev/null)
410    [ ! -d $TFTPDIR/$DIR ] && raiseError notfound "Directory for index \"$2\"."
411    # Assign ISO file to JSON entry.
412    jq ".oglive[$2].iso=\"$1\"" $INFOFILE | sponge $INFOFILE && jq ".oglive[$2]" $INFOFILE
413}
414
415
416# Main progrram.
417
418# Global constants definition.
419PROG=$(basename $(realpath "$0"))
420OPENGNSYS=/opt/opengnsys
421DOWNLOADDIR=$OPENGNSYS/lib
422DOWNLOADURL="http://opengnsys.es/downloads"
423TFTPDIR=$OPENGNSYS/tftpboot
424DEFOGLIVE=ogLive
425INFOFILE=$OPENGNSYS/etc/ogliveinfo.json
426
427# Access control.
428[ "$USER" = "root" ] || raiseError access "Need to be root."
429# Check dependencies.
430JQ=$(which jq 2>/dev/null) || raiseError notfound "Need to install \"jq\"."
431which sponge &>/dev/null || raiseError notfound "Need to install \"moreutils\"."
432# Commands control.
433case "$1" in
434    help|convert|config|check|list|show|search|download|install|uninstall|get-default|set-default|assign)
435        COMMAND="${1/-/}"; shift; $COMMAND "$@" ;;
436    *)  raiseError usage ;;
437esac
438
439exit $?
440
Note: See TracBrowser for help on using the repository browser.