summaryrefslogtreecommitdiffstats
path: root/repoman/bin/importimage
blob: 9ced5b78e1210f8779dbfb23ed5eafc8929bf770 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/bin/bash
#/**
#@file    importimage
#@usage   importimage [User] Repo ImageName
#@brief   Imports an image file from other repository
#@param   User       username to access the remote repository (local user, by default)
#@param   Repo       repository IP address or hostaname
#@param   ImageName  image name to download
#@warning Program will request the repository REST token.
#@version 1.1.1 - Initial version
#@author  Ramón M. Gómez, ETSII Universidad de Sevilla
#@date    2018-10-08
#@version 1.1.1b - Fix some bugs.
#@author  Ramón M. Gómez, ETSII Universidad de Sevilla
#@date    2020-02-17
#*/


# Variables.
OPENGNSYS=${OPENGNSYS:-"/opt/opengnsys"}
REPODIR="$OPENGNSYS/images"
REPOCONF="$OPENGNSYS/etc/ogAdmRepo.cfg"
SERVERCONF="$OPENGNSYS/etc/ogserver.json"
DEFAULTFILE="/etc/default/opengnsys"
let BACKUP=0
source $DEFAULTFILE
source $REPOCONF &>/dev/null

# Functions.
source $OPENGNSYS/lib/ogfunctions.sh || exit 1

[ "$RUN_OGADMSERVER" == "yes" ] && source_json_config $SERVERCONF &>/dev/null

# Main program.

# Error control.
[ "$USER" == "root" ] || raiseError access "Need to be root."
[ "$RUN_OGADMREPO" == "yes" ] || raiseError access "This server is not defined as image repository."
[ -w "$REPODIR" ] || raiseError access "Cannot write in local repository."
[ -n "$IPlocal" ] || raiseError access "Cannot read repository configuration file."
case $# in
    2)  USERNAME="$SUDO_USER"; REPO="$1"; IMAGE="$2" ;;
    3)  USERNAME="$1"; REPO="$2"; IMAGE="$3" ;;
    *)  [[ $* =~ ^(help|version)$ ]] && $* || raiseError usage
esac
[ "${REPO,,}" == "${HOSTNAME,,}" ] || [ "${REPO,,}" == "localhost" ] || [[ ${REPO} =~ ^127\. ]] || [ "${REPO,,}" == "${IPlocal,,}" ] && raiseError access "Cannot import from local repository."

# Fetching image info from the repository.
read -rp "Enter repository API token: " APITOKEN
IMAGEINFO="$(curl -k -H "Authorization: $APITOKEN" "https://$REPO/opengnsys/rest/repository/image/$IMAGE" 2> /dev/null | jq -r .)"
IMAGENAME="$(jq -r '.name' <<< "$IMAGEINFO" 2>/dev/null)"
case "$IMAGEINFO" in
    "") # Connection error.
        raiseError access "Cannot connect to $REPO" ;;
    "[]") # Image not found.
        raiseError notfound "Image $IMAGE in remote repository $REPO" ;;
    *)  # Checking REST error.
        MESSAGE="$(jq -r '.message' <<< "$IMAGEINFO" 2>/dev/null)"
        [ -n "$MESSAGE" ] && raiseError access "$MESSAGE"
esac
IMAGETYPE="$(jq -r '.type' <<< "$IMAGEINFO" 2>/dev/null)"
IMAGELOCKED="$(jq -r '.locked' <<< "$IMAGEINFO" 2>/dev/null)"
[ "$IMAGELOCKED" == "true" ] && raiseError access "Image locked by remote repository."
IMAGESIZE="$(jq -r '.size' <<< "$IMAGEINFO" 2>/dev/null)"
[ -z "$IMAGESIZE" ] && raiseError access "Cannot retrieve image size"
# Checking if local image exists.
IMAGEPATH="$REPODIR/$IMAGENAME.$IMAGETYPE"
LOCKFILE="$IMAGEPATH.lock"
if [ -e "$IMAGEPATH" ]; then
    # Checking if local image is locked.
    [ -f "$LOCKFILE" ] && raiseError access "Local image is locked, cannot write."
    # Confirm image download.
    read -rp "Image $IMAGENAME exists in the local repository. Do you want to continue? (y/N): " ANSWER
    [ "${ANSWER,,}" = "y" ]  || exit
    BACKUP=1
    REMOTEDATE=$(jq -r '.modified' <<< "$IMAGEINFO" 2>/dev/null)
    LOCALDATE=$(stat -c "%y" "$IMAGEPATH" | cut -f1 -d.)
    if [[ "$REMOTEDATE" < "$LOCALDATE" ]]; then
        read -rp "Remote image seems older than the local one. Do you want to continue? (y/N): " ANSWER
        [ "${ANSWER,,}" = "y" ]  || exit
    fi
