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 }