#!/bin/bash # # Version 1.7 # Maintainer: Brad Diggs # Contributors: # Alan Nichols, Anthony Waldron Christian Candia, and John Clingan # # The purpose of this script is to automate creating and managing Solaris 10 # zones. # # 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 view the CDDL license by running this script with the # -l flag or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # # Change Log # Version 1.7 # - Adopted and incorporated CDDL license via -l flag. # - Added zone cloning. # - Improved usage by making output more man like and piping to less. # - Added Blastwave pkg-get support to automate installing any blastwave # package into a new non-global zone. # - Added BrandZ support http://www.opensolaris.org/os/community/brandz # Currently supports the lx brand. The -t, -M, -r, -w, -d, -D, and -s # are not supported with the brand option. # - Added the ability to add a zone with no networking. # - Prevent a user from creating a zone when the zone directory that already # exists. # - Fixed bug where zonepath ends with a / # - Added support for multiple IP addresses on independent network # interfaces and independent network mask per IP address and host name # - Added the ability to specify your own minimization package list file # - Added the ability to specify services file via "-f " flag # - Added the ability to specify input password file for clear text or # encrypted passwords # - Removed the -i flag since it has been obsoleted by the # new "-I :::" method of # specifying the network interface. Now the non-global host name # will be the host name specified or derived from the first IP # address. If no host name is specified or derived, the zone name # will be used. # - Removed the -H flag since it has been obsolated by the new -I spec # - Moved recursive file copy to before command execution so that the # command to be executed can be something that was copied into place. # - Added hosts file updating for global and new non-global zones # - Added the ability to specify multiple commands to run. # - Added the ability to setup one or more NFS mounts in /etc/vfstab of # the non-global zone. # - Fixed bug with -X "". # - Fixed bug where domain was not getting set in /etc/defaultdomain # - Added the ability to specify a destination directory for the file or # directory being copied by the -C command. # - Added ability to specify a zone root directory # - Fixed Bug where TZ doesn't get set # - Updated NFSv4 config in sysidcfg for Solaris 06/06 # - Fixed Bug with input parameters for optional file parameters # - Added the runcmd action that enables you to run one or more commands # in all specified zones from the global zone. # - Synchronized the delimiter to be the pipe symbol (|) instead of a # mix of the pipe and colon. # # Version 1.6 # - If not specified, IP address is obtained from name service # based on specified host name or zone name # - Enabled by default root login into the non-global zone # - Added -H flag to specify the host name of the non-global zone # - Added -A flag to disable autoboot (set to false) # - Added -M flag with an optional file to remove (minimize) unnedeed # packages (slow) # - Added 'only' action to halt all non-global zones but those # specified by -n \" ...\" and boot any of these # specified zones that are not currently running # - Added ability via 'only' special case 'bootall' to boot all zones # - Added ability via 'only' special case 'haltall' to halt all zones # - Extended -C flag to perform recursive copy # - Makes sure a matching IP/host name exists in the global zone # /etc/hosts file # - Makes sure that the zone IP isn't already in use # - Added more robust error messaging # - Added -X flag to enabling running a post-install script # - Added assurance validation for risky actions # - Added -F flag to force actions that otherwise require assurance # - Clarified action to be forced. # # Outstanding Feature List # Version 1.8 # - Add detach and attach for moving a zone from one server to another # - Add zone memory resource constraint via rcapd # rcapadm -E # projmod -K 'rcap.max-rss=60000000' system # - Add support for one or more ZFS partitions # http://onesearch.sun.com/search/blog/index.jsp?qt=zones+zfs # zpool create -m # zfs set quota=M # - Add support for the new package minimization feature to make # minimization much quicker. Excludes list of packages during # zone creation instead of removing them after the zone is # created. This feature is RFE (CR4963323). # - Add support for zone cloning feature. # http://onesearch.sun.com/search/blog/index.jsp?qt=zones+clone # - Add support for zone backup/restore feature. # - Add support for running JASS to harden the OS # - Integration into N1 SPS. N1 SPS allows administrators to provision # applications. It could provide a GUI-based front-end to Zonemgr to # allow provisioning of JES applications within Zone Containers. This # (combined with something like Anthony's EMRA toolkit) could be used # to provide automated installations into multiple zones. # - The Sun Cluster Product group has released an Agent for Solaris # Containers (Zones). My thought was this significantly simplifies HA # installations of JES. Rather than requiring the installation and # configuration of each application's HA agent, you would simply # configure an agent for the Container which has the JES application # installed. On failover, the entire Zone would be failed over to the # standby server. The JES applications would treat the failover # condition as a reboot. This would serve the primary purpose of HA # which is to protect applications from hardware faults. # - All interfaces that may be used by zones are given an IPMP group # name that matches the network number during the jumpstart # installation. My script does not allow you to specify a physical # interface, rather it looks at the address to be used and picks an # interface for you based upon the IPMP group name. That is ( ip & # netmask = ipmp_group ). If multiple interfaces exist in the IPMP # group, it balances zones between interfaces. # - I don't check to see if the IP is up because I may be pre-staging # a zone for a "migration". I have instead re-written the zone boot # script (/lib/svc/method/...) to only bring a zone up if it is not # pingable. This script does some other magic too, such as setting up # resource pools, default routes, etc. # ############################################################################## ### This script is submitted to BigAdmin by a user of the BigAdmin community. ### Sun Microsystems, Inc. is not responsible for the ### contents or the code enclosed. ### ### ### Copyright 2005 Sun Microsystems, Inc. ALL RIGHTS RESERVED ### Use of this software is authorized pursuant to the ### terms of the license found at ### http://www.sun.com/bigadmin/common/berkeley_license.html ############################################################################## # # Initialize variables # PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/sfw/bin:/opt/sfw/bin:/usr/local/bin:.:$PATH" version='1.7' autoboot='true' domains='' domainname='' manage_services='' zonetype='s' zoneminimize='' roothomedir='' rodirlist='' rwdirlist='' ronum=0 rwnum=0 fnum=0 snum=0 rodirs[$ronum]='' rwdirs[$rwnum]='' files[$fnum]='' services[$snum]='' pkgdefaults='/tmp/default' forceaction='false' zoneipinfo='' n=0 zoneip[$n]='' zoneif[$n]='' zonenm[$n]='' zonecidrnm[$n]='' zoneipname[$n]='' p=0 nfshost[$p]='' nfsexport[$p]='' nfsmount[$p]='' nfsoptions[$p]='' q=0 runcmd[$q]='' brandname='' brandsrcpath='' brandsubset='' r=0 pkglist[$r]='' ############################################################################## # # Define error message routine # error_message() { errmsg=$1 if [ -n "$errmsg" ] then echo -e "Error: $errmsg" echo "Use -h flag to see proper usage or -l flag to see the license." exit 1 fi } ############################################################################## # # Find pager # findpager() { # # Set the page command # pgcmd='cat - ' ck4less=`which less 2>&1 | grep -v "no less"` if [ -n "$ck4less" ] then pgcmd='less' else ck4more=`which more 2>&1 | grep -v "no more"` if [ -n "$ck4more" ] then pgcmd='more' fi fi } ############################################################################## # # Define appropriate usage # usage() { errmsg=$1 if [ -n "$errmsg" ]; then echo "$errrmsg";fi findpager echo "Usage: $0 -a -n System Administration Commands zonemgr(1M) NAME zonemgr - set up and manage zones SYNOPSIS zonemgr -a zonemgr -n -a [zZPEINBtrwRGdDCsfSAMXFhv] zonemgr -h zonemgr -v DESCRIPTION The purpose of zonemgr is to simplify Solaris 10 zones management. There are many pre-defined actions that can be applied to one or more zones depending on the action. OPTIONS The following options are supported: -a Specify the action to be performed -n Specify the name of the zone -h See this usage information -l See the CDDL license -v See the version number of this script ACTIONS Actions which can result in destructive actions or loss of work have a -F flag to force the action. The following actions are supported: add -n -z [add_options] The \"add\" action adds a new zone. The following add_options are required: -z \"\" Base directory for this zone. -P \"\" Unencrypted password of the root user of this new non-global zone. The password can either be specified in a file or as a quoted string. The following add_options can be used as substitutes for the required options: -Z \"\" Root zone directory for this zone. This is an alternate way from -z of specifying the zones root directory. -E \"\" This is an alternate way from -P of specifying the non- global root user's password via an encrypted format. The encrypted password can either be specified in a file or as a quoted string. You can copy and paste the user's password from /etc/shadow). The following optional add_options are supported: -t Type of zone where w=Whole Root and s=Sparse Root. A sparse root zone inherits the following directories from the global zone: /lib, /usr, /sbin, and /platform. A whole root zone does not inherit any directories from the global zone. The default value is sparse root (s). -A Disable autoboot (prevent zone from booting when the server reboots). -I \"|||\" IP Address of the non-global zone plus the network interface for that IP address, the netmask in CIDR format, and the host name for that IP address. If not specified the default network interface is the first non-loopback interface listed by ifconfig. The default netmask is the netmask that corresponds to the IP address that you specify. There is no default host name. Note that a zone can be created without a network address. -D \"\" DNS Domain Name. If a domain is specified, then dns name servers must also be specified. Note also that the fully qualified host name of the non-global zone must be resolvable by the naming service. -d \",,..\" Ordered list of DNS Name Servers. If domain name servers are specified the domain name must also be specified. Note also that the fully qualified host name of the non-global zone must be resolvable by the naming service. -r \"|\" Loopback mount global zone directory (gdir) on a non-global zone directory (ldir) in read only mode. -w \"|\" Loopback mount global zone directory (gdir) on a non-global zone directory (ldir) in read write mode. -N \"|||\" Mount an NFS directory where is the NFS server host name or IP address, is the NFS exported directory, is the mount point within the non-global zone to mount the NFS filesystem, and are the NFS mount options. Note that zones only supports mounting an NFS filesystem from a host on a separate physical server. e.g. You cannot at the present time mount an NFS filesystem from another zone on this physical server. -B \"||\" Make the zone into a Linux branded zone where is the brand name, , is the brand subset, and is the path and file name of the brand archive. If a media drive is being used, is the path to the mounted media. e.g. /cdrom/cdrom0 -R \"\" Custom home directory for the root user of the non-global zone. -C \"|\" File/Directory to recursively copy from the global zone into the non- global zone. The is an option to specify a different location in the non-global zone that presently exists in the global zone. -s [enable or disable] Enable (unlock) or disable (lock down) operating system services of the non-global zone. -f \"\" File containing a list of services to enable or disable. The format of the file is one service per line. -S \"\" Restart specified service after adding zone. A special case is 'reboot' to restart all services in the zone. -M [] Minimize the non-global zone by either excluding or removing un- necessary packages. The optional is a file containing a list of packages that you would like removed from the zone. If no is specified, the following categories will be removed with pkgrm -Y : JDS4 JDS3 JDS JDSosol GNOME2 CTL ALE APOC CTL EVO146 G11NTOLS GLOW JAI JAVAAPPS JDIC -X \" \" Runs inside the non-global command once it is successfully created. Note that you may need to include the full path to the command as well. And you can pass (arguments) to the command if you include them in the quoted the command. -G Fully automates the installation of specified BlastWave package. For a full list of available BlastWave packages, visit the following URL: http://blastwave.org/packages del -n [-F] The del action deletes an existing zone The \"del\" action supports the following optional option: -F Don't confirm an action; Just do it. list The \"list\" action lists all current zones lock -n [-F] [-f file] The \"lock\" action disables all un-necessary services The \"lock\" action supports the following optional options: -F Don't confirm an action; Just do it. -f \"\" File containing services to enable or disable unlock -n [-F] [-f file] The \"unlock\" action enables all un-necessary services The \"unlock\" action supports the following optional options: -F Don't confirm an action; Just do it. -f \"\" File containing services to enable or disable minimize -n [-F] [-f file] The \"minimize\" action ensures that all un-necessary packages are either not installed or removed after installation. The \"minimize\" action supports the following optional options: -F Don't confirm an action; Just do it. -f \"\" File containing services to enable or disable clone -n -y [clone_options] The \"clone\" action clones an existing zone into a new zone. The new zone can be tailored via the optional arguments used when creating a new zone. The \"clone\" action supports the following required options: The following clone_options are required: -z \"\" Base directory for this zone. -P \"\" Unencrypted password of the root user of this new non-global zone. The password can either be specified in a file or as a quoted string. The following clone_options can be used as substitutes for the required options: -Z \"\" Root zone directory for this zone. This is an alternate way from -z of specifying the zones root directory. -E \"\" This is an alternate way from -P of specifying the non- global root user's password via an encrypted format. The encrypted password can either be specified in a file or as a quoted string. You can copy and paste the user's password from /etc/shadow). The following optional clone_options are supported: -F Don't confirm an action; Just do it. -t Type of zone where w=Whole Root and s=Sparse [default: s] -d \",,..\" Ordered list of DNS Name Servers -D \"\" DNS Domain Name -A Disable autoboot (prevent zone from booting on system reboots) -I \"|||\" IP Address of the non-global zone plus the network interface for that IP address, the netmask in CIDR format, and the host name for that IP address. If not specified the default network interface is the first non-loopback interface listed by ifconfig. The default netmask is the netmask that corresponds to the IP address that you specify. There is no default host name. Note that a zone can be created without a network address. -r \"|\" Mount global zone directory (gdir) on a non-global zone directory (ldir) in read only mode -w \"|\" Mount global zone directory (gdir) on a non-global zone directory (ldir) in read write mode -N \"|||\" Mount an NFS directory where is the NFS server host name or IP address, is the NFS exported directory, is the mount point within the non-global zone to mount the NFS filesystem, and are the NFS mount options. Note that zones only supports mounting an NFS filesystem from a host on a separate physical server. e.g. You cannot at the present time mount an NFS filesystem from another zone on this physical server. shutdown -n [-F] The \"shutdown\" action shuts down a zone. The \"shutdown\" action supports the following optional option: -F Don't confirm an action; Just do it. boot -n The \"boot\" action boots a zone. The \"boot\" action supports the following optional option: -F Don't confirm an action; Just do it. reboot -n [-F] The \"reboot\" action reboots a zone. The \"reboot\" action supports the following optional option: -F Don't confirm an action; Just do it. halt -n [-F] The \"halt\" action halts a zone. The \"halt\" action supports the following optional option: -F Don't confirm an action; Just do it. only -n [-F] The \"only\" action halts all non-global zones but those specified by -n \" \" and boot any of these specified zones that are not currently running. There are two zone name special cases. bootall This zone name makes sure all non-global zones are booted. haltall This zone name makes sure all zones are halted. The \"only\" action supports the following optional option: -F Don't confirm an action; Just do it. runcmd -n -X \"\" [-F] The \"runcmd\" action runs commands specified with the -X \"\" flags in all non-global zones specified by -n \" \" flag. There is one zone name special case. all This zone name runs the specified commands on all non-global zones. The following options are required: -n \" ...\" Specify the name of the zones -X Runs inside the non-global command once it is successfully created. Note that you may need to include the full path to the command as well. The \"runcmd\" action supports the following optional option: -F Don't confirm an action; Just do it. EXAMPLES Example 1: Create A Zone The following command will create a non-global zone named m1. # zonemgr -a add -n m1 -z \"/zones\" -P \"abc123\" \\ -I \"192.168.0.10|hme0|24|myzonehost\" Example 2: Delete A Zone The following command will delete the non-global zone named m1 and it will not be prompted to continue because the action is forced with the -F flag. # zonemgr -F -a del -n m1 Example 3: Create A Zone With Multiple IP Addresses The following command will create a non-global zone named m1 with three IP addresses where each IP address is configured on its own network interface. # zonemgr -a add -n m1 -z \"/zones\" -P \"abc123\" \\ -I \"192.168.0.10|hme0|24|myzonehost1\" \\ -I \"192.168.5.27|bge0|24|myzonehost2\" \\ -I \"192.168.10.5|bge1|24|myzonehost3\" Example 4: A Complex Example The following command will perform the details stated below. # zonemgr -a add -n m2 -t w -z \"/zones\" \\ -P \"abc123\" -R /root \\ -I \"192.168.0.10|hme0|24|myzonehost\" \\ -r \"/ds/build11/bits|/bits\" \\ -w \"/zones/m2|/ds/m2\" \\ -s lock -S ssh \\ -C /etc/ssh/sshd_config -C /etc/resolv.conf \\ -C /etc/nsswitch.conf 1. Create a whole root zone named m2 in /zones/m2. 2. Set the root password of that zone to abc123. 3. Set the home directory of the root user of the non-global zone to /root. 4. Set the IP address of the zone to 192.168.0.10, the netmask to 255.255.255.0, assign it to interface hme0, and assign it a host name of myzonehost. 5. Read only mount /ds/build11/bits from the global zone to /bits in the non-global zone. 6. Read write mount /zones/m2 from the global zone to /ds/m2 in the non-global zone. 7. Disable all un-necessary services in the non-global zone and restart the ssh service once the lockdown is complete. 8. Copy the /etc/ssh/sshd_config, /etc/resolv.conf, and /etc/nsswitch.conf files from the global zone to the non-global zone Example 5: List All Zones The following command will list all available zones. # zonemgr -a list Example 6: Reboot A Zone The following command will reboot non-global zone m1. # zonemgr -a reboot -n m1 Example 7: Disable Un-necessary Services The following command will disable all un-necessary services of non-global zone m1. # zonemgr -a lock -n m1 Example 8: Enable Un-necessary Services The following command will enable all un-necessary services of non-global zone m1. # zonemgr -a unlock -n m1 Example 9: Manage State Of Multiple Zones The following command will halt all non-global zones but those specified by the -n parameter and will boot any of the specified zones that are not currently running. # zonemgr -a only -n \"m1 m2\" Example 10: Halt All Zones The following command will halt all non-global zones. # zonemgr -a only -n \"haltall\" Example 11: Boot All Zones The following command will boot all non-global zones. # zonemgr -a only -n \"bootall\" Example 12: Creating A BrandZ (e.g. Linux) Zone The following command will add a BrandZ zone # zonemgr -a add -n m1 -z \"/zones\" -P \"abc123\" \\ -I \"192.168.0.10|hme0|24|myzonehost\" \\ -B \"lx|all|/data/brandz/centos_fs_image.tar\" The parameters passed to -B break down as follwos: * lx: The zone brand (only lx is currently supported) * all: The brand subset to install. Valid values include desktop, applications, server, development, system, and all. I don't yet have an idea as to how this option will impact other distributions that folks come up with. These options may or may not be valid. TBD. * /data/brandz/centos_fs_image.tar: The path to the brand bits. I simply pointed them to the BrandZ community's CentOS image. Example 13: Create A Zone AND Install MySQL5 From BlastWave The following command will add a zone named m1, download and install mysql5 and all requisite bits from Blastwave.org, and install all those bits in the proper order in the m1 zone. # zonemgr -a add -n m1 -z \"/zones\" -P \"abc123\" \\ -I \"192.168.0.10|hme0|24|myzonehost\" -G \"mysql5\" NOTES Note that most parameters are multivalued. In other words, you can specify the same parameter multiple times. For example, to mount the /data1 and /data2 directories in read only mode from the global zone to the non-global zone, add the following to the add action: -r \"/data1\" -r \"/data2\" EXIT STATUS The following exit values are returned: 0 Successful completion. 1 An error occurred. 2 Invalid usage. SEE ALSO svcs(1), zlogin(1), zonename(1), svcadm(1M), svc.startd(1M) and init(1M), svc.startd(1M), zoneadm(1M), zonecfg(1M), attributes(5), smf(5), zones(5) " | $pgcmd exit 2 } ############################################################################## # # Show the CDDL license # showlicense() { findpager echo "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0 1. Definitions. 1.1. \"Contributor\" means each individual or entity that creates or contributes to the creation of Modifications. 1.2. \"Contributor Version\" means the combination of the Original Software, prior Modifications used by a Contributor (if any), and the Modifications made by that particular Contributor. 1.3. \"Covered Software\" means (a) the Original Software, or (b) Modifications, or (c) the combination of files containing Original Software with files containing Modifications, in each case including portions thereof. 1.4. \"Executable\" means the Covered Software in any form other than Source Code. 1.5. \"Initial Developer\" means the individual or entity that first makes Original Software available under this License. 1.6. \"Larger Work\" means a work which combines Covered Software or portions thereof with code not governed by the terms of this License. 1.7. \"License\" means this document. 1.8. \"Licensable\" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. \"Modifications\" means the Source Code and Executable form of any of the following: A. Any file that results from an addition to, deletion from or modification of the contents of a file containing Original Software or previous Modifications; B. Any new file that contains any part of the Original Software or previous Modifications; or C. Any new file that is contributed or otherwise made available under the terms of this License. 1.10. \"Original Software\" means the Source Code and Executable form of computer software code that is originally released under this License. 1.11. \"Patent Claims\" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.12. \"Source Code\" means (a) the common form of computer software code in which modifications are made and (b) associated documentation included in or with such code. 1.13. \"You\" (or \"Your\") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, \"You\" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, \"control\" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants. 2.1. The Initial Developer Grant. Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer, to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions thereof), with or without Modifications, and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof). (c) The licenses granted in Sections 2.1(a) and (b) are effective on the date Initial Developer first distributes or otherwise makes the Original Software available to a third party under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: (1) for code that You delete from the Original Software, or (2) for infringements caused by: (i) the modification of the Original Software, or (ii) the combination of the Original Software with other software or devices. 2.2. Contributor Grant. Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: (1) Modifications made by that Contributor (or portions thereof); and (2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first distributes or otherwise makes the Modifications available to a third party. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: (1) for any code that Contributor has deleted from the Contributor Version; (2) for infringements caused by: (i) third party modifications of Contributor Version, or (ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or (3) under Patent Claims infringed by Covered Software in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Availability of Source Code. Any Covered Software that You distribute or otherwise make available in Executable form must also be made available in Source Code form and that Source Code form must be distributed only under the terms of this License. You must include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used for software exchange. 3.2. Modifications. The Modifications that You create or to which You contribute are governed by the terms of this License. You represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to grant the rights conveyed by this License. 3.3. Required Notices. You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification. You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer. 3.4. Application of Additional Terms. You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the applicable version of this License or the recipients' rights hereunder. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.5. Distribution of Executable Versions. You may distribute the Executable form of the Covered Software under the terms of this License or under the terms of a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable form does not attempt to limit or alter the recipient's rights in the Source Code form from the rights set forth in this License. If You distribute the Covered Software in Executable form under a different license, You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.6. Larger Works. You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Software. 4. Versions of the License. 4.1. New Versions. Sun Microsystems, Inc. is the initial license steward and may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3, no one other than the license steward has the right to modify this License. 4.2. Effect of New Versions. You may always continue to use, distribute or otherwise make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. If the Initial Developer includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under any subsequent version of the License, You must distribute and make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. Otherwise, You may also choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version of the License published by the license steward. 4.3. Modified Versions. When You are an Initial Developer and You want to create a new license for Your Original Software, You may create and use a modified version of this License if You: (a) rename the license and remove any references to the name of the license steward (except to note that the license differs from this License); and (b) otherwise make it clear that the license contains terms which differ from this License. 5. DISCLAIMER OF WARRANTY. COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN \"AS IS\" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 6. TERMINATION. 6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as \"Participant\") alleging that the Participant Software (meaning the Contributor Version where the Participant is a Contributor or the Original Software where the Participant is the Initial Developer) directly or indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant, the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement with Participant. 6.3. In the event of termination under Sections 6.1 or 6.2 above, all end user licenses that have been validly granted by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor) shall survive termination. 7. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 8. U.S. GOVERNMENT END USERS. The Covered Software is a \"commercial item,\" as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of \"commercial computer software\" (as that term is defined at 48 C.F.R. 252.227-7014(a)(1)) and \"commercial computer software documentation\" as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License. 9. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any, provides otherwise), excluding such jurisdiction's conflict-of-law provisions. Any litigation relating to this License shall be subject to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the losing party responsible for costs, including, without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use, distribute or otherwise make available any Covered Software. 10. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. -------------------------------------------------------------------- NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) For Covered Software in this distribution, this License shall be governed by the laws of the State of California (excluding conflict-of-law provisions). Any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California and the state courts of the State of California, with venue lying in Santa Clara County, California. " | $pgcmd exit 0 } ############################################################################## # # Subroutine to seek assurance # are_you_sure() { faction="$1" if [ "$forceaction" = 'false' ] then read -ep "Are you sure that you want to \"$faction\"? [no]" ck4response ck4response=`echo $ck4response | sed -e "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/"` if [ "$ck4response" != 'yes' ] then error_message "You chose not to perform action \"$faction\"." fi else echo "The \"$faction\" action was forced with the -F parameter." fi } ############################################################################## # # Subroutine for deleting a zone # delete_zone() { zonename="$1" # Validate assurance are_you_sure "Delete Zone" if [ -z "$zonename" ] then error_message "Must specify a zone name with the -n flag" else # # Get necessary info to intelligently know what to clean up # zonepath=`zonecfg -z "$zonename" info zonepath 2> /dev/null | awk '{ print $2 }'` zonedirs=`zonecfg -z "$zonename" info fs 2> /dev/null | grep "special" | awk '{ print $2 }'` # # Make sure that the zone exists before trying to remove it. # ck4zone=`zoneadm -z "$zonename" list -v 2> /dev/null | grep "$zonename" | awk '{ print $3 }'` if [ -n "$ck4zone" ] then # # Ensure that the zone is shutdown # if [ "$ck4zone" = 'running' ] then zoneadm -z "$zonename" halt fi # # Uninstall and delete the zone # zoneadm -z $zonename uninstall -F zonecfg -z $zonename delete -F # # Try to remove the directories if they are empty # for dir in $zonedirs $zonepath do rmdir "$dir" > /dev/null 2>&1 done # # Provide info on what may need to be cleaned up # echo "With the exception of the root users's home directory, this script does" echo "not remove any zone data. There may be contents within the following" echo "directories that you may want to manually remove." echo "Zone path: $zonepath" echo "Globally mounted zone directories:" echo "$zonedirs" else echo "Error: Zone \"$zonename\" does not exist." exit 1 fi fi } ############################################################################## # # Subroutine for adding a zone # add_zone() { zonename="$1" # # See if the zone already exists # ck4zone=`zoneadm -z "$zonename" list 2> /dev/null` if [ -n "$ck4zone" ] then error_message "The specified zone name ($zonename) is already in use."; fi # # Make sure that the zone type specified is valid # if [ "$zonetype" != 's' ] then if [ "$zonetype" != 'w' ]; then error_message "Must specify a valid zone type [w=whole root or s=sparse root]"; fi fi # # Minimize the non-global zone # if [ "$zoneminimize" = 'yes' ] then if [ "$zonetype" != 'w' ] then error_message "The zone type must be set to 'whole' in order to minimize the zone!"; fi fi # # If networking info has been specified, add it to the zone configuration # i=0 while [ $i -lt $n ] do if [ -n "${zoneip[$i]}" ] then zoneipinfo="$zoneipinfo add net set address=${zoneip[$i]}/${zonecidrnm[$i]} set physical=${zoneif[$i]} end" fi i=$(($i+1)) done # # Ensure that the root password is specified # if [ -z "$encrootpw" ]; then error_message "Must specify either encrypted (-E) or non-encrypted (-P) password and the password cannot be null (e.g. \"\")"; fi # # Make sure there is a valid zonedir # if [ -n "$zonedir" ] && [ -n "$zonepath" ] then bzonepath=`dirname $zonedir` if [ "$bzonepath" != "$zonepath" ] then error_message "If the zone path (-z ) and the base of the zone directory (-Z ) \nare specified, then the zone path:\n $zonepath\nand the base directory of the zone directory:\n $bzonepath\nmust match." fi elif [ -z "$zonedir" ] then if [ -z "$zonepath" ] then error_message "Must provide either a zone directory with -Z or a zone path with -z ." else zonedir="$zonepath/$zonename" fi else if [ -z "$zonepath" ] then zonepath=`dirname $zonedir` fi fi # # Make sure there is no trailing / at the end of the directory # zonedir=`echo $zonedir | sed -e "s/\/$//g"` zonepath=`echo $zonepath | sed -e "s/\/$//g"` if [ -d "$zonedir" ] || [ -f "$zonedir" ] then error_message "The zone directory ($zonedir) is already in use. \nPlease select a zone directory that does not exist or remove the existing directory." fi # # Ensure that zone name is specified # if [ -z "$zonename" ] then error_message "Must specify a zone name" else # # Create the zone config file # wholeroot='' if [ "$zonetype" = 'w' ] && [ -z "$brandname" ] then wholeroot=" remove inherit-pkg-dir dir=/lib remove inherit-pkg-dir dir=/usr remove inherit-pkg-dir dir=/sbin remove inherit-pkg-dir dir=/platform" fi # # Construct readonly directories to insert into the zone config # i=0 while [[ $i -lt $ronum ]] do globaldir=`echo ${rodirs[$i]} | cut -d"|" -f1` localdir=`echo ${rodirs[$i]} | cut -d"|" -f2` # If no dstdir specified, use the srcdir if [ -z "$dstdir"] then dstdir="$srcdir" fi rodirlist="$rodirlist add fs set dir=$localdir set special=$globaldir set type=lofs add options [ro,nodevices] end" i=$(($i+1)) done # # Construct readwrite directories to insert into the zone config # i=0 while [[ $i -lt $rwnum ]] do globaldir=`echo ${rwdirs[$i]} | cut -d"|" -f1` localdir=`echo ${rwdirs[$i]} | cut -d"|" -f2` # If no dstdir specified, use the srcdir if [ -z "$dstdir"] then dstdir="$srcdir" fi rwdirlist="$rwdirlist add fs set dir=$localdir set special=$globaldir set type=lofs add options [rw,nodevices] end" i=$(($i+1)) done # # If branding is specified set up the brand args for zone creation # addbrandcfg='' addbrandinstall='' if [ -n "$brandname" ]; then if [ -n "$zoneminimize" ] || [ -n "$nameservers" ] || [ -n "$domains" ] || [ $snum != 0 ] || [ -n "$domainname" ] || [ -n "$manage_services" ] then error_message "Invalid option supplied with brand zone. Options -t, -M, -d, -D, and -s are not supported" fi addbrandcfg=" -B $brandname" addbrandinstall=" -d "$brandsrcpath" $brandsubset" fi addminimize='' if [ "$zoneminimize" == 'yes' ]; then addminimize=" -b " wholeroot='' fi zonefile="/tmp/zone$$" cat >> $zonefile < /dev/null i=0 while [[ $i -lt $ronum ]] do localdir=`echo ${rodirs[$i]} | cut -d"|" -f2` mkdir -p "$localdir" 2> /dev/null i=$(($i+1)) done i=0 while [[ $i -lt $rwnum ]] do localdir=`echo ${rwdirs[$i]} | cut -d"|" -f2` mkdir -p "$localdir" 2> /dev/null i=$(($i+1)) done # # Add and configure the zone # ck4zone=`zoneadm -z "$zonename" list -v 2> /dev/null | grep "$zonename" | awk '{ print $3 }'` if [ -n "$ck4zone" ] then echo "Error: Zone \"$zonename\" already exists and is in the $ck4zone state." exit 1 fi zonecfg -z "$zonename" -f "$zonefile" if [ $? -ne 0 ] then error_message "Error configuring $zonename, return value: $?" fi if [ "$action" == 'add' ] then zoneadm -z "$zonename" install $addbrandinstall if [ $? -ne 0 ] then error_message "Zone installation failed, return value: $?" fi elif [ "$action" == 'clone' ] then prevstate=`zoneadm -z "$srczonename" list -p | cut -d: -f3` if [ "$prevstate" == 'running' ] then zoneadm -z "$srczonename" halt fi sleep 2 zoneadm -z "$zonename" clone "$srczonename" if [ $? -ne 0 ] then error_message "Zone installation failed, return value: $?" fi if [ "$prevstate" == 'running' ] then zoneadm -z "$srczonename" boot fi fi # # Generate a sysidcfg file # adddomain='' if [ -n "$domainname" ] then adddomain="domain_name=$domainname " fi nameservice='NONE' if [ -n "$domains" ] then nameservice="DNS {$adddomain name_server=$domains}" fi netif="NONE { hostname=$zonename }" if [ -n "${zoneip[0]}" ] then netif="PRIMARY { hostname=${zoneipname[0]} ip_address=${zoneip[0]} protocol_ipv6=no }" fi if [ -z "$TZ" ] then TZ="US/Central" fi if [ -n "$domainname" ] then nfs4domain="$domainname" else nfs4domain="domain" fi cat >> "$zonedir/root/etc/sysidcfg" <> "$zonedir/root/etc/inet/netmasks" fi fi i=$(($i+1)) done # # Update the /etc/inet/hosts file in the new non-global zones # i=0 while [ $i -lt $n ] do adddomainname='' if [ -n "$domainname" ]; then adddomainname=" ${zoneipname[$i]}.$domainname"; fi if [ -n "${zoneip[$i]}" ] && [ -n "${zoneipname[$i]}" ] then # # Check the global hosts file # ck4name=`egrep "[ ]${zoneipname[$i]}$|[ ]${zoneipname[$i]}\.|[ ]${zoneipname[$i]}[ ]" "/etc/inet/hosts"` ck4ip=`egrep "^${zoneip[$i]}[ ]" "/etc/inet/hosts"` if [ -z "$ck4name" ] && [ -z "$ck4ip" ] then echo "${zoneip[$i]} ${zoneipname[$i]} $adddomainname" >> "/etc/inet/hosts" elif [ -z "$ck4name" ] && [ -n "$ck4ip" ] then ck4iptoname=`grep "^${zoneip[$i]}[ ]" "/etc/inet/hosts" | grep -i "${zoneipname[$i]}"` if [ -z "$ck4ip2name" ] then grep -v "^${zoneip[$i]}[ ]" "/etc/inet/hosts" > "/etc/inet/hosts.new" grep "^${zoneip[$i]}[ ]" "/etc/inet/hosts" | sed -e "s/$/ ${zoneipname[$i]}$adddomainname/g" >> "/etc/inet/hosts.new" mv "/etc/inet/hosts.new" "/etc/inet/hosts" fi fi # # Check the non-global hosts file # ck4name=`egrep "[ ]${zoneipname[$i]}$|[ ]${zoneipname[$i]}\.|[ ]${zoneipname[$i]}[ ]" "$zonedir/root/etc/inet/hosts"` ck4ip=`egrep "^${zoneip[$i]}[ ]" "$zonedir/root/etc/inet/hosts"` if [ -z "$ck4name" ] && [ -z "$ck4ip" ] then echo "${zoneip[$i]} ${zoneipname[$i]} $adddomainname" >> "$zonedir/root/etc/inet/hosts" elif [ -z "$ck4name" ] && [ -n "$ck4ip" ] then ck4iptoname=`grep "^${zoneip[$i]}[ ]" "$zonedir/root/etc/inet/hosts" | grep -i "${zoneipname[$i]}"` if [ -z "$ck4ip2name" ] then grep -v "^${zoneip[$i]}[ ]" "$zonedir/root/etc/inet/hosts" > "$zonedir/root/etc/inet/hosts.new" grep "^${zoneip[$i]}[ ]" "$zonedir/root/etc/inet/hosts" | sed -e "s/$/ ${zoneipname[$i]}$adddomainname/g" >> "$zonedir/root/etc/inet/hosts.new" mv "$zonedir/root/etc/inet/hosts.new" "$zonedir/root/etc/inet/hosts" fi fi fi i=$(($i+1)) done # # Add NFS mount points # i=0 while [ $i -lt $p ] do echo "${nfshost[$i]}:${nfsexport[$i]} - ${nfsmount[$i]} nfs - yes ${nfsoptions[$i]}" >> /etc/vfstab done # # If domainname is specified, create a /etc/defaultdomain # if [ -n "$domainname" ] then echo "$domainname" >> "$zonedir/root/etc/defaultdomain" fi # # Add branding customization # if [ -n "$brandname" ]; then # # Enable zone network interface # mkdir -p "$zonedir/root/etc/sysconfig" 2> /dev/null cat > "$zonedir/root/etc/sysconfig/network" < $tmpshadow cat $tmpshadow > "$zonedir/root/etc/shadow" rm $tmpshadow fi fi ########################################################################### # # Recursively copy specified files/directories from global into the # non-global zone # i=0 while [[ $i -lt $fnum ]] do ck4destination=`echo ${files[$i]} | tr -cd ':'` if [ -z "$ck4destination" ] then srccpdir="${files[$i]}" dstcpdir="${files[$i]}" elif [ "$ck4destination" = ':' ] then srccpdir=`echo ${files[$i]} | cut -d"|" -f1` dstcpdir=`echo ${files[$i]} | cut -d"|" -f2` else error_message "The proper format for the -C flag is -C \"\" or -C \"|\"" fi if [ -e "$srccpdir" ] then b=`dirname $dstcpdir` mkdir -p "$zonedir/root/$b" cp -r "$srccpdir" "$zonedir/root/$dstcpdir" else echo "File \"$srccpdir\" does not exist." fi i=$(($i+1)) done # # Run commands after zone creation # i=0 while [ $i -lt $q ] do echo "Executing \"${runcmd[$i]}\" in zone $zonename..." zlogin -S "$zonename" "${runcmd[$i]}" i=$(($i+1)) done } ############################################################################## # # Subroutine for disabling or enabling all un-necessary OS services # run_manage_services() { if [ -z "$1" ];then error_message "Must specify zone name"; fi # Validate assurance if [ "$action" != 'add' ];then are_you_sure "Disable Services"; fi rzonepath=`zonecfg -z "$zonename" info zonepath 2> /dev/null | awk '{ print $2 }'` maction="$2" donothing='' case "$maction" in 'disable') inetaction='-d';; 'lock') maction='disable'; inetaction='-d';; 'enable') inetaction='-e';; 'unlock') maction='enable'; inetaction='-e';; *) donothing='true';; esac if [ "$donothing" = 'true' ] then error_message "Error: the -s flag must include a valid selection such as 'enable' or 'disable' or an input services file (in \"svcs -o FMRI\" format)." else if [ -n "$svcsfile" ] && [ -f "$svcsfile" ] then rcfiles=`grep "^lrc:" "$svcsfile" | cut -d: -f2- | sed -e "s/rc2_d/rc2.d/g" -e "s/rc3_d/rc3.d/g"` svcs=`grep "^svc:" "$svcsfile" | cut -d: -f2-` else rc2="/etc/rc2.d" rc3="/etc/rc3.d" rcfiles="$rc3/S16boot.server $rc3/S50apache $rc3/S52imq $rc3/S76snmpdx $rc3/S77dmi $rc3/S81volmgt $rc3/S82initsma $rc3/S84appserv $rc3/S90samba $rc2/S70uucp $rc2/S72autoinstall $rc2/S73cachefs.daemon $rc2/S89PRESERVE $rc2/S90wbem $rc2/S90webconsole $rc2/S98deallocate $rc2/S99audit $rc2/S99dtlogin" svcs="svc:/network/smtp:sendmail svc:/system/filesystem/autofs:default svc:/network/nfs/status:default svc:/network/nfs/nlockmgr:default svc:/network/nfs/client:default svc:/network/nfs/rquota:default svc:/network/rpc/bind:default svc:/application/font/stfsloader:default svc:/application/x11/xfs:default svc:/network/finger:default svc:/network/ftp:default svc:/network/login:rlogin svc:/network/rpc/gss:default svc:/network/rpc/rstat:default svc:/network/rpc/rusers:default svc:/network/rpc/smserver:default svc:/network/security/ktkt_warn:default svc:/network/shell:default svc:/network/telnet:default svc:/network/rpc-100235_1/rpc_ticotsord:default svc:/network/rpc-100083_1/rpc_tcp:default svc:/network/rpc-100068_2-5/rpc_udp:default svc:/application/print/rfc1179" fi # # Disable unnecessary legacy (rc) services # for i in $rcfiles do j=`echo $i | sed -e "s/d\/S/d\/s/g"` if [ "$maction" = 'disable' ] then if [ -e "$rzonepath/root/$i" ] then zlogin "$zonename" "mv $i $j;$j stop > /dev/null 2>&1" fi elif [ "$maction" = 'enable' ] then if [ -e "$rzonepath/root/$j" ] then zlogin "$zonename" "mv $j $i;$i start > /dev/null 2>&1" fi fi done # # Disable unnecessary sfw services # for svc in $svcs do zlogin $zonename "svcadm $maction $svc" done fi } ############################################################################## # # Minimize the zone # run_remove_packages() { if [ "$zonetype" != 'w' ] && [ "$action" = 'add' ]; then error_message "The zone type must be set to 'whole' in order to minimize the zone!"; else sparsezone=`zonecfg -z $zonename info inherit-pkg-dir` if [ -n "$sparsezone" ] then error_message "The zone type must be set to 'whole' in order to minimize the zone!"; fi fi ck4zone=`zoneadm -z "$zonename" list -p | cut -d: -f3` if [ "$ck4zone" != 'running' ] then error_message "Zone must be running in order to minimize the zone!"; fi # Validate assurance are_you_sure "Minimize Zone (e.g. Remove unnecessary packages)" zlogin "$zonename" "sed -e 's/ask/nocheck/' /var/sadm/install/admin/default > $pkgdefaults" if [ -n "$minimizationfile" ] && [ -f "$minimizeationfile" ] then pkg_cats=`cat "$minimizationfile"` pkgs=`cat "$minimizationfile"` else pkg_cats="JDS4 JDS3 JDS JDSosol GNOME2 CTL ALE APOC CTL EVO146 G11NTOLS GLOW JAI JAVAAPPS JDIC" pkgs='' # Identify bundled Message Queue packages pkgstorm=`zlogin "$zonename" "pkginfo |grep SUNWiq|grep -i java|cut -c13-35"` pkgs="`echo $pkgstorm` $pkgs" # Identify bundled App Server pkgstorm=`zlogin "$zonename" "pkginfo |grep SUNWas|egrep -i '(java|pointbase)' |cut -c13-35"` pkgs="`echo $pkgstorm` $pkgs" fi # # Remove package categories # if [ -n "$pkg_cats" ] then for pkg_cat in $pkg_cats do zlogin "$zonename" "pkgrm -n -a $pkgdefaults -Y $pkg_cat" done fi # # Remove individual packages # if [ -n "$pkgs" ] then for pkg in $pkgs do zlogin "$zonename" "pkgrm -n -a $pkgdefaults $pkg" done fi } ############################################################################## # # Manage zones # only_my_zones() { myzones="$*" if [ -z "$myzones" ] then echo -e "Error: you must specify one or more zones for this action.\nAvailable zones include the following" zoneadm list -cv else # Validate assurance if [ "$myzones" = 'bootall' ] then are_you_sure "Boot All Zones" myzones=`zoneadm list -cp| cut -d: -f2 |grep -v global` for myzone in $myzones do ck4zone=`zoneadm -z "$myzone" list -p | cut -d: -f3` if [ "$ck4zone" != 'running' ] then echo "Zone $myzone is not currently running. Starting up zone $myzone now." zoneadm -z "$myzone" boot fi done echo "All zones are now running." elif [ "$myzones" = 'haltall' ] then are_you_sure "Halt All Zones" myzones=`zoneadm list -cp| cut -d: -f2 |grep -v global` for myzone in $myzones do ck4zone=`zoneadm -z "$myzone" list -p 2>&1 | cut -d: -f3` if [ "$ck4zone" != 'installed' ] then echo "Zone $myzone is currently running. Halting zone $myzone now." zoneadm -z "$myzone" halt fi done echo "All zones are now halted." else are_you_sure "Make Only Selected Zones Online" # # Figure out which zones aren't in my list # zlist=`zoneadm list` for z in $zlist do inmylist='false' for myzone in $myzones do ck4zone=`zoneadm -z "$myzone" list -p 2>&1 | cut -d: -f3` if [ "$ck4zone" = ' No such zone configured' ] then error_message "Zone \"$myzone\" does not exist. Exiting" fi if [ "$z" = "$myzone" ] || [ "$z" = 'global' ] then inmylist='true' fi done if [ "$inmylist" = 'false' ] then notmyzones="$notmyzones $z" fi done # # Ensure my zones are booted # for myzone in $myzones do ck4zone=`zoneadm -z "$myzone" list -p | cut -d: -f3` if [ "$ck4zone" != 'running' ] then echo "Zone $myzone is not currently running. Starting up zone $myzone now." zoneadm -z "$myzone" boot fi done # # Halt all other non-global zones # for z in $notmyzones do echo "Shutting down zone \"$z\"" zoneadm -z "$z" halt done fi echo "Now only your zones are running." fi } ############################################################################## # # Run a command in specified zones # run_in_zones() { myzones="$*" if [ -z "$myzones" ] then echo -e "Error: you must specify one or more zones for this action.\nAvailable zones include the following" zoneadm list -cv else # Validate assurance if [ "$myzones" = 'all' ] then are_you_sure "Run command in zones $myzones" myzones=`zoneadm list -cp| cut -d: -f2 |grep -v global` fi for myzone in $myzones do ck4zone=`zoneadm -z "$myzone" list -p | cut -d: -f3` if [ "$ck4zone" == 'running' ] then i=0 while [ $i -lt $q ] do echo "Running \"${runcmd[$i]}\" in zone $myzone..." zlogin -S "$myzone" "${runcmd[$i]}" i=$(($i+1)) done else echo -e "Error: Couldn't run commands in $myzone zone\nbecause the zone wasn't in the running state." fi done fi } ############################################################################## # # Convert the netmask from dot notation to CIDR format # nm2cidr() { nm=$1 oct1=`echo $nm | cut -d. -f1` oct2=`echo $nm | cut -d. -f2` oct3=`echo $nm | cut -d. -f3` oct4=`echo $nm | cut -d. -f4` # Assume that most networks are class C (e.g. cidr = 24) cidr=24 if [ $oct1 -lt 128 ]&&[ $oct2 -eq 0 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=0; elif [ $oct1 -lt 192 ]&&[ $oct2 -eq 0 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=1; elif [ $oct1 -lt 224 ]&&[ $oct2 -eq 0 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=2; elif [ $oct1 -lt 240 ]&&[ $oct2 -eq 0 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=3; elif [ $oct1 -lt 248 ]&&[ $oct2 -eq 0 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=4; elif [ $oct1 -lt 252 ]&&[ $oct2 -eq 0 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=5; elif [ $oct1 -lt 254 ]&&[ $oct2 -eq 0 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=5; elif [ $oct1 -lt 255 ]&&[ $oct2 -eq 0 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=7; elif [ $oct1 -eq 255 ]&&[ $oct2 -lt 127 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=8; elif [ $oct1 -eq 255 ]&&[ $oct2 -lt 192 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=9; elif [ $oct1 -eq 255 ]&&[ $oct2 -lt 124 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=10; elif [ $oct1 -eq 255 ]&&[ $oct2 -lt 240 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=11; elif [ $oct1 -eq 255 ]&&[ $oct2 -lt 248 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=12; elif [ $oct1 -eq 255 ]&&[ $oct2 -lt 252 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=13; elif [ $oct1 -eq 255 ]&&[ $oct2 -lt 254 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=14; elif [ $oct1 -eq 255 ]&&[ $oct2 -lt 255 ]&&[ $oct3 -eq 0 ]&&[ $oct4 -eq 0 ];then cidr=15; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -lt 128 ]&&[ $oct4 -eq 0 ];then cidr=16; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -lt 192 ]&&[ $oct4 -eq 0 ];then cidr=17; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -lt 124 ]&&[ $oct4 -eq 0 ];then cidr=18; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -lt 240 ]&&[ $oct4 -eq 0 ];then cidr=19; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -lt 248 ]&&[ $oct4 -eq 0 ];then cidr=20; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -lt 252 ]&&[ $oct4 -eq 0 ];then cidr=21; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -lt 254 ]&&[ $oct4 -eq 0 ];then cidr=22; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -lt 255 ]&&[ $oct4 -eq 0 ];then cidr=23; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -eq 0 ];then cidr=24; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -lt 128 ];then cidr=25; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -lt 192 ];then cidr=26; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -lt 224 ];then cidr=27; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -lt 240 ];then cidr=28; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -lt 248 ];then cidr=29; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -lt 254 ];then cidr=30; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -lt 255 ];then cidr=31; elif [ $oct1 -eq 255 ]&&[ $oct2 -eq 255 ]&&[ $oct3 -eq 255 ]&&[ $oct4 -eq 255 ];then cidr=32; fi echo "$cidr" } ############################################################################## # # Convert the netmask from CIDR format to dot notation # cidr2dot() { cidr=$1 if [ $cidr -ge 32 ];then netmask='255.255.255.255' elif [ $cidr -ge 31 ];then netmask='255.255.255.254' elif [ $cidr -ge 30 ];then netmask='255.255.255.252' elif [ $cidr -ge 29 ];then netmask='255.255.255.248' elif [ $cidr -ge 28 ];then netmask='255.255.255.240' elif [ $cidr -ge 27 ];then netmask='255.255.255.224' elif [ $cidr -ge 26 ];then netmask='255.255.255.192' elif [ $cidr -ge 25 ];then netmask='255.255.255.128' elif [ $cidr -ge 24 ];then netmask='255.255.255.0' elif [ $cidr -ge 23 ];then netmask='255.255.254.0' elif [ $cidr -ge 22 ];then netmask='255.255.252.0' elif [ $cidr -ge 21 ];then netmask='255.255.248.0' elif [ $cidr -ge 20 ];then netmask='255.255.240.0' elif [ $cidr -ge 19 ];then netmask='255.255.224.0' elif [ $cidr -ge 18 ];then netmask='255.255.192.0' elif [ $cidr -ge 17 ];then netmask='255.255.128.0' elif [ $cidr -ge 16 ];then netmask='255.255.0.0' elif [ $cidr -ge 15 ];then netmask='255.254.0.0' elif [ $cidr -ge 14 ];then netmask='255.252.0.0' elif [ $cidr -ge 13 ];then netmask='255.248.0.0' elif [ $cidr -ge 12 ];then netmask='255.240.0.0' elif [ $cidr -ge 11 ];then netmask='255.224.0.0' elif [ $cidr -ge 10 ];then netmask='255.192.0.0' elif [ $cidr -ge 9 ];then netmask='255.128.0.0' elif [ $cidr -ge 8 ];then netmask='255.0.0.0' elif [ $cidr -ge 7 ];then netmask='254.0.0.0' elif [ $cidr -ge 6 ];then netmask='252.0.0.0' elif [ $cidr -ge 5 ];then netmask='248.0.0.0' elif [ $cidr -ge 4 ];then netmask='240.0.0.0' elif [ $cidr -ge 3 ];then netmask='224.0.0.0' elif [ $cidr -ge 2 ];then netmask='192.0.0.0' elif [ $cidr -ge 1 ];then netmask='128.0.0.0' elif [ $cidr -ge 0 ];then netmask='0.0.0.0' elif [ $cidr -le 0 ];then netmask='0.0.0.0' fi echo $netmask } ############################################################################## # # Convert an IP address from decimal format to dot notation # dword2dot() { dword=$1 byte0=$((($dword & 0xff000000)/256/256/256)) byte1=$((($dword & 0x00ff0000)/256/256)) byte2=$((($dword & 0x0000ff00)/256)) byte3=$(($dword & 0x000000ff)) echo "$byte0.$byte1.$byte2.$byte3" } ############################################################################## # # Convert an IP address from dot notation to decimal format # dot2dword() { dot=$1 oct1=`echo $dot | cut -d. -f1` oct2=`echo $dot | cut -d. -f2` oct3=`echo $dot | cut -d. -f3` oct4=`echo $dot | cut -d. -f4` echo $(($oct1*256*256*256+$oct2*256*256+$oct3*256+$oct4)) } ############################################################################## # # Download and install requested CSW packages # addCSWpkgs() { # # Wait for about 10 seconds to make sure that the zone is # ready to download packages from the Internet. # sleep 10; # # Make sure that the CSWpkgget is installed and at version 3.5 or above # cswdata=`zlogin "$zonename" "pkginfo -l CSWpkgget 2>&1 | grep VERSION | awk '{ print $2 }'"`; cswversion=`echo $cswdata | cut -d. -f1` cswrelease=`echo $cswdata | cut -d. -f2` if [ -n "$cswdata" ] then if [ $cswversion -lt 3 ] || [ $cswrelease -lt 5 ] then error_message "CSWpkgget version must be 3.5 or greater." fi else # # If CSWpkgget isn't installed, then download it # from Blastwave and install it. # zlogin "$zonename" "PATH=$PATH:/usr/sfw/bin;wget http://www.blastwave.org/pkg_get.pkg" if [ "$?" -eq 0 ]; then zlogin "$zonename" "yes | pkgadd -d pkg_get.pkg all"; else error_message "The wget command is required to download and install the BlastWave pkg_get.pkg package."; fi fi echo -e "Install md5 package in zone $zonename in order \nto properly verify Blastwave packages..." # # Install the gnupg and md5 tools to verify Blastwave packages # zlogin "$zonename" "yes | /opt/csw/bin/pkg-get -i gnupg textutils" # # Install the Blastwave pgp.key # zlogin "$zonename" "PATH=$PATH:/usr/sfw/bin:/opt/csw/bin;wget --output-document=/tmp/pgp.key http://www.blastwave.org/mirrors.html; /opt/csw/bin/gpg --import /tmp/pgp.key" i=0 while [ $i -lt $r ] do echo "Installing package \"${pkglist[$i]}\" in zone $zonename..." # # Install the requested Blastwave packages # zlogin "$zonename" "yes | /opt/csw/bin/pkg-get -i ${pkglist[$i]}" i=$(($i+1)) done } ############################################################################## # # If any parameters were passed evaluate their usage... # while getopts a:n:y:z:Z:P:E:I:N:B:t:r:w:R:G:d:D:C:s:f:S:AM:X:Fhlv OPT do case $OPT in a|+a) if [ -z "$OPTARG" ];then error_message "Must provide a valid action with the -a flag";fi action="$OPTARG" ;; n|+n) if [ -z "$OPTARG" ];then error_message "Must provide a zone name with the -n flag";fi zonename="$OPTARG" ;; y|+y) if [ -z "$OPTARG" ];then error_message "Must provide a source zone name with the -y flag";fi ck4cloning=`zoneadm 2>&1 | grep clone` if [ -z "$ck4cloning" ] then error_message "The clone feature does not exist on ths version of Solaris."; fi srczonename="$OPTARG" ;; Z|+Z) if [ -z "$OPTARG" ];then error_message "Must provide a zone directory with the -Z flag";fi zonedir="$OPTARG" ;; z|+z) if [ -z "$OPTARG" ];then error_message "Must provide a base zone directory with the -z flag";fi zonepath="$OPTARG" ;; P|+P) if [ -z "$OPTARG" ];then error_message "Must provide an unencrypted password with the -P flag and the password cannot be null (e.g. \"\")";fi rootpw="$OPTARG" if [ -f "$rootpw" ] then rootpw=`cat "$rootpw"` fi # Encrypt the password encrootpw=`/usr/bin/perl -e "print crypt(\"$rootpw\", (('a'..'z', 'A'..'Z', '0'..'9', '.', '/')[int(rand(64))].('a'..'z', 'A'..'Z', '0'..'9', '.', '/')[int(rand(64))]));"` ;; E|+E) if [ -z "$OPTARG" ];then error_message "Must provide an encrypted password with the -E flag";fi encrootpw="$OPTARG" if [ -f "$encrootpw" ] then encrootpw=`cat "$encrootpw"` fi ;; I|+I) if [ -z "$OPTARG" ];then error_message "Must provide a valid IP address, interface, netmask, and host name with the -I flag";fi zoneip[$n]=`echo $OPTARG | cut -d"|" -f1` zoneif[$n]=`echo $OPTARG | cut -d"|" -f2` zonenm[$n]=`echo $OPTARG | cut -d"|" -f3` zoneipname[$n]=`echo $OPTARG | cut -d"|" -f4` # # Make sure we get a cidr formatted and non-cidr formatted netmask # ck4noncidr=`echo ${zonenm[$n]} | tr -cd '\.'` if [ "$ck4noncidr" = '...' ] then zonecidrnm[$n]=`nm2cidr ${zonenm[$n]}` else zonecidrnm[$n]="${zonenm[$n]}" zonenm[$n]=`cidr2dot ${zonecidrnm[$n]}` fi # # Validate the specified IP address # if [ -z "${zoneip[$n]}" ]; then error_message "Must specify a valid IP address with the -I flag."; fi ping -I 1 ${zoneip[$n]} 56 3 > /dev/null 2>&1 if [ $? -eq 0 ] then error_message "The specified zone ip address (${zoneip[$n]}) is already in use. Please specify an unused IP address." fi # # Validate the specified network interface # if [ -z "${zoneif[$n]}" ]; then error_message "Must specify a valid network interface with the -I flag."; fi ck4zoneif=`ifconfig ${zoneif[$n]} 2> /dev/null` if [ $? -ne 0 ] || [ -z "$ck4zoneif" ];then error_message "Network interface specified (${zoneif[$n]}) does not exist";fi # # Validate the specified netmask # if [ -z "${zonenm[$n]}" ]; then error_message "Must specify a valid netmask with the -I flag."; fi if [ ${zonecidrnm[$n]} -gt 32 ] || [ ${zonecidrnm[$n]} -lt 0 ] then error_message "If using the CIDR netmask format, the value cannot be greater than 32 or less than 0" fi # # Validate the specified host name # if [ -z "${zoneipname[$n]}" ]; then error_message "Must specify a valid host name with the -I flag."; fi ck4ip=`/usr/bin/getent hosts "${zoneipname[$i]}"| awk '{ print $1 }'` if [ -n "$ck4ip" ] && [ "${zoneip[$n]}" != "$ck4ip" ] then error_message "The specified host name resolves to an IP address ($ck4ip) that does not match the specified IP address (${zoneip[$n]})." fi n=$(($n+1)) ;; N|+N) if [ -z "$OPTARG" ];then error_message "Must provide a valid NFS server name or IP, export directory, and mount directory with the -N flag";fi nfshost[$p]=`echo $OPTARG | cut -d"|" -f1` nfsexport[$p]=`echo $OPTARG | cut -d"|" -f2` nfsmount[$p]=`echo $OPTARG | cut -d"|" -f3` nfsoptions[$p]=`echo $OPTARG | cut -d"|" -f4` localhost=`hostname` if [ "${nfsexport[$p]}" = "$localhost" ]; then error_message "The NFS host cannot be the global-zone. NFS mounting from the global zone to a non-global zone is not supported.";fi p=$(($p+1)) ;; B|+B) if [ -z "$OPTARG" ];then error_message "Must provide valid branding info with the -B flag";fi # Make sure that the packages are installed before validating input parameters pkginfo SUNWlx SUNWbrand > /dev/null 2>&1 if [ "$?" -ne 0 ]; then error_message "Brandz must be installed prior to attempting to create a BrandZ zone.\nSee the Brandz site for installation details:\n http://www.opensolaris.org/os/community/brandz/install"; fi brandname=`echo $OPTARG | cut -d"|" -f1` brandsubset=`echo $OPTARG | cut -d"|" -f2` brandsrcpath=`echo $OPTARG | cut -d"|" -f3` if [ "$brandname" != 'lx' ]; then error_message "At this time, 'lx' is the only supported brand name."; fi case "$brandsubset" in 'desktop') true;; 'applications') true;; 'server') true;; 'development') true;; 'system') true;; 'all') true;; *) error_message "Valid brand subsets include: desktop, applications, server, development, system, and all";; esac if [ -d "${brandsrcpath[$r]}" ]; then true; else error_message "Must specify a valid brand source path to the brand brand archive/CD."; fi ;; G|+G) if [ -z "$OPTARG" ];then error_message "Must provide a valid package name with the -G flag";fi pkglist[$r]="$OPTARG" r=$(($r+1)) ;; t|+t) if [ -z "$OPTARG" ];then error_message "Must specify a valid zone type (w or s) with the -t flag";fi zonetype="$OPTARG" ;; r|+r) if [ -z "$OPTARG" ];then error_message "";fi rodirs[$ronum]="$OPTARG" globaldir=`echo ${rodirs[$ronum]} | cut -d"|" -f1` if [ -d "$globaldir" ]; then true; elif [ -e "$globaldir" ]; then true; else error_message "The global directory \"$globaldir\" does not exist."; fi ronum=$(($ronum+1)) ;; w|+w) if [ -z "$OPTARG" ];then error_message "";fi rwdirs[$rwnum]="$OPTARG" rwnum=$(($rwnum+1)) ;; R|+R) if [ -z "$OPTARG" ];then error_message "";fi roothomedir="$OPTARG" ;; d|+d) if [ -z "$OPTARG" ];then error_message "";fi if [ -n "$domains" ] then domains="$domains,$OPTARG" else domains="$OPTARG" fi if [ "$domains" = "local" ] then if [ -f /etc/resolv.conf ] then nameservers=`grep nameserver /etc/resolv.conf|sed -e 's/nameserver//' -e 's/ //g'` domains="" for ns in `echo $nameservers` do if [ -z "$domains" ] then domains=$ns else domains="$domains,$ns" fi done domainname=`grep domain /etc/resolv.conf|sed -e 's/domain//' -e 's/ //g'` else error_message "DNS is not configured on global zone." fi fi ;; D|+D) if [ -z "$OPTARG" ];then error_message "";fi domainname="$OPTARG" ;; C|+C) if [ -z "$OPTARG" ];then error_message "";fi files[$fnum]="$OPTARG" fnum=$(($fnum+1)) ;; s|+s) if [ -z "$OPTARG" ];then error_message "Must provide enable or disable option for the -s