source: gpfs_3.1_ker2.6.20/lpp/mmfs/bin/mmimportfs @ 214

Last change on this file since 214 was 16, checked in by rock, 17 years ago
  • Property svn:executable set to *
File size: 56.9 KB
Line 
1#!/bin/ksh
2# IBM_PROLOG_BEGIN_TAG
3# This is an automatically generated prolog.
4
5
6
7# Licensed Materials - Property of IBM
8
9# (C) COPYRIGHT International Business Machines Corp. 2003,2006
10# All Rights Reserved
11
12# US Government Users Restricted Rights - Use, duplication or
13# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
14
15# IBM_PROLOG_END_TAG
16# @(#)37 1.45.1.2 src/avs/fs/mmfs/ts/admin/mmimportfs.sh, mmfs, avs_rgpfs24, rgpfs24s002a 4/21/06 14:48:31
17##############################################################################
18#
19# Usage:
20#   mmimportfs {Device|all} -i ImportfsFile [-S ChangeSpecFile] [-R]
21#
22# where
23#   Device        is the file system to be imported.
24#                 If Device is "all", then all file systems in
25#                 the input file are imported.  Free disks, if any,
26#                 are imported as well.
27#                 Note:  To request a file system with the name "all",
28#                        specify "/dev/all" to distinguish from the
29#                        keyword "all" (import all file systems).
30#
31#   -i ImportfsFile   is the name of a file with the file system
32#                     information.  It must be created by mmexportfs.
33#
34#   -S ChangeSpecFile  a file containing a detailed description of changes
35#                 to be made to the file systems during the import step.
36#
37# Undocumented option:
38#
39#   -R            remove the specified file system from the mmsdrfs file
40#                 and replace it with the data from the import file.
41#                 If 'all' is specified, all file system and free disk
42#                 information that may currently exist is removed from
43#                 the mmsdrfs file and is replaced with the data from
44#                 the import file.
45#
46##############################################################################
47
48# Include global declarations and service routines.
49. /usr/lpp/mmfs/bin/mmglobfuncs
50. /usr/lpp/mmfs/bin/mmsdrfsdef
51. /usr/lpp/mmfs/bin/mmfsfuncs
52
53sourceFile="mmimportfs.sh"
54[[ -n $DEBUG || -n $DEBUGmmimportfs ]] && set -x
55$mmTRACE_ENTER "$*"
56
57
58# Local work files.  Names should be of the form:
59#   fn=${tmpDir}fn.${mmcmd}.$$
60existingDisks=${tmpDir}existingDisks.${mmcmd}.$$
61recoveryFiles=${tmpDir}recoveryFiles.${mmcmd}.$$
62importedFreeDisks=${tmpDir}importedFreeDisks.${mmcmd}.$$
63resetFreeDisks=${tmpDir}resetFreeDisks.${mmcmd}.$$
64disksToUnfence=${tmpDir}disksToUnfence.${mmcmd}.$$
65aixNodes=${tmpDir}aixNodes.${mmcmd}.$$
66
67# The following declarations are the prefixes for the file names
68# that will contain information relevant to a specific file system.
69# The actual file names consist of the prefix followed by a device name.
70importFile=${tmpDir}importFile.${mmcmd}.$$
71resetNSDs=${tmpDir}resetNSDs.${mmcmd}.$$
72resetLVs=${tmpDir}resetLVs.${mmcmd}.$$
73
74LOCAL_FILES=" $existingDisks $recoveryFiles $importedFreeDisks $resetFreeDisks \
75              $aixNodes $disksToUnfence $importFile.* $resetNSDs.* $resetLVs.* "
76
77# Local variable declarations
78usageMsg=571
79iflag=""
80Cflag=""
81Sflag=""
82
83existingMountPoints=""
84maxDiskNumber=0
85
86# Local functions:
87
88
89##############################################################################
90#
91# Function:  Given the source and target cluster types, determine whether
92#            the present version of mmimportfs can import the file system.
93#
94#            Note:  Not all possible cluster type combinations are supported.
95#                   In some cases, simplifying assumptions are made.
96#
97# Input:     $1 - source cluster type
98#            $2 - target cluster type
99#
100# Output:    None
101#
102# Returns:   0 - the two cluster types are compatible.
103#            1 - the two cluster types are not compatible.
104#
105##############################################################################
106function checkClusterCompatibility  # <source> <target>
107{
108  sourceFile="mmimportfs.sh"
109  [[ -n $DEBUG || -n $DEBUGcheckClusterCompatibility ]] && set -x
110  $mmTRACE_ENTER "$*"
111
112  typeset source=$1
113  typeset target=$2
114
115  typeset rc
116
117  case $source in
118    lc )
119      [[ $target = lc     ]] && rc=0
120      [[ $target = single ]] && rc=0
121      ;;
122
123    sp )
124      [[ $target = lc     ]] && rc=0
125      [[ $target = single ]] && rc=0
126      ;;
127
128    rpd )
129      [[ $target = lc     ]] && rc=0
130      [[ $target = single ]] && rc=0
131      ;;
132
133    hacmp )
134      [[ $target = lc     ]] && rc=0
135      [[ $target = single ]] && rc=0
136      ;;
137
138    single )
139      [[ $target = lc     ]] && rc=0
140      [[ $target = single ]] && rc=0
141      ;;
142
143     * )
144      # Unknown source cluster type.
145      rc=1
146      ;;
147  esac
148
149  return $rc
150
151}  #----- end of function checkClusterCompatibility ----------------
152
153
154###########################################################################
155#
156# Function:  See if there are any disks that will need to be recovered
157#            because of a previous failure of mmimportfs.
158#
159# Input:     $1 - source cluster type
160#            $2 - output file name
161#
162# Output:    File containing the disk names that may have failed a previous
163#            tspreparedisk -m call.  Each line has the following format:
164#              <diskName> <checksum> <timestamp> <server> <fullPathName>
165#
166# Returns:   0 - no errors
167#            1 - error encountered
168#
169###########################################################################
170function getDiskRecoveryInformation  # <source> <outputFile>
171{
172  sourceFile="mmimportfs.sh"
173  [[ -n $DEBUG || -n $DEBUGgetDiskRecoveryInformation ]] && set -x
174  $mmTRACE_ENTER "$*"
175
176  typeset source=$1
177  typeset outputFile=$2
178
179  typeset server
180
181  $rm -f $outputFile
182
183  # If we are not creating NSDs, there is nothing to worry about.
184  [[ $source = lc || $source = single ]] &&  \
185    return 0
186
187  # Create a list of all disk recovery files created by tspreparedisk.
188  # Such files, if any, will be stored in /var/mmfs/tmp/mmimportfs on
189  # the primary and backup server configuration nodes.  The file names
190  # have the following format:
191  #   tspreparedisk.diskDesc.<diskName>.<checksum>.<timestamp>
192  #
193  # Put the results in a file with the following format:
194  #   <diskName> <checksum> <timestamp> <server> <fullPathName>
195  #
196  for server in $(print -- $primaryServer $backupServer)
197  do
198    run onNode $server lsSGDescFile 2>/dev/null |  \
199      $awk -F. '
200        { print $3" "$4" "$5" '${server}' "$0 }
201      ' >> $outputFile
202  done
203
204  # Sort the result so that if there is more than one recovery file
205  # for any given disk, the most recent version appears first.
206  $sort -k 1,1 -k 3,3nr -o $outputFile $outputFile
207  checkForErrors "sort $outputFile" $?
208
209  return 0
210
211}  #----- end of function getDiskRecoveryInformation ---------------
212
213
214#########################################################################
215#
216# Function:  Restore the disk and SG descriptors of the specified disk.
217#
218# Input:     $1 - diskName
219#            $2 - file created by function getDiskRecoveryInformation
220#
221# Output:    None.
222#
223# Returns:   0 - no errors
224#            1 - error encountered
225#
226#########################################################################
227function recoverOldSGdescriptor  # <diskName> <recoveryInfoFile>
228{
229  sourceFile="mmimportfs.sh"
230  [[ -n $DEBUG || -n $DEBUGrecoverOldSGdescriptor ]] && set -x
231  $mmTRACE_ENTER "$*"
232
233  typeset diskName=$1
234  typeset recoveryInfoFile=$2
235
236  typeset recoveryInfo checksum serverNode fqName sumOutput newSum
237  typeset rc=0
238
239  # See if there is a recovery file for this disk.
240  recoveryInfo=$($grep -w $diskName $recoveryInfoFile)
241
242  # Return if there is nothing to do.
243  [[ -z $recoveryInfo ]] &&  \
244    return 0
245
246  print -u2 -- "$mmcmd: Recovering SG descriptor area of disk $diskName"
247
248  # Parse the information from the recoveryInfoFile.
249  set -f ; set -- $recoveryInfo ; set +f
250  checksum=$2
251  serverNode=$4
252  fqName=$5
253
254  # Retrieve the file if it isn't already on our node.
255  if [[ ! -e $fqName ]]
256  then
257    # Ensure the target directory for rcp exists.
258    $mkdir -p ${fqName%/*}
259
260    # Copy the file from the server node.
261    $rcp ${serverNode}:${fqName} $fqName
262    checkForErrors "rcp ${serverNode}:${fqName}" $?
263
264    # Verify the checksum.
265    sumOutput=$($sum $fqName)
266    rc=$?
267    set -f ; set -- $sumOutput ; set +f
268    newSum=$1
269    if [[ $checksum != $newSum ]]
270    then
271      printErrorMsg 379 $mmcmd $serverNode $ourNodeName
272      return 1
273    fi
274  fi  # end of if [[ ! -e $fqName ]]
275
276  # Restore the disk and SG descriptors of the disk.
277  $dd if=$fqName of=/dev/$diskName seek=1 2>$errMsg
278  rc=$?
279  if [[ $rc -ne 0 ]]
280  then
281    [[ -s $errMsg ]] && $cat $errMsg 1>&2
282    $rm -f $errMsg
283    print -u2 "$mmcmd: dd if=$fqName of=/dev/$diskName seek=1 failed with rc $rc."
284    print -u2 "$mmcmd: Error recovering disk $diskName from a previous failure."
285    return $rc
286  fi
287  $rm -f $errMsg
288
289  print -u2 -- "$mmcmd: Disk $diskName successfully recovered."
290
291  # At this point the disk was successfully restored.
292  # Remove all SG descriptor files for this disk and return.
293  $rm -f ${fqName%/*}/tspreparedisk.diskDesc.${diskName}.*
294  for server in $(print -- $primaryServer $backupServer)
295  do
296    run onNode $server rmSGDescFile $diskName
297  done
298
299  return 0
300
301}  #----- end of function recoverOldSGdescriptor -------------------
302
303
304############################################################################
305#
306# Function:  Import a disk into cluster type single.  Depending on the
307#            source cluster types, this may also involve the conversion
308#            of the disk into an NSD.
309#
310#            Note:  The disk is assumed to be accessible on the local node.
311#
312# Input:     $1 - source cluster type
313#            $2 - current SG_DISKS line for the disk
314#            $3 - target nodesetId
315#
316# Output:    $1 - result: error, success.
317#            $2 - updated SG_DISKS line.
318#
319# Returns:   0 - everything worked OK
320#            1 - error encountered
321#
322############################################################################
323function importDisk_single  # <source> <diskLine> <targetNodeset>
324{
325  sourceFile="mmimportfs.sh"
326  [[ -n $DEBUG || -n $DEBUGimportDisk_single ]] && set -x
327  $mmTRACE_ENTER "$*"
328
329  typeset sourceCluster=$1
330  typeset currentDiskLine=$2
331  typeset targetNodesetId=$3
332
333  typeset rc=0
334  typeset result="success"
335  typeset invokingCommand="mmimportfs"
336  typeset updatedDiskLine createNsdOutput tspreparediskOutput
337  typeset diskName magicWord rc2 pvid nsdSubtype nsdSubtypeDiskname
338
339  # Parse the current SG_DISKS line for the disk.
340  IFS=":"
341  set -f ; set -A v -- - $currentDiskLine ; set +f
342  IFS="$IFS_sv"
343  diskName=${v[$DISK_NAME_Field]}
344  [[ -z ${v[$NSD_SUBTYPE_Field]} ]] &&  \
345    v[$NSD_SUBTYPE_Field]="generic"
346  nsdSubtype=${v[$NSD_SUBTYPE_Field]}
347  aixPvidValue=${v[$PVID_Field]}
348  [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] &&  \
349    invokingCommand="mmimportfs_freeDisk"
350  [[ ${v[$NODESETID_Field]} != $FREE_DISK ]] &&  \
351    v[$NODESETID_Field]=$targetNodesetId
352
353  if [[ $sourceCluster != lc && $sourceCluster != single ]]
354  then
355    # The source cluster type is sp, rpd, or hacmp.
356    # In all of these cases we may have to import
357    # the underlying logical volumes and, if applicable,
358    # recreate the VSDs.
359
360    # For now, we assume that the disks are already in place.
361
362    # See if this disk needs to be recovered from a previous
363    # partial SG descriptor migration.
364    if [[ -s $recoveryFiles ]]
365    then
366      recoverOldSGdescriptor $diskName $recoveryFiles
367      rc=$?
368      if [[ $rc -ne 0 ]]
369      then
370        print -- "error"
371        return $rc
372      fi
373    fi
374
375    # Convert the disk into an NSD.
376    createNsdOutput=$(createNsd $diskName no $invokingCommand NULL)
377    rc=$?
378
379    # The output of createNsd consists of a one-word NSD subtype value,
380    # followed by the output from tspreparedisk.  Separate the two parts.
381    nsdSubtype=${createNsdOutput%% *}
382    tspreparediskOutput=${createNsdOutput#* }
383
384    # Set the value for the nsd subtype diskname if the nsd subtype
385    # is lv or vsd.
386    nsdSubtypeDiskname=""
387    [[ $nsdSubtype = lv || $nsdSubtype = vsd ]] && nsdSubtypeDiskname=$diskName
388
389    # Parse the output from the tspreparedisk command.
390    IFS=":"
391    set -f ; set -- $tspreparediskOutput ; set +f
392    magicWord=$1
393    rc2=$2
394    pvid=$3
395    IFS="$IFS_sv"
396
397    if [[ $rc  -ne 0 || $nsdSubtype = error ||
398          $rc2 -ne 0 || $magicWord != tspreparedisk ]]
399    then
400      # Try to make sense of the error.
401      if [[ $nsdSubtype = error ]]
402      then
403        : # determineNsdSubtype failed.  Messages were already issued.
404
405      elif [[ $magicWord = tspreparedisk ]]
406      then
407        # tspreparedisk was executed but was not happy about something.
408        if [[ $rc2 = 1 ]]       # E_PERM
409        then
410          # Permission was denied for disk.
411          printErrorMsg 523 $mmcmd "/dev/$diskName"
412        elif [[ $rc2 = 2 ]]     # E_NOENT
413        then
414          # The disk was not found.
415          printErrorMsg 524 $mmcmd "/dev/$diskName"
416        elif [[ $rc2 = 5 ]]     # E_IO
417        then
418          # I/O error
419          printErrorMsg 525 $mmcmd "/dev/$diskName"
420        elif [[ $rc2 = $MM_DeviceNotFound ]]    # E_NODEV
421        then
422          # A return code of ENODEV was returned for the disk.
423          printErrorMsg 187 $mmcmd $ourNodeName "/dev/$diskName"
424        elif [[ $rc2 = 27 ]]    # E_FBIG
425        then
426          # The disk is too large.
427          printErrorMsg 508 $mmcmd "/dev/$diskName"
428        elif [[ $rc2 = 50 ]]    # E_NOCONNECT
429        then
430          # The disk is fenced out.
431          printErrorMsg 395 $mmcmd $ourNodeName "/dev/$diskName"
432        else
433          # Show the result from tspreparedisk.
434          print -u2 "$tspreparediskOutput"
435          # Unexpected error from tspreparedisk
436          printErrorMsg 171 "$mmcmd" "tspreparedisk $diskName" $rc2
437        fi  # end if [[ $rc2 = 1 ]]
438      else
439        # Something is really wrong.  Output error information if any.
440        [[ -n $createNsdOutput ]] && print -u2 "$createNsdOutput"
441      fi  # end if [[ $nsdSubtype = error ]]
442
443      # We failed to create an NSD from this disk.
444      printErrorMsg 47 $mmcmd $diskName
445      result="error"
446      rc=1
447
448    else
449      # At this point the disk was successfully defined as an NSD.
450      # Add the missing or updated information.
451      v[$PVID_Field]=$pvid
452      v[$NSD_SUBTYPE_Field]=$nsdSubtype
453      v[$NSD_SUBTYPE_DISKNAME_Field]=$nsdSubtypeDiskname
454      if [[ $nsdSubtype = lv ]]
455      then
456        v[$AIX_PVID_Field]=$aixPvidValue
457      else
458        v[$AIX_PVID_Field]=""
459      fi
460
461      # Remove any leftover files from tspreparedisk -m.
462      $rm -f ${fqName%/*}/tspreparedisk.diskDesc.${diskName}.*
463    fi  # end if [[ $rc  -ne 0 || $nsdSubtype = error ||  ...
464  fi  # end of if [[ $sourceCluster != lc && $sourceCluster != single ]]
465
466  # Ensure certain fields in the SG_DISKS line have
467  # appropriate values for cluster type single.
468  v[$NSD_PRIMARY_NODE_Field]=""
469  v[$NSD_BACKUP_NODE_Field]=""
470  v[$DAEMON_NSD_PRIMARY_Field]=""
471  v[$DAEMON_NSD_BACKUP_Field]=""
472  v[$DISK_TYPE_Field]="disk"
473  updatedDiskLine=$(print_newLine)
474
475  # Return to the caller the updated SG_DISKS line.
476  print -- "$result" "$updatedDiskLine"
477  return $rc
478
479}  #----- end of function importDisk_single ------------------------
480
481
482###########################################################################
483#
484# Function:  Import a disk into an lc cluster.  Depending on the source
485#            cluster types, this may involve one or more of the following
486#            operations to make the disk usable in the new cluster:
487#            import the base logical volume, make/redefine a VSD,
488#            make an NSD out of the disk, verify NSD servers belong
489#            to the right nodeset, etc.
490#
491# Input:     $1 - source cluster type
492#            $2 - current SG_DISKS line for the disk
493#            $3 - target nodesetId
494#            $4 - (optional) disk descriptor spec file
495#
496# Output:    $1 - result; error, success, successServersRemoved.
497#            $2 - updated SG_DISKS line.
498#
499# Returns:   0 - everything worked OK
500#            1 - error encountered
501#
502###########################################################################
503function importDisk_lc  # <source> <diskLine> <targetNodeset> [<specFile>]
504{
505  sourceFile="mmimportfs.sh"
506  [[ -n $DEBUG || -n $DEBUGimportDisk_lc ]] && set -x
507  $mmTRACE_ENTER "$*"
508
509  typeset sourceCluster=$1
510  typeset currentDiskLine=$2
511  typeset targetNodesetId=$3
512  typeset specFile=$4
513
514  typeset rc=0
515  typeset diskDesc=""
516  typeset result="success"
517  typeset invokingCommand="mmimportfs"
518  typeset diskName server backup nodesetId validateDescriptorOutput
519  typeset updatedDiskLine createNsdOutput tspreparediskOutput
520  typeset magicWord rc2 pvid nsdSubtype nsdSubtypeDiskname invokedNode
521
522  # Parse the current SG_DISKS line for the disk.
523  IFS=":"
524  set -f ; set -A v -- - $currentDiskLine ; set +f
525  IFS="$IFS_sv"
526  diskName=${v[$DISK_NAME_Field]}
527  nsdSubtype=${v[$NSD_SUBTYPE_Field]}
528  aixPvidValue=${v[$PVID_Field]}
529  [[ -z $nsdSubtype ]] && nsdSubtype="generic"
530  [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] &&  \
531    invokingCommand="mmimportfs_freeDisk"
532  [[ ${v[$NODESETID_Field]} != $FREE_DISK ]] &&  \
533    v[$NODESETID_Field]=$targetNodesetId
534  nodesetId=${v[$NODESETID_Field]}
535
536  # If a change file is specified (-S option),
537  # see if it contains a descriptor for this disk.
538  [[ -s $specFile ]] &&  \
539    diskDesc=$($grep -e "[$BLANKchar$TABchar]$diskName:"   \
540                     -e "^$diskName:" $specFile 2>/dev/null)
541
542  if [[ -n $diskDesc ]]
543  then
544    # If a disk descriptor was specified,
545    # parse it to get the server names.
546    IFS=':'
547    set -f ; set -- $diskDesc ; set +f
548    server=$2
549    backup=$3
550    IFS="$IFS_sv"  # Restore the default IFS setting.
551
552    # If a primary server was specified, make sure that it is valid
553    # and convert it if necessary to an admin adapter name, since it
554    # may be needed for the subsequent createNsd call.
555    # We don't bother to check the backup server here, since it will
556    # be checked later by the validateAndConvertNsdDescriptor routine.
557    if [[ -n $server ]]
558    then
559      server=$(checkAndConvertNodeValue $server $REL_HOSTNAME_Field)
560      [[ $? -ne 0 ]] && cleanupAndExit
561    fi
562#   if [[ -n $backup ]]
563#   then
564#     backup=$(checkAndConvertNodeValue $backup $REL_HOSTNAME_Field)
565#     [[ $? -ne 0 ]] && cleanupAndExit
566#   fi
567
568  else
569    # Otherwise, use the current NSD server names, if any.
570    if [[ $sourceCluster = lc ]]
571    then
572      server=${v[$NSD_PRIMARY_NODE_Field]}
573      backup=${v[$NSD_BACKUP_NODE_Field]}
574    else
575      server=""
576      backup=""
577    fi
578  fi  # end of if [[ -n $diskDesc ]]
579
580  if [[ $sourceCluster != lc && $sourceCluster != single ]]
581  then
582    # The source cluster type is sp, rpd, or hacmp.
583    # In all of these cases we may have to import
584    # the underlying logical volumes and, if applicable,
585    # recreate the VSDs.
586
587    :  # For now, we assume that the disks are already in place.
588
589  fi  # end of if [[ $sourceCluster != lc && $sourceCluster != single ]]
590
591  # If the user did not specify a new disk descriptor,
592  # generate one from the current SG_DISKS line.
593  [[ -z $diskDesc ]] &&  \
594    diskDesc="$diskName:$server:$backup:"
595
596  # If NSD server names were not specified by the user,
597  # or cannot be reasonably defaulted by us, the user
598  # will have to use mmchnsd to assign NSD servers.
599  [[ -z $server ]] &&  \
600    result=successServersRemoved
601
602  # Verify the correctness of the NSD server nodes.
603  validateDescriptorOutput=$(validateAndConvertNsdDescriptor "$diskDesc"  \
604                   $currentDiskLine $CHANGE_NSD $nodesetId NULL oldDiskUsage)
605  rc=$?
606  if [[ $rc -eq 0 ]]
607  then
608    # If there are no problems, parse the result to get the new SG_DISKS line.
609    set -f ; set -- $validateDescriptorOutput ; set +f
610    updatedDiskLine="$1"
611
612    # Parse the line that was returned by the validate function
613    # to pick up fields that may have been changed.
614    IFS=":"
615    set -f ; set -A v -- - $updatedDiskLine ; set +f
616    IFS="$IFS_sv"
617
618  else
619    # Remove the NSD servers.  The user will have to run mmchnsd.
620    v[$NSD_PRIMARY_NODE_Field]=""
621    v[$NSD_BACKUP_NODE_Field]=""
622    v[$DAEMON_NSD_PRIMARY_Field]=""
623    v[$DAEMON_NSD_BACKUP_Field]=""
624    result=successServersRemoved
625    rc=0
626  fi
627
628  # Convert the disk into an NSD.
629  if [[ $sourceCluster != lc && $sourceCluster != single ]]
630  then
631    # See if this disk needs to be recovered from a previous
632    # partial SG descriptor migration.
633    if [[ -s $recoveryFiles ]]
634    then
635      recoverOldSGdescriptor $diskName $recoveryFiles
636      rc=$?
637      if [[ $rc -ne 0 ]]
638      then
639        print -- "error"
640        return $rc
641      fi
642    fi
643
644    # Generate and write an unique NSD volume id on sector 2 of the disk.
645    # If an NSD server is specified, invoke the function on that node.
646    # This rule does not apply when the underlying disk is a VSD.
647    # For VSDs we should have access to the disk from the local node.
648    if [[ $sourceCluster = sp || -z $server || $server = $ourNodeName ]]
649    then
650      invokedNode=$ourNodeName
651      createNsdOutput=$(createNsd $diskName no $invokingCommand NULL)
652      rc=$?
653    else
654      invokedNode=$server
655      createNsdOutput=$(run on1 $server  \
656                        createNsd $diskName no $invokingCommand NULL)
657      rc=$?
658    fi
659
660    # The output of createNsd consists of a one-word NSD subtype value,
661    # followed by the output from tspreparedisk.  Separate the two parts.
662    nsdSubtype=${createNsdOutput%% *}
663    tspreparediskOutput=${createNsdOutput#* }
664
665    # Set the value for the nsd subtype diskname if the nsd subtype
666    # is lv, vsd or file; this name is persistent across the nodes.
667    nsdSubtypeDiskname=""
668    [[ $nsdSubtype = lv || $nsdSubtype = vsd || $nsdSubtype = file ]] &&  \
669      nsdSubtypeDiskname=$diskName
670
671    # Parse the output from the tspreparedisk command.
672    IFS=":"
673    set -f ; set -- $tspreparediskOutput ; set +f
674    magicWord=$1
675    rc2=$2
676    pvid=$3
677    IFS="$IFS_sv"
678
679    if [[ $rc  -ne 0 || $nsdSubtype = error ||
680          $rc2 -ne 0 || $magicWord != tspreparedisk ]]
681    then
682      # Try to make sense of the error.
683      if [[ $nsdSubtype = error ]]
684      then
685        :  # determineNsdSubtype failed.  Messages were already issued.
686
687      elif [[ $magicWord = tspreparedisk ]]
688      then
689        # tspreparedisk was executed but was not happy about something.
690        if [[ $rc2 = 1 ]]       # E_PERM
691        then
692          # Permission was denied for disk.
693          printErrorMsg 523 $mmcmd "/dev/$diskName"
694        elif [[ $rc2 = 2 ]]     # E_NOENT
695        then
696          # The disk was not found.
697          printErrorMsg 524 $mmcmd "/dev/$diskName"
698        elif [[ $rc2 = 5 ]]     # E_IO
699        then
700          # I/O error
701          printErrorMsg 525 $mmcmd "/dev/$diskName"
702        elif [[ $rc2 = $MM_DeviceNotFound ]]    # E_NODEV
703        then
704          # A return code of ENODEV was returned for the disk.
705          printErrorMsg 187 $mmcmd $invokedNode "/dev/$diskName"
706        elif [[ $rc2 = 27 ]]    # E_FBIG
707        then
708          # The disk is too large.
709          printErrorMsg 508 $mmcmd "/dev/$diskName"
710        elif [[ $rc2 = 50 ]]    # E_NOCONNECT
711        then
712          # The disk is fenced out.
713          printErrorMsg 395 $mmcmd $invokedNode "/dev/$diskName"
714        else
715          # Show the result from tspreparedisk.
716          print -u2 "$tspreparediskOutput"
717          # Unexpected error from tspreparedisk.
718          printErrorMsg 171 "$mmcmd" "tspreparedisk $diskName" $rc2
719        fi  # end if [[ $rc2 = 1 ]]
720      else
721        # Something is really wrong.  Output error information if any.
722        [[ -n $createNsdOutput ]] && print -u2 "$createNsdOutput"
723      fi  # end if [[ $nsdSubtype = error ]]
724
725      # We failed to create an NSD from this disk.
726      printErrorMsg 47 $mmcmd $diskName
727      result="error"
728      rc=1
729
730    else
731      # At this point the disk was successfully defined as an NSD.
732      # Add missing or updated information.
733      v[$PVID_Field]=$pvid
734      v[$NSD_SUBTYPE_DISKNAME_Field]=$nsdSubtypeDiskname
735      if [[ $nsdSubtype = lv ]]
736      then
737        v[$AIX_PVID_Field]=$aixPvidValue
738      else
739        v[$AIX_PVID_Field]=""
740      fi
741
742      # Remove any leftover files from tspreparedisk -m.
743      $rm -f ${fqName%/*}/tspreparedisk.diskDesc.${diskName}.*
744      for server in $(print -- $primaryServer $backupServer)
745      do
746        run onNode $server rmSGDescFile $diskName
747      done
748    fi  # end if [[ $rc  -ne 0 || $nsdSubtype = error || ... ]]
749
750  fi  # end of if [[ $sourceCluster != lc && $sourceCluster != single ]]
751
752  # Add the remaining missing or updated information and rebuild the line.
753  v[$DISK_TYPE_Field]=nsd
754  v[$NSD_SUBTYPE_Field]=$nsdSubtype
755  updatedDiskLine=$(print_newLine)
756
757  # Return to the caller the updated SG_DISKS line.
758  print -- "$result" "$updatedDiskLine"
759  return $rc
760
761}  #----- end of function importDisk_lc ----------------------------
762
763
764###########################################################################
765#
766# Function:  Unfence logical volumes and remove PR registrations.
767#
768# Input:     $1 - file with the nodes on which to unfence
769#            $2 - SG_DISKS lines for the disks to unfence
770#
771# Output:    None
772#
773# Returns:   0 - everything worked OK
774#            1 - error encountered
775#
776###########################################################################
777function unfenceLogicalVolumes  # <nodeFile> <diskFile>
778{
779  sourceFile="mmimportfs.sh"
780  [[ -n $DEBUG || -n $DEBUGunfenceLogicalVolumes ]] && set -x
781  $mmTRACE_ENTER "$*"
782
783  typeset nodefile=$1
784  typeset diskLines=$2
785
786  typeset rc=0
787  typeset unfenceDisksOutput outputLine nodeName magicWord rc2
788  typeset failedNode errorFound
789
790  # Give up if any of the input files is empty.
791  [[ ! -s $nodefile || ! -s $diskLines ]] &&  \
792    return 0
793
794  $rm -f $tmpfile
795
796  # Exclude the local host from the list of nodes.
797  $grep -v -w $ourNodeName $nodefile > ${nodefile}tmp
798
799  # If there are remote nodes left in the file,
800  # unfence the disks on those nodes.
801  if [[ -s ${nodefile}tmp ]]
802  then
803    print -- "$mmcmd:  Attempting to unfence the disks.  This may take a while ... "
804
805    # Create a copy of the file to propagate.
806    $cp $diskLines ${diskLines}tmp
807    checkForErrors "cp $diskLines ${diskLines}tmp" $?
808
809    # Perform the tasks on all remote nodes.
810    $mmdsh -f 10 -vF ${nodefile}tmp -I ${diskLines}tmp  \
811       $mmremote unfenceDisks ${diskLines}tmp >$tmpfile 2>&1
812    rc=$?
813  fi
814
815  # Unfence the disks on the local node.
816  # Append the result to the output from the remote nodes.
817  if [[ $osName = AIX ]]
818  then
819    unfenceDisksOutput=$(unfenceDisks $diskLines)
820    rc=$?
821
822    # Append the output to the output from the remote nodes
823    # so that we can process the overall result.
824    print -- "$ourNodeName: $unfenceDisksOutput" >>$tmpfile
825  fi
826
827  # Ignore the results and declare a success.  If we were not
828  # successful on some node, the mount will fail and the user
829  # will have to run mmremote unfenceDisks or fix the disks
830  # by himself.  Our problem is that we do not have a good
831  # way to tell whether the unfence process should work on
832  # any given node or not.  And we most definitely do not
833  # want to fail the mmimportfs command for such a reason.
834  $rm -f ${nodefile}tmp ${diskLines}tmp
835  return 0
836
837}  #----- end of function unfenceLogicalVolumes --------------------
838
839
840
841#######################
842# Mainline processing
843#######################
844
845#################################
846# Process the command arguments.
847#################################
848[[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] &&  \
849  syntaxError "help" $usageMsg
850
851[[ $argc -lt 3 ]] &&  \
852  syntaxError "missingArgs" $usageMsg
853
854device=$arg1   # Save the stripe group device (always the first parameter).
855shift 1        # Drop the device name from the parameter list.
856
857while getopts :C:i:RS: OPT
858do
859  case $OPT in
860    C) syntaxError "obsoleteOption" $usageMsg "-$OPT"
861       ;;
862
863    i) # name of input file
864       [[ -n $iflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
865       fsImportData=$OPTARG
866       ;;
867
868    R) # replace existing file systems.
869       [[ -n $Rflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
870       Rflag=yes
871       ;;
872
873    S) # file with change specifications.
874       [[ -n $Sflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
875       Sflag=yes
876       changeSpecFile=$OPTARG
877       ;;
878
879    :) syntaxError "missingValue" $usageMsg $OPTARG
880       ;;
881
882    +[CiRS]) syntaxError "invalidOption" $usageMsg $OPT
883       ;;
884
885    *) # invalid option specified
886       syntaxError "invalidOption" $usageMsg $OPTARG
887       ;;
888  esac
889done
890
891shift OPTIND-1
892[[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1
893
894# Check the input file parameters.
895if [[ ! -f $fsImportData || ! -r $fsImportData ]]
896then
897  # Can't read the input file.
898  printErrorMsg 43 $mmcmd $fsImportData
899  cleanupAndExit
900fi
901if [[ ! -s $fsImportData ]]
902then
903  # Input file is empty.
904  printErrorMsg 329 $mmcmd $fsImportData
905  cleanupAndExit
906fi
907
908if [[ -n $Sflag && ( ! -f $changeSpecFile || ! -r $changeSpecFile ) ]]
909then
910  # Can't read the input file.
911  printErrorMsg 43 $mmcmd $changeSpecFile
912  cleanupAndExit
913fi
914if [[ -n $Sflag && ! -s $changeSpecFile ]]
915then
916  # Input file is empty.
917  printErrorMsg 329 $mmcmd $changeSpecFile
918  cleanupAndExit
919fi
920
921# Process the input device name parameter.
922[[ $device = all ]] && importAll=true
923deviceName=${device#/dev+(/)}   # Strip /dev from the device name.
924
925
926#####################################################################
927# Set up trap exception handling and call the gpfsInit function.
928# It will ensure that the local copy of the mmsdrfs and the rest of
929# the GPFS system files are up-to-date and will obtain the sdr lock.
930#####################################################################
931trap pretrap HUP INT QUIT KILL
932gpfsInitOutput=$(gpfsInit $lockId)
933setGlobalVar $? $gpfsInitOutput
934
935targetNodesetId=$nsId
936
937# Determine the lookup order for resolving host names.
938[[ $osName != AIX ]] && resolveOrder=$(setHostResolveOrder)
939
940
941######################################################################
942# Create a new version of the mmsdrfs file that will receive the data
943# and collect information for the existing file systems, disks, etc.
944# If the -R option is specified, remove the affected lines from the
945# mmsdrfs file.
946######################################################################
947$rm -f $newsdrfs $existingDisks $allClusterNodes $aixNodes
948IFS=":"
949exec 3<&-
950exec 3< $mmsdrfsFile
951while read -u3 sdrfsLine
952do
953  # Parse the line.
954  set -f ; set -A v -- - $sdrfsLine ; set +f
955  IFS="$IFS_sv"
956  printLine=true
957
958  # Change some of the fields depending on the type of line.
959  case ${v[$LINE_TYPE_Field]} in
960
961    $VERSION_LINE )  # This is the global header line.
962       # Increment the generation number.
963       newGenNumber=${v[$SDRFS_GENNUM_Field]}+1
964       v[$SDRFS_GENNUM_Field]=$newGenNumber
965
966       targetCluster=${v[$CLUSTER_TYPE_Field]}
967       if [[ $MMMODE = lc ]]
968       then
969         [[ ${v[$HIGHEST_GPFS_DISK_NBR_Field]} -lt $initialDiskNumber ]] &&  \
970           v[$HIGHEST_GPFS_DISK_NBR_Field]=$initialDiskNumber
971         prevMaxDiskNumber=${v[$HIGHEST_GPFS_DISK_NBR_Field]}
972       fi
973       ;;
974
975    $MEMBER_NODE )  # This line describes a node that belongs to some nodeset.
976       # Create a file with the names of all nodes in the cluster.
977       print -- "${v[$REL_HOSTNAME_Field]}" >> $allClusterNodes
978       checkForErrors "writing to file $allClusterNodes" $?
979
980       # Create separate files with the names of the AIX nodes.
981       if [[ ${v[$OS_NAME_Field]} = "AIX" ]]
982       then
983         print -- "${v[$REL_HOSTNAME_Field]}" >> $aixNodes
984         checkForErrors "writing to file $aixNodes" $?
985       fi
986       ;;
987
988    $SG_HEADR )  # This is the header line for some file system.
989       # We are starting the processing of a new file system.  If the file
990       # system should be replaced, remove the line from the mmsdrfs file.
991       if [[ (${v[$DEV_NAME_Field]} = $deviceName || $device = all) &&
992              -n $Rflag && ${v[$FS_TYPE_Field]} = $localfs ]]
993       then
994         # This file system should be replaced.
995         replaceThisFileSystem=true
996         printLine=false
997
998       else
999         replaceThisFileSystem=""
1000
1001         # Create a list of the already assigned minor numbers.
1002         existingMinorNumbers="$existingMinorNumbers ${v[$DEV_MINOR_Field]}"
1003
1004         # If this file systems belongs to the nodeset on which we
1005         # are running, remember its name.  It will be needed shortly
1006         # to figure out the value of the GPFS device major number.
1007         [[ ${v[$NODESETID_Field]} = $nsId ]] &&  \
1008           fqDeviceName="/dev/${v[$DEV_NAME_Field]}"
1009       fi  # end if [[ (${v[$DEV_NAME_Field]} = $deviceName || $device = all) ...
1010       ;;
1011
1012    $SG_ETCFS )  # This line is a stanza line for one of the filesystems.
1013       if [[ -n $replaceThisFileSystem ]]
1014       then
1015         printLine=false
1016       else
1017         # If this is the first line in the stanza,
1018         # save the device name and mount point.
1019         if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line ]]
1020         then
1021           fsInfo="${v[$DEV_NAME_Field]}:${v[$ETCFS_TEXT_Field]}:${v[$NODESETID_Field]}"
1022           existingFsInfo="$fsInfo $existingFsInfo"
1023
1024           # Note:  the trailing blanks in the following lists are important.
1025           existingFileSystems="$existingFileSystems ${v[$DEV_NAME_Field]} "
1026           existingMountPoints="$existingMountPoints ${v[$ETCFS_TEXT_Field]} "
1027         fi
1028       fi  # end if [[ -n $replaceThisFileSystem ]]
1029       ;;
1030
1031    $SG_MOUNT )
1032       [[ -n $replaceThisFileSystem ]] &&  \
1033         printLine=false
1034       ;;
1035
1036    $SG_DISKS )  # This line describes a disk.
1037       # Decide if this disk is to be replaced.  If the disk belongs to some
1038       # file system, the replaceThisFileSystem flag already has the correct
1039       # value.  If this is a free disk, it will be replaced only if all file
1040       # systems are being replaced.  Note that the replaceThisFileSystem flag
1041       # is used to control the replacing of disks that are part of some file
1042       # system as well as the replacing of free disks.
1043       if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]]
1044       then
1045         if [[ $device != all ]]
1046         then
1047           replaceThisFileSystem=""
1048         else
1049           replaceThisFileSystem=true
1050         fi
1051       fi  # end if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]]
1052
1053       if [[ -n $replaceThisFileSystem ]]
1054       then
1055         printLine=false
1056       else
1057         # Create a file with the names of all existing disks.
1058         # It doesn't matter if the disks are free or not.
1059         print -- "${v[$DISK_NAME_Field]}" >> $existingDisks
1060         checkForErrors "writing to file $existingDisks" $?
1061
1062         # Keep track of the highest NSD number assigned to a disk.
1063         if [[ ${v[$DISK_NAME_Field]} = gpfs+([0-9])nsd ]]
1064         then
1065           nsdName=${v[$DISK_NAME_Field]}
1066           nsdNumber=${nsdName#gpfs}
1067           nsdNumber=${nsdNumber%nsd}
1068           [[ $nsdNumber -gt $maxDiskNumber ]] && maxDiskNumber=$nsdNumber
1069         fi
1070       fi  # end if [[ -n $replaceThisFileSystem ]]
1071       ;;
1072
1073    * )  # Pass all other lines without a change.
1074       ;;
1075
1076  esac  # end Change some of the fields
1077
1078  # Build and write the line to the new mmsdrfs file.
1079  if [[ $printLine = true ]]
1080  then
1081    print_newLine >> $newsdrfs
1082    checkForErrors "writing to file $newsdrfs" $?
1083  fi
1084
1085  IFS=":"  # Change the separator back to ":" for the next iteration.
1086
1087done  # end while read -u3 sdrfsLine
1088
1089IFS="$IFS_sv"  # Restore the default IFS settings.
1090
1091
1092###########################################################################
1093# Figure out what should the GPFS file systems device major number be.
1094###########################################################################
1095if [[ $osName = Linux && -n $fqDeviceName ]]
1096then
1097  devMajor=$(LC_ALL=C $ls -l $fqDeviceName 2>/dev/null | $awk ' { print $5 } ')
1098  devMajor=${devMajor%,*}
1099fi
1100[[ -z $devMajor ]] && devMajor=$defaultMajorNumber
1101
1102
1103###########################################################################
1104# If the source is hacmp or LV based rpd cluster, make an attempt
1105# to remove any PR settings and unfence the disks on all nodes in
1106# the new cluster.  This processing is by necessity time consuming.
1107#
1108# Notes:  The main loop is further down.  This is preliminary processing
1109#         and a necessary evil.  Some of the error checking is duplicated
1110#         here to allow us to get out faster if there is an obvious error.
1111###########################################################################
1112$rm -f $disksToUnfence $resetLVs.*
1113IFS=":"
1114exec 3<&-
1115exec 3< $fsImportData
1116while read -u3 sdrfsLine
1117do
1118  # Parse the line.
1119  set -f ; set -A v -- - $sdrfsLine ; set +f
1120
1121  IFS="$IFS_sv"    # Restore the default IFS settings.
1122  printLine=true   # Assume the line will be printed.
1123
1124  case ${v[$LINE_TYPE_Field]} in
1125
1126    $VERSION_LINE )  # This is the global header line.
1127       sourceCluster=${v[$CLUSTER_TYPE_Field]}
1128       [[ -z $sourceCluster ]] && sourceCluster=sp
1129       checkClusterCompatibility $sourceCluster $targetCluster
1130       rc=$?
1131       if [[ $rc -ne 0 ]]
1132       then
1133         # Incompatible cluster types.
1134         printErrorMsg 44 $mmcmd $sourceCluster $targetCluster
1135         cleanupAndExit
1136       fi
1137       getDiskRecoveryInformation $sourceCluster $recoveryFiles
1138
1139       # Skip the preliminary processing if LVs are not possible.
1140       [[ $sourceCluster != rpd && $sourceCluster != hacmp ]] &&  \
1141         break
1142
1143       # Skip the preliminary processing if -R is specified.
1144       [[ -n $Rflag ]] &&  \
1145         break
1146       ;;
1147
1148    $SG_HEADR )  # This is the header line for some file system.
1149       # Starting the processing of a new file system.
1150       # See if the file system should be imported.
1151       if [[ ${v[$DEV_NAME_Field]} = $deviceName || -n $importAll ]]
1152       then
1153         importThisFileSystem=true
1154       else
1155         importThisFileSystem=""
1156       fi
1157
1158       # Verify that the target cluster does not already
1159       # have a file system with the same name.
1160       if [[ -n $importThisFileSystem &&
1161             $existingFileSystems = *" ${v[$DEV_NAME_Field]} "* ]]
1162       then
1163         importThisFileSystem=""
1164       fi
1165       ;;
1166
1167    $SG_ETCFS )  # This line is a stanza line for one of the file systems.
1168       # If this is the first line in the stanza for a file system
1169       # being imported, verify that the mount point does not already
1170       # exist in the target cluster.
1171       if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line &&
1172             -n $importThisFileSystem &&
1173             $existingMountPoints = *" ${v[$ETCFS_TEXT_Field]} "* ]]
1174       then
1175         importThisFileSystem=""
1176       fi
1177       ;;
1178
1179    $SG_DISKS )  # This line describes a disk.
1180       # Create the device suffix to be used for temp files.
1181       if [[ ${v[$DEV_NAME_Field]} = $NO_DEVICE ]]
1182       then
1183         # Avoid any name collision by using ":", a prohibited character.
1184         suffix=_FREEDISK:_
1185       else
1186         suffix=${v[$DEV_NAME_Field]}
1187       fi
1188
1189       # Decide if this disk is to be imported.  If the disk belongs to some
1190       # file system, the importThisFileSystem flag already has the correct
1191       # value.  If this is a free disk, it will be imported only if all file
1192       # systems are being imported.  Note that the importThisFileSystem flag
1193       # is used to control the importing of disks that are part of some file
1194       # system as well as the importing of free disks.
1195       if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]]
1196       then
1197         if [[ -z $importAll ]]
1198         then
1199           importThisFileSystem=""
1200         else
1201           importThisFileSystem=true
1202         fi
1203       fi
1204
1205       # If this disk belongs to a file system being imported, verify that
1206       # there are no name conflicts.  If there is a name conflict with a
1207       # disk that is part of a file system, that file system is dropped.
1208       # If the conflict is with a free disk, only that disk is dropped.
1209       if [[ -n $importThisFileSystem ]]
1210       then
1211         # Check the name.
1212         conflictingDisk=$($grep -w ${v[$DISK_NAME_Field]} $existingDisks 2>/dev/null)
1213         if [[ -n $conflictingDisk ]]
1214         then
1215           # There is already a disk with the same name.
1216           if [[ ${v[$DEV_NAME_Field]} != $NO_DEVICE ]]
1217           then
1218             $rm -f $resetLVs.$suffix
1219           fi
1220           importThisFileSystem=""
1221         fi  # end if [[ -n $conflictingDisk ]]
1222       fi  # end of if [[ -n $importThisFileSystem ]]
1223
1224       # If this is a PR-capable logical volume,
1225       # add the line to the disks to be unfenced.
1226       if [[ -n $importThisFileSystem      &&
1227             ${v[$DISK_TYPE_Field]} = "lv" &&
1228             ${v[$DISK_SUBTYPE_Field]} != "other" ]]
1229       then
1230         print -- ${sdrfsLine} >> $resetLVs.$suffix
1231         checkForErrors "writing to file $resetLVs.$suffix" $?
1232       fi
1233       ;;
1234
1235    * )  # Pass all other lines without a change.
1236       ;;
1237
1238  esac  # end of case ${v[$LINE_TYPE_Field]} in
1239
1240  IFS=":"  # Change the separator back to ":" for the next iteration.
1241
1242done  # end while read -u3 sdrfsLine
1243
1244IFS="$IFS_sv"  # Restore the default IFS settings.
1245
1246# Combine all resetLVs files.
1247for fs in $($ls $resetLVs.* 2>/dev/null)
1248do
1249  $cat $fs >> $disksToUnfence
1250  checkForErrors "writing to file $disksToUnfence" $?
1251done
1252
1253# If there are disks to unfence, do it now.
1254if [[ -s $disksToUnfence ]]
1255then
1256  unfenceLogicalVolumes $aixNodes $disksToUnfence
1257  rc=$?
1258fi
1259
1260
1261###########################################################################
1262# Go through the input file with the exportfs information and extract
1263# in separate files the information for each individual file system
1264# that is to be imported.  Verify that there are no name conflicts and
1265# adjust the target nodeset id if necessary.
1266###########################################################################
1267$rm -f $importFile.* $resetNSDs.* $importedFreeDisks $resetFreeDisks
1268IFS=":"
1269exec 3<&-
1270exec 3< $fsImportData
1271while read -u3 sdrfsLine
1272do
1273  # Parse the line.
1274  set -f ; set -A v -- - $sdrfsLine ; set +f
1275
1276  IFS="$IFS_sv"    # Restore the default IFS settings.
1277  printLine=true   # Assume the line will be printed.
1278
1279  case ${v[$LINE_TYPE_Field]} in
1280
1281 # The version line has been processed in the preliminary pass.
1282 #  $VERSION_LINE )  # This is the global header line.
1283 #     sourceCluster=${v[$CLUSTER_TYPE_Field]}
1284 #     checkClusterCompatibility $sourceCluster $targetCluster
1285 #     rc=$?
1286 #     if [[ $rc -ne 0 ]]
1287 #     then
1288 #       # Incompatible cluster types.
1289 #       printErrorMsg 44 $mmcmd $sourceCluster $targetCluster
1290 #       cleanupAndExit
1291 #     fi
1292 #     getDiskRecoveryInformation $sourceCluster $recoveryFiles
1293 #     ;;
1294
1295    $SG_HEADR )  # This is the header line for some file system.
1296       # Starting the processing of a new file system.
1297       # See if the file system should be imported.
1298       if [[ ${v[$DEV_NAME_Field]} = $deviceName || -n $importAll ]]
1299       then
1300         # This file system should be imported.
1301         importThisFileSystem=true
1302         if [[ -n $importAll ]]
1303         then
1304           someFsFound=true
1305         else
1306           specifiedFsFound=true
1307         fi
1308         # Put an informational message:  processing file system ...
1309         print -- ""  # Output a blank separator line.
1310         printInfoMsg 250 $mmcmd ${v[$DEV_NAME_Field]}
1311       else
1312         # This file system should not be imported.
1313         importThisFileSystem=""
1314       fi # end of if [[ ${v[$DEV_NAME_Field]} = $deviceName || -n $importAll ]]
1315
1316       # Verify that the target cluster does not already
1317       # have a file system with the same name.
1318       if [[ -n $importThisFileSystem &&
1319             $existingFileSystems = *" ${v[$DEV_NAME_Field]} "* ]]
1320       then
1321         # There is already a file system with the same name.
1322         printErrorMsg 48 $mmcmd ${v[$DEV_NAME_Field]}
1323         failedFileSystems="${failedFileSystems}\n\t${v[$DEV_NAME_Field]}"
1324         importThisFileSystem=""
1325       fi
1326
1327       # If the file system will be imported and there are no problems so far,
1328       # start building temporary files with the file system information.
1329       if [[ -n $importThisFileSystem ]]
1330       then
1331         # First, figure out what the device minor number should be.
1332         # Keep trying until we get an unused minor number.  If this
1333         # does not work, we'll leave the device minor field null
1334         # hoping that mmfsmknod will take care of things later on.
1335         rc=0
1336         newDevMinor=""
1337         while [[ -z $newDevMinor && rc -eq 0 ]]
1338         do
1339           # Assign a minor number to the file system.
1340           devMinor=$(assignDevMinor "$existingMinorNumbers")
1341           rc=$?
1342           if [[ $rc -eq 0 ]]
1343           then
1344             # See if the new device number is not being used by somebody on
1345             # the local node.  This is a crude check but better than nothing.
1346             # Going and checking all nodes in the nodeset is too expensive.
1347             inuse=$($ls -lL /dev 2>/dev/null |  \
1348                   $grep "^${fsDeviceType}.* $devMajor, *$devMinor ")
1349
1350             # The number seems to be free, use it.
1351             [[ -z $inuse ]] && newDevMinor=$devMinor
1352
1353             # Add the number to the list of existing number.
1354             existingMinorNumbers="$existingMinorNumbers $devMinor"
1355
1356           fi  # end of if [[ $rc -eq 0 ]]
1357         done # end of while [[ -z $newDevMinor && rc -eq 0 ]]
1358
1359         # Change some of the fields as needed and put the line out.
1360         v[$NODESETID_Field]=$targetNodesetId
1361         v[$DEV_MINOR_Field]=$devMinor
1362         print_newLine >> $importFile.${v[$DEV_NAME_Field]}
1363         checkForErrors "writing to file $importFile.${v[$DEV_NAME_Field]}" $?
1364       fi
1365       ;;
1366
1367    $SG_ETCFS )  # This line is a stanza line for one of the file systems.
1368       # If this is the first line in the stanza for a file system
1369       # being imported, verify that the mount point does not already
1370       # exist in the target cluster.
1371       if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line &&
1372             -n $importThisFileSystem &&
1373             $existingMountPoints = *" ${v[$ETCFS_TEXT_Field]} "* ]]
1374       then
1375         # There is already a file system with the same mount point.
1376         # Tell the guy to use mmchfs -T to change the existing mount point.
1377         printErrorMsg 49 $mmcmd ${v[$DEV_NAME_Field]} ${v[$ETCFS_TEXT_Field]}
1378         failedFileSystems="${failedFileSystems}\n\t${v[$DEV_NAME_Field]}"
1379         $rm -f $importFile.${v[$DEV_NAME_Field]} $resetNSDs.${v[$DEV_NAME_Field]}
1380         importThisFileSystem=""
1381       fi
1382
1383       # If the file system will be imported and there are no problems so far,
1384       # add the lines to the temporary files with the file system information.
1385       if [[ -n $importThisFileSystem ]]
1386       then
1387         v[$NODESETID_Field]=$targetNodesetId
1388         print_newLine >> $importFile.${v[$DEV_NAME_Field]}
1389         checkForErrors "writing to file $importFile.${v[$DEV_NAME_Field]}" $?
1390       fi
1391       ;;
1392
1393    $SG_MOUNT )  # This line has the mount options.
1394       # If the file system will be imported and there are no problems so far,
1395       # add the line to the temporary file with the file system information.
1396       if [[ -n $importThisFileSystem ]]
1397       then
1398         v[$NODESETID_Field]=$targetNodesetId
1399         print_newLine >> $importFile.${v[$DEV_NAME_Field]}
1400         checkForErrors "writing to file $importFile.${v[$DEV_NAME_Field]}" $?
1401       fi
1402       ;;
1403
1404    $SG_DISKS )  # This line describes a disk.
1405       # Decide if this disk is to be imported.  If the disk belongs to some
1406       # file system, the importThisFileSystem flag already has the correct
1407       # value.  If this is a free disk, it will be imported only if all file
1408       # systems are being imported.  Note that the importThisFileSystem flag
1409       # is used to control the importing of disks that are part of some file
1410       # system as well as the importing of free disks.
1411       if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]]
1412       then
1413         if [[ -z $importAll ]]
1414         then
1415           importThisFileSystem=""
1416         else
1417           importThisFileSystem=true
1418           # If not done already, put an informational message.
1419           if [[ -z $freeDiskStartMsg ]]
1420           then
1421             # Put an informational message:  processing free disks ...
1422             print -- ""  # Output a blank separator line.
1423             printInfoMsg 98 $mmcmd
1424             freeDiskStartMsg=issued
1425           fi
1426         fi  # end if [[ -z $importAll ]]
1427       fi  # end if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]]
1428
1429       # If this disk belongs to a file system being imported, verify that
1430       # there are no name conflicts.  If there is a name conflict with a
1431       # disk that is part of a file system, that file system is dropped.
1432       # If the conflict is with a free disk, only that disk is dropped.
1433       if [[ -n $importThisFileSystem ]]
1434       then
1435         # Put an informational message:  processing disk ...
1436         printInfoMsg 251 $mmcmd ${v[$DISK_NAME_Field]}
1437         # Check the name.
1438         conflictingDisk=$($grep -w ${v[$DISK_NAME_Field]} $existingDisks 2>/dev/null)
1439         if [[ -n $conflictingDisk ]]
1440         then
1441           # There is already a disk with the same name.
1442           printErrorMsg 51 $mmcmd ${v[$DISK_NAME_Field]}
1443           if [[ ${v[$DEV_NAME_Field]} != $NO_DEVICE ]]
1444           then
1445             failedFileSystems="${failedFileSystems}\n\t${v[$DEV_NAME_Field]}"
1446             $rm -f $importFile.${v[$DEV_NAME_Field]} $resetNSDs.${v[$DEV_NAME_Field]}
1447           fi
1448           importThisFileSystem=""
1449         fi  # end if [[ -n $conflictingDisk ]]
1450       fi  # end of if [[ -n $importThisFileSystem ]]
1451
1452       # If the file system will be imported and there are no problems so far,
1453       # add the lines to the temporary files with the file system information.
1454       if [[ -n $importThisFileSystem ]]
1455       then
1456         # Ensure the disk is of the correct type for the cluster.
1457         importDiskOutput=$(importDisk_$targetCluster  \
1458              $sourceCluster $sdrfsLine $targetNodesetId $changeSpecFile)
1459         rc=$?
1460
1461         # The output of importDisk consists of a one word overall result,
1462         # followed by the updated SG_DISKS line.  Separate the two parts.
1463         importDiskResult=${importDiskOutput%% *}
1464         newDiskLine="${importDiskOutput#* }"
1465         if [[ $importDiskResult = success* ]]
1466         then
1467           if [[ ${v[$DEV_NAME_Field]} = $NO_DEVICE ]]
1468           then
1469             print -- ${newDiskLine} >> $importedFreeDisks
1470             checkForErrors "writing to file $importedFreeDisks" $?
1471           else
1472             print -- ${newDiskLine} >> $importFile.${v[$DEV_NAME_Field]}
1473             checkForErrors "writing to file $importFile.${v[$DEV_NAME_Field]}" $?
1474           fi
1475
1476           if [[ $importDiskResult = successServersRemoved ]]
1477           then
1478             if [[ ${v[$DEV_NAME_Field]} = $NO_DEVICE ]]
1479             then
1480               print -- "\t${v[$DISK_NAME_Field]}" >> $resetFreeDisks
1481               checkForErrors "writing to file $resetFreeDisks" $?
1482             else
1483               print -- "\t${v[$DISK_NAME_Field]}" >> $resetNSDs.${v[$DEV_NAME_Field]}
1484               checkForErrors "writing to file $resetNSDs.${v[$DEV_NAME_Field]}" $?
1485             fi
1486           fi  # end if [[ $importDiskResult = successServersRemoved ]]
1487
1488           # Keep track of the highest NSD number assigned to a disk.
1489           if [[ ${v[$DISK_NAME_Field]} = gpfs+([0-9])nsd ]]
1490           then
1491             nsdName=${v[$DISK_NAME_Field]}
1492             nsdNumber=${nsdName#gpfs}
1493             nsdNumber=${nsdNumber%nsd}
1494             [[ $nsdNumber -gt $maxDiskNumber ]] && maxDiskNumber=$nsdNumber
1495           fi
1496
1497         else
1498           # There is a problem with this disk;
1499           # free disk errors are reported but ignored.
1500           printErrorMsg 50 $mmcmd ${v[$DISK_NAME_Field]}
1501           if [[ ${v[$DEV_NAME_Field]} != $NO_DEVICE ]]
1502           then
1503             failedFileSystems="${failedFileSystems}\n\t${v[$DEV_NAME_Field]}"
1504             $rm -f $importFile.${v[$DEV_NAME_Field]} $resetNSDs.${v[$DEV_NAME_Field]}
1505             importThisFileSystem=""
1506           fi
1507         fi  # end of if [[ $importDiskResult = success* ]]
1508       fi  # end of if [[ -n $importThisFileSystem ]]
1509       ;;
1510
1511    * )  # Pass all other lines without a change.
1512       ;;
1513
1514  esac  # end of case ${v[$LINE_TYPE_Field]} in
1515
1516  IFS=":"  # Change the separator back to ":" for the next iteration.
1517
1518done  # end while read -u3 sdrfsLine
1519
1520IFS="$IFS_sv"  # Restore the default IFS settings.
1521
1522
1523###################################################################
1524# Add to the new mmsdrfs file the information for all file systems
1525# that have not encountered any problems so far.
1526###################################################################
1527for fs in $($ls $importFile.* 2>/dev/null)
1528do
1529  $cat $fs >> $newsdrfs
1530  checkForErrors "writing to file $newsdrfs" $?
1531  fsToImport="$fsToImport\n\t${fs#$importFile.}"
1532done
1533
1534# Add the imported free disks, if any.
1535if [[ -s $importedFreeDisks ]]
1536then
1537  $cat $importedFreeDisks >> $newsdrfs
1538  checkForErrors "writing to file $newsdrfs" $?
1539fi
1540
1541# If nothing was imported, there is no sense continuing.
1542if [[ -z $fsToImport && ! -s $importedFreeDisks ]]
1543then
1544  # There is nothing to do.  Issue appropriate messages.
1545  if [[ -n $importAll && -z $someFsFound ]]
1546  then
1547    # There is no file system information in the input file.
1548    printErrorMsg 273 $mmcmd $fsImportData
1549  elif [[ -z $importAll && -z $specifiedFsFound ]]
1550  then
1551    # The file system was not found in the input file.
1552    printErrorMsg 274 $mmcmd $device $fsImportData
1553  else
1554    :  # nothing here for now
1555  fi
1556
1557  # Tell the user which file systems had problems.
1558  if [[ -n $failedFileSystems ]]
1559  then
1560    # Report the file systems that were not imported.
1561    print -- ""   # Output a blank separator line.
1562    printErrorMsg 275 $mmcmd "$failedFileSystems"
1563  fi
1564
1565  # The command failed.
1566  printErrorMsg 389 $mmcmd
1567  cleanupAndExit
1568fi
1569
1570
1571########################################################
1572# Update the HIGHEST_GPFS_DISK_NBR_Field if necessary.
1573########################################################
1574$rm -f $tmpfile   # Make sure there is nothing in the file.
1575if [[ $maxDiskNumber -gt $prevMaxDiskNumber && $MMMODE = lc ]]
1576then
1577  $awk -F:  '                                                                 \
1578     # If this is the global header line, change the max NSD number.          \
1579     /^'$GLOBAL_ID:$VERSION_LINE:'/ {                                         \
1580        { $'$HIGHEST_GPFS_DISK_NBR_Field' = "'$maxDiskNumber'" }              \
1581        { print  $1":" $2":" $3":" $4":" $5":" $6":" $7":" $8":" $9":"$10":"  \
1582                $11":"$12":"$13":"$14":"$15":"$16":"$17":"$18":"$19":"$20":"  \
1583                $21":"$22":"$23":"$24":"$25":"$26":"$27":" >> "'$tmpfile'" }  \
1584        { next }                                                              \
1585     }                                                                        \
1586     # All other lines are echoed without change.                             \
1587     { print $0 >> "'$tmpfile'" }                                             \
1588  ' $newsdrfs
1589  checkForErrors awk $?
1590
1591  # The file was updated successfully.
1592  $mv $tmpfile $newsdrfs
1593  checkForErrors "mv $outfile $newsdrfs" $?
1594fi
1595
1596
1597############################################
1598# Sort the new version of the mmsdrfs file.
1599############################################
1600LC_ALL=C $SORT_MMSDRFS $newsdrfs -o $newsdrfs
1601checkForErrors "sorting $newsdrfs" $?
1602
1603
1604############################################################
1605# Replace the mmsdrfs file in the sdr with the new version.
1606############################################################
1607print -- ""   # Output a blank separator line.
1608print -- "$mmcmd: Committing the changes ..."
1609
1610trap "" HUP INT QUIT KILL
1611gpfsObjectInfo=$(commitChanges  \
1612   $nsId $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer)
1613rc=$?
1614if [[ $rc -ne 0 ]]
1615then
1616  # Cannot replace the file in the sdr.
1617  printErrorMsg 381 $mmcmd
1618  cleanupAndExit
1619fi
1620
1621
1622###################################################################
1623# Unlock the sdr.
1624###################################################################
1625freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
1626sdrLocked=no
1627trap posttrap HUP INT QUIT KILL
1628
1629
1630######################################################################
1631# Issue messages summarizing the results and what remains to be done.
1632######################################################################
1633print -- ""   # Output a blank separator line.
1634# Tell the user which file systems were successfully imported.
1635[[ -n $fsToImport ]] &&  \
1636  print -u2 "$mmcmd: The following file systems were successfully imported: $fsToImport"
1637
1638# Tell the user which disks may need new server nodes.
1639for fs in $($ls $resetNSDs.* 2>/dev/null)
1640do
1641  print -u2 "$mmcmd: The NSD servers for the following disks from file system ${fs#$resetNSDs.} were reset or not defined:"
1642  $cat $fs 1>&2
1643  mmchnsdMessageNeeded=true
1644done
1645# Add the imported free disks, if any.
1646if [[ -s $resetFreeDisks ]]
1647then
1648  print -u2 "$mmcmd: The NSD servers for the following free disks were reset or not defined:"
1649  $cat $resetFreeDisks 1>&2
1650  mmchnsdMessageNeeded=true
1651fi
1652[[ -n $mmchnsdMessageNeeded ]] &&  \
1653  print -u2 "$mmcmd: Use the mmchnsd command to assign NSD servers as needed."
1654
1655# Tell the user which file systems were not imported.
1656[[ -n $failedFileSystems ]] &&  \
1657  print -u2 "$mmcmd: The following file systems were not imported: $failedFileSystems"
1658
1659
1660#################################################################
1661# Propagate the new mmsdrfs file.  This process is asynchronous.
1662#################################################################
1663propagateSdrfsFile async $allClusterNodes $newsdrfs $newGenNumber rereadnsd
1664
1665cleanupAndExit 0
1666
Note: See TracBrowser for help on using the repository browser.