New functions
  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 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 22 # Use is subject to license terms.
 23 #
 24 #ident   "@(#)functions 1.1     08/02/14 SMI"
 25 #
 26 
 27 PKG=SUNWscxvm
 28 LOGFILE=/var/tmp/${RESOURCE}_logfile
 29 TASK_COMMAND=""
 30 RESOURCE_PROJECT_NAME=""
 31 SCLOGGER=/usr/cluster/lib/sc/scds_syslog
 32 LOGGER=/usr/bin/logger
 33 
 34 syslog_tag()
 35 {
 36         ${SET_DEBUG}
 37         print "SC[${PKG:-??}.${METHOD:-??}]:${RESOURCEGROUP:-??}:${RESOURCE:-??}"
 38 }
 39 
 40 scds_syslog()
 41 {
 42         if [ -f "${SCLOGGER}" ]
 43         then
 44            ${SCLOGGER} "$@" &
 45         else
 46            while getopts 'p:t:m' opt
 47            do
 48                 case "${opt}" in
 49                    t) TAG=${OPTARG};;
 50                    p) PRI=${OPTARG};;
 51                 esac
 52            done
 53         
 54            shift $((${OPTIND} - 1))
 55            LOG_STRING=`/usr/bin/printf "$@"`
 56            ${LOGGER} -p ${PRI} -t ${TAG} ${LOG_STRING}
 57         fi
 58 }
 59 
 60 debug_message()
 61 {
 62         if [ "${DEBUG}" = "${RESOURCE}" -o "${DEBUG}" = "ALL" ]
 63         then
 64            SET_DEBUG="set -x"
 65            DEBUG_TEXT=${1}
 66 
 67            scds_syslog -p daemon.debug -t $(syslog_tag) -m \
 68               "%s" "${DEBUG_TEXT}"
 69         else
 70            SET_DEBUG=
 71         fi
 72 }
 73 
 74 validate()
 75 {
 76         debug_message "Function: validate - Begin"
 77         ${SET_DEBUG}
 78 
 79         if [ "$(/usr/bin/uname -i)" != "i86xpv" ] 
 80         then
 81            # SCMSGS
 82            # @explanation
 83            # Solaris is not booted with xVM.
 84            # @user_action
 85            # Ensure that the default boot grub menu is set to boot
 86            # Solaris xVM.
 87            scds_syslog -p daemon.error -t $(syslog_tag) -m \
 88                 "Node is not booted with xVM"
 89 
 90            return 1
 91         fi
 92 
 93         if [ ! -d ${DOMAIN_PATHNAME} ]
 94         then
 95            # SCMSGS
 96            # @explanation
 97            # The domain pathname does not exist.
 98            # @user_action
 99            # Ensure that the correct domain pathname is specified
100            # within /opt/SUWNscxvm/xvm/config.
101            # Solaris xVM.
102            scds_syslog -p daemon.error -t $(syslog_tag) -m \
103                 "Domain pathname not found"
104 
105            return 1
106         fi
107 
108         if [[ "${FAILOVER_TYPE}" != "normal" && "${FAILOVER_TYPE}" != "migrate" && "${FAILOVER_TYPE}" != "migrate --live" ]]
109         then
110            # SCMSGS
111            # @explanation
112            # Incorrect Failover_type specified.
113            # @user_action
114            # Ensure that Failover_type="normal"|"migrate"|"migrate --live" 
115            # is specified within /opt/SUWNscxvm/xvm/config.
116            scds_syslog -p daemon.error -t $(syslog_tag) -m \
117                 "Failover_type %s is not valid" \
118                 "${FAILOVER_TYPE}"
119 
120            return 1
121         fi
122 
123         debug_message "Function: validate - End"
124         return 0
125 }
126 
127 start_domain()
128 {
129         debug_message "Function: start_domain - Begin"
130         ${SET_DEBUG}
131 
132         /usr/bin/rm ${LOGFILE} > /dev/null
133         typeset rc=0
134 
135         # Turn off PMF restart. Starting a domain does not leave
136         # a running pid as in a classic Solaris Cluster agent.
137 
138         sleep ${START_TIMEOUT} &
139         /usr/cluster/bin/pmfadm -s ${RESOURCEGROUP},${RESOURCE},0.svc
140 
141         # Check if the domain exists. If it does not exist either 
142         #
143         # - the domain has not been initially defined
144         # - the domain name is incorrect
145         #
146         # Alternatively, we maybe starting the domain on a new node
147         # following a failover for whatever reason. As such the domain
148         # may not have been defined. To cater for this after successfully
149         # starting a domain, the domain information is dumped to an XML
150         # file which may be used to define the domain on a new node.
151         #
152         # Defining a domain using an XML file will only be done if the 
153         # domain does not exist on the Solaris Cluster xVM node.
154 
155         if /usr/bin/virsh dominfo ${DOMAIN} > /dev/null
156         then
157            debug_message "Validate - domain ${DOMAIN} exists"
158         else
159            if [ -f ${DOMAIN_PATHNAME}/${RESOURCE}.xml ]
160            then
161                 if /usr/bin/virsh define ${DOMAIN_PATHNAME}/${RESOURCE}.xml > /dev/null
162                 then
163                    # SCMSGS
164                    # @explanation
165                    # The domain is being defined using a XML file.
166                    # @user_action
167                    # None, the domain is being defined using a previously defined
168                    # XML file when the domain was last successfully started.
169                    scds_syslog -p daemon.notice -t $(syslog_tag) -m \
170                         "Domain %s defined using %s/%s.xml" \
171                         "${DOMAIN}" "${DOMAIN_PATHNAME}" "${RESOURCE}"
172                 else
173                    # SCMSGS
174                    # @explanation
175                    # The domain XML define file does not exist
176                    # @user_action
177                    # Determine if the domain name is correct or that the 
178                    # domain has been intially defined.
179                    scds_syslog -p daemon.error -t $(syslog_tag) -m \
180                         "%s/%s.xml missing for domain %s" \
181                         "${DOMAIN_PATHNAME}" "${RESOURCE}" "${DOMAIN}"
182 
183                    return 1
184                 fi
185            else
186                 # SCMSGS
187                 # @explanation
188                 # The domain does not exist.
189                 # @user_action
190                 # You must ensure that the domain exists. The preferred
191                 # method for creating a domain is to use virt-install. 
192                 # Refer to the virt-install(1M) man page for further
193                 # information.
194                 scds_syslog -p daemon.error -t $(syslog_tag) -m \
195                    "Domain %s does not exist" \
196                    "${DOMAIN}"
197 
198                 return 1
199            fi
200         fi
201 
202         # Tolerate a manually started domain and a NO-OP start
203         # otherwise start the domain.
204 
205         if [ -f ${DOMAIN_PATHNAME}/.noop_${RESOURCE} ]
206         then
207            # SCMSGS
208            # @explanation
209            # The domain was migrated or live migrated.
210            # @user_action
211            # None required. Informational message.
212            scds_syslog -p daemon.notice -t $(syslog_tag) -m \
213               "NO-OP START being performed"
214 
215            /usr/bin/rm ${DOMAIN_PATHNAME}/.noop_${RESOURCE}
216            debug_message "start_domain - ${DOMAIN_PATHNAME}/.noop_${RESOURCE} deleted"
217            
218         elif check_domain
219         then
220            # SCMSGS
221            # @explanation
222            # The domain was manually started.
223            # @user_action
224            # None required. Informational message.
225            scds_syslog -p daemon.notice -t $(syslog_tag) -m \
226               "Domain %s was manually started" \
227               "${DOMAIN}"
228         else
229            if /usr/bin/virsh start ${DOMAIN} > /dev/null
230            then
231                 # SCMSGS
232                 # @explanation
233                 # The domain was started successfully.
234                 # @user_action
235                 # None required. Informational message.
236                 scds_syslog -p daemon.info -t $(syslog_tag) -m \
237                    "Domain %s started" \
238                    "${DOMAIN}"
239            else
240                 # SCMSGS
241                 # @explanation
242                 # The domain failed to start.
243                 # @user_action
244                 # Check the syslog for further messages. If possible the 
245                 # Solaris Cluster will attempt to restart the domain.
246                 scds_syslog -p daemon.error -t $(syslog_tag) -m \
247                    "Domain %s failed to start" \
248                    "${DOMAIN}"
249 
250                 rc=1
251            fi
252         fi
253 
254         if [ ${rc} -eq 0 ]
255         then
256            # Dump the domain configuration into an XML file. This file is then used
257            # on a new Solaris Cluster xVM node to create the domain but only if the
258            # domain does not exist.
259 
260            if /usr/bin/virsh dumpxml ${DOMAIN} > ${DOMAIN_PATHNAME}/${RESOURCE}.xml
261            then
262                 debug_message "start_domain - ${DOMAIN_PATHNAME}/${RESOURCE}.xml created"
263            else
264                 # SCMSGS
265                 # @explanation
266                 # The dumpxml for domain failed.
267                 # @user_action
268                 # Determine why the /usr/bin/virsh dumpxml command failed.
269                 scds_syslog -p daemon.error -t $(syslog_tag) -m \
270                    "/usr/bin/virsh dumpxml %s > %s/%s.xml failed" \
271                    "${DOMAIN}" "${DOMAIN_PATHNAME}" "${RESOURCE}"
272            fi
273         fi
274 
275         debug_message "Function: start_domain - End"
276         return 0
277 }
278 
279 check_domain()
280 {
281         debug_message "Function: check_domain - Begin"
282         ${SET_DEBUG}
283 
284         typeset rc
285 
286         domstate=$(/usr/bin/virsh domstate ${DOMAIN})
287 
288         case "${domstate}" in
289 
290                 # Acceptable run states
291 
292                 "running"|"blocked"|"paused"|"in shutdown")
293 
294                         rc=0
295                         ;;
296                            
297                 # Restartable run states
298 
299                 "shut off"|"crashed")
300 
301                         rc=100
302                         ;;
303 
304                 # Unknown run states
305         
306                 *)              
307                         rc=100
308                         ;;
309         esac
310 
311         debug_message "check_domain - ${DOMAIN} ${domstate}"
312 
313         debug_message "Function: check_domain - End"
314         return ${rc}
315 }
316 
317 stop_domain()
318 {
319         debug_message "Function: stop_domain - Begin"
320         ${SET_DEBUG}
321 
322         MAX_MIGRATE_TIMEOUT=$(/usr/bin/expr ${STOP_TIMEOUT} \* 25 \/ 100)
323         MAX_STOP_TIMEOUT=$(/usr/bin/expr ${STOP_TIMEOUT} \* 70 \/ 100)
324         SECONDS=0
325 
326         # At resource creation, the administrator can determine the Failover_type.
327         # Valid values for Failover_type are 
328         #
329         # Failover_type="normal"
330         #   o Stop the resource (shutdown the domain)
331         #   o Failover the resource group from the source node to the target node
332         #   o Start the resource (start the domain)
333         #
334         # Failover_type="migrate"
335         #   o Suspend the domain on the source node
336         #   o Copy the domain's memory pages from the source node to the target node
337         #   o Resume the domain on the target node
338         #    
339         # Failover_type="migrate --live"
340         #   o Iteratively copy the domain's memory pages from the source node to the taregt node
341         #   o When pre-copy is no longer benefical, suspend the domain on the source node
342         #   o Copy the domain's remaning "dirty" pages from the source node to the taregt node
343         #   o Resume the domain on the target node
344         #
345         # For migration or live migration to be attempted across Solaris Cluster xVM nodes 
346         # the following conditions must be met.
347         #
348         # - The target Solaris Cluster xVM node must be running the same xVM version.
349         #
350         # - The migration TCP port must be open and accepting connections from the source
351         #    Solaris Cluster xVM node.
352         #
353         # - There must be sufficient resources for the domain to run in.
354         #
355         # - If the conditions are met and migration or live migration is successful a NO-OP 
356         # STOP and START is performed. This will ensure a successful STOP and START to the 
357         # appropriate RGM callback methods. Furthermore, doing a NO-OP RGM failover will
358         # ensure that RGM subsequently actions any dependencies and that Solaris Cluster
359         # reflects the correct state and status of resource groups and resources.
360         #
361         # - If the conditions are met but migration or live migration is not successful a
362         # normal failover will be performed.
363         #
364         # - If the conditions are not met, migration or live migration will fail and a normal 
365         # failover will be performed. 
366         #
367         # However, before attempting a migration or live migration we need to determine if the
368         # resource is being disabled. To distinguish if the resource is being disabled we
369         # test the ON_OFF_SWITCH property of the resource.
370         #
371         # If the resource is being disabled the ON_OFF_SWITCH will be DISABLED before the STOP
372         # method is called. So, conversely if the ON_OFF_SWITCH is ENABLED the resource is not
373         # being disabled and instead the resource group is undergoing either a switch to
374         # another node or is being evacuated from the node. 
375         #
376         # - If the resource is being disabled we perform a normal shutdown, regardless of the
377         # Failover_type setting. 
378 
379         ON_OFF_SWITCH=$(/usr/cluster/bin/scha_resource_get -O ON_OFF_SWITCH -R ${RESOURCE} -G ${RESOURCEGROUP})
380 
381         debug_message "stop_domain - ON_OFF_SWITCH=${ON_OFF_SWITCH}"
382         debug_message "stop_domain - FAILOVER_TYPE=${FAILOVER_TYPE}"
383 
384         if [ "${ON_OFF_SWITCH}" = "DISABLED" ]
385         then
386            domain_shutdown
387         else
388            case "${FAILOVER_TYPE}" in
389                 normal)         domain_shutdown
390                                 rc=$?
391                                 ;;
392                 migrate*)       if ! domain_migrate
393                                 then
394                                    domain_shutdown
395                                 fi
396                                 rc=$?
397                                 ;;
398                 *)              # SCMSGS
399                                 # @eplanation
400                                 # Invalid Failover_type specified.
401                                 # @user_action
402                                 # Delete and reregister the resource with 
403                                 # a valid Failover_type entry.
404                                 scds_syslog -p daemon.error -t $(syslog_tag) -m \
405                                    "Invalid Failover_type=%s" \
406                                    "${FAILOVER_TYPE}"
407                                 rc=1
408                                 ;;
409            esac
410         fi
411         
412         debug_message "Function: stop_domain - End"
413         return ${rc}
414 }
415 
416 get_target_host()
417 {
418         debug_message "Function: get_target_host - Begin"
419         ${SET_DEBUG}
420 
421         typeset rc=1
422 
423         # Here, we need to determine the target host as the resource group is either being
424         # switched or the node, where the resoure grouop is online, is being evacuated.
425         #
426         # To determine the target host for a resource group switch we rely on the cluster
427         # command log file /var/cluster/logs/commandlog to supply the target host. We need to
428         # obtain the correct entry form the command log file and match against the following
429         #
430         #       <date> + ${RESOURCEGROUP} + "START" + "switch"
431         #
432         # after which we only save the nodename from a clrg or scswitch command. 
433         #
434         # Sample /var/cluster/log/commandlog output is as follows,
435         #
436         # 02/07/2008 08:45:13 pelko1 10548 root START - scswitch -z -g "xvm2-rg" -h "pelko2"
437         # 02/07/2008 08:45:38 pelko1 10548 root END 0
438         # 02/07/2008 09:01:35 pelko1 10874 root START - clrg "switch" -n "pelko1" "xvm2-rg"
439         # 02/07/2008 09:01:36 pelko1 10874 root END -20827641
440         #
441         # If we are unable to match an entry, as perhaps the entry was logged at <date>
442         # and we are checking at <date> + 1 second, i.e. we are checking just as the second
443         # entry is incrementing to the next second, we perform another check. In fact the
444         # last 10 seconds are checked from the commandlog. 
445         #
446         # Once we have matched an entry from /var/cluster/logs/commandlog, we verify that 
447         # the target host is a valid nodelist entry for the resource group. 
448         #
449         # - If we have a valid nodelist entry we then determine that target hosts's cluster
450         # interconnect hostname to perform the migration or live migration.
451         #
452         # - If we are unable to find a match for a switch, we need to consider that an evacuate
453         # node is being performed. However, if the node is being evacuated we will rely on 
454         # RGM to dertermine the nodename regardless if a mirgation or live migration was 
455         # requested. Subsequently, we perform a normal failover. This ensures that we do not
456         # migrate or live migrate the domain to a node that maybe different to the node
457         # selected by RGM. 
458         #
459         # So, suffice to say that if a "switch" match is not found, following the discovery
460         # that the resource is not just being disabled, and that a migrate or live migrate 
461         # was defined, we will always perform a normal failover.
462         #
463         # Note that the target host match is performed within check_commandlog().
464 
465         check_commandlog
466 
467         debug_message "get_target_host - ${TARGET_HOST} size=${#TARGET_HOST}"
468 
469         if [ "${#TARGET_HOST}" -eq 0 ]
470         then
471            # SCMSGS
472            # @explanation
473            # A target host was not found
474            # @user_action
475            # None required. The domain will not be migrated or live
476            # migrated instead a normal failover will be performed.
477            scds_syslog -p daemon.notice -t $(syslog_tag) -m \
478                 "Target host not found, normal failover will be perfomed"
479 
480         elif [ ${TARGET_HOST} = "$(/usr/bin/uname -n)" ] || [ $(echo ${TARGET_HOST} | /usr/bin/grep [0-9]:global) ] 
481         then
482            # SCMSGS
483            # @explanation
484            # The node is being evecuated.
485            # @user_action
486            # None required. The domain will not be migrated or live
487            # migrated instead a normal failover will be performed.
488            scds_syslog -p daemon.notice -t $(syslog_tag) -m \
489                 "Node is being evacuated, normal failover will be perfomed"
490 
491         else
492            for i in $(/usr/cluster/bin/scha_resourcegroup_get -O NODELIST -G ${RESOURCEGROUP})
493            do
494                 [[ "${i}" != "$(uname -n)" || "${i}" = "${TARGET_HOST}" ]] && rc=0 && break
495            done
496 
497            if [ "${rc}" -eq 0 ]
498            then
499                 PRIVATELINK_TARGET_HOST=$(/usr/cluster/bin/scha_cluster_get -O PRIVATELINK_HOSTNAME_NODE ${TARGET_HOST})
500                 debug_message "get_target_host - PRIVATELINK_TARGET_HOST=${PRIVATELINK_TARGET_HOST}"
501            else
502                 # SCMSGS
503                 # @eplanation
504                 # The target host found in the command log file is not
505                 # a valid an entry within the resource groups nodelist.
506                 # @user_action
507                 # None required. The domain will not be migrated or live
508                 # migrated instead a normal failover will be performed.
509                 scds_syslog -p daemon.notice -t $(syslog_tag) -m \
510                    "Target host %s not matched with the resource group nodelist, normal failover will be perfomed" \
511                    "${TARGET_HOST}"
512            fi
513         fi
514 
515         debug_message "Function: get_target_host - End"
516         return ${rc}
517 }
518 
519 check_commandlog()
520 {
521         debug_message "Function: check_commandlog - Begin"
522         
523         # Get the current epoch time
524         typeset ETIME=$(perl -e 'print time;')
525         typeset DATE=$(date '+%m/%d/%Y')
526         i=10
527 
528         while (( $i > 0 ))
529         do
530            # Iteratively search the commandlog for a switch or evacuate, going back in time
531            # by one second each time. However, if a match is found we break out of the loop.
532            #
533            # The following may help to understand the iterative loop. 
534            #
535            # bash-3.2# ETIME=$(perl -e 'print time;')
536            # bash-3.2# echo $ETIME
537            # 1202814041
538            # bash-3.2# HHMMSS=$(echo "0t${ETIME}=Y" | /usr/bin/mdb | awk '{print $4}')
539            # bash-3.2# echo $HHMMSS
540            # 03:00:41
541            # bash-3.2# ETIME=$(expr ${ETIME} - 1)
542            # bash-3.2# echo $ETIME
543            # 1202814040
544            # bash-3.2# HHMMSS=$(echo "0t${ETIME}=Y" | /usr/bin/mdb | awk '{print $4}')
545            # bash-3.2# echo $HHMMSS
546            # 03:00:40
547            # bash-3.2#
548 
549            # Convert the epoch time into a readable format
550            HHMMSS=$(echo "0t${ETIME}=Y" | /usr/bin/mdb | /usr/bin/awk '{print $4}')
551 
552            debug_message "check_commadlog - performed for ${DATE} ${HHMMSS}"
553 
554            # Check for a clrg switch or scswitch 
555            TARGET_HOST=$(/usr/bin/grep "${DATE} ${HHMMSS}" /var/cluster/logs/commandlog |\
556                 /usr/bin/grep -w START | /usr/bin/grep switch | /usr/bin/grep -w ${RESOURCEGROUP} |\
557                 /usr/bin/sed -e 's/^.*-h //' -e 's/^.*-n //' | /usr/bin/awk '{print $1}' | /usr/xpg4/bin/tr -d '" ')
558 
559            [ "${#TARGET_HOST}" -ne 0 ] && break
560 
561            # Check for a clrg evacuate 
562            TARGET_HOST=$(/usr/bin/grep "${DATE} ${HHMMSS}" /var/cluster/logs/commandlog |\
563                 /usr/bin/grep -w START | /usr/bin/grep evacuate |\
564                  /usr/bin/sed -e 's/^.*-n //' | /usr/bin/awk '{print $1}' | /usr/xpg4/bin/tr -d '+" ' )
565 
566            [ "${#TARGET_HOST}" -ne 0 ] && break
567 
568            # Check for a scswitch -S
569            TARGET_HOST=$(/usr/bin/grep "${DATE} ${HHMMSS}" /var/cluster/logs/commandlog |\
570                 /usr/bin/grep -w START | /usr/bin/grep scswitch | /usr/bin/grep "\-S" |\
571                 /usr/bin/sed -e 's/^.*-h //' | /usr/bin/awk '{print $1}' | /usr/xpg4/bin/tr -d '\-SK" ' )
572 
573            [ "${#TARGET_HOST}" -ne 0 ] && break
574 
575            i=$(expr $i - 1)
576            ETIME=$(expr ${ETIME} - 1)
577         done
578 
579         debug_message "check_commandlog - TARGET_HOST=${TARGET_HOST}"
580 
581         debug_message "Function: check_commandlog - End"
582 }
583 
584 domain_migrate()
585 {
586         debug_message "Function: domain_migrate - Begin"
587         ${SET_DEBUG}
588 
589         typeset rc
590 
591         [ "${FAILOVER_TYPE}" = "migrate" ] && MSG="migrated"
592         [ "${FAILOVER_TYPE}" = "migrate --live" ] && MSG="live migrated"
593 
594         if get_target_host 
595         then
596            # SCMSGS
597            # @explanation
598            # The domain is being migrated or live migrated to the target host.
599            # @user_action
600            # None required. 
601            scds_syslog -p daemon.notice -t $(syslog_tag) -m \
602                 "Domain %s is being %s to %s" \
603                 "${DOMAIN}" "${MSG}" "${TARGET_HOST}"
604 
605            debug_message "domain_migrate - Running /usr/sbin/xm ${FAILOVER_TYPE} ${DOMAIN} ${PRIVATELINK_TARGET_HOST}"
606 
607            /usr/cluster/bin/hatimerun -t ${MAX_MIGRATE_TIMEOUT} -k KILL \
608                 /usr/sbin/xm ${FAILOVER_TYPE} "${DOMAIN}" ${PRIVATELINK_TARGET_HOST} > /dev/null
609            rc=$?
610 
611            if [ "${rc}" -eq 0 ]
612            then
613                 # SCMSGS
614                 # @explanation
615                 # The domain was migrated or live migrated to the target host.
616                 # @user_action
617                 # None required. The domain successfully migrated or live migrated 
618                 # from the source node to the target node.
619                 scds_syslog -p daemon.notice -t $(syslog_tag) -m \
620                    "Domain %s successfully %s to %s" \
621                    "${DOMAIN}" "${MSG}" "${TARGET_HOST}"
622 
623                 # As the domain has been successfully migrated or live migrated
624                 # we need to indicate a successful stop by performing a NO-OP stop
625                 # and subsequently a successful start by performing a NO-OP start.
626                 
627                 touch ${DOMAIN_PATHNAME}/.noop_${RESOURCE}
628                 debug_message "domain_migrate - ${DOMAIN_PATHNAME}/.noop_${RESOURCE} created"
629 
630                 # SCMSGS
631                 # @explanation
632                 # The domain was migrated or live migrated.
633                 # @user_action
634                 # None required. Informational message.
635                 scds_syslog -p daemon.notice -t $(syslog_tag) -m \
636                    "NO-OP STOP being performed" 
637 
638            elif [ "${rc}" -eq 99 ]
639            then
640                 # SCMSGS
641                 # @explanation
642                 # The domain migration or live migration timed out.
643                 # @user_action
644                 # None required. Informational message.
645                 scds_syslog -p daemon.notice -t $(syslog_tag) -m \
646                    "Migration of domain %s timed out, the domain state is now shut off" \
647                    "${DOMAIN}" 
648 
649                 rc=1
650            else
651                 # SCMSGS
652                 # @eplanation
653                 # The domain failed to migrate or live migrate to the target host.
654                 # @user_action
655                 # None required. The domain failed to migrate or live migrate 
656                 # from the source node to the target node. A normal failover
657                 # will be performed.
658                 scds_syslog -p daemon.notice -t $(syslog_tag) -m \
659                    "Domain %s failed to %s to %s, normal failover will be perfomed" \
660                    "${DOMAIN}" "${MSG}" "${TARGET_HOST}" 
661 
662                 rc=1
663            fi
664         else
665            rc=1
666         fi
667 
668         debug_message "Function: domain_migrate - End"
669         return ${rc}
670 }
671         
672 domain_shutdown()
673 {
674         debug_message "Function: domain_shutdown - Begin"
675         ${SET_DEBUG}
676 
677         typeset rc
678 
679         # Corordinate with the domain OS to perform a graceful shutdown.
680         # Note that the virsh shutdown command returns before the domain
681         # has shutdown, as such we do not use hatimerun.
682 
683         if /usr/bin/virsh shutdown ${DOMAIN} > /dev/null
684         then
685 
686            # Loop to test if the domain shuts down gracefully
687            # or if the shutdown time is exceeded.
688 
689            while [ "${SECONDS}" -lt "${MAX_STOP_TIMEOUT}" ]
690            do
691                 if check_domain
692                 then
693                    sleep 5
694                 else
695                    SECONDS=${MAX_STOP_TIMEOUT}
696                 fi
697            done
698 
699            if check_domain
700            then
701                 # SCMSGS
702                 # @explanation
703                 # The domain failed to shutdown gracefully.
704                 # @user_action
705                 # None required. The domain failed to shutdown 
706                 # gracefully and will now be immediately terminated.
707                 scds_syslog -p daemon.notice -t $(syslog_tag) -m \
708                    "Domain %s failed to shutdown gracefully" \
709                    "${DOMAIN}"
710 
711                 domain_destroy
712                 rc=$?
713            else
714                 # SCMSGS
715                 # @explanation
716                 # The domain was shutdown gracefully.
717                 # @user_action
718                 # None required. The domain has shutdown gracefully.
719                 scds_syslog -p daemon.info -t $(syslog_tag) -m \
720                    "Domain %s has been gracefully shutdown" \
721                    "${DOMAIN}"
722                 rc=0
723            fi
724 
725         else
726            # SCMSGS
727            # @explanation
728            # The /usr/bin/virsh shutdown command failed.
729            # @user_action
730            # None required. The domain will now be terminated immediately.
731            scds_syslog -p daemon.notice -t $(syslog_tag) -m \
732                 "Domain %s failed to gracefully shutdown, immediate shutdown will now be performed" \
733                 "${DOMAIN}"
734 
735            domain_destroy
736            rc=$?
737         fi
738 
739         debug_message "Function: domain_shutdown - End"
740         return ${rc}
741 }
742 
743 domain_destroy()
744 {
745         debug_message "Function: domain_destroy - Begin"
746         ${SET_DEBUG}
747 
748         typeset rc
749 
750         if /usr/bin/virsh destroy ${DOMAIN} > /dev/null
751         then
752            # SCMSGS
753            # @explanation
754            # The domain was immediately terminated.
755            # @user_action
756            # None required. The domain had previously failed to shutdown
757            # gracefully but has now been immediately terminated.
758            scds_syslog -p daemon.notice -t $(syslog_tag) -m \
759                 "Domain %s has been immediately terminated" \
760                 "${DOMAIN}"
761            rc=0
762         else
763            # SCMSGS
764            # @explanation
765            # The /usr/bin/virsh destroy command failed.
766            # @user_action
767            # Determine why it was not possible to immediately terminate
768            # the domain. 
769            scds_syslog -p daemon.error -t $(syslog_tag) -m \
770                 "Domain %s failed to shutdown immediately" \
771                 "${DOMAIN}"
772            rc=1
773         fi
774 
775         debug_message "Function: domain_destroy - End"
776         return ${rc}
777 }
778