-
-
Save jclulow/f43a4911d06a04c4c551 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/smartdc/bin/smartos_prompt_config.sh b/smartdc/bin/smartos_prompt_config.sh | |
index c51fa99..be4e641 100644 | |
--- a/smartdc/bin/smartos_prompt_config.sh | |
+++ b/smartdc/bin/smartos_prompt_config.sh | |
@@ -6,6 +6,9 @@ | |
PATH=/usr/sbin:/usr/bin | |
export PATH | |
+ | |
+. /lib/svc/share/smf_include.sh | |
+ | |
. /lib/sdc/config.sh | |
load_sdc_sysinfo | |
load_sdc_config | |
@@ -22,6 +25,22 @@ declare -a states | |
declare -a nics | |
declare -a assigned | |
declare -a DISK_LIST | |
+declare -a DISK_LAYOUT | |
+declare -a CONSOLE_TYPE | |
+ | |
+detect_console() | |
+{ | |
+ local tty=$(tty) | |
+ local console=$(bootparams | awk -F= '$1 == "console" { print $2 }') | |
+ | |
+ CONSOLE_TYPE=serial | |
+ if [[ $tty == "/dev/console" && $console == "text" ]]; then | |
+ CONSOLE_TYPE=vga | |
+ elif [[ $tty == "/dev/wscons" ]]; then | |
+ CONSOLE_TYPE=vga | |
+ fi | |
+ export CONSOLE_TYPE | |
+} | |
sigexit() | |
{ | |
@@ -31,6 +50,19 @@ sigexit() | |
exit 0 | |
} | |
+fatal() | |
+{ | |
+ echo | |
+ if [[ -n "$1" ]]; then | |
+ echo "ERROR: $1" | |
+ fi | |
+ echo | |
+ echo "System configuration failed." | |
+ echo "You must reboot to re-run system configuration." | |
+ echo | |
+ exit $SMF_EXIT_ERR_FATAL | |
+} | |
+ | |
# | |
# Get the max. IP addr for the given field, based in the netmask. | |
# That is, if netmask is 255, then its just the input field, otherwise its | |
@@ -242,7 +274,7 @@ promptpw() | |
else | |
break | |
fi | |
- else | |
+ else | |
echo "A value must be provided." | |
fi | |
done | |
@@ -264,36 +296,118 @@ promptpw() | |
done | |
} | |
+printdisklayout() | |
+{ | |
+ json -f "$1" | json -e ' | |
+ out = "vdevs:\n"; | |
+ disklist = []; | |
+ for (var i = 0; i < vdevs.length; i++) { | |
+ var x = vdevs[i]; | |
+ if (!x.type) { | |
+ out += " " + x.name + "\n"; | |
+ } | |
+ if (x.type === "mirror") { | |
+ out += " " + x.type + " " + x.devices[0].name + " " + | |
+ x.devices[1].name + "\n"; | |
+ continue; | |
+ } | |
+ out += " " + x.type + "\n"; | |
+ var lout = " "; | |
+ for (var j = 0; j < x.devices.length; j++) { | |
+ if ((lout + x.devices[j].name).length > 80) { | |
+ out += lout + "\n"; | |
+ lout = " " + x.devices[j].name + " "; | |
+ } else { | |
+ lout += x.devices[j].name + " "; | |
+ } | |
+ } | |
+ out += lout + "\n"; | |
+ } | |
+ if (spares && spares.length > 0) { | |
+ out += "spares:\n"; | |
+ var lout = " "; | |
+ for (var i = 0; i < spares.length; i++) { | |
+ if ((lout + spares[i].name).length > 80) { | |
+ out += lout + "\n"; | |
+ lout += " " + spares[i].name + " "; | |
+ } else { | |
+ lout += spares[i].name + " "; | |
+ } | |
+ } | |
+ out += lout + "\n"; | |
+ } | |
+ if (logs && logs.length > 0) { | |
+ out += "logs:\n"; | |
+ var lout = " "; | |
+ for (var i = 0; i < logs.length; i++) { | |
+ if ((lout + logs[i].name).length > 80) { | |
+ out += lout + "\n"; | |
+ lout += " " + logs[i].name + " "; | |
+ } else { | |
+ lout += logs[i].name + " "; | |
+ } | |
+ } | |
+ out += lout + "\n"; | |
+ } | |
+ out += "total capacity: " + Number(capacity / 1073741824).toFixed(2) | |
+ + " GB"; | |
+ ' out | |
+} | |
+ | |
promptpool() | |
{ | |
- disks=$(disklist -n) | |
+ local layout=mirror | |
+ local disks= | |
while [[ /usr/bin/true ]]; do | |
- echo "Please select disks for the storage pool, space separated" | |
+ diskinfo -Hp > /var/tmp/mydisks | |
+ disklayout -f /var/tmp/mydisks $layout > /var/tmp/disklayout.json | |
+ printdisklayout /var/tmp/disklayout.json | |
echo "" | |
- printf "Valid choices are ${disks}" | |
+ echo "This is the '${layout}' storage configuration. To use it, type 'yes'." | |
+ echo " To see a different configuration, type: 'raidz2' or 'mirror'. " | |
+ echo " To specify a manual configuration, type: 'manual'." | |
echo "" | |
- bad="" | |
read val | |
- if [[ $val == "" ]]; then | |
- echo "At least one disk must be specified" | |
- echo "" | |
- continue | |
- fi | |
- for disk in $(echo $val | tr " " "\n"); do | |
- if [[ -z $disk ]]; then continue; fi; | |
- echo $disks | grep $disk 1>&2 > /dev/null | |
- if [[ $? != 0 ]]; then | |
- bad="$disk $bad" | |
- fi | |
- done | |
- if [[ $bad != "" ]]; then | |
- printf "The disks %s are not valid choices" $bad | |
- else | |
- DISK_LIST="$val" | |
+ if [[ $val == "raidz2" || $val == "mirror" ]]; then | |
+ # go around again | |
+ layout=$val | |
+ elif [[ $val == "yes" ]]; then | |
+ DISK_LAYOUT=/var/tmp/disklayout.json | |
+ return | |
+ elif [[ $val == "manual" ]]; then | |
+ # let the user specify a list of disks, as we used to do | |
+ DISK_LAYOUT="manual" | |
+ disks=$(disklist -n) | |
+ while [[ /usr/bin/true ]]; do | |
+ echo "" | |
+ echo "Please select disks for the storage pool, space separated" | |
+ echo "" | |
+ printf "Valid choices are ${disks}" | |
+ echo "" | |
+ bad="" | |
+ read val | |
+ if [[ $val == "" ]]; then | |
+ echo "At least one disk must be specified" | |
+ echo "" | |
+ continue | |
+ fi | |
+ for disk in $(echo $val | tr " " "\n"); do | |
+ if [[ -z $disk ]]; then continue; fi; | |
+ echo $disks | grep $disk 1>&2 > /dev/null | |
+ if [[ $? != 0 ]]; then | |
+ bad="$disk $bad" | |
+ fi | |
+ done | |
+ if [[ $bad != "" ]]; then | |
+ printf "The disks %s are not valid choices" $bad | |
+ else | |
+ DISK_LIST="$val" | |
+ return | |
+ fi | |
+ done | |
break | |
fi | |
done | |
- | |
} | |
create_dump() | |
@@ -396,62 +510,75 @@ setup_datasets() | |
create_zpool() | |
{ | |
- disks=$1 | |
+ layout=$1 | |
+ disks=$2 | |
pool=zones | |
# If the pool already exists, don't create it again. | |
if /usr/sbin/zpool list -H -o name $pool; then | |
+ printf "%-56s" "Pool '$pool' exists, skipping creation... " | |
return 0 | |
fi | |
- disk_count=$(echo "${disks}" | wc -w | tr -d ' ') | |
printf "%-56s" "Creating pool $pool... " | |
- # If no pool profile was provided, use a default based on the number of | |
- # devices in that pool. | |
- if [[ -z ${profile} ]]; then | |
- case ${disk_count} in | |
- 0) | |
- fatal "no disks found, can't create zpool";; | |
- 1) | |
- profile="";; | |
- 2) | |
- profile=mirror;; | |
- *) | |
- profile=raidz;; | |
- esac | |
- fi | |
- | |
- zpool_args="" | |
- | |
- # When creating a mirrored pool, create a mirrored pair of devices out of | |
- # every two disks. | |
- if [[ ${profile} == "mirror" ]]; then | |
- ii=0 | |
- for disk in ${disks}; do | |
- if [[ $(( $ii % 2 )) -eq 0 ]]; then | |
- zpool_args="${zpool_args} ${profile}" | |
- fi | |
- zpool_args="${zpool_args} ${disk}" | |
- ii=$(($ii + 1)) | |
- done | |
+ if [[ $layout != 'manual' ]]; then | |
+ # If this is not a manual layout, then we've been given | |
+ # a JSON file describing the desired pool, so use that: | |
+ mkzpool -f $pool $layout || \ | |
+ fatal "failed to create pool ${pool}" | |
else | |
- zpool_args="${profile} ${disks}" | |
+ # Otherwise, we have a list of disks to use: | |
+ disk_count=$(echo "${disks}" | wc -w | tr -d ' ') | |
+ # If no pool profile was provided, use a default based on the number of | |
+ # devices in that pool. | |
+ if [[ -z ${profile} ]]; then | |
+ case ${disk_count} in | |
+ 0) | |
+ fatal "no disks found, can't create zpool";; | |
+ 1) | |
+ profile="";; | |
+ 2) | |
+ profile=mirror;; | |
+ *) | |
+ profile=raidz;; | |
+ esac | |
+ fi | |
+ | |
+ zpool_args="" | |
+ | |
+ # When creating a mirrored pool, create a mirrored pair of devices out of | |
+ # every two disks. | |
+ if [[ ${profile} == "mirror" ]]; then | |
+ ii=0 | |
+ for disk in ${disks}; do | |
+ if [[ $(( $ii % 2 )) -eq 0 ]]; then | |
+ zpool_args="${zpool_args} ${profile}" | |
+ fi | |
+ zpool_args="${zpool_args} ${disk}" | |
+ ii=$(($ii + 1)) | |
+ done | |
+ else | |
+ zpool_args="${profile} ${disks}" | |
+ fi | |
+ | |
+ zpool create -f ${pool} ${zpool_args} || \ | |
+ fatal "failed to create pool ${pool}" | |
fi | |
- zpool create -f ${pool} ${zpool_args} || \ | |
- fatal "failed to create pool ${pool}" | |
zfs set atime=off ${pool} || \ | |
fatal "failed to set atime=off for pool ${pool}" | |
printf "%4s\n" "done" | |
} | |
+ | |
create_zpools() | |
{ | |
- devs=$1 | |
+ layout=$1 | |
+ devs=$2 | |
export SYS_ZPOOL="zones" | |
- create_zpool "$devs" | |
+ create_zpool "$layout" "$devs" | |
sleep 5 | |
svccfg -s svc:/system/smartdc/init setprop config/zpool="zones" | |
@@ -480,22 +607,64 @@ updatenicstates() | |
done < <(dladm show-phys -po link,state 2>/dev/null) | |
} | |
-printheader() | |
+clear_screen() | |
{ | |
- local newline= | |
- local cols=`tput cols` | |
- local subheader=$1 | |
- | |
- if [ $cols -gt 80 ] ;then | |
- newline='\n' | |
+ if [[ $CONSOLE_TYPE == "vga" ]]; then | |
+ # | |
+ # Only clear the screen if we're on a VGA console. | |
+ # | |
+ clear | |
+ else | |
+ # | |
+ # Otherwise, it is more helpful to retain output in the scrollback buffer | |
+ # of the terminal attached to the serial console. | |
+ # | |
+ printf "\n\n" | |
fi | |
- | |
- clear | |
- for i in {1..80} ; do printf "-" ; done && printf "$newline" | |
- printf " %-40s\n" "SmartOS Setup" | |
- printf " %-40s%38s\n" "$subheader" "http://wiki.smartos.org/install" | |
- for i in {1..80} ; do printf "-" ; done && printf "$newline" | |
+} | |
+# | |
+# Print a Horizontal Rule, i.e. | |
+# ---------------------------------------------- | |
+# | |
+printhr() | |
+{ | |
+ local bold=$(tput bold) | |
+ local reset=$(tput sgr0) | |
+ local width=$1 | |
+ printf "${bold}" | |
+ (( i = 0 )) | |
+ while (( i < $width )); do | |
+ printf "-" | |
+ (( i++ )) | |
+ done | |
+ printf "${reset}" | |
+} | |
+ | |
+printheader() | |
+{ | |
+ local cols=$(tput cols) | |
+ local subheader=$1 | |
+ local bold=$(tput bold) | |
+ local reset=$(tput sgr0) | |
+ | |
+ clear_screen | |
+ | |
+ [[ CONSOLE_TYPE == "vga" ]] && tput cup 0 0 || printf "\n" | |
+ printhr $cols | |
+ | |
+ [[ CONSOLE_TYPE == "vga" ]] && tput cup 1 0 || printf "\n" | |
+ printf " ${bold}%-40s${reset}" \ | |
+ "SmartOS Setup" | |
+ | |
+ [[ CONSOLE_TYPE == "vga" ]] && tput cup 2 0 || printf "\n" | |
+ printf " ${bold}%-40s${reset}%38s" \ | |
+ "$subheader" "http://wiki.smartos.org/install" | |
+ | |
+ [[ CONSOLE_TYPE == "vga" ]] && tput cup 3 0 || printf "\n" | |
+ printhr $cols | |
+ | |
+ printf "\n" | |
} | |
trap sigexit SIGINT | |
@@ -520,9 +689,23 @@ fi | |
ifconfig -a plumb | |
updatenicstates | |
-export TERM=sun-color | |
-export TERM=xterm-color | |
-stty erase ^H | |
+# | |
+# Detect the console and set TERM appropriately: | |
+# | |
+detect_console | |
+if [[ $CONSOLE_TYPE == "vga" ]]; then | |
+ # | |
+ # Deal with our Most Exotic VGA Console: | |
+ # | |
+ export TERM=sun-color | |
+ stty erase ^H | |
+else | |
+ # | |
+ # Everybody else is probably on a real computer attached via serial: | |
+ # | |
+ export TERM=xterm-color | |
+fi | |
+stty sane | |
printheader "Copyright 2011, Joyent, Inc." | |
@@ -605,14 +788,14 @@ while [ /usr/bin/true ]; do | |
fi | |
promptval "Is this correct?" "y" | |
[ "$val" == "y" ] && break | |
- clear | |
+ clear_screen | |
done | |
admin_network="$net_a.$net_b.$net_c.$net_d" | |
# | |
# Generate config file | |
# | |
-tmp_config=/tmp_config | |
+tmp_config=/tmp/config | |
touch $tmp_config | |
chmod 600 $tmp_config | |
@@ -652,20 +835,25 @@ echo >>$tmp_config | |
echo | |
echo "Your configuration is about to be applied." | |
promptval "Would you like to edit the final configuration file?" "n" | |
-[ "$val" == "y" ] && vi $tmp_config | |
-clear | |
+[[ "$val" == "y" ]] && vi $tmp_config | |
+clear_screen | |
echo | |
echo "Your data pool will be created with the following disks:" | |
-echo $DISK_LIST | |
+if [[ $DISK_LAYOUT == "manual" ]]; then | |
+ echo $DISK_LIST | |
+else | |
+ printdisklayout $DISK_LAYOUT | |
+fi | |
echo "*********************************************" | |
echo "* This will erase *ALL DATA* on these disks *" | |
echo "*********************************************" | |
promptval "are you sure?" "n" | |
-[ "$val" == "y" ] && (create_zpools "$DISK_LIST") | |
+[[ "$val" == "y" ]] && (create_zpools "$DISK_LAYOUT" "$DISK_LIST") | |
+ | |
+printf "\n\nThe system will now finish configuration and reboot." | |
+printf "\n\nPlease wait...\n\n" | |
-clear | |
-echo "The system will now finish configuration and reboot. Please wait..." | |
mv $tmp_config /usbkey/config | |
# set the root password | |
@@ -674,7 +862,8 @@ sed -e "s|^root:[^\:]*:|root:${root_shadow}:|" /etc/shadow > /usbkey/shadow \ | |
&& chmod 400 /usbkey/shadow | |
cp -rp /etc/ssh /usbkey/ssh | |
-cp /usr/img/etc/sources.list.sample /var/db/imgadm/sources.list | |
+if [[ -f /usr/img/etc/sources.list.sample ]]; then | |
+ cp /usr/img/etc/sources.list.sample /var/db/imgadm/sources.list | |
+fi | |
reboot | |
- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment