~ubuntu-branches/ubuntu/precise/mdadm/precise-updates

« back to all changes in this revision

Viewing changes to debian/mdadd.sh

  • Committer: Package Import Robot
  • Author(s): Clint Byrum
  • Date: 2012-02-09 16:53:02 UTC
  • mfrom: (1.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120209165302-bs4cfosmhoga2rpt
Tags: 3.2.3-2ubuntu1
* Merge from Debian testing. (LP: #920324)  Remaining changes:
  - Call checks in local-premount to avoid race condition with udev
    and opening a degraded array.
  - d/initramfs/mdadm-functions: Record in /run when boot-degraded 
    question has been asked so that it is only asked once
  - pass --test to mdadm to enable result codes for degraded arrays. 
  - Build udeb with -O2 on ppc64, working around a link error.
  - debian/control: we need udev and util-linux in the right version. We
    also remove the build dependency from quilt and docbook-to-man as both
    are not used in Ubuntus mdadm.
  - debian/initramfs/hook: kept the Ubuntus version for handling the absence
    of active raid arrays in <initramfs>/etc/mdadm/mdadm.conf
  - debian/initramfs/script.local-top.DEBIAN, debian/mdadm-startall,
    debian/mdadm.raid.DEBIAN: removed. udev does its job now instead.
  - debian/mdadm-startall.sgml, debian/mdadm-startall.8: documentation of
    unused startall script
  - debian/mdadm.config, debian/mdadm.postinst - let udev do the handling
    instead. Resolved merge conflict by keeping Ubuntu's version.
  - debian/mdadm.postinst, debian/mdadm.config, initramfs/init-premount:
    boot-degraded enablement; maintain udev starting of RAID devices;
    init-premount hook script for the initramfs, to provide information at
    boot
  - debian/mkconf.in is the older mkconf. Kept the Ubuntu version.
  - debian/rules: Kept Ubuntus version for installing apport hooks, not
    installing un-used startall script and for adding a udev rule
    corresponding to mdadm.
  - debian/install-rc, check.d/_numbers, check.d/root_on_raid: Ubuntu partman
    installer changes
  - debian/presubj: Dropped this unused bug reporting file. Instead use
    source_mdadm.py act as an apport hook for bug handling.
  - rename debian/mdadm.vol_id.udev to debian/mdadm.mdadm-blkid.udev so that
    the rules file ends up with a more reasonable name
  - d/p/debian-changes-3.1.4-1+8efb9d1ubuntu4: mdadm udev rule
    incrementally adds mdadm member when detected. Starting such an
    array in degraded mode is possible by mdadm -IRs. Using mdadm
    -ARs without stopping the array first does nothing when no
    mdarray-unassociated device is available. Using mdadm -IRs to
    start a previously partially assembled array through incremental
    mode. Keeping the mdadm -ARs for assembling arrays which were for
    some reason not assembled through incremental mode (i.e through
    mdadm's udev rule).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/sh
 
2
 
 
3
MY_VERSION="1.52a"
 
4
# ----------------------------------------------------------------------------------------------------------------------
 
5
# Linux MD (Soft)RAID Add Script - Add a (new) harddisk to another multi MD-array harddisk
 
6
# Last update: January 10, 2012
 
7
# (C) Copyright 2005-2012 by Arno van Amersfoort
 
8
# Homepage              : http://rocky.eld.leidenuniv.nl/
 
9
# Email                 : a r n o v a AT r o c k y DOT e l d DOT l e i d e n u n i v DOT n l
 
10
#                         (note: you must remove all spaces and substitute the @ and the . at the proper locations!)
 
11
# ----------------------------------------------------------------------------------------------------------------------
 
12
# This program is free software; you can redistribute it and/or
 
13
# modify it under the terms of the GNU General Public License
 
14
# version 2 as published by the Free Software Foundation.
 
15
#
 
16
# This program is distributed in the hope that it will be useful,
 
17
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
# GNU General Public License for more details.
 
20
#
 
21
# You should have received a copy of the GNU General Public License
 
22
# along with this program; if not, write to the Free Software
 
23
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
24
# ----------------------------------------------------------------------------------------------------------------------
 
25
 
 
26
EOL='
 
27
'
 
28
 
 
29
show_help()
 
30
{
 
31
  echo "Bad or missing parameter(s)"
 
32
  echo "Usage: $(basename $0) [ options ] [ source_disk ] [ target_disk ]"
 
33
  echo "Options:"
 
34
  echo "--force       = Even proceed if target device does not appear empty"
 
35
  echo "--noptupdate  = Do NOT update the partition table on the target device (EXPERT!)"
 
36
  echo "--nombrupdate = Do NOT update the MBR boot-loader on the target device (EXPERT!)"
 
37
}
 
38
 
 
39
 
 
40
get_partitions()
 
41
{
 
42
  local DEVICE="$(echo "$1" |sed s,'^/dev/',, )"
 
43
 
 
44
  if [ -z "$DEVICE" ]; then
 
45
    cat /proc/partitions |sed -e '1,2d' -e s,' /dev/',,
 
46
  else
 
47
    cat /proc/partitions |sed -e '1,2d' -e s,' /dev/',, |grep -E " ${DEVICE}p?[0-9]+$"
 
48
  fi
 
49
}
 
50
 
 
51
get_part_size()
 
52
{
 
53
  get_partitions |grep -E " ${1}$" |awk '{ print $3 }' 
 
54
}
 
55
 
 
56
check_binary()
 
57
{
 
58
  if ! which "$1" >/dev/null 2>&1; then
 
59
    printf "\033[40m\033[1;31mERROR: Binary \"$1\" does not exist or is not executable!\033[0m\n" >&2
 
60
    printf "\033[40m\033[1;31m       Please, make sure that it is (properly) installed!\033[0m\n" >&2
 
61
    exit 2
 
62
  fi
 
63
}
 
64
 
 
65
 
 
66
sanity_check()
 
67
{
 
68
  if [ "$(id -u)" != "0" ]; then 
 
69
    printf "\033[40m\033[1;31mERROR: Root check FAILED (you MUST be root to use this script)! Quitting...\n\033[0m" >&2
 
70
    exit 1
 
71
  fi
 
72
 
 
73
  check_binary mdadm
 
74
  check_binary sfdisk
 
75
  check_binary dd
 
76
  check_binary awk
 
77
  check_binary grep
 
78
  check_binary sed
 
79
  check_binary cat
 
80
 
 
81
  if [ -z "$SOURCE" ] || [ -z "$TARGET" ]; then
 
82
    echo "ERROR: Bad or missing argument(s)" >&2
 
83
    show_help;
 
84
    exit 4
 
85
  fi
 
86
 
 
87
  if ! echo "$SOURCE" |grep -q '^/dev/'; then
 
88
    printf "\033[40m\033[1;31mERROR: Source device $SOURCE does not start with /dev/! Quitting...\n\033[0m" >&2
 
89
    exit 5
 
90
  fi
 
91
 
 
92
  if ! echo "$TARGET" |grep -q '^/dev/'; then
 
93
    printf "\033[40m\033[1;31mERROR: Target device $TARGET does not start with /dev/! Quitting...\n\033[0m" >&2
 
94
    exit 5
 
95
  fi
 
96
 
 
97
  if echo "$SOURCE" |grep -q 'md[0-9]'; then
 
98
    printf "\033[40m\033[1;31mERROR: The source device specified is an md-device! Quitting...\n\033[0m" >&2
 
99
    echo "A physical drive (part of the md-array(s)) is required as source device (eg. /dev/sda)!" >&2
 
100
    exit 5
 
101
  fi
 
102
 
 
103
  # We also want variables without /dev/ :
 
104
  SOURCE_NODEV="$(echo "$SOURCE" |sed 's,^/dev/,,')"
 
105
  TARGET_NODEV="$(echo "$TARGET" |sed 's,^/dev/,,')"
 
106
 
 
107
  if [ -z "$(get_partitions ${SOURCE_NODEV})" ]; then
 
108
    printf "\033[40m\033[1;31mERROR: Source device $SOURCE does not contain any partitions!? Quitting...\n\033[0m" >&2
 
109
    exit 7
 
110
  fi
 
111
 
 
112
  if [ -n "$(get_partitions ${TARGET_NODEV})" ] && [ $FORCE -ne 1 ]; then
 
113
    sfdisk -l "$TARGET"
 
114
    printf "\033[40m\033[1;31mERROR: Target device $TARGET already contains partitions! Use --force to override. Quitting...\n\033[0m" >&2
 
115
    exit 8
 
116
  fi
 
117
 
 
118
  SOURCE_SIZE="$(get_part_size $SOURCE_NODEV)"
 
119
  TARGET_SIZE="$(get_part_size $TARGET_NODEV)"
 
120
  if [ $SOURCE_SIZE -gt $TARGET_SIZE ]; then
 
121
    printf "\033[40m\033[1;31mWARNING: Target device $TARGET ($TARGET_SIZE blocks) is smaller than source device $SOURCE ($SOURCE_SIZE blocks)\nPress enter to continue or CTRL-C to abort...\n\033[0m" >&2
 
122
    read
 
123
  fi
 
124
 
 
125
  echo "--> Saving mdadm detail scan to /tmp/mdadm-detail-scan..."
 
126
  mdadm --detail --scan --verbose >|/tmp/mdadm-detail-scan
 
127
  retval=$?
 
128
  if [ $retval -ne 0 ]; then
 
129
    printf "\033[40m\033[1;31mERROR: mdadm returned an error($retval) while determining detail information!\n\033[0m" >&2
 
130
    exit 9
 
131
  fi 
 
132
 
 
133
  echo "--> Saving partition table of target device $TARGET to /tmp/partitions.target..."
 
134
  sfdisk -d "$TARGET" >|"/tmp/partitions.target" 2>/dev/null
 
135
  retval=$?
 
136
  if [ $retval -ne 0 ]; then
 
137
    echo "NOTE: sfdisk returned an error($retval) while reading the partition table on $TARGET"
 
138
  fi
 
139
 
 
140
  echo "--> Saving partition table of source device $SOURCE to /tmp/partitions.source..."
 
141
  sfdisk -d "$SOURCE" >|"/tmp/partitions.source"
 
142
  retval=$?
 
143
  if [ $retval -ne 0 ]; then
 
144
    printf "\033[40m\033[1;31mERROR: sfdisk returned an error($retval) while reading the partition table on $SOURCE!\n\033[0m" >&2
 
145
    exit 11
 
146
  fi
 
147
  
 
148
  echo "--> Checking status of running MDs..."
 
149
  MD_DEV=""
 
150
  IFS=$EOL
 
151
  for MDSTAT_LINE in `cat /proc/mdstat`; do
 
152
    if echo "$MDSTAT_LINE" |grep -q '^md'; then
 
153
      MD_DEV_LINE="$MDSTAT_LINE"
 
154
      MD_DEV="$(echo "$MDSTAT_LINE" |awk '{ print $1 }')"
 
155
 
 
156
      IFS=$EOL
 
157
      for part_nodev in `cat "/tmp/partitions.target" |grep '^/dev/' |grep -i -v 'Id= 0' |awk '{ print $1 }' |sed 's,^/dev/,,'`; do
 
158
        if echo "$MD_DEV_LINE" |grep -E -q "[[:blank:]]$part_nodev\["; then
 
159
          printf "\033[40m\033[1;31mERROR: Partition /dev/$part_nodev on target device is already in use by array /dev/$MD_DEV!\n\033[0m" >&2
 
160
          exit 12
 
161
        fi
 
162
      done
 
163
    fi
 
164
 
 
165
    if echo "$MDSTAT_LINE" |grep -E -q '[[:blank:]]blocks[[:blank:]]' && ! echo "$MDSTAT_LINE" |grep -q '_'; then
 
166
      # This array is NOT degraded so now check whether we want to add devices to it:
 
167
 
 
168
      IFS=$EOL
 
169
      for part_nodev in `cat "/tmp/partitions.source" |grep '^/dev/' |grep -i -v 'Id= 0' |awk '{ print $1 }' |sed 's,^/dev/,,'`; do
 
170
        if echo "$MD_DEV_LINE" |grep -E -q "[[:blank:]]$part_nodev\["; then
 
171
          printf "$MD_DEV_LINE\n$MDSTAT_LINE\n"
 
172
          printf "\033[40m\033[1;31mWARNING: Array $MD_DEV is NOT degraded, target device ${TARGET}$(echo "$part_nodev" |sed "s,$SOURCE_NODEV,,") will become a hotspare!\nPress enter to continue or CTRL-C to abort...\n\033[0m" >&2
 
173
          read
 
174
        fi
 
175
      done
 
176
    fi
 
177
  done
 
178
}
 
179
 
 
180
 
 
181
# Wrapper for partprobe (call when performing a partition table update with eg. fdisk/sfdisk).
 
182
# $1 = Device to re-read
 
183
partprobe()
 
184
{
 
185
  local DEVICE="$1"
 
186
  local result=""
 
187
   
 
188
  printf "(Re)reading partition table on $DEVICE"
 
189
 
 
190
  # Retry several times since some daemons can block the re-reread for a while (like dm/lvm or blkid)
 
191
  for x in `seq 1 10`; do
 
192
    printf "."
 
193
    result=`sfdisk -R "$DEVICE" 2>&1`
 
194
    
 
195
    # Wait a bit for things to settle
 
196
    sleep 1
 
197
 
 
198
    if [ -z "$result" ]; then
 
199
      break;
 
200
    fi
 
201
  done
 
202
  
 
203
  echo ""
 
204
  
 
205
  if [ -n "$result" ]; then
 
206
    echo "$result" >&2
 
207
    return 1
 
208
  fi
 
209
  return 0
 
210
}
 
211
 
 
212
 
 
213
# Program entry point
 
214
echo "MDadd for SoftRAID-MDADM v$MY_VERSION"
 
215
echo "Written by Arno van Amersfoort"
 
216
echo "--------------------------------"
 
217
 
 
218
# Set environment variables to default
 
219
FORCE=0
 
220
NOPTUPDATE=0
 
221
NOMBRUPDATE=0
 
222
SOURCE=""
 
223
TARGET=""
 
224
 
 
225
# Check arguments
 
226
unset IFS
 
227
for arg in $*; do
 
228
  ARGNAME="$(echo "$arg" |cut -d= -f1)"
 
229
  ARGVAL="$(echo "$arg" |cut -d= -f2)"
 
230
 
 
231
  if ! echo "$ARGNAME" |grep -q '^-'; then
 
232
    if [ -z "$SOURCE" ]; then
 
233
      SOURCE="$ARGVAL"
 
234
    else
 
235
      if [ -z "$TARGET" ]; then
 
236
        TARGET="$ARGVAL"
 
237
      else
 
238
        show_help;
 
239
        exit 3
 
240
      fi
 
241
    fi
 
242
  else
 
243
    case "$ARGNAME" in
 
244
      --force|-force|-f) FORCE=1;;
 
245
      --noptupdate|-noptupdate|--noptu|-noptu) NOPTUPDATE=1;;
 
246
      --nombrupdate|-nombrupdate|--nombru|nombru) NOMBRUPDATE=1;;
 
