First pass lxc support

This commit is contained in:
devrandom 2012-04-21 22:44:00 -07:00
parent 8e161f4e6c
commit 28bb421156
12 changed files with 192 additions and 35 deletions

View File

@ -12,17 +12,30 @@ This performs a build inside a VM, with deterministic inputs and outputs. If th
Install prereqs: Install prereqs:
sudo apt-get install python-vm-builder qemu-kvm apt-cacher sudo apt-get install apt-cacher
sudo service apt-cacher start sudo service apt-cacher start
If you want to use kvm:
sudo apt-get install python-vm-builder qemu-kvm
or alternatively, lxc (no need for hardware support):
sudo apt-get install debootstrap lxc
Create the base VM for use in further builds (requires sudo, please review the script): Create the base VM for use in further builds (requires sudo, please review the script):
bin/make-base-vm bin/make-base-vm
bin/make-base-vm --arch i386
or for lxc:
bin/make-base-vm --lxc
bin/make-base-vm --lxc --arch i386
Copy any additional build inputs into a directory named _inputs_. Copy any additional build inputs into a directory named _inputs_.
Then execute the build using a YAML description file (can be run as non-root): Then execute the build using a YAML description file (can be run as non-root):
export USE_LXC=1 # LXC only
bin/gbuild <package>.yml bin/gbuild <package>.yml
or if you need to specify a commit for one of the git remotes: or if you need to specify a commit for one of the git remotes:

View File

@ -22,7 +22,7 @@ def sanitize(str, where)
end end
def sanitize_path(str, where) def sanitize_path(str, where)
raise "unsanitary string in #{where}" if (str =~ /[^\w\/.-]/) raise "unsanitary string in #{where}" if (str =~ /[^\w\/.:-]/)
str str
end end
@ -34,6 +34,12 @@ def build_one_configuration(suite, arch, build_desc, reference_datetime)
FileUtils.rm_f("var/build.log") FileUtils.rm_f("var/build.log")
bits = @bitness[arch] or raise "unknown architecture ${arch}" bits = @bitness[arch] or raise "unknown architecture ${arch}"
if ENV["USE_LXC"]
ENV["LXC_ARCH"] = arch
ENV["LXC_SUITE"] = suite
end
suitearch = "#{suite}-#{arch}" suitearch = "#{suite}-#{arch}"
info "Stopping target if it is up" info "Stopping target if it is up"
@ -43,7 +49,7 @@ def build_one_configuration(suite, arch, build_desc, reference_datetime)
unless @options[:skip_image] unless @options[:skip_image]
info "Making a new image copy" info "Making a new image copy"
system! "cp base-#{suitearch}.qcow2 target-#{suitearch}.qcow2" system! "make-clean-vm --suite #{suite} --arch #{arch}"
end end
info "Starting target" info "Starting target"
@ -66,7 +72,7 @@ def build_one_configuration(suite, arch, build_desc, reference_datetime)
build_desc["files"].each do |filename| build_desc["files"].each do |filename|
filename = sanitize(filename, "files section") filename = sanitize(filename, "files section")
system! "cd inputs && copy-to-target #{@quiet_flag} #{filename} build/" system! "copy-to-target #{@quiet_flag} inputs/#{filename} build/"
end end
info "Updating apt-get repository (log in var/install.log)" info "Updating apt-get repository (log in var/install.log)"
@ -92,8 +98,14 @@ def build_one_configuration(suite, arch, build_desc, reference_datetime)
script.puts "REFERENCE_TIME='#{ref_time}'" script.puts "REFERENCE_TIME='#{ref_time}'"
script.puts script.puts
build_desc["remotes"].each do |remote| build_desc["remotes"].each do |remote|
script.puts "git clone -q #{remote["url"]} build/#{remote["dir"]}" dir = sanitize(remote["dir"], remote["dir"])
script.puts "(cd build/#{remote["dir"]} && git checkout -q #{remote["commit"]})" if File.exist?("inputs/#{dir}")
system!("cd inputs/#{dir} && git fetch")
else
system!("git clone -q #{sanitize_path(remote["url"], remote["url"])} inputs/#{dir}")
end
system! "copy-to-target #{@quiet_flag} inputs/#{dir} build/"
script.puts "(cd build/#{dir} && git checkout -q #{remote["commit"]})"
end end
script.puts "cd build" script.puts "cd build"
script.puts build_desc["script"] script.puts build_desc["script"]

View File

