28 import solaris_install.ict as ICT |
28 import solaris_install.ict as ICT |
29 from stat import S_IRUSR |
29 from stat import S_IRUSR |
30 |
30 |
31 from solaris_install import Popen |
31 from solaris_install import Popen |
32 |
32 |
|
33 # Checkpoint specific dictionary and keys |
|
34 APPLY_SYSCONFIG_DICT = "apply_sysconfig_dict" |
|
35 APPLY_SYSCONFIG_PROFILE_KEY = "profile" |
|
36 |
33 |
37 |
34 class ApplySysConfig(ICT.ICTBaseClass): |
38 class ApplySysConfig(ICT.ICTBaseClass): |
35 '''ICT checkpoint that applies the system configuration SMF profile |
39 '''ICT checkpoint that applies the system configuration SMF profile(s) |
36 to the target during an AI installation''' |
40 to the target during an AI installation''' |
37 |
41 |
38 def __init__(self, name): |
42 def __init__(self, name): |
39 '''Initializes the class |
43 '''Initializes the class |
40 Parameters: |
44 Parameters: |
41 -name - this arg is required by the AbstractCheckpoint |
45 -name - this arg is required by the AbstractCheckpoint |
42 and is not used by the checkpoint. |
46 and is not used by the checkpoint. |
43 ''' |
47 ''' |
44 super(ApplySysConfig, self).__init__(name) |
48 super(ApplySysConfig, self).__init__(name) |
45 |
49 |
|
50 self.profile = None |
|
51 |
46 def execute(self, dry_run=False): |
52 def execute(self, dry_run=False): |
47 ''' |
53 ''' |
48 The AbstractCheckpoint class requires this method |
54 The AbstractCheckpoint class requires this method |
49 in sub-classes. |
55 in sub-classes. |
50 |
56 |
51 Validates the profile against service configuration DTD |
57 Validates the profile against service configuration DTD |
52 using svccfg. |
58 using svccfg. |
53 |
59 |
54 Copies the profiles in PROFILE_DIR to the profile destination |
60 Copies a profile or directory of profiles to the smf site profile |
55 to the target during an AI installation. |
61 directory in the target destination area. The path of the profile |
|
62 or directory of profiles is stored in a data dictionary in the DOC |
|
63 with a name defined by this checkpoint. |
56 |
64 |
57 Parameters: |
65 Parameters: |
58 - the dry_run keyword paramater. The default value is False. |
66 - the dry_run keyword paramater. The default value is False. |
59 If set to True, the log message describes the checkpoint tasks. |
67 If set to True, the log message describes the checkpoint tasks. |
60 |
68 |
61 Returns: |
69 Returns: |
62 - Nothing |
70 - Nothing |
63 On failure, errors raised are managed by the engine. |
71 On failure, errors raised are managed by the engine. |
64 ''' |
72 ''' |
65 self.logger.debug('ICT current task: Applying the system ' |
73 self.logger.debug('ICT current task: Applying the system ' |
66 'configuration profile') |
74 'configuration profile(s)') |
67 |
75 |
68 # parse_doc populates variables necessary to execute the checkpoint |
76 # parse_doc populates variables necessary to execute the checkpoint |
69 self.parse_doc() |
77 self.parse_doc() |
70 |
78 |
71 sc_profile_dst = os.path.join(self.target_dir, ICT.PROFILE_DEST) |
79 sc_profile_dst = os.path.join(self.target_dir, ICT.PROFILE_DEST) |
72 |
80 |
73 # make list of files in profile input directory |
81 # Get the profile specification from the specific |
74 self.logger.debug("Checking for %s", ICT.PROFILE_DIR) |
82 # data dictionary stored in the DOC |
75 if not dry_run: |
83 as_doc_dict = self.doc.volatile.get_first_child( \ |
76 if not os.access(ICT.PROFILE_DIR, os.F_OK): |
84 name=APPLY_SYSCONFIG_DICT) |
77 self.logger.debug("%s does not exist", ICT.PROFILE_DIR) |
|
78 self.logger.debug("There are no system configuration profiles " |
|
79 "to apply") |
|
80 return |
|
81 |
85 |
|
86 # If dictionary not set, or profile value not set in |
|
87 # dictionary, there's no work to do. |
|
88 if as_doc_dict is not None: |
|
89 self.profile = as_doc_dict.data_dict.get( \ |
|
90 APPLY_SYSCONFIG_PROFILE_KEY) |
|
91 |
|
92 if self.profile is None: |
|
93 self.logger.debug("No profile given.") |
|
94 return |
|
95 |
|
96 self.logger.debug("Checking for profile %s", self.profile) |
|
97 |
|
98 # If profile does not exist, there's no work to do |
|
99 if not os.access(self.profile, os.F_OK): |
|
100 self.logger.debug("Cannot access profile %s" % self.profile) |
|
101 self.logger.debug("There are no system configuration profiles " |
|
102 "to apply") |
|
103 return |
|
104 |
|
105 # Make sure destination directory exists. |
82 if not dry_run: |
106 if not dry_run: |
83 if not os.path.exists(sc_profile_dst): |
107 if not os.path.exists(sc_profile_dst): |
84 os.makedirs(sc_profile_dst) |
108 os.makedirs(sc_profile_dst) |
85 # read-only by user (root) |
109 # read-only by user (root) |
86 os.chmod(sc_profile_dst, S_IRUSR) |
110 os.chmod(sc_profile_dst, S_IRUSR) |
87 # chown root:sys |
111 # chown root:sys |
88 os.chown(sc_profile_dst, 0, grp.getgrnam(ICT.SYS).gr_gid) |
112 os.chown(sc_profile_dst, 0, grp.getgrnam(ICT.SYS).gr_gid) |
89 |
113 |
90 for root, dirs, files in os.walk(ICT.PROFILE_DIR, topdown=False): |
114 # profile may be a file or directory, handle either case. |
91 for name in files: |
115 profile_list = list() |
92 # only copy files matching the template 'profileNNNN.xml' |
116 if os.path.isdir(self.profile): |
93 if not name.startswith('profile') or not name.endswith('.xml'): |
117 self.logger.debug("Processing profile directory %s", self.profile) |
94 continue |
118 for root, dirs, files in os.walk(self.profile, topdown=False): |
|
119 for name in files: |
|
120 # Add name to list of profile files to process. |
|
121 profile_list.append(os.path.join(root, name)) |
|
122 else: |
|
123 self.logger.debug("Processing profile file %s", self.profile) |
|
124 profile_list.append(self.profile) |
95 |
125 |
96 self.logger.debug("Applying profile %s", name) |
126 for profile in profile_list: |
97 # validate against DTD using svccfg |
127 self.logger.debug("Applying profile %s", profile) |
98 cmd = [ICT.SVCCFG, 'apply', '-n ', os.path.join(root, name)] |
128 # validate against DTD using svccfg |
99 if dry_run: |
129 cmd = [ICT.SVCCFG, 'apply', '-n ', profile] |
100 self.logger.debug('Executing: %s', cmd) |
130 if dry_run: |
101 if not dry_run: |
131 self.logger.debug('Executing: %s', cmd) |
102 os.environ[ICT.SVCCFG_DTD] = os.path.join(self.target_dir, |
132 if not dry_run: |
103 ICT.SVC_BUNDLE) |
133 os.environ[ICT.SVCCFG_DTD] = os.path.join(self.target_dir, |
104 os.environ[ICT.SVCCFG_REPOSITORY] = os.path.join( |
134 ICT.SVC_BUNDLE) |
105 self.target_dir, |
135 os.environ[ICT.SVCCFG_REPOSITORY] = os.path.join( |
106 ICT.SVC_REPO) |
136 self.target_dir, |
107 Popen.check_call(cmd, stdout=Popen.STORE, \ |
137 ICT.SVC_REPO) |
108 stderr=Popen.STORE, |
138 Popen.check_call(cmd, stdout=Popen.STORE, \ |
109 logger=self.logger) |
139 stderr=Popen.STORE, logger=self.logger) |
110 |
140 |
111 fdst = os.path.join(sc_profile_dst, name) |
141 fdst = os.path.join(sc_profile_dst, os.path.basename(profile)) |
112 |
142 |
113 self.logger.debug('Copying %s to %s', name, fdst) |
143 self.logger.debug('Copying %s to %s', profile, fdst) |
114 if not dry_run: |
144 if not dry_run: |
115 shutil.copy(os.path.join(root, name), fdst) |
145 shutil.copy(profile, fdst) |
116 # read-only by user (root) |
146 # read-only by user (root) |
117 os.chmod(fdst, S_IRUSR) |
147 os.chmod(fdst, S_IRUSR) |
118 # chown root:sys |
148 # chown root:sys |
119 os.chown(fdst, 0, grp.getgrnam(ICT.SYS).gr_gid) |
149 os.chown(fdst, 0, grp.getgrnam(ICT.SYS).gr_gid) |