[DEPRECATED, use docker as replacement] Install RPM Based Distros, e.g. SuSE or Fedora, in chroots (for schroot) in an Ubuntu. This is the old method, now I'm using docker.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

537 lines
19 KiB

9 years ago
#! /bin/bash -e
function error() {
echo "**** ERROR aborted. Status of last operation: $?" 1>&2
exit 1
}
trap error HUP INT QUIT TERM ERR
# log LEVEL "Text"
# LEVEL: 0=normal 1=verbose 2=more-verbose
function echon() {
if test "$1" == "-n"; then
shift
echo -n "$*"
else
echo "$*"
fi
}
function log() {
l=$1
shift
if test "$1" == "-n"; then
shift
n="-n"
else
n=""
fi
if test $q -eq 1; then
return
elif test $l -eq 0 -o $l -eq 1 -a $v -eq 1 -o $l -eq 2 -a $vv -eq 1; then
if test $l -gt 0; then
echon $n " $l$*"
else
echon $n "$*"
fi
fi
}
################################################################################
# Arguments
################################################################################
q=0
v=0
vv=0
while test $# -gt 0; do
case "$1" in
(-q) q=1; v=0; vv=0;;
(-v) q=0; v=1; vv=0;;
(-vv) q=0; v=1; vv=1;;
(-h|--help)
echo "SYNOPSIS: $0 [-q|-v|-vv]"
echo " -q quiet"
echo " -v verbose"
echo " -vv more verbose"
exit 0;;
esac
shift
done
################################################################################
################################################################################
# CONFIGURATION you can overwrite any of the variables when you start the script
# e.g. HW="x86_64 noarch" VERSION=11.4 sudo susebootstrap.sh
# Setup OS sources
#
# OS: name of the OS, used for chroot pathname
OS=${OS:-"opensuse"}
log 2 "OS=$OS"
#
# VERSION: see e.g. http://download.opensuse.org/distribution/
VERSION=${VERSION:-$(
case "$OS" in
opensuse) echo "openSUSE-current";;
fedora) echo "$(wget -O- http://mirror.switch.ch/ftp/mirror/fedora/linux/releases 2>/dev/null | html2 | sed -n 's,.*/a/@href=\([0-9][0-9]*\)/,\1,gp' | uniq | tail -1)";;
centos) echo "$(wget -O- http://mirror.switch.ch/ftp/mirror/centos 2>/dev/null | sed -n 's,.*href="\([0-9][0-9]*\)/".*,\1,pg' | uniq | tail -1)"
esac)}
log 2 "VERSION=$VERSION"
#
# HW: list of hardware subdirs in openSUSE, e.g. "x86_64 noarch"
HW=${HW:-$(
case "$OS" in
opensuse) echo "i586 noarch";;
fedora) echo "i686 noarch";;
centos) echo "x86_64 noarch";;
esac)}
log 2 "HW=$HW"
#
# BASEARCH: Base architecture, e.g. for i686 and i566 BASEARCH is i386
BASEARCH=${BASEARCH:-$(
case "${HW%% *}" in
i?86) echo "i386";;
*) echo "${HW%% *}";;
esac)}
log 2 "BASEARCH=$BASEARCH"
#
# URL: where to download packages from
URL=${URL:-$(
case "$OS" in
opensuse)
case "$VERSION" in
(tumbleweed) echo "http://download.opensuse.org/tumbleweed/repo/oss/suse";;
(*) echo "http://download.opensuse.org/distribution/${VERSION}/repo/oss/suse";;
esac;;
fedora)
if test "$VERSION" -gt 20; then
echo "http://mirror.switch.ch/ftp/mirror/fedora/linux/releases/${VERSION}/Server/${BASEARCH}/os"
else
echo "http://mirror.switch.ch/ftp/mirror/fedora/linux/releases/${VERSION}/Fedora/${BASEARCH}/os"
fi;;
centos) echo "http://mirror.switch.ch/ftp/mirror/centos/${VERSION}/os/${BASEARCH}";;
esac)}
log 2 "URL=$URL"
# Setup installation pathes
#
# BASE: Base path to the chroots on your system
BASE=${BASE:-/var/chroot}
log 2 "BASE=$BASE"
#
# SCHROOTCONF: Configurationfile for schroot
SCHROOTCONF=${SCHROOTCONF:-${OS}-${VERSION}_${BASEARCH}}
log 2 "SCHROOTCONF=$SCHROOTCONF"
#
# ROOT: Full path to the chroot directory
ROOT=${ROOT:-${BASE}/${SCHROOTCONF}}
log 2 "ROOT=$ROOT"
#
# PACKAGES: Where to store package lists path+filename-prefix
PACKAGES=${PACKAGES:-${ROOT}/var/tmp/packagelist}
log 2 "PACKAGES=$PACKAGES"
#
# PKGDIR: Where to store downloaded packages, relative to ${ROOT}
PKGDIR=${PKGDIR:-/var/tmp/packages}
log 2 "PKGDIR=$PKGDIR"
#
# SCHROOTUSER: Name of user or list of user that will use schroot
SCHROOTUSER=${SCHROOTUSER:-${USER}}
log 2 "SCHROOTUSER=$SCHROOTUSER"
#
# CHROOT: Command for starting chroot, more possibilities, see below
CHROOT="schroot -c ${SCHROOTCONF} -d / -u root"
log 2 "CHROOT=$CHROOT"
#
# YUM: Set Fedora / CentOS repository tool
if test "$OS" = "fedora" && test "${VERSION}" -gt "21"; then
YUM=${YUM:-"dnf"}
else
YUM=${YUM:-"yum"}
fi
log 2 "YUM=$YUM"
#
# PKGS: Base packages to install for minimal system
PKGS=${PKGS:-$(
case "$OS" in
opensuse) echo "bash rpm zypper";;
fedora)
echo "bash rpm fedora-release"
if test "${VERSION}" -gt "21"; then
echo "dnf"
else
echo "yum"
fi
;;
centos)
echo "bash rpm yum centos-release"
;;
esac)}
log 2 "PKGS=$PKGS"
#
#
if [ -z "${CHROOT}" ]; then
echo "**** ERROR: Variable CHROOT must be set." 1>&2
exit 1
fi
# ADDITIONAL_DEFINITIONS: Add additional definitions to /etc/schroot/chroot.d
# Example: ADDITIONAL_DEFINITIONS="setup.fstab=jenkins/fstab"
ADDITIONAL_DEFINITIONS=${ADDITIONAL_DEFINITIONS:-}
log 2 "ADDITIONAL_DEFINITIONS=$ADDITIONAL_DEFINITIONS"
################################################################################
################################################################################
# Main Part
################################################################################
# 1. Download basic packages
# 2. Unpack them into a chroot-path
# 3. Tweak the minimal system
# 4. Setup basic /dev
# 5. Properly install all the packages within chroot
# 6. configure basic system
# 7. Done, now chroot to the path and install whatever you need
################################################################################
log 0 "Install ${OS} ${VERSION} for ${BASEARCH} in ${ROOT}"
################################################################################
# Preparation of path for chroot and packages
test -d ${ROOT}${PKGDIR} || mkdir -p ${ROOT}${PKGDIR}
################################################################################
################################################################################
# 0. Setup schroot configuration
cat > /etc/schroot/chroot.d/${SCHROOTCONF} <<EOF
[${SCHROOTCONF}]
description=${OS}-${VERSION} ${BASEARCH}
directory=${ROOT}
users=${SCHROOTUSER}
root-groups=root
root-users=${SCHROOTUSER}
type=directory
${ADDITIONAL_DEFINITIONS}
EOF
################################################################################
################################################################################
# 0. Search for dependencies to install
# requires: rpm xml2 schroot
log 0 " ... read repository meta data"
test -d ${PACKAGES} || mkdir -p ${PACKAGES}
test -f ${PACKAGES}/repomd.xml || \
wget -q -O ${PACKAGES}/repomd.xml ${URL}/repodata/repomd.xml
datapath=$(xml2 < ${PACKAGES}/repomd.xml \
| awk -F= 'BEGIN {x=0}
x==1 && $1=="/repomd/data/location/@href" {print $2; exit}
$1=="/repomd/data/@type" && $2=="primary" {x=1}')
dataname=${PACKAGES}/${datapath##*/}
log 2 "dataname=${dataname} from ${URL}/${datapath}"
log 0 " ... read repository details"
test -f ${dataname} || \
wget -q -O ${dataname} ${URL}/${datapath}
log 0 " ... recursively extract dependencies"
oldPKGS=""
if [ ! -f ${PACKAGES}/packages ]; then
test ! -f ${PACKAGES}/install || rm ${PACKAGES}/install
while [ "$PKGS" != "$oldPKGS" ]; do
oldPKGS=$PKGS
log 0 " ... extract dependencies: scan $(echo "$PKGS" | wc -w)" \
"packages"
log 0 " ... extract dependencies: find requirements"
PKGS=${PKGS% }
chkinstpkgs=$(echo $PKGS | sed -e 's/[^-A-Za-z0-9_ ]/./g' | tr ' ' '|')
deps=$(
(
echo "$PKGS" | tr ' ' '\n';
zcat $dataname | xml2 | awk -F= '
BEGIN {
x=0
}
x==1 &&
( $1=="/metadata/package/format/rpm:requires/rpm:entry/@name" ||
( $1=="/metadata/package/format/rpm:provides/rpm:entry/@name" &&
$2~/^('${chkinstpkgs}')$/ ) ) {
print $2
}
$1=="/metadata/package/name" && $2~/^('${chkinstpkgs}')$/ {
x=1
}
$1=="/metadata/package/name" && $2!~/^('${chkinstpkgs}')$/ {
x=0
}
$1=="/metadata/package/arch" && $2!~/^('${HW// /|}')$/ {
x=0
}'
) | \
sed -e 's/[^-A-Za-z0-9_]/./g' | \
sort | uniq | tr '\n ' '||' | \
sed -e 's/^|//' -e 's/|$//'
)
log 0 " ... extract dependencies: extend packagelist by providers"
PKGS=$(
zcat $dataname | xml2 | awk -F= '
BEGIN {
matcher="^('${deps}')$" #(|\\(.*\\))$"
}
$1=="/metadata/package/name" && $2~matcher {
name=$2
tmp=$2
gsub(/[^-A-Za-z0-9_]/, ".", tmp)
sub("\\|" tmp "\\|", "|", matcher)
sub("^" tmp ")\\|", "", matcher)
sub("\\|" tmp "$", "", matcher)
print name
}
$1=="/metadata/package/name" && $2!~matcher {
name=$2
}
( $1=="/metadata/package/format/rpm:provides/rpm:entry/@name" ||
$1=="/metadata/package/format/file" ) &&
$2~matcher {
tmp=$2
gsub(/[^-A-Za-z0-9_]/, ".", tmp)
sub("\\|" tmp "\\|", "|", matcher)
sub("^" tmp ")\\|", "", matcher)
sub("\\|" tmp "$", "", matcher)
print name
}
END {
}' | sort | uniq | tr '\n' ' '
)
((++pkgcnt)) ###
log 2 "temp packages: $PKGS"
log 2 "temp dependencies: $deps"
done
else
log 2 "packages already evaluated"
PKGS=$(<${PACKAGES}/packages)
fi
PKGS=${PKGS% }
echo ${PKGS} > ${PACKAGES}/packages
log 1 "final packages: $PKGS"
log 0 " ... extract dependencies: find files to download and install"
if [ -f ${PACKAGES}/install ]; then
log 2 "installations already evaluated"
INSTALL=$(<${PACKAGES}/install)
else
chkinstpkgs=$(echo $PKGS | sed -e 's/[^-A-Za-z0-9_ ]/./g' | tr ' ' '|')
INSTALL=$(
zcat $dataname | xml2 | awk -F= '
BEGIN {
x=0
}
x==1 && $1=="/metadata/package/location/@href" {
print $2
}
$1=="/metadata/package/name" && $2~/^('${chkinstpkgs}')$/ {
x=1
}
$1=="/metadata/package/name" && $2!~/^('${chkinstpkgs}')$/ {
x=0
}
$1=="/metadata/package/arch" && $2!~/^('${HW// /|}')$/ {
x=0
}' | sort | uniq | tr '\n' ' '
)
echo $INSTALL > ${PACKAGES}/install
fi
log 1 "installations: ${INSTALL}"
log 0 " ... download and install $(echo ${INSTALL} | wc -w) files"
################################################################################
################################################################################
# 1. Download basic packages
# We know the logical package names, find matching package files
# on server
# INST: Will be filled with a list of package files to download and
# install
for p in $INSTALL; do # for all packages to install
log 0 " ... download $p"
test -f ${ROOT}${PKGDIR}/${p##*/} || \
wget -q -O ${ROOT}${PKGDIR}/${p##*/} ${URL}/$p
INST="$INST ${p##*/}"
done
################################################################################
################################################################################
# 2. Unpack them into a chroot-path
# Extract all downloaded packages in the chroot directory
cd ${ROOT}
for p in $INST; do # for all downloaded packages
# just extract the file structure withing the package without running
# pre-/post-install scripts
# this is necessary for a minimal basic system to chroot in
log 0 " ... unpack $p"
rpm2cpio ${ROOT}${PKGDIR}/$p | cpio -dim --quiet 2> /dev/null
done
cd - > /dev/null
################################################################################
################################################################################
# 3. Tweak the minimal system
log 0 " ... setup system"
#
# Do some system setup tweaks
#
# Create minimal /etc/passwd and /etc/group with user "root"
test -e ${ROOT}/etc/passwd || \
echo 'root:x:0:0:root:/root:/bin/bash' > ${ROOT}/etc/passwd
test -e ${ROOT}/etc/group || \
( \
echo 'root:x:0:'; \
echo 'utmp:x:0:' \
) > ${ROOT}/etc/group
test -e ${ROOT}/etc/shadow || touch ${ROOT}/etc/shadow
test -e ${ROOT}/etc/gshadow || touch ${ROOT}/etc/gshadow
test -e ${ROOT}/etc/fstab || touch ${ROOT}/etc/fstab
#
# copy /etc/resolv.conf into chroot to be able to access internet
test -e ${ROOT}/etc/resolv.conf || \
cp /etc/resolv.conf ${ROOT}/etc/
################################################################################
# 4. Setup basic /dev
log 0 " ... setup prepare minimal /dev with /dev/null and /dev/zero"
if [ -n "${CHROOT//*schroot*/}" ]; then
# only if chroot is not schroot, schroot creates /dev
test -d ${ROOT}/dev || ${CHROOT} mkdir ${ROOT}/dev
test -e ${ROOT}/dev/null || \
( \
${CHROOT} mknod -m 666 /dev/null c 1 3 && \
${CHROOT} chown root:root /dev/null
)
test -e ${ROOT}/dev/zero || \
( \
${CHROOT} mknod -m 666 /dev/zero c 1 5 && \
${CHROOT} chown root:root /dev/zero \
)
fi
################################################################################
################################################################################
# 5. Properly install all the package packages within chroot
# now chroot into the new system and properly install all downloaded packages,
# this executes triggers and maintains package database
log 0 " ... install all packages"
all_success=1
if ! ${CHROOT} -- rpm -i --nodeps --force ${PKGDIR}/*.rpm > /dev/null 2> /dev/null; then
for p in ${ROOT}${PKGDIR}/*.rpm; do
log 0 -n " ... install ${p#${ROOT}}"
if ${CHROOT} -- rpm -i --nodeps --force ${p#${ROOT}} \
> /dev/null 2> /dev/null; then
log 0 " success"
else
all_success=0
log 0 " error"
fi
done
fi
################################################################################
################################################################################
# System Dependent Part
################################################################################
case "$OS" in
(opensuse)
########################################################################
# 6. Add an archive source to package manager
# add installation source as repository
log 0 " ... setup package manager"
${CHROOT} -- zypper -q ar ${URL} repo-oss
#
# setup hardware architecture in zypper, necessary different from host
${CHROOT} -- perl -pi \
-e 's#^\#? *arch = .*$#arch = '${HW%% *}'#g' \
/etc/zypp/zypp.conf
#
# basic initialisation, first update - bug with key in 12.2
log 0 " ... basic initialisation of package manager"
${CHROOT} -- zypper -q -n --gpg-auto-import-keys update || \
${CHROOT} -- zypper -q -n --no-gpg-checks update
${CHROOT} -- zypper -q -n --gpg-auto-import-keys dist-upgrade || \
${CHROOT} -- zypper -q -n --no-gpg-checks dist-upgrade
#
# install some basic packages
log 0 " ... install more basic packages"
${CHROOT} -- zypper -q -n --gpg-auto-import-keys \
install openSUSE-release
########################################################################
;;
(fedora)
########################################################################
# 6. Install basic packages
log 0 " ... setup package manager using $YUM"
test -d ${ROOT}/etc/rpm || mkdir -p ${ROOT}/etc/rpm
sed -i 's,$basearch,'${BASEARCH}',g' \
$(grep -lr '$basearch' ${ROOT}/etc/yum.repos.d)
echo "${HW%% *}-${OS}-linux" > ${ROOT}/etc/rpm/platform
if test "${VERSION}" -gt "16"; then # hack for fedora 17 and above
log 0 " ... convert fedora 17+ filesystem"
${0%/*}/convertfs-fedora-17.sh ${ROOT}
fi
log 0 " ... upgrade base system"
${CHROOT} -- ${YUM} -y -q upgrade || \
( ${CHROOT} -- bash -c 'sed -i "s|^#baseurl|baseurl| ; s|^mirrorlist|#mirrorlist|" /etc/yum.repos.d/*' && \
${CHROOT} -- ${YUM} -y -q upgrade )
log 0 " ... install more basic packages"
for g in "Base" "Minimal Install"; do
if ${CHROOT} -- ${YUM} -y -q grouplist | grep -q "$g"; then
log 2 "install $g"
case "$VERSION" in
(*-Fedora)
${CHROOT} -- ${YUM} -y -q groups mark install "$g"
;;
(*)
${CHROOT} -- ${YUM} -y -q groupupdate "$g"
;;
esac
fi
done
########################################################################
;;
(centos)
########################################################################
# 6. Install basic packages
log 0 " ... setup package manager using $YUM"
${CHROOT} -- ln -s /sbin/chkconfig /usr/sbin/chkconfig
test -d ${ROOT}/etc/rpm || mkdir -p ${ROOT}/etc/rpm
echo "${HW%% *}-${OS}-linux" > ${ROOT}/etc/rpm/platform
if test "${VERSION}" -gt "6"; then # hack for fedora 17 and above
log 0 " ... convert fedora 17+ filesystem"
${0%/*}/convertfs-fedora-17.sh ${ROOT}
fi
log 0 " ... upgrade base system"
${CHROOT} -- ${YUM} -y -q upgrade || \
( ${CHROOT} -- bash -c 'sed -i "s|^#baseurl|baseurl| ; s|^mirrorlist|#mirrorlist|" /etc/yum.repos.d/*' && \
${CHROOT} -- ${YUM} -y -q upgrade )
log 0 " ... install more basic packages"
for g in "Base" "Minimal Install"; do
if ${CHROOT} -- ${YUM} -y -q grouplist | grep -q "$g"; then
log 2 "install $g"
${CHROOT} -- ${YUM} -y -q groups mark install "$g"
${CHROOT} -- ${YUM} -y -q upgrade
log 2 "update $g"
${CHROOT} -- ${YUM} -y -q groupupdate "$g"
fi
done
########################################################################
;;
esac
################################################################################
################################################################################
# 7. Done - use your chroot to work or install more packages
log 0 "**** SUCCESS done."
log 0
log 0 "########################################################################"
log 0 "Use your new chroot:"
log 0 " > ${CHROOT} -- bash"
log 0 " > [... work in your chroot ...]"
log 0 " > exit"
log 0 "########################################################################"
log 0 " ... cleanup chroot"
################################################################################