Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 38e1b9e9129081e0dc59f0212635b7e9d33b4f0c 0 parents
John Sonnenschein JohnSonnenschein authored
3  README
@@ -0,0 +1,3 @@
+This is the overlay directory containing extra files specific to
+SmartOS ( http://github.com/joyent/smartos-live ) not required or conflicting
+with analogues in the SDC product
92 lib/svc/manifest/network/network-physical.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ NOTE: This service manifest is not editable; its contents will
+ be overwritten by package or patch operations, including
+ operating system upgrade. Make customizations in a different
+ file.
+-->
+
+<service_bundle type='manifest' name='SUNWcsr:network-physical'>
+
+<service
+ name='network/physical'
+ type='service'
+ version='1'>
+
+ <!-- ifconfig needs loopback for IPC with dhcpagent -->
+ <dependency
+ name='loopback'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/network/loopback' />
+ </dependency>
+
+ <dependency
+ name='joyent'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/system/filesystem/smartdc' />
+ </dependency>
+
+ <instance name='default' enabled='true'>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='/lib/svc/method/net-physical'
+ timeout_seconds='600' />
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':true'
+ timeout_seconds='3' />
+
+ <property_group name='startd' type='framework'>
+ <propval name='duration' type='astring' value='transient' />
+ </property_group>
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ physical network interfaces
+ </loctext>
+ </common_name>
+ <documentation>
+ <manpage title='ifconfig' section='1M'
+ manpath='/usr/share/man' />
+ </documentation>
+ </template>
+
+ </instance>
+
+ <stability value='Unstable' />
+
+</service>
+
+</service_bundle>
92 lib/svc/manifest/system/filesystem/joyent-fs.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License, Version 1.0 only
+ (the "License"). You may not use this file except in compliance
+ with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ ident "%Z%%M% %I% %E% SMI"
+
+ NOTE: This service manifest is not editable; its contents will
+ be overwritten by package or patch operations, including
+ operating system upgrade. Make customizations in a different
+ file.
+-->
+
+<service_bundle type='manifest' name='SUNWcsr:filesystem-joyent'>
+
+<service
+ name='system/filesystem/smartdc'
+ type='service'
+ version='1'>
+
+ <create_default_instance enabled='true' />
+
+ <single_instance/>
+
+ <dependency
+ name='usr'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/system/filesystem/usr' />
+ </dependency>
+
+ <!--
+ Start method timeout is infinite to handle potentially unbounded
+ fsck times.
+ -->
+ <exec_method
+ type='method'
+ name='start'
+ exec='/lib/svc/method/fs-joyent'
+ timeout_seconds='0' />
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':true'
+ timeout_seconds='0' />
+
+ <property_group name='startd' type='framework'>
+ <propval name='duration' type='astring' value='transient' />
+ </property_group>
+ <property_group name='joyentfs' type='application'>
+ <stability value='Evolving'/>
+ <propval name='debug' type='boolean' value='false'/>
+ <propval name='usb_copy_path' type='astring' value='/usbkey'/>
+ <propval name='usb_mountpoint' type='astring' value='usbkey'/>
+ </property_group>
+
+
+ <stability value='Unstable' />
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ Joyent file system mounts
+ </loctext>
+ </common_name>
+ </template>
+</service>
+
+</service_bundle>
110 lib/svc/manifest/system/smartdc-init.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2010 Joyent, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ NOTE: This service manifest is not editable; its contents will
+ be overwritten by package or patch operations, including
+ operating system upgrade. Make customizations in a different
+ file.
+-->
+
+<service_bundle type='manifest' name='Joyent:joyent'>
+
+<!--
+ This service imports the zone's zpool on bootup, before zones try to
+ start. It also sets up configuration data on that zpool, if necessary.
+-->
+<service
+ name='system/smartdc/init'
+ type='service'
+ version='1'>
+
+ <create_default_instance enabled='true' />
+
+ <single_instance />
+
+ <!--
+ dependency info
+ This depends on the system/zones svc which seems weird since that
+ svc runs late in boot because it depends on milestone/multi-user-server.
+ Our svc does the initial setup of the infrastructure zones on the
+ headnode so we need the system/zones svc to run first so that we can
+ install and boot the infrastructure zones. The reason this seems
+ weird is that this svc also sets up the zpool when we first boot,
+ before we reboot to install the infrastructure zones, so it might seem
+ like it should run early in boot, but it can't because of the zone
+ issue described above.
+ -->
+ <dependency
+ name='zones'
+ type='service'
+ grouping='require_all'
+ restart_on='none'>
+ <service_fmri value='svc:/system/zones' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='/lib/svc/method/smartdc-init %m'
+ timeout_seconds='0'>
+ </exec_method>
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec='/lib/svc/method/smartdc-init %m'
+ timeout_seconds='60'>
+ </exec_method>
+
+ <property_group name='startd' type='framework'>
+ <propval name='duration' type='astring' value='transient' />
+ </property_group>
+
+ <!--
+ The zpool holding the zones (this must be imported).
+ -->
+ <property_group name='config' type='application'>
+ <propval name='zpool' type='astring' value='zones' />
+ </property_group>
+
+ <stability value='Unstable' />
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ Joyent live-image management service
+ </loctext>
+ </common_name>
+ <documentation>
+ <manpage title='zones' section='5' manpath='/usr/share/man' />
+ <manpage
+ title='zpool'
+ section='1M'
+ manpath='/usr/share/man' />
+ </documentation>
+ </template>
+</service>
+
+</service_bundle>
228 lib/svc/method/fs-joyent
@@ -0,0 +1,228 @@
+#gents!/bin/bash
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at COPYING
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at COPYING.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2010,2011 Joyent Inc.
+
+set -o xtrace
+
+. /lib/svc/share/smf_include.sh
+. /lib/svc/share/fs_include.sh
+
+# first of all, if we aren't the global zone this doesn't make any sense to run
+
+smf_is_globalzone || exit $SMF_EXIT_OK
+
+# Need to run syseventd now because it talks to devfs to create /dev/dsk
+# so that we can try to import the zpool.
+/usr/lib/sysevent/syseventd
+
+function destroy_zpools
+{
+ for pool in $(zpool list -p -o name | grep -v NAME) ; do
+ zpool destroy -f ${pool}
+ done
+}
+
+/bin/bootparams | grep "^noimport=true" >/dev/null
+if [ $? -ne 0 ]; then
+ # If the zpool doesn't exist, then there's nothing to mount.
+
+ # Assume the system zpool is zones, but if a different system pool
+ # identifies itself (by virtue of the .system_pool file being present in the
+ # pool's root dataset), then use that system pool instead.
+ SYS_ZPOOL=zones
+
+ # Import specified zpools, or all zpools available
+ pools=$(/bin/bootparams | egrep "^zpools?=" | cut -d= -f2 | tr , ' ')
+ if [ -z ${pools} ]; then
+ pools=$(zpool import | grep "pool:" | awk '{print $2}')
+ fi
+
+ for pool in $pools; do
+ zpool import -f $pool
+ if [[ -f /$pool/.system_pool ]]; then
+ SYS_ZPOOL=$pool
+ fi
+ done
+
+ svccfg -s svc:/system/smartdc/init setprop \
+ config/zpool=${SYS_ZPOOL}
+ svccfg -s svc:/system/smartdc/init:default refresh
+
+ # If the destroy_zpools boot parameter is set, destroy all zpools
+ /bin/bootparams | grep "^destroy_zpools=true" >/dev/null
+ if [ $? -eq 0 ]; then
+ destroy_zpools
+ fi
+
+ # A machine is reset to its original unsetup state (i.e. a 'factory reset')
+ # when the smartdc:factoryreset ZFS user property is set on the var dataset.
+ reset=$(zfs get -H -o value smartdc:factoryreset ${SYS_ZPOOL}/var)
+ if [ ${reset} == "yes" ]; then
+ destroy_zpools
+ fi
+
+ # For the system zpool, mount and configure all system datasets
+ zpool status -v ${SYS_ZPOOL}
+ if [ $? -eq 0 ]; then
+ mount -F zfs ${SYS_ZPOOL}/var /var
+ mount -F zfs ${SYS_ZPOOL}/config /etc/zones
+ mount -F zfs ${SYS_ZPOOL}/opt /opt
+ if [[ -n $(/bin/bootparams | grep '^headnode=true') ]]; then
+ mkdir -p /opt/smartdc/agents/smf
+ mount -O -F lofs /var/svc/manifest/site /opt/smartdc/agents/smf
+ fi
+
+ if [[ -n $(/bin/bootparams | grep '^headnode=true') || \
+ -n $(/bin/bootparams | grep '^smartos=true') ]]; then
+ mkdir /usbkey
+ mount -F zfs ${SYS_ZPOOL}/usbkey /usbkey
+ fi
+ if [[ -n $(/bin/bootparams | grep '^smartos=true') ]]; then
+ mount -F lofs /usbkey/shadow /etc/shadow
+ mount -F lofs /usbkey/ssh /etc/ssh
+ fi
+
+ swap -a /dev/zvol/dsk/${SYS_ZPOOL}/swap
+ dumpadm -y -d /dev/zvol/dsk/${SYS_ZPOOL}/dump
+
+ ln -s /${SYS_ZPOOL}/global/cores /cores
+
+ [[ -f /${SYS_ZPOOL}/currbooted ]] && \
+ mv /${SYS_ZPOOL}/currbooted /${SYS_ZPOOL}/lastbooted
+ uname -v >/${SYS_ZPOOL}/currbooted
+ fi
+fi
+
+# The rest only applies to the headnode
+/bin/bootparams | grep "^headnode=true" >/dev/null || exit $SMF_EXIT_OK
+
+USBMOUNTPOINT=/mnt/`svcprop -p "joyentfs/usb_mountpoint" ${SMF_FMRI}`
+COPYINPOINT=`svcprop -p "joyentfs/usb_copy_path" ${SMF_FMRI}`
+DEBUG=`svcprop -p "joyentfs/debug" ${SMF_FMRI}`
+
+mount_usb_msg=""
+
+if [[ -d /mnt ]]; then
+ chown root:root /mnt
+ chmod 700 /mnt
+else
+ mkdir -m 700 /mnt
+fi
+
+function make_usb_copy
+{
+ $(cd ${USBMOUNTPOINT}; rsync -a --exclude private --exclude os * ${COPYINPOINT})
+ if [[ -d ${USBMOUNTPOINT}/os ]]; then
+ (cd ${USBMOUNTPOINT}/os ; \
+ for dir in $(ls -d *); do
+ # source comes from pcfs which we've got lowering the case
+ # of everything, but we normally use capital T and Z for
+ # buildstamp, so fix it here.
+ source_dir=${dir}
+ target_dir=$(echo ${dir} | tr "[:lower:]" "[:upper:]")
+ mkdir -p ${COPYINPOINT}/os
+ rsync -a ${source_dir}/ ${COPYINPOINT}/os/${target_dir}
+ done
+ )
+ fi
+}
+
+mkdir -p ${USBMOUNTPOINT}
+
+if [[ -f "${USBMOUNTPOINT}/.joyliveusb" ]]; then
+ mount_usb_msg="already mounted"
+
+ zpool list | grep zones
+ if [[ $? == 0 ]]; then
+ make_usb_copy
+ exit $?
+ fi
+ exit 0;
+fi
+
+# First thing to do is to mount the USB key / VMWare disk
+USBKEYS=`/usr/bin/disklist -a`
+for key in ${USBKEYS}; do
+ if [[ `/usr/sbin/fstyp /dev/dsk/${key}p0:1` == 'pcfs' ]]; then
+ /usr/sbin/mount -F pcfs -o foldcase,noatime /dev/dsk/${key}p0:1 \
+ ${USBMOUNTPOINT};
+ if [[ $? == "0" ]]; then
+ if [[ ! -f ${USBMOUNTPOINT}/.joyliveusb ]]; then
+ if [[ ${DEBUG} == "true" ]]; then
+ mount_usb_msg="${mount_usb_msg}\n[debug] didn't find ${USBMOUNTPOINT}/.joyliveusb on pcfs /dev/dsk/${key}p0:1"
+ fi
+ /usr/sbin/umount ${USBMOUNTPOINT};
+ else
+ if [[ ${DEBUG} == "true" ]]; then
+ mount_usb_msg="${mount_usb_msg}\n[debug] found ${USBMOUNTPOINT}/.joyliveusb on pcfs /dev/dsk/${key}p0:1"
+ fi
+ break;
+ fi
+ elif [[ ${DEBUG} == "true" ]]; then
+ mount_usb_msg="${mount_usb_msg}\n[debug] mount failed for pcfs /dev/dsk/${key}p0:1"
+ fi
+ elif [[ ${DEBUG} == "true" ]]; then
+ mount_usb_msg="${mount_usb_msg}\n[debug] /dev/dsk/${key}p0:1 is not pcfs"
+ fi
+done
+
+if [[ ! -f "${USBMOUNTPOINT}/.joyliveusb" ]]; then
+ # we're probably VMWare, so we're looking at a non-USB disk.
+ for disk in `/usr/bin/disklist -a`; do
+ if [[ `/usr/sbin/fstyp /dev/dsk/${disk}p1` == 'pcfs' ]]; then
+ /usr/sbin/mount -F pcfs -o foldcase,noatime /dev/dsk/${disk}p1 \
+ ${USBMOUNTPOINT};
+ if [[ $? == "0" ]]; then
+ if [[ ! -f ${USBMOUNTPOINT}/.joyliveusb ]]; then
+ if [[ ${DEBUG} == "true" ]]; then
+ mount_usb_msg="${mount_usb_msg}\n[debug] didn't find ${USBMOUNTPOINT}/.joyliveusb on pcfs /dev/dsk/${disk}p1"
+ fi
+ /usr/sbin/umount ${USBMOUNTPOINT};
+ else
+ if [[ ${DEBUG} == "true" ]]; then
+ mount_usb_msg="${mount_usb_msg}\n[debug] found ${USBMOUNTPOINT}/.joyliveusb on pcfs /dev/dsk/${disk}p1"
+ fi
+ break;
+ fi
+ elif [[ ${DEBUG} == "true" ]]; then
+ mount_usb_msg="${mount_usb_msg}\n[debug] unable to mount /dev/dsk/${disk}p1"
+ fi
+ elif [[ ${DEBUG} == "true" ]]; then
+ mount_usb_msg="${mount_usb_msg}\n[debug] /dev/dsk/${disk}p1 is not pcfs"
+ fi
+ done
+fi
+
+if [[ -f "${USBMOUNTPOINT}/.joyliveusb" ]]; then
+ mount_usb_msg="success"
+
+ zpool list | grep zones
+
+ if [[ $? == 0 ]]; then
+ make_usb_copy
+ fi
+
+ exit 0;
+fi
+
+mount_usb_msg="${mount_usb_msg}\n[FATAL] mount_usb(): could not find USB Key"
+exit 1;
298 lib/svc/method/net-physical
@@ -0,0 +1,298 @@
+#!/usr/bin/ksh93
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T. All rights reserved.
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2011 Joyent Inc., All rights reserved.
+#
+
+. /lib/svc/share/smf_include.sh
+. /lib/sdc/config.sh
+. /lib/sdc/network.sh
+
+set -o errexit
+set -o xtrace
+
+#
+# In a shared-IP zone we need this service to be up, but all of the work
+# it tries to do is irrelevant (and will actually lead to the service
+# failing if we try to do it), so just bail out.
+# In the global zone and exclusive-IP zones we proceed.
+#
+smf_configure_ip || exit ${SMF_EXIT_OK}
+
+# Make sure that the libraries essential to this stage of booting can be found.
+LD_LIBRARY_PATH=/lib; export LD_LIBRARY_PATH
+
+smf_netstrategy
+
+function log_if_state
+{
+ echo "== debug start: $1 =="
+ if ! dladm show-phys; then
+ echo "WARNING: 'dladm show-phys' failed"
+ fi
+ # NOTE: DO NOT do a 'dladm show-linkprop' when using the bnx driver,
+ # as it puts it into an unusable state!
+ if ! /sbin/ifconfig -a; then
+ echo "WARNING: 'ifconfig -a' failed"
+ fi
+ echo "== debug end: $1 =="
+}
+
+# Creates, plumbs and brings up a vnic with the specified parameters
+function vnic_up
+{
+ typeset link="$1"
+ typeset iface="$2"
+ typeset ip="$3"
+ typeset netmask="$4"
+ typeset vlan_id="$5"
+ typeset mac_addr="$6"
+ typeset dhcp_primary="$7"
+ typeset details="link='${link}', iface='${iface}', ip='${ip}', netmask='${netmask}, vlan_id='${vlan_id}'"
+ typeset vlan_opt=
+ typeset mac_addr_opt=
+
+ if [[ -z ${link} ]] || [[ -z ${iface} ]] || [[ -z ${ip} ]] || [[ -z ${netmask} ]]; then
+ echo "WARNING: not bringing up nic (insufficient configuration): $details"
+ return
+ fi
+
+ eval "vnic_already_up=\${vnic_${iface}_up}"
+ if [[ -n "${vnic_already_up}" ]]; then
+ echo "vnic already up: $details"
+ return
+ fi
+ echo "Bringing up nic: $details"
+
+ if [[ -n ${vlan_id} ]] && [[ ${vlan_id} != 0 ]]; then
+ vlan_opt="-v ${vlan_id}"
+ fi
+
+ if [[ -n ${mac_addr} ]]; then
+ mac_addr_opt="-m ${mac_addr}"
+ fi
+
+ dladm create-vnic -l ${link} ${vlan_opt} ${mac_addr_opt} ${iface}
+ ifconfig ${iface} plumb
+
+ if [[ ${ip} == "dhcp" ]]; then
+ # We ignore errors here because the most common one is that DHCP
+ # is already running.
+
+ if [[ -n ${dhcp_primary} ]]; then
+ ifconfig ${iface} dhcp primary || /bin/true
+ else
+ ifconfig ${iface} dhcp || /bin/true
+ fi
+ else
+ ifconfig ${iface} inet ${ip} netmask ${netmask} up
+ fi
+ eval "vnic_${iface}_up=true"
+}
+
+if smf_is_globalzone; then
+
+ dladm init-phys
+
+ # The next command is for logging purposes only
+ log_if_state before
+
+ # Load sysinfo variables with SYSINFO_ prefix
+ load_sdc_sysinfo
+ # Load config variables with CONFIG_ prefix, and sets the headnode variable
+ load_sdc_config
+ # Load boot params with BOOT_ prefix
+ load_sdc_bootparams
+
+ # Setup admin NIC
+ if [[ -n ${SYSINFO_NIC_admin} ]]; then
+ ifconfig ${SYSINFO_NIC_admin} plumb
+ if [[ ${headnode} == "true" ]]; then
+ if [[ -n ${CONFIG_admin_ip} ]] && [[ -n ${CONFIG_admin_netmask} ]];
+ then
+ ifconfig ${SYSINFO_NIC_admin} inet ${CONFIG_admin_ip} \
+ netmask ${CONFIG_admin_netmask} up
+ ADMIN_NIC_UP=true
+
+ # also setup resolv.conf if we can
+ if [[ -n ${CONFIG_dns_domain} ]] && [[ -n ${CONFIG_dns_resolvers} ]]; then
+ echo "search ${CONFIG_dns_domain}" > /etc/resolv.conf
+ for serv in $(echo "${CONFIG_dns_resolvers}" | sed -e "s/,/ /g"); do
+ echo "nameserver ${serv}" >> /etc/resolv.conf
+ done
+ fi
+ else
+ echo "ERROR: headnode but no admin_{ip,netmask} in config, not bringing up admin network."
+ # Set a flag, but try to plumb the other interfaces anyway
+ ADMIN_NIC_MISCONFIGURED=true
+ fi
+ elif [[ -n $(/usr/bin/bootparams | grep "^smartos") ]]; then
+ if [[ -n ${CONFIG_admin_ip} ]] && [[ -n ${CONFIG_admin_netmask} ]]; then
+ ifconfig ${SYSINFO_NIC_admin} inet ${CONFIG_admin_ip} \
+ netmask ${CONFIG_admin_netmask} up
+ ADMIN_NIC_UP=true
+
+ # also setup resolv.conf if we can
+ if [[ -n ${CONFIG_dns_domain} ]] && [[ -n ${CONFIG_dns_resolvers} ]]; then
+ echo "search ${CONFIG_dns_domain}" > /etc/resolv.conf
+ for serv in $(echo "${CONFIG_dns_resolvers}" | sed -e "s/,/ /g"); do
+ echo "nameserver ${serv}" >> /etc/resolv.conf
+ done
+ fi
+ else
+ ifconfig ${SYSINFO_NIC_admin} dhcp || /bin/true
+ ADMIN_NIC_UP=true
+ fi
+
+ else
+ # We ignore errors here because the most common one is that DHCP is
+ # already running.
+ ifconfig ${SYSINFO_NIC_admin} dhcp || /bin/true
+ ADMIN_NIC_UP=true
+ fi
+ # If on VMWare, create a bridge which allows traffic to flow correctly to the host-only network
+ if [[ "${ADMIN_NIC_UP}" == "true" ]] && [[ ${SYSINFO_Product} == "VMware Virtual Platform" ]]; then
+ dladm create-bridge -l ${SYSINFO_NIC_admin} vmwarebr
+ fi
+ else
+ echo "ERROR: admin NIC not found, unable to bring up admin network."
+ exit ${SMF_EXIT_ERR_CONFIG}
+ fi
+
+ # Setup external NIC
+ if [[ -n ${SYSINFO_NIC_external} ]] && [[ -n "${CONFIG_external_ip}" ]]; then
+ vnic_up "${SYSINFO_NIC_external}" "external0" "${CONFIG_external_ip}" \
+ "${CONFIG_external_netmask}" "${CONFIG_external_vlan_id}" "" "primary"
+ fi
+
+ # Set up the GZ to NAT for Coal
+ if [[ -n ${SYSINFO_NIC_external} ]] && [[ -n "${CONFIG_external_ip}" ]] &&
+ [[ "${CONFIG_coal}" == "true" ]]; then
+
+ # Convert the admin IP and netmask to CIDR notation
+ CIDR=$(ip_netmask_to_cidr ${CONFIG_admin_ip} ${CONFIG_admin_netmask})
+
+ # Allow zones to reach the internet using the global zone as a router
+ cat >> /etc/ipf/ipnat.conf <<IPNAT
+map external0 ${CIDR} -> 0.0.0.0/32
+map external0 ${CIDR} -> 0.0.0.0/32 portmap tcp/udp auto
+IPNAT
+ fi
+
+ # Use headnode_default_gateway if set, otherwise fall back to admin_gateway
+ # if that's set.
+ if [[ -n "${CONFIG_headnode_default_gateway}" ]]; then
+ echo "${CONFIG_headnode_default_gateway}" > /etc/defaultrouter
+ elif [[ -n ${CONFIG_admin_gateway} ]]; then
+ echo "${CONFIG_admin_gateway}" > /etc/defaultrouter
+ fi
+
+ # Setup extra nics, if specified in the config file
+ nic_tags="${SYSINFO_Nic_Tags}"
+ if [[ -n "${nic_tags}" ]]; then
+ tags=(${nic_tags//,/ })
+
+ bootparam_ip_keys=$(sdc_bootparams_keys | grep -- "-ip$" || true)
+ config_ip_keys=$(sdc_config_keys | grep "_ip$" || true)
+ for tag in "${tags[@]}"; do
+
+ eval "link=\${SYSINFO_NIC_${tag}}"
+ if [[ -z "${link}" ]]; then
+ echo "WARNING: No link found with tag '${tag}'"
+ continue
+ fi
+
+ for key in ${config_ip_keys}; do
+ if [[ ${key} == ${tag}[0-9]_ip ]] || [[ ${key} == ${tag}[0-9][0-9]_ip ]]; then
+ iface=${key//_ip/}
+ #echo " iface=$iface"
+ eval "ip=\${CONFIG_${iface}_ip}"
+ eval "netmask=\${CONFIG_${iface}_netmask}"
+ eval "vlan=\${CONFIG_${iface}_vlan_id}"
+ eval "macaddr=\${CONFIG_${iface}_mac}"
+
+ echo vnic_up "${link}" "${iface}" "${ip}" "${netmask}" "${vlan}" "${macaddr}"
+ vnic_up "${link}" "${iface}" "${ip}" "${netmask}" "${vlan}" "${macaddr}"
+ fi
+ done
+
+ for key in ${bootparam_ip_keys}; do
+ if [[ ${key} == ${tag}[0-9]-ip ]] || [[ ${key} == ${tag}[0-9][0-9]-ip ]]; then
+ iface=${key//-ip/}
+ eval "ip=\${BOOT_${iface}_ip}"
+ eval "netmask=\${BOOT_${iface}_netmask}"
+ eval "vlan=\${BOOT_${iface}_vlan_id}"
+ eval "macaddr=\${BOOT_${iface}_mac}"
+ echo vnic_up "${link}" "${iface}" "${ip}" "${netmask}" "${vlan}" "${macaddr}"
+ vnic_up "${link}" "${iface}" "${ip}" "${netmask}" "${vlan}" "${macaddr}"
+ fi
+ done
+
+ done
+ fi
+else
+ # Non-global zones
+ for iface in `dladm show-vnic -p -o link`; do
+ ifconfig ${iface} plumb
+ if [[ -f /etc/dhcp.${iface} || ! -f /etc/hostname.${iface} ]]; then
+ ifconfig ${iface} dhcp
+ else
+ ifconfig ${iface} inet `cat /etc/hostname.${iface}` up
+ fi
+ done
+fi
+
+log_if_state after
+
+# Since we hopefully made networking changes here, update the sysinfo cache
+if smf_is_globalzone; then
+ /usr/bin/sysinfo -u
+fi
+
+# If the admin nic was missing config options, exit with a config error
+if [[ -n "${ADMIN_NIC_MISCONFIGURED}" ]]; then
+ exit ${SMF_EXIT_ERR_CONFIG}
+fi
+
+# Any non-loopback IPv4 interfaces with usable addresses up?
+if [[ -n "`/sbin/ifconfig -a4u`" ]]; then
+ /sbin/ifconfig -a4u | while read intf addr rest; do
+ [[ ${intf} == "inet" ]] && [[ ${addr} != "127.0.0.1" ]] &&
+ [[ ${addr} != "0.0.0.0" ]] && exit ${SMF_EXIT_OK}
+ done && exit ${SMF_EXIT_OK}
+fi
+
+# Any DHCP interfaces started?
+[[ -n "`/sbin/ifconfig -a4 dhcp status 2>/dev/null`" ]] && exit ${SMF_EXIT_OK}
+
+# Any non-loopback IPv6 interfaces up?
+if [[ -n "`/sbin/ifconfig -au6`" ]]; then
+ /sbin/ifconfig -au6 | while read intf addr rest; do
+ [[ ${intf} = "inet6" ]] && [[ ${addr} != "::1/128" ]] && exit ${SMF_EXIT_OK}
+ done && exit ${SMF_EXIT_OK}
+fi
+
+# This service was supposed to configure something yet didn't. Exit
+# with config error.
+exit ${SMF_EXIT_ERR_CONFIG}
218 lib/svc/method/smartdc-config
@@ -0,0 +1,218 @@
+#!/bin/bash
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2011 Joyent, Inc. All rights reserved.
+# Use is subject to license terms.
+
+set -o errexit
+set -o xtrace
+
+. /lib/svc/share/smf_include.sh
+. /lib/sdc/config.sh
+
+export PATH="/usr/sbin:/sbin:/usr/bin"
+
+set_root_password() {
+ enc_password=$1
+
+ sed -e "s|^root:[^\:]*:|root:${enc_password}:|" /etc/shadow > /etc/shadow.new \
+ && chmod 400 /etc/shadow.new \
+ && mv /etc/shadow.new /etc/shadow
+}
+
+set_ntp_hosts() {
+ ntp_hosts=$1
+
+ (
+ for i in $(echo ${ntp_hosts} | sed -e "s/,/ /g"); do
+ echo "server ${i}"
+ done
+ if [[ -f /etc/inet/ntp.conf ]]; then
+ cat /etc/inet/ntp.conf | grep -v "^server"
+ fi
+ ) > /etc/inet/ntp.conf.new \
+ && mv /etc/inet/ntp.conf.new /etc/inet/ntp.conf
+}
+
+case "$1" in
+'start')
+
+ # If we're a headnode, see if we have to do interactive configuration.
+ if /bin/bootparams | grep "^headnode=true" > /dev/null 2>&1; then
+ USB_PATH=/mnt/`svcprop -p "joyentfs/usb_mountpoint" svc:/system/filesystem/smartdc:default`
+
+ # Check for config and run interactive if it doesn't exist.
+ if [[ ! -f ${USB_PATH}/config ]]; then
+ if /bin/bootparams | grep "^noimport=true" >/dev/null 2>&1; then
+ # Skipping interactive config, bypass rest of script.
+ exit $SMF_EXIT_OK
+ fi
+
+ # Start interactive config on console and ttys
+
+ ${USB_PATH}/scripts/prompt-config.sh "${USB_PATH}" \
+ </dev/console >&/dev/console &
+ cnt=1
+
+ if [ -c /dev/ttya ]; then
+ ${USB_PATH}/scripts/prompt-config.sh "${USB_PATH}" \
+ </dev/ttya >&/dev/ttya &
+ cnt=`expr $cnt + 1`
+ fi
+
+ if [ -c /dev/ttyb ]; then
+ ${USB_PATH}/scripts/prompt-config.sh "${USB_PATH}" \
+ </dev/ttyb >&/dev/ttyb &
+ cnt=`expr $cnt + 1`
+ fi
+
+ # Wait for one of the interactive configs to finish
+ while [ true ]; do
+ got=`jobs -p | wc -l`
+ [ $got -lt $cnt ] && break
+ sleep 1
+ done
+
+ # If user quit from interactive configuration then we're done.
+ [[ ! -f ${USB_PATH}/config ]] && exit $SMF_EXIT_OK
+ fi
+ elif /bin/bootparams | grep "^smartos=true" > /dev/null 2>&1; then
+ USB_PATH=/`svcprop -p "joyentfs/usb_copy_path" svc:/system/filesystem/smartdc:default`
+
+ # Check for config and run interactive if it doesn't exist.
+ if [[ ! -f ${USB_PATH}/config ]]; then
+ if /bin/bootparams | grep "^noimport=true" >/dev/null 2>&1; then
+ # Skipping interactive config, bypass rest of script.
+ exit $SMF_EXIT_OK
+ fi
+
+ /smartdc/bin/smartos_prompt_config.sh "${USB_PATH}" \
+ </dev/console >&/dev/console
+
+ # If user quit from interactive configuration then we're done.
+ [[ ! -f ${USB_PATH}/config ]] && exit $SMF_EXIT_OK
+ fi
+ fi
+
+ # This puts config vars in CONFIG_
+ load_sdc_config
+ load_sdc_sysinfo
+
+ # Write the info about this datacenter to /.dcinfo so we can use in the GZ
+ echo "SDC_DATACENTER_NAME='${CONFIG_datacenter_name}'" > /.dcinfo
+ if [[ "${SYSINFO_Bootparam_headnode}" == "true" ]]; then
+ echo "SDC_DATACENTER_HEADNODE_ID=${CONFIG_datacenter_headnode_id}" \
+ >> /.dcinfo
+ fi
+
+ if [[ -n "${SYSINFO_Bootparam_smartos}" && -f /usbkey/shadow ]]; then
+ echo "setting root password from /usbkey/shadow"
+ else
+ # Boot parameter takes precidence over config
+ if [[ -n "${SYSINFO_Bootparam_root_shadow}" ]]; then
+ set_root_password "${SYSINFO_Bootparam_root_shadow}"
+ echo "Set root password boot parameters."
+ elif [[ -n "${CONFIG_root_shadow}" ]]; then
+ set_root_password "${CONFIG_root_shadow}"
+ echo "Set root password from config."
+ else
+ echo "No root shadow entry in the config, cannot set."
+ fi
+ fi
+ # Set authorized_keys for root
+ if [[ -n "${CONFIG_root_authorized_keys_file}" ]] \
+ && [[ -n "${CONFIG_config_inc_dir}" ]] \
+ && [[ -d "${CONFIG_config_inc_dir}" ]] \
+ && [[ -f "${CONFIG_config_inc_dir}/${CONFIG_root_authorized_keys_file}" ]]; then
+
+ mkdir -p /root/.ssh
+ cp "${CONFIG_config_inc_dir}/${CONFIG_root_authorized_keys_file}" /root/.ssh/authorized_keys
+ chmod 0600 /root/.ssh/authorized_keys
+ chmod 0700 /root/.ssh
+ fi
+
+ if [[ -n "${CONFIG_ntp_conf_file}" ]] \
+ && [[ -n "${CONFIG_config_inc_dir}" ]] \
+ && [[ -d "${CONFIG_config_inc_dir}" ]] \
+ && [[ -f "${CONFIG_config_inc_dir}/${CONFIG_ntp_conf_file}" ]]; then
+
+ cp "${CONFIG_config_inc_dir}/${CONFIG_ntp_conf_file}" /etc/inet/ntp.conf
+ echo "Copied ntp config."
+
+ elif [[ -n "${CONFIG_ntp_hosts}" ]]; then
+ # split on ',' and resolve bits that aren't IP addresses then merge back
+ servers=""
+ for entry in $(echo "${CONFIG_ntp_hosts}" | tr ',' ' '); do
+ if echo "${entry}" | grep "^[0-9,\.]*$" >/dev/null 2>&1; then
+ # entry is an IP
+ [[ -n ${servers} ]] && entry=",${entry}"
+ servers="${servers}${entry}"
+ else
+ # DNS, try to resolve
+ for s in $( (dig ${entry} +short || /bin/true) | grep "^[0-9]" | xargs); do
+ [[ -n ${servers} ]] && s=",${s}"
+ servers="${servers}${s}"
+ done
+ fi
+ done
+
+ if [[ -n ${servers} ]]; then
+ set_ntp_hosts "${servers}"
+ echo "Set ntp hosts (${servers})."
+ fi
+ else
+ # No NTP hosts set, use some from pool.ntp.org
+ servers=$( (dig pool.ntp.org +short || /bin/true) | grep "^[0-9]" | xargs | sed -e "s/ /,/g")
+
+ # Note, if we don't find some here, we just go with ones already in the file.
+ if [[ -n ${servers} ]]; then
+ set_ntp_hosts "${servers}"
+ echo "Set default ntp hosts (${servers})."
+ fi
+ fi
+ # set the keymap. For dvorak for instance
+ if [[ -n ${CONFIG_default_keymap} ]]; then
+ /usr/bin/loadkeys ${CONFIG_default_keymap}
+ fi
+
+ # Enable virtual terminals to support interactive installation
+ vtdaemon="svc:/system/vtdaemon"
+ svccfg -s ${vtdaemon} setprop options/hotkeys=true
+ svcadm refresh ${vtdaemon}
+ svcadm enable ${vtdaemon}
+ svcadm enable svc:/system/console-login:vt2
+ svcadm enable svc:/system/console-login:vt3
+ svcadm enable svc:/system/console-login:vt4
+ svcadm enable svc:/system/console-login:vt5
+ svcadm enable svc:/system/console-login:vt6
+
+ ;;
+
+'stop')
+ ;;
+
+*)
+ echo "Usage: $0 { start | stop }"
+ exit $SMF_EXIT_ERR_FATAL
+ ;;
+esac
+exit $SMF_EXIT_OK
13 manifest
@@ -0,0 +1,13 @@
+d lib/ 0755 root bin
+d lib/svc 0755 root bin
+d lib/svc/method 0755 root bin
+f lib/svc/method/fs-joyent 0555 root bin
+f lib/svc/method/smartdc-config 0555 root bin
+f lib/svc/method/net-physical 0555 root bin
+d smartdc 0755 root bin
+d smartdc/bin 0755 root bin
+f smartdc/bin/smartos_prompt_config.sh 0555 root bin
+d root 0755 root root
+f root/.bash_profile 0644 root root
+f root/.bashrc 0644 root root
+f root/.profile 0644 root root
2  root/.bash_profile
@@ -0,0 +1,2 @@
+[ -f /root/.profile ] && source /root/.profile
+[ -f /root/.bashrc ] && source /root/.bashrc
35 root/.bashrc
@@ -0,0 +1,35 @@
+if [ "$PS1" ]; then
+ shopt -s checkwinsize
+ if [[ -f /.dcinfo ]]; then
+ . /.dcinfo
+ DC_NAME="${SDC_DATACENTER_NAME}"
+ DC_HEADNODE_ID="${SDC_DATACENTER_HEADNODE_ID}"
+ fi
+ if [[ -n "${DC_NAME}" && -n "${DC_HEADNODE_ID}" ]]; then
+ PS1="[\u@\h (${DC_NAME}:${DC_HEADNODE_ID}) \w]\\$ "
+ elif [[ -n "${DC_NAME}" ]]; then
+ PS1="[\u@\h (${DC_NAME}) \w]\\$ "
+ else
+ PS1="[\u@\h \w]\\$ "
+ fi
+ alias ll='ls -lF'
+ [ -n "${SSH_CLIENT}" ] && export PROMPT_COMMAND='echo -ne "\033]0;${HOSTNAME} \007" && history -a'
+fi
+
+# Load bash completion
+[ -f /etc/bash/bash_completion ] && . /etc/bash/bash_completion
+
+if [ "${TERM}" == "screen" ]; then
+ export TERM=xterm-color
+fi
+
+svclog() {
+ if [[ -z "$PAGER" ]]; then
+ PAGER=less
+ fi
+ $PAGER `svcs -L $1`
+}
+
+svclogf() {
+ /usr/bin/tail -f `svcs -L $1`
+}
4 root/.profile
@@ -0,0 +1,4 @@
+PATH=/usr/bin:/usr/sbin:/smartdc/bin:/opt/local/bin:/opt/local/sbin
+MANPATH=/usr/share/man:/opt/local/man:/smartdc/man
+PAGER=less
+export PATH MANPATH PAGER
684 smartdc/bin/smartos_prompt_config.sh
@@ -0,0 +1,684 @@
+#!/usr/bin/bash
+
+# XXX - TODO
+# - if $ntp_hosts == "local", configure ntp for no external time source
+# - try to figure out why ^C doesn't intr when running under SMF
+
+PATH=/usr/sbin:/usr/bin
+export PATH
+
+# Defaults
+datacenter_headnode_id=0
+mail_to="root@localhost"
+ntp_hosts="pool.ntp.org"
+dns_resolver1="8.8.8.8"
+dns_resolver2="8.8.4.4"
+
+# Globals
+declare -a states
+declare -a nics
+declare -a assigned
+declare -a DISK_LIST
+
+sigexit()
+{
+ echo
+ echo "System configuration has not been completed."
+ echo "You must reboot to re-run system configuration."
+ exit 0
+}
+
+#
+# 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
+# the host portion of the netmask (e.g. netmask 224 -> 31).
+# Param 1 is the field and param 2 the mask for that field.
+#
+max_fld()
+{
+ if [ $2 -eq 255 ]; then
+ fmax=$1
+ else
+ fmax=$((255 & ~$2))
+ fi
+}
+
+#
+# Converts an IP and netmask to a network
+# For example: 10.99.99.7 + 255.255.255.0 -> 10.99.99.0
+# Each field is in the net_a, net_b, net_c and net_d variables.
+# Also, host_addr stores the address of the host w/o the network number (e.g.
+# 7 in the 10.99.99.7 example above). Also, max_host stores the max. host
+# number (e.g. 10.99.99.254 in the example above).
+#
+ip_netmask_to_network()
+{
+ IP=$1
+ NETMASK=$2
+
+ OLDIFS=$IFS
+ IFS=.
+ set -- $IP
+ net_a=$1
+ net_b=$2
+ net_c=$3
+ net_d=$4
+ addr_d=$net_d
+
+ set -- $NETMASK
+
+ # Calculate the maximum host address
+ max_fld "$net_a" "$1"
+ max_a=$fmax
+ max_fld "$net_b" "$2"
+ max_b=$fmax
+ max_fld "$net_c" "$3"
+ max_c=$fmax
+ max_fld "$net_d" "$4"
+ max_d=$(expr $fmax - 1)
+ max_host="$max_a.$max_b.$max_c.$max_d"
+
+ net_a=$(($net_a & $1))
+ net_b=$(($net_b & $2))
+ net_c=$(($net_c & $3))
+ net_d=$(($net_d & $4))
+
+ host_addr=$(($addr_d & ~$4))
+ IFS=$OLDIFS
+}
+
+# Tests whether entire string is a number.
+isdigit ()
+{
+ [ $# -eq 1 ] || return 1
+
+ case $1 in
+ *[!0-9]*|"") return 1;;
+ *) return 0;;
+ esac
+}
+
+# Tests network numner (num.num.num.num)
+is_net()
+{
+ NET=$1
+
+ OLDIFS=$IFS
+ IFS=.
+ set -- $NET
+ a=$1
+ b=$2
+ c=$3
+ d=$4
+ IFS=$OLDIFS
+
+ isdigit "$a" || return 1
+ isdigit "$b" || return 1
+ isdigit "$c" || return 1
+ isdigit "$d" || return 1
+
+ [ -z $a ] && return 1
+ [ -z $b ] && return 1
+ [ -z $c ] && return 1
+ [ -z $d ] && return 1
+
+ [ $a -lt 0 ] && return 1
+ [ $a -gt 255 ] && return 1
+ [ $b -lt 0 ] && return 1
+ [ $b -gt 255 ] && return 1
+ [ $c -lt 0 ] && return 1
+ [ $c -gt 255 ] && return 1
+ [ $d -lt 0 ] && return 1
+ # Make sure the last field isn't the broadcast addr.
+ [ $d -ge 255 ] && return 1
+ return 0
+}
+
+# Optional input
+promptopt()
+{
+ val=
+ printf "%s [press enter for none]: " "$1"
+ read val
+}
+
+promptval()
+{
+ val=""
+ def="$2"
+ while [ -z "$val" ]; do
+ if [ -n "$def" ]; then
+ printf "%s [%s]: " "$1" "$def"
+ else
+ printf "%s: " "$1"
+ fi
+ read val
+ [ -z "$val" ] && val="$def"
+ [ -n "$val" ] && break
+ echo "A value must be provided."
+ done
+}
+
+# Input must be a valid network number (see is_net())
+promptnet()
+{
+ val=""
+ def="$2"
+ while [ -z "$val" ]; do
+ if [ -n "$def" ]; then
+ printf "%s [%s]: " "$1" "$def"
+ else
+ printf "%s: " "$1"
+ fi
+ read val
+ [ -z "$val" ] && val="$def"
+ if [[ "$val" != "dhcp" ]]; then
+ is_net "$val" || val=""
+ fi
+ [ -n "$val" ] && break
+ echo "A valid network number (n.n.n.n) or 'dhcp' must be provided."
+ done
+}
+
+printnics()
+{
+ i=1
+ printf "%-6s %-9s %-18s %-7s %-10s\n" "Number" "Link" "MAC Address" \
+ "State" "Network"
+ while [ $i -le $nic_cnt ]; do
+ printf "%-6d %-9s %-18s %-7s %-10s\n" $i ${nics[$i]} \
+ ${macs[$i]} ${states[$i]} ${assigned[i]}
+ ((i++))
+ done
+}
+
+# Must choose a valid NIC on this system
+promptnic()
+{
+ if [[ $nic_cnt -eq 1 ]]; then
+ val="${macs[1]}"
+ return
+ fi
+
+ printnics
+ num=0
+ while [ /usr/bin/true ]; do
+ printf "Enter the number of the NIC for the %s interface: " \
+ "$1"
+ read num
+ if ! [[ "$num" =~ ^[0-9]+$ ]] ; then
+ echo ""
+ elif [ $num -ge 1 -a $num -le $nic_cnt ]; then
+ mac_addr="${macs[$num]}"
+ assigned[$num]=$1
+ break
+ fi
+ # echo "You must choose between 1 and $nic_cnt."
+ updatenicstates
+ printnics
+ done
+
+ val=$mac_addr
+}
+
+promptpw()
+{
+ while [ /usr/bin/true ]; do
+ val=""
+ while [ -z "$val" ]; do
+ printf "%s: " "$1"
+ stty -echo
+ read val
+ stty echo
+ echo
+ if [ -n "$val" ]; then
+ if [ "$2" == "chklen" -a ${#val} -lt 6 ]; then
+ echo "The password must be at least" \
+ "6 characters long."
+ val=""
+ else
+ break
+ fi
+ else
+ echo "A value must be provided."
+ fi
+ done
+
+ cval=""
+ while [ -z "$cval" ]; do
+ printf "%s: " "Confirm password"
+ stty -echo
+ read cval
+ stty echo
+ echo
+ [ -n "$cval" ] && break
+ echo "A value must be provided."
+ done
+
+ [ "$val" == "$cval" ] && break
+
+ echo "The entries do not match, please re-enter."
+ done
+}
+
+promptpool()
+{
+ disks=$(disklist -n)
+ while [[ /usr/bin/true ]]; do
+ echo "Please select disks for the storage pool, space separated"
+ echo ""
+ printf "Valid choices are ${disks}"
+ echo ""
+ bad=""
+ read val
+ 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
+ break
+ fi
+ done
+
+}
+create_dump()
+{
+ # Get avail zpool size - this assumes we're not using any space yet.
+ base_size=`zfs get -H -p -o value available ${SYS_ZPOOL}`
+ # Convert to MB
+ base_size=`expr $base_size / 1000000`
+ # Calculate 5% of that
+ base_size=`expr $base_size / 20`
+ # Cap it at 4GB
+ [ ${base_size} -gt 4096 ] && base_size=4096
+
+ # Create the dump zvol
+ zfs create -V ${base_size}mb ${SYS_ZPOOL}/dump || \
+ fatal "failed to create the dump zvol"
+ dumpadm -a /dev/zvol/dsk/${SYS_ZPOOL}/dump
+}
+
+#
+# Setup the persistent datasets on the zpool.
+#
+setup_datasets()
+{
+ datasets=$(zfs list -H -o name | xargs)
+
+ if ! echo $datasets | grep dump > /dev/null; then
+ printf "%-56s" "Making dump zvol... " >&4
+ create_dump
+ printf "%4s\n" "done" >&4
+ fi
+
+ if ! echo $datasets | grep ${CONFDS} > /dev/null; then
+ printf "%-56s" "Initializing config dataset for zones... " >&4
+ zfs create ${CONFDS} || fatal "failed to create the config dataset"
+ chmod 755 /${CONFDS}
+ cp -p /etc/zones/* /${CONFDS}
+ zfs set mountpoint=legacy ${CONFDS}
+ printf "%4s\n" "done" >&4
+ fi
+
+ if ! echo $datasets | grep ${USBKEYDS} > /dev/null; then
+ if [[ -n $(/bin/bootparams | grep "^smartos=true") ]]; then
+ printf "%-56s" "Creating config dataset... " >&4
+ zfs create -o mountpoint=legacy ${USBKEYDS} || \
+ fatal "failed to create the config dataset"
+ mkdir /usbkey
+ mount -F zfs ${USBKEYDS} /usbkey
+ printf "%4s\n" "done" >&4
+ fi
+ fi
+
+ if ! echo $datasets | grep ${COREDS} > /dev/null; then
+ printf "%-56s" "Creating global cores dataset... " >&4
+ zfs create -o quota=10g -o mountpoint=/${SYS_ZPOOL}/global/cores \
+ -o compression=gzip ${COREDS} || \
+ fatal "failed to create the cores dataset"
+ printf "%4s\n" "done" >&4
+ fi
+
+ if ! echo $datasets | grep ${OPTDS} > /dev/null; then
+ printf "%-56s" "Creating opt dataset... " >&4
+ zfs create -o mountpoint=legacy ${OPTDS} || \
+ fatal "failed to create the opt dataset"
+ printf "%4s\n" "done" >&4
+ fi
+
+ if ! echo $datasets | grep ${VARDS} > /dev/null; then
+ printf "%-56s" "Initializing var dataset... " >&4
+ zfs create ${VARDS} || \
+ fatal "failed to create the var dataset"
+ chmod 755 /${VARDS}
+ cd /var
+ if ( ! find . -print | cpio -pdm /${VARDS} 2>/dev/null ); then
+ fatal "failed to initialize the var directory"
+ fi
+
+ zfs set mountpoint=legacy ${VARDS}
+ printf "%4s\n" "done" >&4
+ fi
+}
+
+create_swap()
+{
+ swapsize=$1
+
+ if ! zfs list -H -o name ${SWAPVOL}; then
+ printf "%-56s" "Creating swap zvol... " >&4
+
+ #
+ # We cannot allow the swap size to be less than the size of DRAM, lest
+ # we run into the availrmem double accounting issue for locked
+ # anonymous memory that is backed by in-memory swap (which will
+ # severely and artificially limit VM tenancy). We will therfore not
+ # create a swap device smaller than DRAM -- but we still allow for the
+ # configuration variable to account for actual consumed space by using
+ # it to set the refreservation on the swap volume if/when the
+ # specified size is smaller than DRAM.
+ #
+ minsize=$(swap_in_GiB 1x)
+
+ if [[ $minsize -gt $swapsize ]]; then
+ zfs create -V ${minsize}g ${SWAPVOL}
+ zfs set refreservation=${swapsize}g ${SWAPVOL}
+ else
+ zfs create -V ${swapsize}g ${SWAPVOL}
+ fi
+
+ swap -a /dev/zvol/dsk/${SWAPVOL}
+ printf "%4s\n" "done" >&4
+ fi
+}
+create_zpool()
+{
+ disks=$1
+ pool=zones
+
+ # If the pool already exists, don't create it again.
+ if /usr/sbin/zpool list -H -o name $pool; then
+ return 0
+ fi
+
+ disk_count=$(echo "${disks}" | wc -w | tr -d ' ')
+ printf "%-56s" "Creating pool $pool... " >&4
+
+ # 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}"
+ zfs set atime=off ${pool} || \
+ fatal "failed to set atime=off for pool ${pool}"
+
+ printf "%4s\n" "done" >&4
+}
+create_zpools()
+{
+ devs=$1
+
+ export SYS_ZPOOL="zones"
+ create_zpool $devs
+ sleep 5
+
+ svccfg -s svc:/system/smartdc/init setprop config/zpool="zones"
+ svccfg -s svc:/system/smartdc/init:default refresh
+
+ export CONFDS=${SYS_ZPOOL}/config
+ export COREDS=${SYS_ZPOOL}/cores
+ export OPTDS=${SYS_ZPOOL}/opt
+ export VARDS=${SYS_ZPOOL}/var
+ export USBKEYDS=${SYS_ZPOOL}/usbkey
+ export SWAPVOL=${SYS_ZPOOL}/swap
+
+ setup_datasets
+ #
+ # Since there may be more than one storage pool on the system, put a
+ # file with a certain name in the actual "system" pool.
+ #
+ touch /${SYS_ZPOOL}/.system_pool
+}
+updatenicstates()
+{
+ states=(1)
+ #states[0]=1
+ while IFS=: read -r link state ; do
+ states=( ${states[@]-} $(echo "$state") )
+ done < <(dladm show-phys -po link,state 2>/dev/null)
+}
+
+printheader()
+{
+ local newline=
+ local cols=`tput cols`
+ local subheader=$1
+
+ if [ $cols -gt 80 ] ;then
+ newline='\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"
+
+}
+
+trap sigexit SIGINT
+
+#
+# Get local NIC info
+#
+nic_cnt=0
+
+while IFS=: read -r link addr ; do
+ ((nic_cnt++))
+ nics[$nic_cnt]=$link
+ macs[$nic_cnt]=`echo $addr | sed 's/\\\:/:/g'`
+ assigned[$nic_cnt]="-"
+done < <(dladm show-phys -pmo link,address 2>/dev/null)
+
+if [[ $nic_cnt -lt 1 ]]; then
+ echo "ERROR: cannot configure the system, no NICs were found."
+ exit 0
+fi
+
+ifconfig -a plumb
+updatenicstates
+
+export TERM=sun-color
+export TERM=xterm-color
+stty erase ^H
+
+printheader "Copyright 2011, Joyent, Inc."
+
+message="
+You must answer the following questions to configure the system.
+You will have a chance to review and correct your answers, as well as a
+chance to edit the final configuration, before it is applied.
+
+Would you like to continue with configuration? [Y/n]"
+
+printf "$message"
+read continue;
+if [[ $continue == 'n' ]]; then
+ exit 0
+fi
+#
+# Main loop to prompt for user input
+#
+while [ /usr/bin/true ]; do
+
+ printheader "Networking"
+
+ promptnic "'admin'"
+ admin_nic="$val"
+
+ promptnet "IP address (or 'dhcp' )" "$admin_ip"
+ admin_ip="$val"
+ if [[ $admin_ip != 'dhcp' ]]; then
+ promptnet "netmask" "$admin_netmask"
+ admin_netmask="$val"
+
+ printheader "Networking - Continued"
+ message=""
+
+ printf "$message"
+
+ message="
+ The default gateway will determine which network will be used to connect to
+ other networks.\n\n"
+
+ printf "$message"
+
+ promptnet "Enter the default gateway IP" "$headnode_default_gateway"
+ headnode_default_gateway="$val"
+
+ promptval "Enter the Primary DNS server IP" "$dns_resolver1"
+ dns_resolver1="$val"
+ promptval "Enter the Secondary DNS server IP" "$dns_resolver2"
+ dns_resolver2="$val"
+ promptval "Enter the domain name" "$domainname"
+ domainname="$val"
+ promptval "Default DNS search domain" "$dns_domain"
+ dns_domain="$val"
+ fi
+ printheader "Storage"
+ promptpool
+
+ printheader "Account Information"
+
+ promptpw "Enter root password" "nolen"
+ root_shadow="$val"
+
+ printheader "Verify Configuration"
+ message=""
+
+ printf "$message"
+
+ echo "Verify that the following values are correct:"
+ echo
+ echo "MAC address: $admin_nic"
+ echo "IP address: $admin_ip"
+ if [[ $admin_ip != 'dhcp' ]]; then
+ echo "Netmask: $admin_netmask"
+ echo "Gateway router IP address: $headnode_default_gateway"
+ echo "DNS servers: $dns_resolver1,$dns_resolver2"
+ echo "Default DNS search domain: $dns_domain"
+ echo "NTP server: $ntp_hosts"
+ echo "Domain name: $domainname"
+ echo
+ fi
+ promptval "Is this correct?" "y"
+ [ "$val" == "y" ] && break
+ clear
+done
+admin_network="$net_a.$net_b.$net_c.$net_d"
+
+#
+# Generate config file
+#
+tmp_config=/tmp_config
+touch $tmp_config
+chmod 600 $tmp_config
+
+echo "#" >$tmp_config
+echo "# This file was auto-generated and must be source-able by bash." \
+ >>$tmp_config
+echo "#" >>$tmp_config
+echo >>$tmp_config
+
+# If in a VM, setup coal so networking will work.
+platform=$(smbios -t1 | nawk '{if ($1 == "Product:") print $2}')
+[ "$platform" == "VMware" ] && echo "coal=true" >>$tmp_config
+
+echo "swap=0.25x" >>$tmp_config
+echo >>$tmp_config
+
+echo "# admin_nic is the nic admin_ip will be connected to for headnode zones."\
+ >>$tmp_config
+echo "admin_nic=$admin_nic" >>$tmp_config
+echo "admin_ip=$admin_ip" >>$tmp_config
+echo "admin_netmask=$admin_netmask" >>$tmp_config
+echo "admin_network=$admin_network" >>$tmp_config
+echo "admin_gateway=$admin_ip" >>$tmp_config
+echo >>$tmp_config
+
+echo "headnode_default_gateway=$headnode_default_gateway" >>$tmp_config
+echo >>$tmp_config
+
+echo "dns_resolvers=$dns_resolver1,$dns_resolver2" >>$tmp_config
+echo "dns_domain=$dns_domain" >>$tmp_config
+echo >>$tmp_config
+
+
+echo "ntp_hosts=$ntp_hosts" >>$tmp_config
+
+echo "compute_node_ntp_hosts=$admin_ip" >>$tmp_config
+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
+
+echo
+echo "Your data pool will be created with the following disks:"
+echo $DISK_LIST
+echo "*********************************************"
+echo "* This will erase *ALL DATA* on these disks *"
+echo "*********************************************"
+promptval "are you sure?" "n"
+[ "$val" == "y" ] && (create_zpools $DISK_LIST)
+
+clear
+echo "The system will now finish configuration and reboot. Please wait..."
+mv $tmp_config /usbkey/config
+
+# set the root password
+root_shadow=$(/usr/lib/cryptpass "$root_shadow")
+sed -e "s|^root:[^\:]*:|root:${root_shadow}:|" /etc/shadow > /usbkey/shadow \
+ && chmod 400 /usbkey/shadow
+
+cp -rp /etc/ssh /usbkey/ssh
+
+reboot
+

1 comment on commit 38e1b9e

Piotr Sikora

I believe you should import /lib/svc/manifest/system/smartdc-config.xml instead of /lib/svc/manifest/system/smartdc-init.xml.

Please sign in to comment.
Something went wrong with that request. Please try again.