We may wanna change some configuration after Solaris installation that can not be done by AI, for example, permitting root ssh/ftp login (I know it’s a security issue), changing root shell to tcsh, providing .cshrc, the tcsh/csh initial configuration file to root and the additional user, specifying an FQDN in /etc/hosts …..
Unlike Jumpstart for Solaris 10 and earlier, AI does not have a mechanism to provide AI client a “finish script” that can be ran during installation. Official procedure is to create an own IPS (package server), make an own package containing the script file, install this additional package (specified in manifest) to AI client, and then run the script in the first boot up of the AI client after Solaris 11 installation.
Let’s go through the procedure,
1. create an own IPS (package server),
# pkgrepo create /work/jumpstart/os-image/Install-repo-finish_script
# pkgrepo set -s /work/jumpstart/os-image/Install-repo-finish_script publisher/prefix=finish-script
# svccfg -s pkg/server add finish
# svccfg -s pkg/server:finish addpg pkg application
# svccfg -s pkg/server:finish setprop pkg/port=100
# svccfg -s pkg/server:finish setprop pkg/inst_root=/work/jumpstart/os-image/Install-repo-finish_script
# svccfg -s pkg/server:finish addpg general framework
# svccfg -s pkg/server:finish addpropvalue general/complete astring: finish
# svccfg -s pkg/server:finish addpropvalue general/enabled boolean: true
# svcadm disable application/pkg/server:finish
# svcadm enable application/pkg/server:finish
above will create an IPS service with name application/pkg/server:finish, root directory /work/jumpstart/os-image/Install-repo-finish_script and port number 100. You can verify the service is enabled by,
# svcs application/pkg/server:finish
STATE STIME FMRI
online 15:40:47 svc:/application/pkg/server:finish
2. we will put package files to /root/package/proto,
# mkdir -p /root/package
# cd /root/package
# mkdir -p proto/lib/svc/manifest/site
# mkdir -p proto/opt/site
3. create a file proto/lib/svc/manifest/site/first-boot-script-svc-manifest.xml
<?xml version=”1.0″?>
<!DOCTYPE service_bundle SYSTEM “/usr/share/lib/xml/dtd/service_bundle.dtd.1”>
<service_bundle type=”manifest” name=”first-boot-script:site-first-boot-script-svc”>
<service name=”site/first-boot-script-svc” type=”service” version=”1″>
<create_default_instance enabled=”true”/>
<single_instance/>
<!–
Run the script late in the startup sequence after first boot.
–>
<dependency name=”multi-user” grouping=”require_all” restart_on=”none” type=”service”>
<service_fmri value=”svc:/milestone/multi-user:default”/>
</dependency>
<exec_method type=”method” name=”start” exec=”/opt/site/first-boot-script.sh” timeout_seconds=”360″>
<method_context>
<method_credential user=”root”/>
</method_context>
</exec_method>
<exec_method type=”method” name=”stop” exec=”:true” timeout_seconds=”60″/>
<property_group name=”startd” type=”framework”>
<propval name=”duration” type=”astring” value=”transient”/>
</property_group>
</service>
</service_bundle>
4. prepare a file cshrc that will be .cshrc later in host, and save it to proto/opt/site/cshrc
5. create the script file proto/opt/site/first-boot-script.sh and here is a sample,
#!/bin/sh
# Load SMF shell support definitions
. /lib/svc/share/smf_include.sh
echo “Save original boot environment first.”
# Obtain the active BE name from beadm: The active BE on reboot has an R in
# the third column of ‘beadm list’ output. Its name is in column one.
bename=`beadm list -Hd|nawk -F ‘;’ ‘$3 ~ /R/ {print $1}’`
beadm create ${bename}.orig
# this is to set FQDN by replacing client hostname ‘test-hostname’ to
# ‘test-hostname test-hostname.example.com’
(echo ‘1,$s/\<test-hostname\>/test-hostname test-hostname.example.com/’ ; echo w ; echo q) \
| ed /etc/hosts >> /dev/null
# permit ssh root login
(echo ‘1,$s/^PermitRootLogin.*$/PermitRootLogin yes/’; echo w; echo q) \
| ed /etc/ssh/sshd_config >> /dev/null\n
# enable ftp
svcadm enable network/ftp
# enable ftp root login
echo ‘1,$s/^#RootLogin on$/RootLogin on/’; echo w; echo q) | ed /etc/proftpd.conf >> /dev/null
(echo ‘1,$s/root/#root/’; echo w; echo q) | ed /etc/ftpd/ftpusers >> /dev/null
# copy .cshrc to root direcotry
cp /opt/site/cshrc /root/.cshrc
# copy .cshrc to the my additional user coco created in profile,
cp /opt/site/cshrc /home/coco/.cshrc
# change shell from /usr/bin/bash to /usr/bin/tcsh for all users
( echo ‘1,$s/\/usr\/bin\/bash/\/usr\/bin\/tcsh/’ ; echo w ; echo q ) | ed /etc/passwd >> /dev/null
# Disable service and uninstall package
svcadm disable svc:/site/first-boot-script-svc:default
pkg uninstall 08:00:27:82:9D:49
pkg unset-publisher finish-script
echo “Site first-boot script done. Rebooting in 5 seconds.” > /dev/console
sleep 5 && reboot -p || reboot &
exit $SMF_EXIT_OK
6. create a file /root/package/first-boot-script.p5m (do not put this file into /root/package/proto ),
set name=pkg.fmri value=080027829D49@1.0,5.11
set name=pkg.summary value=”AI first boot script”
set name=pkg.description value=”Script that runs at first boot after AI installation”
file path=lib/svc/manifest/site/first-boot-script-svc-manifest.xml mode=0444 \
owner=root group=sys
dir path=opt/site mode=0755 owner=root group=sys
file path=opt/site/first-boot-script.sh mode=0555 owner=root group=sys
file path=opt/site/cshrc mode=0644 owner=root group=sys
where
the mac address 080027829D49 (without colon) in line 1 is the package name so that
I can easily associate this package to the particular client.
7. with a ‘find’ we see the directories and files,
# find .
.
./proto
./proto/opt
./proto/opt/site
./proto/opt/site/cshrc
./proto/opt/site/first-boot-script.sh
./proto/lib
./proto/lib/svc
./proto/lib/svc/manifest
./proto/lib/svc/manifest/site
./proto/lib/svc/manifest/site/first-boot-script-svc-manifest.xml
./first-boot-script.p5m
8. use pkglint to verify the p5m file first-boot-script.p5m,
# pkglint first-boot-script.p5m
Lint engine setup…
Starting lint run…
WARNING pkglint.manifest011 SMF manifests were delivered by pkg:/080027829D49@1.0,5.11, but no org.opensolaris.smf.fmri attribute was found. Manifests found were: lib/svc/manifest/site/first-boot-script-svc-manifest.xml
9. use pkgsend to publish this package to our IPS created in Step 1,
# pkgsend publish -d ./proto -s /work/jumpstart/os-image/Install-repo-finish_script first-boot-script.p5m
pkg://finish-script/080027829D49@1.0,5.11:20141013T090737Z
PUBLISHED
where the directory /work/jumpstart/os-image/Install-repo-finish is the IPS root directory I specified in Step 1. If you have specified another directory please change the command with your own configuration.
10. we can verify this publishment by,
# pkg list -g http://192.168.1.115:100
NAME (PUBLISHER) VERSION IFO
080027829D49 (finish-script) 1.0 —
or point your browser to http://192.168.1.115:100 for an GUI.
11. back to the manifest we talked about here. check the sections “source” and “software_data” we had settings below,
<source>
<publisher name=”solaris”>
<origin name=”http://192.168.1.115:90/”/>
</publisher>
</source>
<software_data action=”install”>
<name>pkg:/entire@latest</name>
<name>pkg:/group/system/solaris-small-server</name>
<name>pkg:/solaris/service/network/ftp</name>
<name>pkg:/solaris/network/ftp</name>
<name>pkg:/shell/tcsh</name>
<name>pkg:/network/telnet</name>
<name>pkg:/service/network/telnet</name>
<name>pkg:/file/gnu-coreutils</name>
</software_data>
Change it by adding those lines in RED,
<source>
<publisher name=”solaris”>
<origin name=”http://192.168.1.115:90/”/>
</publisher>
<publisher name=”finish-script”>
<origin name=”http://192.168.1.115:100/”/>
</publisher>
</source>
<software_data action=”install”>
<name>pkg:/entire@latest</name>
<name>pkg:/group/system/solaris-small-server</name>
<name>pkg:/solaris/service/network/ftp</name>
<name>pkg:/solaris/network/ftp</name>
<name>pkg:/shell/tcsh</name>
<name>pkg:/network/telnet</name>
<name>pkg:/service/network/telnet</name>
<name>pkg:/file/gnu-coreutils</name>
<name>pkg:/080027829D49</name>
</software_data>
12. surely, you need an “installadm create-manifest” or “installadm update-manifest” to take this AI manifest effect.
Then, AI will install this package pkg:/080027829D49 from IPS http://192.168.1.115:100 with publisher name finish-script to the client. After installation is finished, either we reboot this client or the client automatically reboots, depends on the setting auto_reboot in manifest, this client is booting up.
As an svc manifest stored in /lib/svc/manifest/site will be automatically imported, and since the restart_on within first-boot-script-svc-manifest.xml is none, the svc manifest first-boot-script-svc-manifest.xml will be imported in the first boot only. The script file /opt/site/first-boot-script.sh will be run when first-boot-script-svc-manifest.xml is imported, and this is what we need. After the script is done it will un-install this additional package and unset finish-script publisher because of these lines in the end of first-boot-script.sh,
svcadm disable svc:/site/first-boot-script-svc:default
pkg uninstall 08:00:27:82:9D:49
pkg unset-publisher finish-script
In the next article I will introduce an UNOFFICIAL procedure to hack into AI boot files so that we can deliver a finish script as what we’ve used in Jumpstart for a long long time.
Unlike Jumpstart for Solaris 10 and earlier, AI does not have a mechanism to provide AI client a “finish script” that can be ran during installation. Official procedure is to create an own IPS (package server), make an own package containing the script file, install this additional package (specified in manifest) to AI client, and then run the script in the first boot up of the AI client after Solaris 11 installation.
Let’s go through the procedure,
1. create an own IPS (package server),
# pkgrepo create /work/jumpstart/os-image/Install-repo-finish_script
# pkgrepo set -s /work/jumpstart/os-image/Install-repo-finish_script publisher/prefix=finish-script
# svccfg -s pkg/server add finish
# svccfg -s pkg/server:finish addpg pkg application
# svccfg -s pkg/server:finish setprop pkg/port=100
# svccfg -s pkg/server:finish setprop pkg/inst_root=/work/jumpstart/os-image/Install-repo-finish_script
# svccfg -s pkg/server:finish addpg general framework
# svccfg -s pkg/server:finish addpropvalue general/complete astring: finish
# svccfg -s pkg/server:finish addpropvalue general/enabled boolean: true
# svcadm disable application/pkg/server:finish
# svcadm enable application/pkg/server:finish
above will create an IPS service with name application/pkg/server:finish, root directory /work/jumpstart/os-image/Install-repo-finish_script and port number 100. You can verify the service is enabled by,
# svcs application/pkg/server:finish
STATE STIME FMRI
online 15:40:47 svc:/application/pkg/server:finish
2. we will put package files to /root/package/proto,
# mkdir -p /root/package
# cd /root/package
# mkdir -p proto/lib/svc/manifest/site
# mkdir -p proto/opt/site
3. create a file proto/lib/svc/manifest/site/first-boot-script-svc-manifest.xml
<?xml version=”1.0″?>
<!DOCTYPE service_bundle SYSTEM “/usr/share/lib/xml/dtd/service_bundle.dtd.1”>
<service_bundle type=”manifest” name=”first-boot-script:site-first-boot-script-svc”>
<service name=”site/first-boot-script-svc” type=”service” version=”1″>
<create_default_instance enabled=”true”/>
<single_instance/>
<!–
Run the script late in the startup sequence after first boot.
–>
<dependency name=”multi-user” grouping=”require_all” restart_on=”none” type=”service”>
<service_fmri value=”svc:/milestone/multi-user:default”/>
</dependency>
<exec_method type=”method” name=”start” exec=”/opt/site/first-boot-script.sh” timeout_seconds=”360″>
<method_context>
<method_credential user=”root”/>
</method_context>
</exec_method>
<exec_method type=”method” name=”stop” exec=”:true” timeout_seconds=”60″/>
<property_group name=”startd” type=”framework”>
<propval name=”duration” type=”astring” value=”transient”/>
</property_group>
</service>
</service_bundle>
4. prepare a file cshrc that will be .cshrc later in host, and save it to proto/opt/site/cshrc
5. create the script file proto/opt/site/first-boot-script.sh and here is a sample,
#!/bin/sh
# Load SMF shell support definitions
. /lib/svc/share/smf_include.sh
echo “Save original boot environment first.”
# Obtain the active BE name from beadm: The active BE on reboot has an R in
# the third column of ‘beadm list’ output. Its name is in column one.
bename=`beadm list -Hd|nawk -F ‘;’ ‘$3 ~ /R/ {print $1}’`
beadm create ${bename}.orig
# this is to set FQDN by replacing client hostname ‘test-hostname’ to
# ‘test-hostname test-hostname.example.com’
(echo ‘1,$s/\<test-hostname\>/test-hostname test-hostname.example.com/’ ; echo w ; echo q) \
| ed /etc/hosts >> /dev/null
# permit ssh root login
(echo ‘1,$s/^PermitRootLogin.*$/PermitRootLogin yes/’; echo w; echo q) \
| ed /etc/ssh/sshd_config >> /dev/null\n
# enable ftp
svcadm enable network/ftp
# enable ftp root login
echo ‘1,$s/^#RootLogin on$/RootLogin on/’; echo w; echo q) | ed /etc/proftpd.conf >> /dev/null
(echo ‘1,$s/root/#root/’; echo w; echo q) | ed /etc/ftpd/ftpusers >> /dev/null
# copy .cshrc to root direcotry
cp /opt/site/cshrc /root/.cshrc
# copy .cshrc to the my additional user coco created in profile,
cp /opt/site/cshrc /home/coco/.cshrc
# change shell from /usr/bin/bash to /usr/bin/tcsh for all users
( echo ‘1,$s/\/usr\/bin\/bash/\/usr\/bin\/tcsh/’ ; echo w ; echo q ) | ed /etc/passwd >> /dev/null
# Disable service and uninstall package
svcadm disable svc:/site/first-boot-script-svc:default
pkg uninstall 08:00:27:82:9D:49
pkg unset-publisher finish-script
echo “Site first-boot script done. Rebooting in 5 seconds.” > /dev/console
sleep 5 && reboot -p || reboot &
exit $SMF_EXIT_OK
6. create a file /root/package/first-boot-script.p5m (do not put this file into /root/package/proto ),
set name=pkg.fmri value=080027829D49@1.0,5.11
set name=pkg.summary value=”AI first boot script”
set name=pkg.description value=”Script that runs at first boot after AI installation”
file path=lib/svc/manifest/site/first-boot-script-svc-manifest.xml mode=0444 \
owner=root group=sys
dir path=opt/site mode=0755 owner=root group=sys
file path=opt/site/first-boot-script.sh mode=0555 owner=root group=sys
file path=opt/site/cshrc mode=0644 owner=root group=sys
where
the mac address 080027829D49 (without colon) in line 1 is the package name so that
I can easily associate this package to the particular client.
7. with a ‘find’ we see the directories and files,
# find .
.
./proto
./proto/opt
./proto/opt/site
./proto/opt/site/cshrc
./proto/opt/site/first-boot-script.sh
./proto/lib
./proto/lib/svc
./proto/lib/svc/manifest
./proto/lib/svc/manifest/site
./proto/lib/svc/manifest/site/first-boot-script-svc-manifest.xml
./first-boot-script.p5m
8. use pkglint to verify the p5m file first-boot-script.p5m,
# pkglint first-boot-script.p5m
Lint engine setup…
Starting lint run…
WARNING pkglint.manifest011 SMF manifests were delivered by pkg:/080027829D49@1.0,5.11, but no org.opensolaris.smf.fmri attribute was found. Manifests found were: lib/svc/manifest/site/first-boot-script-svc-manifest.xml
9. use pkgsend to publish this package to our IPS created in Step 1,
# pkgsend publish -d ./proto -s /work/jumpstart/os-image/Install-repo-finish_script first-boot-script.p5m
pkg://finish-script/080027829D49@1.0,5.11:20141013T090737Z
PUBLISHED
where the directory /work/jumpstart/os-image/Install-repo-finish is the IPS root directory I specified in Step 1. If you have specified another directory please change the command with your own configuration.
10. we can verify this publishment by,
# pkg list -g http://192.168.1.115:100
NAME (PUBLISHER) VERSION IFO
080027829D49 (finish-script) 1.0 —
or point your browser to http://192.168.1.115:100 for an GUI.
11. back to the manifest we talked about here. check the sections “source” and “software_data” we had settings below,
<source>
<publisher name=”solaris”>
<origin name=”http://192.168.1.115:90/”/>
</publisher>
</source>
<software_data action=”install”>
<name>pkg:/entire@latest</name>
<name>pkg:/group/system/solaris-small-server</name>
<name>pkg:/solaris/service/network/ftp</name>
<name>pkg:/solaris/network/ftp</name>
<name>pkg:/shell/tcsh</name>
<name>pkg:/network/telnet</name>
<name>pkg:/service/network/telnet</name>
<name>pkg:/file/gnu-coreutils</name>
</software_data>
Change it by adding those lines in RED,
<source>
<publisher name=”solaris”>
<origin name=”http://192.168.1.115:90/”/>
</publisher>
<publisher name=”finish-script”>
<origin name=”http://192.168.1.115:100/”/>
</publisher>
</source>
<software_data action=”install”>
<name>pkg:/entire@latest</name>
<name>pkg:/group/system/solaris-small-server</name>
<name>pkg:/solaris/service/network/ftp</name>
<name>pkg:/solaris/network/ftp</name>
<name>pkg:/shell/tcsh</name>
<name>pkg:/network/telnet</name>
<name>pkg:/service/network/telnet</name>
<name>pkg:/file/gnu-coreutils</name>
<name>pkg:/080027829D49</name>
</software_data>
12. surely, you need an “installadm create-manifest” or “installadm update-manifest” to take this AI manifest effect.
Then, AI will install this package pkg:/080027829D49 from IPS http://192.168.1.115:100 with publisher name finish-script to the client. After installation is finished, either we reboot this client or the client automatically reboots, depends on the setting auto_reboot in manifest, this client is booting up.
As an svc manifest stored in /lib/svc/manifest/site will be automatically imported, and since the restart_on within first-boot-script-svc-manifest.xml is none, the svc manifest first-boot-script-svc-manifest.xml will be imported in the first boot only. The script file /opt/site/first-boot-script.sh will be run when first-boot-script-svc-manifest.xml is imported, and this is what we need. After the script is done it will un-install this additional package and unset finish-script publisher because of these lines in the end of first-boot-script.sh,
svcadm disable svc:/site/first-boot-script-svc:default
pkg uninstall 08:00:27:82:9D:49
pkg unset-publisher finish-script
In the next article I will introduce an UNOFFICIAL procedure to hack into AI boot files so that we can deliver a finish script as what we’ve used in Jumpstart for a long long time.