]> git.proxmox.com Git - mirror_lxc.git/blob - templates/lxc-ubuntu.in
Make ubuntu templates squid-deb-proxy-client aware
[mirror_lxc.git] / templates / lxc-ubuntu.in
1 #!/bin/bash
2
3 #
4 # template script for generating ubuntu container for LXC
5 #
6 # This script consolidates and extends the existing lxc ubuntu scripts
7 #
8
9 # Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
10 # Copyright © 2010 Wilhelm Meier
11 # Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
12 #
13 # This library is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU Lesser General Public
15 # License as published by the Free Software Foundation; either
16 # version 2.1 of the License, or (at your option) any later version.
17
18 # This library is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # Lesser General Public License for more details.
22
23 # You should have received a copy of the GNU Lesser General Public
24 # License along with this library; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26
27 set -e
28
29 LOCALSTATEDIR="@LOCALSTATEDIR@"
30 LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
31
32 if [ -r /etc/default/lxc ]; then
33 . /etc/default/lxc
34 fi
35
36 configure_ubuntu()
37 {
38 rootfs=$1
39 hostname=$2
40 release=$3
41 user=$4
42 password=$5
43
44 # configure the network using the dhcp
45 cat <<EOF > $rootfs/etc/network/interfaces
46 # This file describes the network interfaces available on your system
47 # and how to activate them. For more information, see interfaces(5).
48
49 # The loopback network interface
50 auto lo
51 iface lo inet loopback
52
53 auto eth0
54 iface eth0 inet dhcp
55 EOF
56
57 # set the hostname
58 cat <<EOF > $rootfs/etc/hostname
59 $hostname
60 EOF
61 # set minimal hosts
62 cat <<EOF > $rootfs/etc/hosts
63 127.0.0.1 localhost
64 127.0.1.1 $hostname
65
66 # The following lines are desirable for IPv6 capable hosts
67 ::1 ip6-localhost ip6-loopback
68 fe00::0 ip6-localnet
69 ff00::0 ip6-mcastprefix
70 ff02::1 ip6-allnodes
71 ff02::2 ip6-allrouters
72 EOF
73
74 if [ ! -f $rootfs/etc/init/container-detect.conf ]; then
75 # suppress log level output for udev
76 sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
77
78 # remove jobs for consoles 5 and 6 since we only create 4 consoles in
79 # this template
80 rm -f $rootfs/etc/init/tty{5,6}.conf
81 fi
82
83 if [ -z "$bindhome" ]; then
84 chroot $rootfs useradd --create-home -s /bin/bash $user
85 echo "$user:$password" | chroot $rootfs chpasswd
86 fi
87
88 # make sure we have the current locale defined in the container
89 if [ -z "$LANG" ] || echo $LANG | grep -E -q "^C(\..+)*$"; then
90 chroot $rootfs locale-gen en_US.UTF-8
91 chroot $rootfs update-locale LANG=en_US.UTF-8
92 else
93 chroot $rootfs locale-gen $LANG
94 chroot $rootfs update-locale LANG=$LANG
95 fi
96
97 # generate new SSH keys
98 if [ -x $rootfs$LOCALSTATEDIR/lib/dpkg/info/openssh-server.postinst ]; then
99 cat > $rootfs/usr/sbin/policy-rc.d << EOF
100 #!/bin/sh
101 exit 101
102 EOF
103 chmod +x $rootfs/usr/sbin/policy-rc.d
104
105 rm -f $rootfs/etc/ssh/ssh_host_*key*
106 mv $rootfs/etc/init/ssh.conf $rootfs/etc/init/ssh.conf.disabled
107 DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot $rootfs $LOCALSTATEDIR/lib/dpkg/info/openssh-server.postinst configure
108 mv $rootfs/etc/init/ssh.conf.disabled $rootfs/etc/init/ssh.conf
109
110 sed -i "s/root@$(hostname)/root@$hostname/g" $rootfs/etc/ssh/ssh_host_*.pub
111
112 rm -f $rootfs/usr/sbin/policy-rc.d
113 fi
114
115 return 0
116 }
117
118 # finish setting up the user in the container by injecting ssh key and
119 # adding sudo group membership.
120 # passed-in user is either 'ubuntu' or the user to bind in from host.
121 finalize_user()
122 {
123 user=$1
124
125 sudo_version=$(chroot $rootfs dpkg-query -W -f='${Version}' sudo)
126
127 if chroot $rootfs dpkg --compare-versions $sudo_version gt "1.8.3p1-1"; then
128 groups="sudo"
129 else
130 groups="sudo admin"
131 fi
132
133 for group in $groups; do
134 chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true
135 chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true
136 done
137
138 if [ -n "$auth_key" -a -f "$auth_key" ]; then
139 u_path="/home/${user}/.ssh"
140 root_u_path="$rootfs/$u_path"
141 mkdir -p $root_u_path
142 cp $auth_key "$root_u_path/authorized_keys"
143 chroot $rootfs chown -R ${user}: "$u_path"
144
145 echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys"
146 fi
147 return 0
148 }
149
150 # A function to try and autodetect squid-deb-proxy servers on the local network
151 # if either the squid-deb-proxy-client package is installed on the host or
152 # a parent container set the 50squid-deb-proxy-client file.
153 squid_deb_proxy_autodetect()
154 {
155 local apt_discover=/usr/share/squid-deb-proxy-client/apt-avahi-discover
156 local proxy_file=/etc/apt/apt.conf.d/50squid-deb-proxy-client
157 squid_proxy_line= # That's a global :/
158
159 # Maybe the host is aware of a squid-deb-proxy?
160 if [ -f $apt_discover ]; then
161 echo -n "Discovering squid-deb-proxy..."
162 squid_proxy_line=$($apt_discover)
163 if [ -n "$squid_proxy_line" ]; then
164 echo "found squid-deb-proxy: $squid_proxy_line"
165 else
166 echo "no squid-deb-proxy found"
167 fi
168 fi
169
170 # Are we in a nested container, and the parent already knows of a proxy?
171 if [ -f $proxy_file ]; then
172 # Extract the squid URL from the file (whatever is between "")
173 squid_proxy_line=`cat $proxy_file | sed "s/.*\"\(.*\)\".*/\1/"`
174 fi
175 }
176
177 #
178 # Choose proxies for container
179 # http_proxy will be used by debootstrap on the host.
180 # APT_PROXY will be used to set /etc/apt/apt.conf.d/70proxy in the container.
181 #
182 choose_container_proxy()
183 {
184 local rootfs=$1
185 local arch=$2
186
187 if [ -z "$HTTP_PROXY" ]; then
188 HTTP_PROXY="none"
189 fi
190 case "$HTTP_PROXY" in
191 none)
192 squid_deb_proxy_autodetect
193 if [ -n "$squid_proxy_line" ]; then
194 APT_PROXY=$squid_proxy_line
195 export http_proxy=$squid_proxy_line
196 else
197 APT_PROXY=
198 fi
199 ;;
200 apt)
201 RES=`apt-config shell APT_PROXY Acquire::http::Proxy`
202 eval $RES
203 [ -z "$APT_PROXY" ] || export http_proxy=$APT_PROXY
204 ;;
205 *)
206 APT_PROXY=$HTTP_PROXY
207 export http_proxy=$HTTP_PROXY
208 ;;
209 esac
210 }
211
212 write_sourceslist()
213 {
214 # $1 => path to the rootfs
215 # $2 => architecture we want to add
216 # $3 => whether to use the multi-arch syntax or not
217
218 if [ -n "$APT_PROXY" ]; then
219 mkdir -p $rootfs/etc/apt/apt.conf.d
220 cat > $rootfs/etc/apt/apt.conf.d/70proxy << EOF
221 Acquire::http::Proxy "$APT_PROXY" ;
222 EOF
223 fi
224
225 case $2 in
226 amd64|i386)
227 MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
228 SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu}
229 ;;
230 *)
231 MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
232 SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
233 ;;
234 esac
235 if [ -n "$3" ]; then
236 cat >> "$1/etc/apt/sources.list" << EOF
237 deb [arch=$2] $MIRROR ${release} main restricted universe multiverse
238 deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse
239 deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse
240 EOF
241 else
242 cat >> "$1/etc/apt/sources.list" << EOF
243 deb $MIRROR ${release} main restricted universe multiverse
244 deb $MIRROR ${release}-updates main restricted universe multiverse
245 deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse
246 EOF
247 fi
248 }
249
250 install_packages()
251 {
252 local rootfs="$1"
253 shift
254 local packages="$*"
255 if [ -z $update ]
256 then
257 chroot $rootfs apt-get update
258 update=true
259 fi
260 if [ -n "${packages}" ]
261 then
262 chroot $rootfs apt-get install --force-yes -y --no-install-recommends ${packages}
263 fi
264 }
265
266 cleanup()
267 {
268 rm -rf $cache/partial-$arch
269 rm -rf $cache/rootfs-$arch
270 }
271
272 suggest_flush()
273 {
274 echo "Container upgrade failed. The container cache may be out of date,"
275 echo "in which case flushing the cache (see -F in the help output) may help."
276 }
277
278 download_ubuntu()
279 {
280 cache=$1
281 arch=$2
282 release=$3
283
284 packages_template=${packages_template:-"ssh,vim"}
285
286 # Try to guess a list of langpacks to install
287 langpacks="language-pack-en"
288
289 if which dpkg >/dev/null 2>&1; then
290 langpacks=`(echo $langpacks &&
291 dpkg -l | grep -E "^ii language-pack-[a-z]* " |
292 cut -d ' ' -f3) | sort -u`
293 fi
294 packages_template="${packages_template},$(echo $langpacks | sed 's/ /,/g')"
295
296
297 echo "Installing packages in template: ${packages_template}"
298
299 trap cleanup EXIT SIGHUP SIGINT SIGTERM
300 # check the mini ubuntu was not already downloaded
301 mkdir -p "$cache/partial-$arch"
302 if [ $? -ne 0 ]; then
303 echo "Failed to create '$cache/partial-$arch' directory"
304 return 1
305 fi
306
307 choose_container_proxy $cache/partial-$arch/ $arch
308 # download a mini ubuntu into a cache
309 echo "Downloading ubuntu $release minimal ..."
310 if [ -n "$(which qemu-debootstrap)" ]; then
311 qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR
312 else
313 debootstrap --verbose --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR
314 fi
315
316 if [ $? -ne 0 ]; then
317 echo "Failed to download the rootfs, aborting."
318 return 1
319 fi
320
321 # Serge isn't sure whether we should avoid doing this when
322 # $release == `distro-info -d`
323 echo "Installing updates"
324 > $cache/partial-$arch/etc/apt/sources.list
325 write_sourceslist $cache/partial-$arch/ $arch
326
327 chroot "$1/partial-${arch}" apt-get update
328 if [ $? -ne 0 ]; then
329 echo "Failed to update the apt cache"
330 return 1
331 fi
332 cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF
333 #!/bin/sh
334 exit 101
335 EOF
336 chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
337
338 lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y || { suggest_flush; false; }
339 rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
340
341 chroot "$1/partial-${arch}" apt-get clean
342
343 mv "$1/partial-$arch" "$1/rootfs-$arch"
344 trap EXIT
345 trap SIGINT
346 trap SIGTERM
347 trap SIGHUP
348 echo "Download complete"
349 return 0
350 }
351
352 copy_ubuntu()
353 {
354 cache=$1
355 arch=$2
356 rootfs=$3
357
358 # make a local copy of the miniubuntu
359 echo "Copying rootfs to $rootfs ..."
360 mkdir -p $rootfs
361 rsync -Ha $cache/rootfs-$arch/ $rootfs/ || return 1
362 return 0
363 }
364
365 install_ubuntu()
366 {
367 rootfs=$1
368 release=$2
369 flushcache=$3
370 cache="$LOCALSTATEDIR/cache/lxc/$release"
371 mkdir -p $LOCALSTATEDIR/lock/subsys/
372
373 (
374 flock -x 9
375 if [ $? -ne 0 ]; then
376 echo "Cache repository is busy."
377 return 1
378 fi
379
380
381 if [ $flushcache -eq 1 ]; then
382 echo "Flushing cache..."
383 rm -rf "$cache/partial-$arch"
384 rm -rf "$cache/rootfs-$arch"
385 fi
386
387 echo "Checking cache download in $cache/rootfs-$arch ... "
388 if [ ! -e "$cache/rootfs-$arch" ]; then
389 download_ubuntu $cache $arch $release
390 if [ $? -ne 0 ]; then
391 echo "Failed to download 'ubuntu $release base'"
392 return 1
393 fi
394 fi
395
396 echo "Copy $cache/rootfs-$arch to $rootfs ... "
397 copy_ubuntu $cache $arch $rootfs
398 if [ $? -ne 0 ]; then
399 echo "Failed to copy rootfs"
400 return 1
401 fi
402
403 return 0
404
405 ) 9>$LOCALSTATEDIR/lock/subsys/lxc-ubuntu$release
406
407 return $?
408 }
409
410 copy_configuration()
411 {
412 path=$1
413 rootfs=$2
414 name=$3
415 arch=$4
416 release=$5
417
418 if [ $arch = "i386" ]; then
419 arch="i686"
420 fi
421
422 # if there is exactly one veth network entry, make sure it has an
423 # associated hwaddr.
424 nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
425 if [ $nics -eq 1 ]; then
426 grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config
427 fi
428
429 # Generate the configuration file
430 ## Create the fstab (empty by default)
431 touch $path/fstab
432
433 ## Relocate all the network config entries
434 sed -i -e "/lxc.network/{w ${path}/config-network" -e "d}" $path/config
435
436 ## Relocate any other config entries
437 sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config
438
439 ## Add all the includes
440 echo "" >> $path/config
441 echo "# Common configuration" >> $path/config
442 if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" ]; then
443 echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" >> $path/config
444 fi
445 if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" ]; then
446 echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" >> $path/config
447 fi
448
449 ## Add the container-specific config
450 echo "" >> $path/config
451 echo "# Container specific configuration" >> $path/config
452 [ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto
453 grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
454 cat <<EOF >> $path/config
455 lxc.mount = $path/fstab
456 lxc.utsname = $name
457 lxc.arch = $arch
458 EOF
459
460 ## Re-add the previously removed network config
461 echo "" >> $path/config
462 echo "# Network configuration" >> $path/config
463 cat $path/config-network >> $path/config
464 rm $path/config-network
465
466 if [ $? -ne 0 ]; then
467 echo "Failed to add configuration"
468 return 1
469 fi
470
471 return 0
472 }
473
474 post_process()
475 {
476 rootfs=$1
477 release=$2
478 packages=$3
479
480 # Disable service startup
481 cat > $rootfs/usr/sbin/policy-rc.d << EOF
482 #!/bin/sh
483 exit 101
484 EOF
485 chmod +x $rootfs/usr/sbin/policy-rc.d
486
487 if [ ! -f $rootfs/etc/init/container-detect.conf ]; then
488 # Make sure we have a working resolv.conf
489 cresolvonf="${rootfs}/etc/resolv.conf"
490 mv $cresolvonf ${cresolvonf}.lxcbak
491 cat /etc/resolv.conf > ${cresolvonf}
492
493 # for lucid, if not trimming, then add the ubuntu-virt
494 # ppa and install lxcguest
495 if [ $release = "lucid" ]; then
496 chroot $rootfs apt-get update
497 install_packages $rootfs "python-software-properties"
498 chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa
499 fi
500
501 chroot $rootfs apt-get update
502 chroot $rootfs apt-get install --force-yes -y lxcguest
503
504 # Restore old resolv.conf
505 rm -f ${cresolvonf}
506 mv ${cresolvonf}.lxcbak ${cresolvonf}
507 fi
508
509 # If the container isn't running a native architecture, setup multiarch
510 if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then
511 dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg)
512 if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then
513 chroot $rootfs dpkg --add-architecture ${hostarch}
514 else
515 mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
516 echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
517 fi
518
519 # Save existing value of MIRROR and SECURITY_MIRROR
520 DEFAULT_MIRROR=$MIRROR
521 DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR
522
523 # Write a new sources.list containing both native and multiarch entries
524 > ${rootfs}/etc/apt/sources.list
525 write_sourceslist $rootfs $arch "native"
526
527 MIRROR=$DEFAULT_MIRROR
528 SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR
529 write_sourceslist $rootfs $hostarch "multiarch"
530
531 # Finally update the lists and install upstart using the host architecture
532 HOST_PACKAGES="upstart:${hostarch} mountall:${hostarch} isc-dhcp-client:${hostarch}"
533 chroot $rootfs apt-get update
534 if chroot $rootfs dpkg -l iproute2 | grep -q ^ii; then
535 HOST_PACKAGES="$HOST_PACKAGES iproute2:${hostarch}"
536 else
537 HOST_PACKAGES="$HOST_PACKAGES iproute:${hostarch}"
538 fi
539 install_packages $rootfs $HOST_PACKAGES
540 fi
541
542 # Install Packages in container
543 if [ -n "$packages" ]
544 then
545 local packages="`echo $packages | sed 's/,/ /g'`"
546 echo "Installing packages: ${packages}"
547 install_packages $rootfs $packages
548 fi
549
550 # Set initial timezone as on host
551 if [ -f /etc/timezone ]; then
552 cat /etc/timezone > $rootfs/etc/timezone
553 chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
554 elif [ -f /etc/sysconfig/clock ]; then
555 . /etc/sysconfig/clock
556 echo $ZONE > $rootfs/etc/timezone
557 chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
558 else
559 echo "Timezone in container is not configured. Adjust it manually."
560 fi
561
562 # rmdir /dev/shm for containers that have /run/shm
563 # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
564 # get bind mounted to the host's /run/shm. So try to rmdir
565 # it, and in case that fails move it out of the way.
566 # NOTE: This can only be removed once 12.04 goes out of support
567 if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then
568 rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak
569 ln -s /run/shm $rootfs/dev/shm
570 fi
571
572 # Re-enable service startup
573 rm $rootfs/usr/sbin/policy-rc.d
574 }
575
576 do_bindhome()
577 {
578 rootfs=$1
579 user=$2
580
581 # copy /etc/passwd, /etc/shadow, and /etc/group entries into container
582 pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; }
583 echo $pwd >> $rootfs/etc/passwd
584
585 # make sure user's shell exists in the container
586 shell=`echo $pwd | cut -d: -f 7`
587 if [ ! -x $rootfs/$shell ]; then
588 echo "shell $shell for user $user was not found in the container."
589 pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1`
590 echo "Installing $pkg"
591 install_packages $rootfs $pkg
592 fi
593
594 shad=`getent shadow $user`
595 echo "$shad" >> $rootfs/etc/shadow
596
597 # bind-mount the user's path into the container's /home
598 h=`getent passwd $user | cut -d: -f 6`
599 mkdir -p $rootfs/$h
600
601 # use relative path in container
602 h2=${h#/}
603 while [ ${h2:0:1} = "/" ]; do
604 h2=${h2#/}
605 done
606 echo "$h $h2 none bind 0 0" >> $path/fstab
607
608 # Make sure the group exists in container
609 grp=`echo $pwd | cut -d: -f 4` # group number for $user
610 grpe=`getent group $grp` || return 0 # if host doesn't define grp, ignore in container
611 chroot $rootfs getent group "$grpe" || echo "$grpe" >> $rootfs/etc/group
612 }
613
614 usage()
615 {
616 cat <<EOF
617 $1 -h|--help [-a|--arch] [-b|--bindhome <user>] [-d|--debug]
618 [-F | --flush-cache] [-r|--release <release>] [ -S | --auth-key <keyfile>]
619 [--rootfs <rootfs>] [--packages <packages>] [-u|--user <user>] [--password <password>]
620 release: the ubuntu release (e.g. precise): defaults to host release on ubuntu, otherwise uses latest LTS
621 bindhome: bind <user>'s home into the container
622 The ubuntu user will not be created, and <user> will have
623 sudo access.
624 arch: the container architecture (e.g. amd64): defaults to host arch
625 auth-key: SSH Public key file to inject into container
626 packages: list of packages to add comma separated
627 EOF
628 return 0
629 }
630
631 options=$(getopt -o a:b:hp:r:n:FS:du: -l arch:,bindhome:,help,path:,release:,name:,flush-cache,auth-key:,debug,rootfs:,packages:,user:,password:,mirror:,security-mirror: -- "$@")
632 if [ $? -ne 0 ]; then
633 usage $(basename $0)
634 exit 1
635 fi
636 eval set -- "$options"
637
638 release=precise # Default to the last Ubuntu LTS release for non-Ubuntu systems
639 if [ -f /etc/lsb-release ]; then
640 . /etc/lsb-release
641 if [ "$DISTRIB_ID" = "Ubuntu" ]; then
642 release=$DISTRIB_CODENAME
643 fi
644 fi
645
646 bindhome=
647
648 # Code taken from debootstrap
649 if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
650 arch=`/usr/bin/dpkg --print-architecture`
651 elif which udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
652 arch=`/usr/bin/udpkg --print-architecture`
653 else
654 arch=$(uname -m)
655 if [ "$arch" = "i686" ]; then
656 arch="i386"
657 elif [ "$arch" = "x86_64" ]; then
658 arch="amd64"
659 elif [ "$arch" = "armv7l" ]; then
660 arch="armhf"
661 fi
662 fi
663
664 debug=0
665 hostarch=$arch
666 flushcache=0
667 packages=""
668 user="ubuntu"
669 password="ubuntu"
670 while true
671 do
672 case "$1" in
673 -h|--help) usage $0 && exit 0;;
674 --rootfs) rootfs=$2; shift 2;;
675 -p|--path) path=$2; shift 2;;
676 -n|--name) name=$2; shift 2;;
677 -u|--user) user=$2; shift 2;;
678 --password) password=$2; shift 2;;
679 -F|--flush-cache) flushcache=1; shift 1;;
680 -r|--release) release=$2; shift 2;;
681 --packages) packages=$2; shift 2;;
682 -b|--bindhome) bindhome=$2; shift 2;;
683 -a|--arch) arch=$2; shift 2;;
684 -S|--auth-key) auth_key=$2; shift 2;;
685 -d|--debug) debug=1; shift 1;;
686 --mirror) MIRROR=$2; shift 2;;
687 --security-mirror) SECURITY_MIRROR=$2; shift 2;;
688 --) shift 1; break ;;
689 *) break ;;
690 esac
691 done
692
693 if [ $debug -eq 1 ]; then
694 set -x
695 fi
696
697 if [ -n "$bindhome" ]; then
698 pwd=`getent passwd $bindhome`
699 if [ $? -ne 0 ]; then
700 echo "Error: no password entry found for $bindhome"
701 exit 1
702 fi
703 fi
704
705
706 if [ "$arch" = "i686" ]; then
707 arch=i386
708 fi
709
710 if [ $hostarch = "i386" -a $arch = "amd64" ]; then
711 echo "can't create $arch container on $hostarch"
712 exit 1
713 fi
714
715 if [ $hostarch = "armhf" -o $hostarch = "armel" ] && \
716 [ $arch != "armhf" -a $arch != "armel" ]; then
717 echo "can't create $arch container on $hostarch"
718 exit 1
719 fi
720
721 if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then
722 echo "can't create $arch container on $hostarch"
723 exit 1
724 fi
725
726 which debootstrap >/dev/null 2>&1 || { echo "'debootstrap' command is missing" >&2; false; }
727
728 if [ -z "$path" ]; then
729 echo "'path' parameter is required"
730 exit 1
731 fi
732
733 if [ "$(id -u)" != "0" ]; then
734 echo "This script should be run as 'root'"
735 exit 1
736 fi
737
738 # detect rootfs
739 config="$path/config"
740 # if $rootfs exists here, it was passed in with --rootfs
741 if [ -z "$rootfs" ]; then
742 if grep -q '^lxc.rootfs' $config 2>/dev/null ; then
743 rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config)
744 else
745 rootfs=$path/rootfs
746 fi
747 fi
748
749 install_ubuntu $rootfs $release $flushcache
750 if [ $? -ne 0 ]; then
751 echo "failed to install ubuntu $release"
752 exit 1
753 fi
754
755 configure_ubuntu $rootfs $name $release $user $password
756 if [ $? -ne 0 ]; then
757 echo "failed to configure ubuntu $release for a container"
758 exit 1
759 fi
760
761 copy_configuration $path $rootfs $name $arch $release
762 if [ $? -ne 0 ]; then
763 echo "failed write configuration file"
764 exit 1
765 fi
766
767 post_process $rootfs $release $trim_container $packages
768
769 if [ -n "$bindhome" ]; then
770 do_bindhome $rootfs $bindhome
771 finalize_user $bindhome
772 else
773 finalize_user $user
774 fi
775
776 echo ""
777 echo "##"
778 if [ -n "$bindhome" ]; then
779 echo "# Log in as user $bindhome"
780 else
781 echo "# The default user is '$user' with password '$password'!"
782 echo "# Use the 'sudo' command to run tasks as root in the container."
783 fi
784 echo "##"
785 echo ""