New functions_static.ksh
  1 #
  2 
  3 # CDDL HEADER START
  4 #
  5 # The contents of this file are subject to the terms of the
  6 # Common Development and Distribution License (the License).
  7 # You may not use this file except in compliance with the License.
  8 #
  9 # You can obtain a copy of the license at usr/src/CDDL.txt
 10 # or http://www.opensolaris.org/os/licensing.
 11 # See the License for the specific language governing permissions
 12 # and limitations under the License.
 13 #
 14 # When distributing Covered Code, include this CDDL HEADER in each
 15 # file and include the License file at usr/src/CDDL.txt.
 16 # If applicable, add the following below this CDDL HEADER, with the
 17 # fields enclosed by brackets [] replaced with your own identifying
 18 # information: Portions Copyright [yyyy] [name of copyright owner]
 19 #
 20 # CDDL HEADER END
 21 #
 22 
 23 #
 24 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 25 # Use is subject to license terms.
 26 #
 27 
 28 #ident  "%Z%%M% %I%     %E% SMI"
 29 
 30 TASK_COMMAND=""
 31 
 32 ZONENAME=/usr/bin/zonename
 33 
 34 SCLOGGER=/usr/cluster/lib/sc/scds_syslog
 35 LOGGER=/usr/bin/logger
 36 SCHA_RESOURCE_SETSTATUS=/usr/cluster/bin/scha_resource_setstatus
 37 SCHA_RESOURCE_GET=/usr/cluster/bin/scha_resource_get
 38 SCHA_RESOURCEGROUP_GET=/usr/cluster/bin/scha_resourcegroup_get
 39 PMFADM=/usr/cluster/bin/pmfadm
 40 UNAME=/usr/bin/uname
 41 ECHO=/usr/bin/echo
 42 AWK=/usr/bin/awk
 43 EGREP=/usr/bin/egrep
 44 GREP=/usr/bin/grep
 45 PROJECTS=/usr/bin/projects
 46 WC=/usr/bin/wc
 47 CAT=/usr/bin/cat
 48 ENV=/usr/bin/env
 49 RM=/usr/bin/rm
 50 SSH_AGENT=/usr/bin/ssh-agent
 51 SSH_ADD=/usr/bin/ssh-add
 52 CHMOD=/usr/bin/chmod
 53 
 54 terminate()
 55 {
 56 
 57         debug_message "Function: terminate - Begin"
 58         ${SET_DEBUG}
 59 
 60         exiting_func=${1}
 61         exit_code=${2}
 62 
 63         # determine the right return code, it is either the return code from the functions or
 64         # the appropriate smf return code
 65 
 66         if in_cluster
 67         then
 68                 
 69                 # called in a clustered global zone
 70                 
 71                 debug_message "Method: ${MYNAME} ${exiting_func} - End (${exit_code})"
 72                 exit ${exit_code}
 73                 
 74         else
 75                 if [ -n "${SMF_FMRI}" ]
 76                 then
 77                         if [ "${exit_code}" -ne 0 ]
 78                         then
 79                         
 80                                 # honour the gds specific probe values like 100 or 201
 81                         
 82                                 if [ "${exiting_func}" == "probe" -o "${exiting_func}" == "validate" ]
 83                                 then
 84                                         debug_message "Method: ${MYNAME} ${exiting_func} - End (${exit_code})"
 85                                         exit ${exit_code}
 86                                 else
 87                                         debug_message "Method: ${MYNAME} ${exiting_func} - End (${SMF_EXIT_ERR_PERM})"
 88                                         exit ${SMF_EXIT_ERR_PERM}
 89                                 fi
 90                         fi
 91                         
 92                         debug_message "Method: ${MYNAME} ${exiting_func} - End (${SMF_EXIT_OK})"
 93                         exit ${SMF_EXIT_OK}
 94                 else
 95                         debug_message "Method: ${MYNAME} ${exiting_func} - End (${exit_code})"
 96                         exit ${exit_code}
 97                 fi
 98         fi
 99 
100         debug_message "Function: terminate - End"
101 
102 }
103 syslog_tag()
104 {
105         #
106         # Data Service message format
107         #
108 
109         ${SET_DEBUG}
110 
111         print "SC[${PKG:-??}.${METHOD:-??}]:${RESOURCEGROUP:-??}:${RESOURCE:-??}"
112 }
113 
114 scds_syslog()
115 {
116 
117         #
118         # Log a message
119         #
120 
121         ${SET_DEBUG}
122 
123         if [ -f ${SCLOGGER} ]
124         then
125                 ${SCLOGGER} "$@" &
126         else
127         
128                 # eliminate -m and honour -p and -t option
129                 while getopts 'p:t:m' opt
130                 do
131                         case "${opt}" in
132                                 t) TAG=${OPTARG};;
133                                 p) PRI=${OPTARG};;
134                         esac
135                 done
136         
137                 shift $((${OPTIND} - 1))
138                 LOG_STRING=`/usr/bin/printf "$@"`
139         
140                 ${LOGGER} -p ${PRI} -t ${TAG} ${LOG_STRING}
141         fi
142 
143 }
144 
145 rgs_zonename()
146 {
147 
148 # Determine wether the host specified by uname -n is combined with a zonename in the 
149 # current resourcegroups nodelist. The seperator beween nodename and zonename is ":".
150 #
151 # This function assume the resource group name preset in the variable ${RESOURCEGROUP} and should be called 
152 #
153 # $(rgs_zonename) 
154 #
155 # It passes back a zonename or nothing. 
156 # If there are more than one zones in the nodelist, it passes back either the zone where the resource group
157 # is online or first one in the list.
158 
159         debug_message "Function: rg_zonename - Begin "
160         ${SET_DEBUG}
161 
162         nodes_zone=
163         nodename=`${UNAME} -n`
164         node=`${SCHA_RESOURCEGROUP_GET} -G ${RESOURCEGROUP} -O NODELIST|${EGREP} "${nodename}$|${nodename}:"`
165 
166         if ${ECHO} ${node} | ${GREP} : >/dev/null 2>&1
167         then
168                 if [ `${ECHO} ${node}|${WC} -w` -gt 1 ]
169                 then
170                         online=0
171                         for i in ${node}
172                         do
173                                 if ${SCHA_RESOURCEGROUP_GET} -G ${RESOURCEGROUP} -O RG_state_node ${i}| ${GREP} -i online >/dev/null 2>&1
174                                 then
175                                         nodes_zone=`${ECHO} ${i} | ${AWK} -F: '{print $2}'`
176                                         online=1
177                                 fi
178                         done
179 
180                         # check if we found a zone where the resource group is online, if not pick the first zone in the list
181 
182                         if [ ${online} -eq 0 ]
183                         then
184                                 first_node=`${ECHO} ${node} | ${AWK} '{print $1}'`
185                                 nodes_zone=`${ECHO} ${first_node} | ${AWK} -F: '{print $2}'`
186                         fi
187                 else
188                         nodes_zone=`${ECHO} ${node} | ${AWK} -F: '{print $2}'`
189                 fi
190                 
191         fi
192 
193         print ${nodes_zone}
194 
195         debug_message "Function: rg_zonename - End "
196 }
197 
198 debug_message()
199 {
200         #
201         # Output a debug message to syslog if required
202         #
203 
204         if [ -n "${DEBUG}" ]
205         then
206 
207                 # determine if we should display a message and do it
208 
209                 if [ "${DEBUG}" = "ALL" ]
210                 then
211                         SET_DEBUG="set -x"
212 
213                         DEBUG_TEXT=${1}
214 
215                         scds_syslog -p daemon.debug -t $(syslog_tag) -m \
216                         "%s" "${DEBUG_TEXT}"
217                 else
218 
219                         # check if the actual resource matches one of the list of resources
220                         # if it matches, display a message
221 
222                         DEBUG=`echo ${DEBUG}|tr "," " "`
223                         for i in ${DEBUG}
224                         do
225                                 if [ "${i}" = "${RESOURCE}" ]
226                                 then
227                                         SET_DEBUG="set -x"
228 
229                                         DEBUG_TEXT=${1}
230 
231                                         scds_syslog -p daemon.debug -t $(syslog_tag) -m \
232                                         "%s" "${DEBUG_TEXT}"
233                                 fi
234                         done
235                 fi
236         else
237                 SET_DEBUG=
238         fi
239 }
240 
241 log_message()
242 {
243         #
244         # Output a message to syslog as required
245         #
246 
247         debug_message "Function: log_message - Begin"
248         ${SET_DEBUG}
249 
250         if [ -s "${LOGFILE}" ]
251         then
252                 PRIORITY=${1}
253                 HEADER=${2}
254 
255                 # 
256                 # Ensure the while loop only reads a closed file
257                 #
258 
259                 strings ${LOGFILE} > ${LOGFILE}.copy
260                 while read MSG_TXT
261                 do
262                         scds_syslog -p daemon.${PRIORITY} -t $(syslog_tag) -m \
263                                 "%s - %s" \
264                                 "${HEADER}" "${MSG_TXT}"
265                 done < ${LOGFILE}.copy
266 
267         fi
268 
269         debug_message "Function: log_message - End"
270 }
271 
272 srm_function()
273 {
274         debug_message "Function: srm_function - Begin"
275         ${SET_DEBUG}
276 
277         USER=${1}
278 
279         #
280         # If Solaris 8 just return
281         #
282 
283         if [ `/usr/bin/uname -r` = "5.8" ];
284         then
285                 return 0
286         fi
287 
288         #
289         # Retrieve RESOURCE_PROJECT_NAME
290         #
291 
292         if in_cluster
293         then
294                 RESOURCE_PROJECT_NAME=`${SCHA_RESOURCE_GET} -R ${RESOURCE} -G ${RESOURCEGROUP} -O  RESOURCE_PROJECT_NAME`
295 
296                 #
297                 # Retrieve RG_PROJECT_NAME if RESOURCE_PROJECT_NAME is not set
298                 #
299 
300                 if [ -z "${RESOURCE_PROJECT_NAME}" ] || [ "${RESOURCE_PROJECT_NAME}" = "default" ];then
301 
302                         RESOURCE_PROJECT_NAME=`${SCHA_RESOURCEGROUP_GET} -G ${RESOURCEGROUP} -O RG_PROJECT_NAME`
303                 fi
304         else
305                 RESOURCE_PROJECT_NAME=${ZONE_PROJECT}
306         fi
307 
308         #
309         # Return if no projects are defined
310         #
311 
312         if [ -z "${RESOURCE_PROJECT_NAME}" ] || [ "${RESOURCE_PROJECT_NAME}" = "default" ]; then
313                 return 0
314         fi
315 
316         #
317         # Validate that $USER belongs to the project defined by
318         # ${RESOURCE_PROJECT_NAME}
319         #
320 
321         PROJ_MEMBER=`${PROJECTS} ${USER} | ${EGREP} "^${RESOURCE_PROJECT_NAME} | ${RESOURCE_PROJECT_NAME} | ${RESOURCE_PROJECT_NAME}$|^${RESOURCE_PROJECT_NAME}$"`
322 
323         if [ -z "${PROJ_MEMBER}" ];
324         then
325              # SCMSGS
326              # @explanation
327              # The specified user does not belong to the project defined by
328              # Resource_project_name or Rg_project_name.
329              # @user_action
330              # Add the user to the defined project in /etc/project.
331              scds_syslog -p daemon.err -t $(syslog_tag) -m \
332                         "srm_function - The user %s does not belongs to project %s" \
333                         "${USER}" "${RESOURCE_PROJECT_NAME}" 
334                 return 1
335         else
336                 debug_message "srm_function - User ${USER} belongs to project ${RESOURCE_PROJECT_NAME}"
337         fi
338 
339         #
340         # Set TASK_COMMAND
341         #
342 
343         TASK_COMMAND="/usr/bin/newtask -p ${RESOURCE_PROJECT_NAME}"
344 
345         debug_message "Function: srm_function - End"
346 
347         return 0
348 }
349 
350 zone_function()
351 {
352         debug_message "Function: zone_function - Begin"
353         ${SET_DEBUG}
354 
355         #
356         # Initialize PZONEOPT as empty
357         PZONEOPT=""
358 
359         #
360         # If Solaris does not have /usr/bin/zonename just return 0
361         # else add "-z <zonename>" to PZONEOPT
362         #
363 
364         if [ -x "${ZONENAME}" ];
365         then
366                 PZONEOPT="-z `${ZONENAME}`"
367         fi
368 
369         debug_message "Function: zone_function - End"
370         return 0
371 }
372 
373 in_cluster()
374 {
375         #
376         # determine if we are started in a clustered global zone
377         #
378 
379         debug_message "Function: in_cluster - Begin"
380         ${SET_DEBUG}
381         
382         in_cluster_val=0
383         
384         if [ ! -d /etc/cluster ]
385         then
386                 in_cluster_val=1
387         fi      
388 
389         debug_message "Function: in_cluster - End"
390         
391         return ${in_cluster_val}
392 }
393 
394 start_dependency()
395 {
396         debug_message "Function: start_dependency - Begin"
397         ${SET_DEBUG}
398 
399         # RETRIEVE START_TIMEOUT
400 
401         if [-z "${ZONE_START_TIMOUT}" ]
402         then
403                 START_TIMEOUT=`standard_resource_get START_TIMEOUT`
404         else
405                 START_TIMEOUT=${ZONE_START_TIMOUT} 
406         fi
407 
408         # 80 % OF THE START-TIMEOUT CAN BE SPENT ON WAITING
409 
410         MAX_START_TIMEOUT=`expr ${START_TIMEOUT} \* 80 \/ 100`
411 
412         # GET CURRENT TIME IN SEC ON 24H BASE
413                 
414         CUR_HOUR=`date '+%H'`
415         CUR_MIN=`date '+%M'`
416         CUR_SEC=`date '+%S'`
417         CUR_TIME=`expr ${CUR_HOUR} \* 3600 + ${CUR_MIN} \* 60 + ${CUR_SEC}`
418 
419         # RUN A TEST LOOP UNTIL THE DEPENDENT RESOURCE IS UP OR 
420         # A TIMEOUT HAS OCCURED
421 
422         while [ 1 -eq 1 ]
423         do
424 
425                 # GET NEW CURRENT TIMEOUT
426                 NEW_HOUR=`date '+%H'`
427                 NEW_MIN=`date '+%M'`
428                 NEW_SEC=`date '+%S'`
429                 NEW_TIME=`expr ${NEW_HOUR} \* 3600 + ${NEW_MIN} \* 60 + ${NEW_SEC}`
430 
431                 # HAVE WE EXEEDED TIMEOUT
432 
433                 s1=`expr ${CUR_TIME} + ${MAX_START_TIMEOUT}`
434 
435                 if [ ${s1} -le ${NEW_TIME} ]; then
436                         # SCMSGS
437                         # @explanation
438                         # The start of a dependent resource takes too long.
439                         # @user_action
440                         # None
441                         scds_syslog -p daemon.err -t $(syslog_tag) -m \
442                         "start_dependency: Exeeded ${MAX_START_TIMEOUT} seconds for waiting on dependent resource for resource ${RESOURCE} to come online"
443 
444                         St=1
445                         break
446                 fi
447 
448                 # CALL check_start_dependency
449 
450                 debug_message "Function: start_dependency - Call check_start_dependency function with argument "$*
451 
452                 check_start_dependency $*
453                 St=$?
454 
455                 if [ ${St} -eq 0 ]; then
456                   St=0
457                   break
458                 fi
459 
460                 # Wait 5 seconds
461 
462                 sleep 5
463         done
464 
465 
466         debug_message "Function: start_dependency - End"
467 
468         return ${St}
469 }
470 
471 restart_dependency()
472 {
473         debug_message "Function: restart_dependency - Begin"
474         ${SET_DEBUG}
475 
476 
477         # CALL check_restart_dependency
478 
479         debug_message "Function: start_dependency - Call check_restart_dependency function with argument "$*
480         check_restart_dependency $*
481         St=$?
482 
483         if [ ${St} -ne 0 ]; then
484            # SCMSGS
485            # @explanation
486            # The dependent resource was restarted, the resource is restarting
487            # now.
488            # @explanation-2
489            # A restart of the dependant resource has been noticed,
490            # it might be necessary to restart the resource depending on
491            # @explanation-3
492            # a restart of the dependant resource has been noticed, it might be
493            # necessary to restart the resource depending on
494            # @explanation-4
495            # a restart of the dependant resource has been noticed, it might be
496            # necessary to restart the resource depending on
497            # @user_action
498            # None
499            # @user_action-2
500            # check the validity of the service. there might be a dependency
501            # problem, a sub resource has been restarted, and functionality
502            # might have been impaired
503            # @user_action-3
504            # check the validity of the service. there might be a dependency
505            # problem, a sub resource has been restarted, and functionality
506            # might have been impaired
507            # @user_action-4
508            # check the validity of the service. there might be a dependency
509            # problem, a sub resource has been restarted, and functionality
510            # might have been impaired
511            scds_syslog -p daemon.err -t $(syslog_tag) -m \
512            "restart_dependency - Dependent resource to resource %s has been restarted, restart this resource %s" \
513            "${RESOURCE}" "${RESOURCE}"
514 
515            St=100
516         else
517            St=0
518         fi
519 
520         debug_message "Function: restart_dependency - End"
521 
522         return ${St}
523 }
524 
525 start_ssh_agent()
526 {
527         # 
528         # Start an ssh-agent and add the decrypted private key.
529         # Only when the ssh-agent contains the private key, a ssh login without a 
530         # passphrase challenge is possible.
531         #
532         # This function stores the environment variables SSH_AUTH_SOCK and 
533         # SSH_AGENT_PID in /tmp/${RESOURCE}-ssh in a ksh compatible format. 
534         #
535         # The start_ssh_agent function is meant to be called in the target users 
536         # environment.
537         #
538         # The only necessary parameter is the passphrase of the target users
539         # private ssh key.
540         # If you use this function you should kill the started ssh-agent in your 
541         # stop function.
542         #
543         # To do this you have to export the SSH_AGENT_PID from tmp/${RESOURCE}-ssh
544         # in the users environment and call /usr/bin/ssh-agent -k.
545         #
546         # The returncode of the start_ssh_agent function is 0 for success, and 1 for error.
547 
548         debug_message "Function: start_ssh_agent - Begin"
549         ${SET_DEBUG}
550 
551         SSH_PASS=${1}
552 
553         rc_start_ssh_agent=0
554         export DISPLAY=""
555 
556         # remove the SSH_ASKPASS script and the temporary store of SSH_AUTH_SOCK 
557         # and SSH_AGENT_PID to satisfy noclobber
558 
559         ${RM} /tmp/${RESOURCE}-askpass 2>/dev/null
560         ${RM} /tmp/${RESOURCE}-ssh 2>/dev/null
561 
562         # start the ssh-agent
563 
564         eval `${SSH_AGENT} -s` >/dev/null 2>&1
565         if [ ${?} -eq 0 ]
566         then
567                 debug_message "Function: start_ssh_agent - ssh-agent started"
568 
569                 ${ENV} | ${EGREP} "SSH_AUTH_SOCK|SSH_AGENT_PID">/tmp/${RESOURCE}-ssh
570         
571                 # create the SSH_ASKPASS script needed for a headless ssh-agent
572 
573                 export SSH_ASKPASS=/tmp/${RESOURCE}-askpass
574                 ${CAT} > ${SSH_ASKPASS} <<EOF
575 #!/usr/bin/ksh
576 # reads a passphrase at the ssh-agent command
577 read x
578 ${ECHO} \${x}
579 EOF
580                 ${CHMOD} +x ${SSH_ASKPASS}
581 
582                 # decrypt the private key and store it in memory
583 
584                 if  print ${SSH_PASS}|${SSH_ADD} >/dev/null 2>&1
585                 then
586                         debug_message "Function: start_ssh_agent - ssh-add successful, private key decryped and stored"
587                 else
588                         # SCMSGS
589                         # @explanation
590                         # The ssh passphrase passed to the start_ssh_agent function is wrong
591                         # @user_action
592                         # Fix the ssh passphrase entry in your parameters
593                         scds_syslog -p daemon.err -t $(syslog_tag) -m \
594                                 "start_ssh_agent: The passphrase %s is wrong" \
595                                 "${SSH_PASS}" 
596                         rc_start_ssh_agent=1
597                 fi
598 
599                 # remove the previously created askpass script
600 
601                 ${RM} ${SSH_ASKPASS}
602         else
603                 # SCMSGS
604                 # @explanation
605                 # The ssh-agent is not startable for the given user
606                 # @user_action
607                 # Determine and fix the root cause by running the ssh-agent manually
608                 # as the target user
609                 scds_syslog -p daemon.err -t $(syslog_tag) -m \
610                         "start_ssh_agent: The start of the ssh-agent was unsuccessful" 
611                 rc_start_ssh_agent=1
612 
613         fi
614 
615         debug_message "Function: start_ssh_agent - End"
616         return ${rc_start_ssh_agent}
617         
618 }