source: src-sh/warden/scripts/backend/functions.sh

Last change on this file was 7a5bb3d5, checked in by William Katsak <wkatsak@…>, 7 months ago

Add warden.conf setting to use NAT for VIMAGE jails

Disable by default.

Signed-off-by: William Katsak <wkatsak@…>

  • Property mode set to 100755
File size: 46.7 KB
Line 
1#!/bin/sh
2# Functions / variables for warden
3######################################################################
4# DO NOT EDIT
5
6# Source local functions
7. /usr/local/share/pcbsd/scripts/functions.sh
8
9# Installation directory
10PROGDIR="/usr/local/share/warden"
11
12# Jail location
13JDIR="$(grep ^JDIR: /usr/local/etc/warden.conf | cut -d' ' -f2)"
14export JDIR
15
16# Set arch type
17REALARCH=`uname -m`
18export REALARCH
19if [ -z "$ARCH" ] ; then
20  ARCH="$REALARCH"
21  export ARCH
22fi
23
24# Location of pcbsd.conf file
25PCBSD_ETCCONF="/usr/local/etc/pcbsd.conf"
26
27# Network interface to use
28NIC="$(grep ^NIC: /usr/local/etc/warden.conf | sed 's|NIC: ||g' | sed 's|NIC:||g')"
29export NIC
30
31# Tmp directory
32WTMP="$(grep ^WTMP: /usr/local/etc/warden.conf | cut -d' ' -f2)"
33export WTMP
34
35# Default IP4 Pool of addresses
36DEFAULT_IP4POOL="$(grep ^IP4POOL: /usr/local/etc/warden.conf | cut -d' ' -f2)"
37if [ -z "$DEFAULT_IP4POOL" ] ; then
38   DEFAULT_IP4POOL="192.168.0.220"
39fi
40export DEFAULT_IP4POOL
41
42# enable NAT
43NAT_ENABLE="$(grep ^NAT_ENABLE: /usr/local/etc/warden.conf | cut -d' ' -f2)"
44export NAT_ENABLE
45
46# FreeBSD release
47FREEBSD_RELEASE="$(grep ^FREEBSD_RELEASE: /usr/local/etc/warden.conf | cut -d' ' -f2)"
48if [ -z "${FREEBSD_RELEASE}" ] ; then
49  FREEBSD_RELEASE="$(uname -r)"
50fi
51export UNAME_r="${FREEBSD_RELEASE}"
52
53# Temp file for dialog responses
54ATMP="/tmp/.wans"
55export ATMP
56
57# Warden Version
58WARDENVER="1.4"
59export WARDENVER
60
61# Dirs to nullfs mount in X jail
62NULLFS_MOUNTS="/tmp /media"
63X11_MOUNTS="/usr/local/lib/X11/icons /usr/local/lib/X11/fonts /usr/local/etc/fonts"
64
65# Clone directory
66CDIR="${JDIR}/clones"
67
68downloadpluginjail() {
69  local _ver="${1}"
70
71  SYSVER=`echo "${_ver}" | sed -E 's|^FreeNAS-(([0-9]+\.){2}[0-9]+).*|\1|'`
72  SYSREL=`echo "${_ver}" | sed -E 's|^FreeNAS-([0-9]+\.){2}[0-9]+-([a-zA-Z0-9]+)-.*|\2|'`
73  SYSARCH=`echo "${_ver}" | sed -E 's#^(.*)(x86|x64)#\2#'`
74
75  SF="http://downloads.sourceforge.net/project/freenas"
76  URL="${SF}/FreeNAS-${SYSVER}/${SYSREL}/${SYSARCH}/plugins"
77
78  PJAIL="FreeNAS-${SYSVER}-${SYSREL}-${SYSARCH}.Plugins_Jail.pbi"
79  PJAILSHA256="${PJAIL}.sha256"
80
81  if [ ! -d "${JDIR}" ] ; then mkdir -p "${JDIR}" ; fi
82  cd ${JDIR}
83
84  echo "Fetching jail environment. This may take a while..."
85
86  if [ ! -e "${PJAIL}" ] ; then
87     echo "Downloading ${URL}/${PJAIL} ..."
88     get_file "${URL}/${PJAIL}" "${PJAIL}" 3
89     [ $? -ne 0 ] && printerror "Error while downloading the pluginjail."
90  fi
91
92  if [ ! -e "${PJAILSHA256}" ] ; then
93     echo "Downloading ${URL}/${PJAILSHA256} ..."
94     get_file "${URL}/${PJAILSHA256}" "${PJAILSHA256}" 3
95     [ $? -ne 0 ] && printerror "Error while downloading the pluginjail sha256."
96  fi
97
98  [ "$(sha256 -q ${PJAIL})" != "$(cat ${PJAILSHA256})" ] &&
99    printerror "Error in download data, checksum mismatch. Please try again later."
100
101  # Get the dataset of the jails mountpoint
102  rDataSet=`mount | grep "on ${JDIR} " | awk '{print $1}'`
103  tSubDir=`basename $WORLDCHROOT`
104  nDataSet="${rDataSet}/${tSubDir}"
105
106  echo "Creating ZFS ${nDataSet} dataset..."
107  isDirZFS "${WORLDCHROOT}" "1"
108  if [ $? -ne 0 ] ; then
109     zfs create -p ${nDataSet}
110     if [ $? -ne 0 ] ; then exit_err "Failed creating ZFS base dataset"; fi
111     mkdir -p "${WORLDCHROOT}/.plugins" >/dev/null 2>&1
112  fi
113
114  pbi_add -e --no-checksig -p ${WORLDCHROOT} ${PJAIL}
115  if [ $? -ne 0 ] ; then exit_err "Failed extracting ZFS chroot environment"; fi
116
117  zfs snapshot ${nDataSet}@clean
118  if [ $? -ne 0 ] ; then exit_err "Failed creating clean ZFS base snapshot"; fi
119  rm ${PJAIL}
120  rm ${PJAILSHA256}
121};
122
123### Download the chroot
124downloadchroot() {
125  local CHROOT="${1}"
126
127  # XXX If this is PCBSD, pbreg get /PC-BSD/Version
128  SYSVER="$(echo "$(uname -r)" | cut -f1 -d'-')"
129  FBSD_TARBALL="fbsd-release.txz"
130  FBSD_TARBALL_CKSUM="${FBSD_TARBALL}.md5"
131
132  # Set the mirror URL, may be overridden by setting MIRRORURL environment variable
133  if [ -z "${MIRRORURL}" ]; then
134    get_mirror
135    MIRRORURL="$VAL"
136  fi
137
138  if [ ! -d "${JDIR}" ] ; then mkdir -p "${JDIR}" ; fi
139  cd ${JDIR}
140
141  echo "Fetching jail environment. This may take a while..."
142  echo "Downloading ${MIRRORURL}/${SYSVER}/${ARCH}/netinstall/${FBSD_TARBALL} ..."
143
144  if [ ! -e "$FBSD_TARBALL" ] ; then
145     get_file "${MIRRORURL}/${SYSVER}/${ARCH}/netinstall/${FBSD_TARBALL}" "$FBSD_TARBALL" 3
146     [ $? -ne 0 ] && printerror "Error while downloading the portsjail."
147  fi
148
149  if [ ! -e "$FBSD_TARBALL_CKSUM" ] ; then
150     get_file "${MIRRORURL}/${SYSVER}/${ARCH}/netinstall/${FBSD_TARBALL_CKSUM}" "$FBSD_TARBALL_CKSUM" 3
151     [ $? -ne 0 ] && printerror "Error while downloading the portsjail."
152  fi
153
154  [ "$(md5 -q ${FBSD_TARBALL})" != "$(cat ${FBSD_TARBALL_CKSUM})" ] &&
155    printerror "Error in download data, checksum mismatch. Please try again later."
156
157  # Get the dataset of the jails mountpoint
158  rDataSet=`mount | grep "on ${JDIR} " | awk '{print $1}'`
159  tSubDir=`basename $CHROOT`
160  nDataSet="${rDataSet}/${tSubDir}"
161
162  echo "Creating ZFS ${CHROOT} dataset..."
163  isDirZFS "${CHROOT}" "1"
164  if [ $? -ne 0 ] ; then
165     zfs create -p ${nDataSet}
166     if [ $? -ne 0 ] ; then exit_err "Failed creating ZFS base dataset"; fi
167  fi
168
169  tar xvpf ${FBSD_TARBALL} -C ${CHROOT} 2>/dev/null
170  if [ $? -ne 0 ] ; then exit_err "Failed extracting ZFS chroot environment"; fi
171
172  zfs snapshot ${nDataSet}@clean
173  if [ $? -ne 0 ] ; then exit_err "Failed creating clean ZFS base snapshot"; fi
174  rm ${FBSD_TARBALL}
175  rm ${FBSD_TARBALL_CKSUM}
176};
177
178# Check if a directory is mounted
179isDirMounted() {
180  mount | grep -q "on $1 ("
181  return $?
182}
183
184### Mount all needed filesystems for the jail
185mountjailxfs() {
186
187  if [ ! -d "${JDIR}/${1}/" ] ; then
188     exit_err "Invalid jail directory: ${JDIR}/${1}"
189  fi
190
191  # Update the user files on the portjail
192  ETCFILES="resolv.conf passwd master.passwd spwd.db pwd.db group localtime"
193  for file in ${ETCFILES}; do
194    rm ${JDIR}/${1}/etc/${file} >/dev/null 2>&1
195    cp /etc/${file} ${JDIR}/${1}/etc/${file}
196  done
197
198  for nullfs_mount in ${NULLFS_MOUNTS}; do
199    if [ ! -d "${JDIR}/${1}${nullfs_mount}" ] ; then
200      mkdir -p "${JDIR}/${1}${nullfs_mount}"
201    fi
202    if is_symlinked_mountpoint ${nullfs_mount}; then
203      echo "${nullfs_mount} has symlink as parent, not mounting"
204      continue
205    fi
206
207    # If this is already mounted we can skip for now
208    isDirMounted "${JDIR}/${1}${nullfs_mount}" && continue
209
210    echo "Mounting ${JDIR}/${1}${nullfs_mount}"
211    mount_nullfs ${nullfs_mount} ${JDIR}/${1}${nullfs_mount}
212  done
213
214  # Check and mount /dev
215  isDirMounted "${JDIR}/${1}/dev"
216  if [ $? -ne 0 ] ; then
217    echo "Enabling devfs"
218    mount -t devfs devfs ${JDIR}/${1}/dev
219  fi
220
221  # Add support for linprocfs for ports that need linprocfs to build/run
222  if [  ! -d "${JDIR}/${1}/compat/linux/proc" ]; then
223    mkdir -p ${JDIR}/${1}/compat/linux/proc
224  fi
225  if is_symlinked_mountpoint ${JDIR}/${1}/compat/linux/proc; then
226    echo "${JDIR}/${1}/compat/linux/proc has symlink as parent, not mounting"
227    return
228  fi
229
230  # If this is already mounted we can skip for now
231  isDirMounted "${JDIR}/${1}/compat/linux/proc"
232  if [ $? -ne 0 ] ; then
233    echo "Enabling linprocfs support."
234    mount -t linprocfs linprocfs ${JDIR}/${1}/compat/linux/proc
235  fi
236
237  # Add support for linsysfs for ports that need linprocfs to build/run
238  if [  ! -d "${JDIR}/${1}/compat/linux/sys" ]; then
239    mkdir -p ${JDIR}/${1}/compat/linux/sys
240  fi
241  if is_symlinked_mountpoint ${JDIR}/${1}/compat/linux/sys; then
242    echo "${JDIR}/${1}/compat/linux/sys has symlink as parent, not mounting"
243    return
244  fi
245
246  # If this is already mounted we can skip for now
247  isDirMounted "${JDIR}/${1}/compat/linux/sys"
248  if [ $? -ne 0 ] ; then
249    echo "Enabling linsysfs support."
250    mount -t linsysfs linsysfs ${JDIR}/${1}/compat/linux/sys
251  fi
252
253  # Lastly we need to mount /usr/home/* directories
254  for i in `ls -d /usr/home/*`
255  do
256    # If this is already mounted we can skip for now
257    isDirMounted "${JDIR}/${1}${i}" && continue
258    if [ ! -d "${JDIR}/${1}${i}" ] ; then mkdir -p ${JDIR}/${1}${i} ; fi
259    echo "Mounting home: ${i}"
260    mount_nullfs ${i} ${JDIR}/${1}${i}
261  done
262
263}
264
265### Umount all the jail's filesystems
266umountjailxfs() {
267  status="0"
268  # Umount all filesystems that are mounted into the portsjail
269  for mountpoint in $(mount | grep ${JDIR}/${1}/ | cut -d" " -f3); do
270    if [ "$mountpoint" = "${JDIR}/${1}/dev" ] ; then continue ; fi
271    if [ "$mountpoint" = "${JDIR}/${1}/" ] ; then continue ; fi
272    if [ "$mountpoint" = "${JDIR}/${1}" ] ; then continue ; fi
273    echo "Unmounting $mountpoint"
274    umount -f ${mountpoint}
275    if [ $? -ne 0 ] ; then status="1" ; fi
276  done
277  # Now try to umount /dev
278  umount -f ${JDIR}/${1}/dev 2>/dev/null >/dev/null
279  return $status
280}
281
282# Check if PBI scripts are loaded in jail
283checkpbiscripts() {
284  if [ -z "${1}" ] ; then return ; fi
285  if [ ! -e "${1}/usr/local/sbin/pbi_info" ] ; then
286    copypbiscripts "${1}"
287  elif [ "`ls -l /usr/local/sbin/pbi_info | awk '{print $5}'`" != "`ls -l ${1}/usr/local/sbin/pbi_info | awk '{print $5}'`" ] ; then
288    copypbiscripts "${1}"
289  fi
290}
291
292# Copy PBI scripts to jail
293copypbiscripts() {
294  if [ -z "${1}" ] ; then return ; fi
295  mkdir -p ${1}/usr/local/sbin >/dev/null 2>/dev/null
296  cp /usr/local/sbin/pbi* ${1}/usr/local/sbin/
297  chmod 755 ${1}/usr/local/sbin/pbi*
298
299  # Copy rc.d pbid script
300  mkdir -p ${1}/usr/local/etc/rc.d >/dev/null 2>/dev/null
301  cp /usr/local/etc/rc.d/pbid ${1}/usr/local/etc/rc.d/
302
303  # Copy any PBI manpages
304  for man in `find /usr/local/man | grep pbi`
305  do
306    if [ ! -d "${1}`dirname $man`" ] ; then
307      mkdir -p "${1}`dirname $man`"
308    fi
309    cp "${man}" "${1}${man}"
310  done
311}
312
313mkportjail() {
314  if [ -z "${1}" ] ; then return ; fi
315  ETCFILES="resolv.conf passwd master.passwd spwd.db pwd.db group localtime"
316  for file in ${ETCFILES}; do
317    rm ${1}/etc/${file} >/dev/null 2>&1
318    cp /etc/${file} ${1}/etc/${file}
319  done
320 
321  # Need to symlink /home
322  chroot ${1} ln -fs /usr/home /home
323
324  # Make sure we remove our cleartmp rc.d script, causes issues
325  [ -e "${1}/etc/rc.d/cleartmp" ] && rm ${1}/etc/rc.d/cleartmp
326
327  # Flag this type
328  touch ${JMETADIR}/jail-portjail
329}
330
331mkpluginjail() {
332  if [ -z "${1}" ] ; then return ; fi
333  ETCFILES="resolv.conf passwd master.passwd spwd.db pwd.db group localtime"
334  for file in ${ETCFILES}; do
335    rm ${1}/etc/${file} >/dev/null 2>&1
336    cp /etc/${file} ${1}/etc/${file}
337  done
338 
339  # Need to symlink /home
340  chroot ${1} ln -fs /usr/home /home
341
342  # Make sure we remove our cleartmp rc.d script, causes issues
343  [ -e "${1}/etc/rc.d/cleartmp" ] && rm ${1}/etc/rc.d/cleartmp
344  # Flag this type
345  touch ${JMETADIR}/jail-pluginjail
346}
347
348mkZFSSnap() {
349  isDirZFS "${1}" "1"
350  if [ $? -ne 0 ] ; then printerror "Not a ZFS volume: ${1}" ; fi
351  tank=`getZFSTank "$1"`
352  rp=`getZFSRelativePath "$1"`
353  zdate=`date +%Y-%m-%d-%H-%M-%S`
354  snaptag="$zdate"
355  if [ -n "$3" ] ; then snaptag="$3"; fi
356
357  rc_halt "zfs snapshot $tank${rp}@${snaptag}"
358
359  # Do we have a comment to set?
360  if [ -n "$2" ] ; then
361      zfs set warden:comment="$2" ${tank}${rp}@${snaptag}
362  fi
363}
364
365listZFSSnap() {
366  isDirZFS "${1}" "1"
367  if [ $? -ne 0 ] ; then printerror "Not a ZFS volume: ${1}" ; fi
368  tank=`getZFSTank "$1"`
369  rp=`getZFSRelativePath "$1"`
370
371  echo "Snapshot                                Comment"
372  echo "-----------------------------------------------"
373  for i in `zfs list -r -t snapshot ${tank}${rp} 2>/dev/null | cut -d '@' -f 2 | awk '{print $1}'`
374  do
375     comment=`zfs get -o value warden:comment ${tank}${rp}@$i 2>/dev/null| grep -v "VALUE"`
376     lcomment=`zfs get -o value lpreserver:comment ${tank}${rp}@$i 2>/dev/null| grep -v "VALUE"`
377     if [ -z "$comment" -a -n "$lcomment" ] ; then
378       echo "$i         $lcomment"
379     else
380       echo "$i         $comment"
381     fi
382  done
383}
384
385listZFSClone() {
386  isDirZFS "${1}" "1"
387  if [ $? -ne 0 ] ; then printerror "Not a ZFS volume: ${1}" ; fi
388  tank=`getZFSTank "$1"`
389  cdir=`getZFSRelativePath "${CDIR}"` 
390  echo "Clone Directory: ${CDIR}"
391  echo "-----------------------------------"
392  zfs list | grep -w "^${tank}${cdir}/${2}" | awk '{print $5}' | sed "s|${CDIR}/${2}-||g"
393}
394
395rmZFSSnap() {
396  isDirZFS "${1}" "1"
397  if [ $? -ne 0 ] ; then printerror "Not a ZFS volume: ${1}" ; fi
398
399  # Get the dataset of the jails mountpoint
400  rDataSet=`mount | grep "on ${1} " | awk '{print $1}'`
401  zfs destroy ${rDataSet}@$2
402}
403
404rmZFSSnapDate() {
405  isDirZFS "${1}" "1"
406  if [ $? -ne 0 ] ; then printerror "Not a ZFS volume: ${1}" ; fi
407  tank=`getZFSTank "$1"`
408  rp=`getZFSRelativePath "$1"`
409
410  snap_rm_date=`echo "$2" | sed 's/-//g'`
411
412  if [ ! `date -j "$snap_rm_date"0000 "+%Y%m%d" 2>/dev/null` ]; then
413    printerror "$2 is not a valid date."
414  fi
415
416  echo "Removing snapshots older than $2."
417  echo "-----------------------------------"
418
419  for i in `zfs list -r -H -S creation -o name -t snapshot ${tank}${rp} 2>/dev/null`
420  do
421    snap_creation_date=`zfs get -H -o value creation $i 2>/dev/null`
422                # Format output to numbered month. zfs get ouput: "Wed Oct  1 17:30 2014"
423    snap_creation_date=`echo $snap_creation_date | sed 's/ Jan / 01 /;s/ Feb / 02 /;s/ Mar / 03 /;s/ Apr / 04 /;s/ May / 05 /;s/ Jun / 06 /;s/ Jul / 07 /;s/ Aug / 08 /;s/ Sep / 09 /;s/ Oct / 10 /;s/ Nov / 11 /;s/ Dec / 12 /'`
424                # Format day output to two digit number. zfs get ouput: "Wed Oct  1 17:30 2014"
425    snap_creation_date=`echo $snap_creation_date | sed 's/ 1 / 01 /;s/ 2 / 02 /;s/ 3 / 03 /;s/ 4 / 04 /;s/ 5 / 05 /;s/ 6 / 06 /;s/ 7 / 07 /;s/ 8 / 08 /;s/ 9 / 09 /' | awk '{ print $5 $2 $3 }'`
426    if [ "$snap_creation_date" -lt "$snap_rm_date" ]; then
427      snapshot=`echo $i | cut -d '@' -f 2 | awk '{ print $1 }'`
428      zfs destroy $i
429      if [ $? -ne 0 ]; then printerror "Something went wrong with removal of $snapshot. Aborting."; fi
430      echo "Removed snapshot $snapshot"
431    fi
432  done
433
434}
435
436revertZFSSnap() {
437  isDirZFS "${1}" "1"
438  if [ $? -ne 0 ] ; then printerror "Not a ZFS volume: ${1}" ; fi
439  tank=`getZFSTank "$1"`
440  rp=`getZFSRelativePath "$1"`
441
442  # Make sure this is a valid snapshot
443  zfs list -t snapshot | grep -w "^${tank}${rp}" | cut -d '@' -f 2 | awk '{print $1}' | grep -q ${2}
444  if [ $? -ne 0 ] ; then printerror "Invalid ZFS snapshot!" ; fi
445
446  # Check if the jail is running first
447  ${PROGDIR}/scripts/backend/checkstatus.sh "${3}"
448  if [ "$?" = "0" ]; then
449    restartJail="YES"
450    # Make sure the jail is stopped
451    ${PROGDIR}/scripts/backend/stopjail.sh "${3}"
452    ${PROGDIR}/scripts/backend/checkstatus.sh "${3}"
453    if [ "$?" = "0" ]; then
454      printerror "Could not stop jail... Halting..."
455    fi
456  fi
457
458  # Rollback the snapshot
459  zfs rollback -R -f ${tank}${rp}@$2
460
461  # If it was started, restart the jail now
462  if [ "$restartJail" = "YES" ]; then
463    ${PROGDIR}/scripts/backend/startjail.sh "${3}"
464  fi
465 
466}
467
468cloneZFSDir() {
469  isDirZFS "${1}" "1"
470  if [ $? -ne 0 ] ; then printerror "Not a ZFS volume: ${1}" ; fi
471
472  # Get the dataset of the jails mountpoint
473  rDataSet=`mount | grep "on ${JDIR} " | awk '{print $1}'`
474  oSubDir=`basename $1`
475  oDataSet="${rDataSet}/${oSubDir}"
476  nSubDir=`basename $2`
477  nDataSet="${rDataSet}/${nSubDir}"
478
479  zdate=`date +%Y-%m-%d-%H-%M-%S`
480  snapName="preClone-$zdate"
481
482  # Create a temp snapshot we can clone
483  zfs snapshot ${oDataSet}@${snapName}
484  if [ $? -ne 0 ] ; then printerror "Failed creating snapshot!" ; fi
485
486  # Clone the snapshot
487  zfs clone -p ${oDataSet}@${snapName} ${nDataSet}
488  if [ $? -ne 0 ] ; then printerror "Failed cloning snapshot!" ; fi
489
490  return 0
491}
492
493set_warden_metadir()
494{
495   JMETADIR="${JDIR}/.${JAILNAME}.meta"
496   export JMETADIR
497}
498
499get_ip_and_netmask()
500{
501   JIP=`echo "${1}" | cut -f1 -d'/'`
502   JMASK=`echo "${1}" | cut -f2 -d'/' -s`
503}
504
505get_interface_addresses()
506{
507   ifconfig ${1} | grep -w inet | awk '{ print $2 }'
508}
509
510get_interface_ipv4_addresses()
511{
512   ifconfig ${1} | grep -w inet | awk '{ print $2 }'
513}
514
515get_interface_ipv6_addresses()
516{
517   ifconfig ${1} | grep -w inet6 | awk '{ print $2 }'
518}
519
520get_interface_address()
521{
522   ifconfig ${1} | grep -w inet | head -1 | awk '{ print $2 }'
523}
524
525get_interface_ipv4_address()
526{
527   ifconfig ${1} | grep -w inet | head -1 | awk '{ print $2 }'
528}
529
530get_interface_ipv6_address()
531{
532   ifconfig ${1} | grep -w inet6 | head -1 | awk '{ print $2 }'
533}
534
535get_interface_aliases()
536{
537   local _count
538
539   _count=`ifconfig ${1} | grep -w inet | wc -l`
540   _count="$(echo "${_count} - 1" | bc)"
541
542   ifconfig ${1} | grep -w inet | tail -${_count} | awk '{ print $2 }'
543}
544
545get_interface_ipv4_aliases()
546{
547   local _count
548
549   _count=`ifconfig ${1} | grep -w inet | wc -l`
550   _count="$(echo "${_count} - 1" | bc)"
551
552   ifconfig ${1} | grep -w inet | tail -${_count} | awk '{ print $2 }'
553}
554
555get_interface_ipv6_aliases()
556{
557   local _count
558
559   _count=`ifconfig ${1} | grep -w inet | wc -l`
560   _count="$(echo "${_count} - 1" | bc)"
561
562   ifconfig ${1} | grep -w inet6 | tail -${_count} | awk '{ print $2 }'
563}
564
565get_default_route()
566{
567   netstat -f inet -nr | grep '^default' | awk '{ print $2 }'
568}
569
570get_default_interface()
571{
572   local iface
573   iface=`netstat -f inet -nrW | grep '^default' | awk '{ print $7 }'`
574   if [ -z "$iface" ] ; then
575     # For 10.1 and later
576     iface=`netstat -f inet -nrW | grep '^default' | awk '{ print $6 }'`
577   fi
578   echo $iface
579}
580
581get_bridge_interfaces()
582{
583   ifconfig -a | grep -E '^bridge[0-9]+' | cut -f1 -d:
584}
585
586get_bridge_members()
587{
588   ifconfig ${1} | grep -w member | awk '{ print $2 }'
589}
590
591get_bridge_interface_by_ipv4_network()
592{
593   local network="${1}"
594   local bridges="$(get_bridge_interfaces)"
595
596   if [ -z "${network}" ]
597   then
598      return 1
599   fi
600
601   for _bridge in ${bridges}
602   do
603      local ips="$(get_interface_ipv4_aliases "${_bridge}")"
604      for _ip in ${ips}
605      do
606         if in_ipv4_network "${_ip}" "${network}"
607         then
608            echo "${_bridge}"
609            return 0
610         fi
611      done
612   done
613
614   return 1
615}
616
617get_bridge_interface_by_ipv6_network()
618{
619   local network="${1}"
620   local bridges="$(get_bridge_interfaces)"
621
622   if [ -z "${network}" ]
623   then
624      return 1
625   fi
626
627   for _bridge in ${bridges}
628   do
629      local ips="$(get_interface_ipv6_aliases "${_bridge}")"
630      for _ip in ${ips}
631      do
632         if in_ipv6_network "${_ip}" "${network}"
633         then
634            echo "${_bridge}"
635            return 0
636         fi
637      done
638   done
639
640   return 1
641}
642
643is_bridge_member()
644{
645   local _bridge="${1}"
646   local _iface="${2}"
647
648   for _member in `get_bridge_members ${_bridge}`
649   do
650      if [ "${_member}" = "${_iface}" ] ; then
651         return 0
652      fi
653   done
654
655   return 1
656}
657
658jail_interfaces_down()
659{
660   local _jid="${1}"
661   local _bridgeif
662   local _epaira
663   local _epairb
664
665   _epairb=`jexec ${_jid} ifconfig -a | grep '^epair' | cut -f1 -d:`
666   if [ -n "${_epairb}" ] ; then
667      _epaira=`echo ${_epairb} | sed -E 's|b$|a|'`
668      _bridgeif=
669
670      for _bridge in `ifconfig -a | grep -E '^bridge[0-9]+' | cut -f1 -d:`
671      do
672         for _member in `ifconfig ${_bridge} | grep member | awk '{ print $2 }'`
673         do
674            if [ "${_member}" = "${_epaira}" ] ; then
675               _bridgeif="${_bridge}"
676                break
677            fi
678         done
679         if [ -n "${_bridgeif}" ] ; then
680            break
681         fi
682      done
683
684      jexec ${_jid} ifconfig ${_epairb} down
685      ifconfig ${_epaira} down
686      ifconfig ${_epaira} destroy
687      _count=`ifconfig ${_bridgeif} | grep member | awk '{ print $2 }' | wc -l`
688      if [ "${_count}" -lt "1" ] ; then
689         ifconfig ${_bridgeif} destroy
690      fi
691   fi
692}
693
694enable_cron()
695{
696   cronscript="${PROGDIR}/scripts/backend/cronsnap.sh"
697   grep -q "${cronscript}" /etc/crontab
698   if [ $? -eq 0 ] ; then return 0 ; fi
699   echo "2     *        *       *       *        root    ${cronscript}" >> /etc/crontab
700   # Restart cron
701   /etc/rc.d/cron restart >/dev/null 2>/dev/null
702}
703
704fix_old_meta()
705{
706   for i in `ls -d ${JDIR}/.*.meta 2>/dev/null`
707   do
708      if [ -e "${i}/xjail" ] ; then
709         touch ${i}/jail-portjail 2>/dev/null
710      fi
711      if [ -e "${i}/linuxjail" ] ; then
712         touch ${i}/jail-linux 2>/dev/null
713      fi
714   done
715}
716
717is_ipv4()
718{
719   local addr="${1}"
720   local res=1
721
722   local ipv4="$(/usr/local/bin/sipcalc "${addr}"|head -1|cut -f2 -d'['|awk '{ print $1 }')"
723   if [ "${ipv4}" = "ipv4" ]
724   then
725      res=0
726   fi
727
728   return ${res}
729}
730
731is_ipv6()
732{
733   local addr="${1}"
734   local res=1
735
736   local ipv6="$(/usr/local/bin/sipcalc "${addr}"|head -1|cut -f2 -d'['|awk '{ print $1 }')"
737   if [ "${ipv6}" = "ipv6" ]
738   then
739      res=0
740   fi
741
742   return ${res}
743}
744
745in_ipv4_network()
746{
747   local addr="${1}"
748   local network="${2}"
749   local res=1
750
751   local start="$(/usr/local/bin/sipcalc "${network}"|awk '/^Usable/ { print $4 }')"
752   local end="$(/usr/local/bin/sipcalc "${network}"|awk '/^Usable/ { print $6 }')"
753
754   local iaddr="$(/usr/local/bin/sipcalc "${addr}"|awk '/(decimal)/ { print $5 }')"
755   local istart="$(/usr/local/bin/sipcalc "${start}"|awk '/(decimal)/ { print $5 }')"
756   local iend="$(/usr/local/bin/sipcalc "${end}"|awk '/(decimal)/ { print $5 }')"
757
758   if [ "${iaddr}" -ge "${istart}" -a "${iaddr}" -le "${iend}" ]
759   then
760      res=0
761   fi
762
763   return ${res}
764}
765
766ipv6_to_binary()
767{
768   echo ${1}|awk '{
769      split($1, octets, ":");
770      olen = length(octets);
771               
772      bnum = "";
773      for (i = 1;i <= olen;i++) {
774         tbnum = "";
775         dnum = int(sprintf("0x%s", octets[i]));
776         for (;;) {
777            rem = int(dnum % 2);
778            if (rem == 0)
779               tbnum = sprintf("0%s", tbnum);
780            else               
781               tbnum = sprintf("1%s", tbnum);
782            dnum /= 2;
783            if (dnum < 1)
784               break;
785         }
786         bnum = sprintf("%s%016s", bnum, tbnum);
787      }
788      printf("%s", bnum);
789   }'
790}
791
792in_ipv6_network()
793{
794   local addr="${1}"
795   local network="${2}"
796   local mask="$(echo "${network}"|cut -f2 -d'/' -s)"
797   local res=1
798
799   local addr="$(/usr/local/bin/sipcalc "${addr}"|awk \
800      '/^Expanded/ { print $4}')"
801   local start="$(/usr/local/bin/sipcalc "${network}"|egrep \
802      '^Network range'|awk '{ print $4 }')"
803
804   local baddr="$(ipv6_to_binary "${addr}")"
805   local bstart="$(ipv6_to_binary "${start}")"
806
807   local baddrnet="$(echo "${baddr}"|awk -v mask="${mask}" \
808      '{ s = substr($0, 1, mask); printf("%s", s); }')"
809   local bstartnet="$(echo "${bstart}"|awk -v mask="${mask}" \
810      '{ s = substr($0, 1, mask); printf("%s", s); }')"
811
812   if [ "${baddrnet}" = "${bstartnet}" ]
813   then
814      res=0
815   fi
816
817   return ${res}
818}
819
820make_bootstrap_pkgng_file_standard()
821{
822  local jaildir="${1}"
823  local outfile="${2}"
824
825  if [ ! -e "${jaildir}/bin/freebsd-version" ] ; then
826     echo "Missing /bin/freebsd-version in jail.."
827     echo "PKG bootstrap can only be done on 10.0 and higher, skipping..."
828     return 1
829  fi
830
831  # Setup the repo to use the XX.0-RELEASE pkgng branch
832  local release="`${jaildir}/bin/freebsd-version | cut -d '-' -f 1 |  cut -d '.' -f 1`.0-RELEASE"
833  local arch="$(uname -m)"
834
835cat<<__EOF__>"${outfile}"
836#!/bin/sh
837tar xvf pkg.txz --exclude +MANIFEST --exclude +MTREE_DIRS 2>/dev/null
838pkg add pkg.txz
839rm pkg.txz
840
841# Create the pkg.conf file
842echo "PKG_CACHEDIR: /usr/local/tmp
843REPOS_DIR: [
844                \"/usr/local/etc/pkg/repos\"
845           ]" > /usr/local/etc/pkg.conf
846
847# Create the repo dirs
848mkdir -p /usr/local/etc/pkg/repos 2>/dev/null
849mkdir -p /usr/local/etc/pkg/fingerprints/pcbsd/trusted 2>/dev/null
850mkdir -p /usr/local/etc/pkg/fingerprints/pcbsd/revoked 2>/dev/null
851
852# Save the repo configuration file
853echo "pcbsd-major: {
854               url: \"http://pkg.cdn.pcbsd.org/${release}/${arch}\",
855               signature_type: \"fingerprints\",
856               fingerprints: \"/usr/local/etc/pkg/fingerprints/pcbsd\",
857               enabled: true
858              }" > /usr/local/etc/pkg/repos/pcbsd.conf
859
860# Create the repo.dist file
861echo "pcbsd: {
862               url: \"http://pkg.cdn.pcbsd.org/VERSION/ARCH\",
863               signature_type: \"fingerprints\",
864               fingerprints: \"/usr/local/etc/pkg/fingerprints/pcbsd\",
865               enabled: true
866              }" > /usr/local/etc/pkg/repos/pcbsd.conf.dist
867
868# Save the fingerprint file
869echo "function: sha256
870fingerprint: b2b9e037f938cf20ba68aa85ac88c15889c729a7f6b70c25069774308e760a03" > /usr/local/etc/pkg/fingerprints/pcbsd/trusted/pkg.cdn.pcbsd.org.20131209
871
872pkg update -f
873
874exit 0
875__EOF__
876
877}
878
879make_bootstrap_pkgng_file_pluginjail()
880{
881
882  local jaildir="${1}"
883  local outfile="${2}"
884
885  if [ ! -e "${jaildir}/bin/freebsd-version" ] ; then
886     echo "Missing /bin/freebsd-version in jail.."
887     echo "PKG bootstrap can only be done on 10.0 and higher, skipping..."
888     return 0
889  fi
890
891  # Setup the repo to use the XX.0-RELEASE pkgng branch
892  local release="`${jaildir}/bin/freebsd-version | cut -d '-' -f 1 |  cut -d '.' -f 1`.0-RELEASE"
893  local arch="$(uname -m)"
894
895  get_mirror
896  local mirror="${VAL}"
897
898  cp /usr/local/share/warden/pluginjail-packages "${jaildir}/pluginjail-packages"
899
900cat<<__EOF__>"${outfile}"
901#!/bin/sh
902tar xvf pkg.txz --exclude +MANIFEST --exclude +MTREE_DIRS 2>/dev/null
903pkg add pkg.txz
904rm pkg.txz
905
906mount -t devfs devfs /dev
907
908# Create the pkg.conf file
909echo "PKG_CACHEDIR: /usr/local/tmp
910REPOS_DIR: [
911                \"/usr/local/etc/pkg/repos\"
912           ]" > /usr/local/etc/pkg.conf
913
914# Create the repo dirs
915mkdir -p /usr/local/etc/pkg/repos 2>/dev/null
916mkdir -p /usr/local/etc/pkg/fingerprints/pcbsd/trusted 2>/dev/null
917mkdir -p /usr/local/etc/pkg/fingerprints/pcbsd/revoked 2>/dev/null
918
919# Save the repo configuration file
920echo "pcbsd-major: {
921               url: \"http://pkg.cdn.pcbsd.org/${release}/${arch}\",
922               signature_type: \"fingerprints\",
923               fingerprints: \"/usr/local/etc/pkg/fingerprints/pcbsd\",
924               enabled: true
925              }" > /usr/local/etc/pkg/repos/pcbsd.conf
926
927# Create the repo.dist file
928echo "pcbsd: {
929               url: \"http://pkg.cdn.pcbsd.org/VERSION/ARCH\",
930               signature_type: \"fingerprints\",
931               fingerprints: \"/usr/local/etc/pkg/fingerprints/pcbsd\",
932               enabled: true
933              }" > /usr/local/etc/pkg/repos/pcbsd.conf.dist
934
935# Save the fingerprint file
936echo "function: sha256
937fingerprint: b2b9e037f938cf20ba68aa85ac88c15889c729a7f6b70c25069774308e760a03" > /usr/local/etc/pkg/fingerprints/pcbsd/trusted/pkg.cdn.pcbsd.org.20131209
938
939pkg update -f
940
941__EOF__
942
943echo '
944i=0
945count=`wc -l /pluginjail-packages| awk "{ print $1 }"`
946for p in `cat /pluginjail-packages`
947do
948  pkg install -y ${p}
949  : $(( i += 1 ))
950done
951
952umount devfs
953exit $?
954' >> "${outfile}"
955}
956
957
958bootstrap_pkgng()
959{
960  local jaildir="${1}"
961  local jailtype="${2}"
962  if [ -z "${jailtype}" ] ; then
963    jailtype="standard"
964  fi
965
966  if [ ! -e "${jaildir}/bin/freebsd-version" ] ; then
967     echo "Missing /bin/freebsd-version in jail.."
968     echo "PKG bootstrap can only be done on 10.0 and higher, skipping..."
969     return 1
970  fi
971
972  local release="`${jaildir}/bin/freebsd-version | cut -d '-' -f 1 |  cut -d '.' -f 1`.0-RELEASE"
973  local arch="$(uname -m)"
974
975  local ffunc="make_bootstrap_pkgng_file_standard"
976  if [ "${jailtype}" = "pluginjail" ] ; then
977    ffunc="make_bootstrap_pkgng_file_pluginjail"
978  fi
979
980  cd ${jaildir} 
981  echo "Boot-strapping pkgng"
982
983  mkdir -p ${jaildir}/usr/local/etc
984
985
986  ${ffunc} "${jaildir}" "${jaildir}/bootstrap-pkgng"
987  chmod 755 "${jaildir}/bootstrap-pkgng"
988
989  if [ -e "pkg.txz" ] ; then rm pkg.txz ; fi
990  get_file_from_mirrors "/${release}/${arch}/Latest/pkg.txz" "pkg.txz" "pkg"
991  if [ $? -eq 0 ] ; then
992    chroot ${jaildir} /bootstrap-pkgng
993    if [ $? -eq 0 ] ; then
994      rm -f "${jaildir}/bootstrap-pkgng"
995      rm -f "${jaildir}/pluginjail-packages"
996      return 0
997    fi
998  fi
999
1000  echo "Failed boot-strapping PKGNG, most likely cause is internet connection failure."
1001  rm -f "${jaildir}/bootstrap-pkgng"
1002  rm -f "${jaildir}/pluginjail-packages"
1003  return 1
1004}
1005
1006ipv4_configured()
1007{
1008   local iface="${1}"
1009   local jid="${2}"
1010   local jexec=
1011
1012   if [ -n "${jid}" ] ; then
1013      jexec="jexec ${jid}"
1014   fi
1015
1016   ${jexec} ifconfig "${iface}" | grep -qw inet 2>/dev/null
1017   return $?
1018}
1019
1020ipv4_address_configured()
1021{
1022   local iface="${1}"
1023   local addr="${2}"
1024   local jid="${3}"
1025   local jexec= 
1026
1027   addr="$(echo ${addr}|cut -f1 -d'/')"
1028
1029   if [ -n "${jid}" ] ; then
1030      jexec="jexec ${jid}"
1031   fi
1032
1033   ${jexec} ifconfig "${iface}" | \
1034      grep -w inet | \
1035      awk '{ print $2 }' | \
1036      grep -Ew "^${addr}" >/dev/null 2>&1
1037   return $?
1038}
1039
1040ipv6_configured()
1041{
1042   local iface="${1}"
1043   local jid="${2}"
1044   local jexec=
1045
1046   if [ -n "${jid}" ] ; then
1047      jexec="jexec ${jid}"
1048   fi
1049
1050   ${jexec} ifconfig "${iface}" | grep -qw inet6 2>/dev/null
1051   return $?
1052}
1053
1054ipv6_address_configured()
1055{
1056   local iface="${1}"
1057   local addr="${2}"
1058   local jid="${3}"
1059   local jexec= 
1060
1061   addr="$(echo ${addr}|cut -f1 -d'/')"
1062
1063   if [ -n "${jid}" ] ; then
1064      jexec="jexec ${jid}"
1065   fi
1066
1067   ${jexec} ifconfig "${iface}" | \
1068      grep -w inet6 | \
1069      awk '{ print $2 }' | \
1070      grep -Ew "^${addr}" >/dev/null 2>&1
1071   return $?
1072}
1073
1074get_ipfw_nat_instance()
1075{
1076   local iface="${1}"
1077   local res=1
1078
1079   if [ -z "${iface}" ] ; then
1080      local instance="`ipfw list|egrep '[0-9]+ nat'|awk '{ print $3 }'|tail -1`"
1081      if [ -z "${instance}" ] ; then
1082         instance="100"
1083      else               
1084         : $(( instance += 100 )) 
1085      fi
1086      echo "${instance}"
1087      return 0
1088   fi
1089
1090   for ni in `ipfw list|egrep '[0-9]+ nat'|awk '{ print $3 }'`
1091   do
1092      ipfw nat "${ni}" show config|egrep -qw "${iface}"
1093      if [ "$?" = "0" ] ; then
1094         echo "${ni}"
1095         res=0
1096         break
1097      fi
1098   done
1099
1100   return ${res}
1101}
1102
1103get_ipfw_nat_priority()
1104{
1105   local iface="${1}"
1106   local res=1
1107
1108   if [ -z "${iface}" ] ; then
1109      local priority="`ipfw list|egrep '[0-9]+ nat'|awk '{ print $1 }'|tail -1`"
1110      if [ -z "${priority}" ] ; then
1111         priority=2000
1112      fi
1113      printf "%05d\n" "${priority}"
1114      return 0
1115   fi
1116
1117   local IFS='
1118'
1119   for rule in `ipfw list|egrep '[0-9]+ nat'`
1120   do
1121      local priority="`echo "${rule}"|awk '{ print $1 }'`"
1122      local ni="`echo "${rule}"|awk '{ print $3 }'`"
1123
1124      ipfw nat "${ni}" show config|egrep -qw "${iface}"
1125      if [ "$?" = "0" ] ; then
1126         echo "${priority}"
1127         res=0
1128         break
1129      fi
1130   done
1131
1132   return ${res}
1133}
1134
1135list_templates()
1136{
1137   echo "Jail Templates:"
1138   echo "------------------------------" 
1139   for i in `ls -d ${JDIR}/.warden-template* 2>/dev/null`
1140   do
1141     if [ ! -e "$i/bin/sh" ] ; then continue ; fi
1142     NICK=`echo "$i" | sed "s|${JDIR}/.warden-template-||g"`
1143     file "$i/bin/sh" 2>/dev/null | grep -q "64-bit"
1144     if [ $? -eq 0 ] ; then
1145        ARCH="amd64"
1146     else
1147        ARCH="i386"
1148     fi
1149     VER=`file "$i/bin/sh" | cut -d ',' -f 5 | awk '{print $3}'`
1150     if [ -e "$i/etc/rc.conf.pcbsd" ] ; then
1151        TYPE="TrueOS"
1152     else
1153        TYPE="FreeBSD"
1154     fi
1155     echo -e "${NICK} - $TYPE $VER ($ARCH)"
1156  done
1157  exit 0
1158}
1159
1160delete_template()
1161{
1162   tDir="${JDIR}/.warden-template-${1}"
1163   isDirZFS "${tDir}" "1"
1164   if [ $? -ne 0 ] ; then printerror "Not a ZFS volume: ${tDir}" ; fi
1165
1166   # Get the dataset of the jails mountpoint
1167   rDataSet=`mount | grep "on ${tDir} " | awk '{print $1}'`
1168
1169   zfs destroy -r ${rDataSet}
1170   if [ $? -ne 0 ] ; then
1171     exit_err "Could not remove template, perhaps you have jails still using it?"
1172   fi
1173   rmdir ${tDir}
1174   echo "DONE"
1175
1176   exit 0
1177}
1178
1179get_ip_host_flags()
1180{
1181         IP4="OFF"
1182         IP6="OFF"
1183         HOST="OFF"
1184         for i in "$@"
1185         do
1186           # Check if we have a new IPv4 address for this import
1187           echo "${i}" | grep '\-\-ipv4=' >/dev/null 2>/dev/null
1188           if [ "$?" = "0" ]; then
1189              tmp="`echo ${i} | cut -d '=' -f 2`"
1190              IP4="`echo ${tmp} | cut -d '/' -f 1 -s`"
1191              MASK4="`echo ${tmp} | cut -d '/' -f 2 -s`"
1192
1193              #Sanity check on the IP
1194              if ! is_ipv4 "${IP4}" ; then
1195                 exit_err "Invalid IPv4 address: $IP4"
1196              fi
1197
1198              for i in `ls -d ${JDIR}/.*.meta 2>/dev/null`
1199              do
1200                if [ "`cat ${i}/ipv4 2>/dev/null`" = "${IP4}/${MASK4}" ] ; then
1201                  exit_err "A jail with this IPv4 address already exists!"
1202                fi
1203              done
1204           fi
1205
1206           # Check if we have a new IPv6 address for this import
1207           echo "${i}" | grep '\-\-ipv6=' >/dev/null 2>/dev/null
1208           if [ "$?" = "0" ]; then
1209              tmp="`echo ${i} | cut -d '=' -f 2`"
1210              IP6="`echo ${tmp} | cut -d '/' -f 1 -s`"
1211              MASK6="`echo ${tmp} | cut -d '/' -f 2 -s`"
1212
1213              #Sanity check on the IP
1214              if ! is_ipv6 "${IP6}" ; then
1215                 exit_err "Invalid IPv6 address!"
1216              fi
1217
1218              for i in `ls -d ${JDIR}/.*.meta 2>/dev/null`
1219              do
1220                _ipv6=`cat ${i}/ipv6 2>/dev/null | tr a-z A-Z`
1221                _nipv6="`echo ${IP6}|tr a-z A-Z`/${MASK6}"
1222
1223                if [ "${_ipv6}" = "${_nipv6}" ] ; then
1224                  exit_err "A jail with this IPv6 address already exists!"
1225                fi
1226              done
1227           fi
1228
1229           # Check if we have a new hostname for this jail
1230           echo ${i} | grep '\-\-host=' >/dev/null 2>/dev/null
1231           if [ "$?" = "0" ]; then
1232              HOST="`echo ${i} | cut -d '=' -f 2`"
1233           fi
1234
1235         done
1236
1237}
1238
1239zfs_prog_check() {
1240
1241   local testDataSet=`mount | grep "on ${JDIR} " | awk '{print $1}'`
1242   if [ -z "$testDataSet" ] ; then
1243      echo "WARNING: JDIR is NOT set to a ZFS managed dataset.."
1244      echo "Please change JDIR in /usr/local/etc/warden.conf to a valid, mounted ZFS dataset!"
1245      exit 1
1246   fi
1247
1248}
1249
1250stop_jail_savestate()
1251{
1252  # Check if the jail is running first
1253  ${PROGDIR}/scripts/backend/checkstatus.sh "${JAILNAME}"
1254  if [ "$?" = "0" ]; then
1255    stateRestartJail="YES"
1256    # Make sure the jail is stopped
1257    ${PROGDIR}/scripts/backend/stopjail.sh "${JAILNAME}"
1258    ${PROGDIR}/scripts/backend/checkstatus.sh "${JAILNAME}"
1259    if [ "$?" = "0" ]; then
1260       exit_err "Failed to stop jail: $JAILNAME..."
1261    fi
1262  fi
1263}
1264
1265start_jail_savedstate()
1266{
1267  if [ "$stateRestartJail" = "YES" ] ; then
1268    ${PROGDIR}/scripts/backend/startjail.sh "${JAILNAME}"
1269  fi
1270}
1271
1272##############################################################
1273# Functions for upgrading jails
1274##############################################################
1275
1276echo_logout()
1277{
1278  echo "$@"
1279  echo "$@" >> ${LOGOUT}
1280}
1281
1282set_update_vars()
1283{
1284  unset EVENT_PIPE
1285
1286  # Set some locations
1287  STAGEMNT="$JAILDIR"
1288  LOGOUT="/var/log/warden-update.log"
1289  OLDPKGLIST="/tmp/.pkgUpdateList.$$"
1290  NEWPKGLIST="/tmp/.newPkgUpdateList.$$"
1291  PKGUPGRADELOG="/tmp/.pkgUpdateLog.$$"
1292  PKGDLCACHE="/usr/local/pkg-cache"
1293  PKG_CMD="chroot ${JAILDIR} /usr/sbin/pkg"
1294  echo "" > $LOGOUT
1295
1296  # Some basic sanity tests
1297  if [ ! -d "$JAILDIR" -o "$JAILDIR" = "/" ] ; then
1298     exit_err "Invalid JAILDIR"
1299  fi
1300  chroot ${STAGEMNT} freebsd-version 2>/dev/null >/dev/null
1301  if [ $? -ne 0 ] ; then
1302     exit_err "Needs FreeBSD > 10 to do updates"
1303  fi
1304}
1305
1306update_freebsd()
1307{
1308
1309  set_update_vars
1310
1311  stop_jail_savestate
1312
1313  mk_snapshot "FreeBSD update snapshot"
1314
1315  run_freebsd_update_script
1316
1317  start_jail_savedstate
1318  echo_logout "Your security update is finished!"
1319  exit 0
1320}
1321
1322
1323update_pkgs_only()
1324{
1325  set_update_vars
1326
1327  mk_pkg_conf
1328  build_pkg_list
1329  dl_pkgs
1330
1331  stop_jail_savestate
1332
1333  mk_snapshot "Pkg update snapshot"
1334  prep_pkgs_chroot
1335  install_pkgs_chroot
1336
1337  start_jail_savedstate
1338
1339  echo_logout "Your package update is finished!"
1340  exit 0
1341}
1342
1343update_world_and_pkgs()
1344{
1345  # Set the new version of FreeBSD we are installing
1346  NEWFREEBSDVERSION="$1"
1347
1348  set_update_vars
1349
1350  mk_pkg_conf
1351  build_pkg_list
1352  dl_pkgs
1353
1354  stop_jail_savestate
1355
1356  mk_snapshot "FreeBSD upgrade snapshot"
1357  run_freebsd_upgrade_script
1358  prep_pkgs_chroot
1359  install_pkgs_chroot
1360
1361  start_jail_savedstate
1362  echo_logout "Your FreeBSD upgrade is finished!"
1363  exit 0
1364}
1365
1366mk_pkg_conf()
1367{
1368   PKG_FLAG=""
1369   PKG_CFLAG=""
1370
1371   if [ ! -d "${JAILDIR}/${PKGDLCACHE}" ] ; then
1372     mkdir -p ${JAILDIR}/${PKGDLCACHE}
1373   fi
1374
1375   # Get rid of FreeBSD.conf repo
1376   if [ -e "${JAILDIR}/etc/pkg/FreeBSD.conf" ] ; then
1377      rm ${JAILDIR}/etc/pkg/FreeBSD.conf
1378   fi
1379
1380   # Set the cache directory
1381   PKG_CFLAG="-C /tmp/.pkgUpdate.conf"
1382   echo "PKG_CACHEDIR: $PKGDLCACHE" > ${JAILDIR}/tmp/.pkgUpdate.conf
1383
1384   # If doing a major update also, add the new repos config
1385   if [ -n "$NEWFREEBSDVERSION" ] ; then
1386      setup_pkgng_newrepo_conf
1387   fi
1388}
1389
1390setup_pkgng_newrepo_conf() {
1391
1392  # Lets create a new repo file to match the version of BSD we are upgrading to
1393
1394  # Set the new ABI
1395  ABIVER="`echo $NEWFREEBSDVERSION | cut -d '-' -f 1 | cut -d '.' -f 1`"
1396  pV="`${PKG_CMD} ${PKG_FLAG} query '%v' ports-mgmt/pkg`"
1397  echo $pV | grep -q '^1.3'
1398  if [ $? -eq 0 ] ; then
1399    PKG_FLAG="$PKG_FLAG -o ABI=freebsd:$ABIVER:x86:64"
1400  else
1401    PKG_FLAG="$PKG_FLAG -o ABI=freebsd:$ABIVER:`uname -m`"
1402  fi
1403  #echo "Setting ABI with: ${PKG_FLAG}"
1404
1405  # See if we need to adjust pcbsd.conf repo file
1406  if [ ! -e "/usr/local/etc/pkg/repos/pcbsd.conf.dist" ];then
1407     echo_logout "ERROR: Missing /usr/local/etc/pkg/repos/pcbsd.conf.dist"
1408     exit 1
1409  fi
1410
1411  ARCH=`uname -m`
1412  FBSDVER="$NEWFREEBSDVERSION"
1413  MAJORVER="`echo $FBSDVER | cut -d '-' -f 1 |  cut -d '.' -f 1`.0-RELEASE"
1414
1415  # Make sure we are on a -RELEASE or -STABLE, otherwise use the proper uname
1416  echo $FBSDVER | grep -q -e 'RELEASE' -e 'STABLE'
1417  if [ $? -ne 0 ] ; then MAJORVER="$FBSDVER"; fi
1418
1419  # If using the EDGE package set, set the right path
1420  case $PACKAGE_SET in
1421       EDGE) FBSDVER="$FBSDVER/edge"
1422             MAJORVER="$MAJORVER/edge"
1423             ;;
1424          *) ;;
1425  esac
1426
1427  rm -rf ${JAILDIR}/tmp/.updateRepo >/dev/null 2>/dev/null
1428  mkdir ${JAILDIR}/tmp/.updateRepo
1429
1430  # Now create standard pcbsd.conf file
1431  if [ "$PACKAGE_SET" = "CUSTOM" -a -n "$CUSTOM_URL" ] ; then
1432     # Change %VERSION% / %ARCH% keys
1433     CUSTOM_URL=`echo $CUSTOM_URL | sed "s|%VERSION%|$MAJORVER|g" | sed "s|%ARCH%|$ARCH|g"`
1434     cat << EOF >${JAILDIR}/tmp/.updateRepo/pkgUpdateRepo.conf
1435pcbsd-major: {
1436               url: "$CUSTOM_URL",
1437               signature_type: "fingerprints",
1438               fingerprints: "/usr/local/etc/pkg/fingerprints/pcbsd",
1439               enabled: true
1440              }
1441EOF
1442  else
1443    # Using PC-BSD CDN
1444    cat /usr/local/etc/pkg/repos/pcbsd.conf.dist \
1445      | sed "s|pcbsd: |pcbsd-major: |g" \
1446      | sed "s|%VERSION%|$MAJORVER|g" \
1447      | sed "s|%ARCH%|$ARCH|g" \
1448      | sed "s|VERSION|$MAJORVER|g" \
1449      | sed "s|ARCH|$ARCH|g" > ${JAILDIR}/tmp/.updateRepo/pkgUpdateRepo.conf
1450  fi
1451
1452  # Set the new PKG_FLAG to use this repo config
1453  PKG_FLAG="-R /tmp/.updateRepo ${PKG_FLAG}"
1454
1455}
1456
1457build_pkg_list()
1458{
1459  # Build top-level list of pkgs installed
1460  echo_logout "Getting list of packages..."
1461  ${PKG_CMD} query -e '%#r=0' '%o %n-%v' | sort | grep -v 'ports-mgmt/pkg ' > $OLDPKGLIST
1462
1463  echo "Original top-level packages:" > $PKGUPGRADELOG
1464  echo "-----------------------------------------------" >> $PKGUPGRADELOG
1465  cat $OLDPKGLIST >> $PKGUPGRADELOG
1466  echo "-----------------------------------------------" >> $PKGUPGRADELOG
1467}
1468
1469dl_pkgs()
1470{
1471  # Update the DB first
1472  echo_logout "Updating the package repo database..."
1473  ${PKG_CMD} ${PKG_FLAG} update -f >${LOGOUT} 2>${LOGOUT}
1474
1475  # Clean pkgs
1476  echo_logout "Cleaning old pkg upgrade cache..."
1477  ${PKG_CMD} ${PKG_CFLAG} ${PKG_FLAG} clean -y >${LOGOUT} 2>${LOGOUT}
1478
1479  if [ -e "$NEWPKGLIST" ] ; then rm $NEWPKGLIST; fi
1480
1481  # Save the PKGNG filename
1482  PKGFILENAME="`${PKG_CMD} ${PKG_FLAG} rquery -U '%n-%v' ports-mgmt/pkg 2>/dev/null | head -n 1`.txz"
1483
1484  # First off, fetch the pkgng pkg
1485  echo_logout "Fetching packages for ports-mgmt/pkg - $PKGFILENAME"
1486  ${PKG_CMD} ${PKG_CFLAG} ${PKG_FLAG} fetch -U -d -y ports-mgmt/pkg >/tmp/.pkgOut.$$ 2>/tmp/.pkgOut.$$
1487  if [ $? -ne 0 ] ; then
1488     cat /tmp/.pkgOut.$$
1489     cat /tmp/.pkgOut.$$ >> $LOGOUT
1490     cat /tmp/.pkgOut.$$ >> $PKGUPGRADELOG
1491     exit_err "Failed fetching: ports-mgmt/pkg - $PKGFILENAME"
1492  fi
1493
1494  CHROOTREALPKGDLCACHE="${PKGDLCACHE}"
1495  REALPKGDLCACHE="${JAILDIR}/${PKGDLCACHE}"
1496  # PKGNG lies, we need to verify if the package was really downloaded
1497  if [ ! -e "${JAILDIR}/${PKGDLCACHE}/${PKGFILENAME}" ] ; then
1498     # Also check All/ since pkg docs are rather unclear about if that will be used or not
1499     if [ -e "${JAILDIR}/${PKGDLCACHE}/All/${PKGFILENAME}" ] ; then
1500        CHROOTREALPKGDLCACHE="${PKGDLCACHE}/All"
1501        REALPKGDLCACHE="${JAILDIR}/${PKGDLCACHE}/All"
1502     else
1503        exit_err "Failed downloading ports-mgmt/pkg with: $PKG_CMD $PKG_FLAG fetch -d -y ports-mgmt/pkg"
1504     fi
1505  fi
1506
1507  # Create the NEWPKGLIST
1508  touch $NEWPKGLIST
1509
1510  # Now start fetching all the update packages
1511  while read pkgLine
1512  do
1513    pkgOrigin="`echo $pkgLine | cut -d ' ' -f 1`"
1514    pkgName="`echo $pkgLine | cut -d ' ' -f 2`"
1515
1516    # Check if this pkg exists in the new repo
1517    unset FETCHFILENAME
1518    FETCHFILENAME="`${PKG_CMD} ${PKG_FLAG} rquery -U '%n-%v' $pkgOrigin 2>/dev/null | head -n 1`"
1519    if [ -z "$FETCHFILENAME" ] ; then
1520       echo_logout "*****"
1521       echo_logout "No such package in new repo: $pkgOrigin"
1522       echo_logout "*****" >> $LOGOUT
1523       echo "*****" >> $PKGUPGRADELOG
1524       echo "No such package in new repo: $pkgOrigin" >> $PKGUPGRADELOG
1525       echo "*****" >> $PKGUPGRADELOG
1526       continue
1527    fi
1528    FETCHFILENAME="${FETCHFILENAME}.txz"
1529
1530    # Fetch the pkg now
1531    echo_logout "Fetching packages for ${pkgOrigin} - $FETCHFILENAME"
1532    echo "Fetching packages for ${pkgOrigin} - $FETCHFILENAME" >> ${PKGUPGRADELOG}
1533    ${PKG_CMD} ${PKG_CFLAG} ${PKG_FLAG} fetch -U -d -y $pkgOrigin >/tmp/.pkgOut.$$ 2>/tmp/.pkgOut.$$
1534    if [ $? -ne 0 ] ; then
1535       echo "*****" >> $PKGUPGRADELOG
1536       echo_logout "Failed fetching: $pkgOrigin"
1537       cat /tmp/.pkgOut.$$
1538       cat /tmp/.pkgOut.$$ >> $LOGOUT
1539       echo_logout "*****"
1540
1541       echo "*****" >> $PKGUPGRADELOG
1542       echo "Failed fetching: $pkgOrigin" >> $PKGUPGRADELOG
1543       cat /tmp/.pkgOut.$$ >> $PKGUPGRADELOG
1544       echo "*****" >> $PKGUPGRADELOG
1545    fi
1546
1547    # PKGNG lies, we need to verify if the package was really downloaded
1548    if [ ! -e "${REALPKGDLCACHE}/${FETCHFILENAME}" ] ; then
1549       echo_logout "*****"
1550       echo_logout "Failed fetching: $pkgOrigin - $FETCHFILENAME"
1551       cat /tmp/.pkgOut.$$
1552       cat /tmp/.pkgOut.$$ >> $LOGOUT
1553       echo_logout "*****"
1554
1555       echo "*****" >> $PKGUPGRADELOG
1556       echo "Failed fetching: $pkgOrigin - $FETCHFILENAME" >> $PKGUPGRADELOG
1557       cat /tmp/.pkgOut.$$ >> $PKGUPGRADELOG
1558       echo "*****" >> $PKGUPGRADELOG
1559       echo "Failed downloading $pkgOrigin with: $PKG_CMD $PKG_FLAG fetch -d -y $pkgOrigin"
1560    fi
1561    echo "$pkgOrigin $FETCHFILENAME" >> $NEWPKGLIST
1562  done < $OLDPKGLIST
1563
1564  # Copy the list of packages to install
1565  rc_halt "cp $NEWPKGLIST ${JAILDIR}/install-pkg-list"
1566
1567  echo_logout "-----------------------------------------------"
1568  echo "-----------------------------------------------" >> ${PKGUPGRADELOG}
1569}
1570
1571do_prune_auto_snaps()
1572{
1573  # Get list of snaps
1574  snaps=$(listZFSSnap "${JAILDIR}")
1575
1576  # Reverse the list
1577  for tmp in $snaps
1578  do
1579     rSnaps="$tmp $rSnaps"
1580  done
1581
1582  # Do any pruning
1583  num=0
1584  keep=2
1585  for snap in $rSnaps
1586  do
1587     echo "$snap" | grep -q "beforeUp-"
1588     if [ $? -ne 0 ] ; then continue; fi
1589
1590     if [ $num -ge $keep ] ; then
1591        echo "Pruning old upgrade snapshot: $snap"
1592        rmZFSSnap "${JAILDIR}" "$snap"
1593     fi
1594     num=`expr $num + 1`
1595  done
1596}
1597
1598mk_snapshot()
1599{
1600  echo_logout "Creating snapshot of $JAILNAME..."
1601
1602  # Auto-prune any old / stale BEs
1603  do_prune_auto_snaps
1604
1605  revertSnap="beforeUp-`date +%Y%m%d_%H%M%S`"
1606  ${PROGDIR}/scripts/backend/zfsmksnap.sh ${JAILNAME} "${1}" $revertSnap
1607  if [ $? -ne 0 ] ; then
1608     exit_err "Failed creating automatic snapshot!"
1609  fi
1610}
1611
1612exit_revertsnap()
1613{
1614  # We had an error and need to exit, but first revert the snapshot
1615  echo_logout "Reverting to snapshot: $revertSnap"
1616  ${PROGDIR}/scripts/backend/zfsrevertsnap.sh ${JAILNAME} $revertSnap
1617  if [ $? -ne 0 ] ; then
1618     echo_logout "Failed reverting automatic snapshot!"
1619  fi
1620  umount -f ${JAILDIR}/dev >/dev/null 2>/dev/null
1621  exit_err "$@"
1622}
1623
1624prep_pkgs_chroot()
1625{
1626  # Make sure jail log dir exists
1627  if [ ! -d "${JAILDIR}/var/log/warden" ] ; then
1628     mkdir -p ${JAILDIR}/var/log/warden
1629  fi
1630
1631  # First, clean the jail environment
1632  echo_logout "Cleaning the jail environment... (This may take a while)"
1633  chroot ${STAGEMNT} /usr/sbin/pkg delete -ay >>${LOGOUT} 2>>${LOGOUT}
1634  if [ $? -ne 0 ] ; then
1635     exit_revertsnap "Failed cleaning jail environment!"
1636  fi
1637
1638  # Next create the script to bootstrap pkgng
1639  echo "#!/bin/sh
1640tar xvpf ${CHROOTREALPKGDLCACHE}/${PKGFILENAME} -C / /usr/local/sbin/pkg-static >/dev/null 2>/dev/null
1641/usr/local/sbin/pkg-static add -f ${CHROOTREALPKGDLCACHE}/${PKGFILENAME}
1642if [ \$? -ne 0 ] ; then exit 1; fi
1643cd ${CHROOTREALPKGDLCACHE}
1644
1645# Cleanup the old /compat/linux for left-overs
1646umount /compat/linux/proc >/dev/null 2>/dev/null
1647umount /compat/linux/sys >/dev/null 2>/dev/null
1648rm -rf /compat/linux
1649mkdir -p /compat/linux/proc
1650mkdir -p /compat/linux/sys
1651
1652while read pkgLine
1653do
1654  pkgOrigin=\"\`echo \$pkgLine | cut -d ' ' -f 1\`\"
1655  pkgName=\"\`echo \$pkgLine | cut -d ' ' -f 2\`\"
1656  if [ ! -e \"\${pkgName}\" ] ; then
1657     echo \"No such package: \${pkgName}\"
1658     echo \"No such package: \${pkgName}\" >>/removed-pkg-list
1659     continue
1660  fi
1661
1662  echo \"Installing \$pkgName...\"
1663  pkg add \${pkgName} >/pkg-add.log 2>/pkg-add.log
1664  if [ \$? -ne 0 ] ; then
1665     echo \"Failed installing \${pkgName}\"
1666     cat /pkg-add.log
1667     echo \"Failed installing \${pkgName}\" >>/failed-pkg-list
1668     cat /pkg-add.log >>/failed-pkg-list
1669  fi
1670done < /install-pkg-list
1671rm /pkg-add.log >/dev/null 2>/dev/null
1672
1673# Save the log files
1674touch /install-pkg-list
1675touch /removed-pkg-list
1676touch /failed-pkg-list
1677mv /install-pkg-list /var/log/warden/
1678mv /removed-pkg-list /var/log/warden/
1679mv /failed-pkg-list /var/log/warden
1680
1681exit 0
1682" > ${STAGEMNT}/.doPkgUp.sh
1683
1684}
1685
1686install_pkgs_chroot()
1687{
1688  # Run it now
1689  echo_logout "Installing packages to jail ${JAILNAME}... (This may take a while)"
1690  chroot ${STAGEMNT} sh /.doPkgUp.sh >>${LOGOUT} 2>>${LOGOUT}
1691  if [ $? -ne 0 ] ; then
1692     exit_revertsnap "Failed upgrading packages!"
1693  fi
1694  rm ${STAGEMNT}/.doPkgUp.sh
1695}
1696
1697run_freebsd_update_script()
1698{
1699  # Start the upgrade with freebsd-update, get files downloaded installed
1700  rc_halt "mount -t devfs devfs ${JAILDIR}/dev"
1701  echo_logout "Fetching FreeBSD update files..."
1702  chroot ${STAGEMNT} freebsd-update --non-interactive fetch >>${LOGOUT} 2>>${LOGOUT}
1703  if [ $? -ne 0 ] ; then
1704     exit_revertsnap "Failed fetching FreeBSD update files!"
1705  fi
1706  echo_logout "Installing freebsd-update files..."
1707  chroot ${STAGEMNT} freebsd-update install >>${LOGOUT} 2>>${LOGOUT}
1708  if [ $? -ne 0 ] ; then
1709     exit_revertsnap "Failed installing FreeBSD update files!"
1710  fi
1711
1712  # Do it again, remove any old shared objs
1713  chroot ${STAGEMNT} freebsd-update install >/dev/null 2>/dev/null
1714  umount -f ${JAILDIR}/dev
1715}
1716
1717run_freebsd_upgrade_script()
1718{
1719  # Super ugly hack alert!
1720  # We modify freebsd-update to make it a bit happier running in a chroot / jail
1721  sed -i '' 's|uname -r|freebsd-version|g' ${JAILDIR}/usr/sbin/freebsd-update
1722
1723  # Start the upgrade with freebsd-update, get files downloaded installed
1724  rc_halt "mount -t devfs devfs ${JAILDIR}/dev"
1725  echo_logout "Fetching FreeBSD upgrade files..."
1726  chroot ${STAGEMNT} freebsd-update --non-interactive upgrade -r $NEWFREEBSDVERSION >>${LOGOUT} 2>>${LOGOUT}
1727  if [ $? -ne 0 ] ; then
1728     exit_revertsnap "Failed fetching FreeBSD upgrade files!"
1729  fi
1730  echo_logout "Installing freebsd-update files..."
1731  chroot ${STAGEMNT} freebsd-update install >>${LOGOUT} 2>>${LOGOUT}
1732  if [ $? -ne 0 ] ; then
1733     exit_revertsnap "Failed installing FreeBSD upgrade files!"
1734  fi
1735
1736  # Do it again, remove any old shared objs
1737  chroot ${STAGEMNT} freebsd-update install >/dev/null 2>/dev/null
1738  umount -f ${JAILDIR}/dev
1739}
1740
1741##############################################################
1742# End functions for upgrading jails
1743##############################################################
Note: See TracBrowser for help on using the repository browser.