]> git.ipfire.org Git - people/jschlag/ipfire-3.x-image.git/blame - functions.sh
Improve how we execute commands in chroot
[people/jschlag/ipfire-3.x-image.git] / functions.sh
CommitLineData
358ea1df
JS
1#!/bin/bash
2
3# Constants
4
5# Proper error codes
6EXIT_OK=0
7EXIT_ERROR=1
8EXIT_CONF_ERROR=2
9EXIT_NOT_SUPPORTED=3
10EXIT_NOT_HANDLED=4
11EXIT_COMMAND_NOT_FOUND=127
12EXIT_ERROR_ASSERT=128
13
14EXIT_TRUE=0
15EXIT_FALSE=1
16EXIT_UNKNOWN=2
17
18TRUE=0
19FALSE=1
20
b7ec229b
JS
21IMAGE_RELEASE=${FALSE}
22
6dd651ff 23CHROOT_SCRIPT="/build/chroot.sh"
7dc7fa1d
JS
24
25
358ea1df
JS
26# Functions
27
28log() {
29 local level=${1}
30 local message=${2}
31 echo "[${level}] ${message}"
32}
33
34cmd() {
8b38bb23 35 local cmd="$@"
358ea1df
JS
36 local ret
37
38 log DEBUG "Running command: ${cmd}"
39
40 ${cmd}
41 ret=$?
42
43 case "${ret}" in
44 ${EXIT_OK})
45 return ${EXIT_OK}
46 ;;
47 *)
48 log DEBUG "Returned with code '${ret}'"
49 return ${ret}
50 ;;
51 esac
52}
53
54
d26067f0
JS
55is_mounted() {
56 local mounted_dir=${1}
7dc7fa1d 57
d26067f0
JS
58 if [ ! -d ${mounted_dir} ]; then
59 log ERROR "Is not a directory ${mounted_dir}"
60 return ${FALSE}
61 else
62 mountpoint ${mounted_dir}
63 fi
64}
65
66unmount_dirs() {
7dc7fa1d 67 local mounted_dir
d26067f0
JS
68 local path
69
70 local return_value=${EXIT_OK}
7dc7fa1d 71
d26067f0
JS
72 for mounted_dir in "/proc" "/sys" "/dev/pts" "/dev/shm" "/dev" "/run" "/tmp" ""
73 do
74 path="${IMAGE_MOUNT_DIR}${mounted_dir}"
75
76 if is_mounted "${path}"; then
77 log DEBUG "Unmounting ${path}"
78 umount "${path}"
79 # Check once again
80 if is_mounted "${path}"; then
81 return_value=${EXIT_ERROR}
82 fi
7dc7fa1d 83 else
d26067f0 84 log DEBUG "${path} is not mounted"
7dc7fa1d
JS
85 fi
86 done
87
d26067f0
JS
88}
89
90
91
92
93cleanup_stage_1() {
358ea1df 94
d26067f0 95 if unmount_dirs; then
358ea1df 96
d26067f0
JS
97 # Remove partition from the kernel table.
98 partx -d ${outlo}p1
358ea1df 99
d26067f0
JS
100 # Remove loopback device
101 log DEBUG " Remove loopback device"
102 losetup -d ${outlo}
103 fi
358ea1df
JS
104
105
106 # Cleanup Config file for the local repo
107 if [ -f "${LOCAL_REPO_FILE}" ]; then
108 rm -f "${LOCAL_REPO_FILE}"
109 fi
110
111}
112
7dc7fa1d 113
358ea1df 114cleanup_stage_2() {
d26067f0
JS
115 if unmount_dirs; then
116 # Drop working dir
117 if [ -d "${WORKING_DIR}" ]; then
118 #rm -dfR "${WORKING_DIR}"
119 echo ""
7dc7fa1d 120 fi
358ea1df
JS
121 fi
122}
123
124cleanup() {
125 cleanup_stage_1
126 cleanup_stage_2
127}
128
129generate_image_filename() {
130 local distro=${1}
131 local version=${2}
132 local arch=${3}
133
134 echo "${distro}-${version}-${arch}"
135}
136
137check_for_pakfire() {
138 local return_value=0
139
140 # TODO
141 # Check that pakfire-server binary is available
142 # Check that pakfire binary is available
143
144 # Check that repo files are installed. (pakfire need to know which repos exist)
145 local repo_dir="/etc/pakfire/repos"
146
147 if [ ! -d "${repo_dir}" ]; then
148 log ERROR "Could not find respository directory ${repo_dir}"
149 return_value=1
150 fi
151
152 return ${return_value}
153}
154
155compress_image() {
156 local compression=${1}
157 local image_file=${2}
158 local level=${3}
159
160 log debug "Compressing ${image_file} with ${compression}"
161
162 case "${compression}" in
163 "xz")
164 # Check that the file does not exist yet
165 if [ -f "${image_file}.xz" ]; then
166 log ERROR "Failed to compress the image. The file already exists"
167 return ${EXIT_ERROR}
168 fi
169 cmd xz "-${level}" "${image_file}"
170 ;;
171 "zip")
172 # Check that the file does not exist yet
173 if [ -f "${image_file}.zip" ]; then
174 log ERROR "Failed to compress the image. The file already exists"
175 return ${EXIT_ERROR}
176
177 fi
178 cmd zip "-${level}" "${image_file}.zip" "${image_file}"
179 # Remove the file which we compressed+
180 rm -f "${image_file}"
181 ;;
182
183 esac
184}
185
186reset_root_password() {
187 local root_dir=${1}
188 # Backup passwd file
189 cp -avf ${root_dir}/etc/passwd ${root_dir}/etc/passwd.orig
190
191 # Drop root password.
192 sed -e "s/^\(root:\)[^:]*:/\1:/" ${root_dir}/etc/passwd.orig > ${root_dir}/etc/passwd
193
194 # Remove passwd backup file.
195 rm -rvf ${root_dir}/etc/passwd.orig
196}
197
198clone_git_repos() {
199 # Dir where the repos should be located
200 local dir=${1}
201 shift
202 local repos="$@"
203
204 local repo
205
206 mkdir -pv ${dir}
207
208 (
209 cd ${dir}
210 # Clone git repositories.
211 for repo in ${repos}; do
212 git clone ${repo}
213 done
214 )
215}
216
217# This function is used to publish the produced images
218
219publish() {
220 local path=${1}
221 # The image we created usually a img. file
222 local image_base_file=${2}
223
224 local image_name_final="$(generate_image_filename "${DISTRO}" "${VERSION}" "${ARCH}")"
225 local image_type
226
227 # Do these steps for every image format we like to publish
228 for image_type in ${IMAGE_TYPES_PUBLISH}; do
229 # Convert images to the type specified in IMAGE_TYPES_PUBLISH
230 convert_image "${image_type}" "${image_base_file}" "${image_name_final}"
231
232 # compress image.
233 if [[ ${IMAGE_RELEASE} -eq ${TRUE} ]]; then
234 local compression_type
235 local compression_level
236
237
238 # Get compressioon type
239 compression_type="$(get_compression_type ${image_type})"
240
241 compression_level=1
242 compress_image "${compression_type}" "${image_name_final}.${image_type}" ${compression_level}
243
244 # Move images to this path
245 mv -f "${image_name_final}.${image_type}.${compression_type}" ${path}
246
247 # point the latest links to these images
248 ln -s -f "${path}/${image_name_final}.${image_type}.${compression_type}" \
249 "${path}/$(generate_image_filename "${DISTRO}" "latest" "${ARCH}").${image_type}.${compression_type}"
250 else
251
252 # Move images to this path
253 mv -f "${image_name_final}.${image_type}" ${path}
254 fi
255 done
256
257}
258
259convert_image() {
260 local type=${1}
261 local from=${2}
262 local to=${3}
263
264 if [[ ${type} = "img" ]]; then
265 # We do not need to convert the image here but we need to rename
266 mv -f ${from} ${to}.${type}
267 return $?
268 fi
269
270 if [[ ${type} = "qcow2" ]]; then
271 local command="qemu-img convert -c -O ${type} ${from} ${to}.${type}"
272 else
273 local command="qemu-img convert -O ${type} ${from} ${to}.${type}"
274 fi
275
276 cmd ${command}
277}
278
279get_compression_type() {
280 local image_type=${1}
281
282 case "${image_type}" in
283 "qcow2" | "img")
284 # These types can be used only under Unix so we use xz as compression
285 echo "xz"
286 ;;
287 "vmdk" | "vdi")
288 # These types can be also under Windows so we use zip as compression
289 echo "zip"
290 ;;
291 esac
292
293}
294
295check_for_free_space() {
296 local space=${1}
297 local path=${2}
298 local space_in_path=0
299
300 space_in_path=$(df -h -B MB --output=avail ${path} | tail -n 1)
301 space_in_path=${space_in_path%MB}
302 log debug ${space_in_path}
303 log debug ${space}
304
305 if [ ${space_in_path} -lt ${space} ]; then
306 log error "Not enough free space available under ${path}"
307 log error "Free space is ${space_in_path}MB but we need at least ${space}MB"
308 return ${EXIT_ERROR}
309 fi
310}
311
312parse_cmdline() {
313 while [ $# -gt 0 ]; do
314 case "${1}" in
315 "--release")
316 IMAGE_RELEASE=${TRUE}
317 ;;
318
319 *)
320 error "Invalid argument: ${1}"
321 return ${EXIT_CONF_ERROR}
322 ;;
323 esac
324 shift
325 done
326}
327
7eb693d2
JS
328chroot_wrapper() {
329 local chroot_dir="${1}"
330
331 shift
332
333 local command
334
335 if [ ! -d ${chroot_dir} ]; then
336 log ERROR "Cannot chroot in a non directory ${chroot_dir}"
337 fi
338
339 mount proc "${chroot_dir}/proc" -t proc -o nosuid,noexec,nodev
340 mount sys "${chroot_dir}/sys" -t sysfs -o nosuid,noexec,nodev,ro
341 mount udev "${chroot_dir}/dev" -t devtmpfs -o mode=0755,nosuid
342 mount devpts "${chroot_dir}/dev/pts" -t devpts -o mode=0620,gid=5,nosuid,noexec
343 mount shm "${chroot_dir}/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev
344 mount /run "${chroot_dir}/run" --bind
345 mount tmp "${chroot_dir}/tmp" -t tmpfs -o mode=1777,strictatime,nodev,nosuid
346
347 for command in "$@"
348 do
349 cmd chroot "${chroot_dir}" "${command}"
350 done
351
352 umount "${chroot_dir}/proc"
353 umount "${chroot_dir}/sys"
354 umount "${chroot_dir}/dev/pts"
355 umount "${chroot_dir}/dev/shm"
356 umount "${chroot_dir}/dev"
357 umount "${chroot_dir}/run"
358 umount "${chroot_dir}/tmp"
359}
6dd651ff
JS
360
361chroot_script_init(){
362 echo "#!/bin/bash" > "${IMAGE_MOUNT_DIR}${CHROOT_SCRIPT}"
363}
364
365chroot_script_add_cmd(){
366 local command
367 for command in "$@"
368 do
369 echo "${command}" >> "${IMAGE_MOUNT_DIR}${CHROOT_SCRIPT}"
370 done
371}
372
373
374chroot_script_exec() {
375 chmod +x "${IMAGE_MOUNT_DIR}${CHROOT_SCRIPT}"
376
377 chroot_wrapper ${IMAGE_MOUNT_DIR} "${CHROOT_SCRIPT}"
378}