[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.
536 lines
19 KiB
536 lines
19 KiB
#! /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" |
|
################################################################################
|
|
|