247
      --help) show_help;
 
248
              exit 0;;
 
249
      *) echo "ERROR: Bad argument: $ARGNAME";
 
250
         show_help;
 
251
         exit 3;;
 
252
    esac
 
253
  fi
 
254
done
 
255
 
 
256
# Make sure everything is sane:
 
257
sanity_check;
 
258
 
 
259
# Disable all swaps on target disk
 
260
echo "--> Disabling any swap partitions on target device $TARGET"
 
261
IFS=$EOL
 
262
for SWAP in `grep -E "^${TARGET}p?[0-9]+" /proc/swaps |awk '{ print $1 }'`; do
 
263
  swapoff $SWAP >/dev/null 2>&1
 
264
done
 
265
 
 
266
# Update track0 on target disk
 
267
if [ $NOMBRUPDATE -ne 1 ]; then
 
268
  echo "--> Copying track0(containing MBR) from $SOURCE to $TARGET..."
 
269
  dd if="$SOURCE" of="$TARGET" bs=32768 count=1
 
270
  retval=$?
 
271
  if [ $retval -ne 0 ]; then
 
272
    printf "\033[40m\033[1;31mERROR: dd returned an error($retval) while copying track0!\n\033[0m" >&2
 
273
    exit 9
 
274
  fi
 
275
fi
 
