New functions.ksh
1 #
2 # CDDL HEADER START
3 #
4 # The contents of this file are subject to the terms of the
5 # Common Development and Distribution License (the License).
6 # You may not use this file except in compliance with the License.
7 #
8 # You can obtain a copy of the license at usr/src/CDDL.txt
9 # or http://www.opensolaris.org/os/licensing.
10 # See the License for the specific language governing permissions
11 # and limitations under the License.
12 #
13 # When distributing Covered Code, include this CDDL HEADER in each
14 # file and include the License file at usr/src/CDDL.txt.
15 # If applicable, add the following below this CDDL HEADER, with the
16 # fields enclosed by brackets [] replaced with your own identifying
17 # information: Portions Copyright [yyyy] [name of copyright owner]
18 #
19 # CDDL HEADER END
20 #
21
22 #
23 # Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 # Use is subject to license terms.
25 #
26
27 # ident "%Z%%M% %I% %E% SMI"
28
29 PKG=SUNWscPostgreSQL
30 METHOD=`basename $0`
31 TASK_COMMAND=""
32
33 ZONENAME=/usr/bin/zonename
34 DIRNAME=/usr/bin/dirname
35
36 SCLOGGER=/usr/cluster/lib/sc/scds_syslog
37 PMFADM=/usr/cluster/bin/pmfadm
38 GETENT=/usr/bin/getent
39 UNAME=/usr/bin/uname
40 MCONNECT=/usr/bin/mconnect
41 SLEEP=/usr/bin/sleep
42 TOUCH=/usr/bin/touch
43 CAT=/usr/bin/cat
44 GREP=/usr/bin/grep
45 ENV=/usr/bin/env
46 PGREP=/usr/bin/pgrep
47 ECHO=/usr/bin/echo
48 SU=/usr/bin/su
49 RM=/usr/bin/rm
50 AWK=/usr/bin/awk
51 NAWK=/usr/bin/nawk
52
53 set_shell_specifics()
54 {
55
56 # Set variables to construct sourcing and output redirection depending
57 # on the login shell of the user
58
59 debug_message "Function: set_shell_specifics - Begin"
60 ${SET_DEBUG}
61
62 ENVSC=
63
64 if ${GETENT} passwd ${USER} | ${AWK} -F: '{print $7}' | ${GREP} csh > /dev/null
65 then
66
67 # C shell specifics
68
69 # sourcing
70
71 if [ -n "${ENVSCRIPT}" ]
72 then
73 ENVSC="source ${ENVSCRIPT};"
74 fi
75
76 # brackets for subshells
77
78 OPEN_BRACKET="("
79 CLOSE_BRACKET=")"
80
81 # redirection
82
83 OUTPUT_APP=">>& ${LOGFILE}"
84 OUTPUT=">& ${LOGFILE}"
85 CAT_OUTPUT="> /tmp/${RESOURCE}-${USER}-cat-out"
86 CAT_ERRPUT=">& /tmp/${RESOURCE}-${USER}-cat-err"
87 else
88
89 # Korn shell specifics
90
91 # sourcing
92
93 if [ -n "${ENVSCRIPT}" ]
94 then
95 ENVSC=". ${ENVSCRIPT};"
96 fi
97
98 # no subshell needed in a ksh
99
100 OPEN_BRACKET=
101 CLOSE_BRACKET=
102
103 # redirection
104
105 OUTPUT_APP=">> ${LOGFILE} 2>&1"
106 OUTPUT="> ${LOGFILE} 2>&1"
107 CAT_OUTPUT="> /tmp/${RESOURCE}-${USER}-cat-out"
108 CAT_ERRPUT="2> /tmp/${RESOURCE}-${USER}-cat-err"
109 fi
110
111
112 debug_message "Function: set_shell_specifics - End"
113 }
114
115 validate_options()
116 {
117 debug_message "Function: validate_options - Begin"
118 ${SET_DEBUG}
119
120 #
121 # Ensure all mandatory options are set
122 #
123
124 for i in RESOURCE RESOURCEGROUP STB_PARFILE TRIGGER WAIT
125 do
126 case ${i} in
127 RESOURCE)
128 if [ -z "${RESOURCE}" ]; then
129 scds_syslog -p daemon.err -t $(syslog_tag) -m \
130 "Function: validate_options: %s Option %s not set" \
131 "${METHOD}" "-R"
132 return 1
133 fi;;
134
135 RESOURCEGROUP)
136 if [ -z "${RESOURCEGROUP}" ]; then
137 scds_syslog -p daemon.err -t $(syslog_tag) -m \
138 "Function: validate_options: %s Option %s not set" \
139 "${METHOD}" "-G"
140 return 1
141 fi;;
142
143 STB_PARFILE)
144 if [ -z "${STB_PARFILE}" ]; then
145 scds_syslog -p daemon.err -t $(syslog_tag) -m \
146 "Function: validate_options: %s Option %s not set" \
147 "${METHOD}" "-P"
148 return 1
149 fi;;
150
151 TRIGGER)
152 if [ -z "${TRIGGER}" ]; then
153 scds_syslog -p daemon.err -t $(syslog_tag) -m \
154 "Function: validate_options: %s Option %s not set" \
155 "${METHOD}" "-T"
156 return 1
157 fi;;
158
159 WAIT)
160 if [ -z "${WAIT}" ]; then
161 scds_syslog -p daemon.err -t $(syslog_tag) -m \
162 "Function: validate_options: %s Option %s not set" \
163 "${METHOD}" "-W"
164 return 1
165 fi;;
166 esac
167 done
168
169 debug_message "Function: validate_options - End"
170 }
171
172 validate()
173 {
174 #
175 # Validate
176 #
177
178 debug_message "Function: validate - Begin"
179 ${SET_DEBUG}
180
181 rc_validate=0
182
183 # Validating the Standby Host
184
185 if [ -n "${STB_HOST}" ]
186 then
187 if ! ${GETENT} hosts ${STB_HOST} >/dev/null 2>&1
188 then
189
190 scds_syslog -p daemon.err -t $(syslog_tag) -m \
191 "Function: validate - The standby host %s is not resolvable" \
192 "${STB_HOST}"
193 rc_validate=1
194
195 else
196 debug_message "Function: validate - STB_HOST resolvable"
197 fi
198
199 else
200 debug_message "Function: validate - STB_HOST OK"
201 fi
202
203 # Validating The WAIT parameter
204
205 if ! let x=${WAIT} >/dev/null 2>&1
206 then
207
208 # SCMSGS
209 # @explanation
210 # The value specified in the WAIT variable
211 # is not numeric
212 # @user_action
213 # Fix the WAIT variable in the
214 # Configuration file.
215 scds_syslog -p daemon.err -t $(syslog_tag) -m \
216 "Function: validate: WAIT %s is not numeric" \
217 "${WAIT}"
218 rc_validate=1
219
220 else
221 debug_message "Function: validate - WAIT numeric"
222 fi
223
224
225 # Validating the standby database parameter file. We are checking the existance, if it has to exist,
226 # and if it is a valid parameter file. The content is validated by the standby PostgreSQL resource.
227 # The validation can only be successful if the parameter file is available.
228 # The precondition for the validation is that either the standby host is configured and matches
229 # the hostname, or the standby host is empty.
230
231 val_pfile=1
232 if [ -z "${STB_HOST}" ]
233 then
234 val_pfile=0
235 else
236 hostname=`${UNAME} -n`
237 if [ "${hostname}" == "${STB_HOST}" ]
238 then
239 val_pfile=0
240 fi
241 fi
242
243 if [ ${val_pfile} -eq 0 ]
244 then
245
246 if val_parfile ${STB_PARFILE} "USER PGROOT PGDATA PGPORT PGLOGFILE SCDB SCUSER SCTABLE NOCONRET"
247 then
248
249 # Source the standbys parmeter file.
250
251 . ${STB_PARFILE}
252
253 # Validating the trigger file.
254 # The trigger file has to be present in the pg_standby command specified in the
255 # recovery.conf file. This will be checked only if the recovery.conf file exists.
256
257 if [ -f {PGDATA}/recovery.conf ]
258 then
259
260 if ! ${GREP} ${TRIGGER} ${PGDATA}/recovery.conf >/dev/null 2>&1
261 then
262 # SCMSGS
263 # @explanation
264 # The trigger file specified in the configuration file
265 # is not mentioned in the recovery.conf.
266 # @user_action
267 # Fix the configuration file or the recovery.conf.
268 scds_syslog -p daemon.err -t $(syslog_tag) -m \
269 "Function: validate: The trigger file %s not set in %s" \
270 "${TRIGGER}" "${PGDATA}/recovery.conf"
271 rc_validate=1
272
273 fi
274 fi
275 else
276
277 rc_validate=1
278
279 fi
280 fi
281
282 debug_message "Function: validate - End"
283 return ${rc_validate}
284 }
285
286 val_parfile()
287 {
288 # Common valdation for parameter file
289 #
290 # If the parameter is in $2, there will be an intensive validation.
291 # If $2 is empty, the validation will just check for the existance of the file.
292
293 debug_message "Function: val_parfile - Begin"
294 ${SET_DEBUG}
295
296 rc_val_parfile=0
297
298 # Validate that parameter file exists
299
300 PARFILE=${1}
301 PARLIST=${2}
302
303 if [ ! -f "${PARFILE}" ]; then
304 scds_syslog -p daemon.err -t $(syslog_tag) -m \
305 "Function: val_parfile - File %s does not exist" \
306 "${PARFILE}"
307 rc_val_parfile=1
308 else
309 debug_message "Function: val_parfile - ${PARFILE} exists"
310 fi
311
312 # Test the semantics only, if the parameter list is specified.
313 # This should not be done when called from validate_probe.
314
315 if [ -n "${2}" ]
316 then
317
318 # Test if the parameter file is a valid ksh script
319
320 if ! ksh -n ${PARFILE} >/dev/null 2>&1
321 then
322 scds_syslog -p daemon.err -t $(syslog_tag) -m \
323 "Function: validate - Syntax errors in %s" \
324 "${PARFILE}"
325 rc_val_parfile=1
326 else
327 debug_message "Function: val_parfile - validated ${PARFILE}"
328 fi
329
330 # Test if all the mandatory variables are included and set correctly in the parameter file
331
332 PARAMETERS=`${CAT} ${PARFILE} |${GREP} -v "^#"|${GREP} -v "^ "|${NAWK} -F= '{print $1}'`
333
334 for i in ${PARLIST}
335 do
336 if ! `${ECHO} ${PARAMETERS} |${GREP} ${i} > /dev/null `; then
337 scds_syslog -p daemon.err -t $(syslog_tag) -m \
338 "Function: val_parfile - %s not specified in %s, which is required" \
339 "${i}" "${PARFILE}"
340 rc_val_parfile=1
341 else
342 debug_message "Function: val_parfile - ${i} included in ${PARFILE}"
343 fi
344 done
345 fi
346
347 debug_message "Function: val_parfile - End"
348 return ${rc_val_parfile}
349 }
350
351 start_rolechg()
352 {
353 #
354 # Start PostgreSQL
355 #
356
357 debug_message "Function: start_rolechg - Begin"
358 ${SET_DEBUG}
359
360 rc_start_command=0
361
362 # disable the pmf tag and run a sleep in the background, to make sure, that there will be a valid
363 # pmftag during the start phase.
364
365 START_TIMEOUT=`${SCHA_RESOURCE_GET} -O START_TIMEOUT -R ${RESOURCE} -G ${RESOURCEGROUP}`
366 sleep ${START_TIMEOUT} &
367
368 ${PMFADM} -s ${RESOURCEGROUP},${RESOURCE},0.svc
369
370 # remove output files to satisfy noclobber
371
372 ${RM} /tmp/${RESOURCE}-${USER}-cat-out >/dev/null 2>&1
373 ${RM} /tmp/${RESOURCE}-${USER}-cat-err >/dev/null 2>&1
374
375 hostname=`${UNAME} -n`
376 if [ "${hostname}" == "${STB_HOST}" ]
377 then
378
379 # check if postgres is reacting on PGPORT.
380
381 ${ECHO} |${MCONNECT} -p ${PGPORT} ${PGHOST} >/dev/null 2>&1
382
383 if [ ${?} -eq 0 ]
384 then
385
386 # If Postgres is listening on PGPORT, check if Postgres is acting as a primary.
387
388 set_shell_specifics
389
390 srm_function ${USER}
391
392 # Set the necessary environment variables.
393 LIBPATH=
394 if [ -n "${LD_LIBRARY_PATH}" ]
395 then
396 LIBPATH="${ENV} LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
397 fi
398
399 # The variable PASSWORD is set to the database user login password.
400
401 PASSWORD=
402 if [ -n "${SCPASS}" ]
403 then
404 PASSWORD="${ENV} PGPASSWORD=${SCPASS}"
405 fi
406 PORT="PGPORT=${PGPORT}"
407 DATA="PGDATA=${PGDATA}"
408
409 if [ -n "${PGHOST}" ]
410 then
411 HOST="${ENV} PGHOST=${PGHOST}"
412 fi
413
414 # First check if Postgres accepts accepts inserts
415
416 DBINSROLE="insert into ${SCTABLE} (sccol) values('rolechangers standby test');"
417 ${SU} ${USER} -c "${OPEN_BRACKET} ${TASK_COMMAND} ${LIBPATH} $HOST ${PASSWORD} ${ENV} ${DATA} ${ENV} ${PORT} ${PGROOT}/bin/psql -d ${SCDB} -U ${SCUSER} -c \"${DBINSROLE}\" ${CAT_OUTPUT} ${CLOSE_BRACKET} ${CAT_ERRPUT}" >/dev/null
418
419
420 if [ ${?} -ne 0 ]
421 then
422 # Only if PostgreSQL does not accept inserts, touch the trigger file
423 # to initate a role change from standby to primary.
424
425 # Wait on a just starting standby.
426
427 ${SLEEP} ${WAIT}
428
429 ${TOUCH} ${TRIGGER}
430
431 # Wait until PostgreSQL changed its role to primary.
432
433 while [ -f ${PGDATA}/recovery.conf ]
434 do
435 ${SLEEP} 1
436 done
437
438 fi
439 fi
440 fi
441 debug_message "Function: start_rolechg - End"
442 return ${rc_start_command}
443 }
444
445 stop_rolechg()
446 {
447 #
448 # Stop the role changer
449 #
450
451 debug_message "Function: stop_rolechg - Begin"
452 ${SET_DEBUG}
453
454 # Just eliminate a probable pending sleep which may be executed by the start
455
456 # Send a kill to any pids under the PMFtag
457 ${PMFADM} -s ${RESOURCEGROUP},${RESOURCE},0.svc KILL 2> /dev/null
458
459 debug_message "Function: stop_rolechg - End"
460 return ${rc_stop_command}
461 }