]> git.proxmox.com Git - mirror_lxc.git/blame - templates/lxc-cirros.in
Merge pull request #2055 from marcosps/cgfsng_debug
[mirror_lxc.git] / templates / lxc-cirros.in
CommitLineData
58a46e06
SH
1#!/bin/bash
2
3# template script for generating ubuntu container for LXC
4#
5# This script consolidates and extends the existing lxc ubuntu scripts
6#
7
8cd80b50 8# Copyright © 2013 Canonical Ltd.
58a46e06
SH
9# Author: Scott Moser <scott.moser@canonical.com>
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License version 2, as
13# published by the Free Software Foundation.
14
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19
20# You should have received a copy of the GNU General Public License along
21# with this program; if not, write to the Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8ec981fc
SG
23
24# Detect use under userns (unsupported)
207bf0e4
SG
25# Make sure the usual locations are in PATH
26export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
27
58a46e06 28VERBOSITY=0
58a46e06 29DOWNLOAD_URL="http://download.cirros-cloud.net/"
58a46e06
SH
30
31UNAME_M=$(uname -m)
32ARCHES=( i386 x86_64 amd64 arm )
33STREAMS=( released devel )
80773206 34SOURCES=( nocloud none )
58a46e06 35BUILD="standard"
6b410562
SH
36LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
37
38LXC_MAPPED_GID=
39LXC_MAPPED_UID=
58a46e06
SH
40
41DEF_VERSION="released"
80773206 42DEF_SOURCE="nocloud"
58a46e06
SH
43case "${UNAME_M}" in
44 i?86) DEF_ARCH="i386";;
45 x86_64) DEF_ARCH="x86_64";;
46 arm*) DEF_ARCH="arm";;
47 *) DEF_ARCH="i386";;
48esac
49
6b410562
SH
50am_in_userns() {
51 [ -e /proc/self/uid_map ] || { echo no; return; }
52 [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; }
53 line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map)
54 [ "$line" = "0 0 4294967295" ] && { echo no; return; }
55 echo yes
56}
57
58in_userns=0
59[ $(am_in_userns) = "yes" ] && in_userns=1
60
6dc6f80b 61# Allow the cache base to be set by environment variable
6b410562 62if [ $(id -u) -eq 0 ]; then
6dc6f80b 63 CACHE_D=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc/cirros"}
6b410562 64else
6dc6f80b 65 CACHE_D=${LXC_CACHE_PATH:-"$HOME/.cache/lxc/cirros"}
6b410562
SH
66fi
67
58a46e06 68error() { echo "$@" 1>&2; }
58a46e06
SH
69inargs() {
70 local needle="$1" x=""
71 shift
72 for x in "$@"; do
73 [ "$needle" = "$x" ] && return 0
74 done
75 return 1
76}
77
78Usage() {
79 cat <<EOF
80${0##*/} [options]
81
80773206 82 -a | --arch A architecture to use [${ARCHES[*]}]
58a46e06
SH
83 default: ${DEF_ARCH}
84 -h | --help this usage
85 -v | --verbose increase verbosity
86 -S | --auth-key K insert auth key 'K'
87 -v | --version V version [${STREAMS[*]}]
88 default: ${DEF_VERSION}
89 -u | --userdata U user-data file
80773206
SH
90 --tarball T read from tarball 'T' rather than downloading
91 or using cache.
92 --source S insert userdata/metadata via source S
93 [${SOURCES[*]}]
58a46e06
SH
94EOF
95}
96
80773206 97bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; return 1; }
58a46e06
SH
98
99debug() {
100 local level=${1}; shift;
101 [ "${level}" -gt "${VERBOSITY}" ] && return
102 error "${@}"
103}
104jsondict() {
105 local k="" v="" ret="{"
106 for arg in "$@"; do
107 k="${arg%%=*}"
108 v="${arg#*=}"
109 ret="${ret} \"${k}\": \"$v\","
110 done
111 ret="${ret%,} }"
112 echo "$ret"
113}
114
115copy_configuration()
116{
117 local path=$1 rootfs=$2 name=$3 arch=$4 release=$5
118cat >> "$path/config" <<EOF
119# Template used to create this container: cirros
120
7a96a068 121lxc.rootfs.path = $rootfs
58a46e06 122
fe1c5887 123lxc.tty.max = 4
232763d6 124lxc.pty.max = 1024
58a46e06 125
b67771bc 126lxc.uts.name = $name
58a46e06
SH
127lxc.arch = $arch
128lxc.cap.drop = sys_module mac_admin mac_override sys_time
129
130# When using LXC with apparmor, uncomment the next line to run unconfined:
a1d5fdfd 131#lxc.apparmor.profile = unconfined
f24a52d5 132lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
58a46e06
SH
133
134lxc.cgroup.devices.deny = a
135# Allow any mknod (but not using the node)
136lxc.cgroup.devices.allow = c *:* m
137lxc.cgroup.devices.allow = b *:* m
138# /dev/null and zero
139lxc.cgroup.devices.allow = c 1:3 rwm
140lxc.cgroup.devices.allow = c 1:5 rwm
141# consoles
142lxc.cgroup.devices.allow = c 5:1 rwm
143lxc.cgroup.devices.allow = c 5:0 rwm
144# /dev/{,u}random
145lxc.cgroup.devices.allow = c 1:9 rwm
146lxc.cgroup.devices.allow = c 1:8 rwm
147lxc.cgroup.devices.allow = c 136:* rwm
148lxc.cgroup.devices.allow = c 5:2 rwm
149# rtc
150lxc.cgroup.devices.allow = c 254:0 rwm
151# fuse
152lxc.cgroup.devices.allow = c 10:229 rwm
153# tun
154lxc.cgroup.devices.allow = c 10:200 rwm
155# full
156lxc.cgroup.devices.allow = c 1:7 rwm
157# hpet
158lxc.cgroup.devices.allow = c 10:228 rwm
159# kvm
160lxc.cgroup.devices.allow = c 10:232 rwm
161EOF
6b410562
SH
162
163 if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then
164 echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.userns.conf" >> $path/config
6b410562
SH
165 fi
166
58a46e06
SH
167}
168
80773206
SH
169insert_ds_nocloud() {
170 local root_d="$1" authkey="$2" udfile="$3"
58a46e06
SH
171 local sdir="$root_d/var/lib/cloud/seed/nocloud"
172
173 mkdir -p "$sdir" ||
174 { error "failed to make datasource dir $sdir"; return 1; }
175 rm -f "$sdir/meta-data" "$sdir/user-data" ||
176 { error "failed to clean old data from $sdir"; return 1; }
177
178 iid="iid-local01"
179 jsondict "instance-id=$iid" \
180 ${authkeys:+"public-keys=${authkeys}"} > "$sdir/meta-data" ||
181 { error "failed to write metadata to $sdir/meta-data"; return 1; }
182
80773206
SH
183 if [ -n "$udfile" ]; then
184 cat "$udfile" > "$sdir/user-data" ||
185 { error "failed to write user-data to $sdir"; return 1; }
186 else
187 rm -f "$sdir/user-data"
188 fi
189}
190
191insert_ds() {
192 local dstype="$1" root_d="$2" authkey="$3" udfile="$4"
193 case "$dstype" in
194 nocloud) insert_ds_nocloud "$root_d" "$authkey" "$udfile"
195 esac
58a46e06
SH
196}
197
198extract_rootfs() {
199 local tarball="$1" rootfs_d="$2"
200 mkdir -p "${rootfs_d}" ||
201 { error "failed to make rootfs dir ${rootfs_d}"; return 1; }
202
6b410562
SH
203 if [ $in_userns -eq 1 ]; then
204 tar -C "${rootfs_d}" --anchored --exclude="dev/*" -Sxzf "${tarball}" ||
205 { error "failed to populate ${rootfs_d}"; return 1; }
206 else
207 tar -C "${rootfs_d}" -Sxzf "${tarball}" ||
208 { error "failed to populate ${rootfs_d}"; return 1; }
209 fi
58a46e06
SH
210 return 0
211}
212
213download_tarball() {
214 local arch="$1" ver="$2" cached="$3" baseurl="$4"
215 local out="" outd="" file="" dlpath=""
216 file="cirros-$ver-$arch-lxc.tar.gz"
217 dlpath="$ver/$file"
218 outd="${cached}/${dlpath%/*}"
219 if [ -f "$cached/$dlpath" ]; then
220 _RET="$cached/$dlpath"
221 return 0
222 fi
223
224 mkdir -p "${outd}" ||
225 { error "failed to create ${outd}"; return 1; }
226
80773206 227 debug 1 "downloading ${baseurl%/}/$dlpath" to "${cached}/$dlpath"
58a46e06
SH
228 wget "${baseurl%/}/$dlpath" -O "$cached/${dlpath}.$$" &&
229 mv "$cached/$dlpath.$$" "$cached/$dlpath" || {
230 rm -f "$cached/$dlpath.$$";
231 error "failed to download $dlpath";
232 return 1;
233 }
234 _RET="$cached/$dlpath"
235}
236
80773206
SH
237create_main() {
238 local short_opts="a:hn:p:S:uvV"
6b410562 239 local long_opts="arch:,auth-key:,name:,path:,tarball:,userdata:,verbose,version:,rootfs:,mapped-uid:,mapped-gid:"
80773206
SH
240 local getopt_out=""
241 getopt_out=$(getopt --name "${0##*/}" \
242 --options "${short_opts}" --long "${long_opts}" -- "$@") &&
243 eval set -- "${getopt_out}" ||
244 { bad_Usage; return; }
245
246 local arch="${DEF_ARCH}" dsource="${DEF_SOURCE}" version="${DEF_VERSION}"
247 local authkey_f="" authkeys="" userdata_f="" path="" tarball=""
248 local cur="" next=""
4165b2c6 249 local rootfs_d=""
80773206
SH
250
251 while [ $# -ne 0 ]; do
252 cur=$1; next=$2;
253 case "$cur" in
254 -a|--arch) arch="$next"; shift;;
255 -h|--help) Usage ; return 0;;
256 -n|--name) name="$next"; shift;;
257 -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
258 -S|--auth-key) authkey_f="$next"; shift;;
259 -p|--path) path=$next; shift;;
260 -v|--version) version=$next; shift;;
261 -u|--userdata) userdata_f="$next"; shift;;
262 --tarball) tarball="$next"; shift;;
263 --source) dsource="$next"; shift;;
4165b2c6 264 --rootfs) rootfs_d="$next"; shift;;
6b410562
SH
265 --mapped-uid) LXC_MAPPED_UID=$next; shift;;
266 --mapped-gid) LXC_MAPPED_GID=$next; shift;;
80773206
SH
267 --) shift; break;;
268 esac
269 shift;
270 done
58a46e06 271
4165b2c6 272 [ -n "$rootfs_d" ] || rootfs_d="$path/rootfs"
80773206
SH
273 [ $# -eq 0 ] || { bad_Usage "unexpected arguments: $*"; return; }
274 [ -n "$path" ] || { error "'path' parameter is required"; return 1; }
58a46e06 275
80773206
SH
276 if [ "$(id -u)" != "0" ]; then
277 { error "must be run as root"; return 1; }
278 fi
58a46e06 279
80773206
SH
280 case "$arch" in
281 i?86) arch="i386";;
282 amd64) arch="x86_64";;
283 esac
284
285 inargs "$arch" "${ARCHES[@]}" ||
286 { error "bad arch '$arch'. allowed: ${ARCHES[*]}"; return 1; }
287
288 inargs "$dsource" "${SOURCES[@]}" ||
289 { error "bad source '$dsource'. allowed: ${SOURCES[*]}"; return 1; }
58a46e06 290
80773206
SH
291 if [ "$dsource" = "none" ] && [ -n "$userdata_f" -o -n "$authkey_f" ]; then
292 error "userdata and authkey are incompatible with --source=none";
293 return 1;
294 fi
58a46e06 295
80773206
SH
296 if [ -n "$authkey_f" ]; then
297 if [ ! -f "$authkey_f" ]; then
298 error "--auth-key=${authkey_f} must reference a file"
299 return 1
300 fi
301 authkeys=$(cat "$authkey_f") ||
302 { error "failed to read ${authkey_f}"; return 1; }
303 fi
58a46e06 304
80773206
SH
305 if [ -n "$userdata_f" -a ! -f "${userdata_f}" ]; then
306 error "${userdata_f}: --userdata arg not a file"
307 return 1
58a46e06 308 fi
58a46e06 309
80773206
SH
310 if [ -z "$tarball" ]; then
311 if inargs "$version" "${STREAMS[@]}"; then
312 out=$(wget -O - -q "${DOWNLOAD_URL%/}/version/$version") ||
313 { error "failed to convert 'version=$version'"; return 1; }
314 version="$out"
315 fi
316 download_tarball "$arch" "$version" "${CACHE_D}" "${DOWNLOAD_URL}" ||
317 return
318 tarball="$_RET"
319 fi
58a46e06 320
80773206 321 extract_rootfs "${tarball}" "${rootfs_d}" || return
58a46e06 322
80773206
SH
323 if [ "$version" = "0.3.2~pre1" ]; then
324 debug 1 "fixing console for lxc and '$version'"
325 sed -i 's,^\(#console.* 115200 \)# /dev/console,\1 console,g' \
326 "$rootfs_d/etc/inittab" ||
327 { error "failed to fix console entry for $version"; return 1; }
328 fi
58a46e06 329
80773206
SH
330 if [ "$dsource" != "none" ]; then
331 insert_ds "$dsource" "$path/rootfs" "$authkeys" "$userdata_f" || {
332 error "failed to insert userdata to $path/rootfs"
333 return 1
334 }
335 fi
58a46e06 336
80773206
SH
337 copy_configuration "$path" "$path/rootfs" "$name" "$arch" "$release"
338 return
339}
58a46e06 340
80773206 341create_main "$@"
58a46e06
SH
342
343# vi: ts=4 expandtab