276
 
 
277
PT_FILE="/tmp/partitions.source"
 
278
if [ $NOPTUPDATE -eq 1 ]; then
 
279
  PT_FILE="/tmp/partitions.target"
 
280
fi
 
281
  
 
282
echo "--> Restoring partition table from $PT_FILE to $TARGET..."
 
283
sfdisk --no-reread --force "$TARGET" < "$PT_FILE"
 
284
retval=$?
 
285
if [ $retval -ne 0 ]; then
 
286
  printf "\033[40m\033[1;31mERROR: sfdisk returned an error($retval) while writing the partition table!\n\033[0m" >&2
 
287
  exit 9
 
288
fi
 
289
 
 
290
echo ""
 
291
 
 
292
if [ $NOPTUPDATE -ne 1 ]; then
 
293
  # Re-read partition table
 
294
  partprobe "$TARGET"
 
295
  retval=$?
 
296
  if [ $retval -ne 0 ]; then
 
297
    printf "\033[40m\033[1;31mERROR: (Re)reading the partition table failed($retval)!\n\033[0m" >&2
 
298
    exit 9
 
299
  fi
 
300
fi
 
301
 
 
302
# Copy/build all md devices that exist on the source drive:
 
303
BOOT=0
 
304
NO_ADD=1
 
305
IFS=$EOL
 
