usr/src/lib/install_ict/apply_sysconfig.py
author Ethan Quach <Ethan.Quach@sun.com>
Tue, 31 May 2011 14:21:09 -0700
changeset 1160 6f7e708c38ec
parent 1055 26f4df2e408e
child 1395 d3e03b36cbe8
permissions -rw-r--r--
16257 Support for zones configuration and installation should be included in AI 7041915 TransferFiles ICT should support transferring a directory that is more than one level deep. 7049824 System installed via AI ends up with incorrect mountpoints for shared ZFS datasets

#!/usr/bin/python
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
#

import grp
import os
import shutil
import solaris_install.ict as ICT
from stat import S_IRUSR

from solaris_install import Popen

# Checkpoint specific dictionary and keys
APPLY_SYSCONFIG_DICT = "apply_sysconfig_dict"
APPLY_SYSCONFIG_PROFILE_KEY = "profile"


class ApplySysConfig(ICT.ICTBaseClass):
    '''ICT checkpoint that applies the system configuration SMF profile(s)
       to the target during an AI installation'''

    def __init__(self, name):
        '''Initializes the class
           Parameters:
               -name - this arg is required by the AbstractCheckpoint
                       and is not used by the checkpoint.
        '''
        super(ApplySysConfig, self).__init__(name)

        self.profile = None

    def execute(self, dry_run=False):
        '''
            The AbstractCheckpoint class requires this method
            in sub-classes.

            Validates the profile against service configuration DTD
            using svccfg.

            Copies a profile or directory of profiles to the smf site profile
            directory in the target destination area.  The path of the profile
            or directory of profiles is stored in a data dictionary in the DOC
            with a name defined by this checkpoint.

            Parameters:
            - the dry_run keyword paramater. The default value is False.
              If set to True, the log message describes the checkpoint tasks.

            Returns:
            - Nothing
              On failure, errors raised are managed by the engine.
        '''
        self.logger.debug('ICT current task: Applying the system '
                          'configuration profile(s)')

        # parse_doc populates variables necessary to execute the checkpoint
        self.parse_doc()

        sc_profile_dst = os.path.join(self.target_dir, ICT.PROFILE_DEST)

        # Get the profile specification from the specific
        # data dictionary stored in the DOC
        as_doc_dict = self.doc.volatile.get_first_child( \
            name=APPLY_SYSCONFIG_DICT)

        # If dictionary not set, or profile value not set in
        # dictionary, there's no work to do.
        if as_doc_dict is not None:
            self.profile = as_doc_dict.data_dict.get( \
                APPLY_SYSCONFIG_PROFILE_KEY)

        if self.profile is None:
            self.logger.debug("No profile given.")
            return

        self.logger.debug("Checking for profile %s", self.profile)

        # If profile does not exist, there's no work to do
        if not os.access(self.profile, os.F_OK):
            self.logger.debug("Cannot access profile %s" % self.profile)
            self.logger.debug("There are no system configuration profiles "
                              "to apply")
            return

        # Make sure destination directory exists.
        if not dry_run:
            if not os.path.exists(sc_profile_dst):
                os.makedirs(sc_profile_dst)
                # read-only by user (root)
                os.chmod(sc_profile_dst, S_IRUSR)
                # chown root:sys
                os.chown(sc_profile_dst, 0, grp.getgrnam(ICT.SYS).gr_gid)

        # profile may be a file or directory, handle either case.
        profile_list = list()
        if os.path.isdir(self.profile):
            self.logger.debug("Processing profile directory %s", self.profile)
            for root, dirs, files in os.walk(self.profile, topdown=False):
                for name in files:
                    # Add name to list of profile files to process.
                    profile_list.append(os.path.join(root, name))
        else:
            self.logger.debug("Processing profile file %s", self.profile)
            profile_list.append(self.profile)

        for profile in profile_list:
            self.logger.debug("Applying profile %s", profile)
            # validate against DTD using svccfg
            cmd = [ICT.SVCCFG, 'apply', '-n ', profile]
            if dry_run:
                self.logger.debug('Executing: %s', cmd)
            if not dry_run:
                os.environ[ICT.SVCCFG_DTD] = os.path.join(self.target_dir,
                                                          ICT.SVC_BUNDLE)
                os.environ[ICT.SVCCFG_REPOSITORY] = os.path.join(
                                                          self.target_dir,
                                                          ICT.SVC_REPO)
                Popen.check_call(cmd, stdout=Popen.STORE, \
                                 stderr=Popen.STORE, logger=self.logger)

            fdst = os.path.join(sc_profile_dst, os.path.basename(profile))

            self.logger.debug('Copying %s to %s', profile, fdst)
            if not dry_run:
                shutil.copy(profile, fdst)
                # read-only by user (root)
                os.chmod(fdst, S_IRUSR)
                # chown root:sys
                os.chown(fdst, 0, grp.getgrnam(ICT.SYS).gr_gid)