· 10 years ago · Sep 18, 2016, 01:18 AM
1% sudo sh -v /usr/local/sbin/iohyve create testbsd 8G
2#!/bin/sh
3
4# iohyve v0.7.6 2016/06/12 "Rideau Street Sinkhole Edition"
5
6# Set proper path thanks to iocage
7PATH=${PATH}:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin
8
9# Check to see if CPU is compatible with bhyve
10if [ -n "$( grep 'POPCNT' /var/run/dmesg.boot )" ]; then
11 if [ -n "$( grep 'CPU:' /var/run/dmesg.boot | grep 'Intel' )" ] && [ -z "$( grep 'VT-x:' /var/run/dmesg.boot | grep 'UG' )" ]; then
12 echo "Your CPU does not seem to fully support bhyve. Missing UG feature on Intel CPU, please upgrade to 5600 series."
13 exit 1
14 fi
15else
16 echo "Your CPU does not seem to support bhyve."
17 echo "For AMD CPUs this means RVI. For Intel CPUs this means EPT."
18 exit 1
19fi
20
21# Check if libs are available (stolen from iocage)
22if [ -e "./lib/ioh-cmd" ] ; then
23 LIB="./lib"
24elif [ -e "/usr/local/lib/iohyve" ] ; then
25 LIB="/usr/local/lib/iohyve"
26else
27 echo "ERROR: missing libraries"
28 exit 1
29fi
30
31. /etc/rc.subr
32# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
33# $FreeBSD: stable/10/etc/rc.subr 292450 2015-12-18 19:58:34Z jilles $
34#
35# Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
36# All rights reserved.
37#
38# This code is derived from software contributed to The NetBSD Foundation
39# by Luke Mewburn.
40#
41# Redistribution and use in source and binary forms, with or without
42# modification, are permitted provided that the following conditions
43# are met:
44# 1. Redistributions of source code must retain the above copyright
45# notice, this list of conditions and the following disclaimer.
46# 2. Redistributions in binary form must reproduce the above copyright
47# notice, this list of conditions and the following disclaimer in the
48# documentation and/or other materials provided with the distribution.
49#
50# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60# POSSIBILITY OF SUCH DAMAGE.
61#
62# rc.subr
63# functions used by various rc scripts
64#
65
66: ${RC_PID:=$$}; export RC_PID
67
68#
69# Operating System dependent/independent variables
70#
71
72if [ -z "${_rc_subr_loaded}" ]; then
73
74_rc_subr_loaded="YES"
75
76SYSCTL="/sbin/sysctl"
77SYSCTL_N="${SYSCTL} -n"
78SYSCTL_W="${SYSCTL}"
79ID="/usr/bin/id"
80IDCMD="if [ -x $ID ]; then $ID -un; fi"
81PS="/bin/ps -ww"
82JID=`$PS -p $$ -o jid=`
83
84#
85# functions
86# ---------
87
88# list_vars pattern
89# List vars matching pattern.
90#
91list_vars()
92{
93 set | { while read LINE; do
94 var="${LINE%%=*}"
95 case "$var" in
96 "$LINE"|*[!a-zA-Z0-9_]*) continue ;;
97 $1) echo $var
98 esac
99 done; }
100}
101
102# set_rcvar [var] [defval] [desc]
103#
104# Echo or define a rc.conf(5) variable name. Global variable
105# $rcvars is used.
106#
107# If no argument is specified, echo "${name}_enable".
108#
109# If only a var is specified, echo "${var}_enable".
110#
111# If var and defval are specified, the ${var} is defined as
112# rc.conf(5) variable and the default value is ${defvar}. An
113# optional argument $desc can also be specified to add a
114# description for that.
115#
116set_rcvar()
117{
118 local _var
119
120 case $# in
121 0) echo ${name}_enable ;;
122 1) echo ${1}_enable ;;
123 *)
124 debug "set_rcvar: \$$1=$2 is added" \
125 " as a rc.conf(5) variable."
126 _var=$1
127 rcvars="${rcvars# } $_var"
128 eval ${_var}_defval=\"$2\"
129 shift 2
130 eval ${_var}_desc=\"$*\"
131 ;;
132 esac
133}
134
135# set_rcvar_obsolete oldvar [newvar] [msg]
136# Define obsolete variable.
137# Global variable $rcvars_obsolete is used.
138#
139set_rcvar_obsolete()
140{
141 local _var
142 _var=$1
143 debug "set_rcvar_obsolete: \$$1(old) -> \$$2(new) is defined"
144
145 rcvars_obsolete="${rcvars_obsolete# } $1"
146 eval ${1}_newvar=\"$2\"
147 shift 2
148 eval ${_var}_obsolete_msg=\"$*\"
149}
150
151#
152# force_depend script [rcvar]
153# Force a service to start. Intended for use by services
154# to resolve dependency issues.
155# $1 - filename of script, in /etc/rc.d, to run
156# $2 - name of the script's rcvar (minus the _enable)
157#
158force_depend()
159{
160 local _depend _dep_rcvar
161
162 _depend="$1"
163 _dep_rcvar="${2:-$1}_enable"
164
165 [ -n "$rc_fast" ] && ! checkyesno always_force_depends &&
166 checkyesno $_dep_rcvar && return 0
167
168 /etc/rc.d/${_depend} forcestatus >/dev/null 2>&1 && return 0
169
170 info "${name} depends on ${_depend}, which will be forced to start."
171 if ! /etc/rc.d/${_depend} forcestart; then
172 warn "Unable to force ${_depend}. It may already be running."
173 return 1
174 fi
175}
176
177#
178# checkyesno var
179# Test $1 variable, and warn if not set to YES or NO.
180# Return 0 if it's "yes" (et al), nonzero otherwise.
181#
182checkyesno()
183{
184 eval _value=\$${1}
185 debug "checkyesno: $1 is set to $_value."
186 case $_value in
187
188 # "yes", "true", "on", or "1"
189 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
190 return 0
191 ;;
192
193 # "no", "false", "off", or "0"
194 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
195 return 1
196 ;;
197 *)
198 warn "\$${1} is not set properly - see rc.conf(5)."
199 return 1
200 ;;
201 esac
202}
203
204#
205# reverse_list list
206# print the list in reverse order
207#
208reverse_list()
209{
210 _revlist=
211 for _revfile; do
212 _revlist="$_revfile $_revlist"
213 done
214 echo $_revlist
215}
216
217# stop_boot always
218# If booting directly to multiuser or $always is enabled,
219# send SIGTERM to the parent (/etc/rc) to abort the boot.
220# Otherwise just exit.
221#
222stop_boot()
223{
224 local always
225
226 case $1 in
227 # "yes", "true", "on", or "1"
228 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
229 always=true
230 ;;
231 *)
232 always=false
233 ;;
234 esac
235 if [ "$autoboot" = yes -o "$always" = true ]; then
236 echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
237 kill -TERM ${RC_PID}
238 fi
239 exit 1
240}
241
242#
243# mount_critical_filesystems type
244# Go through the list of critical filesystems as provided in
245# the rc.conf(5) variable $critical_filesystems_${type}, checking
246# each one to see if it is mounted, and if it is not, mounting it.
247#
248mount_critical_filesystems()
249{
250 eval _fslist=\$critical_filesystems_${1}
251 for _fs in $_fslist; do
252 mount | (
253 _ismounted=false
254 while read what _on on _type type; do
255 if [ $on = $_fs ]; then
256 _ismounted=true
257 fi
258 done
259 if $_ismounted; then
260 :
261 else
262 mount $_fs >/dev/null 2>&1
263 fi
264 )
265 done
266}
267
268#
269# check_pidfile pidfile procname [interpreter]
270# Parses the first line of pidfile for a PID, and ensures
271# that the process is running and matches procname.
272# Prints the matching PID upon success, nothing otherwise.
273# interpreter is optional; see _find_processes() for details.
274#
275check_pidfile()
276{
277 _pidfile=$1
278 _procname=$2
279 _interpreter=$3
280 if [ -z "$_pidfile" -o -z "$_procname" ]; then
281 err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
282 fi
283 if [ ! -f $_pidfile ]; then
284 debug "pid file ($_pidfile): not readable."
285 return
286 fi
287 read _pid _junk < $_pidfile
288 if [ -z "$_pid" ]; then
289 debug "pid file ($_pidfile): no pid in file."
290 return
291 fi
292 _find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
293}
294
295#
296# check_process procname [interpreter]
297# Ensures that a process (or processes) named procname is running.
298# Prints a list of matching PIDs.
299# interpreter is optional; see _find_processes() for details.
300#
301check_process()
302{
303 _procname=$1
304 _interpreter=$2
305 if [ -z "$_procname" ]; then
306 err 3 'USAGE: check_process procname [interpreter]'
307 fi
308 _find_processes $_procname ${_interpreter:-.} '-ax'
309}
310
311#
312# _find_processes procname interpreter psargs
313# Search for procname in the output of ps generated by psargs.
314# Prints the PIDs of any matching processes, space separated.
315#
316# If interpreter == ".", check the following variations of procname
317# against the first word of each command:
318# procname
319# `basename procname`
320# `basename procname` + ":"
321# "(" + `basename procname` + ")"
322# "[" + `basename procname` + "]"
323#
324# If interpreter != ".", read the first line of procname, remove the
325# leading #!, normalise whitespace, append procname, and attempt to
326# match that against each command, either as is, or with extra words
327# at the end. As an alternative, to deal with interpreted daemons
328# using perl, the basename of the interpreter plus a colon is also
329# tried as the prefix to procname.
330#
331_find_processes()
332{
333 if [ $# -ne 3 ]; then
334 err 3 'USAGE: _find_processes procname interpreter psargs'
335 fi
336 _procname=$1
337 _interpreter=$2
338 _psargs=$3
339
340 _pref=
341 if [ $_interpreter != "." ]; then # an interpreted script
342 _script="${_chroot}${_chroot:+/}$_procname"
343 if [ -r "$_script" ]; then
344 read _interp < $_script # read interpreter name
345 case "$_interp" in
346 \#!*)
347 _interp=${_interp#\#!} # strip #!
348 set -- $_interp
349 case $1 in
350 */bin/env)
351 shift # drop env to get real name
352 ;;
353 esac
354 if [ $_interpreter != $1 ]; then
355 warn "\$command_interpreter $_interpreter != $1"
356 fi
357 ;;
358 *)
359 warn "no shebang line in $_script"
360 set -- $_interpreter
361 ;;
362 esac
363 else
364 warn "cannot read shebang line from $_script"
365 set -- $_interpreter
366 fi
367 _interp="$* $_procname" # cleanup spaces, add _procname
368 _interpbn=${1##*/}
369 _fp_args='_argv'
370 _fp_match='case "$_argv" in
371 ${_interp}|"${_interp} "*|"[${_interpbn}]"|"${_interpbn}: ${_procname}"*)'
372 else # a normal daemon
373 _procnamebn=${_procname##*/}
374 _fp_args='_arg0 _argv'
375 _fp_match='case "$_arg0" in
376 $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
377 fi
378
379 _proccheck="\
380 $PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
381 while read _npid _jid '"$_fp_args"'; do
382 '"$_fp_match"'
383 if [ "$JID" -eq "$_jid" ];
384 then echo -n "$_pref$_npid";
385 _pref=" ";
386 fi
387 ;;
388 esac
389 done'
390
391# debug "in _find_processes: proccheck is ($_proccheck)."
392 eval $_proccheck
393}
394
395# sort_lite [-b] [-n] [-k POS] [-t SEP]
396# A lite version of sort(1) (supporting a few options) that can be used
397# before the real sort(1) is available (e.g., in scripts that run prior
398# to mountcritremote). Requires only shell built-in functionality.
399#
400sort_lite()
401{
402 local funcname=sort_lite
403 local sort_sep="$IFS" sort_ignore_leading_space=
404 local sort_field=0 sort_strict_fields= sort_numeric=
405 local nitems=0 skip_leading=0 trim=
406
407 local OPTIND flag
408 while getopts bnk:t: flag; do
409 case "$flag" in
410 b) sort_ignore_leading_space=1 ;;
411 n) sort_numeric=1 sort_ignore_leading_space=1 ;;
412 k) sort_field="${OPTARG%%,*}" ;; # only up to first comma
413 # NB: Unlike sort(1) only one POS allowed
414 t) sort_sep="$OPTARG"
415 if [ ${#sort_sep} -gt 1 ]; then
416 echo "$funcname: multi-character tab \`$sort_sep'" >&2
417 return 1
418 fi
419 sort_strict_fields=1
420 ;;
421 \?) return 1 ;;
422 esac
423 done
424 shift $(( $OPTIND - 1 ))
425
426 # Create transformation pattern to trim leading text if desired
427 case "$sort_field" in
428 ""|[!0-9]*|*[!0-9.]*)
429 echo "$funcname: invalid sort field \`$sort_field'" >&2
430 return 1
431 ;;
432 *.*)
433 skip_leading=${sort_field#*.} sort_field=${sort_field%%.*}
434 while [ ${skip_leading:-0} -gt 1 ] 2> /dev/null; do
435 trim="$trim?" skip_leading=$(( $skip_leading - 1 ))
436 done
437 esac
438
439 # Copy input to series of local numbered variables
440 # NB: IFS of NULL preserves leading whitespace
441 local LINE
442 while IFS= read -r LINE || [ "$LINE" ]; do
443 nitems=$(( $nitems + 1 ))
444 local src_$nitems="$LINE"
445 done
446
447 #
448 # Sort numbered locals using insertion sort
449 #
450 local curitem curitem_orig curitem_mod curitem_haskey
451 local dest dest_orig dest_mod dest_haskey
452 local d gt n
453 local i=1
454 while [ $i -le $nitems ]; do
455 curitem_haskey=1 # Assume sort field (-k POS) exists
456 eval curitem=\"\$src_$i\"
457 curitem_mod="$curitem" # for modified comparison
458 curitem_orig="$curitem" # for original comparison
459
460 # Trim leading whitespace if desired
461 if [ "$sort_ignore_leading_space" ]; then
462 while case "$curitem_orig" in
463 [$IFS]*) : ;; *) false; esac
464 do
465 curitem_orig="${curitem_orig#?}"
466 done
467 curitem_mod="$curitem_orig"
468 fi
469
470 # Shift modified comparison value if sort field (-k POS) is > 1
471 n=$sort_field
472 while [ $n -gt 1 ]; do
473 case "$curitem_mod" in
474 *[$sort_sep]*)
475 # Cut text up-to (and incl.) first separator
476 curitem_mod="${curitem_mod#*[$sort_sep]}"
477
478 # Skip NULLs unless strict field splitting
479 [ "$sort_strict_fields" ] ||
480 [ "${curitem_mod%%[$sort_sep]*}" ] ||
481 [ $n -eq 2 ] ||
482 continue
483 ;;
484 *)
485 # Asked for a field that doesn't exist
486 curitem_haskey= break
487 esac
488 n=$(( $n - 1 ))
489 done
490
491 # Trim trailing words if sort field >= 1
492 [ $sort_field -ge 1 -a "$sort_numeric" ] &&
493 curitem_mod="${curitem_mod%%[$sort_sep]*}"
494
495 # Apply optional trim (-k POS.TRIM) to cut leading characters
496 curitem_mod="${curitem_mod#$trim}"
497
498 # Determine the type of modified comparison to use initially
499 # NB: Prefer numerical if requested but fallback to standard
500 case "$curitem_mod" in
501 ""|[!0-9]*) # NULL or begins with non-number
502 gt=">"
503 [ "$sort_numeric" ] && curitem_mod=0
504 ;;
505 *)
506 if [ "$sort_numeric" ]; then
507 gt="-gt"
508 curitem_mod="${curitem_mod%%[!0-9]*}"
509 # NB: trailing non-digits removed
510 # otherwise numeric comparison fails
511 else
512 gt=">"
513 fi
514 esac
515
516 # If first time through, short-circuit below position-search
517 if [ $i -le 1 ]; then
518 d=0
519 else
520 d=1
521 fi
522
523 #
524 # Find appropriate element position
525 #
526 while [ $d -gt 0 ]
527 do
528 dest_haskey=$curitem_haskey
529 eval dest=\"\$dest_$d\"
530 dest_mod="$dest" # for modified comparison
531 dest_orig="$dest" # for original comparison
532
533 # Trim leading whitespace if desired
534 if [ "$sort_ignore_leading_space" ]; then
535 while case "$dest_orig" in
536 [$IFS]*) : ;; *) false; esac
537 do
538 dest_orig="${dest_orig#?}"
539 done
540 dest_mod="$dest_orig"
541 fi
542
543 # Shift modified value if sort field (-k POS) is > 1
544 n=$sort_field
545 while [ $n -gt 1 ]; do
546 case "$dest_mod" in
547 *[$sort_sep]*)
548 # Cut text up-to (and incl.) 1st sep
549 dest_mod="${dest_mod#*[$sort_sep]}"
550
551 # Skip NULLs unless strict fields
552 [ "$sort_strict_fields" ] ||
553 [ "${dest_mod%%[$sort_sep]*}" ] ||
554 [ $n -eq 2 ] ||
555 continue
556 ;;
557 *)
558 # Asked for a field that doesn't exist
559 dest_haskey= break
560 esac
561 n=$(( $n - 1 ))
562 done
563
564 # Trim trailing words if sort field >= 1
565 [ $sort_field -ge 1 -a "$sort_numeric" ] &&
566 dest_mod="${dest_mod%%[$sort_sep]*}"
567
568 # Apply optional trim (-k POS.TRIM), cut leading chars
569 dest_mod="${dest_mod#$trim}"
570
571 # Determine type of modified comparison to use
572 # NB: Prefer numerical if requested, fallback to std
573 case "$dest_mod" in
574 ""|[!0-9]*) # NULL or begins with non-number
575 gt=">"
576 [ "$sort_numeric" ] && dest_mod=0
577 ;;
578 *)
579 if [ "$sort_numeric" ]; then
580 gt="-gt"
581 dest_mod="${dest_mod%%[!0-9]*}"
582 # NB: kill trailing non-digits
583 # for numeric comparison safety
584 else
585 gt=">"
586 fi
587 esac
588
589 # Break if we've found the proper element position
590 if [ "$curitem_haskey" -a "$dest_haskey" ]; then
591 if [ "$dest_mod" = "$curitem_mod" ]; then
592 [ "$dest_orig" ">" "$curitem_orig" ] &&
593 break
594 elif [ "$dest_mod" $gt "$curitem_mod" ] \
595 2> /dev/null
596 then
597 break
598 fi
599 else
600 [ "$dest_orig" ">" "$curitem_orig" ] && break
601 fi
602
603 # Break if we've hit the end
604 [ $d -ge $i ] && break
605
606 d=$(( $d + 1 ))
607 done
608
609 # Shift remaining positions forward, making room for new item
610 n=$i
611 while [ $n -ge $d ]; do
612 # Shift destination item forward one placement
613 eval dest_$(( $n + 1 ))=\"\$dest_$n\"
614 n=$(( $n - 1 ))
615 done
616
617 # Place the element
618 if [ $i -eq 1 ]; then
619 local dest_1="$curitem"
620 else
621 local dest_$d="$curitem"
622 fi
623
624 i=$(( $i + 1 ))
625 done
626
627 # Print sorted results
628 d=1
629 while [ $d -le $nitems ]; do
630 eval echo \"\$dest_$d\"
631 d=$(( $d + 1 ))
632 done
633}
634
635#
636# wait_for_pids pid [pid ...]
637# spins until none of the pids exist
638#
639wait_for_pids()
640{
641 local _list _prefix _nlist _j
642
643 _list="$@"
644 if [ -z "$_list" ]; then
645 return
646 fi
647 _prefix=
648 while true; do
649 _nlist="";
650 for _j in $_list; do
651 if kill -0 $_j 2>/dev/null; then
652 _nlist="${_nlist}${_nlist:+ }$_j"
653 [ -n "$_prefix" ] && sleep 1
654 fi
655 done
656 if [ -z "$_nlist" ]; then
657 break
658 fi
659 _list=$_nlist
660 echo -n ${_prefix:-"Waiting for PIDS: "}$_list
661 _prefix=", "
662 pwait $_list 2>/dev/null
663 done
664 if [ -n "$_prefix" ]; then
665 echo "."
666 fi
667}
668
669#
670# get_pidfile_from_conf string file
671#
672# Takes a string to search for in the specified file.
673# Ignores lines with traditional comment characters.
674#
675# Example:
676#
677# if get_pidfile_from_conf string file; then
678# pidfile="$_pidfile_from_conf"
679# else
680# pidfile='appropriate default'
681# fi
682#
683get_pidfile_from_conf()
684{
685 if [ -z "$1" -o -z "$2" ]; then
686 err 3 "USAGE: get_pidfile_from_conf string file ($name)"
687 fi
688
689 local string file line
690
691 string="$1" ; file="$2"
692
693 if [ ! -s "$file" ]; then
694 err 3 "get_pidfile_from_conf: $file does not exist ($name)"
695 fi
696
697 while read line; do
698 case "$line" in
699 *[#\;]*${string}*) continue ;;
700 *${string}*) break ;;
701 esac
702 done < $file
703
704 if [ -n "$line" ]; then
705 line=${line#*/}
706 _pidfile_from_conf="/${line%%[\"\;]*}"
707 else
708 return 1
709 fi
710}
711
712#
713# check_startmsgs
714# If rc_quiet is set (usually as a result of using faststart at
715# boot time) check if rc_startmsgs is enabled.
716#
717check_startmsgs()
718{
719 if [ -n "$rc_quiet" ]; then
720 checkyesno rc_startmsgs
721 else
722 return 0
723 fi
724}
725
726#
727# run_rc_command argument
728# Search for argument in the list of supported commands, which is:
729# "start stop restart rcvar status poll ${extra_commands}"
730# If there's a match, run ${argument}_cmd or the default method
731# (see below).
732#
733# If argument has a given prefix, then change the operation as follows:
734# Prefix Operation
735# ------ ---------
736# fast Skip the pid check, and set rc_fast=yes, rc_quiet=yes
737# force Set ${rcvar} to YES, and set rc_force=yes
738# one Set ${rcvar} to YES
739# quiet Don't output some diagnostics, and set rc_quiet=yes
740#
741# The following globals are used:
742#
743# Name Needed Purpose
744# ---- ------ -------
745# name y Name of script.
746#
747# command n Full path to command.
748# Not needed if ${rc_arg}_cmd is set for
749# each keyword.
750#
751# command_args n Optional args/shell directives for command.
752#
753# command_interpreter n If not empty, command is interpreted, so
754# call check_{pidfile,process}() appropriately.
755#
756# desc n Description of script.
757#
758# extra_commands n List of extra commands supported.
759#
760# pidfile n If set, use check_pidfile $pidfile $command,
761# otherwise use check_process $command.
762# In either case, only check if $command is set.
763#
764# procname n Process name to check for instead of $command.
765#
766# rcvar n This is checked with checkyesno to determine
767# if the action should be run.
768#
769# ${name}_program n Full path to command.
770# Meant to be used in /etc/rc.conf to override
771# ${command}.
772#
773# ${name}_chroot n Directory to chroot to before running ${command}
774# Requires /usr to be mounted.
775#
776# ${name}_chdir n Directory to cd to before running ${command}
777# (if not using ${name}_chroot).
778#
779# ${name}_flags n Arguments to call ${command} with.
780# NOTE: $flags from the parent environment
781# can be used to override this.
782#
783# ${name}_env n Environment variables to run ${command} with.
784#
785# ${name}_fib n Routing table number to run ${command} with.
786#
787# ${name}_nice n Nice level to run ${command} at.
788#
789# ${name}_user n User to run ${command} as, using su(1) if not
790# using ${name}_chroot.
791# Requires /usr to be mounted.
792#
793# ${name}_group n Group to run chrooted ${command} as.
794# Requires /usr to be mounted.
795#
796# ${name}_groups n Comma separated list of supplementary groups
797# to run the chrooted ${command} with.
798# Requires /usr to be mounted.
799#
800# ${name}_prepend n Command added before ${command}.
801#
802# ${rc_arg}_cmd n If set, use this as the method when invoked;
803# Otherwise, use default command (see below)
804#
805# ${rc_arg}_precmd n If set, run just before performing the
806# ${rc_arg}_cmd method in the default
807# operation (i.e, after checking for required
808# bits and process (non)existence).
809# If this completes with a non-zero exit code,
810# don't run ${rc_arg}_cmd.
811#
812# ${rc_arg}_postcmd n If set, run just after performing the
813# ${rc_arg}_cmd method, if that method
814# returned a zero exit code.
815#
816# required_dirs n If set, check for the existence of the given
817# directories before running a (re)start command.
818#
819# required_files n If set, check for the readability of the given
820# files before running a (re)start command.
821#
822# required_modules n If set, ensure the given kernel modules are
823# loaded before running a (re)start command.
824# The check and possible loads are actually
825# done after start_precmd so that the modules
826# aren't loaded in vain, should the precmd
827# return a non-zero status to indicate a error.
828# If a word in the list looks like "foo:bar",
829# "foo" is the KLD file name and "bar" is the
830# module name. If a word looks like "foo~bar",
831# "foo" is the KLD file name and "bar" is a
832# egrep(1) pattern matching the module name.
833# Otherwise the module name is assumed to be
834# the same as the KLD file name, which is most
835# common. See load_kld().
836#
837# required_vars n If set, perform checkyesno on each of the
838# listed variables before running the default
839# (re)start command.
840#
841# Default behaviour for a given argument, if no override method is
842# provided:
843#
844# Argument Default behaviour
845# -------- -----------------
846# start if !running && checkyesno ${rcvar}
847# ${command}
848#
849# stop if ${pidfile}
850# rc_pid=$(check_pidfile $pidfile $command)
851# else
852# rc_pid=$(check_process $command)
853# kill $sig_stop $rc_pid
854# wait_for_pids $rc_pid
855# ($sig_stop defaults to TERM.)
856#
857# reload Similar to stop, except use $sig_reload instead,
858# and doesn't wait_for_pids.
859# $sig_reload defaults to HUP.
860# Note that `reload' isn't provided by default,
861# it should be enabled via $extra_commands.
862#
863# restart Run `stop' then `start'.
864#
865# status Show if ${command} is running, etc.
866#
867# poll Wait for ${command} to exit.
868#
869# rcvar Display what rc.conf variable is used (if any).
870#
871# enabled Return true if the service is enabled.
872#
873# Variables available to methods, and after run_rc_command() has
874# completed:
875#
876# Variable Purpose
877# -------- -------
878# rc_arg Argument to command, after fast/force/one processing
879# performed
880#
881# rc_flags Flags to start the default command with.
882# Defaults to ${name}_flags, unless overridden
883# by $flags from the environment.
884# This variable may be changed by the precmd method.
885#
886# rc_pid PID of command (if appropriate)
887#
888# rc_fast Not empty if "fast" was provided (q.v.)
889#
890# rc_force Not empty if "force" was provided (q.v.)
891#
892# rc_quiet Not empty if "quiet" was provided
893#
894#
895run_rc_command()
896{
897 _return=0
898 rc_arg=$1
899 if [ -z "$name" ]; then
900 err 3 'run_rc_command: $name is not set.'
901 fi
902
903 # Don't repeat the first argument when passing additional command-
904 # line arguments to the command subroutines.
905 #
906 shift 1
907 rc_extra_args="$*"
908
909 _rc_prefix=
910 case "$rc_arg" in
911 fast*) # "fast" prefix; don't check pid
912 rc_arg=${rc_arg#fast}
913 rc_fast=yes
914 rc_quiet=yes
915 ;;
916 force*) # "force" prefix; always run
917 rc_force=yes
918 _rc_prefix=force
919 rc_arg=${rc_arg#${_rc_prefix}}
920 if [ -n "${rcvar}" ]; then
921 eval ${rcvar}=YES
922 fi
923 ;;
924 one*) # "one" prefix; set ${rcvar}=yes
925 _rc_prefix=one
926 rc_arg=${rc_arg#${_rc_prefix}}
927 if [ -n "${rcvar}" ]; then
928 eval ${rcvar}=YES
929 fi
930 ;;
931 quiet*) # "quiet" prefix; omit some messages
932 _rc_prefix=quiet
933 rc_arg=${rc_arg#${_rc_prefix}}
934 rc_quiet=yes
935 ;;
936 esac
937
938 eval _override_command=\$${name}_program
939 command=${_override_command:-$command}
940
941 _keywords="start stop restart rcvar enabled $extra_commands"
942 rc_pid=
943 _pidcmd=
944 _procname=${procname:-${command}}
945
946 # setup pid check command
947 if [ -n "$_procname" ]; then
948 if [ -n "$pidfile" ]; then
949 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
950 else
951 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
952 fi
953 if [ -n "$_pidcmd" ]; then
954 _keywords="${_keywords} status poll"
955 fi
956 fi
957
958 if [ -z "$rc_arg" ]; then
959 rc_usage $_keywords
960 fi
961
962 if [ "$rc_arg" = "enabled" ] ; then
963 checkyesno ${rcvar}
964 return $?
965 fi
966
967 if [ -n "$flags" ]; then # allow override from environment
968 rc_flags=$flags
969 else
970 eval rc_flags=\$${name}_flags
971 fi
972 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \
973 _nice=\$${name}_nice _user=\$${name}_user \
974 _group=\$${name}_group _groups=\$${name}_groups \
975 _fib=\$${name}_fib _env=\$${name}_env \
976 _prepend=\$${name}_prepend
977
978 if [ -n "$_user" ]; then # unset $_user if running as that user
979 if [ "$_user" = "$(eval $IDCMD)" ]; then
980 unset _user
981 fi
982 fi
983
984 [ -z "$autoboot" ] && eval $_pidcmd # determine the pid if necessary
985
986 for _elem in $_keywords; do
987 if [ "$_elem" != "$rc_arg" ]; then
988 continue
989 fi
990 # if ${rcvar} is set, $1 is not "rcvar"
991 # and ${rc_pid} is not set, then run
992 # checkyesno ${rcvar}
993 # and return if that failed
994 #
995 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" ] ||
996 [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then
997 if ! checkyesno ${rcvar}; then
998 if [ -n "${rc_quiet}" ]; then
999 return 0
1000 fi
1001 echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
1002 echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
1003 echo "instead of '${rc_arg}'."
1004 return 0
1005 fi
1006 fi
1007
1008 if [ $rc_arg = "start" -a -z "$rc_fast" -a -n "$rc_pid" ]; then
1009 if [ -z "$rc_quiet" ]; then
1010 echo 1>&2 "${name} already running? " \
1011 "(pid=$rc_pid)."
1012 fi
1013 return 1
1014 fi
1015
1016 # if there's a custom ${XXX_cmd},
1017 # run that instead of the default
1018 #
1019 eval _cmd=\$${rc_arg}_cmd \
1020 _precmd=\$${rc_arg}_precmd \
1021 _postcmd=\$${rc_arg}_postcmd
1022
1023 if [ -n "$_cmd" ]; then
1024 _run_rc_precmd || return 1
1025 _run_rc_doit "$_cmd $rc_extra_args" || return 1
1026 _run_rc_postcmd
1027 return $_return
1028 fi
1029
1030 case "$rc_arg" in # default operations...
1031
1032 status)
1033 _run_rc_precmd || return 1
1034 if [ -n "$rc_pid" ]; then
1035 echo "${name} is running as pid $rc_pid."
1036 else
1037 echo "${name} is not running."
1038 return 1
1039 fi
1040 _run_rc_postcmd
1041 ;;
1042
1043 start)
1044 if [ ! -x "${_chroot}${_chroot:+/}${command}" ]; then
1045 warn "run_rc_command: cannot run $command"
1046 return 1
1047 fi
1048
1049 if ! _run_rc_precmd; then
1050 warn "failed precmd routine for ${name}"
1051 return 1
1052 fi
1053
1054 # setup the full command to run
1055 #
1056 check_startmsgs && echo "Starting ${name}."
1057 if [ -n "$_chroot" ]; then
1058 _doit="\
1059${_nice:+nice -n $_nice }\
1060${_fib:+setfib -F $_fib }\
1061${_env:+env $_env }\
1062chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
1063$_chroot $command $rc_flags $command_args"
1064 else
1065 _doit="\
1066${_chdir:+cd $_chdir && }\
1067${_fib:+setfib -F $_fib }\
1068${_env:+env $_env }\
1069$command $rc_flags $command_args"
1070 if [ -n "$_user" ]; then
1071 _doit="su -m $_user -c 'sh -c \"$_doit\"'"
1072 fi
1073 if [ -n "$_nice" ]; then
1074 if [ -z "$_user" ]; then
1075 _doit="sh -c \"$_doit\""
1076 fi
1077 _doit="nice -n $_nice $_doit"
1078 fi
1079 if [ -n "$_prepend" ]; then
1080 _doit="$_prepend $_doit"
1081 fi
1082 fi
1083
1084 # run the full command
1085 #
1086 if ! _run_rc_doit "$_doit"; then
1087 warn "failed to start ${name}"
1088 return 1
1089 fi
1090
1091 # finally, run postcmd
1092 #
1093 _run_rc_postcmd
1094 ;;
1095
1096 stop)
1097 if [ -z "$rc_pid" ]; then
1098 [ -n "$rc_fast" ] && return 0
1099 _run_rc_notrunning
1100 return 1
1101 fi
1102
1103 _run_rc_precmd || return 1
1104
1105 # send the signal to stop
1106 #
1107 echo "Stopping ${name}."
1108 _doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
1109 _run_rc_doit "$_doit" || return 1
1110
1111 # wait for the command to exit,
1112 # and run postcmd.
1113 wait_for_pids $rc_pid
1114
1115 _run_rc_postcmd
1116 ;;
1117
1118 reload)
1119 if [ -z "$rc_pid" ]; then
1120 _run_rc_notrunning
1121 return 1
1122 fi
1123
1124 _run_rc_precmd || return 1
1125
1126 _doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
1127 _run_rc_doit "$_doit" || return 1
1128
1129 _run_rc_postcmd
1130 ;;
1131
1132 restart)
1133 # prevent restart being called more
1134 # than once by any given script
1135 #
1136 if ${_rc_restart_done:-false}; then
1137 return 0
1138 fi
1139 _rc_restart_done=true
1140
1141 _run_rc_precmd || return 1
1142
1143 # run those in a subshell to keep global variables
1144 ( run_rc_command ${_rc_prefix}stop $rc_extra_args )
1145 ( run_rc_command ${_rc_prefix}start $rc_extra_args )
1146 _return=$?
1147 [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
1148
1149 _run_rc_postcmd
1150 ;;
1151
1152 poll)
1153 _run_rc_precmd || return 1
1154 if [ -n "$rc_pid" ]; then
1155 wait_for_pids $rc_pid
1156 fi
1157 _run_rc_postcmd
1158 ;;
1159
1160 rcvar)
1161 echo -n "# $name"
1162 if [ -n "$desc" ]; then
1163 echo " : $desc"
1164 else
1165 echo ""
1166 fi
1167 echo "#"
1168 # Get unique vars in $rcvar $rcvars
1169 for _v in $rcvar $rcvars; do
1170 case $v in
1171 $_v\ *|\ *$_v|*\ $_v\ *) ;;
1172 *) v="${v# } $_v" ;;
1173 esac
1174 done
1175
1176 # Display variables.
1177 for _v in $v; do
1178 if [ -z "$_v" ]; then
1179 continue
1180 fi
1181
1182 eval _desc=\$${_v}_desc
1183 eval _defval=\$${_v}_defval
1184 _h="-"
1185
1186 eval echo \"$_v=\\\"\$$_v\\\"\"
1187 # decode multiple lines of _desc
1188 while [ -n "$_desc" ]; do
1189 case $_desc in
1190 *^^*)
1191 echo "# $_h ${_desc%%^^*}"
1192 _desc=${_desc#*^^}
1193 _h=" "
1194 ;;
1195 *)
1196 echo "# $_h ${_desc}"
1197 break
1198 ;;
1199 esac
1200 done
1201 echo "# (default: \"$_defval\")"
1202 done
1203 echo ""
1204 ;;
1205
1206 *)
1207 rc_usage $_keywords
1208 ;;
1209
1210 esac
1211 return $_return
1212 done
1213
1214 echo 1>&2 "$0: unknown directive '$rc_arg'."
1215 rc_usage $_keywords
1216 # not reached
1217}
1218
1219#
1220# Helper functions for run_rc_command: common code.
1221# They use such global variables besides the exported rc_* ones:
1222#
1223# name R/W
1224# ------------------
1225# _precmd R
1226# _postcmd R
1227# _return W
1228#
1229_run_rc_precmd()
1230{
1231 check_required_before "$rc_arg" || return 1
1232
1233 if [ -n "$_precmd" ]; then
1234 debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
1235 eval "$_precmd $rc_extra_args"
1236 _return=$?
1237
1238 # If precmd failed and force isn't set, request exit.
1239 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1240 return 1
1241 fi
1242 fi
1243
1244 check_required_after "$rc_arg" || return 1
1245
1246 return 0
1247}
1248
1249_run_rc_postcmd()
1250{
1251 if [ -n "$_postcmd" ]; then
1252 debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
1253 eval "$_postcmd $rc_extra_args"
1254 _return=$?
1255 fi
1256 return 0
1257}
1258
1259_run_rc_doit()
1260{
1261 debug "run_rc_command: doit: $*"
1262 eval "$@"
1263 _return=$?
1264
1265 # If command failed and force isn't set, request exit.
1266 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1267 return 1
1268 fi
1269
1270 return 0
1271}
1272
1273_run_rc_notrunning()
1274{
1275 local _pidmsg
1276
1277 if [ -n "$pidfile" ]; then
1278 _pidmsg=" (check $pidfile)."
1279 else
1280 _pidmsg=
1281 fi
1282 echo 1>&2 "${name} not running?${_pidmsg}"
1283}
1284
1285_run_rc_killcmd()
1286{
1287 local _cmd
1288
1289 _cmd="kill -$1 $rc_pid"
1290 if [ -n "$_user" ]; then
1291 _cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
1292 fi
1293 echo "$_cmd"
1294}
1295
1296#
1297# run_rc_script file arg
1298# Start the script `file' with `arg', and correctly handle the
1299# return value from the script.
1300# If `file' ends with `.sh', it's sourced into the current environment
1301# when $rc_fast_and_loose is set, otherwise it is run as a child process.
1302# If `file' appears to be a backup or scratch file, ignore it.
1303# Otherwise if it is executable run as a child process.
1304#
1305run_rc_script()
1306{
1307 _file=$1
1308 _arg=$2
1309 if [ -z "$_file" -o -z "$_arg" ]; then
1310 err 3 'USAGE: run_rc_script file arg'
1311 fi
1312
1313 unset name command command_args command_interpreter \
1314 extra_commands pidfile procname \
1315 rcvar rcvars rcvars_obsolete required_dirs required_files \
1316 required_vars
1317 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
1318
1319 case "$_file" in
1320 /etc/rc.d/*.sh) # no longer allowed in the base
1321 warn "Ignoring old-style startup script $_file"
1322 ;;
1323 *[~#]|*.OLD|*.bak|*.orig|*,v) # scratch file; skip
1324 warn "Ignoring scratch file $_file"
1325 ;;
1326 *) # run in subshell
1327 if [ -x $_file ]; then
1328 if [ -n "$rc_fast_and_loose" ]; then
1329 set $_arg; . $_file
1330 else
1331 ( trap "echo Script $_file interrupted >&2 ; kill -QUIT $$" 3
1332 trap "echo Script $_file interrupted >&2 ; exit 1" 2
1333 trap "echo Script $_file running >&2" 29
1334 set $_arg; . $_file )
1335 fi
1336 fi
1337 ;;
1338 esac
1339}
1340
1341#
1342# load_rc_config [service]
1343# Source in the configuration file(s) for a given service.
1344# If no service is specified, only the global configuration
1345# file(s) will be loaded.
1346#
1347load_rc_config()
1348{
1349 local _name _rcvar_val _var _defval _v _msg _new _d
1350 _name=$1
1351
1352 if ${_rc_conf_loaded:-false}; then
1353 :
1354 else
1355 if [ -r /etc/defaults/rc.conf ]; then
1356 debug "Sourcing /etc/defaults/rc.conf"
1357 . /etc/defaults/rc.conf
1358 source_rc_confs
1359 elif [ -r /etc/rc.conf ]; then
1360 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
1361 . /etc/rc.conf
1362 fi
1363 _rc_conf_loaded=true
1364 fi
1365
1366 # If a service name was specified, attempt to load
1367 # service-specific configuration
1368 if [ -n "$_name" ] ; then
1369 for _d in /etc ${local_startup}; do
1370 _d=${_d%/rc.d}
1371 if [ -f ${_d}/rc.conf.d/"$_name" ]; then
1372 debug "Sourcing ${_d}/rc.conf.d/$_name"
1373 . ${_d}/rc.conf.d/"$_name"
1374 elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then
1375 local _rc
1376 for _rc in ${_d}/rc.conf.d/"$_name"/* ; do
1377 if [ -f "$_rc" ] ; then
1378 debug "Sourcing $_rc"
1379 . "$_rc"
1380 fi
1381 done
1382 fi
1383 done
1384 fi
1385
1386 # Set defaults if defined.
1387 for _var in $rcvar $rcvars; do
1388 eval _defval=\$${_var}_defval
1389 if [ -n "$_defval" ]; then
1390 eval : \${$_var:=\$${_var}_defval}
1391 fi
1392 done
1393
1394 # check obsolete rc.conf variables
1395 for _var in $rcvars_obsolete; do
1396 eval _v=\$$_var
1397 eval _msg=\$${_var}_obsolete_msg
1398 eval _new=\$${_var}_newvar
1399 case $_v in
1400 "")
1401 ;;
1402 *)
1403 if [ -z "$_new" ]; then
1404 _msg="Ignored."
1405 else
1406 eval $_new=\"\$$_var\"
1407 if [ -z "$_msg" ]; then
1408 _msg="Use \$$_new instead."
1409 fi
1410 fi
1411 warn "\$$_var is obsolete. $_msg"
1412 ;;
1413 esac
1414 done
1415}
1416
1417#
1418# load_rc_config_var name var
1419# Read the rc.conf(5) var for name and set in the
1420# current shell, using load_rc_config in a subshell to prevent
1421# unwanted side effects from other variable assignments.
1422#
1423load_rc_config_var()
1424{
1425 if [ $# -ne 2 ]; then
1426 err 3 'USAGE: load_rc_config_var name var'
1427 fi
1428 eval $(eval '(
1429 load_rc_config '$1' >/dev/null;
1430 if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
1431 echo '$2'=\'\''${'$2'}\'\'';
1432 fi
1433 )' )
1434}
1435
1436#
1437# rc_usage commands
1438# Print a usage string for $0, with `commands' being a list of
1439# valid commands.
1440#
1441rc_usage()
1442{
1443 echo -n 1>&2 "Usage: $0 [fast|force|one|quiet]("
1444
1445 _sep=
1446 for _elem; do
1447 echo -n 1>&2 "$_sep$_elem"
1448 _sep="|"
1449 done
1450 echo 1>&2 ")"
1451 exit 1
1452}
1453
1454#
1455# err exitval message
1456# Display message to stderr and log to the syslog, and exit with exitval.
1457#
1458err()
1459{
1460 exitval=$1
1461 shift
1462
1463 if [ -x /usr/bin/logger ]; then
1464 logger "$0: ERROR: $*"
1465 fi
1466 echo 1>&2 "$0: ERROR: $*"
1467 exit $exitval
1468}
1469
1470#
1471# warn message
1472# Display message to stderr and log to the syslog.
1473#
1474warn()
1475{
1476 if [ -x /usr/bin/logger ]; then
1477 logger "$0: WARNING: $*"
1478 fi
1479 echo 1>&2 "$0: WARNING: $*"
1480}
1481
1482#
1483# info message
1484# Display informational message to stdout and log to syslog.
1485#
1486info()
1487{
1488 case ${rc_info} in
1489 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1490 if [ -x /usr/bin/logger ]; then
1491 logger "$0: INFO: $*"
1492 fi
1493 echo "$0: INFO: $*"
1494 ;;
1495 esac
1496}
1497
1498#
1499# debug message
1500# If debugging is enabled in rc.conf output message to stderr.
1501# BEWARE that you don't call any subroutine that itself calls this
1502# function.
1503#
1504debug()
1505{
1506 case ${rc_debug} in
1507 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1508 if [ -x /usr/bin/logger ]; then
1509 logger "$0: DEBUG: $*"
1510 fi
1511 echo 1>&2 "$0: DEBUG: $*"
1512 ;;
1513 esac
1514}
1515
1516#
1517# backup_file action file cur backup
1518# Make a backup copy of `file' into `cur', and save the previous
1519# version of `cur' as `backup' or use rcs for archiving.
1520#
1521# This routine checks the value of the backup_uses_rcs variable,
1522# which can be either YES or NO.
1523#
1524# The `action' keyword can be one of the following:
1525#
1526# add `file' is now being backed up (and is possibly
1527# being reentered into the backups system). `cur'
1528# is created and RCS files, if necessary, are
1529# created as well.
1530#
1531# update `file' has changed and needs to be backed up.
1532# If `cur' exists, it is copied to to `back' or
1533# checked into RCS (if the repository file is old),
1534# and then `file' is copied to `cur'. Another RCS
1535# check in done here if RCS is being used.
1536#
1537# remove `file' is no longer being tracked by the backups
1538# system. If RCS is not being used, `cur' is moved
1539# to `back', otherwise an empty file is checked in,
1540# and then `cur' is removed.
1541#
1542#
1543backup_file()
1544{
1545 _action=$1
1546 _file=$2
1547 _cur=$3
1548 _back=$4
1549
1550 if checkyesno backup_uses_rcs; then
1551 _msg0="backup archive"
1552 _msg1="update"
1553
1554 # ensure that history file is not locked
1555 if [ -f $_cur,v ]; then
1556 rcs -q -u -U -M $_cur
1557 fi
1558
1559 # ensure after switching to rcs that the
1560 # current backup is not lost
1561 if [ -f $_cur ]; then
1562 # no archive, or current newer than archive
1563 if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1564 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1565 rcs -q -kb -U $_cur
1566 co -q -f -u $_cur
1567 fi
1568 fi
1569
1570 case $_action in
1571 add|update)
1572 cp -p $_file $_cur
1573 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1574 rcs -q -kb -U $_cur
1575 co -q -f -u $_cur
1576 chown root:wheel $_cur $_cur,v
1577 ;;
1578 remove)
1579 cp /dev/null $_cur
1580 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1581 rcs -q -kb -U $_cur
1582 chown root:wheel $_cur $_cur,v
1583 rm $_cur
1584 ;;
1585 esac
1586 else
1587 case $_action in
1588 add|update)
1589 if [ -f $_cur ]; then
1590 cp -p $_cur $_back
1591 fi
1592 cp -p $_file $_cur
1593 chown root:wheel $_cur
1594 ;;
1595 remove)
1596 mv -f $_cur $_back
1597 ;;
1598 esac
1599 fi
1600}
1601
1602# make_symlink src link
1603# Make a symbolic link 'link' to src from basedir. If the
1604# directory in which link is to be created does not exist
1605# a warning will be displayed and an error will be returned.
1606# Returns 0 on success, 1 otherwise.
1607#
1608make_symlink()
1609{
1610 local src link linkdir _me
1611 src="$1"
1612 link="$2"
1613 linkdir="`dirname $link`"
1614 _me="make_symlink()"
1615
1616 if [ -z "$src" -o -z "$link" ]; then
1617 warn "$_me: requires two arguments."
1618 return 1
1619 fi
1620 if [ ! -d "$linkdir" ]; then
1621 warn "$_me: the directory $linkdir does not exist."
1622 return 1
1623 fi
1624 if ! ln -sf $src $link; then
1625 warn "$_me: unable to make a symbolic link from $link to $src"
1626 return 1
1627 fi
1628 return 0
1629}
1630
1631# devfs_rulesets_from_file file
1632# Reads a set of devfs commands from file, and creates
1633# the specified rulesets with their rules. Returns non-zero
1634# if there was an error.
1635#
1636devfs_rulesets_from_file()
1637{
1638 local file _err _me _opts
1639 file="$1"
1640 _me="devfs_rulesets_from_file"
1641 _err=0
1642
1643 if [ -z "$file" ]; then
1644 warn "$_me: you must specify a file"
1645 return 1
1646 fi
1647 if [ ! -e "$file" ]; then
1648 debug "$_me: no such file ($file)"
1649 return 0
1650 fi
1651
1652 # Disable globbing so that the rule patterns are not expanded
1653 # by accident with matching filesystem entries.
1654 _opts=$-; set -f
1655
1656 debug "reading rulesets from file ($file)"
1657 { while read line
1658 do
1659 case $line in
1660 \#*)
1661 continue
1662 ;;
1663 \[*\]*)
1664 rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1665 if [ -z "$rulenum" ]; then
1666 warn "$_me: cannot extract rule number ($line)"
1667 _err=1
1668 break
1669 fi
1670 rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1671 if [ -z "$rulename" ]; then
1672 warn "$_me: cannot extract rule name ($line)"
1673 _err=1
1674 break;
1675 fi
1676 eval $rulename=\$rulenum
1677 debug "found ruleset: $rulename=$rulenum"
1678 if ! /sbin/devfs rule -s $rulenum delset; then
1679 _err=1
1680 break
1681 fi
1682 ;;
1683 *)
1684 rulecmd="${line%%"\#*"}"
1685 # evaluate the command incase it includes
1686 # other rules
1687 if [ -n "$rulecmd" ]; then
1688 debug "adding rule ($rulecmd)"
1689 if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1690 then
1691 _err=1
1692 break
1693 fi
1694 fi
1695 ;;
1696 esac
1697 if [ $_err -ne 0 ]; then
1698 debug "error in $_me"
1699 break
1700 fi
1701 done } < $file
1702 case $_opts in *f*) ;; *) set +f ;; esac
1703 return $_err
1704}
1705
1706# devfs_init_rulesets
1707# Initializes rulesets from configuration files. Returns
1708# non-zero if there was an error.
1709#
1710devfs_init_rulesets()
1711{
1712 local file _me
1713 _me="devfs_init_rulesets"
1714
1715 # Go through this only once
1716 if [ -n "$devfs_rulesets_init" ]; then
1717 debug "$_me: devfs rulesets already initialized"
1718 return
1719 fi
1720 for file in $devfs_rulesets; do
1721 if ! devfs_rulesets_from_file $file; then
1722 warn "$_me: could not read rules from $file"
1723 return 1
1724 fi
1725 done
1726 devfs_rulesets_init=1
1727 debug "$_me: devfs rulesets initialized"
1728 return 0
1729}
1730
1731# devfs_set_ruleset ruleset [dir]
1732# Sets the default ruleset of dir to ruleset. The ruleset argument
1733# must be a ruleset name as specified in devfs.rules(5) file.
1734# Returns non-zero if it could not set it successfully.
1735#
1736devfs_set_ruleset()
1737{
1738 local devdir rs _me
1739 [ -n "$1" ] && eval rs=\$$1 || rs=
1740 [ -n "$2" ] && devdir="-m "$2"" || devdir=
1741 _me="devfs_set_ruleset"
1742
1743 if [ -z "$rs" ]; then
1744 warn "$_me: you must specify a ruleset number"
1745 return 1
1746 fi
1747 debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1748 if ! /sbin/devfs $devdir ruleset $rs; then
1749 warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1750 return 1
1751 fi
1752 return 0
1753}
1754
1755# devfs_apply_ruleset ruleset [dir]
1756# Apply ruleset number $ruleset to the devfs mountpoint $dir.
1757# The ruleset argument must be a ruleset name as specified
1758# in a devfs.rules(5) file. Returns 0 on success or non-zero
1759# if it could not apply the ruleset.
1760#
1761devfs_apply_ruleset()
1762{
1763 local devdir rs _me
1764 [ -n "$1" ] && eval rs=\$$1 || rs=
1765 [ -n "$2" ] && devdir="-m "$2"" || devdir=
1766 _me="devfs_apply_ruleset"
1767
1768 if [ -z "$rs" ]; then
1769 warn "$_me: you must specify a ruleset"
1770 return 1
1771 fi
1772 debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1773 if ! /sbin/devfs $devdir rule -s $rs applyset; then
1774 warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1775 return 1
1776 fi
1777 return 0
1778}
1779
1780# devfs_domount dir [ruleset]
1781# Mount devfs on dir. If ruleset is specified it is set
1782# on the mount-point. It must also be a ruleset name as specified
1783# in a devfs.rules(5) file. Returns 0 on success.
1784#
1785devfs_domount()
1786{
1787 local devdir rs _me
1788 devdir="$1"
1789 [ -n "$2" ] && rs=$2 || rs=
1790 _me="devfs_domount()"
1791
1792 if [ -z "$devdir" ]; then
1793 warn "$_me: you must specify a mount-point"
1794 return 1
1795 fi
1796 debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1797 if ! mount -t devfs dev "$devdir"; then
1798 warn "$_me: Unable to mount devfs on $devdir"
1799 return 1
1800 fi
1801 if [ -n "$rs" ]; then
1802 devfs_init_rulesets
1803 devfs_set_ruleset $rs $devdir
1804 devfs -m $devdir rule applyset
1805 fi
1806 return 0
1807}
1808
1809# Provide a function for normalizing the mounting of memory
1810# filesystems. This should allow the rest of the code here to remain
1811# as close as possible between 5-current and 4-stable.
1812# $1 = size
1813# $2 = mount point
1814# $3 = (optional) extra mdmfs flags
1815mount_md()
1816{
1817 if [ -n "$3" ]; then
1818 flags="$3"
1819 fi
1820 /sbin/mdmfs $flags -s $1 md $2
1821}
1822
1823# Code common to scripts that need to load a kernel module
1824# if it isn't in the kernel yet. Syntax:
1825# load_kld [-e regex] [-m module] file
1826# where -e or -m chooses the way to check if the module
1827# is already loaded:
1828# regex is egrep'd in the output from `kldstat -v',
1829# module is passed to `kldstat -m'.
1830# The default way is as though `-m file' were specified.
1831load_kld()
1832{
1833 local _loaded _mod _opt _re
1834
1835 while getopts "e:m:" _opt; do
1836 case "$_opt" in
1837 e) _re="$OPTARG" ;;
1838 m) _mod="$OPTARG" ;;
1839 *) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1840 esac
1841 done
1842 shift $(($OPTIND - 1))
1843 if [ $# -ne 1 ]; then
1844 err 3 'USAGE: load_kld [-e regex] [-m module] file'
1845 fi
1846 _mod=${_mod:-$1}
1847 _loaded=false
1848 if [ -n "$_re" ]; then
1849 if kldstat -v | egrep -q -e "$_re"; then
1850 _loaded=true
1851 fi
1852 else
1853 if kldstat -q -m "$_mod"; then
1854 _loaded=true
1855 fi
1856 fi
1857 if ! $_loaded; then
1858 if ! kldload "$1"; then
1859 warn "Unable to load kernel module $1"
1860 return 1
1861 else
1862 info "$1 kernel module loaded."
1863 fi
1864 else
1865 debug "load_kld: $1 kernel module already loaded."
1866 fi
1867 return 0
1868}
1869
1870# ltr str src dst [var]
1871# Change every $src in $str to $dst.
1872# Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1873# awk(1). If var is non-NULL, set it to the result.
1874ltr()
1875{
1876 local _str _src _dst _out _com _var
1877 _str="$1"
1878 _src="$2"
1879 _dst="$3"
1880 _var="$4"
1881 _out=""
1882
1883 local IFS="${_src}"
1884 for _com in ${_str}; do
1885 if [ -z "${_out}" ]; then
1886 _out="${_com}"
1887 else
1888 _out="${_out}${_dst}${_com}"
1889 fi
1890 done
1891 if [ -n "${_var}" ]; then
1892 setvar "${_var}" "${_out}"
1893 else
1894 echo "${_out}"
1895 fi
1896}
1897
1898# Creates a list of providers for GELI encryption.
1899geli_make_list()
1900{
1901 local devices devices2
1902 local provider mountpoint type options rest
1903
1904 # Create list of GELI providers from fstab.
1905 while read provider mountpoint type options rest ; do
1906 case ":${options}" in
1907 :*noauto*)
1908 noauto=yes
1909 ;;
1910 *)
1911 noauto=no
1912 ;;
1913 esac
1914
1915 case ":${provider}" in
1916 :#*)
1917 continue
1918 ;;
1919 *.eli)
1920 # Skip swap devices.
1921 if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
1922 continue
1923 fi
1924 devices="${devices} ${provider}"
1925 ;;
1926 esac
1927 done < /etc/fstab
1928
1929 # Append providers from geli_devices.
1930 devices="${devices} ${geli_devices}"
1931
1932 for provider in ${devices}; do
1933 provider=${provider%.eli}
1934 provider=${provider#/dev/}
1935 devices2="${devices2} ${provider}"
1936 done
1937
1938 echo ${devices2}
1939}
1940
1941# Find scripts in local_startup directories that use the old syntax
1942#
1943find_local_scripts_old() {
1944 zlist=''
1945 slist=''
1946 for dir in ${local_startup}; do
1947 if [ -d "${dir}" ]; then
1948 for file in ${dir}/[0-9]*.sh; do
1949 grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1950 continue
1951 zlist="$zlist $file"
1952 done
1953 for file in ${dir}/[!0-9]*.sh; do
1954 grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1955 continue
1956 slist="$slist $file"
1957 done
1958 fi
1959 done
1960}
1961
1962find_local_scripts_new() {
1963 local_rc=''
1964 for dir in ${local_startup}; do
1965 if [ -d "${dir}" ]; then
1966 for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
1967 case "$file" in
1968 *.sample) ;;
1969 *) if [ -x "$file" ]; then
1970 local_rc="${local_rc} ${file}"
1971 fi
1972 ;;
1973 esac
1974 done
1975 fi
1976 done
1977}
1978
1979# check_required_{before|after} command
1980# Check for things required by the command before and after its precmd,
1981# respectively. The two separate functions are needed because some
1982# conditions should prevent precmd from being run while other things
1983# depend on precmd having already been run.
1984#
1985check_required_before()
1986{
1987 local _f
1988
1989 case "$1" in
1990 start)
1991 for _f in $required_vars; do
1992 if ! checkyesno $_f; then
1993 warn "\$${_f} is not enabled."
1994 if [ -z "$rc_force" ]; then
1995 return 1
1996 fi
1997 fi
1998 done
1999
2000 for _f in $required_dirs; do
2001 if [ ! -d "${_f}/." ]; then
2002 warn "${_f} is not a directory."
2003 if [ -z "$rc_force" ]; then
2004 return 1
2005 fi
2006 fi
2007 done
2008
2009 for _f in $required_files; do
2010 if [ ! -r "${_f}" ]; then
2011 warn "${_f} is not readable."
2012 if [ -z "$rc_force" ]; then
2013 return 1
2014 fi
2015 fi
2016 done
2017 ;;
2018 esac
2019
2020 return 0
2021}
2022
2023check_required_after()
2024{
2025 local _f _args
2026
2027 case "$1" in
2028 start)
2029 for _f in $required_modules; do
2030 case "${_f}" in
2031 *~*) _args="-e ${_f#*~} ${_f%%~*}" ;;
2032 *:*) _args="-m ${_f#*:} ${_f%%:*}" ;;
2033 *) _args="${_f}" ;;
2034 esac
2035 if ! load_kld ${_args}; then
2036 if [ -z "$rc_force" ]; then
2037 return 1
2038 fi
2039 fi
2040 done
2041 ;;
2042 esac
2043
2044 return 0
2045}
2046
2047# check_jail mib
2048# Return true if security.jail.$mib exists and set to 1.
2049
2050check_jail()
2051{
2052 local _mib _v
2053
2054 _mib=$1
2055 if _v=$(${SYSCTL_N} "security.jail.$_mib" 2> /dev/null); then
2056 case $_v in
2057 1) return 0;;
2058 esac
2059 fi
2060 return 1
2061}
2062
2063# check_kern_features mib
2064# Return existence of kern.features.* sysctl MIB as true or
2065# false. The result will be cached in $_rc_cache_kern_features_
2066# namespace. "0" means the kern.features.X exists.
2067
2068check_kern_features()
2069{
2070 local _v
2071
2072 [ -n "$1" ] || return 1;
2073 eval _v=\$_rc_cache_kern_features_$1
2074 [ -n "$_v" ] && return "$_v";
2075
2076 if ${SYSCTL_N} kern.features.$1 > /dev/null 2>&1; then
2077 eval _rc_cache_kern_features_$1=0
2078 return 0
2079 else
2080 eval _rc_cache_kern_features_$1=1
2081 return 1
2082 fi
2083}
2084
2085# check_namevarlist var
2086# Return "0" if ${name}_var is reserved in rc.subr.
2087
2088_rc_namevarlist="program chroot chdir env flags fib nice user group groups prepend"
2089check_namevarlist()
2090{
2091 local _v
2092
2093 for _v in $_rc_namevarlist; do
2094 case $1 in
2095 $_v) return 0 ;;
2096 esac
2097 done
2098
2099 return 1
2100}
2101
2102# _echoonce var msg mode
2103# mode=0: Echo $msg if ${$var} is empty.
2104# After doing echo, a string is set to ${$var}.
2105#
2106# mode=1: Echo $msg if ${$var} is a string with non-zero length.
2107#
2108_echoonce()
2109{
2110 local _var _msg _mode
2111 eval _var=\$$1
2112 _msg=$2
2113 _mode=$3
2114
2115 case $_mode in
2116 1) [ -n "$_var" ] && echo "$_msg" ;;
2117 *) [ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
2118 esac
2119}
2120
2121fi # [ -z "${_rc_subr_loaded}" ]
2122
2123_rc_subr_loaded=:
2124
2125. "${LIB}/ioh-cmd"
2126#!/bin/sh
2127
2128# Check whether a given command requires root
2129__root_req_cmd () {
2130 case "$1" in
2131 setup|fetchiso|fetch|cpiso|renameiso|rmiso|fetchfw|cpfw|renamefw|rmfw|create|install|load\
2132 |boot|start|uefi|stop|forcekill|scram|destroy|rename|delete|set|rmpci|fix-bargs|add|remove\
2133 |resize|disks|snap|roll|clone|export|console|conreset)
2134 return 0
2135 ;;
2136 *)
2137 return 1
2138 ;;
2139 esac
2140}
2141
2142# Process command line
2143__parse_cmd () {
2144 while [ $# -gt 0 ] ; do
2145 case "$1" in
2146 version)
2147 __version
2148 exit
2149 ;;
2150 setup)
2151 __setup "$@"
2152 exit
2153 ;;
2154 list)
2155 __guest_list "$2"
2156 exit
2157 ;;
2158 info)
2159 __guest_info "$@"
2160 exit
2161 ;;
2162 isolist)
2163 __iso_list
2164 exit
2165 ;;
2166 fwlist)
2167 __firmware_list
2168 exit
2169 ;;
2170 fetchiso|fetch)
2171 __iso_fetch "$@"
2172 exit
2173 ;;
2174 cpiso)
2175 __iso_copy "$@"
2176 exit
2177 ;;
2178 renameiso)
2179 __iso_rename "$@"
2180 exit
2181 ;;
2182 rmiso)
2183 __iso_delete "$@"
2184 exit
2185 ;;
2186 fetchfw)
2187 __firmware_fetch "$@"
2188 exit
2189 ;;
2190 cpfw)
2191 __firmware_copy "$@"
2192 exit
2193 ;;
2194 renamefw)
2195 __firmware_rename "$@"
2196 exit
2197 ;;
2198 rmfw)
2199 __firmware_delete "$@"
2200 exit
2201 ;;
2202 create)
2203 __guest_create "$@"
2204 exit
2205 ;;
2206 install)
2207 __guest_install "$@"
2208 exit
2209 ;;
2210 load)
2211 __guest_load "$2" "$3"
2212 exit
2213 ;;
2214 boot)
2215 __guest_boot "$2" "$3" "$4"
2216 exit
2217 ;;
2218 start)
2219 __guest_start "$@"
2220 exit
2221 ;;
2222 uefi)
2223 __guest_uefi "$@"
2224 exit
2225 ;;
2226 stop)
2227 __guest_stop "$@"
2228 exit
2229 ;;
2230 forcekill)
2231 __guest_forcekill "$@"
2232 exit
2233 ;;
2234 scram)
2235 __guest_scram
2236 exit
2237 ;;
2238 destroy)
2239 __guest_destroy "$@"
2240 exit
2241 ;;
2242 rename)
2243 __guest_rename "$@"
2244 exit
2245 ;;
2246 delete)
2247 __guest_delete "$@"
2248 exit
2249 ;;
2250 set)
2251 __zfs_set "$@"
2252 exit
2253 ;;
2254 get)
2255 __zfs_get "$@"
2256 exit
2257 ;;
2258 rmpci)
2259 __zfs_rmpci "$@"
2260 exit
2261 ;;
2262 getall)
2263 __zfs_getall "$@"
2264 exit
2265 ;;
2266 fix-bargs)
2267 __fixbargs "$@"
2268 exit
2269 ;;
2270 add)
2271 __disk_add "$@"
2272 exit
2273 ;;
2274 remove)
2275 __disk_remove "$@"
2276 exit
2277 ;;
2278 resize)
2279 __disk_resize "$@"
2280 exit
2281 ;;
2282 disks)
2283 __disk_disks "$@"
2284 exit
2285 ;;
2286 snap)
2287 __zfs_snapguest "$@"
2288 exit
2289 ;;
2290 roll)
2291 __zfs_rollguest "$@"
2292 exit
2293 ;;
2294 clone)
2295 __zfs_cloneguest "$@"
2296 exit
2297 ;;
2298 export)
2299 __zfs_exportguest "$@"
2300 exit
2301 ;;
2302 snaplist)
2303 __zfs_snaplist
2304 exit
2305 ;;
2306 taplist)
2307 __tap_list
2308 exit
2309 ;;
2310 activetaps)
2311 __tap_active_list
2312 exit
2313 ;;
2314 conlist)
2315 __console_list
2316 exit
2317 ;;
2318 console)
2319 __console_console "$@"
2320 exit
2321 ;;
2322 conreset)
2323 __console_reset
2324 exit
2325 ;;
2326 help|-h)
2327 __help
2328 exit
2329 ;;
2330 *)
2331 __unrecognised "$@"
2332 exit 1
2333 ;;
2334 esac
2335 shift
2336 done
2337}
2338
2339# Informs user that command is unrecognised.
2340__unrecognised() {
2341 echo "'$1' is not a valid command!"
2342 echo "Try 'iohyve help' for more info."
2343}
2344. "${LIB}/ioh-setup"
2345#!/bin/sh
2346
2347# Setup iohyve
2348__setup() {
2349 shift 1
2350 local args="$@"
2351 local poolval
2352 local kmodval
2353 local netval
2354
2355 for arg in $args; do
2356 local prop="$(echo $arg | cut -d '=' -f1)"
2357 local val="$(echo $arg | cut -d '=' -f2)"
2358 if [ $prop = "pool" ]; then
2359 poolval=$val
2360 elif [ $prop = "kmod" ]; then
2361 kmodval=$val
2362 elif [ $prop = "net" ]; then
2363 netval=$val
2364 fi
2365
2366 done
2367
2368 # Run commands in correct order, so that the kernel modules are loaded
2369 # before the network is setup
2370 if [ -n "$poolval" ]; then
2371 __setup_pool $poolval
2372 fi
2373 if [ -n "$kmodval" ]; then
2374 __load_kernel_modules $kmodval
2375 fi
2376 if [ -n "$netval" ]; then
2377 __setup_network $netval
2378 fi
2379}
2380
2381__setup_pool() {
2382 local pool="$1"
2383 if ! zfs list ${pool}/iohyve > /dev/null 2>&1; then
2384 echo "Setting up iohyve pool..."
2385 zfs create $pool/iohyve
2386 # iohyve is already setup on a pool
2387 if [ -d /iohyve/ISO ]; then
2388 echo "Secondary pool set up..."
2389 zfs set mountpoint="/iohyve/$pool" $pool/iohyve
2390 # iohyve is not set up yet
2391 else
2392 zfs set mountpoint="/iohyve" $pool/iohyve
2393 zfs create $pool/iohyve/ISO
2394 zfs create $pool/iohyve/Firmware
2395 fi
2396 else
2397 echo "iohyve already exists on $pool"
2398 fi
2399 # Checks to see if on FreeNAS
2400 # The web UI references this file to display the version
2401 if [ -e /etc/version ]; then
2402 local OS=$( cat /etc/version | cut -d - -f1 )
2403 if [ "$OS" = "FreeNAS" ]; then
2404 setup_freenas $val
2405 fi
2406 fi
2407}
2408
2409__setup_freenas() {
2410 local val=$1
2411 echo "On FreeNAS installation."
2412 echo "Checking for symbolic link to /iohyve from /mnt/iohyve..."
2413 if [ -d /mnt/iohyve ]; then
2414 if [ ! -e /iohyve ]; then
2415 ln -s /mnt/iohyve /iohyve
2416 if [ -L /iohyve ]; then
2417 echo "Symbolic link to /iohyve from /mnt/iohyve successfully created."
2418 else
2419 echo "Failed to create symbolic link."
2420 echo "Please manually do so by running the following as root:"
2421 echo "# ln -s /mnt/iohyve /iohyve"
2422 fi
2423 elif [ -L /iohyve ]; then
2424 echo "Symbolic link to /iohyve already exists."
2425 fi
2426 elif [ "$val" = "freenas-boot" ] && [ -d /iohyve ]; then
2427 echo "Symbolic link not needed. /iohyve exists."
2428 echo "iohyve is installed on the freenas-boot pool."
2429 echo "This is not recommended configuration."
2430 else
2431 echo "iohyve does not seem to be setup."
2432 fi
2433}
2434
2435__load_kernel_modules() {
2436 local val=$1
2437 if [ $val = "1" ]; then
2438 echo "Loading kernel modules..."
2439 local modulelist
2440 if ! $(kldstat -q -m vmm); then
2441 modulelist="$modulelist vmm"
2442 fi
2443 if ! $(kldstat -q -m nmdm); then
2444 modulelist="$modulelist nmdm"
2445 fi
2446 if ! $(kldstat -q -m if_bridge); then
2447 modulelist="$modulelist if_bridge"
2448 fi
2449 if ! $(kldstat -q -m if_tap); then
2450 modulelist="$modulelist if_tap"
2451 fi
2452 # Load all modules together
2453 if [ "$modulelist" ]; then
2454 kldload $modulelist
2455 fi
2456 elif [ $val = "0" ]; then
2457 echo "Unloading kernel modules..."
2458 local modulelist
2459 if $(kldstat -q -m vmm); then
2460 modulelist="$modulelist vmm"
2461 fi
2462 if $(kldstat -q -m nmdm); then
2463 modulelist="$modulelist nmdm"
2464 fi
2465 if $(kldstat -q -m if_bridge); then
2466 modulelist="$modulelist if_bridge"
2467 fi
2468 if $(kldstat -q -m if_tap); then
2469 modulelist="$modulelist if_tap"
2470 fi
2471 # Unload all modules together
2472 if [ "$modulelist" ]; then
2473 kldunload $modulelist
2474 fi
2475 else
2476 echo "Improper syntax"
2477 echo "kmod=1 to load modules"
2478 echo "kmod=0 to unload modules"
2479 fi
2480}
2481
2482__setup_network() {
2483 local iface=$1
2484 local bridgeif="$('ifconfig' -l | grep -F "bridge0" | cut -c1)"
2485 if [ -z $bridgeif ]; then
2486 echo "Setting up bridge0 on $iface..."
2487 if ! sysctl net.link.tap.up_on_open=1 > /dev/null 2>&1; then
2488 echo "cannot set 'net.link.tap.up_on_open': is if_tap loaded?"
2489 fi
2490 ifconfig bridge0 create descr "iohyve-bridge" addm $iface up
2491 else
2492 echo "bridge0 is already enabled on this machine..."
2493 local sysctlexist
2494 if ! sysctlexist="$(sysctl -n net.link.tap.up_on_open 2> /dev/null)"; then
2495 echo "cannot set 'net.link.tap.up_on_open': is if_tap loaded?"
2496 return 1
2497 fi
2498
2499 if [ $sysctlexist = "0" ]; then
2500 echo "Setting up correct sysctl value..."
2501 sysctl net.link.tap.up_on_open=1
2502 else
2503 echo "sysctl already setup properly as well..."
2504 fi
2505 fi
2506}
2507. "${LIB}/ioh-zfs"
2508#!/bin/sh
2509
2510# Set ZFS properties
2511__zfs_set() {
2512 local name="$2"
2513 if [ -z $3 ]; then
2514 printf "missing argument\nusage:\n"
2515 printf "\tset <name> <property=value> ...\n"
2516 exit 1
2517 fi
2518 local pool="$(zfs list -H -t volume | grep iohyve/$name | cut -d '/' -f 1 | head -n1)"
2519 shift 2
2520 for arg in "$@"; do
2521 local prop="$(echo $arg | cut -d '=' -f1)"
2522 local val="$(echo $arg | cut -d '=' -f2)"
2523 if [ $prop = "bargs" ]; then
2524 local sval="$(echo $val | cut -d '"' -f2 | sed -e 's/ /_/g')"
2525 echo "Setting $name $prop=$val..."
2526 zfs set iohyve:$prop=$sval $pool/iohyve/$name
2527 elif [ $prop = "description" ]; then
2528 local sval="$(echo $val | cut -d '"' -f2)"
2529 echo "Setting $name $prop=$val..."
2530 zfs set "iohyve:$prop=$sval" $pool/iohyve/$name
2531 else
2532 echo "Setting $name $prop=$val..."
2533 zfs set iohyve:$prop=$val $pool/iohyve/$name
2534 fi
2535 done
2536}
2537
2538# Get ZFS props
2539__zfs_get() {
2540 local name="$2"
2541 local prop="$3"
2542 if [ -z $prop ]; then
2543 printf "missing argument\nusage:\n"
2544 printf "\tget <name> <prop>\n"
2545 exit 1
2546 fi
2547 local pool="$(zfs list -H -t volume | grep iohyve/$name | cut -d '/' -f 1 | head -n1)"
2548 echo "Getting $name prop $prop..."
2549 zfs get -H -o value iohyve:$prop $pool/iohyve/$name
2550}
2551
2552# Remove a PCIDEV property
2553__zfs_rmpci() {
2554 local flagone="$2"
2555 local flagtwo="$3"
2556 local flagthree="$4"
2557 if [ $flagone = "-f" ]; then
2558 if [ -z $flagthree ]; then
2559 printf "missing argument\nusage:\n"
2560 printf "\trmpci [-f] <name> <pcidev:N>\n"
2561 exit 1
2562 fi
2563 echo "Removing $flagthree from $flagtwo"
2564 local pciprop="$(echo "$flagthree" | grep pcidev:)"
2565 local pool="$(zfs list -H -t volume | grep $flagtwo | cut -d '/' -f 1 | head -n1)"
2566 # Make sure it's a valid pcidev property as to not shoot foot
2567 if [ -z $pciprop ]; then
2568 echo "Not a valid PCIDEV property"
2569 else
2570 zfs inherit -r iohyve:$flagthree $pool/iohyve/$flagtwo
2571 fi
2572 else
2573 if [ -z $flagtwo ]; then
2574 printf "missing argument\nusage:\n"
2575 printf "\trmpci [-f] <name> <pcidev:N>\n"
2576 exit 1
2577 fi
2578 local pciprop="$(echo "$flagtwo" | grep pcidev:)"
2579 local pool="$(zfs list -H -t volume | grep $flagone | cut -d '/' -f 1 | head -n1)"
2580 # Make sure it's a valid pcidev property as to not shoot foot
2581 if [ -z $pciprop ]; then
2582 echo "Not a valid PCIDEV property"
2583 else
2584 read -p "Are you sure you want to remove $flagtwo [Y/N]? " an </dev/tty
2585 case "$an" in
2586 y|Y) zfs inherit -r iohyve:$flagtwo $pool/iohyve/$flagone
2587 ;;
2588 *) echo "Not removed..."
2589 ;;
2590 esac
2591 fi
2592 fi
2593}
2594
2595# Get all ZFS props
2596__zfs_getall() {
2597 local name="$2"
2598 if [ -z $name ]; then
2599 printf "missing argument\nusage:\n"
2600 printf "\tgetall <name>\n"
2601 exit 1
2602 fi
2603 local pool="$(zfs list -H -t volume | grep iohyve/$name | grep disk0 | cut -d '/' -f 1 | head -n1)"
2604 echo "Getting $name iohyve properties..."
2605 zfs get -o property,value all $pool/iohyve/$name | grep iohyve: | sort | sed -e 's/iohyve://g'
2606}
2607
2608# Snapshot a guest
2609__zfs_snapguest() {
2610 local fullsnap="$2"
2611 local name="$(echo $fullsnap | cut -d '@' -f1)"
2612 if [ -z $name ] || [ -z "$(echo $fullsnap | grep '@')" ]; then
2613 printf "missing argument\nusage:\n"
2614 printf "\tsnap <name>@<snap>\n"
2615 exit 1
2616 fi
2617 local pool="$(zfs list -H -t volume | grep iohyve/$name | grep disk0 | cut -d '/' -f 1 | head -n1)"
2618 echo "Taking snapshot $fullsnap"
2619 # Check if guest exists
2620 if [ -d /iohyve/$pool/$name ] || [ -d /iohyve/$name ]; then
2621 zfs snap -r $pool/iohyve/$fullsnap
2622 else
2623 echo "Not a valid guest name"
2624 fi
2625}
2626
2627# Rollback guest
2628__zfs_rollguest() {
2629 local fullsnap="$2"
2630 local name="$(echo $fullsnap | cut -d '@' -f1)"
2631 local pool="$(zfs list -H -t volume | grep iohyve/$name | grep disk0 | cut -d '/' -f 1 | head -n1)"
2632 local snap="$(echo $fullsnap | cut -d '@' -f2)"
2633 if [ -z $snap ] || [ -z "$(echo $fullsnap | grep '@')" ]; then
2634 printf "missing argument\nusage:\n"
2635 printf "\troll <name>@<snap>\n"
2636 exit 1
2637 fi
2638 local disklist="$(zfs list -H | grep iohyve/$name | grep disk | cut -f1 | cut -d '/' -f4-)"
2639 # Check if guest exists
2640 echo "Rolling back to $fullsnap"
2641 if [ -d /iohyve/$pool/$name ] || [ -d /iohyve/$name ]; then
2642 # Check to make sure guest isn't running
2643 local running=$(pgrep -fx "bhyve: ioh-$name")
2644 if [ -z $running ]; then
2645 zfs rollback -rR $pool/iohyve/$fullsnap
2646 for disk in $disklist ; do
2647 zfs rollback -rR $pool/iohyve/$name/$disk@$snap
2648 done
2649 else
2650 echo "Please stop the guest first"
2651 fi
2652 else
2653 echo "Not a valid guest name"
2654 fi
2655}
2656
2657# Clone a guest
2658__zfs_cloneguest() {
2659 local flag="$2"
2660 local name="$2"
2661 local cname="$3"
2662 if [ "$flag" == "-r" ]; then
2663 name="$3"
2664 cname="$4"
2665
2666 if [ -z $cname ]; then
2667 printf "missing argument\nusage:\n"
2668 printf "\tclone <name> <clonename>\n"
2669 exit 1
2670 fi
2671
2672 local description="$(date | sed -e 's/ /_/g')"
2673 local pool="$(zfs list -H -t volume | grep iohyve/$name | grep disk0 | cut -d '/' -f 1 | head -n1)"
2674 # Check if guest exists
2675 echo "Cloning $name to $cname"
2676 if [ -d /iohyve/$pool/$name ] || [ -d /iohyve/$name ]; then
2677 # Take snapshot
2678 zfs snap -r $pool/iohyve/$name@$cname
2679 # zfs send that snap and desendants then receive to cname
2680 zfs send -R $pool/iohyve/$name@$cname | \
2681 zfs recv $pool/iohyve/$cname
2682 # clean up
2683 zfs destroy -rR $pool/iohyve/$name@$cname
2684 zfs destroy -rR $pool/iohyve/$cname@$cname
2685 # rename the guest
2686 zfs set iohyve:name=$cname $pool/iohyve/$cname
2687 zfs set iohyve:description=$description $pool/iohyve/$cname
2688 # change con and tap properties to next available if -r is specified
2689 if [ "$flag" == "-r" ]; then
2690 local guestlist="$(zfs list -H -o name -t volume | grep iohyve | cut -d'/' -f1-3)"
2691 listtaps(){
2692 for i in $guestlist ; do
2693 local tapprop="$(zfs get -H -o value iohyve:tap $i)"
2694 printf $tapprop'\n'
2695 done
2696 }
2697 local taplast="$(listtaps | sort -V | cut -c4- | tail -n1)"
2698 if [ -z $taplast ]; then
2699 local tap='0'
2700 else
2701 local tap="$(expr $taplast + 1)"
2702 fi
2703 listcons(){
2704 for i in $guestlist ; do
2705 local conprop="$(zfs get -H -o value iohyve:con $i)"
2706 printf $conprop'\n'
2707 done
2708 }
2709 local conlast="$(listcons | sort -V | cut -c5- | tail -n1)"
2710 if [ -z $conlast ]; then
2711 local con='0'
2712 else
2713 local con="$(expr $conlast + 1)"
2714 fi
2715
2716 zfs set iohyve:tap=tap$tap $pool/iohyve/$cname
2717 zfs set iohyve:con=nmdm$con $pool/iohyve/$cname
2718 fi
2719 fi
2720 else
2721 echo "Not a valid guest name"
2722 fi
2723}
2724
2725# Export Guest
2726__zfs_exportguest() {
2727 local name="$2"
2728 if [ -z $name ]; then
2729 printf "missing argument\nusage:\n"
2730 printf "\texport <name>\n"
2731 exit 1
2732 fi
2733 local pool="$(zfs list -H -t volume | grep $name | grep disk0 | cut -d '/' -f 1 | head -n1)"
2734 local disklist="$(zfs list -H | grep iohyve | grep $name | grep disk | \
2735 cut -f1 | cut -d '/' -f4-)"
2736 # Check if guest exists
2737 echo "Exporting $name. Note this may take some time depending on the size."
2738 if [ -d /iohyve/$pool/$name ] || [ -d /iohyve/$name ]; then
2739 # Check to make sure guest isn't running
2740 local running=$(pgrep -fx "bhyve: ioh-$name")
2741 if [ -z $running ]; then
2742 # Create /tmp/iohyve/$name
2743 echo "Creating temp directory..."
2744 mkdir -p /tmp/iohyve/$name
2745 # Export Properties to file
2746 echo "Exporting properties..."
2747 zfs get -H -o property,value all $pool/iohyve/$name | grep iohyve: | sort | \
2748 sed -e 's/iohyve://g' | sed -e 's/ /=/g' > /tmp/iohyve/$name/properties.ucl
2749 # Write disks to file
2750 echo "Exporting disks..."
2751 for disk in $disklist ; do
2752 dd if=/dev/zvol/$pool/iohyve/$name/$disk of=/tmp/iohyve/$name/${disk}.img bs=1M
2753 done
2754 # Compress and add to archive
2755 echo "Compressing to archive..."
2756 tar -czf /iohyve/$name/$name.tar.gz -C /tmp/iohyve/$name/ .
2757 # Remove /tmp/iohyve/
2758 echo "Removing temp directory..."
2759 rm -fr /tmp/iohyve
2760 else
2761 echo "Please stop the guest first"
2762 fi
2763 else
2764 echo "Not a valid guest name"
2765 fi
2766}
2767
2768# List all the snapshots
2769__zfs_snaplist() {
2770 zfs list -H -t snap | grep iohyve | grep -v disk | cut -f1 | cut -d '/' -f3
2771}
2772
2773# Get PCI device config from zfs
2774__zfs_get_pcidev_conf() {
2775 local pool="$1"
2776 local oldifs=$IFS
2777 #local pci
2778 IFS=$'\n'
2779 for pcidev in $(zfs get -H -o property,value all $pool | grep iohyve:pcidev: | sort )
2780 do
2781 echo $pcidev | cut -f2-
2782 done
2783 IFS=$oldifs
2784}
2785. "${LIB}/ioh-console"
2786#!/bin/sh
2787
2788# List consoles in use
2789__console_list() {
2790 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2791 local guestlist="$(zfs list -H | grep iohyve | grep -v ISO | grep -v disk | grep -v Firmware | sed 1d | cut -f1 | cut -d '/' -f3)"
2792 (
2793 printf 'Guest\tConsole\n'
2794 for guest in $guestlist; do
2795 local con="$(zfs get -H -o value iohyve:con $pool/iohyve/$guest)"
2796 printf $guest'\t'$con'\n'
2797 done
2798 ) | column -t
2799}
2800
2801# Run console
2802__console_console() {
2803 local name="$2"
2804 if [ -z $name ]; then
2805 printf "missing argument\nusage:\n"
2806 printf "\tconsole <name>\n"
2807 exit 1
2808 fi
2809
2810 local pool="$(zfs list -H -t volume | grep iohyve/$name | grep disk0 | cut -d '/' -f 1-3 | head -n1)"
2811 local con="$(zfs get -H -o value iohyve:con $pool)"
2812 echo "Starting console on $name..."
2813 echo "~~. to escape console [uses cu(1) for console]"
2814 cu -l /dev/${con}B -s 9600
2815}
2816
2817# Reset all consoles. This kills the cu(1)
2818__console_reset() {
2819 killall cu
2820}
2821. "${LIB}/ioh-iso"
2822#!/bin/sh
2823
2824# List iso's
2825__iso_list() {
2826 echo "Listing ISO's..."
2827 zfs list -H | grep iohyve/ISO | cut -f 1 | cut -d '/' -f 4 | sed 1d
2828}
2829
2830
2831# Fetch ISO
2832__iso_fetch() {
2833 local url="$2"
2834 if [ -z $url ]; then
2835 printf "missing argument\nusage:\n"
2836 printf "\tfetchiso <URL>\n"
2837 exit 1
2838 fi
2839 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2840 local name="$(basename $2)"
2841 echo "Fetching $url..."
2842 zfs create $pool/iohyve/ISO/$name
2843 fetch $url -o /iohyve/ISO/$name
2844}
2845
2846# Copy ISO from local machine
2847__iso_copy() {
2848 local loc="$2"
2849 if [ -z $loc ]; then
2850 printf "missing argument\nusage:\n"
2851 printf "\tcpiso <path>\n"
2852 exit 1
2853 fi
2854 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2855 local name="$(basename $loc)"
2856 echo "Copying $name from $loc..."
2857 zfs create $pool/iohyve/ISO/$name
2858 cp $loc /iohyve/ISO/$name
2859}
2860
2861# Rename an ISO
2862__iso_rename() {
2863 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2864 local iso="$2"
2865 local name="$3"
2866 if [ -z $name ]; then
2867 printf "missing argument\nusage:\n"
2868 printf "\trenameiso <ISO> <newname>\n"
2869 exit 1
2870 fi
2871 echo "Renaming ISO $2 to $3..."
2872 mv /iohyve/ISO/$iso/$iso /iohyve/ISO/$iso/$name
2873 zfs rename $pool/iohyve/ISO/$iso $pool/iohyve/ISO/$name
2874}
2875
2876# Delete ISO
2877__iso_delete() {
2878 local name="$2"
2879 if [ -z $name ]; then
2880 printf "missing argument\nusage:\n"
2881 printf "\trmiso <name>\n"
2882 exit 1
2883 fi
2884 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2885 echo "Deleting $name..."
2886 zfs destroy -rR $pool/iohyve/ISO/$name
2887}
2888. "${LIB}/ioh-firmware"
2889#!/bin/sh
2890
2891# List Firmware
2892__firmware_list() {
2893 echo "Listing Firmware..."
2894 zfs list -H | grep iohyve/Firmware | cut -f1 | cut -d '/' -f 4 | sed 1d
2895}
2896
2897# Fetch Firmware
2898__firmware_fetch() {
2899 local url="$2"
2900 if [ -z $url ]; then
2901 printf "missing argument\nusage:\n"
2902 printf "\tfetchfw <URL>\n"
2903 exit 1
2904 fi
2905 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2906 local name="$(basename $2)"
2907 echo "Fetching $url..."
2908 zfs create $pool/iohyve/Firmware/$name
2909 fetch $url -o /iohyve/Firmware/$name
2910}
2911
2912# Copy Firmware from local machine
2913__firmware_copy() {
2914 local loc="$2"
2915 if [ -z $loc ]; then
2916 printf "missing argument\nusage:\n"
2917 printf "\tcpfw <path>\n"
2918 exit 1
2919 fi
2920 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2921 local name="$(basename $loc)"
2922 echo "Copying $name from $loc..."
2923 zfs create $pool/iohyve/Firmware/$name
2924 cp $loc /iohyve/Firmware/$name
2925}
2926
2927# Rename Firmware
2928__firmware_rename() {
2929 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2930 local fw="$2"
2931 local name="$3"
2932 if [ -z $name ]; then
2933 printf "missing argument\nusage:\n"
2934 printf "\trenamefw <firmware> <newname>\n"
2935 exit 1
2936 fi
2937 echo "Renaming Firmware $2 to $3..."
2938 mv /iohyve/Firmware/$fw/$fw /iohyve/Firmware/$fw/$name
2939 zfs rename $pool/iohyve/Firmware/$fw $pool/iohyve/Firmware/$name
2940}
2941
2942# Delete Firmware
2943__firmware_delete() {
2944 local name="$2"
2945 if [ -z $name ]; then
2946 printf "missing argument\nusage:\n"
2947 printf "\trmfw <firmware> <newname>\n"
2948 exit 1
2949 fi
2950 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
2951 echo "Deleting $name..."
2952 zfs destroy -rR $pool/iohyve/Firmware/$name
2953}
2954. "${LIB}/ioh-guest"
2955#!/bin/sh
2956
2957# List Guests
2958__guest_list() {
2959 local flags="$1"
2960 (
2961 printf "%s^%s^%s^%s^%s\n" "Guest" "VMM?" "Running" "rcboot?" "Description"
2962 local guests="$(zfs get -H -s local -o name,value -t filesystem iohyve:name | tr '\t' ',')"
2963 for guest in $guests; do
2964 local dataset="$(echo $guest | cut -f1 -d,)"
2965 local name="$(echo $guest | cut -f2 -d,)"
2966
2967 local vmm="/dev/vmm/ioh-$name"
2968 if [ -e $vmm ]; then
2969 vmm="YES"
2970 else
2971 vmm="NO"
2972 fi
2973 local running=$(pgrep -fx "bhyve: ioh-$name")
2974 if [ -z $running ]; then
2975 running="NO"
2976 else
2977 running="YES"
2978 fi
2979 local boot="$(zfs get -H -o value iohyve:boot $dataset)"
2980 if [ $boot = '1' ]; then
2981 boot="YES"
2982 else
2983 boot="NO"
2984 fi
2985 local description="$(zfs get -H -o value iohyve:description $dataset)"
2986 printf "%s^%s^%s^%s^%s\n" "$name" "$vmm" "$running" "$boot" "$description"
2987 done
2988 ) | column -ts^ | \
2989 (
2990 if [ "$flags" = '-l' ]
2991 then
2992 less
2993 else
2994 cat
2995 fi
2996 )
2997}
2998
2999# Display info about all guests.
3000__guest_info() {
3001 local flags="$@"
3002
3003 # Poll to see what pools have active guests
3004 local guests="$(zfs get -H -s local -o name,value -t filesystem iohyve:name | tr '\t' ',')"
3005
3006 ( # Begining of very large table of output.
3007 # Print common header
3008 printf "%s^%s^%s^%s^%s" "Guest" "Size" "CPU" "RAM" "Pool"
3009
3010 # Print headers for -v flag
3011 if [ -n "$(echo "$flags" | grep 'v')" ]; then
3012 printf "^%s^%s^%s^%s" "OS" "Loader" "Tap" "Con"
3013 fi
3014
3015 # Print headers for -s flag
3016 if [ -n "$(echo "$flags" | grep 's')" ]; then
3017 printf "^%s^%s^%s" "VMM?" "Running" "rcboot?"
3018 fi
3019
3020 # Print headers for -d flag
3021 if [ -n "$(echo "$flags" | grep 'd')" ]; then
3022 printf "^%s" "Description"
3023 fi
3024
3025 # Print new line for first guest.
3026 printf "\n"
3027
3028 # Poll to see which guests are on $pool
3029 # Spider through guests
3030 for guest in $guests; do
3031 local dataset="$(echo $guest | cut -f1 -d,)"
3032 local name="$(echo $guest | cut -f2 -d,)"
3033 local disks="$(zfs list -H -r -t volume -o name $dataset)"
3034 local pool="$(echo $dataset | cut -f1 -d/)"
3035
3036 # Poll variables for common section
3037 local cpu="$(zfs get -H -o value iohyve:cpu $dataset)"
3038 local ram="$(zfs get -H -o value iohyve:ram $dataset)"
3039
3040 # Print common section (guest, size, cpu, raml)
3041 printf "%s^-^%s^%s^%s" "$name" "$cpu" "$ram" "$pool"
3042
3043 # Get variable and print for verbose section (os, loader, tap, con)
3044 if [ -n "$(echo "$flags" | grep 'v')" ]; then
3045 local os="$(zfs get -H -o value iohyve:os $dataset)"
3046 local loader="$(zfs get -H -o value iohyve:loader $dataset)"
3047 local tap="$(zfs get -H -o value iohyve:tap $dataset)"
3048 local con="$(zfs get -H -o value iohyve:con $dataset)"
3049
3050 printf "^%s^%s^%s^%s" "$os" "$loader" "$tap" "$con"
3051 fi
3052
3053 # Get info, set variables, and print for status section (VMM, Running, rcboot)
3054 if [ -n "$(echo "$flags" | grep 's')" ]; then
3055 local vmm="/dev/vmm/ioh-$name"
3056 if [ -e $vmm ]; then
3057 vmm="YES"
3058 else
3059 vmm="NO"
3060 fi
3061 local running=$(pgrep -fx "bhyve: ioh-$name")
3062 if [ -z $running ]; then
3063 running="NO"
3064 else
3065 running="YES"
3066 fi
3067 local boot="$(zfs get -H -o value iohyve:boot $dataset)"
3068 if [ $boot = '1' ]; then
3069 boot="YES"
3070 else
3071 boot="NO"
3072 fi
3073
3074 printf "^%s^%s^%s" "$vmm" "$running" "$boot"
3075 fi
3076
3077 # Print description if flag set
3078 if [ -n "$(echo "$flags" | grep 'd')" ]; then
3079 local description="$(zfs get -H -o value iohyve:description $dataset)"
3080 printf "^%s" "$description"
3081 fi
3082
3083 # Print new line for next guest.
3084 printf "\n"
3085
3086 for disk in $disks; do
3087 local diskname="$(echo $disk | rev | cut -f1 -d/ | rev)"
3088 local size="$(zfs get -H -o value iohyve:size $disk)"
3089 printf "^%s^%s^-^-^%s" "$name/$diskname" "$size" "$pool"
3090 if [ -n "$(echo "$flags" | grep 'v')" ]; then
3091 printf "^-^-^-^-"
3092 fi
3093 if [ -n "$(echo "$flags" | grep 's')" ]; then
3094 printf "^-^-^-"
3095 fi
3096 if [ -n "$(echo "$flags" | grep 'd')" ]; then
3097 local description="$(zfs get -H -o value iohyve:description $disk)"
3098 printf "^%s" "$description"
3099 fi
3100 printf "\n"
3101 done
3102 done
3103 ) | column -ts^ | \
3104 (
3105 if [ -n "$(echo "$flags" | grep 'l')" ]
3106 then
3107 less
3108 else
3109 cat
3110 fi
3111 )
3112}
3113
3114# Create guest
3115__guest_create() {
3116 local name="$2"
3117 local pool="${4-$(zfs get -H -s local -o name -t filesystem iohyve:name | head -n1 | cut -f1 -d/)}"
3118 local size="$3"
3119 if [ -z $pool ]; then
3120 local pool="$(zfs list -H | grep /iohyve/ISO | cut -f1 -d/)"
3121 fi
3122 if [ -z $size ]; then
3123 printf "missing argument\nusage:\n"
3124 printf "\tcreate <name> <size> [pool]\n"
3125 exit 1
3126 fi
3127 local description="$(date)"
3128
3129 # Check if guest with this name already exists
3130 if [ -n "$(zfs get -H -o value -s local -t filesystem iohyve:name | grep ^$name$)" ]; then
3131 echo "Error: Guest with this name already exists"
3132 exit 1
3133 fi
3134
3135 local guestlist="$(zfs get -H -o name -t filesystem -s local iohyve:name)"
3136 listtaps(){
3137 for i in $guestlist ; do
3138 local tapprop="$(zfs get -H -o value iohyve:tap $i)"
3139 printf $tapprop'\n'
3140 done
3141 }
3142 local taplast="$(listtaps | sort -V | cut -c4- | tail -n1)"
3143 if [ -z $taplast ]; then
3144 local tap='0'
3145 else
3146 local tap="$(expr $taplast + 1)"
3147 fi
3148 listcons(){
3149 for i in $guestlist ; do
3150 local conprop="$(zfs get -H -o value iohyve:con $i)"
3151 printf $conprop'\n'
3152 done
3153 }
3154 local conlast="$(listcons | sort -V | cut -c5- | tail -n1)"
3155 if [ -z $conlast ]; then
3156 local con='0'
3157 else
3158 local con="$(expr $conlast + 1)"
3159 fi
3160 echo "Creating $name..."
3161 zfs create -o iohyve:name=$name \
3162 -o iohyve:size=$size \
3163 -o iohyve:ram=256M \
3164 -o iohyve:cpu=1 \
3165 -o iohyve:tap=tap$tap \
3166 -o iohyve:con=nmdm$con \
3167 -o iohyve:persist=1 \
3168 -o iohyve:boot=0 \
3169 -o iohyve:loader=bhyveload \
3170 -o iohyve:os=default \
3171 -o "iohyve:description=$description" \
3172 -o iohyve:bargs=-A_-H_-P \
3173 -o iohyve:vnc=NO \
3174 -o iohyve:vnc_ip=127.0.0.1 \
3175 -o iohvye:vnc_port=5900 \
3176 -o iohyve:vnc_w=800 \
3177 -o iohyve:vnc_h=600 \
3178 -o iohyve:vnc_wait=NO \
3179 -o iohyve:vnc_tablet=NO \
3180 $pool/iohyve/$name
3181
3182 zfs create -V $size -o volmode=dev $pool/iohyve/$name/disk0
3183
3184}
3185
3186# Install guest
3187__guest_install() {
3188 local name="$2"
3189 local iso="$3"
3190
3191 if [ -z $iso ]; then
3192 printf "missing argument\nusage:\n"
3193 printf "\tinstall <name> <ISO>\n"
3194 exit 1
3195 fi
3196
3197 if ! __guest_exist $name; then
3198 echo "guest $name doesn't exist"
3199 return 1
3200 fi
3201
3202 local dataset="$(zfs get -H -s local -o name,value -t filesystem iohyve:name | grep "$(printf '\t')$name$" | cut -f1)"
3203 local mountpoint="$(zfs get -H -o value mountpoint $dataset)"
3204 local loader="$(zfs get -H -o value iohyve:loader $dataset)"
3205 if [ $loader = "uefi" ]; then
3206 __guest_uefi "$name" "$iso"
3207 exit 0
3208 fi
3209 # Check if guest exists
3210 if [ -d $mountpoint ]; then
3211 # Check to make sure guest isn't running
3212 local running=$(pgrep -fx "bhyve: ioh-$name")
3213 if [ -z $running ]; then
3214 local ram="$(zfs get -H -o value iohyve:ram $dataset)"
3215 local con="$(zfs get -H -o value iohyve:con $dataset)"
3216 local cpu="$(zfs get -H -o value iohyve:cpu $dataset)"
3217 local bargexist="$(zfs get -H -o value iohyve:bargs $dataset)"
3218 local bargs="$(echo $bargexist | sed -e 's/_/ /g')"
3219 echo "Installing $name..."
3220 # Set install prop
3221 zfs set iohyve:install=yes $dataset
3222 # Load from CD
3223 __guest_load "$name" "/iohyve/ISO/$iso/$iso"
3224 # Prepare and start guest
3225 pci="$(__guest_prepare $name) ahci-cd,/iohyve/ISO/$iso/$iso"
3226 local pci_args=$(__guest_get_bhyve_cmd "$pci" )
3227 bhyve -c $cpu $bargs -m $ram $pci_args -lcom1,/dev/${con}A ioh-$name &
3228 else
3229 echo "Guest is already running."
3230 fi
3231 else
3232 echo "Not a valid guest name"
3233 fi
3234}
3235
3236# Load guest
3237__guest_load() {
3238 local name="$1"
3239 local media="$2"
3240
3241 if [ -z $media ]; then
3242 printf "missing argument\nusage:\n"
3243 printf "\tload <name> <path/to/bootdisk>\n"
3244 exit 1
3245 fi
3246
3247 if ! __guest_exist $name; then
3248 echo "guest $name doesn't exist"
3249 return 1
3250 fi
3251
3252 local disk="${3-$(zfs get -H -t volume -o name,value iohyve:name | grep "$(printf '\t')$name$" | cut -f1)}"
3253 local dataset="$(zfs get -H -o name,value -s local -t filesystem iohyve:name | grep "$(printf '\t')$name$" | cut -f1)"
3254 local ram="$(zfs get -H -o value iohyve:ram $dataset)"
3255 local con="$(zfs get -H -o value iohyve:con $dataset)"
3256 local loader="$(zfs get -H -o value iohyve:loader $dataset)"
3257 local install="$(zfs get -H -o value iohyve:install $dataset)"
3258 local os="$(zfs get -H -o value iohyve:os $dataset)"
3259 local autogrub="$(zfs get -H -o value iohyve:autogrub $dataset)"
3260 local bargexist="$(zfs get -H -o value iohyve:bargs $dataset)"
3261 local bargs="$(echo $bargexist | sed -e 's/_/ /g')"
3262 #Testing if -S is in the bargs settings. If then pass -S to bhyveload.
3263 local test_for_wire_memory="-S"
3264 case $bargs in
3265 *${test_for_wire_memory}*) local wire_memory="-S" ;;
3266 *) local wire_memory="" ;;
3267 esac
3268 if [ $loader = "grub-bhyve" ]; then
3269 echo "GRUB Process does not run in background...."
3270 echo "If your terminal appears to be hanging, check iohyve console $name in second terminal to complete GRUB process..."
3271 if [ $install = "yes" ]; then
3272 if [ $os = "openbsd59" ]; then
3273 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3274 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3275 printf 'kopenbsd -h com0 (cd0)/5.9/amd64/bsd.rd\nboot\n' > /iohyve/$name/grub.cfg
3276 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3277 elif [ $os = "openbsd58" ]; then
3278 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3279 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3280 printf 'kopenbsd -h com0 (cd0)/5.8/amd64/bsd.rd\nboot\n' > /iohyve/$name/grub.cfg
3281 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3282 elif [ $os = "openbsd57" ]; then
3283 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3284 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3285 printf 'kopenbsd -h com0 (cd0)/5.7/amd64/bsd.rd\nboot\n' > /iohyve/$name/grub.cfg
3286 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3287 elif [ $os = "netbsd" ]; then
3288 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3289 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3290 printf 'knetbsd -h -r cd0a (cd0)/netbsd\nboot\n' > /iohyve/$name/grub.cfg
3291 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3292 elif [ $os = "debian" ]; then
3293 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3294 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3295 grub-bhyve $wire_memory-m /iohyve/$name/device.map -r cd0 -c /dev/${con}A -M $ram ioh-$name
3296 elif [ $os = "d8lvm" ]; then
3297 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3298 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3299 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r cd0 -c /dev/${con}A -M $ram ioh-$name
3300 elif [ $os = "centos6" ] || [ $os = "centos7" ]; then
3301 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3302 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3303 printf 'linux (cd0)/isolinux/vmlinuz\ninitrd (cd0)/isolinux/initrd.img\nboot\n' > /iohyve/$name/grub.cfg
3304 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3305 elif [ $os = "arch" ]; then
3306 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3307 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3308 printf 'linux (cd0)/arch/boot/x86_64/vmlinuz archisobasedir=arch archisolabel=ARCH_'$(date +%Y%m)' ro\ninitrd (cd0)/arch/boot/x86_64/archiso.img\nboot\n' > /iohyve/$name/grub.cfg
3309 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3310 elif [ $os = "custom" ]; then
3311 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3312 else
3313 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3314 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3315 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r cd0 -c /dev/${con}A -M $ram ioh-$name
3316 fi
3317 elif [ $install = "no" ]; then
3318 if [ $os = "openbsd59" ]; then
3319 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3320 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3321 printf 'kopenbsd -h com0 -r sd0a (hd0,openbsd1)/bsd\nboot\n' > /iohyve/$name/grub.cfg
3322 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3323 elif [ $os = "openbsd58" ]; then
3324 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3325 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3326 printf 'kopenbsd -h com0 -r sd0a (hd0,openbsd1)/bsd\nboot\n' > /iohyve/$name/grub.cfg
3327 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3328 elif [ $os = "openbsd57" ]; then
3329 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3330 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3331 printf 'kopenbsd -h com0 -r sd0a (hd0,openbsd1)/bsd\nboot\n' > /iohyve/$name/grub.cfg
3332 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3333 elif [ $os = "netbsd" ]; then
3334 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3335 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3336 printf 'knetbsd -h -r wd0a (hd0,msdos1)/netbsd\nboot\n' > /iohyve/$name/grub.cfg
3337 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3338 elif [ $os = "debian" ]; then
3339 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3340 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3341 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r hd0,msdos1 -c /dev/${con}A -M $ram ioh-$name
3342 elif [ $os = "d8lvm" ]; then
3343 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3344 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3345 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r hd0,msdos1 -d /grub -c /dev/${con}A -M $ram ioh-$name
3346 elif [ $os = "centos6" ]; then
3347 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3348 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3349 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r hd0,msdos1 -d /grub -c /dev/${con}A -M $ram ioh-$name
3350 elif [ $os = "centos7" ]; then
3351 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3352 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3353 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r hd0,msdos1 -d /grub2 -c /dev/${con}A -M $ram ioh-$name
3354 elif [ $os = "custom" ]; then
3355 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r host -d /iohyve/$name -c /dev/${con}A -M $ram ioh-$name
3356 else
3357 printf '\(hd0\)\ /dev/zvol/'$disk'\n' > /iohyve/$name/device.map
3358 printf '\(cd0\)\ '$media'\n' >> /iohyve/$name/device.map
3359 grub-bhyve $wire_memory -m /iohyve/$name/device.map -r hd0,msdos1 -c /dev/${con}A -M $ram ioh-$name
3360 fi
3361 fi
3362 else
3363 bhyveload $wire_memory -m $ram -d $media -c /dev/${con}A ioh-$name
3364 fi
3365}
3366
3367# Boot guest
3368__guest_boot() {
3369 local name="$1"
3370 if [ -z $name ]; then
3371 printf "missing argument\nusage:\n"
3372 printf "\tboot <name> [runmode] [pcidevices]\n"
3373 exit 1
3374 fi
3375
3376 if ! __guest_exist $name; then
3377 echo "guest $name doesn't exist"
3378 return 1
3379 fi
3380
3381 # runmode (runonce/persist)
3382 # 0 = once
3383 # 1 = persist regular (stop if guest is powering off)
3384 # 2 = always persist (start again even if guest is powering off)
3385 local runmode="$2"
3386 local pci="$3"
3387 local dataset="$(zfs get -H -s local -o name,value -t filesystem iohyve:name | grep "$(printf '\t')$name$" | cut -f1)"
3388 local ram="$(zfs get -H -o value iohyve:ram $dataset)"
3389 local con="$(zfs get -H -o value iohyve:con $dataset)"
3390 local cpu="$(zfs get -H -o value iohyve:cpu $dataset)"
3391 local persist="$(zfs get -H -o value iohyve:persist $dataset)"
3392 local bargexist="$(zfs get -H -o value iohyve:bargs $dataset)"
3393 local bargs="$(echo $bargexist | sed -e 's/_/ /g')"
3394 # Set install prop
3395 zfs set iohyve:install=no $dataset
3396 # Generate list of bhyve -s commands for all devices
3397 local pci_args=$(__guest_get_bhyve_cmd "$pci" )
3398 # Handle the starting of the guest inside a spawned subshell so the guest
3399 # can be restarted automatically if the guest reboots or crashes
3400 local runstate="1"
3401 (
3402 while [ $runstate = "1" ]
3403 do
3404 __guest_load "$name" "/dev/zvol/$dataset/disk0"
3405 bhyve -c $cpu $bargs -m $ram $pci_args -lcom1,/dev/${con}A ioh-$name &
3406 local vmpid=$!
3407 wait $vmpid
3408 vmrc=$?
3409 sleep 5
3410 if [ $runmode == "0" ]; then
3411 runstate="0"
3412 elif [ $vmrc == "1" ] && [ $runmode != 2 ]; then
3413 # VM has been powered off
3414 runstate="0"
3415 else
3416 if [ $(zfs get -H -o value iohyve:persist $dataset) != 1 ]; then
3417 runstate="0"
3418 fi
3419 fi
3420 done
3421 bhyvectl --destroy --vm=ioh-$name
3422 # Resetting the flag so that a vm which we stopped by abusing zfs set/get
3423 # as as an IPC mechanism is persistent again next time we start it
3424 if [ -n "$persist" ]; then
3425 zfs set iohyve:persist="$persist" $dataset
3426 fi
3427 ) &
3428}
3429
3430__guest_prepare() {
3431 local name="$1"
3432 local dataset="$(zfs get -H -s local -o name,value -t filesystem iohyve:name | grep "$(printf '\t')$name$" | cut -f1)"
3433 local pci="$(__zfs_get_pcidev_conf $dataset)"
3434 # Setup tap if needed
3435 local listtap="$(zfs get -H -o value iohyve:tap $dataset)"
3436 for tap in $(echo $listtap | sed -n 1'p' | tr ',' '\n'); do
3437 if [ $tap ] && [ $tap != "-" ]; then
3438 local tapif="$(ifconfig -l | tr ' ' '\n' | grep -F -w $tap)"
3439 if [ -z $tapif ]; then
3440 # create tap interface
3441 ifconfig $tap create descr "iohyve-$name"
3442 ifconfig bridge0 addm $tap
3443 fi
3444 # Add a virtio-net pci device for the tap
3445 local mac="$(zfs get -H -o value iohyve:mac_$tap $dataset)"
3446 if [ $mac = "-" ]; then
3447 pci="$pci virtio-net,$tap"
3448 else
3449 pci="$pci virtio-net,${tap},mac=${mac}"
3450 fi
3451 fi
3452 done
3453 #Add disk as second PCI device
3454 pci="ahci-hd,/dev/zvol/$dataset/disk0 $pci"
3455 #Add Hostbridge and lpc as the first PCI devices
3456 pci="hostbridge lpc $pci"
3457 # return the list of pci devices
3458 echo $pci
3459}
3460
3461# Start guest (combine load and boot)
3462__guest_start() {
3463 local name="$2"
3464 if [ -z $name ]; then
3465 printf "missing argument\nusage:\n"
3466 printf "\tstart <name> [-s | -a]\n"
3467 exit 1
3468 fi
3469
3470 if ! __guest_exist $name; then
3471 echo "guest $name doesn't exist"
3472 return 1
3473 fi
3474
3475 local flag="$3"
3476 local pci=""
3477 local runmode="1"
3478 local dataset="$(zfs get -H -s local -o name,value -t filesystem iohyve:name | grep "$(printf '\t')$name$" | cut -f1)"
3479 local loader="$(zfs get -H -o value iohyve:loader $dataset)"
3480 # Check if loader is UEFI
3481 if [ $loader = "uefi" ]; then
3482 __guest_uefi "$name" "$flag"
3483 exit 0
3484 fi
3485 local mountpoint="$(zfs get -H -o value mountpoint $dataset)"
3486
3487 # Check if guest exists
3488 if [ -d $mountpoint ]; then
3489 # Check to make sure guest isn't running
3490 local running=$(pgrep -fx "bhyve: ioh-$name")
3491 if [ -z $running ]; then
3492 case "$flag" in
3493 -s) runmode="0" # single - start only once
3494 ;;
3495 -a) runmode="2" # always - persist regardless what
3496 ;;
3497 *) runmode="1" # persist - persists until guest is powering off
3498 ;;
3499 esac
3500 echo "Starting $name... (Takes 15 seconds for FreeBSD guests)"
3501 # Prepare and boot guest
3502 pci="$(__guest_prepare $name)"
3503 __guest_boot "$name" "$runmode" "$pci"
3504 else
3505 echo "Guest is already running."
3506 fi
3507 else
3508 echo "Not a valid guest name"
3509 fi
3510}
3511
3512# Start a UEFI enabled bhyve instance.
3513# This is experimental, use with caution.
3514__guest_uefi() {
3515 local name="$1"
3516 local media="$2"
3517
3518 if [ -z $name ]; then
3519 printf "missing argument\nusage:\n"
3520 printf "\tuefi <name> <ISO>\n"
3521 exit 1
3522 fi
3523
3524 if ! __guest_exist $name; then
3525 echo "guest $name doesn't exist"
3526 return 1
3527 fi
3528
3529 local dataset="$(zfs get -H -s local -o name,value -t filesystem iohyve:name | grep "$(printf '\t')$name$" | cut -f1)"
3530 local ram="$(zfs get -H -o value iohyve:ram $dataset)"
3531 local con="$(zfs get -H -o value iohyve:con $dataset)"
3532 local cpu="$(zfs get -H -o value iohyve:cpu $dataset)"
3533 local fw="$(zfs get -H -o value iohyve:fw $dataset)"
3534 local tap="$(zfs get -H -o value iohyve:tap $dataset)"
3535 local bargs="$(zfs get -H -o value iohyve:bargs $dataset | sed -e 's/_/ /g')"
3536 local vnc="$(zfs get -H -o value iohyve:vnc $dataset)"
3537 local vnc_ip="$(zfs get -H -o value iohyve:vnc_ip $dataset)"
3538 local vnc_port="$(zfs get -H -o value iohyve:vnc_port $dataset)"
3539 local vnc_w="$(zfs get -H -o value iohyve:vnc_w $dataset)"
3540 local vnc_h="$(zfs get -H -o value iohyve:vnc_h $dataset)"
3541 local vnc_wait="$(zfs get -H -o value iohyve:vnc_wait $dataset)"
3542 local vnc_tablet="$(zfs get -H -o value iohyve:vnc_tablet $dataset)"
3543 local pool="$(zfs list -H -t volume -o name | grep iohyve/$name | cut -d '/' -f1)"
3544 # Create tap if needed
3545 # check to see if tap is already created before attempting to create new tap interface
3546 local tapif="$(ifconfig -l | tr ' ' '\n' | grep -F -w $tap)"
3547 if [ -z $tapif ]; then
3548 # create tap interface
3549 ifconfig $tap create descr "iohyve-$name"
3550 ifconfig bridge0 addm $tap
3551 fi
3552 # Make sure everything is in order...
3553 if [ $fw = '-' ]; then
3554 echo "You must set a firmware file property to use UEFI..."
3555 exit 1
3556 fi
3557 local mountpoint="$(zfs get -H -o value mountpoint $dataset)"
3558 # Check if guest exists
3559 if [ -d $mountpoint ]; then
3560 # Check to make sure guest isn't running
3561 local running=$(pgrep -fx "bhyve: ioh-$name")
3562 if [ -z $running ]; then
3563 # Check for vnc
3564 if [ $vnc = "YES" ]; then
3565 # build vnc arguments
3566 if [ $vnc_wait = "YES" ]; then
3567 vncline="-s 11,fbuf,tcp=${vnc_ip}:${vnc_port},w=${vnc_w},h=${vnc_h},wait"
3568 else
3569 vncline="-s 11,fbuf,tcp=${vnc_ip}:${vnc_port},w=${vnc_w},h=${vnc_h}"
3570 fi
3571 # build tablet argument
3572 if [ $vnc_tablet = "YES" ]; then
3573 tabletline="-s 12,xhci,tablet"
3574 else
3575 tabletline=""
3576 fi
3577 bhyve -c $cpu $bargs -m $ram \
3578 -s 0,hostbridge \
3579 -s 3,ahci-cd,/iohyve/ISO/$media/$media \
3580 -s 4,ahci-hd,/dev/zvol/$dataset/disk0,sectorsize=512 \
3581 -s 10,virtio-net,$tap \
3582 $vncline \
3583 $tabletline \
3584 -s 31,lpc \
3585 -l com1,/dev/${con}A \
3586 -l bootrom,/iohyve/Firmware/$fw/$fw \
3587 ioh-$name &
3588 else
3589 bhyve -c $cpu $bargs -m $ram \
3590 -s 0,hostbridge \
3591 -s 3,ahci-cd,/iohyve/ISO/$media/$media \
3592 -s 4,ahci-hd,/dev/zvol/$dataset/disk0,sectorsize=512 \
3593 -s 10,virtio-net,$tap \
3594 -s 31,lpc \
3595 -l com1,/dev/${con}A \
3596 -l bootrom,/iohyve/Firmware/$fw/$fw \
3597 ioh-$name &
3598 fi
3599 else
3600 echo "Guest is already running."
3601 fi
3602 else
3603 echo "Not a valid guest name"
3604 fi
3605}
3606
3607# Gracefully stop a guest
3608__guest_stop() {
3609 local name="$2"
3610 if [ -z $name ]; then
3611 printf "missing argument\nusage:\n"
3612 printf "\tstop <name>\n"
3613 exit 1
3614 fi
3615
3616 local pid=$(pgrep -fx "bhyve: ioh-$name")
3617 echo "Stopping $name..."
3618# zfs set iohyve:persist=0 $pool/iohyve/$name
3619 if [ -n "$pid" ]; then
3620 kill $pid
3621 else
3622 echo "$name not running"
3623 fi
3624# sleep 20
3625# bhyvectl --destroy --vm=ioh-$name
3626}
3627
3628# Force kill -9 everyting matching $name and destroy
3629# THIS WILL KILL EVERYTHING MATCHING $NAME
3630__guest_forcekill() {
3631 local name="$2"
3632 if [ -z $name ]; then
3633 printf "missing argument\nusage:\n"
3634 printf "\tforcekill <name>\n"
3635 exit 1
3636 fi
3637 local pids="$(pgrep -f $name)"
3638 for apid in "$pids"; do
3639 kill -9 $apid
3640 done
3641 bhyvectl --destroy --vm=ioh-$name
3642}
3643
3644# Gracefully shut down all guests via ACPI (Does not destroy)
3645__guest_scram() {
3646 echo "Shutting down all guests..."
3647 local pids="$(pgrep -f ioh-)"
3648 for apid in "$pids"; do
3649 kill $apid
3650 done
3651 wait_for_pids $pids
3652}
3653
3654# Destroy guest
3655__guest_destroy() {
3656 local name="$2"
3657 if [ -z $name ]; then
3658 printf "missing argument\nusage:\n"
3659 printf "\tdestroy <name>\n"
3660 exit 1
3661 fi
3662 echo "Destroying $name..."
3663# zfs set iohyve:persist=0 $pool/iohyve/$name
3664 bhyvectl --force-poweroff --vm=ioh-$name
3665 bhyvectl --destroy --vm=ioh-$name
3666}
3667
3668# Rename the guest
3669__guest_rename() {
3670 local name="$2"
3671 local newname="$3"
3672 if [ -z $newname ]; then
3673 printf "missing argument\nusage:\n"
3674 printf "\trename <name> <newname>\n"
3675 exit 1
3676 fi
3677
3678 if ! __guest_exist $name; then
3679 echo "guest $name doesn't exist"
3680 return 1
3681 fi
3682
3683 local dataset="$(zfs get -H -o name,value -s local -t filesystem iohyve:name | grep "$(printf '\t')$name$" | cut -f1)"
3684 local path="$(echo $dataset | rev | cut -f2- -d/ | rev)"
3685 echo "Renaming $name to $newname..."
3686 zfs rename -f $dataset $path/$newname
3687 zfs set iohyve:name=$newname $path/$newname
3688}
3689
3690# Delete guest
3691__guest_delete() {
3692 local flagone="$2"
3693 local flagtwo="$3"
3694 if [ $flagone = "-f" ]; then
3695 if [ -z $flagtwo ]; then
3696 printf "missing argument\nusage:\n"
3697 printf "\tdelete [-f] <name>\n"
3698 exit 1
3699 fi
3700
3701 if ! __guest_exist $flagtwo; then
3702 echo "guest $flagtwo doesn't exist"
3703 return 1
3704 fi
3705
3706 local target_dataset="$(zfs get -H -o name,value -s local -t filesystem iohyve:name | grep "$(printf '\t')$flagtwo$" | cut -f1)"
3707 echo ""
3708 echo "[WARNING] Forcing permanent deletion of $flagtwo"
3709 echo "Location: $target_dataset including children and clones"
3710 echo ""
3711 echo "Hit Ctrl+C in the next 10 seconds to cancel..."
3712 sleep 10
3713 echo "Deleting $flagtwo at $target_dataset..."
3714 zfs destroy -rR $target_dataset
3715 else
3716 if [ -z $flagone ]; then
3717 printf "missing argument\nusage:\n"
3718 printf "\tdelete [-f] <name>\n"
3719 exit 1
3720 fi
3721
3722 if ! __guest_exist $flagone; then
3723 echo "guest $flagone doesn't exist"
3724 return 1
3725 fi
3726
3727 local target_dataset="$(zfs get -H -o name,value -s local -t filesystem iohyve:name | grep "$(printf '\t')$flagone$" | cut -f1)"
3728 echo ""
3729 echo "[WARNING] Are you sure you want to permanently delete $flagone and all child datasets?"
3730 read -p "Location: $target_dataset [Y/N]? " an </dev/tty
3731 case "$an" in
3732 y|Y) echo "Deleting $flagone at $target_dataset..."; zfs destroy -r $target_dataset
3733 ;;
3734 *) echo "$flagone not deleted..."
3735 esac
3736 fi
3737}
3738
3739__guest_get_bhyve_cmd() {
3740 local devices="$1"
3741 local pci_slot_count=0
3742 for device in $devices ; do
3743 echo "-s $pci_slot_count,$device"
3744 pci_slot_count=$(( pci_slot_count + 1 ))
3745 done
3746}
3747
3748__guest_exist() {
3749 zfs get -H -s local -o value iohyve:name | grep ^$1$ > /dev/null
3750}
3751. "${LIB}/ioh-disk"
3752#!/bin/sh
3753
3754# Add a new disk to guest
3755__disk_add() {
3756 local name="$2"
3757 local size="$3"
3758
3759 if [ -z $size ]; then
3760 printf "missing argument\nusage:\n"
3761 printf "\tadd <name> <size>\n"
3762 exit 1
3763 fi
3764
3765 local pool="$(zfs list -H -t volume | grep iohyve/$name | cut -d '/' -f 1 | head -n1)"
3766 # optionally allow the pool for the new disk to be specified. If not set, its set to $pool
3767 local newpool="${4-$pool}"
3768 # Find the last disk number and increment one
3769 local lastdisk="$(zfs list -H | grep iohyve/$name | grep disk | cut -d '/' -f4 | cut -f1 | \
3770 sort -V | cut -c5- | tail -n1)"
3771 local newdisk="$(expr $lastdisk + 1)"
3772 echo "Creating new zvol for $name..."
3773 zfs create $newpool/iohyve/$name 2> /dev/null
3774 zfs create -V $size -o volmode=dev $newpool/iohyve/$name/disk$newdisk
3775 # Find the last pcidev and increment by one
3776 local lastpci="$(zfs get -H all | grep iohyve/$name | grep pcidev | cut -f2 | \
3777 cut -d ':' -f3 | sort -V | tail -n1)"
3778 if [ -z $lastpci ]; then
3779 local newpci='1'
3780 else
3781 local newpci="$(expr $lastpci + 1)"
3782 fi
3783 zfs set iohyve:pcidev:$newpci=ahci-hd,/dev/zvol/$newpool/iohyve/$name/disk$newdisk $pool/iohyve/$name
3784}
3785
3786# Remove disk from guest
3787__disk_remove() {
3788 local flagone="$2"
3789 local flagtwo="$3"
3790 local flagthree="$4"
3791 if [ $flagone = "-f" ]; then
3792 if [ -z $flagthree ]; then
3793 printf "missing argument\nusage:\n"
3794 printf "\tremove [-f] <name> <diskN>\n"
3795 exit 1
3796 fi
3797 echo "Removing $flagthree from $flagtwo"
3798 local pool="$(zfs list -H -o name | grep $flagtwo | grep $flagthree | cut -d '/' -f 1)"
3799 local pciprop="$(zfs get -H all $pool/iohyve/$flagtwo | grep pcidev | grep $flagthree | cut -f2 )"
3800 # Make sure it's a valid pcidev property as to not shoot foot
3801 if [ -z $pciprop ]; then
3802 echo "Not a valid PCIDEV property"
3803 else
3804 zfs inherit -r $pciprop $pool/iohyve/$flagtwo
3805 zfs destroy $pool/iohyve/$flagtwo/$flagthree
3806 fi
3807 else
3808 if [ -z $flagtwo ]; then
3809 printf "missing argument\nusage:\n"
3810 printf "\tremove [-f] <name> <diskN>\n"
3811 exit 1
3812 fi
3813 local pool="$(zfs list -H -o name | grep $flagone | grep $flagtwo | cut -d '/' -f 1)"
3814 local pciprop="$(zfs get -H all $pool/iohyve/$flagone | grep pcidev | grep $flagtwo | cut -f2 )"
3815 # Make sure it's a valid pcidev property as to not shoot foot
3816 if [ -z $pciprop ]; then
3817 echo "Not a valid PCIDEV property"
3818 else
3819 read -p "Are you sure you want to remove $flagtwo from $flagone [Y/N]? " an </dev/tty
3820 case "$an" in
3821 y|Y) zfs inherit -r $pciprop $pool/iohyve/$flagone
3822 zfs destroy $pool/iohyve/$flagone/$flagtwo
3823 ;;
3824 *) echo "Not removed..."
3825 ;;
3826 esac
3827 fi
3828 fi
3829}
3830
3831# Resize a disk
3832__disk_resize(){
3833 local name="$2"
3834 local disk="$3"
3835 local size="$4"
3836 if [ -z $size ]; then
3837 printf "missing argument\nusage:\n"
3838 printf "\tresize <name> <diskN> <size>\n"
3839 exit 1
3840 fi
3841 local pool="$(zfs list -H -o name | grep iohyve/$name | grep $disk | cut -d '/' -f 1)"
3842 # Check if guest exists
3843 echo "Resizing $disk to $size"
3844 if [ -d /iohyve/$pool/$name ] || [ -d /iohyve/$name ]; then
3845 # Check to make sure guest isn't running
3846 local running=$(pgrep -fx "bhyve: ioh-$name")
3847 if [ -z $running ]; then
3848 zfs set volsize=$size $pool/iohyve/$name/$disk
3849 zfs set iohyve:size=$size $pool/iohyve/$name
3850 else
3851 echo "Please stop the guest first"
3852 fi
3853 else
3854 echo "Not a valid guest name"
3855 fi
3856}
3857
3858# List disks for a guest
3859__disk_disks() {
3860 local name="$2"
3861 if [ -z $name ]; then
3862 printf "missing argument\nusage:\n"
3863 printf "\tdisks <name>\n"
3864 exit 1
3865 fi
3866 local pool="$(zfs list -H | grep iohyve | cut -d '/' -f 1 | head -n1)"
3867 if [ -z $name ]; then
3868 echo "You must enter a guest name."
3869 elif [ -d /iohyve/$pool/$name ] || [ -d /iohyve/$name ]; then
3870 (
3871 echo "Listing disks for $name..."
3872 printf "diskN\tSize\n"
3873 zfs list -H -o name,volsize | grep -E "iohyve.*$name.*disk" | \
3874 cut -d '/' -f4
3875 ) | column -t
3876 else
3877 echo "Not a valid guest name"
3878 fi
3879}
3880. "${LIB}/ioh-tap"
3881#!/bin/sh
3882
3883# List taps in use
3884__tap_list() {
3885 local guestlist="$(zfs list -H -o name -t volume | grep iohyve | cut -d'/' -f1-3)"
3886 echo "Listing all network taps:"
3887 for i in $guestlist ; do
3888 conprop="$(zfs get -H -o value iohyve:tap $i)"
3889 printf $i'......'$conprop'\n'
3890 done
3891}
3892
3893# List active taps in use
3894__tap_active_list() {
3895 echo "Listing active network taps..."
3896 ls /dev | grep tap
3897}
3898
3899# Show version
3900__version() {
3901 echo "iohyve v0.7.6 2016/06/12 Rideau Street Sinkhole Edition"
3902}
3903
3904# Print help page
3905__help() {
3906cat << 'EOT'
3907iohyve version
3908 setup <pool=poolname> [kmod=0|1] [net=iface]
3909 list [-l]
3910 info [-vsdl]
3911 isolist
3912 fwlist
3913 fetchiso <URL>
3914 cpiso <path>
3915 renameiso <ISO> <newname>
3916 rmiso <ISO>
3917 fetchfw <URL>
3918 cpfw <path>
3919 renamefw <firmware> <newname>
3920 rmfw <firmware>
3921 create <name> <size> [pool]
3922 install <name> <ISO>
3923 load <name> <path/to/bootdisk>
3924 boot <name> [runmode] [pcidevices]
3925 start <name> [-s | -a]
3926 stop <name>
3927 forcekill <name>
3928 scram
3929 destroy <name>
3930 rename <name> <newname>
3931 delete [-f] <name>
3932 set <name> <property=value> ...
3933 get <name> <prop>
3934 rmpci [-f] <name> <pcidev:N>
3935 getall <name>
3936 add <name> <size> [pool]
3937 remove [-f] <name> <diskN>
3938 resize <name> <diskN> <size>
3939 disks <name>
3940 snap <name>@<snap>
3941 roll <name>@<snap>
3942 clone [-c | -r] <name> <clonename>
3943 export <name>
3944 snaplist
3945 taplist
3946 activetaps
3947 conlist
3948 console <name>
3949 conreset
3950 help
3951EOT
3952}
3953
3954if [ -z "$1" ] ; then
3955 __help
3956 exit 0
3957fi
3958
3959if __root_req_cmd "$1" && [ "$(whoami)" != "root" ]; then
3960 echo "The $1 command needs root credentials!"
3961 exit 1
3962fi
3963
3964__parse_cmd "$@"
3965Creating testbsd...
3966too many arguments
3967usage:
3968 create [-pu] [-o property=value] ... <filesystem>
3969 create [-ps] [-b blocksize] [-o property=value] ... -V <size> <volume>
3970
3971For the property list, run: zfs set|get
3972
3973For the delegated permission list, run: zfs allow|unallow
3974too many arguments
3975usage:
3976 create [-pu] [-o property=value] ... <filesystem>
3977 create [-ps] [-b blocksize] [-o property=value] ... -V <size> <volume>
3978
3979For the property list, run: zfs set|get
3980
3981For the delegated permission list, run: zfs allow|unallow