306
for LINE in `cat /tmp/mdadm-detail-scan`; do
 
307
  if echo "$LINE" |grep -E -q '^ARRAY[[:blank:]]'; then
 
308
    MD_DEV=$(echo "$LINE" |awk '{ print $2 }')
 
309
  fi
 
310
 
 
311
  if echo "$LINE" |grep -E -q "devices=.*${SOURCE}p?[0-9]+"; then
 
312
    PARTITION_NR=""
 
313
    IFS=','
 
314
    for item in `echo "$LINE" |sed -e "s:.*devices=::"`; do
 
315
      if echo "$item" |grep -E -q -x "${SOURCE}p?[0-9]+"; then
 
316
        PARTITION_NR=`echo "$item" |sed s:"$SOURCE"::`
 
317
        break;
 
318
      fi
 
319
    done
 
320
 
 
321
    if [ -z "$PARTITION_NR" ]; then
 
322
      printf "\033[40m\033[1;31mERROR: Unable to retrieve detail information for $SOURCE from $MD_DEV!\n\033[0m" >&2
 
323
      exit 11
 
324
    fi
 
325
 
 
326
    # Check whether we're a root or boot partition
 
327
    if grep -E -q -e "^$MD_DEV[[:blank:]]*/boot[[:blank:]]" -e "$MD_DEV[[:blank:]]*/[[:blank:]]" /etc/fstab; then
 
