]> git.proxmox.com Git - mirror_lxc.git/blob - templates/lxc-gentoo.in
Merge pull request #2055 from marcosps/cgfsng_debug
[mirror_lxc.git] / templates / lxc-gentoo.in
1 #!/bin/bash
2
3 #
4 # LXC template for gentoo
5 #
6 # Author: Guillaume Zitta <lxc@zitta.fr>
7 #
8 # Widely inspired from lxc-gentoo script at https://github.com/globalcitizen/lxc-gentoo
9 #
10 # this version is reworked with :
11 # - out of the lxc-create compat
12 # - vanilla gentoo config
13 # - ready to use cache
14 #
15
16 # Detect use under userns (unsupported)
17 for arg in "$@"; do
18 [ "$arg" = "--" ] && break
19 if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
20 echo "This template can't be used for unprivileged containers." 1>&2
21 echo "You may want to try the \"download\" template instead." 1>&2
22 exit 1
23 fi
24 done
25
26 # Make sure the usual locations are in PATH
27 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
28
29 # Ensure strict root's umask doesen't render the VM unusable
30 umask 022
31
32 LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
33
34 ################################################################################
35 # Various helper functions
36 ################################################################################
37
38 # param: $1: the name of the lock
39 # param: $2: the timeout for the lock
40 # The rest contain the command to execute and its parameters
41 execute_exclusively()
42 {
43 mkdir -p @LOCALSTATEDIR@/lock/subsys/
44
45 local lock_name="$1"
46 local timeout="$2"
47 shift 2
48
49 {
50 printf "Attempting to obtain an exclusive lock (timeout: %s sec) named \"%s\"...\n" "${timeout}" "$lock_name"
51
52 flock -x -w "${timeout}" 50
53
54 if [[ $? -ne 0 ]]; then
55 printf " => unable to obtain lock, aborting.\n"
56 return 2
57 else
58 printf " => done.\n"
59 fi
60
61 printf " => Executing \"%s\"\n" "$*"
62 "$@"
63 retval=$?
64 } 50> "@LOCALSTATEDIR@/lock/subsys/lxc-gentoo-${lock_name}"
65 return $retval
66 }
67
68 # a die function is always a good idea
69 die()
70 {
71 printf "\n[the last exit code leading to this death was: %s ]\n" "$?"
72 local retval="$1"
73 shift 1
74 printf "$@"
75 exit "$retval"
76 }
77
78 # gentoo arch/variant detection
79 set_default_arch()
80 {
81 printf "### set_default_arch: default arch/variant autodetect...\n"
82 arch=$(uname -m)
83 if [[ $arch =~ i.86 ]]; then
84 arch="x86"
85 variant="x86"
86 elif [[ $arch == "x86_64" ]]; then
87 arch="amd64"
88 variant="amd64"
89 elif [[ $arch =~ arm.* ]]; then
90 arch="arm"
91 variant="armv7a"
92 else
93 #who knows, it may work...
94 printf " => warn: unexpected arch:${arch} let me knows if it works :)\n"
95 variant="${arch}"
96 fi
97 printf " => Got: arch=%s variant=%s\n" "${arch}" "${variant}"
98 }
99
100 store_user_message()
101 {
102 user_message="${user_message}=> $@\n"
103 }
104
105 ################################################################################
106 # CACHE Preparation
107 ################################################################################
108 # during setup cachedir is $cacheroot/partial-$arch-$variant
109 # at the end, it will be $cacheroot/rootfs-$arch-$variant
110
111 cache_setup(){
112 partialfs="${cacheroot}/partial-${arch}-${variant}"
113
114 #if cache exists and flush not needed, return
115 [[ -d "${cachefs}" && -z "${flush_cache}" ]] && return 0
116
117 printf "###### cache_setup(): doing cache preparation\n"
118 local retval=1
119
120 #clean from failed previous run
121 rm -rf "${partialfs}"
122 mkdir -p "${partialfs}"
123
124 #let's go
125 cache_precheck && \
126 cache_stage3 && \
127 cache_portage && \
128 cache_inittab && \
129 cache_net && \
130 cache_dev && \
131 cache_openrc && \
132 cache_locale && \
133 rm -rf "${cachefs}" && \
134 mv "${partialfs}" "${cachefs}" && \
135 printf "###### cache_setup: Cache should be ready\n"
136
137 return $?
138 }
139
140 cache_precheck()
141 {
142 printf "### cache_precheck(): doing some pre-start checks ...\n"
143 # never hurts to have a fail-safe.
144 [[ -n "${cacheroot//\/}" ]] \
145 || die 8 "\$cacheroot (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${cacheroot}"
146 }
147
148 #get latest stage3 tarball
149 cache_stage3()
150 {
151 printf "### cache_stage3(): stage3 cache deployment...\n"
152
153 if [ -z "${tarball}" ]; then
154 #variables init
155 local stage3_baseurl="${mirror}/releases/${arch}/autobuilds"
156
157 # get latest-stage3....txt file for subpath
158 local stage3_pointer="${stage3_baseurl}/latest-stage3-${variant}.txt"
159
160 printf "Determining path to latest Gentoo %s (%s) stage3 archive...\n" "${arch}" "${variant}"
161 printf " => downloading and processing %s\n" "${stage3_pointer}"
162
163 local stage3_latest_tarball=$(wget -q -O - "${stage3_pointer}" | tail -n1 | cut -d' ' -f1) \
164 || die 6 "Error: unable to fetch\n"
165
166 printf " => Got: %s\n" "${stage3_latest_tarball}"
167
168 printf "Downloading/untarring the actual stage3 tarball...\n"
169 wget -O - "${stage3_baseurl}/${stage3_latest_tarball}" \
170 | tar -xjpf - --numeric-owner -C "${partialfs}" \
171 || die 6 "Error: unable to fetch or untar\n"
172 printf " => extracted to: %s\n" "${partialfs}"
173 else
174 printf "Extracting the stage3 tarball...\n"
175 tar -xpf "${tarball}" --numeric-owner -C "${partialfs}" \
176 || die 6 "unable to untar ${tarball} to ${partialfs}"
177 fi
178
179 #check if it chroots
180 printf "chroot test..."
181 chroot ${partialfs} /bin/true || die 1 "Error: chroot %s /bin/true, failed" "${partialfs}"
182 printf " OK\n"
183 printf " => stage3 cache extracted in : %s\n" "${partialfs}"
184 return 0
185 }
186
187 cache_portage()
188 {
189 printf "### cache_portage: caching portage tree tarball...\n"
190 [[ -z "${flush_cache}" && -f "${portage_cache}" ]] && return 0
191
192 rm -f ${portage_cache}
193
194 printf "Downloading Gentoo portage (software build database) snapshot...\n"
195 execute_exclusively portage 60 wget -O "${portage_cache}" "${mirror}/snapshots/portage-latest.tar.bz2" \
196 || die 6 "Error: unable to fetch\n"
197 printf " => done.\n"
198 }
199
200 # custom inittab
201 cache_inittab()
202 {
203 printf "### cache_inittab: tuning inittab...\n"
204
205 INITTAB="${partialfs}/etc/inittab"
206
207 [[ -w "$INITTAB" ]] || die 1 "Error: $INITTAB is not writeable"
208
209 # create console
210 echo "# Lxc main console" >> "$INITTAB"
211 echo "1:12345:respawn:/sbin/agetty -a root --noclear 115200 console linux" >> "$INITTAB"
212
213 # finally we add a pf line to enable clean shutdown on SIGPWR (issue 60)
214 echo "# clean container shutdown on SIGPWR" >> "$INITTAB"
215 echo "pf:12345:powerwait:/sbin/halt" >> "$INITTAB"
216
217 # we also blank out /etc/issue here in order to prevent delays spawning login
218 # caused by attempts to determine domainname on disconnected containers
219 sed -i 's/[\][Oo]//g' "${partialfs}/etc/issue"
220 }
221
222 cache_net()
223 {
224 printf "### cache_net: doing some useful net tuning...\n"
225 # useful for chroot
226 # /etc/resolv.conf
227 grep -i 'search ' /etc/resolv.conf > "${partialfs}/etc/resolv.conf"
228 grep -i 'nameserver ' /etc/resolv.conf >> "${partialfs}/etc/resolv.conf"
229
230 # fix boot-time interface config wipe under aggressive cap drop
231 # (openrc 0.9.8.4 ~sep 2012 - https://bugs.gentoo.org/show_bug.cgi?id=436266)
232 # initial warkaround was: sed -i -e 's/^#rc_nostop=""/rc_nostop="net.eth0 net.lo"/' "${partialfs}/etc/rc.conf"
233 # but this one does not depends on interfaces names
234 echo 'rc_keyword="-stop"' >> "${partialfs}/etc/conf.d/net"
235 }
236
237 cache_dev()
238 {
239 printf "### cache_dev(): /dev tuning...\n"
240
241 #Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054
242 mkdir "${partialfs}/dev/pts"
243 mkdir "${partialfs}/dev/shm"
244 mkdir "${partialfs}/dev/mqueue"
245
246 mkdir -m 755 "${partialfs}/dev/net"
247 mknod -m 666 "${partialfs}/dev/net/tun" c 10 200
248
249 return 0
250 }
251
252 # fix openrc system
253 cache_openrc()
254 {
255 printf "### cache_openrc(): doing openrc tuning\n"
256
257 #Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054
258 chroot "${partialfs}" sed s/-lxc//g -i "/etc/init.d/devfs"
259
260 return 0
261 }
262
263 cache_locale()
264 {
265 printf "### cache_locale(): initiating minimale locale en_US.UTF-8 \n"
266
267 echo "en_US.UTF-8 UTF-8" >> "${partialfs}/etc/locale.gen"
268 chroot "${partialfs}" locale-gen
269
270 return 0
271 }
272
273 ################################################################################
274 # CONTAINER Preparation
275 ################################################################################
276
277 container_setup() {
278 printf "##### container_setup(): starting container setup\n"
279
280 #in most cases lxc-create should have provided a copy of default lxc.conf
281 #let's tag where template starts, or just create the files
282 echo '### lxc-gentoo template stuff starts here' >> "$path/config"
283
284 #Determine rootfs
285 #If backingstore was specified, lxc.rootfs.path should be present or --rootfs did the rootfs var creation
286 if [ -z "${rootfs}" ]; then
287 rootfs=`awk -F= '$1 ~ /^lxc.rootfs.path/ { print $2 }' "$path/config" 2>/dev/null`
288 if [ -z "${rootfs}" ]; then
289 #OK it's default
290 rootfs="${path}/rootfs"
291 fi
292 fi
293 store_user_message "rootfs of container is : ${rootfs}"
294 store_user_message "config of container is : ${path}/config"
295
296 container_precheck && \
297 container_rootfs && \
298 container_consoles && \
299 container_tz && \
300 container_portage && \
301 container_net && \
302 container_hostname && \
303 container_auth && \
304 container_sshd && \
305 container_conf
306 if [ $? -ne 0 ]; then
307 die 1 "container_setup(): one step didn't complete, sorry\n"
308 fi
309
310 printf "###### container_setup(): container should be ready to start!\n"
311 printf "\n\n"
312 printf "You could now use you container with: lxc-start -n %s\n" "${name}"
313 printf "little things you should know about your container:\n"
314 printf "${user_message}"
315 return 0
316 }
317
318 container_precheck()
319 {
320 printf "### container_precheck(): doing some pre-start checks ...\n"
321 # never hurts to have a fail-safe.
322 [[ -n "${name//\/}" ]] \
323 || die 8 "\$name (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${name}"
324
325 [[ -n "${rootfs//\/}" ]] \
326 || die 8 "\$rootfs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${rootfs}"
327
328 [[ -n "${cachefs//\/}" ]] \
329 || die 8 "\$cachefs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${cachefs}"
330
331 # check if the rootfs already exists
332 [[ -d "${rootfs}/etc" ]] && die 18 "Error: \$rootfs (%s) already exists!" "${rootfs}"
333
334 # check cache
335 [[ ! -d "${cachefs}/etc" ]] && die 1 "Error: \$cachefs (%s) not found!" "${cachefs}"
336
337 return 0
338 }
339
340 container_rootfs()
341 {
342 printf "#### container_rootfs(): copying rootfs %s from cache %s ...\n" "${rootfs}" "${cachefs}"
343 tar -c -f - --numeric-owner -C "${cachefs}" . \
344 | tar -x -p -f - --numeric-owner -C "${rootfs}" \
345 || die 1 "Error: cache copy to rootfs failed"
346
347 printf "chroot test..."
348 chroot "${rootfs}" /bin/true || die 1 "Error: 'chroot %s /bin/true' failed"
349 printf " OK\n"
350
351 printf " => done\n"
352 return 0
353 }
354
355 container_consoles() {
356 printf "#### container_consoles(): setting container consoles ...\n"
357
358 # disable unwanted ttys
359 if [[ ${tty} < 6 ]]; then
360 local mindis=$(( ${tty} + 1 ))
361 sed -i "s/^c[${mindis}-6]/#&/" "${rootfs}/etc/inittab"
362 fi
363 printf " => main console + ${tty} ttys\n"
364
365 if [[ -z "${autologin}" ]]; then
366 sed 's/agetty -a root/agetty/' -i "${rootfs}/etc/inittab"
367 elif [[ "${user}" != "root" ]]; then
368 sed "s/agetty -a root/agetty -a ${user}/" -i "${rootfs}/etc/inittab"
369 printf " => Autologin on main console for %s enabled\n" "${user}"
370 [[ -z "${forced_password}" ]] && unset password
371 store_user_message "${user} has autologin on main console"
372 else
373 printf " => Autologin on main console for root enabled\n"
374 [[ -z "${forced_password}" ]] && unset password
375 store_user_message "${user} has autologin on main console"
376 fi
377 printf " => done\n"
378 }
379
380 container_tz()
381 {
382 printf "#### container_tz(): setting container timezone ...\n"
383
384 #let's try to copy it from host
385 if [ -L "/etc/localtime" ]; then
386 #host has a symlink
387 #let see if we can reproduct symlink
388 target=$(readlink /etc/localtime)
389 if [[ "$target" != "" ]]; then
390 if [ -f "${rootfs}/${target}" ]; then
391 #same target exists in container
392 chroot "${rootfs}" ln -sf "${target}" "/etc/localtime"
393 printf " => host symlink reproducted in container : %s\n" "${target}"
394 store_user_message "timezone copyed from host"
395 return 0
396 fi
397 fi
398 fi
399
400 if [ -e /etc/localtime ]; then
401 # duplicate host timezone
402 cat /etc/localtime > "${rootfs}/etc/localtime"
403 printf " => host localtime copyed to container\n"
404 store_user_message "timezone was staticly copyed from host"
405 else
406 # otherwise set up UTC
407 chroot "${rootfs}" ln -sf /usr/share/zoneinfo/UTC /etc/localtime
408 printf " => fallback: fixed to UTC\n"
409 store_user_message "timezone was fixed to UTC"
410 fi
411 }
412
413
414 container_portage()
415 {
416 printf "#### container_portage(): setting container portage... \n"
417
418 #default entry for conf
419 portage_mount="#container set with private portage tree, no mount here"
420
421 printf "Warnings are normal here, don't worry\n"
422 #container repos detection
423 if chroot ${rootfs} portageq get_repo_path / gentoo > /dev/null ; then
424 portage_container="$(chroot ${rootfs} portageq get_repo_path / gentoo)"
425 else
426 die 1 "Failed to figure out container portage tree location with portageq get_repo_path / gentoo\n"
427 fi
428
429 if [[ -n "${private_portage}" ]]; then
430 container_private_portage
431 return 0
432 fi
433
434 if [ -z "${portage_dir}" ]; then
435 #gentoo host detection
436 printf "trying to guess portage_dir from host...\n"
437 portage_dir="$(portageq get_repo_path / gentoo 2>/dev/null)"
438 if [ ! -d "${portage_dir}/profiles" ]; then
439 printf " => host portage detection failed (not gentoo host), fallback to private portage tree\n"
440 container_private_portage
441 return 0
442 fi
443 else
444 if [ ! -d "${portage_dir}/profiles" ]; then
445 die 1 "specified portage_dir (%s) does not contains profiles, is it a portage tree ?\n" "${portage_dir}"
446 fi
447 fi
448
449 printf "trying to guess portage distfiles dir from host ...\n"
450 portage_distfiles_dir="$(portageq distdir 2>/dev/null)"
451 if [ ! -d "${portage_distfiles_dir}" ]; then
452 portage_distfiles_dir="${portage_dir}/distfiles"
453 fi
454
455 # if we are here, we have shared portage_dir
456 #ensure dir exists
457 chroot "${rootfs}" mkdir ${portage_container}
458 portage_mount="#container set with shared portage
459 lxc.mount.entry=${portage_dir} ${portage_container/\//} none ro,bind 0 0
460 lxc.mount.entry=${portage_distfiles_dir} ${portage_container/\//}/distfiles none rw,bind 0 0
461 #If you use eix, you should uncomment this
462 #lxc.mount.entry=/var/cache/eix var/cache/eix none ro,bind 0 0"
463 store_user_message "container has a shared portage from host's ${portage_dir} to ${portage_container/\//}"
464 #Let's propose binary packages
465 cat <<- EOF >> "${rootfs}/etc/portage/make.conf"
466 # enable this to store built binary packages
467 #FEATURES="\$FEATURES buildpkg"
468
469 # enable this to use built binary packages
470 #EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --usepkg"
471
472 # enable and *tune* this kind of entry to slot binaries, specialy if you use multiples archs and variants
473 #PKGDIR="\${PKGDIR}/amd64
474 #or PKGDIR="\${PKGDIR}/hardened"
475 EOF
476 printf " => portage stuff done, see /etc/portage/make.conf for additional tricks\n"
477
478 }
479
480 container_private_portage()
481 {
482 #called from container_portage() do not call directly from container_setup
483 printf "# untaring private portage to %s from %s ... \n" "${rootfs}/${portage_container}" "${portage_cache}"
484 mkdir -p "${rootfs}/${portage_container}"
485 execute_exclusively portage 60 \
486 tar -xp --strip-components 1 -C "${rootfs}/${portage_container}" \
487 -f "${portage_cache}" --numeric-owner \
488 || die 2 "Error: unable to extract the portage tree.\n"
489 store_user_message "container has its own portage tree at ${portage_container}"
490 printf "=> done\n"
491 }
492
493 #helper func for container_genconf_net()
494 nic_write()
495 {
496 #display with gentoo's confd.net format
497 echo "config_${nic_name}=\"${nic_conf}\""
498 #add to managed list
499 [[ "${nic_conf}" == "dhcp" ]] && nic_managed="${nic_managed} ${nic_name}"
500 [[ "${nic_conf}" == "null" ]] && nic_unmanaged="${nic_unmanaged} ${nic_name}"
501 [[ -z "${nic_hwaddr}" && ${nic_type} == "veth" ]] && nic_wo_hwaddr="${nic_wo_hwaddr} ${nic_name}"
502 nic_writed=1
503 }
504
505 #Analyse lxc.conf and print conf.d/net content
506 container_conf_net()
507 {
508 local file=${1}
509 [[ -z "${nic_last}" ]] && nic_last=-1
510 [[ -z "${nic_named}" ]] && nic_named=0
511 OLDIFS=$IFS
512 IFS="
513 "
514 #let's do some drity bash things to parse lxc network conf
515 for line in $( sed -r "s/[ ]*=[ ]*/_real_ugly_sep_42_/" "${file}" ); do
516 key=$(echo "${line}" | sed 's/_real_ugly_sep_42_.*$//')
517 value=$(echo "${line}" | sed 's/^.*_real_ugly_sep_42_//')
518
519 #new nic !
520 if [[ "${key}" == "lxc.net.0.type" ]]; then
521 #we don't know what to do with it.
522 [[ "${value}" == "empty" ]] && continue
523
524 #write conf from previous loops
525 [[ "${nic_writed}" == "0" ]] && nic_write
526
527 #init defaults
528 let nic_last=nic_last+1
529
530 nic_writed=0
531 #if 1 named between 2 not named: last is eth1
532 #=> Number is ID munis number of named NIC before
533 nic_name="eth$(( ${nic_last} - ${nic_named} ))"
534 nic_conf="dhcp"
535 nic_type="${value}"
536 fi
537
538 if [[ "${key}" == "lxc.net.0.hwaddr" ]]; then
539 nic_hwaddr=1
540 fi
541
542 if [[ "${key}" =~ ^lxc.net.0.ipv(4|6) ]]; then
543 #tell openrc to not manage this NIC as LXC set there address
544 nic_conf="null"
545 fi
546 if [[ "${key}" =~ ^lxc.net.0.name ]]; then
547 nic_name="${value}"
548 let nic_named=nic_named+1
549 fi
550 if [[ "${key}" == "lxc.include" ]]; then
551 #recursive into include
552 container_conf_net "${value}"
553 fi
554 done
555 #write conf from previous loops
556 [[ "${nic_writed}" == "0" ]] && nic_write
557 IFS=$OLDIFS
558 }
559
560 container_net()
561 {
562 printf "container_net(): setting container network conf... \n"
563
564 #Analyse network configuration in config
565 container_conf_net "$path/config" >> "${rootfs}/etc/conf.d/net"
566
567 # found how much nic finally have
568 nic_count=$(( ${nic_last} + 1 ))
569
570 # unless openrc manage a nic, we now have to force openrc to automatic
571 # provision of the 'net' dep. If we do not, network dependent services
572 # will fail to load
573 if [[ -z "${nic_managed}" ]]; then
574 #tell openrc that lxc already did the work
575 echo 'rc_provide="net"' >> "${rootfs}/etc/rc.conf"
576 fi
577
578 #No NIC ?
579 if [[ ${nic_count} == 0 ]]; then
580 #If no Nic, no need to continue
581 bridge=$(brctl show | awk 'NR==2 {print $1}')
582 if [[ "${bridge}" != "" ]]; then
583 store_user_message "No network interface for this container
584 It's a pitty, you have bridge, ${bridge}.
585 If it is for Lxc, use it next time by adding this to your default.conf :
586 lxc.net.0.type = veth
587 lxc.net.0.link = ${bridge}
588 lxc.net.0.flags = up
589 lxc.net.0.hwaddr = fe:xx:xx:xx:xx:xx"
590 return 0
591 else
592 store_user_message "No network interface for this container"
593 return 0
594 fi
595 fi
596
597 #For each openrc managed nic, activate
598 sys_nic_index=1
599 for nic in ${nic_managed}
600 do
601 chroot "${rootfs}" ln -s net.lo "/etc/init.d/net.${nic}"
602 chroot "${rootfs}" rc-update add net.${nic} default
603 #fake sysfs for openrc, in case settings does not provide it
604 mkdir -p "${rootfs}/sys/class/net/${nic}"
605 echo ${sys_nic_index} > "${rootfs}/sys/class/net/${nic}/ifindex"
606 echo up > "${rootfs}/sys/class/net/${nic}/operstate"
607 let sys_nic_index=sys_nic_index+1
608 done
609
610 #Warn about dynamic hwaddr
611 if [[ -n "${nic_wo_hwaddr}" ]]; then
612 store_user_message "Warning, these veth NIC don't have fixed hwaddr :
613 ${nic_wo_hwaddr}
614
615 see http://lists.linuxcontainers.org/pipermail/lxc-devel/2013-December/006736.html
616 and man lxc.conf"
617 fi
618
619 printf " => network conf done.\n"
620 }
621
622 # custom hostname
623 container_hostname()
624 {
625 printf "#### container_hostname(): setting hostname... \n"
626 printf "hostname=\"%s\"\n" "${name}" > "${rootfs}/etc/conf.d/hostname"
627 printf " => done.\n"
628 }
629
630 container_auth()
631 {
632 printf "#### container_auth(): setting authentification... \n"
633 if [[ "${user}" != "root" ]]; then
634 printf " non root user requested, creating... \n"
635 chroot "${rootfs}" useradd --create-home -s /bin/bash "${user}" || die 1 "failed to create user ${user}"
636 printf " => user %s created\n" "${user}"
637 fi
638 store_user_message "Connection user is ${user}"
639 #Home of user
640 auth_home=$(chroot "${rootfs}" getent passwd "${user}" | cut -d : -f 6)
641 if [[ -r "${auth_key}" ]]; then
642 printf " deploying auth_key %s for user %s ...\n" "${auth_key}" "${user}"
643 mkdir -p "${rootfs}/${auth_home}/.ssh"
644 cat "${auth_key}" >> "${rootfs}/${auth_home}/.ssh/authorized_keys"
645 chroot "${rootfs}" chown "${user}:" "${auth_home}/.ssh/authorized_keys"
646 printf " => inserted public key in %s/.ssh/authorized_keys\n" "${auth_home}"
647 [[ -z "${forced_password}" ]] && unset password
648 store_user_message "${user} has the ssh key you gave us"
649 fi
650
651 if [[ -n "${password}" ]]; then
652 printf " setting password for %s ...\n" "${user}"
653 echo "${user}:${password}" | chroot "${rootfs}" chpasswd || die 1 "failed to change password"
654 printf " => done. if you didn't specify , default is 'toor'\n"
655 if [[ -n "${forced_password}" ]]; then
656 store_user_message "${user} has the password you give for him"
657 fi
658 fi
659
660 printf " => done.\n"
661 }
662
663 container_sshd() {
664 printf "#### container_sshd(): enabling sshd... \n"
665
666 chroot "${rootfs}" rc-update add sshd || die 1 "failed to enable sshd\n"
667
668 printf " => done.\n"
669 }
670
671 ################################################################################
672 # lxc configuration files
673 ################################################################################
674
675 container_conf()
676 {
677 printf "container_configuration(): making lxc configuration file... \n"
678
679 #at this point if there
680 conf_file="${path}/config"
681
682 # if there is exactly one veth network entry, make sure it has an
683 # associated hwaddr.
684 nics=`grep -e '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' ${conf_file} | wc -l`
685 if [ $nics -eq 1 ]; then
686 grep -q "^lxc.net.0.hwaddr" ${conf_file} || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" ${conf_file}
687 fi
688
689 if grep -q "^lxc.rootfs.path" "${conf_file}" ; then
690 #lxc-create already provided one
691 conf_rootfs_line=""
692 else
693 conf_rootfs_line="lxc.rootfs.path = $(readlink -f "${rootfs}")"
694 fi
695 if [[ "${arch}" == "x86" || "${arch}" == "amd64" ]]; then
696 local conf_arch_line="lxc.arch = ${arch}"
697 else
698 local conf_arch_line="# lxc.arch = ${arch}"
699 fi
700
701 cat <<- EOF >> "${conf_file}"
702 # sets container architecture
703 # If desired architecture != amd64 or x86, then we leave it unset as
704 # LXC does not oficially support anything other than x86 or amd64.
705 ${conf_arch_line}
706
707 # set the hostname
708 lxc.uts.name = ${name}
709 lxc.tty.max = ${tty}
710
711 ${conf_rootfs_line}
712 ${portage_mount}
713 ${conf_sysfs}
714 ${conf_mounts}
715
716 lxc.include = ${LXC_TEMPLATE_CONFIG}/gentoo.${settings}.conf
717 EOF
718 printf " => done.\n"
719 }
720
721 usage()
722 {
723 cat <<EOF
724 $1 -h|--help [-a|--arch <arch>] [-v|--variant <variant>] [-P|--private-portage] [--portage-dir <protagedir>] [-t|--tarball <stage3file>]
725 [-F|--flush-cache] [-c|--cache-only] [-u|--user <username>] [-w|--password <password>] [--autologin] [-S|--auth-key <keyfile>]
726 [-s|--settings <name>] [-m|--mirror <gentoomirror>] [--tty <number>]
727
728 arch: the container architecture (e.g. amd64): defaults to host arch (currently: '${arch}')
729 If you choose one that needs emulation
730 tested: amd64, x86
731 You could try any other gentoo arch, why not...
732
733 variant: gentoo's Architecture variant as of dec 2013 : (currently: '${variant}')
734 for amd64 arch: amd64 (default), amd64-hardened+nomultilib, amd64-hardened, amd64-nomultilib, x32
735 for x86 arch: i686 (default), i486, i686-hardened
736 for arm arch: armv7a (default), armv7a_hardfp, armv6j, armv6j_hardfp, armv5tel, armv4tl
737
738 private-portage: by default, /usr/portage is mount-binded with host one if exists (currently: '${private_portage}')
739 this force container to have his own copy
740
741 portage-dir: portage dir used for shared portage
742 by default the host on if any (currently: '${portage_dir}')
743
744 tarball: force usage of local stage3 archive (currently: '${arch}')
745 If empty, latest will be downloaded
746
747 flush-cache: do like there is no previous cache
748
749 cache-only: just ensure cache is present
750 if cache exists and "flush-cache" not specified, does nothing
751
752 user: user used in auth oriented options (currently: '${user}')
753
754 password: password for user (currently: '${password}')
755 if default, usage of auth-key will disable password setting
756
757 autologin: enable autologin for user (currently: '${autologin}')
758 This unset default password setting
759
760 auth-key: SSH Public key file to inject into container for user (currently: '${auth_key}')
761 This unset default password setting
762
763 settings: choose common configuration (currently: '${settings}')
764 see ${LXC_TEMPLATE_CONFIG}/gentoo.*.conf
765 Available settings:
766 $(ls -1 ${LXC_TEMPLATE_CONFIG}/gentoo.*.conf | xargs basename -a -s .conf | sed 's/^gentoo.//')
767
768 mirror: gentoo mirror for download (currently: '${mirror}')
769
770 tty: number of tty (6 max) (currently: '${tty}')
771 EOF
772 exit 0
773 }
774
775 #some overridable defaults
776 set_default_arch
777
778 mirror="http://distfiles.gentoo.org"
779 user="root"
780 tty=1
781 settings="common"
782 options=$(getopt -o hp:n:a:FcPv:t:S:u:w:s:m: -l help,rootfs:,path:,name:,arch:,flush-cache,cache-only,private-portage,variant:,portage-dir:,tarball:,auth-key:,user:,autologin,password:,settings:,mirror:,tty: -- "$@")
783
784 eval set -- "$options"
785
786 while true
787 do
788 case "$1" in
789 -h|--help) usage $0 && exit 0;;
790 --rootfs) rootfs=$2; shift 2;;
791 -p|--path) path=$2; shift 2;;
792 -n|--name) name=$2; shift 2;;
793 -a|--arch) arch=$2; shift 2;;
794 -F|--flush-cache) flush_cache=1; shift 1;;
795 -c|--cache-only) cache_only=1; shift 1;;
796 -P|--private-portage) private_portage=1; shift 1;;
797 -v|--variant) variant=$2; shift 2;;
798 --portage-dir) portage_dir=$2; shift 2;;
799 -t|--tarball) tarball=$2; shift 2;;
800 -S|--auth-key) auth_key=$2; shift 2;;
801 -u|--user) user=$2; shift 2;;
802 -w|--password) forced_password=1; password=$2; shift 2;;
803 -s|--settings) settings=$2; shift 2;;
804 -m|--mirror) mirror=$2; shift 2;;
805 --container-cache) containercache=$2; shift 2;;
806 --tty) [[ $2 -lt 6 ]] && tty=$2; shift 2;;
807 --autologin) autologin=1; shift 1;;
808 --) shift 1; break ;;
809 *) break ;;
810 esac
811 done
812
813 # Allow the cache path to be set by environment variable
814 cacheroot="${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/gentoo"
815 portage_cache="${cacheroot}/portage.tbz"
816 cachefs="${cacheroot}/rootfs-${arch}-${variant}"
817
818 alias wget="wget --timeout=8 --read-timeout=15 -c -t10 -nd"
819
820 do_all() {
821 cache_setup
822 if [ -z "${cache_only}" ]; then
823 container_setup
824 fi
825 }
826
827 execute_exclusively "cache-${arch}-${variant}" 60 do_all