fi

# Trapping signal to unlock image before exit.
trap "rm -f $LOCKFILE" 1 2 3 6 9 15
# Creating lock file.
touch $LOCKFILE
# Backing up local image.
if [ $BACKUP -eq 1 ]; then
    mv -vf "$IMAGEPATH" "$IMAGEPATH.ant" 2>/dev/null
    mv -vf "$IMAGEPATH.torrent" "$IMAGEPATH.torrent.ant" 2>/dev/null
    mv -vf "$IMAGEPATH.sum" "$IMAGEPATH.sum.ant" 2>/dev/null
    mv -vf "$IMAGEPATH.full.sum" "$IMAGEPATH.full.sum.ant" 2>/dev/null
fi
# Downloading image file.
[[ $IMAGEPATH =~ / ]] && mkdir -p "$(dirname "$IMAGEPATH")"
if scp "$USERNAME@$REPO:$IMAGEPATH" $REPODIR; then
    # Cheking image size.
    DOWNLOADSIZE=$(stat -c "%s" "$IMAGEPATH")
    [ $IMAGESIZE -ne $DOWNLOADSIZE ] && echo "Warning: image sizes differ: source=$IMAGESIZE, target=$DOWNLOADSIZE."
    # Storing creation info.
    jq -r '.clonator+":"+.compressor+":"+.filesystem+":"+(.datasize|tostring)+":"' <<<"$IMAGEINFO" > "$IMAGEPATH.info"
    # Updating the database when the repo is also configured as Administration Server.
    if [ "$RUN_OGADMSERVER" == "yes" ]; then
        if [ $BACKUP -eq 1 ]; then
            # If the image exists, increase its revision number.
            dbexec "UPDATE imagenes SET revision = revision + 1 WHERE nombreca = '$IMAGE';"
	else
            # Obtaining defined Organizational Units.
            while read -re DATA; do 
                OUS[${#OUS[@]}]="$DATA" 
            done <<<$(dbexec "SELECT idcentro, nombrecentro FROM centros;")
	    if [ ${#OUS[@]} -eq 1 ]; then
                # Only 1 OU is defined.
                let OUID="${OUS%%	*}"
	    else
                # Choose image OU.
                echo "Choose Organization Unit:"
                PS3="Enter number: "
                select opt in "${OUS[@]#* }"; do
                    [ -n "$opt" ] && let OUID="${OUS[REPLY-1]%% *}" && break
                done
	    fi
            # Creating a new image associated with an empty software profile.
            dbexec "
SET @repoid = (SELECT idrepositorio FROM repositorios
                WHERE ip='$IPlocal' LIMIT 1),
    @profname = '$IMAGE imported from $REPO';
INSERT INTO perfilessoft (descripcion, idcentro, grupoid)
       SELECT @profname, '$OUID', 0
         FROM DUAL
        WHERE NOT EXISTS
              (SELECT descripcion
	         FROM perfilessoft
                WHERE descripcion = @profname AND idcentro = '$OUID')
        LIMIT 1;
SET @profid = LAST_INSERT_ID();
INSERT INTO imagenes
            (nombreca, revision, descripcion, idperfilsoft, idcentro,
             comentarios, grupoid, idrepositorio, tipo, fechacreacion)
       VALUES ('$IMAGE', 1, '$IMAGE imported', @profid, '$OUID',
               'Image imported from repo $REPO', 0, @repoid, 1, NOW());"
        fi
    fi
else
    # On download error, trying to recover backup.
    raiseError download "$USERNAME@$REPO:$IMAGEPATH"
    if [ $BACKUP -eq 1 ]; then
        mv -vf "$IMAGEPATH.ant" "$IMAGEPATH" 2>/dev/null
        mv -vf "$IMAGEPATH.torrent.ant" "$IMAGEPATH.torrent" 2>/dev/null
        mv -vf "$IMAGEPATH.sum.ant" "$IMAGEPATH.sum" 2>/dev/null
        mv -vf "$IMAGEPATH.full.sum.ant" "$IMAGEPATH.full.sum" 2>/dev/null
    fi
fi

# Unlocking image and removing temporary file.
rm -f $LOCKFILE