Merge lp:~ubuntu-branches/ubuntu/precise/lxc/precise-201203021506 into lp:ubuntu/precise/lxc

Proposed by Ubuntu Package Importer
Status: Rejected
Rejected by: James Westby
Proposed branch: lp:~ubuntu-branches/ubuntu/precise/lxc/precise-201203021506
Merge into: lp:ubuntu/precise/lxc
Diff against target: 6272 lines (+6158/-0) (has conflicts)
16 files modified
.pc/0050-clone-lvm-sizes/src/lxc/lxc-clone.in (+247/-0)
.pc/0051-lxc-create-lvm-use-1G/src/lxc/lxc-create.in (+295/-0)
.pc/0052-ubuntu-bind-user-conflict/templates/lxc-ubuntu.in (+645/-0)
.pc/0053-lxc-start-pin-rootfs/src/lxc/conf.c (+1876/-0)
.pc/0053-lxc-start-pin-rootfs/src/lxc/conf.h (+233/-0)
.pc/0053-lxc-start-pin-rootfs/src/lxc/start.c (+748/-0)
.pc/0054-ubuntu-debug/templates/lxc-ubuntu-cloud.in (+304/-0)
.pc/0054-ubuntu-debug/templates/lxc-ubuntu.in (+665/-0)
.pc/0055-ubuntu-handle-badgrp/templates/lxc-ubuntu.in (+671/-0)
debian/lxc.postinst (+61/-0)
debian/patches/0050-clone-lvm-sizes (+34/-0)
debian/patches/0051-lxc-create-lvm-use-1G (+29/-0)
debian/patches/0052-ubuntu-bind-user-conflict (+95/-0)
debian/patches/0053-lxc-start-pin-rootfs (+110/-0)
debian/patches/0054-ubuntu-debug (+100/-0)
debian/patches/0055-ubuntu-handle-badgrp (+45/-0)
Conflict adding file .pc/0050-clone-lvm-sizes.  Moved existing file to .pc/0050-clone-lvm-sizes.moved.
Conflict adding file .pc/0051-lxc-create-lvm-use-1G.  Moved existing file to .pc/0051-lxc-create-lvm-use-1G.moved.
Conflict adding file .pc/0052-ubuntu-bind-user-conflict.  Moved existing file to .pc/0052-ubuntu-bind-user-conflict.moved.
Conflict adding file .pc/0053-lxc-start-pin-rootfs.  Moved existing file to .pc/0053-lxc-start-pin-rootfs.moved.
Conflict adding file .pc/0054-ubuntu-debug.  Moved existing file to .pc/0054-ubuntu-debug.moved.
Conflict adding file .pc/0055-ubuntu-handle-badgrp.  Moved existing file to .pc/0055-ubuntu-handle-badgrp.moved.
Conflict adding file debian/lxc.postinst.  Moved existing file to debian/lxc.postinst.moved.
Conflict adding file debian/patches/0050-clone-lvm-sizes.  Moved existing file to debian/patches/0050-clone-lvm-sizes.moved.
Conflict adding file debian/patches/0051-lxc-create-lvm-use-1G.  Moved existing file to debian/patches/0051-lxc-create-lvm-use-1G.moved.
Conflict adding file debian/patches/0052-ubuntu-bind-user-conflict.  Moved existing file to debian/patches/0052-ubuntu-bind-user-conflict.moved.
Conflict adding file debian/patches/0053-lxc-start-pin-rootfs.  Moved existing file to debian/patches/0053-lxc-start-pin-rootfs.moved.
Conflict adding file debian/patches/0054-ubuntu-debug.  Moved existing file to debian/patches/0054-ubuntu-debug.moved.
Conflict adding file debian/patches/0055-ubuntu-handle-badgrp.  Moved existing file to debian/patches/0055-ubuntu-handle-badgrp.moved.
To merge this branch: bzr merge lp:~ubuntu-branches/ubuntu/precise/lxc/precise-201203021506
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+95584@code.launchpad.net

Description of the change

The package importer has detected a possible inconsistency between the package history in the archive and the history in bzr. As the archive is authoritative the importer has made lp:ubuntu/precise/lxc reflect what is in the archive and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/precise/lxc/precise-201203021506. This merge proposal was created so that an Ubuntu developer can review the situations and perform a merge/upload if necessary. There are three typical cases where this can happen.
  1. Where someone pushes a change to bzr and someone else uploads the package without that change. This is the reason that this check is done by the importer. If this appears to be the case then a merge/upload should be done if the changes that were in bzr are still desirable.
  2. The importer incorrectly detected the above situation when someone made a change in bzr and then uploaded it.
  3. The importer incorrectly detected the above situation when someone just uploaded a package and didn't touch bzr.

If this case doesn't appear to be the first situation then set the status of the merge proposal to "Rejected" and help avoid the problem in future by filing a bug at https://bugs.launchpad.net/udd linking to this merge proposal.

(this is an automatically generated message)

To post a comment you must log in.

Unmerged revisions

78. By Serge Hallyn

* 0054-ubuntu-debug: add --debug option to ubuntu and ubuntu-cloud
  templates (LP: #942847)
* 0055-ubuntu-handle-badgrp: fix the group handling to not assume a user's
  group has the user's name. (LP: #942850)

77. By Serge Hallyn

get the rootfs pinning working

76. By Serge Hallyn

0053-lxc-start-pin-rootfs: don't let the container remount an underlying
shared fs readonly (LP: #942325)

75. By Serge Hallyn

fix some syntax errors

74. By Serge Hallyn

0052-ubuntu-bind-user-conflict: don't create 'ubuntu' user when a user
gets bound in. (LP: #942144)

73. By Serge Hallyn

mark patches which have been forwarded upstream as such

72. By Serge Hallyn

0051-lxc-create-lvm-use-1G: bump lvm blockdev size to 1G (LP: #942338)

71. By Serge Hallyn

add lxc-dnsmasq group and set homedir to /var/lib/lxc

70. By Serge Hallyn

* 0050-clone-lvm-sizes: make lxc-clone with lvm snapshots create a
  snapshot of the same size as the original. (LP: #939765)
* run our dnsmasq as user 'lxc-dnsmasq' (LP: #939774)
  - add debian/lxc.postinst to create the user
  - debian/lxc.lxc-net.upstart: run dnsmasq as lxc-dnsmasq user

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc/0050-clone-lvm-sizes'
2=== renamed directory '.pc/0050-clone-lvm-sizes' => '.pc/0050-clone-lvm-sizes.moved'
3=== added file '.pc/0050-clone-lvm-sizes/.timestamp'
4=== added directory '.pc/0050-clone-lvm-sizes/src'
5=== added directory '.pc/0050-clone-lvm-sizes/src/lxc'
6=== added file '.pc/0050-clone-lvm-sizes/src/lxc/lxc-clone.in'
7--- .pc/0050-clone-lvm-sizes/src/lxc/lxc-clone.in 1970-01-01 00:00:00 +0000
8+++ .pc/0050-clone-lvm-sizes/src/lxc/lxc-clone.in 2012-03-02 15:11:19 +0000
9@@ -0,0 +1,247 @@
10+#!/bin/bash
11+
12+#
13+# lxc: linux Container library
14+
15+# Authors:
16+# Serge Hallyn <serge.hallyn@ubuntu.com>
17+# Daniel Lezcano <daniel.lezcano@free.fr>
18+
19+# This library is free software; you can redistribute it and/or
20+# modify it under the terms of the GNU Lesser General Public
21+# License as published by the Free Software Foundation; either
22+# version 2.1 of the License, or (at your option) any later version.
23+
24+# This library is distributed in the hope that it will be useful,
25+# but WITHOUT ANY WARRANTY; without even the implied warranty of
26+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27+# Lesser General Public License for more details.
28+
29+# You should have received a copy of the GNU Lesser General Public
30+# License along with this library; if not, write to the Free Software
31+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32+
33+usage() {
34+ echo "usage: lxc-clone -o <orig> -n <new> [-s] [-h] [-L fssize] [-v vgname]"
35+}
36+
37+help() {
38+ usage
39+ echo
40+ echo "creates a lxc system object."
41+ echo
42+ echo "Options:"
43+ echo "orig : name of the original container"
44+ echo "new : name of the new container"
45+ echo "-s : make the new rootfs a snapshot of the original"
46+ echo "fssize : size if creating a new fs. By default, 2G"
47+ echo "vgname : lvm volume group name, lxc by default"
48+}
49+
50+shortoptions='ho:n:sL:v:'
51+longoptions='help,orig:,name:,snapshot,fssize,vgname'
52+lxc_path=/var/lib/lxc
53+bindir=/usr/bin
54+snapshot=no
55+lxc_size=2G
56+lxc_vg=lxc
57+
58+getopt=$(getopt -o $shortoptions --longoptions $longoptions -- "$@")
59+if [ $? != 0 ]; then
60+ usage
61+ exit 1;
62+fi
63+
64+eval set -- "$getopt"
65+
66+while true; do
67+ case "$1" in
68+ -h|--help)
69+ help
70+ exit 1
71+ ;;
72+ -s|--snapshot)
73+ shift
74+ snapshot=yes
75+ ;;
76+ -o|--orig)
77+ shift
78+ lxc_orig=$1
79+ shift
80+ ;;
81+ -L|--fssize)
82+ shift
83+ lxc_size=$1
84+ shift
85+ ;;
86+ -v|--vgname)
87+ shift
88+ lxc_vg=$1
89+ shift
90+ ;;
91+ -n|--new)
92+ shift
93+ lxc_new=$1
94+ shift
95+ ;;
96+ --)
97+ shift
98+ break;;
99+ *)
100+ echo $1
101+ usage
102+ exit 1
103+ ;;
104+ esac
105+done
106+
107+if [ -z "$lxc_path" ]; then
108+ echo "no configuration path defined !"
109+ exit 1
110+fi
111+
112+if [ ! -r $lxc_path ]; then
113+ echo "configuration path '$lxc_path' not found"
114+ exit 1
115+fi
116+
117+if [ -z "$lxc_orig" ]; then
118+ echo "no original container name specified"
119+ usage
120+ exit 1
121+fi
122+
123+if [ -z "$lxc_new" ]; then
124+ echo "no new container name specified"
125+ usage
126+ exit 1
127+fi
128+
129+if [ "$(id -u)" != "0" ]; then
130+ echo "This command has to be run as root"
131+ exit 1
132+fi
133+
134+if [ ! -r $lxc_path ]; then
135+ echo "no configuration path defined !"
136+ exit 1
137+fi
138+
139+if [ ! -d "$lxc_path/$lxc_orig" ]; then
140+ echo "'$lxc_orig' does not exist"
141+ exit 1
142+fi
143+
144+if [ -d "$lxc_path/$lxc_new" ]; then
145+ echo "'$lxc_new' already exists"
146+ exit 1
147+fi
148+
149+hostname=$lxc_new
150+mkdir -p $lxc_path/$lxc_new
151+
152+echo "Tweaking configuration"
153+cp $lxc_path/$lxc_orig/config $lxc_path/$lxc_new/config
154+sed -i '/lxc.utsname/d' $lxc_path/$lxc_new/config
155+echo "lxc.utsname = $hostname" >> $lxc_path/$lxc_new/config
156+
157+sed -i '/lxc.mount/d' $lxc_path/$lxc_new/config
158+echo "lxc.mount = $lxc_path/$lxc_new/fstab" >> $lxc_path/$lxc_new/config
159+
160+cp $lxc_path/$lxc_orig/fstab $lxc_path/$lxc_new/fstab
161+sed -i "s@$lxc_path/$lxc_orig@$lxc_path/$lxc_new@" $lxc_path/$lxc_new/fstab
162+
163+rootfs=$lxc_path/$lxc_new/rootfs
164+# First figure out if the old is a device. For now we only support
165+# lvm devices.
166+mounted=0
167+sed -i '/lxc.rootfs/d' $lxc_path/$lxc_new/config
168+oldroot=`grep lxc.rootfs $lxc_path/$lxc_orig/config | awk -F= '{ print $2 '}`
169+
170+cleanup() {
171+ if [ -b $oldroot ]; then
172+ if [ $mounted -eq 1 ]; then
173+ umount $rootfs
174+ fi
175+ lvremove -f $rootdev
176+ fi
177+ ${bindir}/lxc-destroy -n $lxc_new
178+ echo aborted
179+ exit 1
180+}
181+trap cleanup SIGHUP SIGINT SIGTERM
182+
183+echo "Copying rootfs..."
184+if [ -b $oldroot ]; then
185+ which vgscan > /dev/null
186+ if [ $? -ne 0 ]; then
187+ echo "vgscan not found. Please install lvm2 package"
188+ exit 1
189+ fi
190+
191+ # this is a device. If we don't want to snapshot, then mkfs, mount
192+ # and rsync. Trivial but not yet implemented
193+ if [ $snapshot == "no" ]; then
194+ echo "non-snapshot and non-lvm clone of block device not yet implemented"
195+ exit 1
196+ fi
197+ lvdisplay $oldroot > /dev/null 2>&1
198+ if [ $? -ne 0 ]; then
199+ echo "non-snapshot and non-lvm clone of block device not yet implemented"
200+ exit 1
201+ fi
202+ # ok, create a snapshot of the lvm device
203+ lvcreate -s -L $lxc_size -n $lxc_new /dev/$lxc_vg/$lxc_orig || cleanup
204+ echo "lxc.rootfs = /dev/$lxc_vg/$lxc_new" >> $lxc_path/$lxc_new/config
205+ # and mount it so we can tweak it
206+ mkdir -p $lxc_path/$lxc_new/rootfs
207+ mount /dev/$lxc_vg/$lxc_new $rootfs || { echo "failed to mount new rootfs"; cleanup; }
208+ mounted=1
209+elif out=$(btrfs subvolume list "$lxc_path/$lxc_orig/rootfs" 2>&1); then
210+ out=$(btrfs subvolume snapshot "$lxc_path/$lxc_orig/rootfs" "$rootfs" 2>&1)
211+ if [ $? -ne 0 ]; then
212+ echo "failed btrfs subvolume snapshot of $lxc_path/$lxc_orig/rootfs"
213+ cleanup
214+ fi
215+ echo "lxc.rootfs = $rootfs" >> "$lxc_path/$lxc_new/config"
216+else
217+ cp -a $lxc_path/$lxc_orig/rootfs $lxc_path/$lxc_new/rootfs || cleanup
218+ echo "lxc.rootfs = $rootfs" >> $lxc_path/$lxc_new/config
219+fi
220+
221+echo "Updating rootfs..."
222+
223+# so you can 'ssh $hostname.' or 'ssh $hostname.local'
224+if [ -f $rootfs/etc/dhcp/dhclient.conf ]; then
225+ sed -i "s/send host-name.*$/send host-name $hostname;/" $rootfs/etc/dhcp/dhclient.conf
226+fi
227+
228+c=$lxc_path/$lxc_new/config
229+# change hwaddrs
230+mv ${c} ${c}.old
231+(
232+while read line; do
233+ if [ "${line:0:18}" = "lxc.network.hwaddr" ]; then
234+ echo "lxc.network.hwaddr= 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')"
235+ else
236+ echo $line
237+ fi
238+done
239+) < ${c}.old > ${c}
240+rm -f ${c}.old
241+
242+# set the hostname
243+cat <<EOF > $rootfs/etc/hostname
244+$hostname
245+EOF
246+# set minimal hosts
247+cat <<EOF > $rootfs/etc/hosts
248+127.0.0.1 localhost $hostname
249+EOF
250+
251+# if this was a block device, then umount it now
252+if [ $mounted -eq 1 ]; then
253+ umount $rootfs
254+fi
255+
256+echo "'$lxc_new' created"
257
258=== added directory '.pc/0051-lxc-create-lvm-use-1G'
259=== renamed directory '.pc/0051-lxc-create-lvm-use-1G' => '.pc/0051-lxc-create-lvm-use-1G.moved'
260=== added file '.pc/0051-lxc-create-lvm-use-1G/.timestamp'
261=== added directory '.pc/0051-lxc-create-lvm-use-1G/src'
262=== added directory '.pc/0051-lxc-create-lvm-use-1G/src/lxc'
263=== added file '.pc/0051-lxc-create-lvm-use-1G/src/lxc/lxc-create.in'
264--- .pc/0051-lxc-create-lvm-use-1G/src/lxc/lxc-create.in 1970-01-01 00:00:00 +0000
265+++ .pc/0051-lxc-create-lvm-use-1G/src/lxc/lxc-create.in 2012-03-02 15:11:19 +0000
266@@ -0,0 +1,295 @@
267+#!/bin/bash
268+
269+#
270+# lxc: linux Container library
271+
272+# Authors:
273+# Daniel Lezcano <daniel.lezcano@free.fr>
274+
275+# This library is free software; you can redistribute it and/or
276+# modify it under the terms of the GNU Lesser General Public
277+# License as published by the Free Software Foundation; either
278+# version 2.1 of the License, or (at your option) any later version.
279+
280+# This library is distributed in the hope that it will be useful,
281+# but WITHOUT ANY WARRANTY; without even the implied warranty of
282+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
283+# Lesser General Public License for more details.
284+
285+# You should have received a copy of the GNU Lesser General Public
286+# License along with this library; if not, write to the Free Software
287+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
288+
289+usage() {
290+ echo "usage: lxc-create -n <name> [-f configuration] [-t template] [-h] -- [template_options]"
291+ echo "usage: lxc-create -n <name> [-f configuration] [-t template] [-h] [fsopts] -- [template_options]"
292+ echo " fsopts: -B none"
293+ echo " fsopts: -B lvm [--lvname lvname] [--vgname vgname] [--fstype fstype] [--fssize fssize]"
294+ echo " fsopts: -B btrfs"
295+ echo " flag is not necessary, if possible btrfs support will be used"
296+# echo " fsopts: -B union [--uniontype overlayfs]"
297+# echo " fsopts: -B loop [--fstype fstype] [--fssize fssize]"
298+# echo " fsopts: -B qemu-nbd [--type qed|qcow2|raw] [--fstype fstype] [--fssize fssize] # Qemu qed disk format"
299+}
300+
301+
302+help() {
303+ usage
304+ echo
305+ echo "creates a lxc system object."
306+ echo
307+ echo "Options:"
308+ echo "name : name of the container"
309+ echo "configuration: lxc configuration"
310+ echo "template : lxc-template is an accessible template script"
311+ echo
312+ echo "The container backing store can be altered using '-B'. By default it"
313+ echo "is 'none', which is a simple directory tree under /var/lib/lxc/<name>/rootfs"
314+ echo "Otherwise, the following option values may be relevant:"
315+ echo "lvname : [for -lvm] name of lv in which to create lv,"
316+ echo " container-name by default"
317+ echo "vgname : [for -lvm] name of vg in which to create lv, 'lxc' by default"
318+ echo "fstype : name of filesystem to create, ext4 by default"
319+ echo "fssize : size of filesystem to create, 500M by default"
320+ if [ -z $lxc_template ]; then
321+ echo "for template-specific help, specify a template, for instance:"
322+ echo "lxc-create -t ubuntu -h"
323+ exit 0
324+ fi
325+ type ${templatedir}/lxc-$lxc_template >/dev/null
326+ echo
327+ echo "template-specific help follows: (these options follow '--')"
328+ if [ $? -eq 0 ]; then
329+ ${templatedir}/lxc-$lxc_template -h
330+ fi
331+}
332+
333+shortoptions='hn:f:t:B:'
334+longoptions='help,name:,config:,template:,backingstore:,fstype:,lvname:,vgname:,fssize:'
335+lxc_path=@LXCPATH@
336+bindir=@BINDIR@
337+templatedir=@LXCTEMPLATEDIR@
338+backingstore=_unset
339+fstype=ext4
340+fssize=500M
341+vgname=lxc
342+
343+getopt=$(getopt -o $shortoptions --longoptions $longoptions -- "$@")
344+if [ $? != 0 ]; then
345+ usage
346+ exit 1;
347+fi
348+
349+eval set -- "$getopt"
350+
351+while true; do
352+ case "$1" in
353+ -h|--help)
354+ help
355+ exit 1
356+ ;;
357+ -n|--name)
358+ shift
359+ lxc_name=$1
360+ shift
361+ ;;
362+ -f|--config)
363+ shift
364+ lxc_config=$1
365+ shift
366+ ;;
367+ -t|--template)
368+ shift
369+ lxc_template=$1
370+ shift
371+ ;;
372+ -B|--backingstore)
373+ shift
374+ backingstore=$1
375+ shift
376+ ;;
377+ --lvname)
378+ shift
379+ lvname=$1
380+ shift
381+ ;;
382+ --vgname)
383+ shift
384+ vgname=$1
385+ shift
386+ ;;
387+ --fstype)
388+ shift
389+ fstype=$1
390+ shift
391+ ;;
392+ --fssize)
393+ shift
394+ fssize=$1
395+ shift
396+ ;;
397+ --)
398+ shift
399+ break;;
400+ *)
401+ echo $1
402+ usage
403+ exit 1
404+ ;;
405+ esac
406+done
407+
408+if [ -z "$lxc_path" ]; then
409+ echo "no configuration path defined !"
410+ exit 1
411+fi
412+
413+if [ ! -r $lxc_path ]; then
414+ echo "configuration path '$lxc_path' not found"
415+ exit 1
416+fi
417+
418+if [ -z "$lxc_name" ]; then
419+ echo "no container name specified"
420+ usage
421+ exit 1
422+fi
423+
424+if [ -z "$lvname" ]; then
425+ lvname="$lxc_name"
426+fi
427+
428+if [ "$(id -u)" != "0" ]; then
429+ echo "This command has to be run as root"
430+ exit 1
431+fi
432+
433+case "$backingstore" in
434+ lvm|none|btrfs|_unset) :;;
435+ *) echo "'$backingstore' is not known ('none', 'lvm', 'btrfs')"
436+ usage
437+ exit 1
438+ ;;
439+esac
440+
441+if [ -d "$lxc_path/$lxc_name" ]; then
442+ echo "'$lxc_name' already exists"
443+ exit 1
444+fi
445+
446+rootfs="$lxc_path/$lxc_name/rootfs"
447+
448+if [ "$backingstore" = "_unset" -o "$backingstore" = "btrfs" ]; then
449+ # if no backing store was given, then see if btrfs would work
450+ if which btrfs >/dev/null 2>&1 &&
451+ btrfs filesystem df "$lxc_path/" >/dev/null 2>&1; then
452+ backingstore="btrfs"
453+ else
454+ if [ "$backingstore" = "btrfs" ]; then
455+ echo "missing 'btrfs' command or $lxc_path is not btrfs";
456+ exit 1;
457+ fi
458+ backingstore="none"
459+ fi
460+fi
461+
462+if [ $backingstore = "lvm" ]; then
463+ which vgscan > /dev/null
464+ if [ $? -ne 0 ]; then
465+ echo "vgscan not found. Please install lvm2 package"
466+ exit 1
467+ fi
468+ grep -q "\<$fstype\>" /proc/filesystems
469+ if [ $? -ne 0 ]; then
470+ echo "$fstype is not listed in /proc/filesystems"
471+ usage
472+ exit 1
473+ fi
474+
475+ vgscan | grep -q "Found volume group \"$vgname\""
476+ if [ $? -ne 0 ]; then
477+ echo "Could not find volume group \"$vgname\""
478+ usage
479+ exit 1
480+ fi
481+
482+ rootdev=/dev/$vgname/$lvname
483+ lvdisplay $rootdev > /dev/null 2>&1
484+ if [ $? -eq 0 ]; then
485+ echo "backing store already exists: $rootdev"
486+ echo "please delete it (using \"lvremove $rootdev\") and try again"
487+ exit 1
488+ fi
489+elif [ "$backingstore" = "btrfs" ]; then
490+ mkdir "$lxc_path/$lxc_name"
491+ if ! out=$(btrfs subvolume create "$rootfs" 2>&1); then
492+ echo "failed to create subvolume in $rootfs: $out";
493+ exit 1;
494+ fi
495+fi
496+
497+cleanup() {
498+ if [ $backingstore = "lvm" ]; then
499+ umount $rootfs
500+ lvremove -f $rootdev
501+ fi
502+ ${bindir}/lxc-destroy -n $lxc_name
503+ echo aborted
504+ exit 1
505+}
506+
507+trap cleanup SIGHUP SIGINT SIGTERM
508+
509+mkdir -p $lxc_path/$lxc_name
510+
511+if [ -z "$lxc_config" ]; then
512+ echo
513+ echo "No config file specified, using the default config"
514+ lxc_config="/etc/lxc/lxc.conf"
515+fi
516+
517+if [ ! -r "$lxc_config" ]; then
518+ echo "'$lxc_config' configuration file not found"
519+ exit 1
520+fi
521+
522+cp $lxc_config $lxc_path/$lxc_name/config
523+
524+# Create the fs as needed
525+[ -d "$rootfs" ] || mkdir "$rootfs"
526+if [ $backingstore = "lvm" ]; then
527+ lvcreate -L $fssize -n $lvname $vgname || exit 1
528+ udevadm settle
529+ mkfs -t $fstype $rootdev || exit 1
530+ mount -t $fstype $rootdev $rootfs
531+fi
532+
533+
534+if [ ! -z $lxc_template ]; then
535+
536+ type ${templatedir}/lxc-$lxc_template >/dev/null
537+ if [ $? -ne 0 ]; then
538+ echo "unknown template '$lxc_template'"
539+ cleanup
540+ fi
541+
542+ ${templatedir}/lxc-$lxc_template --path=$lxc_path/$lxc_name --name=$lxc_name $*
543+ if [ $? -ne 0 ]; then
544+ echo "failed to execute template '$lxc_template'"
545+ cleanup
546+ fi
547+
548+ echo "'$lxc_template' template installed"
549+fi
550+
551+if [ $backingstore = "lvm" ]; then
552+ echo "Unmounting LVM"
553+ umount $rootfs
554+
555+ # TODO: make the templates set this right from the start
556+ sed -i '/lxc.rootfs/d' $lxc_path/$lxc_name/config
557+ echo "lxc.rootfs = $rootdev" >> $lxc_path/$lxc_name/config
558+fi
559+
560+
561+echo "'$lxc_name' created"
562
563=== added directory '.pc/0052-ubuntu-bind-user-conflict'
564=== renamed directory '.pc/0052-ubuntu-bind-user-conflict' => '.pc/0052-ubuntu-bind-user-conflict.moved'
565=== added file '.pc/0052-ubuntu-bind-user-conflict/.timestamp'
566=== added directory '.pc/0052-ubuntu-bind-user-conflict/templates'
567=== added file '.pc/0052-ubuntu-bind-user-conflict/templates/lxc-ubuntu.in'
568--- .pc/0052-ubuntu-bind-user-conflict/templates/lxc-ubuntu.in 1970-01-01 00:00:00 +0000
569+++ .pc/0052-ubuntu-bind-user-conflict/templates/lxc-ubuntu.in 2012-03-02 15:11:19 +0000
570@@ -0,0 +1,645 @@
571+#!/bin/bash
572+
573+#
574+# template script for generating ubuntu container for LXC
575+#
576+# This script consolidates and extends the existing lxc ubuntu scripts
577+#
578+
579+# Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
580+# Copyright © 2010 Wilhelm Meier
581+# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
582+#
583+# This program is free software; you can redistribute it and/or modify
584+# it under the terms of the GNU General Public License version 2, as
585+# published by the Free Software Foundation.
586+
587+# This program is distributed in the hope that it will be useful,
588+# but WITHOUT ANY WARRANTY; without even the implied warranty of
589+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
590+# GNU General Public License for more details.
591+
592+# You should have received a copy of the GNU General Public License along
593+# with this program; if not, write to the Free Software Foundation, Inc.,
594+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
595+#
596+
597+set -e
598+
599+if [ -r /etc/default/lxc ]; then
600+ . /etc/default/lxc
601+fi
602+
603+configure_ubuntu()
604+{
605+ rootfs=$1
606+ hostname=$2
607+ release=$3
608+
609+ # configure the network using the dhcp
610+ cat <<EOF > $rootfs/etc/network/interfaces
611+auto lo
612+iface lo inet loopback
613+
614+auto eth0
615+iface eth0 inet dhcp
616+EOF
617+
618+ # set the hostname
619+ cat <<EOF > $rootfs/etc/hostname
620+$hostname
621+EOF
622+ # set minimal hosts
623+ cat <<EOF > $rootfs/etc/hosts
624+127.0.0.1 localhost $hostname
625+EOF
626+
627+ if [ "$release" = "precise" ]; then
628+ groups="sudo"
629+ else
630+ groups="sudo admin"
631+
632+ # suppress log level output for udev
633+ sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
634+
635+ # remove jobs for consoles 5 and 6 since we only create 4 consoles in
636+ # this template
637+ rm -f $rootfs/etc/init/tty{5,6}.conf
638+ fi
639+
640+ chroot $rootfs useradd --create-home -s /bin/bash ubuntu
641+ echo "ubuntu:ubuntu" | chroot $rootfs chpasswd
642+
643+ for group in $groups; do
644+ chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true
645+ chroot $rootfs adduser ubuntu $group >/dev/null 2>&1 || true
646+ done
647+
648+ if [ -n "$auth_key" -a -f "$auth_key" ]; then
649+ u_path="/home/ubuntu/.ssh"
650+ root_u_path="$rootfs/$u_path"
651+ mkdir -p $root_u_path
652+ cp $auth_key "$root_u_path/authorized_keys"
653+ chroot $rootfs chown -R ubuntu: "$u_path"
654+
655+ echo "Inserted SSH public key from $auth_key into /home/ubuntu/.ssh/authorized_keys"
656+ fi
657+ return 0
658+}
659+
660+write_sourceslist()
661+{
662+ # $1 => path to the rootfs
663+ # $2 => architecture we want to add
664+ # $3 => whether to use the multi-arch syntax or not
665+
666+ case $2 in
667+ amd64|i386)
668+ MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
669+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu}
670+ ;;
671+ sparc)
672+ case $SUITE in
673+ gutsy)
674+ MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
675+ SECURITY_MIRROR=${SECURITY_MIRRORMIRROR:-http://security.ubuntu.com/ubuntu}
676+ ;;
677+ *)
678+ MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
679+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
680+ ;;
681+ esac
682+ ;;
683+ *)
684+ MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
685+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
686+ ;;
687+ esac
688+ if [ -n "$3" ]; then
689+ cat >> "$1/etc/apt/sources.list" << EOF
690+deb [arch=$2] $MIRROR ${release} main restricted universe multiverse
691+deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse
692+deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse
693+EOF
694+ else
695+ cat >> "$1/etc/apt/sources.list" << EOF
696+deb $MIRROR ${release} main restricted universe multiverse
697+deb $MIRROR ${release}-updates main restricted universe multiverse
698+deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse
699+EOF
700+ fi
701+}
702+
703+download_ubuntu()
704+{
705+ cache=$1
706+ arch=$2
707+ release=$3
708+
709+ if [ $release = "lucid" ]; then
710+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,dhcp3-client,ssh,lsb-release,gnupg
711+ elif [ $release = "maverick" ]; then
712+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,dhcp3-client,ssh,lsb-release,gnupg,netbase
713+ elif [ $release = "natty" ]; then
714+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,isc-dhcp-client,isc-dhcp-common,ssh,lsb-release,gnupg,netbase
715+ else
716+ packages=dialog,apt,apt-utils,iproute,inetutils-ping,vim,isc-dhcp-client,isc-dhcp-common,ssh,lsb-release,gnupg,netbase,ubuntu-keyring
717+ fi
718+ echo "installing packages: $packages"
719+
720+ # check the mini ubuntu was not already downloaded
721+ mkdir -p "$cache/partial-$arch"
722+ if [ $? -ne 0 ]; then
723+ echo "Failed to create '$cache/partial-$arch' directory"
724+ return 1
725+ fi
726+
727+ # download a mini ubuntu into a cache
728+ echo "Downloading ubuntu $release minimal ..."
729+ if [ -n "$(which qemu-debootstrap)" ]; then
730+ qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
731+ else
732+ debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
733+ fi
734+
735+ if [ $? -ne 0 ]; then
736+ echo "Failed to download the rootfs, aborting."
737+ return 1
738+ fi
739+
740+ # Serge isn't sure whether we should avoid doing this when
741+ # $release == `distro-info -d`
742+ echo "Installing updates"
743+ > $cache/partial-$arch/etc/apt/sources.list
744+ write_sourceslist $cache/partial-$arch/ $arch
745+
746+ chroot "$1/partial-${arch}" apt-get update
747+ if [ $? -ne 0 ]; then
748+ echo "Failed to update the apt cache"
749+ return 1
750+ fi
751+ cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF
752+#!/bin/sh
753+exit 101
754+EOF
755+ chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
756+
757+ lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y
758+ ret=$?
759+ rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
760+
761+ if [ $ret -ne 0 ]; then
762+ echo "Failed to upgrade the cache"
763+ return 1
764+ fi
765+
766+ mv "$1/partial-$arch" "$1/rootfs-$arch"
767+ echo "Download complete"
768+ return 0
769+}
770+
771+copy_ubuntu()
772+{
773+ cache=$1
774+ arch=$2
775+ rootfs=$3
776+
777+ # make a local copy of the miniubuntu
778+ echo "Copying rootfs to $rootfs ..."
779+ mkdir -p $rootfs
780+ rsync -a $cache/rootfs-$arch/ $rootfs/ || return 1
781+ return 0
782+}
783+
784+install_ubuntu()
785+{
786+ rootfs=$1
787+ release=$2
788+ flushcache=$3
789+ cache="/var/cache/lxc/$release"
790+ mkdir -p /var/lock/subsys/
791+ (
792+ flock -n -x 200
793+ if [ $? -ne 0 ]; then
794+ echo "Cache repository is busy."
795+ return 1
796+ fi
797+
798+
799+ if [ $flushcache -eq 1 ]; then
800+ echo "Flushing cache..."
801+ rm -rf "$cache/partial-$arch"
802+ rm -rf "$cache/rootfs-$arch"
803+ fi
804+
805+ echo "Checking cache download in $cache/rootfs-$arch ... "
806+ if [ ! -e "$cache/rootfs-$arch" ]; then
807+ download_ubuntu $cache $arch $release
808+ if [ $? -ne 0 ]; then
809+ echo "Failed to download 'ubuntu $release base'"
810+ return 1
811+ fi
812+ fi
813+
814+ echo "Copy $cache/rootfs-$arch to $rootfs ... "
815+ copy_ubuntu $cache $arch $rootfs
816+ if [ $? -ne 0 ]; then
817+ echo "Failed to copy rootfs"
818+ return 1
819+ fi
820+
821+ return 0
822+
823+ ) 200>/var/lock/subsys/lxc
824+
825+ return $?
826+}
827+
828+copy_configuration()
829+{
830+ path=$1
831+ rootfs=$2
832+ name=$3
833+ arch=$4
834+ release=$5
835+
836+ if [ $arch = "i386" ]; then
837+ arch="i686"
838+ fi
839+
840+ ttydir=""
841+ if [ $release = "precise" ]; then
842+ ttydir=" lxc"
843+ fi
844+
845+ # if there is exactly one veth network entry, make sure it has an
846+ # associated hwaddr.
847+ nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
848+ if [ $nics -eq 1 ]; then
849+ grep -q "^lxc.network.hwaddr" $path/config || cat <<EOF >> $path/config
850+lxc.network.hwaddr= 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')
851+EOF
852+ fi
853+
854+ cat <<EOF >> $path/config
855+lxc.utsname = $name
856+
857+lxc.devttydir =$ttydir
858+lxc.tty = 4
859+lxc.pts = 1024
860+lxc.rootfs = $rootfs
861+lxc.mount = $path/fstab
862+lxc.arch = $arch
863+lxc.cap.drop = sys_module mac_admin
864+
865+lxc.cgroup.devices.deny = a
866+# Allow any mknod (but not using the node)
867+lxc.cgroup.devices.allow = c *:* m
868+lxc.cgroup.devices.allow = b *:* m
869+# /dev/null and zero
870+lxc.cgroup.devices.allow = c 1:3 rwm
871+lxc.cgroup.devices.allow = c 1:5 rwm
872+# consoles
873+lxc.cgroup.devices.allow = c 5:1 rwm
874+lxc.cgroup.devices.allow = c 5:0 rwm
875+#lxc.cgroup.devices.allow = c 4:0 rwm
876+#lxc.cgroup.devices.allow = c 4:1 rwm
877+# /dev/{,u}random
878+lxc.cgroup.devices.allow = c 1:9 rwm
879+lxc.cgroup.devices.allow = c 1:8 rwm
880+lxc.cgroup.devices.allow = c 136:* rwm
881+lxc.cgroup.devices.allow = c 5:2 rwm
882+# rtc
883+lxc.cgroup.devices.allow = c 254:0 rwm
884+#fuse
885+lxc.cgroup.devices.allow = c 10:229 rwm
886+#tun
887+lxc.cgroup.devices.allow = c 10:200 rwm
888+#full
889+lxc.cgroup.devices.allow = c 1:7 rwm
890+#hpet
891+lxc.cgroup.devices.allow = c 10:228 rwm
892+#kvm
893+lxc.cgroup.devices.allow = c 10:232 rwm
894+EOF
895+
896+ cat <<EOF > $path/fstab
897+proc $rootfs/proc proc nodev,noexec,nosuid 0 0
898+sysfs $rootfs/sys sysfs defaults 0 0
899+EOF
900+
901+ if [ $? -ne 0 ]; then
902+ echo "Failed to add configuration"
903+ return 1
904+ fi
905+
906+ return 0
907+}
908+
909+trim()
910+{
911+ rootfs=$1
912+ release=$2
913+
914+ # provide the lxc service
915+ cat <<EOF > $rootfs/etc/init/lxc.conf
916+# fake some events needed for correct startup other services
917+
918+description "Container Upstart"
919+
920+start on startup
921+
922+script
923+ rm -rf /var/run/*.pid
924+ rm -rf /var/run/network/*
925+ /sbin/initctl emit stopped JOB=udevtrigger --no-wait
926+ /sbin/initctl emit started JOB=udev --no-wait
927+end script
928+EOF
929+
930+ # fix buggus runlevel with sshd
931+ cat <<EOF > $rootfs/etc/init/ssh.conf
932+# ssh - OpenBSD Secure Shell server
933+#
934+# The OpenSSH server provides secure shell access to the system.
935+
936+description "OpenSSH server"
937+
938+start on filesystem
939+stop on runlevel [!2345]
940+
941+expect fork
942+respawn
943+respawn limit 10 5
944+umask 022
945+# replaces SSHD_OOM_ADJUST in /etc/default/ssh
946+oom never
947+
948+pre-start script
949+ test -x /usr/sbin/sshd || { stop; exit 0; }
950+ test -e /etc/ssh/sshd_not_to_be_run && { stop; exit 0; }
951+ test -c /dev/null || { stop; exit 0; }
952+
953+ mkdir -p -m0755 /var/run/sshd
954+end script
955+
956+# if you used to set SSHD_OPTS in /etc/default/ssh, you can change the
957+# 'exec' line here instead
958+exec /usr/sbin/sshd
959+EOF
960+
961+ cat <<EOF > $rootfs/etc/init/console.conf
962+# console - getty
963+#
964+# This service maintains a console on tty1 from the point the system is
965+# started until it is shut down again.
966+
967+start on stopped rc RUNLEVEL=[2345]
968+stop on runlevel [!2345]
969+
970+respawn
971+exec /sbin/getty -8 38400 /dev/console
972+EOF
973+
974+ cat <<EOF > $rootfs/lib/init/fstab
975+# /lib/init/fstab: cleared out for bare-bones lxc
976+EOF
977+
978+ # reconfigure some services
979+ if [ -z "$LANG" ]; then
980+ chroot $rootfs locale-gen en_US.UTF-8
981+ chroot $rootfs update-locale LANG=en_US.UTF-8
982+ else
983+ chroot $rootfs locale-gen $LANG
984+ chroot $rootfs update-locale LANG=$LANG
985+ fi
986+
987+ # remove pointless services in a container
988+ chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove
989+
990+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done'
991+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done'
992+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done'
993+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done'
994+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done'
995+
996+ # if this isn't lucid, then we need to twiddle the network upstart bits :(
997+ if [ $release != "lucid" ]; then
998+ sed -i 's/^.*emission handled.*$/echo Emitting lo/' $rootfs/etc/network/if-up.d/upstart
999+ fi
1000+}
1001+
1002+post_process()
1003+{
1004+ rootfs=$1
1005+ release=$2
1006+ trim_container=$3
1007+
1008+ if [ $trim_container -eq 1 ]; then
1009+ trim $rootfs $release
1010+ elif [ $release = "lucid" -o $release = "maverick" -o $release = "natty" \
1011+ -o $release = "oneiric" ]; then
1012+ # for lucid and maverick, if not trimming, then add the ubuntu-virt
1013+ # ppa and install lxcguest
1014+ if [ $release = "lucid" -o $release = "maverick" ]; then
1015+ chroot $rootfs apt-get install --force-yes -y python-software-properties
1016+ chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa
1017+ fi
1018+ cresolvonf="${rootfs}/etc/resolv.conf"
1019+ mv $cresolvonf ${cresolvonf}.lxcbak
1020+ cat /etc/resolv.conf > ${cresolvonf}
1021+ chroot $rootfs apt-get update
1022+ chroot $rootfs apt-get install --force-yes -y lxcguest
1023+ rm -f ${cresolvonf}
1024+ mv ${cresolvonf}.lxcbak ${cresolvonf}
1025+ fi
1026+
1027+ # If the container isn't running a native architecture, setup multiarch
1028+ if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then
1029+ mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
1030+ echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
1031+
1032+ # Save existing value of MIRROR and SECURITY_MIRROR
1033+ DEFAULT_MIRROR=$MIRROR
1034+ DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR
1035+
1036+ # Write a new sources.list containing both native and multiarch entries
1037+ > ${rootfs}/etc/apt/sources.list
1038+ write_sourceslist $rootfs $arch "native"
1039+
1040+ MIRROR=$DEFAULT_MIRROR
1041+ SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR
1042+ write_sourceslist $rootfs $hostarch "multiarch"
1043+
1044+ # Finally update the lists and install upstart using the host architecture
1045+ chroot $rootfs apt-get update
1046+ chroot $rootfs apt-get install --force-yes -y --no-install-recommends upstart:${hostarch} mountall:amd64 iproute:amd64 isc-dhcp-client:amd64
1047+ fi
1048+}
1049+
1050+do_bindhome()
1051+{
1052+ rootfs=$1
1053+ user=$2
1054+
1055+ # copy /etc/passwd, /etc/shadow, and /etc/group entries into container
1056+ pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; }
1057+ echo $pwd >> $rootfs/etc/passwd
1058+
1059+ # make sure user's shell exists in the container
1060+ shell=`echo $pwd | cut -d: -f 7`
1061+ if [ ! -x $rootfs/$shell ]; then
1062+ echo "shell $shell for user $user was not found in the container."
1063+ pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1`
1064+ echo "Installing $pkg"
1065+ chroot $rootfs apt-get --force-yes -y install $pkg
1066+ fi
1067+
1068+ shad=`getent shadow $user`
1069+ echo "$shad" >> $rootfs/etc/shadow
1070+
1071+ # bind-mount the user's path into the container's /home
1072+ h=`getent passwd $user | cut -d: -f 6`
1073+ mkdir -p $rootfs/$h
1074+ echo "$h $rootfs/$h none bind 0 0" >> $path/fstab
1075+
1076+ # Make sure the group exists in container
1077+ chroot $rootfs getent group $user || { \
1078+ grp=`getent group $user`
1079+ echo "$grp" >> $rootfs/etc/group
1080+ }
1081+}
1082+
1083+usage()
1084+{
1085+ cat <<EOF
1086+$1 -h|--help [-a|--arch] [-b|--bindhome <user>] [--trim]
1087+ [-F | --flush-cache] [-r|--release <release>] [ -S | --auth-key <keyfile>]
1088+release: lucid | maverick | natty | oneiric | precise
1089+trim: make a minimal (faster, but not upgrade-safe) container
1090+bindhome: bind <user>'s home into the container
1091+arch: amd64 or i386: defaults to host arch
1092+auth-key: SSH Public key file to inject into container
1093+EOF
1094+ return 0
1095+}
1096+
1097+options=$(getopt -o a:b:hp:r:xn:FS: -l arch:,bindhome:,help,path:,release:,trim,name:,flush-cache,auth-key: -- "$@")
1098+if [ $? -ne 0 ]; then
1099+ usage $(basename $0)
1100+ exit 1
1101+fi
1102+eval set -- "$options"
1103+
1104+release=lucid
1105+if [ -f /etc/lsb-release ]; then
1106+ . /etc/lsb-release
1107+ case "$DISTRIB_CODENAME" in
1108+ lucid|maverick|natty|oneiric|precise)
1109+ release=$DISTRIB_CODENAME
1110+ ;;
1111+ esac
1112+fi
1113+
1114+bindhome=
1115+arch=$(arch)
1116+
1117+# Code taken from debootstrap
1118+if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
1119+ arch=`/usr/bin/dpkg --print-architecture`
1120+elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
1121+ arch=`/usr/bin/udpkg --print-architecture`
1122+else
1123+ arch=$(arch)
1124+ if [ "$arch" = "i686" ]; then
1125+ arch="i386"
1126+ elif [ "$arch" = "x86_64" ]; then
1127+ arch="amd64"
1128+ elif [ "$arch" = "armv7l" ]; then
1129+ arch="armel"
1130+ fi
1131+fi
1132+
1133+trim_container=0
1134+hostarch=$arch
1135+flushcache=0
1136+while true
1137+do
1138+ case "$1" in
1139+ -h|--help) usage $0 && exit 0;;
1140+ -p|--path) path=$2; shift 2;;
1141+ -n|--name) name=$2; shift 2;;
1142+ -F|--flush-cache) flushcache=1; shift 1;;
1143+ -r|--release) release=$2; shift 2;;
1144+ -b|--bindhome) bindhome=$2; shift 2;;
1145+ -a|--arch) arch=$2; shift 2;;
1146+ -x|--trim) trim_container=1; shift 1;;
1147+ -S|--auth-key) auth_key=$2; shift 2;;
1148+ --) shift 1; break ;;
1149+ *) break ;;
1150+ esac
1151+done
1152+
1153+pwd=`getent passwd $bindhome`
1154+if [ $? -ne 0 ]; then
1155+ echo "Error: no password entry found for $bindhome"
1156+ exit 1
1157+fi
1158+
1159+
1160+if [ "$arch" == "i686" ]; then
1161+ arch=i386
1162+fi
1163+
1164+if [ $hostarch = "i386" -a $arch = "amd64" ]; then
1165+ echo "can't create amd64 container on i386"
1166+ exit 1
1167+fi
1168+
1169+type debootstrap
1170+if [ $? -ne 0 ]; then
1171+ echo "'debootstrap' command is missing"
1172+ exit 1
1173+fi
1174+
1175+if [ -z "$path" ]; then
1176+ echo "'path' parameter is required"
1177+ exit 1
1178+fi
1179+
1180+if [ "$(id -u)" != "0" ]; then
1181+ echo "This script should be run as 'root'"
1182+ exit 1
1183+fi
1184+
1185+rootfs=$path/rootfs
1186+
1187+install_ubuntu $rootfs $release $flushcache
1188+if [ $? -ne 0 ]; then
1189+ echo "failed to install ubuntu $release"
1190+ exit 1
1191+fi
1192+
1193+configure_ubuntu $rootfs $name $release
1194+if [ $? -ne 0 ]; then
1195+ echo "failed to configure ubuntu $release for a container"
1196+ exit 1
1197+fi
1198+
1199+copy_configuration $path $rootfs $name $arch $release
1200+if [ $? -ne 0 ]; then
1201+ echo "failed write configuration file"
1202+ exit 1
1203+fi
1204+
1205+post_process $rootfs $release $trim_container
1206+if [ ! -z $bindhome ]; then
1207+ do_bindhome $rootfs $bindhome
1208+fi
1209+
1210+echo ""
1211+echo "##"
1212+echo "# The default user is 'ubuntu' with password 'ubuntu'!"
1213+echo "# Use the 'sudo' command to run tasks as root in the container."
1214+echo "##"
1215+echo ""
1216
1217=== added directory '.pc/0053-lxc-start-pin-rootfs'
1218=== renamed directory '.pc/0053-lxc-start-pin-rootfs' => '.pc/0053-lxc-start-pin-rootfs.moved'
1219=== added file '.pc/0053-lxc-start-pin-rootfs/.timestamp'
1220=== added directory '.pc/0053-lxc-start-pin-rootfs/src'
1221=== added directory '.pc/0053-lxc-start-pin-rootfs/src/lxc'
1222=== added file '.pc/0053-lxc-start-pin-rootfs/src/lxc/conf.c'
1223--- .pc/0053-lxc-start-pin-rootfs/src/lxc/conf.c 1970-01-01 00:00:00 +0000
1224+++ .pc/0053-lxc-start-pin-rootfs/src/lxc/conf.c 2012-03-02 15:11:19 +0000
1225@@ -0,0 +1,1876 @@
1226+/*
1227+ * lxc: linux Container library
1228+ *
1229+ * (C) Copyright IBM Corp. 2007, 2008
1230+ *
1231+ * Authors:
1232+ * Daniel Lezcano <dlezcano at fr.ibm.com>
1233+ *
1234+ * This library is free software; you can redistribute it and/or
1235+ * modify it under the terms of the GNU Lesser General Public
1236+ * License as published by the Free Software Foundation; either
1237+ * version 2.1 of the License, or (at your option) any later version.
1238+ *
1239+ * This library is distributed in the hope that it will be useful,
1240+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1241+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1242+ * Lesser General Public License for more details.
1243+ *
1244+ * You should have received a copy of the GNU Lesser General Public
1245+ * License along with this library; if not, write to the Free Software
1246+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1247+ */
1248+#define _GNU_SOURCE
1249+#include <stdio.h>
1250+#undef _GNU_SOURCE
1251+#include <stdlib.h>
1252+#include <stdarg.h>
1253+#include <errno.h>
1254+#include <string.h>
1255+#include <dirent.h>
1256+#include <mntent.h>
1257+#include <unistd.h>
1258+#include <sys/wait.h>
1259+#include <pty.h>
1260+
1261+#include <linux/loop.h>
1262+
1263+#include <sys/types.h>
1264+#include <sys/utsname.h>
1265+#include <sys/param.h>
1266+#include <sys/stat.h>
1267+#include <sys/socket.h>
1268+#include <sys/mount.h>
1269+#include <sys/mman.h>
1270+#include <sys/prctl.h>
1271+#include <sys/capability.h>
1272+#include <sys/personality.h>
1273+
1274+#include <arpa/inet.h>
1275+#include <fcntl.h>
1276+#include <netinet/in.h>
1277+#include <net/if.h>
1278+#include <libgen.h>
1279+
1280+#include "network.h"
1281+#include "error.h"
1282+#include "parse.h"
1283+#include "config.h"
1284+#include "utils.h"
1285+#include "conf.h"
1286+#include "log.h"
1287+#include "lxc.h" /* for lxc_cgroup_set() */
1288+
1289+lxc_log_define(lxc_conf, lxc);
1290+
1291+#define MAXHWLEN 18
1292+#define MAXINDEXLEN 20
1293+#define MAXMTULEN 16
1294+#define MAXLINELEN 128
1295+
1296+#ifndef MS_DIRSYNC
1297+#define MS_DIRSYNC 128
1298+#endif
1299+
1300+#ifndef MS_REC
1301+#define MS_REC 16384
1302+#endif
1303+
1304+#ifndef MNT_DETACH
1305+#define MNT_DETACH 2
1306+#endif
1307+
1308+#ifndef MS_RELATIME
1309+#define MS_RELATIME (1 << 21)
1310+#endif
1311+
1312+#ifndef MS_STRICTATIME
1313+#define MS_STRICTATIME (1 << 24)
1314+#endif
1315+
1316+#ifndef CAP_SETFCAP
1317+#define CAP_SETFCAP 31
1318+#endif
1319+
1320+#ifndef CAP_MAC_OVERRIDE
1321+#define CAP_MAC_OVERRIDE 32
1322+#endif
1323+
1324+#ifndef CAP_MAC_ADMIN
1325+#define CAP_MAC_ADMIN 33
1326+#endif
1327+
1328+#ifndef PR_CAPBSET_DROP
1329+#define PR_CAPBSET_DROP 24
1330+#endif
1331+
1332+extern int pivot_root(const char * new_root, const char * put_old);
1333+
1334+typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
1335+
1336+struct mount_opt {
1337+ char *name;
1338+ int clear;
1339+ int flag;
1340+};
1341+
1342+struct caps_opt {
1343+ char *name;
1344+ int value;
1345+};
1346+
1347+static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
1348+static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
1349+static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
1350+static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
1351+static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
1352+
1353+static instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
1354+ [LXC_NET_VETH] = instanciate_veth,
1355+ [LXC_NET_MACVLAN] = instanciate_macvlan,
1356+ [LXC_NET_VLAN] = instanciate_vlan,
1357+ [LXC_NET_PHYS] = instanciate_phys,
1358+ [LXC_NET_EMPTY] = instanciate_empty,
1359+};
1360+
1361+static struct mount_opt mount_opt[] = {
1362+ { "defaults", 0, 0 },
1363+ { "ro", 0, MS_RDONLY },
1364+ { "rw", 1, MS_RDONLY },
1365+ { "suid", 1, MS_NOSUID },
1366+ { "nosuid", 0, MS_NOSUID },
1367+ { "dev", 1, MS_NODEV },
1368+ { "nodev", 0, MS_NODEV },
1369+ { "exec", 1, MS_NOEXEC },
1370+ { "noexec", 0, MS_NOEXEC },
1371+ { "sync", 0, MS_SYNCHRONOUS },
1372+ { "async", 1, MS_SYNCHRONOUS },
1373+ { "dirsync", 0, MS_DIRSYNC },
1374+ { "remount", 0, MS_REMOUNT },
1375+ { "mand", 0, MS_MANDLOCK },
1376+ { "nomand", 1, MS_MANDLOCK },
1377+ { "atime", 1, MS_NOATIME },
1378+ { "noatime", 0, MS_NOATIME },
1379+ { "diratime", 1, MS_NODIRATIME },
1380+ { "nodiratime", 0, MS_NODIRATIME },
1381+ { "bind", 0, MS_BIND },
1382+ { "rbind", 0, MS_BIND|MS_REC },
1383+ { "relatime", 0, MS_RELATIME },
1384+ { "norelatime", 1, MS_RELATIME },
1385+ { "strictatime", 0, MS_STRICTATIME },
1386+ { "nostrictatime", 1, MS_STRICTATIME },
1387+ { NULL, 0, 0 },
1388+};
1389+
1390+static struct caps_opt caps_opt[] = {
1391+ { "chown", CAP_CHOWN },
1392+ { "dac_override", CAP_DAC_OVERRIDE },
1393+ { "dac_read_search", CAP_DAC_READ_SEARCH },
1394+ { "fowner", CAP_FOWNER },
1395+ { "fsetid", CAP_FSETID },
1396+ { "kill", CAP_KILL },
1397+ { "setgid", CAP_SETGID },
1398+ { "setuid", CAP_SETUID },
1399+ { "setpcap", CAP_SETPCAP },
1400+ { "linux_immutable", CAP_LINUX_IMMUTABLE },
1401+ { "net_bind_service", CAP_NET_BIND_SERVICE },
1402+ { "net_broadcast", CAP_NET_BROADCAST },
1403+ { "net_admin", CAP_NET_ADMIN },
1404+ { "net_raw", CAP_NET_RAW },
1405+ { "ipc_lock", CAP_IPC_LOCK },
1406+ { "ipc_owner", CAP_IPC_OWNER },
1407+ { "sys_module", CAP_SYS_MODULE },
1408+ { "sys_rawio", CAP_SYS_RAWIO },
1409+ { "sys_chroot", CAP_SYS_CHROOT },
1410+ { "sys_ptrace", CAP_SYS_PTRACE },
1411+ { "sys_pacct", CAP_SYS_PACCT },
1412+ { "sys_admin", CAP_SYS_ADMIN },
1413+ { "sys_boot", CAP_SYS_BOOT },
1414+ { "sys_nice", CAP_SYS_NICE },
1415+ { "sys_resource", CAP_SYS_RESOURCE },
1416+ { "sys_time", CAP_SYS_TIME },
1417+ { "sys_tty_config", CAP_SYS_TTY_CONFIG },
1418+ { "mknod", CAP_MKNOD },
1419+ { "lease", CAP_LEASE },
1420+#ifdef CAP_AUDIT_WRITE
1421+ { "audit_write", CAP_AUDIT_WRITE },
1422+#endif
1423+#ifdef CAP_AUDIT_CONTROL
1424+ { "audit_control", CAP_AUDIT_CONTROL },
1425+#endif
1426+ { "setfcap", CAP_SETFCAP },
1427+ { "mac_override", CAP_MAC_OVERRIDE },
1428+ { "mac_admin", CAP_MAC_ADMIN },
1429+};
1430+
1431+static int run_script(const char *name, const char *section,
1432+ const char *script, ...)
1433+{
1434+ int ret;
1435+ FILE *f;
1436+ char *buffer, *p, *output;
1437+ size_t size = 0;
1438+ va_list ap;
1439+
1440+ INFO("Executing script '%s' for container '%s', config section '%s'",
1441+ script, name, section);
1442+
1443+ va_start(ap, script);
1444+ while ((p = va_arg(ap, char *)))
1445+ size += strlen(p) + 1;
1446+ va_end(ap);
1447+
1448+ size += strlen(script);
1449+ size += strlen(name);
1450+ size += strlen(section);
1451+ size += 3;
1452+
1453+ if (size > INT_MAX)
1454+ return -1;
1455+
1456+ buffer = alloca(size);
1457+ if (!buffer) {
1458+ ERROR("failed to allocate memory");
1459+ return -1;
1460+ }
1461+
1462+ ret = sprintf(buffer, "%s %s %s", script, name, section);
1463+
1464+ va_start(ap, script);
1465+ while ((p = va_arg(ap, char *)))
1466+ ret += sprintf(buffer + ret, " %s", p);
1467+ va_end(ap);
1468+
1469+ f = popen(buffer, "r");
1470+ if (!f) {
1471+ SYSERROR("popen failed");
1472+ return -1;
1473+ }
1474+
1475+ output = malloc(LXC_LOG_BUFFER_SIZE);
1476+ if (!output) {
1477+ ERROR("failed to allocate memory for script output");
1478+ return -1;
1479+ }
1480+
1481+ while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
1482+ DEBUG("script output: %s", output);
1483+
1484+ free(output);
1485+
1486+ if (pclose(f)) {
1487+ ERROR("Script exited on error");
1488+ return -1;
1489+ }
1490+
1491+ return 0;
1492+}
1493+
1494+static int find_fstype_cb(char* buffer, void *data)
1495+{
1496+ struct cbarg {
1497+ const char *rootfs;
1498+ const char *target;
1499+ int mntopt;
1500+ } *cbarg = data;
1501+
1502+ char *fstype;
1503+
1504+ /* we don't try 'nodev' entries */
1505+ if (strstr(buffer, "nodev"))
1506+ return 0;
1507+
1508+ fstype = buffer;
1509+ fstype += lxc_char_left_gc(fstype, strlen(fstype));
1510+ fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
1511+
1512+ DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
1513+ cbarg->rootfs, cbarg->target, fstype);
1514+
1515+ if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) {
1516+ DEBUG("mount failed with error: %s", strerror(errno));
1517+ return 0;
1518+ }
1519+
1520+ INFO("mounted '%s' on '%s', with fstype '%s'",
1521+ cbarg->rootfs, cbarg->target, fstype);
1522+
1523+ return 1;
1524+}
1525+
1526+static int mount_unknow_fs(const char *rootfs, const char *target, int mntopt)
1527+{
1528+ int i;
1529+
1530+ struct cbarg {
1531+ const char *rootfs;
1532+ const char *target;
1533+ int mntopt;
1534+ } cbarg = {
1535+ .rootfs = rootfs,
1536+ .target = target,
1537+ .mntopt = mntopt,
1538+ };
1539+
1540+ /*
1541+ * find the filesystem type with brute force:
1542+ * first we check with /etc/filesystems, in case the modules
1543+ * are auto-loaded and fall back to the supported kernel fs
1544+ */
1545+ char *fsfile[] = {
1546+ "/etc/filesystems",
1547+ "/proc/filesystems",
1548+ };
1549+
1550+ for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
1551+
1552+ int ret;
1553+
1554+ if (access(fsfile[i], F_OK))
1555+ continue;
1556+
1557+ ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
1558+ if (ret < 0) {
1559+ ERROR("failed to parse '%s'", fsfile[i]);
1560+ return -1;
1561+ }
1562+
1563+ if (ret)
1564+ return 0;
1565+ }
1566+
1567+ ERROR("failed to determine fs type for '%s'", rootfs);
1568+ return -1;
1569+}
1570+
1571+static int mount_rootfs_dir(const char *rootfs, const char *target)
1572+{
1573+ return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL);
1574+}
1575+
1576+static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
1577+{
1578+ int rfd;
1579+ int ret = -1;
1580+
1581+ rfd = open(rootfs, O_RDWR);
1582+ if (rfd < 0) {
1583+ SYSERROR("failed to open '%s'", rootfs);
1584+ return -1;
1585+ }
1586+
1587+ memset(loinfo, 0, sizeof(*loinfo));
1588+
1589+ loinfo->lo_flags = LO_FLAGS_AUTOCLEAR;
1590+
1591+ if (ioctl(fd, LOOP_SET_FD, rfd)) {
1592+ SYSERROR("failed to LOOP_SET_FD");
1593+ goto out;
1594+ }
1595+
1596+ if (ioctl(fd, LOOP_SET_STATUS64, loinfo)) {
1597+ SYSERROR("failed to LOOP_SET_STATUS64");
1598+ goto out;
1599+ }
1600+
1601+ ret = 0;
1602+out:
1603+ close(rfd);
1604+
1605+ return ret;
1606+}
1607+
1608+static int mount_rootfs_file(const char *rootfs, const char *target)
1609+{
1610+ struct dirent dirent, *direntp;
1611+ struct loop_info64 loinfo;
1612+ int ret = -1, fd = -1;
1613+ DIR *dir;
1614+ char path[MAXPATHLEN];
1615+
1616+ dir = opendir("/dev");
1617+ if (!dir) {
1618+ SYSERROR("failed to open '/dev'");
1619+ return -1;
1620+ }
1621+
1622+ while (!readdir_r(dir, &dirent, &direntp)) {
1623+
1624+ if (!direntp)
1625+ break;
1626+
1627+ if (!strcmp(direntp->d_name, "."))
1628+ continue;
1629+
1630+ if (!strcmp(direntp->d_name, ".."))
1631+ continue;
1632+
1633+ if (strncmp(direntp->d_name, "loop", 4))
1634+ continue;
1635+
1636+ sprintf(path, "/dev/%s", direntp->d_name);
1637+ fd = open(path, O_RDWR);
1638+ if (fd < 0)
1639+ continue;
1640+
1641+ if (ioctl(fd, LOOP_GET_STATUS64, &loinfo) == 0) {
1642+ close(fd);
1643+ continue;
1644+ }
1645+
1646+ if (errno != ENXIO) {
1647+ WARN("unexpected error for ioctl on '%s': %m",
1648+ direntp->d_name);
1649+ continue;
1650+ }
1651+
1652+ DEBUG("found '%s' free lodev", path);
1653+
1654+ ret = setup_lodev(rootfs, fd, &loinfo);
1655+ if (!ret)
1656+ ret = mount_unknow_fs(path, target, 0);
1657+ close(fd);
1658+
1659+ break;
1660+ }
1661+
1662+ if (closedir(dir))
1663+ WARN("failed to close directory");
1664+
1665+ return ret;
1666+}
1667+
1668+static int mount_rootfs_block(const char *rootfs, const char *target)
1669+{
1670+ return mount_unknow_fs(rootfs, target, 0);
1671+}
1672+
1673+static int mount_rootfs(const char *rootfs, const char *target)
1674+{
1675+ char absrootfs[MAXPATHLEN];
1676+ struct stat s;
1677+ int i;
1678+
1679+ typedef int (*rootfs_cb)(const char *, const char *);
1680+
1681+ struct rootfs_type {
1682+ int type;
1683+ rootfs_cb cb;
1684+ } rtfs_type[] = {
1685+ { S_IFDIR, mount_rootfs_dir },
1686+ { S_IFBLK, mount_rootfs_block },
1687+ { S_IFREG, mount_rootfs_file },
1688+ };
1689+
1690+ if (!realpath(rootfs, absrootfs)) {
1691+ SYSERROR("failed to get real path for '%s'", rootfs);
1692+ return -1;
1693+ }
1694+
1695+ if (access(absrootfs, F_OK)) {
1696+ SYSERROR("'%s' is not accessible", absrootfs);
1697+ return -1;
1698+ }
1699+
1700+ if (stat(absrootfs, &s)) {
1701+ SYSERROR("failed to stat '%s'", absrootfs);
1702+ return -1;
1703+ }
1704+
1705+ for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
1706+
1707+ if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
1708+ continue;
1709+
1710+ return rtfs_type[i].cb(absrootfs, target);
1711+ }
1712+
1713+ ERROR("unsupported rootfs type for '%s'", absrootfs);
1714+ return -1;
1715+}
1716+
1717+static int setup_utsname(struct utsname *utsname)
1718+{
1719+ if (!utsname)
1720+ return 0;
1721+
1722+ if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
1723+ SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
1724+ return -1;
1725+ }
1726+
1727+ INFO("'%s' hostname has been setup", utsname->nodename);
1728+
1729+ return 0;
1730+}
1731+
1732+static int setup_tty(const struct lxc_rootfs *rootfs,
1733+ const struct lxc_tty_info *tty_info, char *ttydir)
1734+{
1735+ char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
1736+ int i, ret;
1737+
1738+ if (!rootfs->path)
1739+ return 0;
1740+
1741+ for (i = 0; i < tty_info->nbtty; i++) {
1742+
1743+ struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1744+
1745+ ret = snprintf(path, sizeof(path), "%s/dev/tty%d",
1746+ rootfs->mount, i + 1);
1747+ if (ret >= sizeof(path)) {
1748+ ERROR("pathname too long for ttys");
1749+ return -1;
1750+ }
1751+ if (ttydir) {
1752+ /* create dev/lxc/tty%d" */
1753+ snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
1754+ rootfs->mount, ttydir, i + 1);
1755+ if (ret >= sizeof(lxcpath)) {
1756+ ERROR("pathname too long for ttys");
1757+ return -1;
1758+ }
1759+ ret = creat(lxcpath, 0660);
1760+ if (ret==-1 && errno != EEXIST) {
1761+ SYSERROR("error creating %s\n", lxcpath);
1762+ return -1;
1763+ }
1764+ close(ret);
1765+ ret = unlink(path);
1766+ if (ret && errno != ENOENT) {
1767+ SYSERROR("error unlinking %s\n", path);
1768+ return -1;
1769+ }
1770+
1771+ if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) {
1772+ WARN("failed to mount '%s'->'%s'",
1773+ pty_info->name, path);
1774+ continue;
1775+ }
1776+
1777+ snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1);
1778+ ret = symlink(lxcpath, path);
1779+ if (ret) {
1780+ SYSERROR("failed to create symlink for tty %d\n", i+1);
1781+ return -1;
1782+ }
1783+ } else {
1784+ if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
1785+ WARN("failed to mount '%s'->'%s'",
1786+ pty_info->name, path);
1787+ continue;
1788+ }
1789+ }
1790+ }
1791+
1792+ INFO("%d tty(s) has been setup", tty_info->nbtty);
1793+
1794+ return 0;
1795+}
1796+
1797+static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
1798+{
1799+ struct lxc_list *mountlist, *listentry, *iterator;
1800+ char *pivotdir, *mountpoint, *mountentry;
1801+ int found;
1802+ void **cbparm;
1803+
1804+ mountentry = buffer;
1805+ cbparm = (void **)data;
1806+
1807+ mountlist = cbparm[0];
1808+ pivotdir = cbparm[1];
1809+
1810+ /* parse entry, first field is mountname, ignore */
1811+ mountpoint = strtok(mountentry, " ");
1812+ if (!mountpoint)
1813+ return -1;
1814+
1815+ /* second field is mountpoint */
1816+ mountpoint = strtok(NULL, " ");
1817+ if (!mountpoint)
1818+ return -1;
1819+
1820+ /* only consider mountpoints below old root fs */
1821+ if (strncmp(mountpoint, pivotdir, strlen(pivotdir)))
1822+ return 0;
1823+
1824+ /* filter duplicate mountpoints */
1825+ found = 0;
1826+ lxc_list_for_each(iterator, mountlist) {
1827+ if (!strcmp(iterator->elem, mountpoint)) {
1828+ found = 1;
1829+ break;
1830+ }
1831+ }
1832+ if (found)
1833+ return 0;
1834+
1835+ /* add entry to list */
1836+ listentry = malloc(sizeof(*listentry));
1837+ if (!listentry) {
1838+ SYSERROR("malloc for mountpoint listentry failed");
1839+ return -1;
1840+ }
1841+
1842+ listentry->elem = strdup(mountpoint);
1843+ if (!listentry->elem) {
1844+ SYSERROR("strdup failed");
1845+ return -1;
1846+ }
1847+ lxc_list_add_tail(mountlist, listentry);
1848+
1849+ return 0;
1850+}
1851+
1852+static int umount_oldrootfs(const char *oldrootfs)
1853+{
1854+ char path[MAXPATHLEN];
1855+ void *cbparm[2];
1856+ struct lxc_list mountlist, *iterator;
1857+ int ok, still_mounted, last_still_mounted;
1858+
1859+ /* read and parse /proc/mounts in old root fs */
1860+ lxc_list_init(&mountlist);
1861+
1862+ /* oldrootfs is on the top tree directory now */
1863+ snprintf(path, sizeof(path), "/%s", oldrootfs);
1864+ cbparm[0] = &mountlist;
1865+
1866+ cbparm[1] = strdup(path);
1867+ if (!cbparm[1]) {
1868+ SYSERROR("strdup failed");
1869+ return -1;
1870+ }
1871+
1872+ snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
1873+
1874+ ok = lxc_file_for_each_line(path,
1875+ setup_rootfs_pivot_root_cb, &cbparm);
1876+ if (ok < 0) {
1877+ SYSERROR("failed to read or parse mount list '%s'", path);
1878+ return -1;
1879+ }
1880+
1881+ /* umount filesystems until none left or list no longer shrinks */
1882+ still_mounted = 0;
1883+ do {
1884+ last_still_mounted = still_mounted;
1885+ still_mounted = 0;
1886+
1887+ lxc_list_for_each(iterator, &mountlist) {
1888+
1889+ /* umount normally */
1890+ if (!umount(iterator->elem)) {
1891+ DEBUG("umounted '%s'", (char *)iterator->elem);
1892+ lxc_list_del(iterator);
1893+ continue;
1894+ }
1895+
1896+ still_mounted++;
1897+ }
1898+
1899+ } while (still_mounted > 0 && still_mounted != last_still_mounted);
1900+
1901+
1902+ lxc_list_for_each(iterator, &mountlist) {
1903+
1904+ /* let's try a lazy umount */
1905+ if (!umount2(iterator->elem, MNT_DETACH)) {
1906+ INFO("lazy unmount of '%s'", (char *)iterator->elem);
1907+ continue;
1908+ }
1909+
1910+ /* be more brutal (nfs) */
1911+ if (!umount2(iterator->elem, MNT_FORCE)) {
1912+ INFO("forced unmount of '%s'", (char *)iterator->elem);
1913+ continue;
1914+ }
1915+
1916+ WARN("failed to unmount '%s'", (char *)iterator->elem);
1917+ }
1918+
1919+ return 0;
1920+}
1921+
1922+static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
1923+{
1924+ char path[MAXPATHLEN];
1925+ int remove_pivotdir = 0;
1926+
1927+ /* change into new root fs */
1928+ if (chdir(rootfs)) {
1929+ SYSERROR("can't chdir to new rootfs '%s'", rootfs);
1930+ return -1;
1931+ }
1932+
1933+ if (!pivotdir)
1934+ pivotdir = "mnt";
1935+
1936+ /* compute the full path to pivotdir under rootfs */
1937+ snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
1938+
1939+ if (access(path, F_OK)) {
1940+
1941+ if (mkdir_p(path, 0755)) {
1942+ SYSERROR("failed to create pivotdir '%s'", path);
1943+ return -1;
1944+ }
1945+
1946+ remove_pivotdir = 1;
1947+ DEBUG("created '%s' directory", path);
1948+ }
1949+
1950+ DEBUG("mountpoint for old rootfs is '%s'", path);
1951+
1952+ /* pivot_root into our new root fs */
1953+ if (pivot_root(".", path)) {
1954+ SYSERROR("pivot_root syscall failed");
1955+ return -1;
1956+ }
1957+
1958+ if (chdir("/")) {
1959+ SYSERROR("can't chdir to / after pivot_root");
1960+ return -1;
1961+ }
1962+
1963+ DEBUG("pivot_root syscall to '%s' successful", rootfs);
1964+
1965+ /* we switch from absolute path to relative path */
1966+ if (umount_oldrootfs(pivotdir))
1967+ return -1;
1968+
1969+ /* remove temporary mount point, we don't consider the removing
1970+ * as fatal */
1971+ if (remove_pivotdir && rmdir(pivotdir))
1972+ WARN("can't remove mountpoint '%s': %m", pivotdir);
1973+
1974+ return 0;
1975+}
1976+
1977+static int setup_rootfs(const struct lxc_rootfs *rootfs)
1978+{
1979+ if (!rootfs->path)
1980+ return 0;
1981+
1982+ if (access(rootfs->mount, F_OK)) {
1983+ SYSERROR("failed to access to '%s', check it is present",
1984+ rootfs->mount);
1985+ return -1;
1986+ }
1987+
1988+ if (mount_rootfs(rootfs->path, rootfs->mount)) {
1989+ ERROR("failed to mount rootfs");
1990+ return -1;
1991+ }
1992+
1993+ DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
1994+
1995+ return 0;
1996+}
1997+
1998+int setup_pivot_root(const struct lxc_rootfs *rootfs)
1999+{
2000+ if (!rootfs->path)
2001+ return 0;
2002+
2003+ if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
2004+ ERROR("failed to setup pivot root");
2005+ return -1;
2006+ }
2007+
2008+ return 0;
2009+}
2010+
2011+static int setup_pts(int pts)
2012+{
2013+ char target[PATH_MAX];
2014+
2015+ if (!pts)
2016+ return 0;
2017+
2018+ if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
2019+ SYSERROR("failed to umount 'dev/pts'");
2020+ return -1;
2021+ }
2022+
2023+ if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL,
2024+ "newinstance,ptmxmode=0666")) {
2025+ SYSERROR("failed to mount a new instance of '/dev/pts'");
2026+ return -1;
2027+ }
2028+
2029+ if (access("/dev/ptmx", F_OK)) {
2030+ if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
2031+ goto out;
2032+ SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
2033+ return -1;
2034+ }
2035+
2036+ if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
2037+ goto out;
2038+
2039+ /* fallback here, /dev/pts/ptmx exists just mount bind */
2040+ if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
2041+ SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
2042+ return -1;
2043+ }
2044+
2045+ INFO("created new pts instance");
2046+
2047+out:
2048+ return 0;
2049+}
2050+
2051+static int setup_personality(int persona)
2052+{
2053+ if (persona == -1)
2054+ return 0;
2055+
2056+ if (personality(persona) < 0) {
2057+ SYSERROR("failed to set personality to '0x%x'", persona);
2058+ return -1;
2059+ }
2060+
2061+ INFO("set personality to '0x%x'", persona);
2062+
2063+ return 0;
2064+}
2065+
2066+static int setup_dev_console(const struct lxc_rootfs *rootfs,
2067+ const struct lxc_console *console)
2068+{
2069+ char path[MAXPATHLEN];
2070+ struct stat s;
2071+ int ret;
2072+
2073+ ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
2074+ if (ret >= sizeof(path)) {
2075+ ERROR("console path too long\n");
2076+ return -1;
2077+ }
2078+
2079+ if (access(path, F_OK)) {
2080+ WARN("rootfs specified but no console found at '%s'", path);
2081+ return 0;
2082+ }
2083+
2084+ if (console->peer == -1) {
2085+ INFO("no console output required");
2086+ return 0;
2087+ }
2088+
2089+ if (stat(path, &s)) {
2090+ SYSERROR("failed to stat '%s'", path);
2091+ return -1;
2092+ }
2093+
2094+ if (chmod(console->name, s.st_mode)) {
2095+ SYSERROR("failed to set mode '0%o' to '%s'",
2096+ s.st_mode, console->name);
2097+ return -1;
2098+ }
2099+
2100+ if (mount(console->name, path, "none", MS_BIND, 0)) {
2101+ ERROR("failed to mount '%s' on '%s'", console->name, path);
2102+ return -1;
2103+ }
2104+
2105+ INFO("console has been setup");
2106+ return 0;
2107+}
2108+
2109+static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
2110+ const struct lxc_console *console,
2111+ char *ttydir)
2112+{
2113+ char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
2114+ int ret;
2115+
2116+ /* create rootfs/dev/<ttydir> directory */
2117+ ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount,
2118+ ttydir);
2119+ if (ret >= sizeof(path))
2120+ return -1;
2121+ ret = mkdir(path, 0755);
2122+ if (ret && errno != EEXIST) {
2123+ SYSERROR("failed with errno %d to create %s\n", errno, path);
2124+ return -1;
2125+ }
2126+ INFO("created %s\n", path);
2127+
2128+ ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console",
2129+ rootfs->mount, ttydir);
2130+ if (ret >= sizeof(lxcpath)) {
2131+ ERROR("console path too long\n");
2132+ return -1;
2133+ }
2134+
2135+ snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
2136+ ret = unlink(path);
2137+ if (ret && errno != ENOENT) {
2138+ SYSERROR("error unlinking %s\n", path);
2139+ return -1;
2140+ }
2141+
2142+ ret = creat(lxcpath, 0660);
2143+ if (ret==-1 && errno != EEXIST) {
2144+ SYSERROR("error %d creating %s\n", errno, lxcpath);
2145+ return -1;
2146+ }
2147+ close(ret);
2148+
2149+ if (console->peer == -1) {
2150+ INFO("no console output required");
2151+ return 0;
2152+ }
2153+
2154+ if (mount(console->name, lxcpath, "none", MS_BIND, 0)) {
2155+ ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
2156+ return -1;
2157+ }
2158+
2159+ /* create symlink from rootfs/dev/console to 'lxc/console' */
2160+ snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
2161+ ret = symlink(lxcpath, path);
2162+ if (ret) {
2163+ SYSERROR("failed to create symlink for console");
2164+ return -1;
2165+ }
2166+
2167+ INFO("console has been setup on %s", lxcpath);
2168+
2169+ return 0;
2170+}
2171+
2172+static int setup_console(const struct lxc_rootfs *rootfs,
2173+ const struct lxc_console *console,
2174+ char *ttydir)
2175+{
2176+ /* We don't have a rootfs, /dev/console will be shared */
2177+ if (!rootfs->path)
2178+ return 0;
2179+ if (!ttydir)
2180+ return setup_dev_console(rootfs, console);
2181+
2182+ return setup_ttydir_console(rootfs, console, ttydir);
2183+}
2184+
2185+static int setup_cgroup(const char *name, struct lxc_list *cgroups)
2186+{
2187+ struct lxc_list *iterator;
2188+ struct lxc_cgroup *cg;
2189+ int ret = -1;
2190+
2191+ if (lxc_list_empty(cgroups))
2192+ return 0;
2193+
2194+ lxc_list_for_each(iterator, cgroups) {
2195+
2196+ cg = iterator->elem;
2197+
2198+ if (lxc_cgroup_set(name, cg->subsystem, cg->value))
2199+ goto out;
2200+
2201+ DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
2202+ }
2203+
2204+ ret = 0;
2205+ INFO("cgroup has been setup");
2206+out:
2207+ return ret;
2208+}
2209+
2210+static void parse_mntopt(char *opt, unsigned long *flags, char **data)
2211+{
2212+ struct mount_opt *mo;
2213+
2214+ /* If opt is found in mount_opt, set or clear flags.
2215+ * Otherwise append it to data. */
2216+
2217+ for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
2218+ if (!strncmp(opt, mo->name, strlen(mo->name))) {
2219+ if (mo->clear)
2220+ *flags &= ~mo->flag;
2221+ else
2222+ *flags |= mo->flag;
2223+ return;
2224+ }
2225+ }
2226+
2227+ if (strlen(*data))
2228+ strcat(*data, ",");
2229+ strcat(*data, opt);
2230+}
2231+
2232+static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
2233+ char **mntdata)
2234+{
2235+ char *s, *data;
2236+ char *p, *saveptr = NULL;
2237+
2238+ *mntdata = NULL;
2239+ *mntflags = 0L;
2240+
2241+ if (!mntopts)
2242+ return 0;
2243+
2244+ s = strdup(mntopts);
2245+ if (!s) {
2246+ SYSERROR("failed to allocate memory");
2247+ return -1;
2248+ }
2249+
2250+ data = malloc(strlen(s) + 1);
2251+ if (!data) {
2252+ SYSERROR("failed to allocate memory");
2253+ free(s);
2254+ return -1;
2255+ }
2256+ *data = 0;
2257+
2258+ for (p = strtok_r(s, ",", &saveptr); p != NULL;
2259+ p = strtok_r(NULL, ",", &saveptr))
2260+ parse_mntopt(p, mntflags, &data);
2261+
2262+ if (*data)
2263+ *mntdata = data;
2264+ else
2265+ free(data);
2266+ free(s);
2267+
2268+ return 0;
2269+}
2270+
2271+static int mount_entry(const char *fsname, const char *target,
2272+ const char *fstype, unsigned long mountflags,
2273+ const char *data)
2274+{
2275+ if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
2276+ SYSERROR("failed to mount '%s' on '%s'", fsname, target);
2277+ return -1;
2278+ }
2279+
2280+ if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
2281+
2282+ DEBUG("remounting %s on %s to respect bind or remount options",
2283+ fsname, target);
2284+
2285+ if (mount(fsname, target, fstype,
2286+ mountflags | MS_REMOUNT, data)) {
2287+ SYSERROR("failed to mount '%s' on '%s'",
2288+ fsname, target);
2289+ return -1;
2290+ }
2291+ }
2292+
2293+ DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
2294+
2295+ return 0;
2296+}
2297+
2298+static inline int mount_entry_on_systemfs(struct mntent *mntent)
2299+{
2300+ unsigned long mntflags;
2301+ char *mntdata;
2302+ int ret;
2303+
2304+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
2305+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
2306+ return -1;
2307+ }
2308+
2309+ ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
2310+ mntent->mnt_type, mntflags, mntdata);
2311+
2312+ free(mntdata);
2313+
2314+ return ret;
2315+}
2316+
2317+static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
2318+ const struct lxc_rootfs *rootfs)
2319+{
2320+ char *aux;
2321+ char path[MAXPATHLEN];
2322+ unsigned long mntflags;
2323+ char *mntdata;
2324+ int ret = 0;
2325+
2326+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
2327+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
2328+ return -1;
2329+ }
2330+
2331+ aux = strstr(mntent->mnt_dir, rootfs->path);
2332+ if (!aux) {
2333+ WARN("ignoring mount point '%s'", mntent->mnt_dir);
2334+ goto out;
2335+ }
2336+
2337+ snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
2338+ aux + strlen(rootfs->path));
2339+
2340+ ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
2341+ mntflags, mntdata);
2342+
2343+out:
2344+ free(mntdata);
2345+ return ret;
2346+}
2347+
2348+static int mount_entry_on_relative_rootfs(struct mntent *mntent,
2349+ const char *rootfs)
2350+{
2351+ char path[MAXPATHLEN];
2352+ unsigned long mntflags;
2353+ char *mntdata;
2354+ int ret;
2355+
2356+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
2357+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
2358+ return -1;
2359+ }
2360+
2361+ /* relative to root mount point */
2362+ snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
2363+
2364+ ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
2365+ mntflags, mntdata);
2366+
2367+ free(mntdata);
2368+
2369+ return ret;
2370+}
2371+
2372+static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file)
2373+{
2374+ struct mntent *mntent;
2375+ int ret = -1;
2376+
2377+ while ((mntent = getmntent(file))) {
2378+
2379+ if (!rootfs->path) {
2380+ if (mount_entry_on_systemfs(mntent))
2381+ goto out;
2382+ continue;
2383+ }
2384+
2385+ /* We have a separate root, mounts are relative to it */
2386+ if (mntent->mnt_dir[0] != '/') {
2387+ if (mount_entry_on_relative_rootfs(mntent,
2388+ rootfs->mount))
2389+ goto out;
2390+ continue;
2391+ }
2392+
2393+ if (mount_entry_on_absolute_rootfs(mntent, rootfs))
2394+ goto out;
2395+ }
2396+
2397+ ret = 0;
2398+
2399+ INFO("mount points have been setup");
2400+out:
2401+ return ret;
2402+}
2403+
2404+static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab)
2405+{
2406+ FILE *file;
2407+ int ret;
2408+
2409+ if (!fstab)
2410+ return 0;
2411+
2412+ file = setmntent(fstab, "r");
2413+ if (!file) {
2414+ SYSERROR("failed to use '%s'", fstab);
2415+ return -1;
2416+ }
2417+
2418+ ret = mount_file_entries(rootfs, file);
2419+
2420+ endmntent(file);
2421+ return ret;
2422+}
2423+
2424+static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount)
2425+{
2426+ FILE *file;
2427+ struct lxc_list *iterator;
2428+ char *mount_entry;
2429+ int ret;
2430+
2431+ file = tmpfile();
2432+ if (!file) {
2433+ ERROR("tmpfile error: %m");
2434+ return -1;
2435+ }
2436+
2437+ lxc_list_for_each(iterator, mount) {
2438+ mount_entry = iterator->elem;
2439+ fprintf(file, "%s\n", mount_entry);
2440+ }
2441+
2442+ rewind(file);
2443+
2444+ ret = mount_file_entries(rootfs, file);
2445+
2446+ fclose(file);
2447+ return ret;
2448+}
2449+
2450+static int setup_caps(struct lxc_list *caps)
2451+{
2452+ struct lxc_list *iterator;
2453+ char *drop_entry;
2454+ int i, capid;
2455+
2456+ lxc_list_for_each(iterator, caps) {
2457+
2458+ drop_entry = iterator->elem;
2459+
2460+ capid = -1;
2461+
2462+ for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
2463+
2464+ if (strcmp(drop_entry, caps_opt[i].name))
2465+ continue;
2466+
2467+ capid = caps_opt[i].value;
2468+ break;
2469+ }
2470+
2471+ if (capid < 0) {
2472+ ERROR("unknown capability %s", drop_entry);
2473+ return -1;
2474+ }
2475+
2476+ DEBUG("drop capability '%s' (%d)", drop_entry, capid);
2477+
2478+ if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
2479+ SYSERROR("failed to remove %s capability", drop_entry);
2480+ return -1;
2481+ }
2482+
2483+ }
2484+
2485+ DEBUG("capabilities has been setup");
2486+
2487+ return 0;
2488+}
2489+
2490+static int setup_hw_addr(char *hwaddr, const char *ifname)
2491+{
2492+ struct sockaddr sockaddr;
2493+ struct ifreq ifr;
2494+ int ret, fd;
2495+
2496+ ret = lxc_convert_mac(hwaddr, &sockaddr);
2497+ if (ret) {
2498+ ERROR("mac address '%s' conversion failed : %s",
2499+ hwaddr, strerror(-ret));
2500+ return -1;
2501+ }
2502+
2503+ memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
2504+ memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
2505+
2506+ fd = socket(AF_INET, SOCK_DGRAM, 0);
2507+ if (fd < 0) {
2508+ ERROR("socket failure : %s", strerror(errno));
2509+ return -1;
2510+ }
2511+
2512+ ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
2513+ close(fd);
2514+ if (ret)
2515+ ERROR("ioctl failure : %s", strerror(errno));
2516+
2517+ DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
2518+
2519+ return ret;
2520+}
2521+
2522+static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
2523+{
2524+ struct lxc_list *iterator;
2525+ struct lxc_inetdev *inetdev;
2526+ int err;
2527+
2528+ lxc_list_for_each(iterator, ip) {
2529+
2530+ inetdev = iterator->elem;
2531+
2532+ err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
2533+ &inetdev->bcast, inetdev->prefix);
2534+ if (err) {
2535+ ERROR("failed to setup_ipv4_addr ifindex %d : %s",
2536+ ifindex, strerror(-err));
2537+ return -1;
2538+ }
2539+ }
2540+
2541+ return 0;
2542+}
2543+
2544+static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
2545+{
2546+ struct lxc_list *iterator;
2547+ struct lxc_inet6dev *inet6dev;
2548+ int err;
2549+
2550+ lxc_list_for_each(iterator, ip) {
2551+
2552+ inet6dev = iterator->elem;
2553+
2554+ err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
2555+ &inet6dev->mcast, &inet6dev->acast,
2556+ inet6dev->prefix);
2557+ if (err) {
2558+ ERROR("failed to setup_ipv6_addr ifindex %d : %s",
2559+ ifindex, strerror(-err));
2560+ return -1;
2561+ }
2562+ }
2563+
2564+ return 0;
2565+}
2566+
2567+static int setup_netdev(struct lxc_netdev *netdev)
2568+{
2569+ char ifname[IFNAMSIZ];
2570+ char *current_ifname = ifname;
2571+ int err;
2572+
2573+ /* empty network namespace */
2574+ if (!netdev->ifindex) {
2575+ if (netdev->flags & IFF_UP) {
2576+ err = lxc_netdev_up("lo");
2577+ if (err) {
2578+ ERROR("failed to set the loopback up : %s",
2579+ strerror(-err));
2580+ return -1;
2581+ }
2582+ }
2583+ return 0;
2584+ }
2585+
2586+ /* retrieve the name of the interface */
2587+ if (!if_indextoname(netdev->ifindex, current_ifname)) {
2588+ ERROR("no interface corresponding to index '%d'",
2589+ netdev->ifindex);
2590+ return -1;
2591+ }
2592+
2593+ /* default: let the system to choose one interface name */
2594+ if (!netdev->name)
2595+ netdev->name = netdev->type == LXC_NET_PHYS ?
2596+ netdev->link : "eth%d";
2597+
2598+ /* rename the interface name */
2599+ err = lxc_netdev_rename_by_name(ifname, netdev->name);
2600+ if (err) {
2601+ ERROR("failed to rename %s->%s : %s", ifname, netdev->name,
2602+ strerror(-err));
2603+ return -1;
2604+ }
2605+
2606+ /* Re-read the name of the interface because its name has changed
2607+ * and would be automatically allocated by the system
2608+ */
2609+ if (!if_indextoname(netdev->ifindex, current_ifname)) {
2610+ ERROR("no interface corresponding to index '%d'",
2611+ netdev->ifindex);
2612+ return -1;
2613+ }
2614+
2615+ /* set a mac address */
2616+ if (netdev->hwaddr) {
2617+ if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
2618+ ERROR("failed to setup hw address for '%s'",
2619+ current_ifname);
2620+ return -1;
2621+ }
2622+ }
2623+
2624+ /* setup ipv4 addresses on the interface */
2625+ if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
2626+ ERROR("failed to setup ip addresses for '%s'",
2627+ ifname);
2628+ return -1;
2629+ }
2630+
2631+ /* setup ipv6 addresses on the interface */
2632+ if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
2633+ ERROR("failed to setup ipv6 addresses for '%s'",
2634+ ifname);
2635+ return -1;
2636+ }
2637+
2638+ /* set the network device up */
2639+ if (netdev->flags & IFF_UP) {
2640+ int err;
2641+
2642+ err = lxc_netdev_up(current_ifname);
2643+ if (err) {
2644+ ERROR("failed to set '%s' up : %s", current_ifname,
2645+ strerror(-err));
2646+ return -1;
2647+ }
2648+
2649+ /* the network is up, make the loopback up too */
2650+ err = lxc_netdev_up("lo");
2651+ if (err) {
2652+ ERROR("failed to set the loopback up : %s",
2653+ strerror(-err));
2654+ return -1;
2655+ }
2656+ }
2657+
2658+ DEBUG("'%s' has been setup", current_ifname);
2659+
2660+ return 0;
2661+}
2662+
2663+static int setup_network(struct lxc_list *network)
2664+{
2665+ struct lxc_list *iterator;
2666+ struct lxc_netdev *netdev;
2667+
2668+ lxc_list_for_each(iterator, network) {
2669+
2670+ netdev = iterator->elem;
2671+
2672+ if (setup_netdev(netdev)) {
2673+ ERROR("failed to setup netdev");
2674+ return -1;
2675+ }
2676+ }
2677+
2678+ if (!lxc_list_empty(network))
2679+ INFO("network has been setup");
2680+
2681+ return 0;
2682+}
2683+
2684+struct lxc_conf *lxc_conf_init(void)
2685+{
2686+ struct lxc_conf *new;
2687+
2688+ new = malloc(sizeof(*new));
2689+ if (!new) {
2690+ ERROR("lxc_conf_init : %m");
2691+ return NULL;
2692+ }
2693+ memset(new, 0, sizeof(*new));
2694+
2695+ new->personality = -1;
2696+ new->console.path = NULL;
2697+ new->console.peer = -1;
2698+ new->console.master = -1;
2699+ new->console.slave = -1;
2700+ new->console.name[0] = '\0';
2701+ new->rootfs.mount = LXCROOTFSMOUNT;
2702+ lxc_list_init(&new->cgroup);
2703+ lxc_list_init(&new->network);
2704+ lxc_list_init(&new->mount_list);
2705+ lxc_list_init(&new->caps);
2706+
2707+ return new;
2708+}
2709+
2710+static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
2711+{
2712+ char veth1buf[IFNAMSIZ], *veth1;
2713+ char veth2buf[IFNAMSIZ], *veth2;
2714+ int err;
2715+
2716+ if (netdev->priv.veth_attr.pair)
2717+ veth1 = netdev->priv.veth_attr.pair;
2718+ else {
2719+ snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
2720+ veth1 = mktemp(veth1buf);
2721+ }
2722+
2723+ snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
2724+ veth2 = mktemp(veth2buf);
2725+
2726+ if (!strlen(veth1) || !strlen(veth2)) {
2727+ ERROR("failed to allocate a temporary name");
2728+ return -1;
2729+ }
2730+
2731+ err = lxc_veth_create(veth1, veth2);
2732+ if (err) {
2733+ ERROR("failed to create %s-%s : %s", veth1, veth2,
2734+ strerror(-err));
2735+ return -1;
2736+ }
2737+
2738+ if (netdev->mtu) {
2739+ err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
2740+ if (!err)
2741+ err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
2742+ if (err) {
2743+ ERROR("failed to set mtu '%s' for %s-%s : %s",
2744+ netdev->mtu, veth1, veth2, strerror(-err));
2745+ goto out_delete;
2746+ }
2747+ }
2748+
2749+ if (netdev->link) {
2750+ err = lxc_bridge_attach(netdev->link, veth1);
2751+ if (err) {
2752+ ERROR("failed to attach '%s' to the bridge '%s' : %s",
2753+ veth1, netdev->link, strerror(-err));
2754+ goto out_delete;
2755+ }
2756+ }
2757+
2758+ netdev->ifindex = if_nametoindex(veth2);
2759+ if (!netdev->ifindex) {
2760+ ERROR("failed to retrieve the index for %s", veth2);
2761+ goto out_delete;
2762+ }
2763+
2764+ err = lxc_netdev_up(veth1);
2765+ if (err) {
2766+ ERROR("failed to set %s up : %s", veth1, strerror(-err));
2767+ goto out_delete;
2768+ }
2769+
2770+ if (netdev->upscript) {
2771+ err = run_script(handler->name, "net", netdev->upscript, "up",
2772+ "veth", veth1, (char*) NULL);
2773+ if (err)
2774+ goto out_delete;
2775+ }
2776+
2777+ DEBUG("instanciated veth '%s/%s', index is '%d'",
2778+ veth1, veth2, netdev->ifindex);
2779+
2780+ return 0;
2781+
2782+out_delete:
2783+ lxc_netdev_delete_by_name(veth1);
2784+ return -1;
2785+}
2786+
2787+static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2788+{
2789+ char peerbuf[IFNAMSIZ], *peer;
2790+ int err;
2791+
2792+ if (!netdev->link) {
2793+ ERROR("no link specified for macvlan netdev");
2794+ return -1;
2795+ }
2796+
2797+ snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
2798+
2799+ peer = mktemp(peerbuf);
2800+ if (!strlen(peer)) {
2801+ ERROR("failed to make a temporary name");
2802+ return -1;
2803+ }
2804+
2805+ err = lxc_macvlan_create(netdev->link, peer,
2806+ netdev->priv.macvlan_attr.mode);
2807+ if (err) {
2808+ ERROR("failed to create macvlan interface '%s' on '%s' : %s",
2809+ peer, netdev->link, strerror(-err));
2810+ return -1;
2811+ }
2812+
2813+ netdev->ifindex = if_nametoindex(peer);
2814+ if (!netdev->ifindex) {
2815+ ERROR("failed to retrieve the index for %s", peer);
2816+ lxc_netdev_delete_by_name(peer);
2817+ return -1;
2818+ }
2819+
2820+ if (netdev->upscript) {
2821+ err = run_script(handler->name, "net", netdev->upscript, "up",
2822+ "macvlan", netdev->link, (char*) NULL);
2823+ if (err)
2824+ return -1;
2825+ }
2826+
2827+ DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
2828+ peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
2829+
2830+ return 0;
2831+}
2832+
2833+/* XXX: merge with instanciate_macvlan */
2834+static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
2835+{
2836+ char peer[IFNAMSIZ];
2837+ int err;
2838+
2839+ if (!netdev->link) {
2840+ ERROR("no link specified for vlan netdev");
2841+ return -1;
2842+ }
2843+
2844+ snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
2845+
2846+ err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
2847+ if (err) {
2848+ ERROR("failed to create vlan interface '%s' on '%s' : %s",
2849+ peer, netdev->link, strerror(-err));
2850+ return -1;
2851+ }
2852+
2853+ netdev->ifindex = if_nametoindex(peer);
2854+ if (!netdev->ifindex) {
2855+ ERROR("failed to retrieve the ifindex for %s", peer);
2856+ lxc_netdev_delete_by_name(peer);
2857+ return -1;
2858+ }
2859+
2860+ DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
2861+ netdev->ifindex);
2862+
2863+ return 0;
2864+}
2865+
2866+static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
2867+{
2868+ if (!netdev->link) {
2869+ ERROR("no link specified for the physical interface");
2870+ return -1;
2871+ }
2872+
2873+ netdev->ifindex = if_nametoindex(netdev->link);
2874+ if (!netdev->ifindex) {
2875+ ERROR("failed to retrieve the index for %s", netdev->link);
2876+ return -1;
2877+ }
2878+
2879+ if (netdev->upscript) {
2880+ int err;
2881+ err = run_script(handler->name, "net", netdev->upscript,
2882+ "up", "phys", netdev->link, (char*) NULL);
2883+ if (err)
2884+ return -1;
2885+ }
2886+
2887+ return 0;
2888+}
2889+
2890+static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
2891+{
2892+ netdev->ifindex = 0;
2893+ if (netdev->upscript) {
2894+ int err;
2895+ err = run_script(handler->name, "net", netdev->upscript,
2896+ "up", "empty", (char*) NULL);
2897+ if (err)
2898+ return -1;
2899+ }
2900+ return 0;
2901+}
2902+
2903+int lxc_create_network(struct lxc_handler *handler)
2904+{
2905+ struct lxc_list *network = &handler->conf->network;
2906+ struct lxc_list *iterator;
2907+ struct lxc_netdev *netdev;
2908+
2909+ lxc_list_for_each(iterator, network) {
2910+
2911+ netdev = iterator->elem;
2912+
2913+ if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
2914+ ERROR("invalid network configuration type '%d'",
2915+ netdev->type);
2916+ return -1;
2917+ }
2918+
2919+ if (netdev_conf[netdev->type](handler, netdev)) {
2920+ ERROR("failed to create netdev");
2921+ return -1;
2922+ }
2923+
2924+ }
2925+
2926+ return 0;
2927+}
2928+
2929+void lxc_delete_network(struct lxc_list *network)
2930+{
2931+ struct lxc_list *iterator;
2932+ struct lxc_netdev *netdev;
2933+
2934+ lxc_list_for_each(iterator, network) {
2935+ netdev = iterator->elem;
2936+ if (netdev->ifindex == 0)
2937+ continue;
2938+
2939+ /* Recent kernels already delete the virtual devices */
2940+ if (netdev->type != LXC_NET_PHYS)
2941+ continue;
2942+
2943+ if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
2944+ WARN("failed to rename to the initial name the netdev '%s'",
2945+ netdev->link);
2946+ }
2947+}
2948+
2949+int lxc_assign_network(struct lxc_list *network, pid_t pid)
2950+{
2951+ struct lxc_list *iterator;
2952+ struct lxc_netdev *netdev;
2953+ int err;
2954+
2955+ lxc_list_for_each(iterator, network) {
2956+
2957+ netdev = iterator->elem;
2958+
2959+ /* empty network namespace, nothing to move */
2960+ if (!netdev->ifindex)
2961+ continue;
2962+
2963+ err = lxc_netdev_move_by_index(netdev->ifindex, pid);
2964+ if (err) {
2965+ ERROR("failed to move '%s' to the container : %s",
2966+ netdev->link, strerror(-err));
2967+ return -1;
2968+ }
2969+
2970+ DEBUG("move '%s' to '%d'", netdev->name, pid);
2971+ }
2972+
2973+ return 0;
2974+}
2975+
2976+int lxc_create_tty(const char *name, struct lxc_conf *conf)
2977+{
2978+ struct lxc_tty_info *tty_info = &conf->tty_info;
2979+ int i;
2980+
2981+ /* no tty in the configuration */
2982+ if (!conf->tty)
2983+ return 0;
2984+
2985+ tty_info->pty_info =
2986+ malloc(sizeof(*tty_info->pty_info)*conf->tty);
2987+ if (!tty_info->pty_info) {
2988+ SYSERROR("failed to allocate pty_info");
2989+ return -1;
2990+ }
2991+
2992+ for (i = 0; i < conf->tty; i++) {
2993+
2994+ struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
2995+
2996+ if (openpty(&pty_info->master, &pty_info->slave,
2997+ pty_info->name, NULL, NULL)) {
2998+ SYSERROR("failed to create pty #%d", i);
2999+ tty_info->nbtty = i;
3000+ lxc_delete_tty(tty_info);
3001+ return -1;
3002+ }
3003+
3004+ DEBUG("allocated pty '%s' (%d/%d)",
3005+ pty_info->name, pty_info->master, pty_info->slave);
3006+
3007+ /* Prevent leaking the file descriptors to the container */
3008+ fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
3009+ fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
3010+
3011+ pty_info->busy = 0;
3012+ }
3013+
3014+ tty_info->nbtty = conf->tty;
3015+
3016+ INFO("tty's configured");
3017+
3018+ return 0;
3019+}
3020+
3021+void lxc_delete_tty(struct lxc_tty_info *tty_info)
3022+{
3023+ int i;
3024+
3025+ for (i = 0; i < tty_info->nbtty; i++) {
3026+ struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
3027+
3028+ close(pty_info->master);
3029+ close(pty_info->slave);
3030+ }
3031+
3032+ free(tty_info->pty_info);
3033+ tty_info->nbtty = 0;
3034+}
3035+
3036+int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
3037+{
3038+ if (setup_utsname(lxc_conf->utsname)) {
3039+ ERROR("failed to setup the utsname for '%s'", name);
3040+ return -1;
3041+ }
3042+
3043+ if (setup_network(&lxc_conf->network)) {
3044+ ERROR("failed to setup the network for '%s'", name);
3045+ return -1;
3046+ }
3047+
3048+ if (setup_rootfs(&lxc_conf->rootfs)) {
3049+ ERROR("failed to setup rootfs for '%s'", name);
3050+ return -1;
3051+ }
3052+
3053+ if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab)) {
3054+ ERROR("failed to setup the mounts for '%s'", name);
3055+ return -1;
3056+ }
3057+
3058+ if (setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list)) {
3059+ ERROR("failed to setup the mount entries for '%s'", name);
3060+ return -1;
3061+ }
3062+
3063+ if (setup_cgroup(name, &lxc_conf->cgroup)) {
3064+ ERROR("failed to setup the cgroups for '%s'", name);
3065+ return -1;
3066+ }
3067+
3068+ if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
3069+ ERROR("failed to setup the console for '%s'", name);
3070+ return -1;
3071+ }
3072+
3073+ if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info, lxc_conf->ttydir)) {
3074+ ERROR("failed to setup the ttys for '%s'", name);
3075+ return -1;
3076+ }
3077+
3078+ if (setup_pivot_root(&lxc_conf->rootfs)) {
3079+ ERROR("failed to set rootfs for '%s'", name);
3080+ return -1;
3081+ }
3082+
3083+ if (setup_pts(lxc_conf->pts)) {
3084+ ERROR("failed to setup the new pts instance");
3085+ return -1;
3086+ }
3087+
3088+ if (setup_personality(lxc_conf->personality)) {
3089+ ERROR("failed to setup personality");
3090+ return -1;
3091+ }
3092+
3093+ if (setup_caps(&lxc_conf->caps)) {
3094+ ERROR("failed to drop capabilities");
3095+ return -1;
3096+ }
3097+
3098+ NOTICE("'%s' is setup.", name);
3099+
3100+ return 0;
3101+}
3102
3103=== added file '.pc/0053-lxc-start-pin-rootfs/src/lxc/conf.h'
3104--- .pc/0053-lxc-start-pin-rootfs/src/lxc/conf.h 1970-01-01 00:00:00 +0000
3105+++ .pc/0053-lxc-start-pin-rootfs/src/lxc/conf.h 2012-03-02 15:11:19 +0000
3106@@ -0,0 +1,233 @@
3107+/*
3108+ * lxc: linux Container library
3109+ *
3110+ * (C) Copyright IBM Corp. 2007, 2008
3111+ *
3112+ * Authors:
3113+ * Daniel Lezcano <dlezcano at fr.ibm.com>
3114+ *
3115+ * This library is free software; you can redistribute it and/or
3116+ * modify it under the terms of the GNU Lesser General Public
3117+ * License as published by the Free Software Foundation; either
3118+ * version 2.1 of the License, or (at your option) any later version.
3119+ *
3120+ * This library is distributed in the hope that it will be useful,
3121+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3122+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3123+ * Lesser General Public License for more details.
3124+ *
3125+ * You should have received a copy of the GNU Lesser General Public
3126+ * License along with this library; if not, write to the Free Software
3127+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3128+ */
3129+#ifndef _conf_h
3130+#define _conf_h
3131+
3132+#include <netinet/in.h>
3133+#include <sys/param.h>
3134+
3135+#include <lxc/list.h>
3136+
3137+#include <lxc/start.h> /* for lxc_handler */
3138+
3139+enum {
3140+ LXC_NET_EMPTY,
3141+ LXC_NET_VETH,
3142+ LXC_NET_MACVLAN,
3143+ LXC_NET_PHYS,
3144+ LXC_NET_VLAN,
3145+ LXC_NET_MAXCONFTYPE,
3146+};
3147+
3148+/*
3149+ * Defines the structure to configure an ipv4 address
3150+ * @address : ipv4 address
3151+ * @broadcast : ipv4 broadcast address
3152+ * @mask : network mask
3153+ */
3154+struct lxc_inetdev {
3155+ struct in_addr addr;
3156+ struct in_addr bcast;
3157+ int prefix;
3158+};
3159+
3160+struct lxc_route {
3161+ struct in_addr addr;
3162+};
3163+
3164+/*
3165+ * Defines the structure to configure an ipv6 address
3166+ * @flags : set the address up
3167+ * @address : ipv6 address
3168+ * @broadcast : ipv6 broadcast address
3169+ * @mask : network mask
3170+ */
3171+struct lxc_inet6dev {
3172+ struct in6_addr addr;
3173+ struct in6_addr mcast;
3174+ struct in6_addr acast;
3175+ int prefix;
3176+};
3177+
3178+struct lxc_route6 {
3179+ struct in6_addr addr;
3180+};
3181+
3182+struct ifla_veth {
3183+ char *pair; /* pair name */
3184+};
3185+
3186+struct ifla_vlan {
3187+ uint flags;
3188+ uint fmask;
3189+ ushort vid;
3190+ ushort pad;
3191+};
3192+
3193+struct ifla_macvlan {
3194+ int mode; /* private, vepa, bridge */
3195+};
3196+
3197+union netdev_p {
3198+ struct ifla_veth veth_attr;
3199+ struct ifla_vlan vlan_attr;
3200+ struct ifla_macvlan macvlan_attr;
3201+};
3202+
3203+/*
3204+ * Defines a structure to configure a network device
3205+ * @link : lxc.network.link, name of bridge or host iface to attach if any
3206+ * @name : lxc.network.name, name of iface on the container side
3207+ * @flags : flag of the network device (IFF_UP, ... )
3208+ * @ipv4 : a list of ipv4 addresses to be set on the network device
3209+ * @ipv6 : a list of ipv6 addresses to be set on the network device
3210+ * @upscript : a script filename to be executed during interface configuration
3211+ */
3212+struct lxc_netdev {
3213+ int type;
3214+ int flags;
3215+ int ifindex;
3216+ char *link;
3217+ char *name;
3218+ char *hwaddr;
3219+ char *mtu;
3220+ union netdev_p priv;
3221+ struct lxc_list ipv4;
3222+ struct lxc_list ipv6;
3223+ char *upscript;
3224+};
3225+
3226+/*
3227+ * Defines a generic struct to configure the control group.
3228+ * It is up to the programmer to specify the right subsystem.
3229+ * @subsystem : the targetted subsystem
3230+ * @value : the value to set
3231+ */
3232+struct lxc_cgroup {
3233+ char *subsystem;
3234+ char *value;
3235+};
3236+
3237+/*
3238+ * Defines a structure containing a pty information for
3239+ * virtualizing a tty
3240+ * @name : the path name of the slave pty side
3241+ * @master : the file descriptor of the master
3242+ * @slave : the file descriptor of the slave
3243+ */
3244+struct lxc_pty_info {
3245+ char name[MAXPATHLEN];
3246+ int master;
3247+ int slave;
3248+ int busy;
3249+};
3250+
3251+/*
3252+ * Defines the number of tty configured and contains the
3253+ * instanciated ptys
3254+ * @nbtty = number of configured ttys
3255+ */
3256+struct lxc_tty_info {
3257+ int nbtty;
3258+ struct lxc_pty_info *pty_info;
3259+};
3260+
3261+/*
3262+ * Defines the structure to store the console information
3263+ * @peer : the file descriptor put/get console traffic
3264+ * @name : the file name of the slave pty
3265+ */
3266+struct lxc_console {
3267+ int slave;
3268+ int master;
3269+ int peer;
3270+ char *path;
3271+ char name[MAXPATHLEN];
3272+ struct termios *tios;
3273+};
3274+
3275+/*
3276+ * Defines a structure to store the rootfs location, the
3277+ * optionals pivot_root, rootfs mount paths
3278+ * @rootfs : a path to the rootfs
3279+ * @pivot_root : a path to a pivot_root location to be used
3280+ */
3281+struct lxc_rootfs {
3282+ char *path;
3283+ char *mount;
3284+ char *pivot;
3285+};
3286+
3287+/*
3288+ * Defines the global container configuration
3289+ * @rootfs : root directory to run the container
3290+ * @pivotdir : pivotdir path, if not set default will be used
3291+ * @mount : list of mount points
3292+ * @tty : numbers of tty
3293+ * @pts : new pts instance
3294+ * @mount_list : list of mount point (alternative to fstab file)
3295+ * @network : network configuration
3296+ * @utsname : container utsname
3297+ * @fstab : path to a fstab file format
3298+ * @caps : list of the capabilities
3299+ * @tty_info : tty data
3300+ * @console : console data
3301+ * @ttydir : directory (under /dev) in which to create console and ttys
3302+ */
3303+struct lxc_conf {
3304+ char *fstab;
3305+ int tty;
3306+ int pts;
3307+ int reboot;
3308+ int need_utmp_watch;
3309+ int personality;
3310+ struct utsname *utsname;
3311+ struct lxc_list cgroup;
3312+ struct lxc_list network;
3313+ struct lxc_list mount_list;
3314+ struct lxc_list caps;
3315+ struct lxc_tty_info tty_info;
3316+ struct lxc_console console;
3317+ struct lxc_rootfs rootfs;
3318+ char *ttydir;
3319+ int close_all_fds;
3320+};
3321+
3322+/*
3323+ * Initialize the lxc configuration structure
3324+ */
3325+extern struct lxc_conf *lxc_conf_init(void);
3326+
3327+extern int lxc_create_network(struct lxc_handler *handler);
3328+extern void lxc_delete_network(struct lxc_list *networks);
3329+extern int lxc_assign_network(struct lxc_list *networks, pid_t pid);
3330+
3331+extern int lxc_create_tty(const char *name, struct lxc_conf *conf);
3332+extern void lxc_delete_tty(struct lxc_tty_info *tty_info);
3333+
3334+/*
3335+ * Configure the container from inside
3336+ */
3337+
3338+extern int lxc_setup(const char *name, struct lxc_conf *lxc_conf);
3339+#endif
3340
3341=== added file '.pc/0053-lxc-start-pin-rootfs/src/lxc/start.c'
3342--- .pc/0053-lxc-start-pin-rootfs/src/lxc/start.c 1970-01-01 00:00:00 +0000
3343+++ .pc/0053-lxc-start-pin-rootfs/src/lxc/start.c 2012-03-02 15:11:19 +0000
3344@@ -0,0 +1,748 @@
3345+/*
3346+ * lxc: linux Container library
3347+ *
3348+ * (C) Copyright IBM Corp. 2007, 2008
3349+ *
3350+ * Authors:
3351+ * Daniel Lezcano <dlezcano at fr.ibm.com>
3352+ *
3353+ * This library is free software; you can redistribute it and/or
3354+ * modify it under the terms of the GNU Lesser General Public
3355+ * License as published by the Free Software Foundation; either
3356+ * version 2.1 of the License, or (at your option) any later version.
3357+ *
3358+ * This library is distributed in the hope that it will be useful,
3359+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3360+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3361+ * Lesser General Public License for more details.
3362+ *
3363+ * You should have received a copy of the GNU Lesser General Public
3364+ * License along with this library; if not, write to the Free Software
3365+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3366+ */
3367+
3368+#include "../config.h"
3369+#include <stdio.h>
3370+#undef _GNU_SOURCE
3371+#include <string.h>
3372+#include <stdlib.h>
3373+#include <dirent.h>
3374+#include <errno.h>
3375+#include <unistd.h>
3376+#include <signal.h>
3377+#include <fcntl.h>
3378+#include <termios.h>
3379+#include <namespace.h>
3380+#include <sys/param.h>
3381+#include <sys/file.h>
3382+#include <sys/mount.h>
3383+#include <sys/stat.h>
3384+#include <sys/types.h>
3385+#include <sys/prctl.h>
3386+#include <sys/types.h>
3387+#include <sys/capability.h>
3388+#include <sys/wait.h>
3389+#include <sys/un.h>
3390+#include <sys/poll.h>
3391+
3392+#ifdef HAVE_SYS_SIGNALFD_H
3393+# include <sys/signalfd.h>
3394+#else
3395+/* assume kernel headers are too old */
3396+#include <stdint.h>
3397+struct signalfd_siginfo
3398+{
3399+ uint32_t ssi_signo;
3400+ int32_t ssi_errno;
3401+ int32_t ssi_code;
3402+ uint32_t ssi_pid;
3403+ uint32_t ssi_uid;
3404+ int32_t ssi_fd;
3405+ uint32_t ssi_tid;
3406+ uint32_t ssi_band;
3407+ uint32_t ssi_overrun;
3408+ uint32_t ssi_trapno;
3409+ int32_t ssi_status;
3410+ int32_t ssi_int;
3411+ uint64_t ssi_ptr;
3412+ uint64_t ssi_utime;
3413+ uint64_t ssi_stime;
3414+ uint64_t ssi_addr;
3415+ uint8_t __pad[48];
3416+};
3417+
3418+# ifndef __NR_signalfd4
3419+/* assume kernel headers are too old */
3420+# if __i386__
3421+# define __NR_signalfd4 327
3422+# elif __x86_64__
3423+# define __NR_signalfd4 289
3424+# elif __powerpc__
3425+# define __NR_signalfd4 313
3426+# elif __s390x__
3427+# define __NR_signalfd4 322
3428+# endif
3429+#endif
3430+
3431+# ifndef __NR_signalfd
3432+/* assume kernel headers are too old */
3433+# if __i386__
3434+# define __NR_signalfd 321
3435+# elif __x86_64__
3436+# define __NR_signalfd 282
3437+# elif __powerpc__
3438+# define __NR_signalfd 305
3439+# elif __s390x__
3440+# define __NR_signalfd 316
3441+# endif
3442+#endif
3443+
3444+int signalfd(int fd, const sigset_t *mask, int flags)
3445+{
3446+ int retval;
3447+
3448+ retval = syscall (__NR_signalfd4, fd, mask, _NSIG / 8, flags);
3449+ if (errno == ENOSYS && flags == 0)
3450+ retval = syscall (__NR_signalfd, fd, mask, _NSIG / 8);
3451+ return retval;
3452+}
3453+#endif
3454+
3455+#if !HAVE_DECL_PR_CAPBSET_DROP
3456+#define PR_CAPBSET_DROP 24
3457+#endif
3458+
3459+#include "start.h"
3460+#include "conf.h"
3461+#include "log.h"
3462+#include "cgroup.h"
3463+#include "error.h"
3464+#include "af_unix.h"
3465+#include "mainloop.h"
3466+#include "utils.h"
3467+#include "utmp.h"
3468+#include "monitor.h"
3469+#include "commands.h"
3470+#include "console.h"
3471+#include "sync.h"
3472+
3473+lxc_log_define(lxc_start, lxc);
3474+
3475+LXC_TTY_HANDLER(SIGINT);
3476+LXC_TTY_HANDLER(SIGQUIT);
3477+
3478+static int match_fd(int fd)
3479+{
3480+ return (fd == 0 || fd == 1 || fd == 2);
3481+}
3482+
3483+int lxc_check_inherited(struct lxc_conf *conf, int fd_to_ignore)
3484+{
3485+ struct dirent dirent, *direntp;
3486+ int fd, fddir;
3487+ DIR *dir;
3488+ int ret = 0;
3489+
3490+restart:
3491+ dir = opendir("/proc/self/fd");
3492+ if (!dir) {
3493+ WARN("failed to open directory: %m");
3494+ return -1;
3495+ }
3496+
3497+ fddir = dirfd(dir);
3498+
3499+ while (!readdir_r(dir, &dirent, &direntp)) {
3500+ char procpath[64];
3501+ char path[PATH_MAX];
3502+ int gotpath = 1;
3503+
3504+ if (!direntp)
3505+ break;
3506+
3507+ if (!strcmp(direntp->d_name, "."))
3508+ continue;
3509+
3510+ if (!strcmp(direntp->d_name, ".."))
3511+ continue;
3512+
3513+ fd = atoi(direntp->d_name);
3514+
3515+ if (fd == fddir || fd == lxc_log_fd || fd == fd_to_ignore)
3516+ continue;
3517+
3518+ if (match_fd(fd))
3519+ continue;
3520+
3521+ snprintf(procpath, sizeof(procpath), "/proc/self/fd/%d", fd);
3522+ if (readlink(procpath, path, sizeof(path)) == -1)
3523+ gotpath = 0;
3524+
3525+ /*
3526+ * found inherited fd
3527+ */
3528+
3529+ if (conf->close_all_fds) {
3530+ if (!gotpath)
3531+ INFO("closing inherited fd %d\n", fd);
3532+ else
3533+ INFO("closing inherited fd %d (%s)", fd, path);
3534+ close(fd);
3535+ closedir(dir);
3536+ goto restart;
3537+ }
3538+
3539+ ret = -1;
3540+
3541+ snprintf(procpath, sizeof(procpath), "/proc/self/fd/%d", fd);
3542+
3543+ if (!gotpath)
3544+ ERROR("readlink(%s) failed : %m", procpath);
3545+ else
3546+ ERROR("inherited fd %d on %s", fd, path);
3547+ }
3548+
3549+ if (closedir(dir))
3550+ ERROR("failed to close directory");
3551+ return ret;
3552+}
3553+
3554+static int setup_signal_fd(sigset_t *oldmask)
3555+{
3556+ sigset_t mask;
3557+ int fd;
3558+
3559+ /* Block everything except serious error signals */
3560+ if (sigfillset(&mask) ||
3561+ sigdelset(&mask, SIGILL) ||
3562+ sigdelset(&mask, SIGSEGV) ||
3563+ sigdelset(&mask, SIGBUS) ||
3564+ sigprocmask(SIG_BLOCK, &mask, oldmask)) {
3565+ SYSERROR("failed to set signal mask");
3566+ return -1;
3567+ }
3568+
3569+ fd = signalfd(-1, &mask, 0);
3570+ if (fd < 0) {
3571+ SYSERROR("failed to create the signal fd");
3572+ return -1;
3573+ }
3574+
3575+ if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
3576+ SYSERROR("failed to set sigfd to close-on-exec");
3577+ close(fd);
3578+ return -1;
3579+ }
3580+
3581+ DEBUG("sigchild handler set");
3582+
3583+ return fd;
3584+}
3585+
3586+static int signal_handler(int fd, void *data,
3587+ struct lxc_epoll_descr *descr)
3588+{
3589+ struct signalfd_siginfo siginfo;
3590+ int ret;
3591+ pid_t *pid = data;
3592+
3593+ ret = read(fd, &siginfo, sizeof(siginfo));
3594+ if (ret < 0) {
3595+ ERROR("failed to read signal info");
3596+ return -1;
3597+ }
3598+
3599+ if (ret != sizeof(siginfo)) {
3600+ ERROR("unexpected siginfo size");
3601+ return -1;
3602+ }
3603+
3604+ if (siginfo.ssi_signo != SIGCHLD) {
3605+ kill(*pid, siginfo.ssi_signo);
3606+ INFO("forwarded signal %d to pid %d", siginfo.ssi_signo, *pid);
3607+ return 0;
3608+ }
3609+
3610+ if (siginfo.ssi_code == CLD_STOPPED ||
3611+ siginfo.ssi_code == CLD_CONTINUED) {
3612+ INFO("container init process was stopped/continued");
3613+ return 0;
3614+ }
3615+
3616+ /* more robustness, protect ourself from a SIGCHLD sent
3617+ * by a process different from the container init
3618+ */
3619+ if (siginfo.ssi_pid != *pid) {
3620+ WARN("invalid pid for SIGCHLD");
3621+ return 0;
3622+ }
3623+
3624+ DEBUG("container init process exited");
3625+ return 1;
3626+}
3627+
3628+int lxc_pid_callback(int fd, struct lxc_request *request,
3629+ struct lxc_handler *handler)
3630+{
3631+ struct lxc_answer answer;
3632+ int ret;
3633+
3634+ answer.pid = handler->pid;
3635+ answer.ret = 0;
3636+
3637+ ret = send(fd, &answer, sizeof(answer), 0);
3638+ if (ret < 0) {
3639+ WARN("failed to send answer to the peer");
3640+ return -1;
3641+ }
3642+
3643+ if (ret != sizeof(answer)) {
3644+ ERROR("partial answer sent");
3645+ return -1;
3646+ }
3647+
3648+ return 0;
3649+}
3650+
3651+int lxc_set_state(const char *name, struct lxc_handler *handler, lxc_state_t state)
3652+{
3653+ handler->state = state;
3654+ lxc_monitor_send_state(name, state);
3655+ return 0;
3656+}
3657+
3658+int lxc_poll(const char *name, struct lxc_handler *handler)
3659+{
3660+ int sigfd = handler->sigfd;
3661+ int pid = handler->pid;
3662+ struct lxc_epoll_descr descr;
3663+
3664+ if (lxc_mainloop_open(&descr)) {
3665+ ERROR("failed to create mainloop");
3666+ goto out_sigfd;
3667+ }
3668+
3669+ if (lxc_mainloop_add_handler(&descr, sigfd, signal_handler, &pid)) {
3670+ ERROR("failed to add handler for the signal");
3671+ goto out_mainloop_open;
3672+ }
3673+
3674+ if (lxc_console_mainloop_add(&descr, handler)) {
3675+ ERROR("failed to add console handler to mainloop");
3676+ goto out_mainloop_open;
3677+ }
3678+
3679+ if (lxc_command_mainloop_add(name, &descr, handler)) {
3680+ ERROR("failed to add command handler to mainloop");
3681+ goto out_mainloop_open;
3682+ }
3683+
3684+ if (handler->conf->need_utmp_watch) {
3685+ if (lxc_utmp_mainloop_add(&descr, handler)) {
3686+ ERROR("failed to add utmp handler to mainloop");
3687+ goto out_mainloop_open;
3688+ }
3689+ }
3690+
3691+ return lxc_mainloop(&descr);
3692+
3693+out_mainloop_open:
3694+ lxc_mainloop_close(&descr);
3695+out_sigfd:
3696+ close(sigfd);
3697+ return -1;
3698+}
3699+
3700+extern int lxc_caps_check(void);
3701+
3702+struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf)
3703+{
3704+ struct lxc_handler *handler;
3705+
3706+ if (!lxc_caps_check()) {
3707+ ERROR("Not running with sufficient privilege");
3708+ return NULL;
3709+ }
3710+
3711+ handler = malloc(sizeof(*handler));
3712+ if (!handler)
3713+ return NULL;
3714+
3715+ memset(handler, 0, sizeof(*handler));
3716+
3717+ handler->conf = conf;
3718+
3719+ handler->name = strdup(name);
3720+ if (!handler->name) {
3721+ ERROR("failed to allocate memory");
3722+ goto out_free;
3723+ }
3724+
3725+ /* Begin the set the state to STARTING*/
3726+ if (lxc_set_state(name, handler, STARTING)) {
3727+ ERROR("failed to set state '%s'", lxc_state2str(STARTING));
3728+ goto out_free_name;
3729+ }
3730+
3731+ if (lxc_create_tty(name, conf)) {
3732+ ERROR("failed to create the ttys");
3733+ goto out_aborting;
3734+ }
3735+
3736+ if (lxc_create_console(conf)) {
3737+ ERROR("failed to create console");
3738+ goto out_delete_tty;
3739+ }
3740+
3741+ /* the signal fd has to be created before forking otherwise
3742+ * if the child process exits before we setup the signal fd,
3743+ * the event will be lost and the command will be stuck */
3744+ handler->sigfd = setup_signal_fd(&handler->oldmask);
3745+ if (handler->sigfd < 0) {
3746+ ERROR("failed to set sigchild fd handler");
3747+ goto out_delete_console;
3748+ }
3749+
3750+ INFO("'%s' is initialized", name);
3751+ return handler;
3752+
3753+out_delete_console:
3754+ lxc_delete_console(&conf->console);
3755+out_delete_tty:
3756+ lxc_delete_tty(&conf->tty_info);
3757+out_aborting:
3758+ lxc_set_state(name, handler, ABORTING);
3759+out_free_name:
3760+ free(handler->name);
3761+ handler->name = NULL;
3762+out_free:
3763+ free(handler);
3764+ return NULL;
3765+}
3766+
3767+void lxc_fini(const char *name, struct lxc_handler *handler)
3768+{
3769+ /* The STOPPING state is there for future cleanup code
3770+ * which can take awhile
3771+ */
3772+ lxc_set_state(name, handler, STOPPING);
3773+ lxc_set_state(name, handler, STOPPED);
3774+
3775+ /* reset mask set by setup_signal_fd */
3776+ if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL))
3777+ WARN("failed to restore sigprocmask");
3778+
3779+ lxc_delete_console(&handler->conf->console);
3780+ lxc_delete_tty(&handler->conf->tty_info);
3781+ free(handler->name);
3782+ free(handler);
3783+}
3784+
3785+void lxc_abort(const char *name, struct lxc_handler *handler)
3786+{
3787+ lxc_set_state(name, handler, ABORTING);
3788+ if (handler->pid > 0)
3789+ kill(handler->pid, SIGKILL);
3790+}
3791+
3792+#include <sys/reboot.h>
3793+#include <linux/reboot.h>
3794+
3795+/*
3796+ * reboot(LINUX_REBOOT_CMD_CAD_ON) will return -EINVAL
3797+ * in a child pid namespace if container reboot support exists.
3798+ * Otherwise, it will either succeed or return -EPERM.
3799+ */
3800+static int container_reboot_supported(void *arg)
3801+{
3802+ int *cmd = arg;
3803+ int ret;
3804+
3805+ ret = reboot(*cmd);
3806+ if (ret == -1 && errno == EINVAL)
3807+ return 1;
3808+ return 0;
3809+}
3810+
3811+static int must_drop_cap_sys_boot(void)
3812+{
3813+ FILE *f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
3814+ int ret, cmd, v;
3815+ long stack_size = 4096;
3816+ void *stack = alloca(stack_size) + stack_size;
3817+ int status;
3818+ pid_t pid;
3819+
3820+ if (!f) {
3821+ DEBUG("failed to open /proc/sys/kernel/ctrl-alt-del");
3822+ return 1;
3823+ }
3824+
3825+ ret = fscanf(f, "%d", &v);
3826+ fclose(f);
3827+ if (ret != 1) {
3828+ DEBUG("Failed to read /proc/sys/kernel/ctrl-alt-del");
3829+ return 1;
3830+ }
3831+ cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF;
3832+
3833+ pid = clone(container_reboot_supported, stack, CLONE_NEWPID | SIGCHLD, &cmd);
3834+ if (pid < 0) {
3835+ SYSERROR("failed to clone\n");
3836+ return -1;
3837+ }
3838+ if (wait(&status) < 0) {
3839+ SYSERROR("unexpected wait error: %m\n");
3840+ return -1;
3841+ }
3842+
3843+ if (WEXITSTATUS(status) != 1)
3844+ return 1;
3845+
3846+ return 0;
3847+}
3848+
3849+static int do_start(void *data)
3850+{
3851+ struct lxc_handler *handler = data;
3852+
3853+ if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
3854+ SYSERROR("failed to set sigprocmask");
3855+ return -1;
3856+ }
3857+
3858+ /* This prctl must be before the synchro, so if the parent
3859+ * dies before we set the parent death signal, we will detect
3860+ * its death with the synchro right after, otherwise we have
3861+ * a window where the parent can exit before we set the pdeath
3862+ * signal leading to a unsupervized container.
3863+ */
3864+ if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
3865+ SYSERROR("failed to set pdeath signal");
3866+ return -1;
3867+ }
3868+
3869+ lxc_sync_fini_parent(handler);
3870+
3871+ /* Tell the parent task it can begin to configure the
3872+ * container and wait for it to finish
3873+ */
3874+ if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE))
3875+ return -1;
3876+
3877+ if (must_drop_cap_sys_boot()) {
3878+ if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
3879+ SYSERROR("failed to remove CAP_SYS_BOOT capability");
3880+ return -1;
3881+ }
3882+ handler->conf->need_utmp_watch = 1;
3883+ DEBUG("Dropped cap_sys_boot\n");
3884+ } else {
3885+ DEBUG("Not dropping cap_sys_boot or watching utmp\n");
3886+ handler->conf->need_utmp_watch = 0;
3887+ }
3888+
3889+ /* Setup the container, ip, names, utsname, ... */
3890+ if (lxc_setup(handler->name, handler->conf)) {
3891+ ERROR("failed to setup the container");
3892+ goto out_warn_father;
3893+ }
3894+
3895+ close(handler->sigfd);
3896+
3897+ /* after this call, we are in error because this
3898+ * ops should not return as it execs */
3899+ if (handler->ops->start(handler, handler->data))
3900+ return -1;
3901+
3902+out_warn_father:
3903+ lxc_sync_wake_parent(handler, LXC_SYNC_POST_CONFIGURE);
3904+ return -1;
3905+}
3906+
3907+int lxc_spawn(struct lxc_handler *handler)
3908+{
3909+ int clone_flags;
3910+ int failed_before_rename = 0;
3911+ const char *name = handler->name;
3912+
3913+ if (lxc_sync_init(handler))
3914+ return -1;
3915+
3916+ clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
3917+ if (!lxc_list_empty(&handler->conf->network)) {
3918+
3919+ clone_flags |= CLONE_NEWNET;
3920+
3921+ /* that should be done before the clone because we will
3922+ * fill the netdev index and use them in the child
3923+ */
3924+ if (lxc_create_network(handler)) {
3925+ ERROR("failed to create the network");
3926+ lxc_sync_fini(handler);
3927+ return -1;
3928+ }
3929+ }
3930+
3931+
3932+ /* Create a process in a new set of namespaces */
3933+ handler->pid = lxc_clone(do_start, handler, clone_flags);
3934+ if (handler->pid < 0) {
3935+ SYSERROR("failed to fork into a new namespace");
3936+ goto out_delete_net;
3937+ }
3938+
3939+ lxc_sync_fini_child(handler);
3940+
3941+ if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE))
3942+ failed_before_rename = 1;
3943+
3944+ if (lxc_cgroup_create(name, handler->pid))
3945+ goto out_delete_net;
3946+
3947+ if (failed_before_rename)
3948+ goto out_delete_net;
3949+
3950+ /* Create the network configuration */
3951+ if (clone_flags & CLONE_NEWNET) {
3952+ if (lxc_assign_network(&handler->conf->network, handler->pid)) {
3953+ ERROR("failed to create the configured network");
3954+ goto out_delete_net;
3955+ }
3956+ }
3957+
3958+ /* Tell the child to continue its initialization and wait for
3959+ * it to exec or return an error
3960+ */
3961+ if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
3962+ return -1;
3963+
3964+ if (handler->ops->post_start(handler, handler->data))
3965+ goto out_abort;
3966+
3967+ if (lxc_set_state(name, handler, RUNNING)) {
3968+ ERROR("failed to set state to %s",
3969+ lxc_state2str(RUNNING));
3970+ goto out_abort;
3971+ }
3972+
3973+ lxc_sync_fini(handler);
3974+ return 0;
3975+
3976+out_delete_net:
3977+ if (clone_flags & CLONE_NEWNET)
3978+ lxc_delete_network(&handler->conf->network);
3979+out_abort:
3980+ lxc_abort(name, handler);
3981+ lxc_sync_fini(handler);
3982+ return -1;
3983+}
3984+
3985+int __lxc_start(const char *name, struct lxc_conf *conf,
3986+ struct lxc_operations* ops, void *data)
3987+{
3988+ struct lxc_handler *handler;
3989+ int err = -1;
3990+ int status;
3991+
3992+ handler = lxc_init(name, conf);
3993+ if (!handler) {
3994+ ERROR("failed to initialize the container");
3995+ return -1;
3996+ }
3997+ handler->ops = ops;
3998+ handler->data = data;
3999+
4000+ err = lxc_spawn(handler);
4001+ if (err) {
4002+ ERROR("failed to spawn '%s'", name);
4003+ goto out_fini;
4004+ }
4005+
4006+ /* Avoid signals from terminal */
4007+ LXC_TTY_ADD_HANDLER(SIGINT);
4008+ LXC_TTY_ADD_HANDLER(SIGQUIT);
4009+
4010+ err = lxc_poll(name, handler);
4011+ if (err) {
4012+ ERROR("mainloop exited with an error");
4013+ goto out_abort;
4014+ }
4015+
4016+ while (waitpid(handler->pid, &status, 0) < 0 && errno == EINTR)
4017+ continue;
4018+
4019+ /*
4020+ * If the child process exited but was not signaled,
4021+ * it didn't call reboot. This should mean it was an
4022+ * lxc-execute which simply exited. In any case, treat
4023+ * it as a 'halt'
4024+ */
4025+ if (WIFSIGNALED(status)) {
4026+ switch(WTERMSIG(status)) {
4027+ case SIGINT: /* halt */
4028+ DEBUG("Container halting");
4029+ break;
4030+ case SIGHUP: /* reboot */
4031+ DEBUG("Container rebooting");
4032+ handler->conf->reboot = 1;
4033+ break;
4034+ default:
4035+ DEBUG("unknown exit status for init: %d\n", WTERMSIG(status));
4036+ break;
4037+ }
4038+ }
4039+
4040+ err = lxc_error_set_and_log(handler->pid, status);
4041+out_fini:
4042+ LXC_TTY_DEL_HANDLER(SIGQUIT);
4043+ LXC_TTY_DEL_HANDLER(SIGINT);
4044+ lxc_cgroup_destroy(name);
4045+ lxc_fini(name, handler);
4046+ return err;
4047+
4048+out_abort:
4049+ lxc_abort(name, handler);
4050+ goto out_fini;
4051+}
4052+
4053+struct start_args {
4054+ char *const *argv;
4055+};
4056+
4057+static int start(struct lxc_handler *handler, void* data)
4058+{
4059+ struct start_args *arg = data;
4060+
4061+ NOTICE("exec'ing '%s'", arg->argv[0]);
4062+
4063+ execvp(arg->argv[0], arg->argv);
4064+ SYSERROR("failed to exec %s", arg->argv[0]);
4065+ return 0;
4066+}
4067+
4068+static int post_start(struct lxc_handler *handler, void* data)
4069+{
4070+ struct start_args *arg = data;
4071+
4072+ NOTICE("'%s' started with pid '%d'", arg->argv[0], handler->pid);
4073+ return 0;
4074+}
4075+
4076+static struct lxc_operations start_ops = {
4077+ .start = start,
4078+ .post_start = post_start
4079+};
4080+
4081+int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf)
4082+{
4083+ struct start_args start_arg = {
4084+ .argv = argv,
4085+ };
4086+
4087+ if (lxc_check_inherited(conf, -1))
4088+ return -1;
4089+
4090+ conf->need_utmp_watch = 1;
4091+ return __lxc_start(name, conf, &start_ops, &start_arg);
4092+}
4093
4094=== added directory '.pc/0054-ubuntu-debug'
4095=== renamed directory '.pc/0054-ubuntu-debug' => '.pc/0054-ubuntu-debug.moved'
4096=== added file '.pc/0054-ubuntu-debug/.timestamp'
4097=== added directory '.pc/0054-ubuntu-debug/templates'
4098=== added file '.pc/0054-ubuntu-debug/templates/lxc-ubuntu-cloud.in'
4099--- .pc/0054-ubuntu-debug/templates/lxc-ubuntu-cloud.in 1970-01-01 00:00:00 +0000
4100+++ .pc/0054-ubuntu-debug/templates/lxc-ubuntu-cloud.in 2012-03-02 15:11:19 +0000
4101@@ -0,0 +1,304 @@
4102+#!/bin/bash
4103+
4104+# template script for generating ubuntu container for LXC based on daily cloud
4105+# images
4106+#
4107+# Copyright © 2012 Serge Hallyn <serge.hallyn@canonical.com>
4108+#
4109+# This program is free software; you can redistribute it and/or modify
4110+# it under the terms of the GNU General Public License version 2, as
4111+# published by the Free Software Foundation.
4112+
4113+# This program is distributed in the hope that it will be useful,
4114+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4115+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4116+# GNU General Public License for more details.
4117+
4118+# You should have received a copy of the GNU General Public License along
4119+# with this program; if not, write to the Free Software Foundation, Inc.,
4120+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
4121+#
4122+
4123+set -e
4124+
4125+if [ -r /etc/default/lxc ]; then
4126+ . /etc/default/lxc
4127+fi
4128+
4129+copy_configuration()
4130+{
4131+ path=$1
4132+ rootfs=$2
4133+ name=$3
4134+ arch=$4
4135+
4136+ if [ $arch = "i386" ]; then
4137+ arch="i686"
4138+ fi
4139+
4140+ # if there is exactly one veth network entry, make sure it has an
4141+ # associated hwaddr.
4142+ nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
4143+ if [ $nics -eq 1 ]; then
4144+ grep -q "^lxc.network.hwaddr" $path/config || cat <<EOF >> $path/config
4145+lxc.network.hwaddr= 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')
4146+EOF
4147+ fi
4148+
4149+ cat <<EOF >> $path/config
4150+lxc.utsname = $name
4151+
4152+lxc.tty = 4
4153+lxc.pts = 1024
4154+lxc.rootfs = $rootfs
4155+lxc.mount = $path/fstab
4156+lxc.arch = $arch
4157+lxc.cap.drop = sys_module mac_admin
4158+
4159+lxc.cgroup.devices.deny = a
4160+# Allow any mknod (but not using the node)
4161+lxc.cgroup.devices.allow = c *:* m
4162+lxc.cgroup.devices.allow = b *:* m
4163+# /dev/null and zero
4164+lxc.cgroup.devices.allow = c 1:3 rwm
4165+lxc.cgroup.devices.allow = c 1:5 rwm
4166+# consoles
4167+lxc.cgroup.devices.allow = c 5:1 rwm
4168+lxc.cgroup.devices.allow = c 5:0 rwm
4169+#lxc.cgroup.devices.allow = c 4:0 rwm
4170+#lxc.cgroup.devices.allow = c 4:1 rwm
4171+# /dev/{,u}random
4172+lxc.cgroup.devices.allow = c 1:9 rwm
4173+lxc.cgroup.devices.allow = c 1:8 rwm
4174+lxc.cgroup.devices.allow = c 136:* rwm
4175+lxc.cgroup.devices.allow = c 5:2 rwm
4176+# rtc
4177+lxc.cgroup.devices.allow = c 254:0 rwm
4178+#fuse
4179+lxc.cgroup.devices.allow = c 10:229 rwm
4180+#tun
4181+lxc.cgroup.devices.allow = c 10:200 rwm
4182+#full
4183+lxc.cgroup.devices.allow = c 1:7 rwm
4184+#hpet
4185+lxc.cgroup.devices.allow = c 10:228 rwm
4186+#kvm
4187+lxc.cgroup.devices.allow = c 10:232 rwm
4188+EOF
4189+
4190+ cat <<EOF > $path/fstab
4191+proc $rootfs/proc proc nodev,noexec,nosuid 0 0
4192+sysfs $rootfs/sys sysfs defaults 0 0
4193+EOF
4194+
4195+ return 0
4196+}
4197+
4198+usage()
4199+{
4200+ cat <<EOF
4201+LXC Container configuration for Ubuntu Cloud images.
4202+
4203+Generic Options
4204+[ -r | --release <release> ]: Release name of container, defaults to host
4205+[ -a | --arch ]: Arhcitecture of container, defaults to host arcitecture
4206+[ -C | --cloud ]: Configure container for use with meta-data service, defaults to no
4207+[ -T | --tarball ]: Location of tarball
4208+
4209+Options, mutually exclusive of "-C" and "--cloud":
4210+ [ -i | --hostid ]: HostID for cloud-init, defaults to random string
4211+ [ -u | --userdata ]: Cloud-init user-data file to configure container on start
4212+ [ -S | --auth-key ]: SSH Public key file to inject into container
4213+ [ -L | --nolocales ]: Do not copy host's locales into container
4214+
4215+EOF
4216+ return 0
4217+}
4218+
4219+options=$(getopt -o a:hp:r:n:Fi:CLS:T: -l arch:,help,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball: -- "$@")
4220+if [ $? -ne 0 ]; then
4221+ usage $(basename $0)
4222+ exit 1
4223+fi
4224+eval set -- "$options"
4225+
4226+release=lucid
4227+if [ -f /etc/lsb-release ]; then
4228+ . /etc/lsb-release
4229+ case "$DISTRIB_CODENAME" in
4230+ lucid|maverick|natty|oneiric|precise)
4231+ release=$DISTRIB_CODENAME
4232+ ;;
4233+ esac
4234+fi
4235+
4236+arch=$(arch)
4237+
4238+# Code taken from debootstrap
4239+if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
4240+ arch=`/usr/bin/dpkg --print-architecture`
4241+elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
4242+ arch=`/usr/bin/udpkg --print-architecture`
4243+else
4244+ arch=$(arch)
4245+ if [ "$arch" = "i686" ]; then
4246+ arch="i386"
4247+ elif [ "$arch" = "x86_64" ]; then
4248+ arch="amd64"
4249+ elif [ "$arch" = "armv7l" ]; then
4250+ arch="armel"
4251+ fi
4252+fi
4253+
4254+hostarch=$arch
4255+cloud=0
4256+locales=1
4257+flushcache=0
4258+while true
4259+do
4260+ case "$1" in
4261+ -h|--help) usage $0 && exit 0;;
4262+ -p|--path) path=$2; shift 2;;
4263+ -n|--name) name=$2; shift 2;;
4264+ -F|--flush-cache) flushcache=1; shift 1;;
4265+ -r|--release) release=$2; shift 2;;
4266+ -a|--arch) arch=$2; shift 2;;
4267+ -i|--hostid) host_id=$2; shift 2;;
4268+ -u|--userdata) userdata=$2; shift 2;;
4269+ -C|--cloud) cloud=1; shift 1;;
4270+ -S|--auth-key) auth_key=$2; shift 2;;
4271+ -L|--no_locales) locales=0; shift 2;;
4272+ -T|--tarball) tarball=$2; shift 2;;
4273+ --) shift 1; break ;;
4274+ *) break ;;
4275+ esac
4276+done
4277+
4278+if [ "$arch" == "i686" ]; then
4279+ arch=i386
4280+fi
4281+
4282+if [ $hostarch = "i386" -a $arch = "amd64" ]; then
4283+ echo "can't create amd64 container on i386"
4284+ exit 1
4285+fi
4286+
4287+if [ $arch != "i386" -a $arch != "amd64" ]; then
4288+ echo "Only i386 and amd64 are supported by the ubuntu cloud template."
4289+ exit 1
4290+fi
4291+
4292+if [ -z "$path" ]; then
4293+ echo "'path' parameter is required"
4294+ exit 1
4295+fi
4296+
4297+if [ "$(id -u)" != "0" ]; then
4298+ echo "This script should be run as 'root'"
4299+ exit 1
4300+fi
4301+
4302+rootfs=$path/rootfs
4303+
4304+type ubuntu-cloudimg-query
4305+type wget
4306+
4307+# determine the url, tarball, and directory names
4308+# download if needed
4309+cache="/var/cache/lxc/cloud-$release"
4310+
4311+mkdir -p $cache
4312+
4313+if [ -n "$tarball" ]; then
4314+ url2="$tarball"
4315+else
4316+ url1=`ubuntu-cloudimg-query precise daily $arch --format "%{url}\n"`
4317+ url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/'`
4318+fi
4319+
4320+filename=`basename $url2`
4321+
4322+mkdir -p /var/lock/subsys/
4323+(
4324+ flock -n -x 200
4325+
4326+ cd $cache
4327+ if [ $flushcache -eq 1 ]; then
4328+ echo "Clearing the cached images"
4329+ rm -f $filename
4330+ fi
4331+
4332+ if [ ! -f $filename ]; then
4333+ wget $url2
4334+ fi
4335+
4336+ echo "Extracting rootfs"
4337+ mkdir -p $rootfs
4338+ cd $rootfs
4339+ tar -zxf $cache/$filename
4340+
4341+
4342+ if [ $cloud -eq 0 ]; then
4343+ echo "Configuring for running outside of a cloud environment"
4344+ echo "If you want to configure for a cloud evironment, please use '-- -C' to create the container"
4345+
4346+ seed_d=$rootfs/var/lib/cloud/seed/nocloud-net
4347+ rhostid=$(uuidgen | cut -c -8)
4348+ host_id=${hostid:-$rhostid}
4349+ mkdir -p $seed_d
4350+
4351+ cat > "$seed_d/meta-data" <<EOF
4352+instance_id: lxc-$host_id
4353+EOF
4354+
4355+ rm $rootfs/etc/hostname
4356+
4357+ if [ $locales -eq 1 ]; then
4358+ cp /usr/lib/locale/locale-archive $rootfs/usr/lib/locale/locale-archive
4359+ fi
4360+
4361+
4362+ if [ -n "$auth_key" -a -f "$auth_key" ]; then
4363+ u_path="/home/ubuntu/.ssh"
4364+ root_u_path="$rootfs/$u_path"
4365+ mkdir -p $root_u_path
4366+ cp $auth_key "$root_u_path/authorized_keys"
4367+ chroot $rootfs chown -R ubuntu: "$u_path"
4368+
4369+ echo "Inserted SSH public key from $auth_key into /home/ubuntu/.ssh/authorized_keys"
4370+ fi
4371+
4372+ if [ ! -f $userdata ]; then
4373+ cp $userdata $data_d/user-data
4374+ else
4375+
4376+ if [ -z "$MIRROR" ]; then
4377+ MIRROR="http://archive.ubuntu.com/ubuntu"
4378+ fi
4379+
4380+ cat > "$seed_d/user-data" <<EOF
4381+#cloud-config
4382+output: {all: '| tee -a /var/log/cloud-init-output.log'}
4383+apt-mirror: $MIRROR
4384+manage_etc_hosts: localhost
4385+locale: $(/usr/bin/locale | awk -F= '/LANG=/ {print$NF}')
4386+EOF
4387+
4388+ fi
4389+
4390+ chroot $rootfs /usr/sbin/usermod -U ubuntu
4391+ echo "Please login as user ubuntu with password ubuntu."
4392+
4393+ else
4394+
4395+ echo "Configured for running in a cloud environment."
4396+ echo "If you do not have a meta-data service, this container will likely be useless."
4397+
4398+ fi
4399+
4400+) 200>/var/lock/subsys/lxc-ubucloud
4401+
4402+copy_configuration $path $rootfs $name $arch
4403+
4404+echo "Container $name created."
4405+exit 0
4406
4407=== added file '.pc/0054-ubuntu-debug/templates/lxc-ubuntu.in'
4408--- .pc/0054-ubuntu-debug/templates/lxc-ubuntu.in 1970-01-01 00:00:00 +0000
4409+++ .pc/0054-ubuntu-debug/templates/lxc-ubuntu.in 2012-03-02 15:11:19 +0000
4410@@ -0,0 +1,665 @@
4411+#!/bin/bash
4412+
4413+#
4414+# template script for generating ubuntu container for LXC
4415+#
4416+# This script consolidates and extends the existing lxc ubuntu scripts
4417+#
4418+
4419+# Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
4420+# Copyright © 2010 Wilhelm Meier
4421+# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
4422+#
4423+# This program is free software; you can redistribute it and/or modify
4424+# it under the terms of the GNU General Public License version 2, as
4425+# published by the Free Software Foundation.
4426+
4427+# This program is distributed in the hope that it will be useful,
4428+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4429+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4430+# GNU General Public License for more details.
4431+
4432+# You should have received a copy of the GNU General Public License along
4433+# with this program; if not, write to the Free Software Foundation, Inc.,
4434+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
4435+#
4436+
4437+set -e
4438+
4439+if [ -r /etc/default/lxc ]; then
4440+ . /etc/default/lxc
4441+fi
4442+
4443+configure_ubuntu()
4444+{
4445+ rootfs=$1
4446+ hostname=$2
4447+ release=$3
4448+
4449+ # configure the network using the dhcp
4450+ cat <<EOF > $rootfs/etc/network/interfaces
4451+auto lo
4452+iface lo inet loopback
4453+
4454+auto eth0
4455+iface eth0 inet dhcp
4456+EOF
4457+
4458+ # set the hostname
4459+ cat <<EOF > $rootfs/etc/hostname
4460+$hostname
4461+EOF
4462+ # set minimal hosts
4463+ cat <<EOF > $rootfs/etc/hosts
4464+127.0.0.1 localhost $hostname
4465+EOF
4466+
4467+ if [ "$release" != "precise" ]; then
4468+ # suppress log level output for udev
4469+ sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
4470+
4471+ # remove jobs for consoles 5 and 6 since we only create 4 consoles in
4472+ # this template
4473+ rm -f $rootfs/etc/init/tty{5,6}.conf
4474+ fi
4475+
4476+ if [ -z "$bindhome" ]; then
4477+ chroot $rootfs useradd --create-home -s /bin/bash ubuntu
4478+ echo "ubuntu:ubuntu" | chroot $rootfs chpasswd
4479+ fi
4480+
4481+ return 0
4482+}
4483+
4484+# finish setting up the user in the container by injecting ssh key and
4485+# adding sudo group membership.
4486+# passed-in user is either 'ubuntu' or the user to bind in from host.
4487+finalize_user()
4488+{
4489+ user=$1
4490+
4491+ if [ "$release" = "precise" ]; then
4492+ groups="sudo"
4493+ else
4494+ groups="sudo admin"
4495+ fi
4496+
4497+ for group in $groups; do
4498+ chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true
4499+ chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true
4500+ done
4501+
4502+ if [ -n "$auth_key" -a -f "$auth_key" ]; then
4503+ u_path="/home/${user}/.ssh"
4504+ root_u_path="$rootfs/$u_path"
4505+ mkdir -p $root_u_path
4506+ cp $auth_key "$root_u_path/authorized_keys"
4507+ chroot $rootfs chown -R ${user}: "$u_path"
4508+
4509+ echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys"
4510+ fi
4511+ return 0
4512+}
4513+
4514+write_sourceslist()
4515+{
4516+ # $1 => path to the rootfs
4517+ # $2 => architecture we want to add
4518+ # $3 => whether to use the multi-arch syntax or not
4519+
4520+ case $2 in
4521+ amd64|i386)
4522+ MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
4523+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu}
4524+ ;;
4525+ sparc)
4526+ case $SUITE in
4527+ gutsy)
4528+ MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
4529+ SECURITY_MIRROR=${SECURITY_MIRRORMIRROR:-http://security.ubuntu.com/ubuntu}
4530+ ;;
4531+ *)
4532+ MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
4533+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
4534+ ;;
4535+ esac
4536+ ;;
4537+ *)
4538+ MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
4539+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
4540+ ;;
4541+ esac
4542+ if [ -n "$3" ]; then
4543+ cat >> "$1/etc/apt/sources.list" << EOF
4544+deb [arch=$2] $MIRROR ${release} main restricted universe multiverse
4545+deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse
4546+deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse
4547+EOF
4548+ else
4549+ cat >> "$1/etc/apt/sources.list" << EOF
4550+deb $MIRROR ${release} main restricted universe multiverse
4551+deb $MIRROR ${release}-updates main restricted universe multiverse
4552+deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse
4553+EOF
4554+ fi
4555+}
4556+
4557+download_ubuntu()
4558+{
4559+ cache=$1
4560+ arch=$2
4561+ release=$3
4562+
4563+ if [ $release = "lucid" ]; then
4564+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,dhcp3-client,ssh,lsb-release,gnupg
4565+ elif [ $release = "maverick" ]; then
4566+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,dhcp3-client,ssh,lsb-release,gnupg,netbase
4567+ elif [ $release = "natty" ]; then
4568+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,isc-dhcp-client,isc-dhcp-common,ssh,lsb-release,gnupg,netbase
4569+ else
4570+ packages=dialog,apt,apt-utils,iproute,inetutils-ping,vim,isc-dhcp-client,isc-dhcp-common,ssh,lsb-release,gnupg,netbase,ubuntu-keyring
4571+ fi
4572+ echo "installing packages: $packages"
4573+
4574+ # check the mini ubuntu was not already downloaded
4575+ mkdir -p "$cache/partial-$arch"
4576+ if [ $? -ne 0 ]; then
4577+ echo "Failed to create '$cache/partial-$arch' directory"
4578+ return 1
4579+ fi
4580+
4581+ # download a mini ubuntu into a cache
4582+ echo "Downloading ubuntu $release minimal ..."
4583+ if [ -n "$(which qemu-debootstrap)" ]; then
4584+ qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
4585+ else
4586+ debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
4587+ fi
4588+
4589+ if [ $? -ne 0 ]; then
4590+ echo "Failed to download the rootfs, aborting."
4591+ return 1
4592+ fi
4593+
4594+ # Serge isn't sure whether we should avoid doing this when
4595+ # $release == `distro-info -d`
4596+ echo "Installing updates"
4597+ > $cache/partial-$arch/etc/apt/sources.list
4598+ write_sourceslist $cache/partial-$arch/ $arch
4599+
4600+ chroot "$1/partial-${arch}" apt-get update
4601+ if [ $? -ne 0 ]; then
4602+ echo "Failed to update the apt cache"
4603+ return 1
4604+ fi
4605+ cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF
4606+#!/bin/sh
4607+exit 101
4608+EOF
4609+ chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
4610+
4611+ lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y
4612+ ret=$?
4613+ rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
4614+
4615+ if [ $ret -ne 0 ]; then
4616+ echo "Failed to upgrade the cache"
4617+ return 1
4618+ fi
4619+
4620+ mv "$1/partial-$arch" "$1/rootfs-$arch"
4621+ echo "Download complete"
4622+ return 0
4623+}
4624+
4625+copy_ubuntu()
4626+{
4627+ cache=$1
4628+ arch=$2
4629+ rootfs=$3
4630+
4631+ # make a local copy of the miniubuntu
4632+ echo "Copying rootfs to $rootfs ..."
4633+ mkdir -p $rootfs
4634+ rsync -a $cache/rootfs-$arch/ $rootfs/ || return 1
4635+ return 0
4636+}
4637+
4638+install_ubuntu()
4639+{
4640+ rootfs=$1
4641+ release=$2
4642+ flushcache=$3
4643+ cache="/var/cache/lxc/$release"
4644+ mkdir -p /var/lock/subsys/
4645+ (
4646+ flock -n -x 200
4647+ if [ $? -ne 0 ]; then
4648+ echo "Cache repository is busy."
4649+ return 1
4650+ fi
4651+
4652+
4653+ if [ $flushcache -eq 1 ]; then
4654+ echo "Flushing cache..."
4655+ rm -rf "$cache/partial-$arch"
4656+ rm -rf "$cache/rootfs-$arch"
4657+ fi
4658+
4659+ echo "Checking cache download in $cache/rootfs-$arch ... "
4660+ if [ ! -e "$cache/rootfs-$arch" ]; then
4661+ download_ubuntu $cache $arch $release
4662+ if [ $? -ne 0 ]; then
4663+ echo "Failed to download 'ubuntu $release base'"
4664+ return 1
4665+ fi
4666+ fi
4667+
4668+ echo "Copy $cache/rootfs-$arch to $rootfs ... "
4669+ copy_ubuntu $cache $arch $rootfs
4670+ if [ $? -ne 0 ]; then
4671+ echo "Failed to copy rootfs"
4672+ return 1
4673+ fi
4674+
4675+ return 0
4676+
4677+ ) 200>/var/lock/subsys/lxc
4678+
4679+ return $?
4680+}
4681+
4682+copy_configuration()
4683+{
4684+ path=$1
4685+ rootfs=$2
4686+ name=$3
4687+ arch=$4
4688+ release=$5
4689+
4690+ if [ $arch = "i386" ]; then
4691+ arch="i686"
4692+ fi
4693+
4694+ ttydir=""
4695+ if [ $release = "precise" ]; then
4696+ ttydir=" lxc"
4697+ fi
4698+
4699+ # if there is exactly one veth network entry, make sure it has an
4700+ # associated hwaddr.
4701+ nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
4702+ if [ $nics -eq 1 ]; then
4703+ grep -q "^lxc.network.hwaddr" $path/config || cat <<EOF >> $path/config
4704+lxc.network.hwaddr= 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')
4705+EOF
4706+ fi
4707+
4708+ cat <<EOF >> $path/config
4709+lxc.utsname = $name
4710+
4711+lxc.devttydir =$ttydir
4712+lxc.tty = 4
4713+lxc.pts = 1024
4714+lxc.rootfs = $rootfs
4715+lxc.mount = $path/fstab
4716+lxc.arch = $arch
4717+lxc.cap.drop = sys_module mac_admin
4718+
4719+lxc.cgroup.devices.deny = a
4720+# Allow any mknod (but not using the node)
4721+lxc.cgroup.devices.allow = c *:* m
4722+lxc.cgroup.devices.allow = b *:* m
4723+# /dev/null and zero
4724+lxc.cgroup.devices.allow = c 1:3 rwm
4725+lxc.cgroup.devices.allow = c 1:5 rwm
4726+# consoles
4727+lxc.cgroup.devices.allow = c 5:1 rwm
4728+lxc.cgroup.devices.allow = c 5:0 rwm
4729+#lxc.cgroup.devices.allow = c 4:0 rwm
4730+#lxc.cgroup.devices.allow = c 4:1 rwm
4731+# /dev/{,u}random
4732+lxc.cgroup.devices.allow = c 1:9 rwm
4733+lxc.cgroup.devices.allow = c 1:8 rwm
4734+lxc.cgroup.devices.allow = c 136:* rwm
4735+lxc.cgroup.devices.allow = c 5:2 rwm
4736+# rtc
4737+lxc.cgroup.devices.allow = c 254:0 rwm
4738+#fuse
4739+lxc.cgroup.devices.allow = c 10:229 rwm
4740+#tun
4741+lxc.cgroup.devices.allow = c 10:200 rwm
4742+#full
4743+lxc.cgroup.devices.allow = c 1:7 rwm
4744+#hpet
4745+lxc.cgroup.devices.allow = c 10:228 rwm
4746+#kvm
4747+lxc.cgroup.devices.allow = c 10:232 rwm
4748+EOF
4749+
4750+ cat <<EOF > $path/fstab
4751+proc $rootfs/proc proc nodev,noexec,nosuid 0 0
4752+sysfs $rootfs/sys sysfs defaults 0 0
4753+EOF
4754+
4755+ if [ $? -ne 0 ]; then
4756+ echo "Failed to add configuration"
4757+ return 1
4758+ fi
4759+
4760+ return 0
4761+}
4762+
4763+trim()
4764+{
4765+ rootfs=$1
4766+ release=$2
4767+
4768+ # provide the lxc service
4769+ cat <<EOF > $rootfs/etc/init/lxc.conf
4770+# fake some events needed for correct startup other services
4771+
4772+description "Container Upstart"
4773+
4774+start on startup
4775+
4776+script
4777+ rm -rf /var/run/*.pid
4778+ rm -rf /var/run/network/*
4779+ /sbin/initctl emit stopped JOB=udevtrigger --no-wait
4780+ /sbin/initctl emit started JOB=udev --no-wait
4781+end script
4782+EOF
4783+
4784+ # fix buggus runlevel with sshd
4785+ cat <<EOF > $rootfs/etc/init/ssh.conf
4786+# ssh - OpenBSD Secure Shell server
4787+#
4788+# The OpenSSH server provides secure shell access to the system.
4789+
4790+description "OpenSSH server"
4791+
4792+start on filesystem
4793+stop on runlevel [!2345]
4794+
4795+expect fork
4796+respawn
4797+respawn limit 10 5
4798+umask 022
4799+# replaces SSHD_OOM_ADJUST in /etc/default/ssh
4800+oom never
4801+
4802+pre-start script
4803+ test -x /usr/sbin/sshd || { stop; exit 0; }
4804+ test -e /etc/ssh/sshd_not_to_be_run && { stop; exit 0; }
4805+ test -c /dev/null || { stop; exit 0; }
4806+
4807+ mkdir -p -m0755 /var/run/sshd
4808+end script
4809+
4810+# if you used to set SSHD_OPTS in /etc/default/ssh, you can change the
4811+# 'exec' line here instead
4812+exec /usr/sbin/sshd
4813+EOF
4814+
4815+ cat <<EOF > $rootfs/etc/init/console.conf
4816+# console - getty
4817+#
4818+# This service maintains a console on tty1 from the point the system is
4819+# started until it is shut down again.
4820+
4821+start on stopped rc RUNLEVEL=[2345]
4822+stop on runlevel [!2345]
4823+
4824+respawn
4825+exec /sbin/getty -8 38400 /dev/console
4826+EOF
4827+
4828+ cat <<EOF > $rootfs/lib/init/fstab
4829+# /lib/init/fstab: cleared out for bare-bones lxc
4830+EOF
4831+
4832+ # reconfigure some services
4833+ if [ -z "$LANG" ]; then
4834+ chroot $rootfs locale-gen en_US.UTF-8
4835+ chroot $rootfs update-locale LANG=en_US.UTF-8
4836+ else
4837+ chroot $rootfs locale-gen $LANG
4838+ chroot $rootfs update-locale LANG=$LANG
4839+ fi
4840+
4841+ # remove pointless services in a container
4842+ chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove
4843+
4844+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done'
4845+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done'
4846+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done'
4847+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done'
4848+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done'
4849+
4850+ # if this isn't lucid, then we need to twiddle the network upstart bits :(
4851+ if [ $release != "lucid" ]; then
4852+ sed -i 's/^.*emission handled.*$/echo Emitting lo/' $rootfs/etc/network/if-up.d/upstart
4853+ fi
4854+}
4855+
4856+post_process()
4857+{
4858+ rootfs=$1
4859+ release=$2
4860+ trim_container=$3
4861+
4862+ if [ $trim_container -eq 1 ]; then
4863+ trim $rootfs $release
4864+ elif [ $release = "lucid" -o $release = "maverick" -o $release = "natty" \
4865+ -o $release = "oneiric" ]; then
4866+ # for lucid and maverick, if not trimming, then add the ubuntu-virt
4867+ # ppa and install lxcguest
4868+ if [ $release = "lucid" -o $release = "maverick" ]; then
4869+ chroot $rootfs apt-get install --force-yes -y python-software-properties
4870+ chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa
4871+ fi
4872+ cresolvonf="${rootfs}/etc/resolv.conf"
4873+ mv $cresolvonf ${cresolvonf}.lxcbak
4874+ cat /etc/resolv.conf > ${cresolvonf}
4875+ chroot $rootfs apt-get update
4876+ chroot $rootfs apt-get install --force-yes -y lxcguest
4877+ rm -f ${cresolvonf}
4878+ mv ${cresolvonf}.lxcbak ${cresolvonf}
4879+ fi
4880+
4881+ # If the container isn't running a native architecture, setup multiarch
4882+ if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then
4883+ mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
4884+ echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
4885+
4886+ # Save existing value of MIRROR and SECURITY_MIRROR
4887+ DEFAULT_MIRROR=$MIRROR
4888+ DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR
4889+
4890+ # Write a new sources.list containing both native and multiarch entries
4891+ > ${rootfs}/etc/apt/sources.list
4892+ write_sourceslist $rootfs $arch "native"
4893+
4894+ MIRROR=$DEFAULT_MIRROR
4895+ SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR
4896+ write_sourceslist $rootfs $hostarch "multiarch"
4897+
4898+ # Finally update the lists and install upstart using the host architecture
4899+ chroot $rootfs apt-get update
4900+ chroot $rootfs apt-get install --force-yes -y --no-install-recommends upstart:${hostarch} mountall:amd64 iproute:amd64 isc-dhcp-client:amd64
4901+ fi
4902+}
4903+
4904+do_bindhome()
4905+{
4906+ rootfs=$1
4907+ user=$2
4908+
4909+ # copy /etc/passwd, /etc/shadow, and /etc/group entries into container
4910+ pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; }
4911+ echo $pwd >> $rootfs/etc/passwd
4912+
4913+ # make sure user's shell exists in the container
4914+ shell=`echo $pwd | cut -d: -f 7`
4915+ if [ ! -x $rootfs/$shell ]; then
4916+ echo "shell $shell for user $user was not found in the container."
4917+ pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1`
4918+ echo "Installing $pkg"
4919+ chroot $rootfs apt-get --force-yes -y install $pkg
4920+ fi
4921+
4922+ shad=`getent shadow $user`
4923+ echo "$shad" >> $rootfs/etc/shadow
4924+
4925+ # bind-mount the user's path into the container's /home
4926+ h=`getent passwd $user | cut -d: -f 6`
4927+ mkdir -p $rootfs/$h
4928+ echo "$h $rootfs/$h none bind 0 0" >> $path/fstab
4929+
4930+ # Make sure the group exists in container
4931+ chroot $rootfs getent group $user || { \
4932+ grp=`getent group $user`
4933+ echo "$grp" >> $rootfs/etc/group
4934+ }
4935+}
4936+
4937+usage()
4938+{
4939+ cat <<EOF
4940+$1 -h|--help [-a|--arch] [-b|--bindhome <user>] [--trim]
4941+ [-F | --flush-cache] [-r|--release <release>] [ -S | --auth-key <keyfile>]
4942+release: lucid | maverick | natty | oneiric | precise
4943+trim: make a minimal (faster, but not upgrade-safe) container
4944+bindhome: bind <user>'s home into the container
4945+ The ubuntu user will not be created, and <user> will have
4946+ sudo access.
4947+arch: amd64 or i386: defaults to host arch
4948+auth-key: SSH Public key file to inject into container
4949+EOF
4950+ return 0
4951+}
4952+
4953+options=$(getopt -o a:b:hp:r:xn:FS: -l arch:,bindhome:,help,path:,release:,trim,name:,flush-cache,auth-key: -- "$@")
4954+if [ $? -ne 0 ]; then
4955+ usage $(basename $0)
4956+ exit 1
4957+fi
4958+eval set -- "$options"
4959+
4960+release=lucid
4961+if [ -f /etc/lsb-release ]; then
4962+ . /etc/lsb-release
4963+ case "$DISTRIB_CODENAME" in
4964+ lucid|maverick|natty|oneiric|precise)
4965+ release=$DISTRIB_CODENAME
4966+ ;;
4967+ esac
4968+fi
4969+
4970+bindhome=
4971+arch=$(arch)
4972+
4973+# Code taken from debootstrap
4974+if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
4975+ arch=`/usr/bin/dpkg --print-architecture`
4976+elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
4977+ arch=`/usr/bin/udpkg --print-architecture`
4978+else
4979+ arch=$(arch)
4980+ if [ "$arch" = "i686" ]; then
4981+ arch="i386"
4982+ elif [ "$arch" = "x86_64" ]; then
4983+ arch="amd64"
4984+ elif [ "$arch" = "armv7l" ]; then
4985+ arch="armel"
4986+ fi
4987+fi
4988+
4989+trim_container=0
4990+hostarch=$arch
4991+flushcache=0
4992+while true
4993+do
4994+ case "$1" in
4995+ -h|--help) usage $0 && exit 0;;
4996+ -p|--path) path=$2; shift 2;;
4997+ -n|--name) name=$2; shift 2;;
4998+ -F|--flush-cache) flushcache=1; shift 1;;
4999+ -r|--release) release=$2; shift 2;;
5000+ -b|--bindhome) bindhome=$2; shift 2;;
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: