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