~serge-hallyn/ubuntu/saucy/lxc/lxc-dnsmasq

« back to all changes in this revision

Viewing changes to templates/lxc-ubuntu-cloud.in

  • Committer: Stéphane Graber
  • Date: 2013-02-18 15:20:18 UTC
  • mto: This revision was merged to the branch mainline in revision 190.
  • Revision ID: stgraber@ubuntu.com-20130218152018-ls2gi9hkqs2kuhj8
Tags: upstream-0.9.0~alpha3
Import upstream version 0.9.0~alpha3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/bin/bash
2
2
 
3
 
# template script for generating ubuntu container for LXC based on daily cloud
 
3
# template script for generating ubuntu container for LXC based on released cloud
4
4
# images
5
5
#
6
6
# Copyright © 2012 Serge Hallyn <serge.hallyn@canonical.com>
31
31
    rootfs=$2
32
32
    name=$3
33
33
    arch=$4
 
34
    release=$5
34
35
 
35
36
    if [ $arch = "i386" ]; then
36
37
        arch="i686"
41
42
    nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
42
43
    if [ $nics -eq 1 ]; then
43
44
        grep -q "^lxc.network.hwaddr" $path/config || cat <<EOF >> $path/config
44
 
lxc.network.hwaddr= 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')
 
45
lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')
45
46
EOF
46
47
    fi
47
48
 
 
49
    grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
48
50
    cat <<EOF >> $path/config
49
51
lxc.utsname = $name
50
52
 
51
53
lxc.tty = 4
52
54
lxc.pts = 1024
53
 
lxc.rootfs = $rootfs
54
 
lxc.mount  = $path/fstab
 
55
lxc.mount = $path/fstab
55
56
lxc.arch = $arch
56
57
lxc.cap.drop = sys_module mac_admin
 
58
lxc.pivotdir = lxc_putold
 
59
 
 
60
# When using LXC with apparmor, uncomment the next line to run unconfined:
 
61
#lxc.aa_profile = unconfined
57
62
 
58
63
lxc.cgroup.devices.deny = a
59
64
# Allow any mknod (but not using the node)
87
92
EOF
88
93
 
89
94
    cat <<EOF > $path/fstab
90
 
proc            $rootfs/proc         proc    nodev,noexec,nosuid 0 0
91
 
sysfs           $rootfs/sys          sysfs defaults  0 0
 
95
proc            proc         proc    nodev,noexec,nosuid 0 0
 
96
sysfs           sys          sysfs defaults  0 0
92
97
EOF
93
98
 
 
99
    # rmdir /dev/shm for containers that have /run/shm
 
100
    # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
 
101
    # get bind mounted to the host's /run/shm.  So try to rmdir
 
102
    # it, and in case that fails move it out of the way.
 
103
    if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then
 
104
        mv $rootfs/dev/shm $rootfs/dev/shm.bak
 
105
        ln -s /run/shm $rootfs/dev/shm
 
106
    fi
 
107
 
94
108
    return 0
95
109
}
96
110
 
104
118
[ -a | --arch ]: Arhcitecture of container, defaults to host arcitecture
105
119
[ -C | --cloud ]: Configure container for use with meta-data service, defaults to no
106
120
[ -T | --tarball ]: Location of tarball
 
121
[ -d | --debug ]: Run with 'set -x' to debug errors
 
122
[ -s | --stream]: Use specified stream rather than 'released'
107
123
 
108
124
Options, mutually exclusive of "-C" and "--cloud":
109
125
  [ -i | --hostid ]:    HostID for cloud-init, defaults to random string
110
126
  [ -u | --userdata ]:  Cloud-init user-data file to configure container on start
111
 
  [ -S | --auth_key ]:  SSH Public key file to inject into container
 
127
  [ -S | --auth-key ]:  SSH Public key file to inject into container
112
128
  [ -L | --nolocales ]: Do not copy host's locales into container
113
129
 
114
130
EOF
115
131
    return 0
116
132
}
117
133
 
118
 
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: -- "$@")
 
134
options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata: -- "$@")
119
135
if [ $? -ne 0 ]; then
120
136
    usage $(basename $0)
121
137
    exit 1
126
142
if [ -f /etc/lsb-release ]; then
127
143
    . /etc/lsb-release
128
144
    case "$DISTRIB_CODENAME" in
129
 
        lucid|maverick|natty|oneiric|precise)
 
145
        lucid|natty|oneiric|precise|quantal)
130
146
            release=$DISTRIB_CODENAME
131
147
        ;;
132
148
    esac
146
162
    elif [ "$arch" = "x86_64" ]; then
147
163
        arch="amd64"
148
164
    elif [ "$arch" = "armv7l" ]; then
 
165
        # note: arm images don't exist before oneiric;  are called armhf in
 
166
        # precise and later;  and are not supported by the query, so we don't actually
 
167
        # support them yet (see check later on).  When Query2 is available,
 
168
        # we'll use that to enable arm images.
149
169
        arch="armel"
150
170
    fi
151
171
fi
152
172
 
 
173
debug=0
153
174
hostarch=$arch
154
175
cloud=0
155
176
locales=1
156
177
flushcache=0
 
178
stream="released"
157
179
while true
158
180
do
159
181
    case "$1" in
166
188
    -i|--hostid)       host_id=$2; shift 2;;
167
189
    -u|--userdata)     userdata=$2; shift 2;;
168
190
    -C|--cloud)        cloud=1; shift 1;;
169
 
    -S|--auth_key)     auth_key=$2; shift 2;;
170
 
    -L|--no_locales)   locales=0; shift 2;;
 
191
    -S|--auth-key)     auth_key=$2; shift 2;;
 
192
    -L|--no_locales)   locales=0; shift 1;;
171
193
    -T|--tarball)      tarball=$2; shift 2;;
 
194
    -d|--debug)        debug=1; shift 1;;
 
195
    -s|--stream)       stream=$2; shift 2;;
172
196
    --)                shift 1; break ;;
173
197
        *)              break ;;
174
198
    esac
175
199
done
176
200
 
 
201
if [ $debug -eq 1 ]; then
 
202
    set -x
 
203
fi
 
204
 
177
205
if [ "$arch" == "i686" ]; then
178
206
    arch=i386
179
207
fi
188
216
    exit 1
189
217
fi
190
218
 
 
219
if [ "$stream" != "daily" -a "$stream" != "released" ]; then
 
220
    echo "Only 'daily' and 'released' streams are supported"
 
221
    exit 1
 
222
fi
 
223
 
 
224
if [ -n "$userdata" ]; then
 
225
    if [ ! -f "$userdata" ]; then
 
226
        echo "Userdata ($userdata) does not exist"
 
227
        exit 1
 
228
    else
 
229
        userdata=`readlink -f $userdata`
 
230
    fi
 
231
fi
 
232
 
 
233
if [ -n "$auth_key" ]; then
 
234
    if [ ! -f "$auth_key" ]; then
 
235
        echo "--auth-key=${auth_key} must reference a file"
 
236
        exit 1
 
237
    fi
 
238
    auth_key=$(readlink -f "${auth_key}") ||
 
239
        { echo "failed to get full path for auth_key"; exit 1; }
 
240
fi
 
241
 
191
242
if [ -z "$path" ]; then
192
243
    echo "'path' parameter is required"
193
244
    exit 1
198
249
    exit 1
199
250
fi
200
251
 
201
 
rootfs=$path/rootfs
 
252
# detect rootfs
 
253
config="$path/config"
 
254
if grep -q '^lxc.rootfs' $config 2>/dev/null ; then
 
255
    rootfs=`grep 'lxc.rootfs =' $config | awk -F= '{ print $2 }'`
 
256
else
 
257
    rootfs=$path/rootfs
 
258
fi
202
259
 
203
260
type ubuntu-cloudimg-query
204
261
type wget
205
262
 
206
263
# determine the url, tarball, and directory names
207
264
# download if needed
208
 
cache="/var/cache/lxc/cloud-$release"
 
265
cache="@LOCALSTATEDIR@/cache/lxc/cloud-$release"
209
266
 
210
267
mkdir -p $cache
211
268
 
212
269
if [ -n "$tarball" ]; then
213
 
        url2="$tarball"
 
270
    url2="$tarball"
214
271
else
215
 
        url1=`ubuntu-cloudimg-query precise daily $arch --format "%{url}\n"`
216
 
        url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/'`
 
272
    url1=`ubuntu-cloudimg-query $release $stream $arch --format "%{url}\n"`
 
273
    url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/'`
217
274
fi
218
275
 
219
276
filename=`basename $url2`
220
277
 
221
 
mkdir -p /var/lock/subsys/
 
278
wgetcleanup()
 
279
{
 
280
    rm -f $filename
 
281
}
 
282
 
 
283
buildcleanup()
 
284
{
 
285
    cd $rootfs
 
286
    umount -l $cache/$xdir || true
 
287
    rm -rf $cache
 
288
}
 
289
 
 
290
# if the release doesn't have a *-rootfs.tar.gz, then create one from the
 
291
# cloudimg.tar.gz by extracting the .img, mounting it loopback, and creating
 
292
# a tarball from the mounted image.
 
293
build_root_tgz()
 
294
{
 
295
    url=$1
 
296
    filename=$2
 
297
 
 
298
    xdir=`mktemp -d -p .`
 
299
    tarname=`basename $url`
 
300
    imgname="$release-*-cloudimg-$arch.img"
 
301
    trap buildcleanup EXIT SIGHUP SIGINT SIGTERM
 
302
    if [ $flushcache -eq 1 -o ! -f $cache/$tarname ]; then
 
303
        rm -f $tarname
 
304
        echo "Downloading cloud image from $url"
 
305
        wget $url || { echo "Couldn't find cloud image $url."; exit 1; }
 
306
    fi
 
307
    echo "Creating new cached cloud image rootfs"
 
308
    tar --wildcards -zxf $tarname $imgname
 
309
    mount -o loop $imgname $xdir
 
310
    (cd $xdir; tar zcf ../$filename .)
 
311
    umount $xdir
 
312
    rm -f $tarname $imgname
 
313
    rmdir $xdir
 
314
    echo "New cloud image cache created"
 
315
    trap EXIT
 
316
    trap SIGHUP
 
317
    trap SIGINT
 
318
    trap SIGTERM
 
319
}
 
320
 
 
321
mkdir -p @LOCALSTATEDIR@/lock/subsys/
222
322
(
223
 
    flock -n -x 200
 
323
    flock -x 200
224
324
 
225
325
    cd $cache
226
326
    if [ $flushcache -eq 1 ]; then
228
328
        rm -f $filename
229
329
    fi
230
330
 
 
331
    trap wgetcleanup EXIT SIGHUP SIGINT SIGTERM
231
332
    if [ ! -f $filename ]; then
232
 
       wget $url2
 
333
        wget $url2 || build_root_tgz $url1 $filename
233
334
    fi
 
335
    trap EXIT
 
336
    trap SIGHUP
 
337
    trap SIGINT
 
338
    trap SIGTERM
234
339
 
235
 
    echo "Extracting rootfs"
 
340
    echo "Extracting container rootfs"
236
341
    mkdir -p $rootfs
237
342
    cd $rootfs
238
343
    tar -zxf $cache/$filename
239
344
 
240
345
 
241
346
    if [ $cloud -eq 0 ]; then
242
 
        echo "Configuring for running outside of a cloud environment"
243
 
        echo "If you want to configure for a cloud evironment, please use '-- -C' to create the container"
244
 
 
245
 
        seed_d=$rootfs/var/lib/cloud/seed/nocloud-net
246
 
        rhostid=$(uuidgen | cut -c -8)
247
 
        host_id=${hostid:-$rhostid}
248
 
        mkdir -p $seed_d
249
 
 
250
 
        cat > "$seed_d/meta-data" <<EOF
251
 
instance_id: lxc-$host_id
 
347
        echo "Configuring for running outside of a cloud environment"
 
348
        echo "If you want to configure for a cloud evironment, please use '-- -C' to create the container"
 
349
 
 
350
        seed_d=$rootfs/var/lib/cloud/seed/nocloud-net
 
351
        rhostid=$(uuidgen | cut -c -8)
 
352
        host_id=${hostid:-$rhostid}
 
353
        mkdir -p $seed_d
 
354
 
 
355
        cat > "$seed_d/meta-data" <<EOF
 
356
instance-id: lxc-$host_id
252
357
EOF
253
 
 
254
 
        rm $rootfs/etc/hostname
255
 
 
256
 
        if [ $locales -eq 1 ]; then
257
 
                cp /usr/lib/locale/locale-archive $rootfs/usr/lib/locale/locale-archive
258
 
        fi
259
 
 
260
 
 
261
 
        if [ -n "$auth_key" -a -f "$auth_key" ]; then
262
 
                u_path="/home/ubuntu/.ssh"
263
 
                root_u_path="$rootfs/$u_path"
264
 
                mkdir -p $root_u_path
265
 
                cp $auth_key "$root_u_path/authorized_keys"
266
 
                chroot $rootfs chown -R ubuntu: "$u_path"
267
 
 
268
 
                echo "Inserted SSH public key from $auth_key into /home/ubuntu/.ssh/authorized_keys"
269
 
        fi
270
 
 
271
 
        if [ ! -f $userdata ]; then
272
 
                cp $userdata $data_d/user-data
273
 
        else
274
 
 
275
 
                if [ -z "$MIRROR" ]; then
276
 
                        MIRROR="http://archive.ubuntu.com/ubuntu"
277
 
                fi
278
 
 
279
 
                cat > "$seed_d/user-data" <<EOF
 
358
        if [ -n "$auth_key" ]; then
 
359
            {
 
360
            echo "public-keys:" &&
 
361
            sed -e '/^$/d' -e 's,^,- ,' "$auth_key" "$auth_key"
 
362
            } >> "$seed_d/meta-data"
 
363
            [ $? -eq 0 ] ||
 
364
                { echo "failed to write public keys to metadata"; exit 1; }
 
365
        fi
 
366
 
 
367
        rm $rootfs/etc/hostname
 
368
 
 
369
        if [ $locales -eq 1 ]; then
 
370
            cp /usr/lib/locale/locale-archive $rootfs/usr/lib/locale/locale-archive
 
371
        fi
 
372
 
 
373
        if [ -f "$userdata" ]; then
 
374
            echo "Using custom user-data"
 
375
            cp $userdata $seed_d/user-data
 
376
        else
 
377
 
 
378
            if [ -z "$MIRROR" ]; then
 
379
                MIRROR="http://archive.ubuntu.com/ubuntu"
 
380
            fi
 
381
 
 
382
            cat > "$seed_d/user-data" <<EOF
280
383
#cloud-config
281
384
output: {all: '| tee -a /var/log/cloud-init-output.log'}
282
 
apt-mirror: $MIRROR
 
385
apt_mirror: $MIRROR
283
386
manage_etc_hosts: localhost
284
387
locale: $(/usr/bin/locale | awk -F= '/LANG=/ {print$NF}')
 
388
password: ubuntu
 
389
chpasswd: { expire: False }
285
390
EOF
286
 
 
287
 
        fi
288
 
 
289
 
        chroot $rootfs /usr/sbin/usermod -U ubuntu
290
 
        echo "Please login as user ubuntu with password ubuntu."
291
 
 
292
 
   else
293
 
 
294
 
        echo "Configured for running in a cloud environment."
295
 
        echo "If you do not have a meta-data service, this container will likely be useless."
296
 
 
297
 
   fi
298
 
 
299
 
) 200>/var/lock/subsys/lxc-ubucloud
300
 
 
301
 
copy_configuration $path $rootfs $name $arch
 
391
        fi
 
392
    else
 
393
 
 
394
        echo "Configured for running in a cloud environment."
 
395
        echo "If you do not have a meta-data service, this container will likely be useless."
 
396
 
 
397
    fi
 
398
) 200>@LOCALSTATEDIR@/lock/subsys/lxc-ubuntu-cloud
 
399
 
 
400
copy_configuration $path $rootfs $name $arch $release
302
401
 
303
402
echo "Container $name created."
304
403
exit 0
 
404
 
 
405
# vi: ts=4 expandtab