Re: partman-md/mdcfg merge
I broke RAID0 creation due to a typo (log_output vs. log-output).
Version 3 attached.
--
Colin Watson [cjwatson@ubuntu.com]
=== modified file 'choose_partition/md/choices'
--- choose_partition/md/choices 2007-12-28 16:24:47 +0000
+++ choose_partition/md/choices 2009-07-13 21:43:11 +0000
@@ -1,7 +1,5 @@
#!/bin/sh
-[ -x /bin/mdcfg ] || exit 0
-
. /lib/partman/lib/base.sh
use_raid=no
=== modified file 'choose_partition/md/do_option'
--- choose_partition/md/do_option 2007-12-28 16:24:47 +0000
+++ choose_partition/md/do_option 2009-07-14 11:43:48 +0000
@@ -1,14 +1,292 @@
#!/bin/sh
-. /lib/partman/lib/base.sh
+. /lib/partman/lib/md-base.sh
. /lib/partman/lib/commit.sh
-confirm_changes partman-md || exit 0
+do_initial_setup () {
+ # Make sure that MD support is available
+ if [ ! -e /proc/mdstat ]; then
+ db_input critical partman-md/nomd
+ db_go
+ exit 0
+ fi
-commit_changes partman-md/commit_failed || exit $?
+ # Commit the changes
+ confirm_changes partman-md || exit 0
+ commit_changes partman-md/commit_failed || exit $?
-stop_parted_server
+ # Try to detect MD devices, and start them
+ mkdir -p /dev/md
+ log-output -t partman-md --pass-stdout \
+ mdadm --examine --scan --config=partitions >/tmp/mdadm.conf
+ log-output -t partman-md \
+ mdadm --assemble --scan --run \
+ --config=/tmp/mdadm.conf --auto=yes
+}
+
+prune_partitions () {
+ local chosen="$1"
+ local new_partitions=
+ local i j
+ for i in $PARTITIONS; do
+ local found=0
+ for j in $chosen; do
+ if [ "$i" = "$j" ]; then
+ found=1
+ break
+ fi
+ done
+ if [ "$found" -eq 0 ]; then
+ new_partitions="${new_partitions:+$new_partitions }$i"
+ fi
+ done
+ PARTITIONS="$new_partitions"
+}
+
+md_create_raid0 () {
+ db_subst partman-md/raid0devs PARTITIONS "$(ssv_to_csv "$PARTITIONS")"
+ db_set partman-md/raid0devs ''
+ db_input critical partman-md/raid0devs
+ db_go || return
+
+ db_get partman-md/raid0devs
+ RET="$(csv_to_ssv "$RET")"
+ local selected="$(echo "$RET" | wc -w)"
+ prune_partitions "$RET"
+
+ local md_num="$(md_next_device_number)"
+
+ logger -t partman-md "Number of devices in the RAID0 array md$md_num: $selected"
+
+ local raid_devices="$(csv_to_ssv "$RET")"
+ log-output -t partman-md \
+ mdadm --create /dev/md$md_num --auto=yes --force -R -l raid0 \
+ -n $selected $raid_devices || return $?
+ md_lock_devices "md$md_num" $raid_devices
+}
+
+md_create_array () {
+ local min_size i
+
+ case $1 in
+ RAID1) min_size=2 ;;
+ RAID5) min_size=3 ;;
+ RAID6) min_size=4 ;;
+ RAID10) min_size=2 ;;
+ *) return ;;
+ esac
+
+ local level="${1#RAID}"
+
+ for i in devcount devs sparecount sparedevs; do
+ db_subst partman-md/raid$i LEVEL "$level"
+ done
+ db_subst partman-md/raiddevcount MINIMUM "$min_size"
+
+ db_set partman-md/raiddevcount "$min_size"
+ md_db_get_number partman-md/raiddevcount "$min_size" 99 || return
+ local dev_count="$RET"
+
+ db_set partman-md/raidsparecount 0
+ md_db_get_number partman-md/raidsparecount 0 99 || return
+ local spare_count="$RET"
+
+ if [ "$level" -ne 1 ] && [ "$dev_count" -lt "$min_size" ]; then
+ # minimum number for the selected RAID level
+ dev_count="$min_size"
+ fi
+ local required="$(($dev_count + $spare_count))"
+ if [ "$level" -ne 1 ] && [ "$required" -gt "$NUM_PART" ]; then
+ db_subst partman-md/notenoughparts NUM_PART "$NUM_PART"
+ db_subst partman-md/notenoughparts REQUIRED "$required"
+ db_input critical partman-md/notenoughparts
+ db_go
+ return
+ fi
+
+ db_set partman-md/raiddevs ''
+ local selected=0
+
+ # RAID 5/6/10: loop until correct number of active devices selected
+ # RAID 1: loop until at least one device selected
+ until ([ "$level" -ne 1 ] && [ "$selected" -eq "$dev_count" ]) || \
+ ([ "$level" -eq 1 ] && [ "$selected" -gt 0 ] && [ "$selected" -le "$dev_count" ]); do
+ db_subst partman-md/raiddevs COUNT "$dev_count"
+ db_subst partman-md/raiddevs PARTITIONS "$(ssv_to_csv "$PARTITIONS")"
+ db_input critical partman-md/raiddevs
+ db_go || return
+
+ db_get partman-md/raiddevs
+ selected="$(echo "$RET" | wc -w)"
+ done
+
+ local missing_devices=
+ if [ "$level" -eq 1 ]; then
+ # Add "missing" for as many devices as weren't selected
+ while [ "$selected" -lt "$dev_count" ]; do
+ missing_devices="$missing_devices missing"
+ selected="$(($selected + 1))"
+ done
+ fi
+
+ # Remove partitions selected in raiddevs from the PARTITIONS list
+ db_get partman-md/raiddevs
+ prune_partitions "$(csv_to_ssv "$RET")"
+
+ db_set partman-md/raidsparedevs ''
+ selected=0
+ if [ "$spare_count" -gt 0 ] && [ -n "$PARTITIONS" ]; then
+ local first=1
+ # Loop until the correct number of devices has been selected.
+ # That means any number less than or equal to the spare count.
+ while [ "$selected" -gt "$spare_count" ] || [ "$first" -eq 1 ]; do
+ first=0
+ db_subst partman-md/raidsparedevs COUNT "$spare_count"
+ db_subst partman-md/raidsparedevs PARTITIONS "$(ssv_to_csv "$PARTITIONS")"
+ db_input critical partman-md/raidsparedevs
+ db_go || return
-mdcfg
+ db_get partman-md/raidsparedevs
+ selected="$(echo "$RET" | wc -w)"
+ done
+ fi
+
+ local layout=
+ if [ "$level" -eq 10 ]; then
+ db_set partman-md/raid10layout n2
+ while :; do
+ db_input low partman-md/raid10layout
+ db_go || return
+ db_get partman-md/raid10layout
+ if echo "$RET" | egrep -q '^[nfo][0-9]{1,2}$' && \
+ [ "$(echo "$RET" | sed 's/.//')" -le "$dev_count" ]; then
+ break
+ fi
+ done
+ layout="--layout=$RET"
+ fi
+
+ # The number of spares the user has selected
+ local named_spares="$selected"
+
+ db_get partman-md/raiddevs
+ local raid_devices="$(csv_to_ssv "$RET")"
+
+ db_get partman-md/raidsparedevs
+ local spare_devices="$(csv_to_ssv "$RET")"
+
+ local missing_spares=
+ local count="$named_spares"
+ while [ "$count" -lt "$spare_count" ]; do
+ missing_spares="$missing_spares missing"
+ count="$(($count + 1))"
+ done
+
+ local md_num="$(md_next_device_number)"
+
+ logger -t partman-md "Selected spare count: $named_spares"
+ logger -t partman-md "RAID devices count: $dev_count"
+ logger -t partman-md "Spare devices count: $spare_count"
+ log-output -t partman-md \
+ mdadm --create /dev/md$md_num --auto=yes --force -R \
+ -l raid$level $layout \
+ -n $dev_count -x $spare_count $raid_devices \
+ $missing_devices $spare_devices $missing_spares || \
+ return $?
+ md_lock_devices "md$md_num" $raid_devices $spare_devices
+}
+
+do_create () {
+ db_input critical partman-md/createmain
+ db_go || return
+ db_get partman-md/createmain
+ local raid_sel="$RET"
+ PARTITIONS="$(md_get_partitions)"
+ if [ -z "$PARTITIONS" ]; then
+ db_input critical partman-md/noparts
+ db_go
+ return
+ fi
+ NUM_PART="$(echo "$PARTITIONS" | wc -w)"
+ case $raid_sel in
+ RAID10|RAID6|RAID5|RAID1)
+ md_create_array "$raid_sel" ;;
+ RAID0)
+ md_create_raid0 ;;
+ esac
+}
+
+md_delete_verify () {
+ local device="$(echo "$1" | sed 's/^\(md.*\)_.*/\1/')"
+ local devices="$(grep "^$DEVICE[ :]" /proc/mdstat | \
+ sed 's/^.*active \(.*\)/\1/; s/raid[0-9]* //')"
+ local mddev="$(md_devnode "$device")" || return 1
+ local mdtype="$(md_get_level "$mddev")"
+
+ db_set partman-md/deleteverify false
+ db_subst partman-md/deleteverify DEVICE "/dev/$device"
+ db_subst partman-md/deleteverify TYPE "$mdtype"
+ db_subst partman-md/deleteverify DEVICES "$devices"
+ db_input critical partman-md/deleteverify
+ db_go || return 0
+ db_get partman-md/deleteverify
+ [ "$RET" = true ] || return 0
+
+ # Stop the MD device and zero the superblock of all the component
+ # devices
+ devices="$(mdadm -Q --detail "$mddev" | \
+ egrep '^[[:space:]]*[0-9].*(active|spare)' | \
+ sed 's/.* //')"
+ logger -t partman-md "Removing $mddev ($devices)"
+ log-output -t partman-md mdadm --stop "$mddev" || return 1
+ local dev
+ for dev in $devices; do
+ log-output -t partman-md \
+ mdadm --zero-superblock --force "$dev" || return 1
+ done
+ return 0
+}
+
+do_delete () {
+ md_get_devices
+ if [ -z "$MD_DEVICES" ]; then
+ db_input high partman-md/delete_no_md
+ db_go
+ return
+ fi
+
+ db_subst partman-md/deletemenu DEVICES "$MD_DEVICES"
+ db_input critical partman-md/deletemenu
+ db_go || return
+ db_get partman-md/deletemenu
+
+ if ! md_delete_verify "$RET"; then
+ db_input critical partman-md/deletefailed
+ db_go
+ fi
+}
+
+do_initial_setup
+
+while :; do
+ db_input critical partman-md/mainmenu
+ db_go || exit 10
+ db_get partman-md/mainmenu
+ case $RET in
+ create) do_create ;;
+ delete) do_delete ;;
+ finish) break ;;
+ *)
+ logger -t partman-md "Unknown selection '$RET'"
+ break ;;
+ esac
+done
+
+# Force mdadm to be installed on the target system
+apt-install mdadm
+
+stop_parted_server
restart_partman
+
+exit 0
=== modified file 'debian/changelog'
--- debian/changelog 2009-06-13 06:49:21 +0000
+++ debian/changelog 2009-07-09 20:00:43 +0000
@@ -1,3 +1,12 @@
+partman-md (46) UNRELEASED; urgency=low
+
+ * Merge mdcfg, making partman-md stand-alone. Bugs fixed along the way:
+ - Talks about "software RAID" or "multiple device" rather than
+ "multidisk" (closes: #387696).
+ - Uses partman locking mechanism (closes: #499285).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 09 Jul 2009 18:23:25 +0100
+
partman-md (45) unstable; urgency=low
[ Colin Watson ]
=== modified file 'debian/control'
--- debian/control 2008-07-31 00:17:08 +0000
+++ debian/control 2009-07-09 15:36:52 +0000
@@ -9,5 +9,5 @@ Vcs-Svn: svn://svn.debian.org/d-i/trunk/
Package: partman-md
XC-Package-Type: udeb
Architecture: all
-Depends: ${misc:Depends}, mdadm-udeb, mdcfg-utils, partman-base (>= 124)
+Depends: ${misc:Depends}, di-utils (>= 1.16), md-modules, mdadm-udeb (>= 2.5.2), partman-base (>= 124)
Description: Add to partman support for MD
=== modified file 'debian/partman-md.templates'
--- debian/partman-md.templates 2008-07-31 00:18:50 +0000
+++ debian/partman-md.templates 2009-07-09 20:58:27 +0000
@@ -8,6 +8,165 @@ Type: text
# :sl3:
_Description: Configure software RAID
+Template: partman-md/text/in_use
+Type: text
+# :sl3:
+# What is "in use" is a partition
+_Description: In use by software RAID device ${DEVICE}
+
+Template: partman-md/nomd
+Type: error
+# :sl3:
+_Description: Software RAID not available
+ The current kernel doesn't seem to support software RAID (MD) devices. This
+ should be solved by loading the necessary modules.
+
+Template: partman-md/mainmenu
+Type: select
+Choices-C: create, delete, finish
+# Note to translators : Please keep your translations of the choices
+# below a 65 columns limit (which means 65 characters
+# in single-byte languages)
+# :sl3:
+__Choices: Create MD device, Delete MD device, Finish
+# :sl3:
+_Description: Software RAID configuration actions
+ This is the software RAID (or MD, "multiple device") configuration menu.
+ .
+ Please select one of the proposed actions to configure software RAID.
+
+Template: partman-md/createmain
+Type: select
+Choices: RAID0, RAID1, RAID5, RAID6, RAID10
+# :sl3:
+_Description: Software RAID device type:
+ Please choose the type of the software RAID device to be created.
+
+Template: partman-md/noparts
+Type: error
+# :sl3:
+_Description: No RAID partitions available
+ No unused partitions of the type "Linux RAID Autodetect" are available.
+ Please create such a partition, or delete an already used software RAID
+ device to free its partitions.
+ .
+ If you have such partitions, they might contain actual file systems, and
+ are therefore not available for use by this configuration utility.
+
+Template: partman-md/raid0devs
+Type: multiselect
+Choices: ${PARTITIONS}
+# :sl3:
+_Description: Active devices for the RAID0 array:
+ You have chosen to create a RAID0 array. Please choose the active devices
+ in this array.
+
+Template: partman-md/raiddevcount
+Type: string
+# :sl3:
+_Description: Number of active devices for the RAID${LEVEL} array:
+ The RAID${LEVEL} array will consist of both active and spare devices. The
+ active devices are those used, while the spare devices will only be used if
+ one or more of the active devices fail. A minimum of ${MINIMUM} active
+ devices is required.
+ .
+ NOTE: this setting cannot be changed later.
+
+Template: partman-md/raiddevs
+Type: multiselect
+Choices: ${PARTITIONS}
+# :sl3:
+_Description: Active devices for the RAID${LEVEL} array:
+ You have chosen to create a RAID${LEVEL} array with ${COUNT} active devices.
+ .
+ Please choose which partitions are active devices.
+ You must select exactly ${COUNT} partitions.
+
+Template: partman-md/raidsparecount
+Type: string
+# :sl3:
+_Description: Number of spare devices for the RAID${LEVEL} array:
+
+Template: partman-md/raidsparedevs
+Type: multiselect
+Choices: ${PARTITIONS}
+# :sl3:
+_Description: Spare devices for the RAID${LEVEL} array:
+ You have chosen to create a RAID${LEVEL} array with ${COUNT} spare devices.
+ .
+ Please choose which partitions will be used as spare devices.
+ You may choose up to ${COUNT} partitions. If you choose less than ${COUNT}
+ devices, the remaining partitions will be added to the array as "missing".
+ You will be able to add them to the array later.
+
+Template: partman-md/notenoughparts
+Type: error
+# :sl3:
+_Description: Not enough RAID partitions available
+ There are not enough RAID partitions available for your selected
+ configuration. You have ${NUM_PART} RAID partitions available but
+ your configuration requires ${REQUIRED} partitions.
+
+Template: partman-md/raid10layout
+Type: string
+# :sl3:
+_Description: Layout of the RAID10 array:
+ The layout must be n, o, or f (arrangement of the copies) followed
+ by a number (number of copies of each chunk). The number must be
+ smaller or equal to the number of active devices.
+ .
+ The letter is the arrangement of the copies:
+ n - near copies: Multiple copies of one data block are at similar
+ offsets in different devices.
+ f - far copies: Multiple copies have very different offsets
+ o - offset copies: Rather than the chunks being duplicated within a
+ stripe, whole stripes are duplicated but are rotated by one
+ device so duplicate blocks are on different devices.
+ .
+ NOTE: this setting cannot be changed later.
+
+Template: partman-md/deletemenu
+Type: select
+Choices: ${DEVICES}
+# :sl3:
+_Description: Software RAID device to be deleted:
+ Deleting a software RAID device will stop it and clear the superblock of
+ all its components.
+ .
+ Please note this will not immediately allow you to reuse the partitions or
+ devices in a new software RAID device. The array will however be unusable
+ after the deletion.
+ .
+ If you select a device for deletion, you will get some information about it
+ and you will be given the option of aborting this operation.
+
+Template: partman-md/delete_no_md
+Type: error
+# :sl3:
+_Description: No software RAID devices available
+ No software RAID devices are available for deletion.
+
+Template: partman-md/deleteverify
+Type: boolean
+Default: false
+# :sl3:
+#flag:translate!:4
+_Description: Really delete this software RAID device?
+ Please confirm whether you really want to delete the following software
+ RAID device:
+ .
+ Device: ${DEVICE}
+ Type: ${TYPE}
+ Component devices:
+ .
+ ${DEVICES}
+
+Template: partman-md/deletefailed
+Type: error
+# :sl3:
+_Description: Failed to delete the software RAID device
+ There was an error deleting the software RAID device. It may be in use.
+
Template: partman-md/confirm
Type: boolean
Default: false
=== modified file 'debian/rules'
--- debian/rules 2008-07-31 00:18:50 +0000
+++ debian/rules 2009-07-09 15:39:30 +0000
@@ -25,6 +25,7 @@ install: build
debian/install-rc init.d
debian/install-rc update.d
dh_install lib lib/partman
+ dh_install finish-install.d usr/lib
binary-indep: build install
dh_testdir
=== added directory 'finish-install.d'
=== added file 'finish-install.d/65partman-md'
--- finish-install.d/65partman-md 1970-01-01 00:00:00 +0000
+++ finish-install.d/65partman-md 2009-07-09 22:00:32 +0000
@@ -0,0 +1,11 @@
+#!/bin/sh
+CF=/target/etc/mdadm/mdadm.conf
+if [ ! -s "$CF" ] && [ -e /proc/mdstat ] && \
+ grep ^md /proc/mdstat >/dev/null; then
+ mkdir -p /target/etc/mdadm
+ echo "# Autogenerated by partman-md. See mdadm.conf(5) for more details on this file." > /etc/mdadm.conf
+ echo "DEVICE partitions" >> $CF
+ chroot /target mount /proc
+ chroot /target mdadm --detail --scan >> $CF
+ chroot /target umount /proc
+fi
=== added file 'lib/md-base.sh'
--- lib/md-base.sh 1970-01-01 00:00:00 +0000
+++ lib/md-base.sh 2009-07-09 21:39:19 +0000
@@ -0,0 +1,118 @@
+. /lib/partman/lib/base.sh
+
+# Translate device from /proc/mdstat (mdX) to device node
+md_devnode () {
+ local num=$(echo $1 | sed -e "s/^md//")
+
+ # Also handle the case where the first does not exist
+ if [ -b /dev/md/$num ]; then
+ echo /dev/md/$num
+ elif [ -b /dev/md$num ]; then
+ echo /dev/md$num
+ else
+ return 1
+ fi
+}
+
+md_get_level () {
+ echo $(mdadm -Q --detail $1 | grep "Raid Level" | sed "s/.*: //")
+}
+
+md_get_devices () {
+ local device
+ MD_DEVICES=""
+ for device in $(grep ^md /proc/mdstat | \
+ sed -e 's/^\(md.*\) : .*/\1/'); do
+ local mddev=$(md_devnode $device) || return 1
+ local mdtype=$(md_get_level $mddev)
+ MD_DEVICES="${MD_DEVICES:+$MD_DEVICES, }${device}_$mdtype"
+ done
+}
+
+md_get_partitions () {
+ local dev method
+
+ PARTITIONS=""
+
+ for dev in $DEVICES/*; do
+ [ -d "$dev" ] || continue
+ cd $dev
+ open_dialog PARTITIONS
+ while { read_line num id size type fs path name; [ "$id" ]; }; do
+ [ -f $id/method ] || continue
+ method=$(cat $id/method)
+ if [ "$method" = raid ]; then
+ local mappedpath="$(mapdevfs "$path")"
+ # Exclude partitions that are already part
+ # of a RAID set
+ if ! egrep -q "(${path#/dev/}|${mappedpath#/dev/})" /proc/mdstat; then
+ echo "$mappedpath"
+ fi
+ fi
+ done
+ close_dialog
+ done
+}
+
+# Converts a list of space (or newline) separated values to comma separated values
+# TODO: duplication from partman-lvm
+ssv_to_csv () {
+ local csv value
+
+ csv=""
+ for value in $1; do
+ if [ -z "$csv" ]; then
+ csv="$value"
+ else
+ csv="$csv, $value"
+ fi
+ done
+ echo "$csv"
+}
+
+# Converts a list of comma separated values to space separated values
+# TODO: duplication from partman-lvm
+csv_to_ssv () {
+ echo "$1" | sed -e 's/ *, */ /g'
+}
+
+md_db_get_number () {
+ local question="$1"
+ local min="$2"
+ local max="$3"
+ while :; do
+ db_input critical "$question"
+ db_go || return $?
+ db_get "$question"
+ # Figure out if the user entered a number
+ RET="$(echo "$RET" | sed 's/[[:space:]]//g')"
+ if [ "$RET" ] && [ "$RET" -ge "$min" ] && [ "$RET" -le "$max" ]; then
+ break
+ fi
+ done
+ return 0
+}
+
+# Find the next available MD device number
+md_next_device_number () {
+ local md_num="$(grep ^md /proc/mdstat | \
+ sed -e 's/^md\(.*\) : active .*/\1/' | sort | tail -n1)"
+ if [ -z "$md_num" ]; then
+ md_num=0
+ else
+ md_num="$(($md_num + 1))"
+ fi
+ echo "$md_num"
+}
+
+md_lock_devices () {
+ local name dev
+ name="$1"
+ shift
+
+ db_subst partman-md/text/in_use DEVICE "$name"
+ db_metaget partman-md/text/in_use description
+ for dev; do
+ partman_lock_unit "$dev" "$RET"
+ done
+}
Reply to: