97c01e48ed
Currently we have all our elements and library files in a top-level directory and install them into <root>/share/diskimage-builder/[elements|lib] (where root is either / or the root of a virtualenv). The problem with this is that editable/development installs (pip -e) do *not* install data_files. Thus we have no canonical location to look for elements -- leading to the various odd things we do such as a whole bunch of guessing at the top of disk-image-create and having a special test-loader in tests/test_elements.py so we can run python unit tests on those elements that have it. data_files is really the wrong thing to use for what are essentially assets of the program. data_files install works well for things like config-files, init.d files or dropping documentation files. By moving the elements under the diskimage_builder package, we always know where they are relative to where we import from. In fact, pkg_resources has an api for this which we wrap in the new diskimage_builder/paths.py helper [1]. We use this helper to find the correct path in the couple of places we need to find the base-elements dir, and for the paths to import the library shell functions. Elements such as svc-map and pkg-map include python unit-tests, which we do not need tests/test_elements.py to special-case load any more. They just get found automatically by the normal subunit loader. I have a follow-on change (I69ca3d26fede0506a6353c077c69f735c8d84d28) to move disk-image-create to a regular python entry-point. Unfortunately, this has to move to work with setuptools. You'd think a symlink under diskimage_builder/[elements|lib] would work, but it doesn't. [1] this API handles stuff like getting files out of .zip archive modules, which we don't do. Essentially for us it's returning __file__. Change-Id: I5e3e3c97f385b1a4ff2031a161a55b231895df5b
262 lines
7.7 KiB
Bash
262 lines
7.7 KiB
Bash
#!/bin/bash
|
|
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
|
# Copyright (c) 2012 NTT DOCOMO, INC.
|
|
#
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
function fullpath() {
|
|
local f=$1
|
|
if [ "${f#/}" = "$f" ]; then
|
|
echo `pwd`/"$f"
|
|
else
|
|
echo "$f"
|
|
fi
|
|
}
|
|
|
|
function create_ramdisk_base () {
|
|
echo "Creating base system"
|
|
|
|
mkdir -p "${TMP_MOUNT_PATH}/"{bin,lib/modules,etc/udev}
|
|
ln -s bin "$TMP_MOUNT_PATH/sbin"
|
|
# cjk adding for discovery support
|
|
mkdir -p "${TMP_MOUNT_PATH}/"{lib/udev/rules.d,var/{lib/dhcp,run}}
|
|
|
|
case "$DISTRO_NAME" in
|
|
fedora|rhel|rhel7|opensuse)
|
|
mkdir -p "$TMP_MOUNT_PATH/usr"
|
|
ln -s ../lib "$TMP_MOUNT_PATH/usr/lib"
|
|
if [[ "`uname -m`" =~ x86_64|ppc64 ]]; then
|
|
ln -s lib "$TMP_MOUNT_PATH/lib64"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if [ -e $LIB_UDEV/rules.d/50-firmware.rules ]; then
|
|
cp -a "$LIB_UDEV/rules.d/50-firmware.rules" "$TMP_MOUNT_PATH/lib/udev/rules.d"
|
|
fi
|
|
|
|
cp -a "$LIB_UDEV/rules.d/80-drivers.rules" "$TMP_MOUNT_PATH/lib/udev/rules.d"
|
|
|
|
if [ -a $LIB_UDEV/firmware ]; then
|
|
cp -a "$LIB_UDEV/firmware" "$TMP_MOUNT_PATH/lib/udev"
|
|
fi
|
|
|
|
# cjk adding dhclient for hwdiscovery support
|
|
# dhclient scripts on some distros appear in different places, copy any we find
|
|
for FILE in /sbin/dhclient-script /usr/sbin/dhclient-script /etc/sysconfig/network-scripts/* /etc/rc.d/init.d/functions /etc/init.d/functions ; do
|
|
if [ -f $FILE ] ; then
|
|
mkdir -p $(dirname $TMP_MOUNT_PATH/$FILE)
|
|
cp $FILE $TMP_MOUNT_PATH/$FILE
|
|
fi
|
|
done
|
|
# /var/lib/dhclient is a directory on Fedora
|
|
if [ -d "/var/lib/dhclient" ] ; then
|
|
mkdir -p "$TMP_MOUNT_PATH/var/lib/dhclient"
|
|
fi
|
|
|
|
mkdir -p "$TMP_MOUNT_PATH/etc/modprobe.d"
|
|
# The directory may or may not exist in the image. If the directory exists in
|
|
# the image, all the files under it should get copied to the ramdisk.
|
|
if [ -d "/etc/modprobe.d/" ] ; then
|
|
find /etc/modprobe.d -name '*.conf' -type f -exec cp -a {} "$TMP_MOUNT_PATH/etc/modprobe.d" \;
|
|
fi
|
|
echo "blacklist evbug" > "$TMP_MOUNT_PATH/etc/modprobe.d/blacklist-dib-ramdisk.conf"
|
|
|
|
# cjk adding for hwdiscovery support
|
|
touch "$TMP_MOUNT_PATH/etc/fstab"
|
|
|
|
mkdir -p "$TMP_MOUNT_PATH/etc/udev"
|
|
cat >"$TMP_MOUNT_PATH/etc/udev/udev.conf" <<EOF
|
|
|
|
udev_root="/dev"
|
|
udev_rules="/lib/udev/rules.d"
|
|
udev_log="no"
|
|
EOF
|
|
|
|
generate_hooks
|
|
TARGET_ROOT=$TMP_MOUNT_PATH run_d root
|
|
}
|
|
|
|
function copy_required_libs() {
|
|
set +e
|
|
ldd_out=`ldd "$1"`
|
|
local ret_code=$?
|
|
set -e
|
|
if [ $ret_code -ne 0 ]; then
|
|
return
|
|
fi
|
|
local IFS="
|
|
"
|
|
|
|
# Patterns of output of ldd
|
|
#
|
|
# 1. name to real path
|
|
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f095e784000)
|
|
# 2. only path
|
|
# /lib64/ld-linux-x86-64.so.2 (0x00007f095ef79000)
|
|
# 3. path to path
|
|
# /lib64/ld-linux-x86-64.so.2 => /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 (0x00007facff857000)
|
|
# 4. name to empty (vdso)
|
|
# linux-vdso.so.1 => (0x00007fff0c5ff000)
|
|
# or, in some setups:
|
|
# linux-vdso.so.1 (0x00007fff0c5ff000)
|
|
|
|
for i in `echo "$ldd_out" | sed -e 's/^\t*//'`; do
|
|
local ref=$( echo "$i" | awk -F '[ ]' '{print $1}')
|
|
local real=$( echo "$i" | awk -F '[ ]' '$2 == "=>" {print $3}
|
|
$2 != "=>" {print $1}')
|
|
if [ -z "$real" ] || [[ "$real" != /* ]]; then
|
|
continue
|
|
fi
|
|
if [ "$ref" = "${ref#/}" ]; then
|
|
ref=/lib/$ref
|
|
fi
|
|
dest=/lib/`basename "$real"`
|
|
cp -Ln "$real" "$TMP_MOUNT_PATH/$dest"
|
|
# Create a symbolic link if the shared library is referred
|
|
# by the different name
|
|
if [ "$ref" != "$dest" ]; then
|
|
local link_path=$TMP_MOUNT_PATH/$ref
|
|
if ! [ -e "$link_path" -o -L "$link_path" ]; then
|
|
mkdir -p $(dirname "$link_path")
|
|
ln -s "$dest" "$link_path"
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
function populate_lib () {
|
|
echo "Populating /lib"
|
|
|
|
# find udevd
|
|
UDEVD=
|
|
for f in /sbin/udevd /lib/udev/udevd /lib/systemd/systemd-udevd \
|
|
/usr/lib/systemd/systemd-udevd \
|
|
/usr/lib/udev/udevd; do
|
|
if [ -x "$f" ]; then
|
|
UDEVD="$f"
|
|
break
|
|
fi
|
|
done
|
|
|
|
UDEV_FIRMWARE=
|
|
if [ -a $LIB_UDEV/firmware ]; then
|
|
UDEV_FIRMWARE="$LIB_UDEV/firmware"
|
|
fi
|
|
|
|
for i in "$BUSYBOX" bash lsmod modprobe udevadm \
|
|
wget reboot shutdown $UDEVD $UDEV_FIRMWARE \
|
|
$(cat /etc/dib_binary_deps) ; do
|
|
# Don't take the ip command from busybox, its missing some features
|
|
if busybox_list | grep -v "^ip$" | grep "^$i\$" >/dev/null; then
|
|
continue
|
|
fi
|
|
path=`which $i 2>/dev/null` || path=$i
|
|
if ! [ -x "$path" ]; then
|
|
echo "$i is not found in PATH" 2>&1
|
|
exit 1
|
|
fi
|
|
cp -L "$path" "$TMP_MOUNT_PATH/bin/"
|
|
copy_required_libs "$path"
|
|
done
|
|
|
|
if [ -f /dib-signed-kernel-version ] ; then
|
|
. /dib-signed-kernel-version
|
|
fi
|
|
if [ -n "${DIB_SIGNED_KERNEL_VERSION:-}" ]; then
|
|
# Secure kernel module directory does not have efi.signed suffix to
|
|
# kernel version.
|
|
if echo $KERNEL_VERSION | grep -q 'efi.signed'; then
|
|
KERNEL_VERSION=`echo "$KERNEL_VERSION" |sed "s/\.efi\.signed//g"`
|
|
fi
|
|
fi
|
|
cp -a "$MODULE_DIR" "$TMP_MOUNT_PATH/lib/modules/$KERNEL_VERSION"
|
|
echo "Removing kernel framebuffer drivers to enforce text mode consoles..."
|
|
find $TMP_MOUNT_PATH/lib/modules/$KERNEL_VERSION/kernel/drivers/video -name '*fb.ko' -exec rm -v {} +
|
|
if [ -d $FIRMWARE_DIR ]; then
|
|
cp -a "$FIRMWARE_DIR" "$TMP_MOUNT_PATH/lib/firmware"
|
|
fi
|
|
}
|
|
|
|
function busybox_list () {
|
|
# busybox supports --list option since version 1.18
|
|
"$BUSYBOX" --list 2> /dev/null && return
|
|
# for busybox under 1.18 we parse command list from --help output
|
|
scrlet='{ if (go) { print } } /Currently defined functions:/ { go=1 }'
|
|
"$BUSYBOX" --help | awk "$scrlet" | tr ',' '\n' | xargs -n1 echo
|
|
}
|
|
|
|
function populate_busybox () {
|
|
echo "Creating symlinks for busybox binaries"
|
|
|
|
for i in $( busybox_list ); do
|
|
if [ -f "$TMP_MOUNT_PATH/bin/$i" ]; then
|
|
echo "skip $i"
|
|
continue
|
|
fi
|
|
ln -s busybox "$TMP_MOUNT_PATH/bin/$i"
|
|
done
|
|
}
|
|
|
|
function populate_init () {
|
|
echo "Installing init"
|
|
cp "$INIT" "$TMP_MOUNT_PATH/init"
|
|
chmod +x $TMP_MOUNT_PATH/init
|
|
for F in "$FUNCTIONS_D"/* ; do
|
|
cp "$F" "$TMP_MOUNT_PATH"
|
|
done
|
|
|
|
# Append /init with any element fragments that are present
|
|
TARGET_DIR="/tmp/in_target.d/"
|
|
for _ELEMENT in $(ls $TARGET_DIR/init.d/) ; do
|
|
_FILE="${TARGET_DIR}/init.d/${_ELEMENT}"
|
|
if [ -a $_FILE ]; then
|
|
cat >>$TMP_MOUNT_PATH/init <<EOF
|
|
|
|
# init fragment from ${_ELEMENT}
|
|
EOF
|
|
cat <$_FILE >>$TMP_MOUNT_PATH/init
|
|
fi
|
|
done
|
|
|
|
# Add our final steps to /init
|
|
cat <${INIT}-end >>$TMP_MOUNT_PATH/init
|
|
}
|
|
|
|
function finalise_image () {
|
|
echo "Finalising image"
|
|
(cd "$TMP_MOUNT_PATH"; find . | cpio -o -H newc | gzip > "$TMP_IMAGE_PATH" )
|
|
}
|
|
|
|
function populate_udev () {
|
|
echo "Installing udev rules"
|
|
|
|
TARGET_DIR="/tmp/in_target.d/"
|
|
for _ELEMENT in $(ls $TARGET_DIR/udev.d/) ; do
|
|
_FILE="${TARGET_DIR}/udev.d/${_ELEMENT}"
|
|
if [ -a $_FILE ]; then
|
|
cp ${_FILE} $TMP_MOUNT_PATH/lib/udev/rules.d/
|
|
fi
|
|
done
|
|
}
|
|
|
|
function find_kernel_version () {
|
|
_TMP=$(ls /boot/vmlinu* | sort | tail -1)
|
|
if [ "$_TMP" == "" ]; then
|
|
echo "Unable to find a suitable kernel" >>/dev/stderr
|
|
exit 1
|
|
fi
|
|
echo ${_TMP##/boot/vmlinu[zx]-}
|
|
}
|