This section contains examples of derived manifests scripts. The scripts determine client attributes and use that information to customize the AI manifest. These examples do not necessarily include all the information required to produce a valid AI manifest.
This script customizes the base manifest to use only half of the target disk on an Oracle Solaris fdisk partition if the size of the disk is greater than 1 TB. Try setting SI_DISKSIZE_1 to less than 1 TB and then greater than 1 TB for different runs of this script. Also set SI_NUMDISKS and SI_DISKNAME_1 before you run the script. Note that this script is only for use with x86 clients because the specified partitioning only applies to x86 clients.
#!/bin/ksh93 SCRIPT_SUCCESS=0 SCRIPT_FAILURE=1 function handler { exit $SCRIPT_FAILURE } trap handler ERR /usr/bin/aimanifest load /usr/share/auto_install/manifest/default.xml # Check that there is only one disk on the system. if [[ $SI_NUMDISKS -gt "1" ]] ; then print -u2 "System has too many disks for this script." exit $SCRIPT_FAILURE fi /usr/bin/aimanifest add \ /auto_install/ai_instance/target/disk/disk_name@name $SI_DISKNAME_1 if [[ $SI_DISKSIZE_1 -gt "1048576" ]] ; then typeset -i PARTN_SIZE=$SI_DISKSIZE_1/2 # Default action is to create. /usr/bin/aimanifest add \ /auto_install/ai_instance/target/disk[disk_name@name=\"$SI_DISKNAME_1\"]/partition@name 1 /usr/bin/aimanifest add \ /auto_install/ai_instance/target/disk/partition[@name=1]/size@val \ ${PARTN_SIZE}mb else /usr/bin/aimanifest add \ /auto_install/ai_instance/target/disk[disk_name@name=\"$SI_DISKNAME_1\"]/partition@action \ use_existing_solaris2 fi exit $SCRIPT_SUCCESS
For AI clients where the value of SI_DISKSIZE_1 is less than or equal to 1048576, the following elements are added to $AIM_MANIFEST:
<target> <disk> <disk_name name="/dev/dsk/c0t0d0s0"/> <partition action="use_existing_solaris2"/> </disk> <!-- <logical> section --> </target>
For AI clients where the value of SI_DISKSIZE_1 is greater than 1048576, elements similar to the following are added to $AIM_MANIFEST, depending on the value of SI_DISKSIZE_1:
<target> <disk> <disk_name name="/dev/dsk/c0t0d0s0"/> <partition name="1"> <size val="524288mb"/> </partition> </disk> <!-- <logical> section --> </target>
The disk_name is specified in the command to add the partition to avoid creating a separate disk specification for the partition. The script in this example specifies that the partition is on the $SI_DISKNAME_1 disk, not on a different disk. If the appropriate lines in this example are replaced by the following lines, you do not get the result you intend:
/usr/bin/aimanifest add \ /auto_install/ai_instance/target/disk/partition@name 1 /usr/bin/aimanifest add \ /auto_install/ai_instance/target/disk/partition[@name=1]/size@val \ ${PARTN_SIZE}mb else /usr/bin/aimanifest add \ /auto_install/ai_instance/target/disk/partition@action \ use_existing_solaris2
Instead of the output shown above, this script would give you the following incorrect output:
<target> <disk> <disk_name name="c0t0d0s0"/> </disk> <disk> <partition name="1"> <size val="524288mb"/> </partition> </disk> </target>
This script customizes the AI manifest to configure a mirror of the root pool if a second disk exists, and configure a three-way mirror if a third disk exists. Set SI_NUMDISKS and SI_DISKNAME_1 before you run the script. Set SI_DISKNAME_2, SI_DISKNAME_3, and any others as necessary, depending on the value you set for SI_NUMDISKS. These environment variables will be set and available to derived manifests scripts during AI installations.
This example demonstrates using the aimanifest return path (–r option). See the aimanifest(8) man page for more information about the return path.
#!/bin/ksh93 SCRIPT_SUCCESS=0 SCRIPT_FAILURE=1 function handler { exit $SCRIPT_FAILURE } trap handler ERR /usr/bin/aimanifest load /usr/share/auto_install/manifest/default.xml # Use the default if there is only one disk. if [[ $SI_NUMDISKS -ge 2 ]] ; then typeset -i disk_num # Turn on mirroring. Assumes a root zpool is already set up. vdev=$(/usr/bin/aimanifest add -r \ target/logical/zpool[@name=rpool]/vdev@name mirror_vdev) /usr/bin/aimanifest set ${vdev}@redundancy mirror for ((disk_num = 1; disk_num <= $SI_NUMDISKS; disk_num++)) ; do eval curr_disk="$"SI_DISKNAME_${disk_num} disk=$(/usr/bin/aimanifest add -r target/disk@in_vdev mirror_vdev) /usr/bin/aimanifest set ${disk}@in_zpool rpool /usr/bin/aimanifest set ${disk}@whole_disk true disk_name=$(/usr/bin/aimanifest add -r \ ${disk}/disk_name@name $curr_disk) /usr/bin/aimanifest set ${disk_name}@name_type ctd done fi exit $SCRIPT_SUCCESS
For a system with two disks named c0t0d0 and c0t1d0, the output of this example is the following XML element:
<target> <disk in_vdev="mirror_vdev" in_zpool="rpool" whole_disk="true"> <disk_name name="c0t0d0" name_type="ctd"/> </disk> <disk in_vdev="mirror_vdev" in_zpool="rpool" whole_disk="true"> <disk_name name="c0t1d0" name_type="ctd"/> </disk> <logical> <zpool name="rpool" is_root="true"> <vdev name="mirror_vdev" redundancy="mirror"/> <filesystem name="export" mountpoint="/export"/> <filesystem name="export/home"/> <be name="solaris"/> </zpool> </logical> </target>
This script customizes the AI manifest to specify a mirrored configuration if the system has at least two 200 GB disks. Use the first two disks found that are at least 200 GB. Set SI_NUMDISKS, SI_DISKNAME_1, and SI_DISKSIZE_1 in your test environment before you run the script. Also set SI_DISKNAME_2, SI_DISKSIZE_2, and any others as necessary, depending on the value you set for SI_NUMDISKS. These environment variables will be set and available to derived manifests scripts during AI installations.
The example shows how to modify a node when more than one node with the same path is present. The shell implementation uses the return path (–r) option of aimanifest to return the path to a specific node, and uses that path to make additional modifications to the same node. The Python implementation demonstrates the use of subpathing (using [] inside a node path) to make additional modifications to the same node.
#!/bin/ksh93 SCRIPT_SUCCESS=0 SCRIPT_FAILURE=1 function handler { exit $SCRIPT_FAILURE } trap handler ERR # Find the disks first. typeset found_1 typeset found_2 typeset -i disk_num for ((disk_num = 1; disk_num <= $SI_NUMDISKS; disk_num++)) ; do eval curr_disk="$"SI_DISKNAME_${disk_num} eval curr_disk_size="$"SI_DISKSIZE_${disk_num} if [[ $curr_disk_size -ge "204800" ]] ; then if [ -z $found_1 ] ; then found_1=$curr_disk else found_2=$curr_disk break fi fi done # Now, install them into the manifest. # Let the installer take the default action if two large disks are not found. /usr/bin/aimanifest load /usr/share/auto_install/manifest/default.xml if [[ -n $found_2 ]] ; then # Turn on mirroring. vdev=$(/usr/bin/aimanifest add -r \ /auto_install/ai_instance/target/logical/zpool/vdev@redundancy mirror) /usr/bin/aimanifest set ${vdev}@name mirror_vdev disk=$(/usr/bin/aimanifest add -r \ /auto_install/ai_instance/target/disk@in_vdev mirror_vdev) disk_name=$(/usr/bin/aimanifest add -r ${disk}/disk_name@name $found_1) /usr/bin/aimanifest set ${disk_name}@name_type ctd disk=$(/usr/bin/aimanifest add -r \ /auto_install/ai_instance/target/disk@in_vdev mirror_vdev) disk_name=$(/usr/bin/aimanifest add -r ${disk}/disk_name@name $found_2) /usr/bin/aimanifest set ${disk_name}@name_type ctd fi exit $SCRIPT_SUCCESS
The following script is a Python version of the preceding Korn shell version.
#!/usr/bin/python2.6 import os import sys from subprocess import check_call, CalledProcessError SCRIPT_SUCCESS = 0 SCRIPT_FAILURE = 1 def main(): # Find the disks first. found_1 = "" found_2 = "" si_numdisks = int(os.environ["SI_NUMDISKS"]) for disk_num in range(1, si_numdisks + 1): curr_disk_var = "SI_DISKNAME_" + str(disk_num) curr_disk = os.environ[curr_disk_var] curr_disk_size_var = "SI_DISKSIZE_" + str(disk_num) curr_disk_size = os.environ[curr_disk_size_var] if curr_disk_size >= "204800": if not len(found_1): found_1 = curr_disk else: found_2 = curr_disk break # Now, write the disk specifications into the manifest. # Let the installer take the default action if two large disks are not found. try: check_call(["/usr/bin/aimanifest", "load", "/usr/share/auto_install/manifest/default.xml"]) except CalledProcessError as err: sys.exit(err.returncode) if len(found_2): try: check_call(["/usr/bin/aimanifest", "add", "target/logical/zpool[@name=rpool]/vdev@redundancy", "mirror"]) check_call(["/usr/bin/aimanifest", "set", "target/logical/zpool/vdev[@redundancy='mirror']@name", "mirror_vdev"]) check_call(["/usr/bin/aimanifest", "add", "target/disk/disk_name@name", found_1]) check_call(["/usr/bin/aimanifest", "set", "target/disk/disk_name[@name='" + found_1 + "']" + "@name_type", "ctd"]) check_call(["/usr/bin/aimanifest", "set", "target/disk[disk_name@name='" + found_1 + "']" + "@in_vdev", "mirror_vdev"]) check_call(["/usr/bin/aimanifest", "add", "target/disk/disk_name@name", found_2]) check_call(["/usr/bin/aimanifest", "set", "target/disk/disk_name[@name='" + found_2 + "']" + "@name_type", "ctd"]) check_call(["/usr/bin/aimanifest", "set", "target/disk[disk_name@name='" + found_2 + "']" + "@in_vdev", "mirror_vdev"]) except CalledProcessError as err: sys.exit(err.returncode) sys.exit(SCRIPT_SUCCESS) if __name__ == "__main__": main()
This script customizes the AI manifest to install one package if the IP address of the AI client is in a specified range, and install a different package if the IP address of the AI client is in a different range. Set SI_HOSTADDRESS in your test environment before you run the script. This environment variable will be set and available to derived manifests scripts during AI installations.
#!/bin/ksh93 SCRIPT_SUCCESS=0 SCRIPT_FAILURE=1 function handler { exit $SCRIPT_FAILURE } trap handler ERR /usr/bin/aimanifest load /usr/share/auto_install/manifest/default.xml # First determine which range the host IP address of the client is in. echo $SI_HOSTADDRESS | sed 's/\./ /g' | read a b c d # Assume all systems are on the same class A and B subnets. # If the system is on class C subnet = 100, then install the /pkg100 package. # If the system is on class C subnet = 101, then install the /pkg101 package. # Otherwise, do not install any other additional package. if ((c == 100)) ; then /usr/bin/aimanifest add \ software/software_data[@action='install']/name pkg:/pkg100 fi if ((c == 101)) ; then /usr/bin/aimanifest add \ software/software_data[@action='install']/name pkg:/pkg101 fi exit $SCRIPT_SUCCESS
This script customizes the AI manifest to install only on a disk that is at least 50 GB. Ignore smaller disks. Set SI_NUMDISKS, SI_DISKNAME_1, and SI_DISKSIZE_1 in your test environment before you run the script. Also set SI_DISKNAME_2, SI_DISKSIZE_2, and any others as necessary, depending on the value you set for SI_NUMDISKS. These environment variables will be set and available to derived manifests scripts during AI installations.
#!/bin/ksh93 SCRIPT_SUCCESS=0 SCRIPT_FAILURE=1 function handler { exit $SCRIPT_FAILURE } trap handler ERR /usr/bin/aimanifest load /usr/share/auto_install/manifest/default.xml typeset found typeset -i disk_num for ((disk_num = 1; disk_num <= $SI_NUMDISKS; disk_num++)) ; do eval curr_disk="$"SI_DISKNAME_${disk_num} eval curr_disk_size="$"SI_DISKSIZE_${disk_num} if [[ $curr_disk_size -ge "512000" ]] ; then found=$curr_disk /usr/bin/aimanifest add \ /auto_install/ai_instance/target/disk/disk_name@name $found break fi done if [[ -z $found ]] ; then exit $SCRIPT_FAILURE fi exit $SCRIPT_SUCCESS
Sometimes a system configuration change is needed for each AI client. Rather than having to create an individual system configuration profile on the AI server for each AI client, you could configure a derived manifests script to create the profile for you. The profile must be stored in /system/volatile/profile in order for the install service to be able to use it. In this script the settings for the local default router are used when the AI client is reconfigured.
ROUTER-CONFIG=/system/volatile/profile/router-config.xml ROUTER=`netstat -rn | grep "^default" | awk '{print $2}'` cat<<EOF>${ROUTER-CONFIG} <!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> <service_bundle type="profile" name="router"> <service name="network/install" version="1" type="service"> <instance name="default" enabled="true"> <property_group name="install_ipv4_interface" type="application"> <propval name="default_route" type="net_address_v4" value="${ROUTER}"/> </property_group> </instance> </service> </service_bundle> EOF
This script example contains errors.
#!/bin/ksh93 SCRIPT_SUCCESS=0 SCRIPT_FAILURE=1 function handler { exit $SCRIPT_FAILURE } trap handler ERR /usr/bin/aimanifest load /usr/share/auto_install/manifest/default.xml /usr/bin/aimanifest set \ software[@type="IPS"]/software_data/name pkg:/driver/pcmcia /usr/bin/aimanifest set \ software/software_data[@name=pkg:/driver/pcmcia]@action uninstall return $SCRIPT_SUCCESS
This example has three problems with writing to $AIM_MANIFEST.
The set subcommand of aimanifest can change the value of an existing element or attribute or create a new attribute. The set subcommand cannot create a new element. The first set subcommand attempts to modify an existing package name in the manifest instead of creating a new package name. If more than one package name already exists in the manifest, an ambiguity error results because the package to be modified cannot be determined. The first set subcommand in this example should have been an add subcommand.
In the second set subcommand in this example, an element name with value pkg:/driver/pcmcia is specified with a preceding @ sign. Although attribute values are specified with a preceding @ sign, element values are not.
The value pkg:/driver/pcmcia should be enclosed in quotation marks. Values with slashes or other special characters must be quoted.
The following lines should replace the two set lines in this example:
/usr/bin/aimanifest add \ software[@type="IPS"]/software_data@action uninstall /usr/bin/aimanifest add \ software/software_data[@action=uninstall]/name pkg:/driver/pcmcia
These two add subcommands add the following lines to the end of the software section of the manifest that is being written:
<software_data action="uninstall"> <name>pkg:/driver/pcmcia</name> </software_data>