source: server/bin/oglivecli @ 2b2311f

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 2b2311f was 715ff08, checked in by ramon <ramongomez@…>, 8 years ago

#768: Enlazar correctamente a directorio de antiguo cliente ogclient al instalar un nuevo cliente ogLive.

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

  • Property mode set to 100755
File size: 17.7 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 OGCLIENT=ogclient
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    ln -vfs $DEFOGLIVE $TFTPDIR/$OGCLIENT
312    # Recover or ask for a new Samba access key.
313    if [ -n "$SAMBAPASS" ]; then
314        echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | $OPENGNSYS/bin/setsmbpass
315    else
316        $OPENGNSYS/bin/setsmbpass
317    fi
318    # Set permissions.
319    find -L $OGLIVEDIR -type d -exec chmod 755 {} \;
320    find -L $OGLIVEDIR -type f -exec chmod 644 {} \;
321    chown -R :opengnsys $OGLIVEDIR
322    # Mount SquashFS and check Rsync version.
323    OGSQFS=$OGLIVEDIR/ogclient.sqfs
324    mount -o loop,ro $OGSQFS $TMPDIR
325    # If Rsync server version > client version, link to compiled file.
326    RSYNCSERV=$(rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
327    RSYNCCLNT=$(chroot $TMPDIR /usr/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
328    if [ -z "$RSYNCSERV" -o ${RSYNCSERV:-0} -gt ${RSYNCCLNT:-1} ]; then
329        [ -e $OPENGNSYS/client/bin/rsync-$RSYNCSERV ] && mv -f $OPENGNSYS/client/bin/rsync-$RSYNCSERV $OPENGNSYS/client/bin/rsync
330    else
331        # Else, rename compiled file using Rsync protocol number.
332        [ -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}')
333    fi
334    # Unmount SquashFS.
335    umount $TMPDIR
336    rmdir $TMPDIR
337    # Update JSON file.
338    addToJson "$OGLIVEDIST" "$OGLIVEKRNL" "$OGLIVEARCH" "$OGLIVEREV" "$OGLIVEDIR" "$OGLIVEFILE"
339}
340
341# Uninstall an ogLive client.
342function uninstall() {
343    local ISO DIR INDEX DEFINDEX
344    [ $# -ne 1 ] && raiseError usage
345    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
346    [ ! -w $TFTPDIR ] && raiseError access "Installation directory."
347    # Get index and directory for the entry.
348    case "$1" in
349        */*)    # Error (access to other directory).
350            raiseError access "Cannot access outside installation directory."
351            ;;
352        $DEFOGLIVE-*.iso)  # ISO file.
353            ISO="$1"
354            # Working directory (ogLive-Distribution-KernelVersion-CodeRevision).
355            DIR="$(echo $ISO|cut -f1,3 -d-)-${ISO##*-}"; DIR=${DIR%.*}
356            INDEX=$(search $DIR 2>/dev/null)
357            ;;
358        [0-9]*) # Index.
359            INDEX=$1; DIR=$(search $INDEX 2>/dev/null)
360            ;;
361        *)      # Directory.
362            DIR="$1"; INDEX=$(search $DIR 2>/dev/null)
363            ;;
364    esac
365    DEFINDEX=$(getdefault)
366    [[ $INDEX = $DEFINDEX ]] && raiseError access "Cannot uninstall default ogLive."
367    # Remove files and delete index entry.
368    rm -vfr ${ISO:+$DOWNLOADDIR/$ISO} ${DIR:+$TFTPDIR/$DIR}    ### Remove $TFTPDIR/$DIR.old ?
369    if [ -n "$INDEX" ]; then
370        jq "del(.oglive[$INDEX])" $INFOFILE | sponge $INFOFILE
371        # Decrement default index if needed (removed < default).
372        [[ $INDEX < $DEFINDEX ]] && jq ".default=$[DEFINDEX-1]" $INFOFILE | sponge $INFOFILE
373    fi
374}
375
376# Get default ogLive index.
377function getdefault() {
378    [ $# -ne 0 ] && raiseError usage
379    [ ! -r $INFOFILE ] && raiseError access "Configuration file."
380    # Read default parameter.
381    jq -r .default $INFOFILE || raiseError notfound "Undefined default index."
382}
383
384# Set default ogLive index.
385function setdefault() {
386    local INDEX OGLIVEDIR
387    [ $# -ne 1 ] && raiseError usage
388    [ ! -w $INFOFILE ] && raiseError access "Configuration file."
389    INDEX=$1
390    # Check if index entry exists.
391    jq ".oglive[$INDEX]" $INFOFILE || raiseError notfound "Index \"$INDEX\"."
392    # Get ogLive directory.
393    OGLIVEDIR=$(jq -r ".oglive[$INDEX].directory" $INFOFILE) || raiseError notfound "Directory for index \"$INDEX\"."
394    # Update default parameter.
395    jq ".default=$INDEX" $INFOFILE | sponge $INFOFILE
396exit
397    # Link to default directory.
398    rm -f $TFTPDIR/$DEFOGLIVE
399    ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE
400}
401
402# Assign an ISO file to a JSON entry.
403function assign() {
404local ISOFILE DIR
405    [ $# -ne 2 ] && raiseError usage
406    [ ! -w $INFOFILE ] && raiseError access "Configuration file."
407    # Check if exist ISO file and index directory.
408    ISOFILE=$DOWNLOADFILE/$1
409    [ ! -f $DOWNLOADDIR/$ISOFILE ] && raiseError notfound "ISO file \"$1\"."
410    DIR=$(search $2 2>/dev/null)
411    [ ! -d $TFTPDIR/$DIR ] && raiseError notfound "Directory for index \"$2\"."
412    # Assign ISO file to JSON entry.
413    jq ".oglive[$2].iso=\"$1\"" $INFOFILE | sponge $INFOFILE && jq ".oglive[$2]" $INFOFILE
414}
415
416
417# Main progrram.
418
419# Global constants definition.
420PROG=$(basename $(realpath "$0"))
421OPENGNSYS=/opt/opengnsys
422DOWNLOADDIR=$OPENGNSYS/lib
423DOWNLOADURL="http://opengnsys.es/downloads"
424TFTPDIR=$OPENGNSYS/tftpboot
425DEFOGLIVE=ogLive
426INFOFILE=$OPENGNSYS/etc/ogliveinfo.json
427
428# Access control.
429[ "$USER" = "root" ] || raiseError access "Need to be root."
430# Check dependencies.
431JQ=$(which jq 2>/dev/null) || raiseError notfound "Need to install \"jq\"."
432which sponge &>/dev/null || raiseError notfound "Need to install \"moreutils\"."
433# Commands control.
434case "$1" in
435    help|convert|config|check|list|show|search|download|install|uninstall|get-default|set-default|assign)
436        COMMAND="${1/-/}"; shift; $COMMAND "$@" ;;
437    *)  raiseError usage ;;
438esac
439
440exit $?
441
Note: See TracBrowser for help on using the repository browser.