stx-anaconda-image.bbclass: add error handling when copy pkgs
[pti/rtp.git] / meta-stx / classes / stx-anaconda-image.bbclass
1 #
2 ## Copyright (C) 2019 Wind River Systems, Inc.
3 #
4 #  Licensed under the Apache License, Version 2.0 (the "License");
5 #  you may not use this file except in compliance with the License.
6 #  You may obtain a copy of the License at
7 #
8 #      http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #  Unless required by applicable law or agreed to in writing, software
11 #  distributed under the License is distributed on an "AS IS" BASIS,
12 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 #  See the License for the specific language governing permissions and
14 #  limitations under the License.
15
16 RPM_POSTPROCESS_COMMANDS_append = "wrl_installer;"
17 do_rootfs[vardeps] += "INSTALLER_TARGET_BUILD INSTALLER_TARGET_IMAGE"
18
19 # Fix system-shutdown hang at ratelimiting
20 APPEND_append = " printk.devkmsg=on"
21
22 INSTPRODUCT ?= "${DISTRO_NAME}"
23 INSTVER     ?= "${DISTRO_VERSION}"
24 INSTBUGURL  ?= "http://www.windriver.com/"
25
26 # NOTE: Please update anaconda-init when you change INSTALLER_CONFDIR, use "="
27 #       but not "?=" since this is not configurable.
28 INSTALLER_CONFDIR = "${IMAGE_ROOTFS}/installer-config"
29 KICKSTART_FILE ??= ""
30 KICKSTART_FILE_EXTRA ??= ""
31 WRL_INSTALLER_CONF ?= ""
32 REPO_INCLUDE_PKG ??= ""
33 REPO_EXCLUDE_PKG ?= ""
34
35 build_iso_prepend() {
36         install -d ${ISODIR}
37         ln -snf /.discinfo ${ISODIR}/.discinfo
38         ln -snf /.buildstamp ${ISODIR}/.buildstamp
39         ln -snf /Packages ${ISODIR}/Packages
40 }
41
42 build_iso_append() {
43         implantisomd5 ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso
44 }
45
46 # Check WRL_INSTALLER_CONF and copy it to
47 # ${IMAGE_ROOTFS}/.buildstamp.$prj_name when exists
48 wrl_installer_copy_buildstamp() {
49     prj_name=$1
50     buildstamp=$2
51     if [ -f $buildstamp ]; then
52         bbnote "Using $buildstamp as the buildstamp"
53         cp $buildstamp ${IMAGE_ROOTFS}/.buildstamp.$prj_name
54     else
55         bbfatal "Can't find WRL_INSTALLER_CONF: $buildstamp"
56     fi
57 }
58
59 # Hardlink when possible, otherwise copy.
60 # $1: src
61 # $2: target
62 wrl_installer_hardlinktree() {
63     src_dev="`stat -c %d $1`"
64     if [ -e "$2" ]; then
65         tgt_dev="`stat -c %d $2`"
66     else
67         tgt_dev="`stat -c %d $(dirname $2)`"
68     fi
69     hdlink=""
70     if [ "$src_dev" = "$tgt_dev" ]; then
71         hdlink="--link"
72     fi
73     cp -rvf $hdlink $1 $2
74 }
75
76 wrl_installer_copy_local_repos() {
77     deploy_dir_rpm=$1
78
79     if [ -d "$deploy_dir_rpm" ]; then
80         echo "Copy rpms from target build to installer image."
81         mkdir -p ${IMAGE_ROOTFS}/Packages.$prj_name
82
83         : > ${IMAGE_ROOTFS}/Packages.$prj_name/.treeinfo
84         echo "[general]" >> ${IMAGE_ROOTFS}/Packages.$prj_name/.treeinfo
85         echo "version = ${DISTRO_VERSION}" >> ${IMAGE_ROOTFS}/Packages.$prj_name/.treeinfo
86
87         # Determine the max channel priority
88         channel_priority=5
89         for pt in $installer_target_archs ; do
90             channel_priority=$(expr $channel_priority + 5)
91         done
92
93         : > ${IMAGE_ROOTFS}/Packages.$prj_name/.feedpriority
94         for arch in $installer_target_archs; do
95             if [ -d "$deploy_dir_rpm/"$arch -a ! -d "${IMAGE_ROOTFS}/Packages.$prj_name/"$arch ]; then
96                 channel_priority=$(expr $channel_priority - 5)
97                 echo "$channel_priority $arch" >> ${IMAGE_ROOTFS}/Packages.$prj_name/.feedpriority
98             fi
99         done
100
101         cd ${deploy_dir_rpm}
102         for pkg in `cat ${REPO_INCLUDE_PKG}`; do
103             pkg_file=$(find . -type f -name ${pkg}.rpm)
104             if [ -z "${pkg_file}" ]; then
105                 bbwarn "Package ${pkg}.rpm not found, please check if there is anything wrong or just remove it from the list."
106             else
107                 cp --parents -vf ${pkg_file} ${IMAGE_ROOTFS}/Packages.$prj_name/
108             fi
109         done
110         cd -
111
112         for pkg in ${REPO_EXCLUDE_PKG}; do
113             rm -rf ${IMAGE_ROOTFS}/Packages.$prj_name/${pkg}
114         done
115
116         createrepo_c --update -q ${IMAGE_ROOTFS}/Packages.$prj_name/
117     fi
118 }
119
120 # Update .buildstamp and copy rpm packages to IMAGE_ROOTFS
121 wrl_installer_copy_pkgs() {
122
123     target_build="$1"
124     target_image="$2"
125     prj_name="$3"
126     if [ -n "$4" ]; then
127         installer_conf="$4"
128     else
129         installer_conf=""
130     fi
131
132     common_grep="-e '^ALL_MULTILIB_PACKAGE_ARCHS=.*' \
133             -e '^MULTILIB_VARIANTS=.*' -e '^PACKAGE_ARCHS=.*'\
134             -e '^PACKAGE_ARCH=.*' -e '^PACKAGE_INSTALL_ATTEMPTONLY=.*' \
135             -e '^DISTRO=.*' -e '^DISTRO_NAME=.*' -e '^DISTRO_VERSION=.*' \
136             "
137
138     if [ -f "$installer_conf" ]; then
139         eval "grep -e \"^PACKAGE_INSTALL=.*\" $common_grep $installer_conf \
140             | sed -e 's/=/=\"/' -e 's/$/\"/' > ${BB_LOGFILE}.distro_vals"
141
142         eval "cat $target_build/installersupport_$target_image | \
143             grep -e '^WORKDIR=.*' >> ${BB_LOGFILE}.distro_vals"
144
145         eval `cat ${BB_LOGFILE}.distro_vals`
146         if [ $? -ne 0 ]; then
147             bbfatal "Something is wrong in $installer_conf, please correct it"
148         fi
149         if [ -z "$PACKAGE_ARCHS" -o -z "$PACKAGE_INSTALL" ]; then
150             bbfatal "PACKAGE_ARCHS or PACKAGE_INSTALL is null, please check $installer_conf"
151         fi
152     else
153         eval "cat $target_build/installersupport_$target_image | \
154             grep $common_grep -e '^PN=.*' -e '^SUMMARY=.*' -e '^WORKDIR=.*'\
155             -e '^DESCRIPTION=.*' -e '^export PACKAGE_INSTALL=.*' > ${BB_LOGFILE}.distro_vals"
156
157         eval `cat ${BB_LOGFILE}.distro_vals`
158     fi
159
160     export installer_default_arch="$PACKAGE_ARCH"
161     # Reverse it for priority
162     export installer_default_archs="`for arch in $PACKAGE_ARCHS; do echo $arch; done | tac | tr - _`"
163     installer_target_archs="$installer_default_archs"
164     if [ -n "$MULTILIB_VARIANTS" ]; then
165         export MULTILIB_VARIANTS
166         mlarchs_reversed="`for mlarch in $ALL_MULTILIB_PACKAGE_ARCHS; do echo $mlarch; \
167             done | tac | tr - _`"
168         for arch in $mlarchs_reversed; do
169             if [ "$arch" != "noarch" -a "$arch" != "all" -a "$arch" != "any" ]; then
170                 installer_target_archs="$installer_target_archs $arch"
171             fi
172         done
173     fi
174     export installer_target_archs
175
176     # Save the vars to .buildstamp when no installer_conf
177     if [ ! -f "$installer_conf" ]; then
178         cat >> ${IMAGE_ROOTFS}/.buildstamp.$prj_name <<_EOF
179 DISTRO=$DISTRO
180 DISTRO_NAME=$DISTRO_NAME
181 DISTRO_VERSION=$DISTRO_VERSION
182
183 [Rootfs]
184 LIST=$PN
185
186 [$PN]
187 SUMMARY=$SUMMARY
188 DESCRIPTION=$DESCRIPTION
189
190 PACKAGE_INSTALL=$PACKAGE_INSTALL
191 PACKAGE_INSTALL_ATTEMPTONLY=$PACKAGE_INSTALL_ATTEMPTONLY
192 ALL_MULTILIB_PACKAGE_ARCHS=$ALL_MULTILIB_PACKAGE_ARCHS
193 MULTILIB_VARIANTS=$MULTILIB_VARIANTS
194 PACKAGE_ARCHS=$PACKAGE_ARCHS
195 PACKAGE_ARCH=$PACKAGE_ARCH
196 IMAGE_LINGUAS=${IMAGE_LINGUAS}
197 _EOF
198     fi
199
200     if [ -d "$WORKDIR/oe-rootfs-repo/rpm" ]; then
201         # Copy local repos while the image is not initramfs
202         bpn=${BPN}
203         if [ "${bpn##*initramfs}" = "${bpn%%initramfs*}" ]; then
204             wrl_installer_copy_local_repos $WORKDIR/oe-rootfs-repo/rpm
205         fi
206         echo "$DISTRO::$prj_name::$DISTRO_NAME::$DISTRO_VERSION" >> ${IMAGE_ROOTFS}/.target_build_list
207     fi
208 }
209
210 wrl_installer_get_count() {
211     sum=0
212     for i in $*; do
213         sum=$(expr $sum + 1)
214     done
215     echo $sum
216 }
217
218 wrl_installer[vardepsexclude] = "DATETIME"
219 wrl_installer() {
220     cat >${IMAGE_ROOTFS}/.discinfo <<_EOF
221 ${DATETIME}
222 ${DISTRO_NAME} ${DISTRO_VERSION}
223 ${TARGET_ARCH}
224 _EOF
225
226     : > ${IMAGE_ROOTFS}/.target_build_list
227     counter=0
228     targetimage_counter=0
229     for target_build in ${INSTALLER_TARGET_BUILD}; do
230         target_build="`readlink -f $target_build`"
231         echo "Installer Target Build: $target_build"
232         counter=$(expr $counter + 1)
233         prj_name="`echo $target_build | sed -e 's#/ *$##g' -e 's#.*/##'`"
234         prj_name="$prj_name-$counter"
235
236             # Generate .buildstamp
237             if [ -n "${WRL_INSTALLER_CONF}" ]; then
238                 installer_conf="`echo ${WRL_INSTALLER_CONF} | awk '{print $'"$counter"'}'`"
239                 wrl_installer_copy_buildstamp $prj_name $installer_conf
240             else
241                 cat >${IMAGE_ROOTFS}/.buildstamp.$prj_name <<_EOF
242 [Main]
243 Product=${INSTPRODUCT}
244 Version=${INSTVER}
245 BugURL=${INSTBUGURL}
246 IsFinal=True
247 UUID=${DATETIME}.${TARGET_ARCH}
248 _EOF
249             fi
250
251             if [ -f "$target_build" ]; then
252                 filename=$(basename "$target_build")
253                 extension="${filename##*.}"
254                 bpn=${BPN}
255                 # Do not copy image for initramfs
256                 if [ "${bpn##*initramfs}" != "${bpn%%initramfs*}" ]; then
257                     continue
258                 elif [ "x$extension" = "xext2" -o "x$extension" = "xext3" -o "x$extension" = "xext4" ]; then
259                     echo "Image based target install selected."
260                     mkdir -p "${IMAGE_ROOTFS}/LiveOS.$prj_name"
261                     wrl_installer_hardlinktree "$target_build" "${IMAGE_ROOTFS}/LiveOS.$prj_name/rootfs.img"
262                     echo "::$prj_name::" >> ${IMAGE_ROOTFS}/.target_build_list
263                 else
264                     bberror "Unsupported image: $target_build."
265                     bberror "The image must be ext2, ext3 or ext4"
266                     exit 1
267                 fi
268             elif [ -d "$target_build" ]; then
269                 targetimage_counter=$(expr $targetimage_counter + 1)
270                 target_image="`echo ${INSTALLER_TARGET_IMAGE} | awk '{print $'"$targetimage_counter"'}'`"
271                 echo "Target Image: $target_image"
272                 wrl_installer_copy_pkgs $target_build $target_image $prj_name $installer_conf
273             else
274                 bberror "Invalid configuration of INSTALLER_TARGET_BUILD: $target_build."
275                 bberror "It must either point to an image (ext2, ext3 or ext4) or to the root of another build directory"
276                 exit 1
277             fi
278
279             ks_cfg="${INSTALLER_CONFDIR}/ks.cfg.$prj_name"
280             if [ -n "${KICKSTART_FILE}" ]; then
281                 ks_file="`echo ${KICKSTART_FILE} | awk '{print $'"$counter"'}'`"
282                 bbnote "Copying kickstart file $ks_file to $ks_cfg ..."
283                 mkdir -p ${INSTALLER_CONFDIR}
284                 cp $ks_file $ks_cfg
285             fi
286             if [ -n "${KICKSTART_FILE_EXTRA}" ]; then
287                 for ks_file in ${KICKSTART_FILE_EXTRA}; do
288                     if [ -f $ks_file ]; then
289                         cp $ks_file ${INSTALLER_CONFDIR}
290                     else
291                         bbwarn "The kickstart file $ks_file in KICKSTART_FILE_EXTRA doesn't exist!"
292                     fi
293                 done
294             fi
295     done
296
297     # Setup the symlink if only one target build dir.
298     if [ "$counter" = "1" ]; then
299         prj_name="`awk -F:: '{print $2}' ${IMAGE_ROOTFS}/.target_build_list`"
300         entries=".buildstamp LiveOS Packages installer-config/ks.cfg"
301         for i in $entries; do
302             if [ -e ${IMAGE_ROOTFS}/$i.$prj_name ]; then
303                 ln -sf `basename $i.$prj_name` ${IMAGE_ROOTFS}/$i
304             fi
305         done
306     fi
307 }
308
309 python __anonymous() {
310     if "selinux" in d.getVar("DISTRO_FEATURES", True).split():
311         raise bb.parse.SkipPackage("Unable to build the installer when selinux is enabled.")
312
313     if bb.data.inherits_class('image', d):
314         if d.getVar("DISTRO", True) != "anaconda":
315             raise bb.parse.SkipPackage("Set DISTRO = 'anaconda' in local.conf")
316
317         target_builds = d.getVar('INSTALLER_TARGET_BUILD', True)
318         if not target_builds:
319             errmsg = "No INSTALLER_TARGET_BUILD is found,\n"
320             errmsg += "set INSTALLER_TARGET_BUILD = '<target-build-topdir>' and\n"
321             errmsg += "INSTALLER_TARGET_IMAGE = '<target-image-pn>' to do RPMs\n"
322             errmsg += "install, or\n"
323             errmsg += "set INSTALLER_TARGET_BUILD = '<target-build-image>' to do\n"
324             errmsg += "image copy install"
325             raise bb.parse.SkipPackage(errmsg)
326
327         count = 0
328         for target_build in target_builds.split():
329             if not os.path.exists(target_build):
330                 raise bb.parse.SkipPackage("The %s of INSTALLER_TARGET_BUILD does not exist" % target_build)
331
332             if os.path.isdir(target_build):
333                 count += 1
334
335         # While do package management install
336         if count > 0:
337             target_images = d.getVar('INSTALLER_TARGET_IMAGE', True)
338             if not target_images:
339                 errmsg = "The INSTALLER_TARGET_BUILD is a dir, but not found INSTALLER_TARGET_IMAGE,\n"
340                 errmsg += "set INSTALLER_TARGET_IMAGE = '<target-image-pn>' to do RPMs install"
341                 raise bb.parse.SkipPackage(errmsg)
342
343             elif count != len(target_images.split()):
344                 errmsg = "The INSTALLER_TARGET_BUILD has %s build dirs: %s\n" % (count, target_builds)
345                 errmsg += "But INSTALLER_TARGET_IMAGE has %s build images: %s\n" % (len(target_images.split()), target_images)
346                 raise bb.parse.SkipPackage(errmsg)
347
348         # The count of INSTALLER_TARGET_BUILD and WRL_INSTALLER_CONF must match when set.
349         wrlinstaller_confs = d.getVar('WRL_INSTALLER_CONF', True)
350         if wrlinstaller_confs:
351             if len(wrlinstaller_confs.split()) != len(target_builds.split()):
352                 raise bb.parse.SkipPackage("The count of INSTALLER_TARGET_BUILD and WRL_INSTALLER_CONF not match!")
353             for wrlinstaller_conf in wrlinstaller_confs.split():
354                 if not os.path.exists(wrlinstaller_conf):
355                     raise bb.parse.SkipPackage("The installer conf %s in WRL_INSTALLER_CONF doesn't exist!" % wrlinstaller_conf)
356
357         # The count of INSTALLER_TARGET_BUILD and KICKSTART_FILE must match when set.
358         kickstart_files = d.getVar('KICKSTART_FILE', True)
359         if kickstart_files:
360             if len(kickstart_files.split()) != len(target_builds.split()):
361                 raise bb.parse.SkipPackage("The count of INSTALLER_TARGET_BUILD and KICKSTART_FILE not match!")
362             for kickstart_file in kickstart_files.split():
363                 if not os.path.exists(kickstart_file):
364                     raise bb.parse.SkipPackage("The kickstart file %s in KICKSTART_FILE doesn't exist!" % kickstart_file)
365
366 }
367
368 python build_syslinux_cfg () {
369     import copy
370     import sys
371
372     workdir = d.getVar('WORKDIR')
373     if not workdir:
374         bb.error("WORKDIR not defined, unable to package")
375         return
376
377     cfile = d.getVar('SYSLINUX_CFG')
378     if not cfile:
379         bb.fatal('Unable to read SYSLINUX_CFG')
380 }