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.cfg"
DEFAULTFILE="/etc/default/opengnsys"
let BACKUP=0
source $DEFAULTFILE
source $REPOCONF &>/dev/null
[ "$RUN_OGADMSERVER" == "yes" ] && source $SERVERCONF &>/dev/null
# Functions.
source $OPENGNSYS/lib/ogfunctions.sh || exit 1
# 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
|