328
      BOOT=1
 
329
    fi
 
330
 
 
331
    NO_ADD=0
 
332
    echo ""
 
333
    echo "--> Adding ${TARGET}${PARTITION_NR} to RAID array $MD_DEV:"
 
334
    printf "\033[40m\033[1;31m"
 
335
    mdadm --add "$MD_DEV" "${TARGET}${PARTITION_NR}"
 
336
    retval=$?
 
337
    if [ $retval -ne 0 ]; then
 
338
      printf "\033[40m\033[1;31mERROR: mdadm returned an error($retval) while adding device!\n\033[0m" >&2
 
339
      exit 12
 
340
    fi
 
341
    printf "\033[0m"
 
342
  fi
 
343
done
 
344
 
 
345
echo ""
 
346
 
 
347
# Create swapspace on partitions with ID=82
 
348
echo "--> Creating swapspace on target device (if any swap partitions exist)..."
 
349
IFS=$EOL
 
350
for SWAP_DEVICE in `sfdisk -d "$TARGET" 2>/dev/null |grep -i 'Id=82$' |awk '{ print $1 }'`; do
 
351
  if ! mkswap "$SWAP_DEVICE"; then
 
352
    printf "\033[40m\033[1;31mWARNING: mkswap failed for $SWAP_DEVICE\n\033[0m" >&2
 
353
  else
 
354
    swapon "$SWAP_DEVICE"
 
355
  fi
 
356
 
 
357
  if ! grep -E -q "^$SWAP_DEVICE[[:blank:]]*none[[:blank:]]*swap[[:blank:]]" /etc/fstab; then
 
358
    printf "\033[40m\033[1;31mWARNING: /etc/fstab does NOT contain a (valid) swap entry for $SWAP_DEVICE\n\033[0m" >&2
 
359
  fi
 
360
done
 
361
 
 
362
# Wait a bit for mdstat to settle
 
363
sleep 3
 
364
 
 
365
echo "--> Showing current /proc/mdstat (you may need to update your mdadm.conf (manually)..."
 
366
cat /proc/mdstat
 
367
echo ""
 
368
 
 
369
if [ $NO_ADD -eq 1 ]; then
 
370
  printf "\033[40m\033[1;31mWARNING: No mdadm --add actions were performed, please investigate!\n\033[0m" >&2
 
371
fi
 
372
 
 
373
if [ $BOOT -eq 1 ]; then
 
374
  printf "\033[40m\033[1;31mNOTE: Boot and/or root partition detected.\n      Please check your bootloader & active partitions!\n\033[0m"
 
375
fi