@ -5,6 +5,7 @@ SUITE=lucid
ARCH=amd64 ARCH=amd64
MIRROR=http://${MIRROR_HOST:-127.0.0.1}:3142/archive.ubuntu.com/ubuntu MIRROR=http://${MIRROR_HOST:-127.0.0.1}:3142/archive.ubuntu.com/ubuntu
SECURITY_MIRROR=http://${MIRROR_HOST:-127.0.0.1}:3142/security.ubuntu.com/ubuntu SECURITY_MIRROR=http://${MIRROR_HOST:-127.0.0.1}:3142/security.ubuntu.com/ubuntu
LXC=0
usage() { usage() {
echo "Usage: ${0##*/} [OPTION]..." echo "Usage: ${0##*/} [OPTION]..."
@ -12,8 +13,9 @@ usage() {
echo echo
cat << EOF cat << EOF
--help display this help and exit --help display this help and exit
--suite=U build suite U instead of lucid --suite U build suite U instead of lucid
--arch=A build architecture A (e.g. i386) instead of amd64 --arch A build architecture A (e.g. i386) instead of amd64
--lxc use lxc instead of kvm
The MIRROR_HOST environment variable can be used to change the The MIRROR_HOST environment variable can be used to change the
apt-cacher host. It should be something that the target VM can apt-cacher host. It should be something that the target VM can
@ -38,6 +40,10 @@ if [ $# != 0 ] ; then
ARCH="$2" ARCH="$2"
shift 2 shift 2
;; ;;
--lxc)
LXC=1
shift 1
;;
--*) --*)
echo "unrecognized option $1" echo "unrecognized option $1"
exit 1 exit 1
@ -56,21 +62,32 @@ if [ ! -e var/id_dsa ]; then
fi fi
OUT=base-$SUITE-$ARCH OUT=base-$SUITE-$ARCH
if [ -e $OUT.qcow2 ]; then
echo $OUT.qcow2 already exists, please remove it first
exit 1
fi
rm -rf $OUT
FLAVOUR=virtual FLAVOUR=virtual
if [ $ARCH = "amd64" -a $SUITE = "hardy" ]; then if [ $ARCH = "amd64" -a $SUITE = "hardy" ]; then
FLAVOUR=server FLAVOUR=server
fi fi
sudo vmbuilder kvm ubuntu --arch=$ARCH --suite=$SUITE --addpkg=openssh-server,pciutils,build-essential,git-core,subversion --ssh-key=var/id_dsa.pub --ssh-user-key=var/id_dsa.pub --mirror=$MIRROR --security-mirror=$SECURITY_MIRROR --dest=$OUT --flavour=$FLAVOUR --firstboot=`pwd`/target-bin/bootstrap-fixup addpkg=openssh-server,pciutils,build-essential,git-core,subversion
mv $OUT/*.qcow2 $OUT.qcow2 if [ $LXC = "0" ]; then
if [ -e $OUT.qcow2 ]; then
echo $OUT.qcow2 already exists, please remove it first
exit 1
fi
rm -rf $OUT
sudo vmbuilder kvm ubuntu --arch=$ARCH --suite=$SUITE --addpkg=$addpkg --ssh-key=var/id_dsa.pub --ssh-user-key=var/id_dsa.pub --mirror=$MIRROR --security-mirror=$SECURITY_MIRROR --dest=$OUT --flavour=$FLAVOUR --firstboot=`pwd`/target-bin/bootstrap-fixup
mv $OUT/*.qcow2 $OUT.qcow2
rm -rf $OUT
else
if [ -e $OUT ]; then
echo $OUT already exists, please remove it first
exit 1
fi
rm -rf $OUT-root
sudo debootstrap --include=$addpkg --arch=$ARCH $SUITE $OUT-root $MIRROR
sudo target-bin/bootstrap-fixup $OUT-root
fi
rm -rf $OUT

32
etc/lxc.config.in Normal file
View File

@ -0,0 +1,32 @@
lxc.tty = 4
lxc.pts = 1024
lxc.rootfs = ROOTFS
lxc.arch = ARCH
lxc.cgroup.devices.deny = a
# /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 4:0 rwm
lxc.cgroup.devices.allow = c 4:1 rwm
# /dev/{,u}random
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc
lxc.cgroup.devices.allow = c 254:0 rwm
# mounts points
lxc.mount.entry=proc ROOTFS/proc proc nodev,noexec,nosuid 0 0
lxc.mount.entry=sysfs ROOTFS/sys sysfs defaults 0 0
# Container with network virtualized using a pre-configured bridge named br0 and
# veth pair virtual network devices
# On the host, run: ifconfig br0 up 10.0.2.2
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.ipv4 = 10.0.2.5/24

4
libexec/config-lxc Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
wd=`pwd`
sed "s;ROOTFS;$wd/target-$LXC_SUITE-$LXC_ARCH-root;;s;ARCH;$LXC_ARCH;g" < etc/lxc.config.in > var/lxc.config

View File

@ -46,4 +46,9 @@ if [ $# = 0 ] ; then
exit 1 exit 1
fi fi
scp $QUIET_FLAG -oConnectTimeout=5 -oNoHostAuthenticationForLocalhost=yes -i ${GITIAN_BASE:-.}/var/id_dsa -P $VM_SSH_PORT -r $TUSER@localhost:$1 $2 if [ -z "$USE_LXC" ]; then
scp $QUIET_FLAG -oConnectTimeout=5 -oNoHostAuthenticationForLocalhost=yes -i ${GITIAN_BASE:-.}/var/id_dsa -P $VM_SSH_PORT -r $TUSER@localhost:$1 $2
else
config-lxc
sudo lxc-start -n gitian -f var/lxc.config -- sudo -i -u $TUSER tar -cf - "$1" | tar -C "$2" -xkf -
fi

View File

@ -46,4 +46,9 @@ if [ $# = 0 ] ; then
exit 1 exit 1
fi fi
scp $QUIET_FLAG -oConnectTimeout=5 -oNoHostAuthenticationForLocalhost=yes -i ${GITIAN_BASE:-.}/var/id_dsa -P $VM_SSH_PORT $1 $TUSER@localhost:$2 if [ -z "$USE_LXC" ]; then
scp $QUIET_FLAG -oConnectTimeout=5 -oNoHostAuthenticationForLocalhost=yes -i ${GITIAN_BASE:-.}/var/id_dsa -P $VM_SSH_PORT $1 $TUSER@localhost:$2
else
config-lxc
tar -C `dirname "$1"` -cf - `basename "$1"` | sudo lxc-start -n gitian -f var/lxc.config -- sudo -i -u $TUSER tar -C "$2" -xf -
fi

53
libexec/make-clean-vm Executable file
View File

@ -0,0 +1,53 @@
#!/bin/sh
set -e
SUITE=lucid
ARCH=amd64
usage() {
echo "Usage: ${0##*/} [OPTION]..."
echo "Make a clean copy of the base client."
echo
cat << EOF
--help display this help and exit
--suite U build suite U instead of lucid
--arch A build architecture A (e.g. i386) instead of amd64
EOF
}
if [ $# != 0 ] ; then
while true ; do
case "$1" in
--help|-h)
usage
exit 0
;;
--suite|-s)
SUITE="$2"
shift 2
;;
--arch|-a)
ARCH="$2"
shift 2
;;
--*)
echo "unrecognized option $1"
exit 1
;;
*)
break
;;
esac
done
fi
BASE=base-$SUITE-$ARCH-root
OUT=target-$SUITE-$ARCH-root
if [ -z "$USE_LXC" ]; then
cp $BASE.qcow2 $OUT.qcow2
else
sudo rm -rf $OUT
sudo cp -a $BASE $OUT
on-target -u root useradd -m ubuntu
fi

View File

@ -41,4 +41,13 @@ fi
# exit 1 # exit 1
#fi #fi
ssh -oConnectTimeout=5 -oNoHostAuthenticationForLocalhost=yes -i ${GITIAN_BASE:-.}/var/id_dsa -p $VM_SSH_PORT $TUSER@localhost $* if [ -z "$USE_LXC" ]; then
ssh -oConnectTimeout=5 -oNoHostAuthenticationForLocalhost=yes -i ${GITIAN_BASE:-.}/var/id_dsa -p $VM_SSH_PORT $TUSER@localhost $*
else
config-lxc
if [ $TUSER = "root" ]; then
sudo lxc-start -n gitian -f var/lxc.config -- $*
else
sudo lxc-start -n gitian -f var/lxc.config -- sudo -i -u $TUSER $*
fi
fi

View File

@ -5,8 +5,11 @@
ARCH=qemu$1 ARCH=qemu$1
SUFFIX=$2 SUFFIX=$2
kvm -cpu $ARCH -m ${VMEM:-2000} -smp ${NPROCS:-2} -drive file=target-$SUFFIX.qcow2 -net nic,model=virtio -net user,hostfwd=tcp:127.0.0.1:$VM_SSH_PORT-:22 -vnc 127.0.0.1:16 > var/target.log 2>&1 & if [ -z "$USE_LXC" ]; then
kvm -cpu $ARCH -m ${VMEM:-2000} -smp ${NPROCS:-2} -drive file=target-$SUFFIX.qcow2 -net nic,model=virtio -net user,hostfwd=tcp:127.0.0.1:$VM_SSH_PORT-:22 -vnc 127.0.0.1:16 > var/target.log 2>&1 &
echo $! > var/target.pid echo $! > var/target.pid
wait wait
rm var/target.pid rm var/target.pid
else
true #sudo lxc-start -n gitian -c var/target.log -f lxc.config
fi

View File

@ -1,14 +1,18 @@
#!/bin/sh #!/bin/sh
if [ ! -e var/target.pid ]; then exit; fi if [ -z "$USE_LXC" ]; then
if [ ! -e var/target.pid ]; then exit; fi
on-target -u root halt on-target -u root halt
sleep 5 sleep 5
if [ ! -e var/target.pid ]; then exit; fi if [ ! -e var/target.pid ]; then exit; fi
sleep 5 sleep 5
if [ ! -e var/target.pid ]; then exit; fi if [ ! -e var/target.pid ]; then exit; fi
echo Killing target since it did not shutdown within 10 seconds echo Killing target since it did not shutdown within 10 seconds
kill `cat var/target.pid` kill `cat var/target.pid`
else
true
fi

View File

@ -2,4 +2,4 @@
set -e set -e
sed -i -e 's/127.0.0.1:/10.0.2.2:/' $1/etc/apt/sources.list echo 'deb http://10.0.2.2:3142/archive.ubuntu.com/ubuntu lucid main universe' > $1/etc/apt/sources.list