lvmanip: handle second-segment failures
[invirt/scripts/pv-fixup.git] / pv-fixup
index 0609971..d5c0830 100644 (file)
--- a/pv-fixup
+++ b/pv-fixup
@@ -8,15 +8,15 @@ TMPDM=tmpfoo
 TMPDEV=/dev/mapper/$TMPDM
 TMPDM2=tmpbar
 TMPDEV2=/dev/mapper/$TMPDM2
-METADATASIZE=3.5m
+METADATASIZE=8128k
 
 #  - pvresize the old PV to half the space
 pvresize --setphysicalvolumesize=${HALFSIZETiB}t $DISK
 
 #  - dmsetup create a device in the latter half
 dmstart=$(python -c "print int(($HALFSIZETiB + 0.01) * 1024 * 1024 * 1024 * 2)")
-dmlen=$(python -c "print int(($HALFSIZETiB - 0.02) * 1024 * 1024 * 1024 * 2)")
-#foreach host:
+dmlen=$(python -c "print int(($HALFSIZETiB - 0.03) * 1024 * 1024 * 1024 * 2)")
+#Foreach host:
 dmsetup create $TMPDM --table "0 $dmlen linear $DISK $dmstart"
 #done
 
@@ -27,46 +27,83 @@ pvcreate $TMPDEV
 vgextend $VG $TMPDEV
 
 #  - pvmove all the LVs to the temporary PV
-#    (something like
-#      for lv in $(LVs for running VMs on this host); do
-#        #some lvchange -a commands
-#        pvmove -n $lv <oldpv> <newpv>
-#        #possibly more lvchange -a to restore old state
-#      done)
+
+yamlkeys () {
+  python -c 'if 1:
+    import yaml, sys
+    mm = yaml.load(sys.stdin.read())
+    for m in sorted(mm.iterkeys()): print m'
+}
+
+lvsleft () {
+  lvs -o name,devices xenvg \
+    | perl -lane "print \$F[0] if (\$F[1] =~ m|$DISK|)"
+}
+
+vmstolvs () {
+  perl -pe 's/^/d_/;s/$/_hda/'
+}
+
+totalsize () {
+  # handy for estimating time; output in GiB; pipe in a list of LVs
+  perl -pe 's.^.xenvg/.' \
+   | xargs lvs -o size --units=g \
+   | perl -lne '$total += $_; END { print $total; }'
+}
 
 movelv () {
-  echo pvmoving $1...
-  lvchange -an $1
-  pvmove -i 10 -n $1 $2
+  echo pvmoving $VG/$1...
+  pvmove -i 10 -n $VG/$1 $2
 }
 
+ssh root@xvm remctl remote web listvms \
+ | yamlkeys \
+ > runningvms
+LVM_SYSTEM_DIR=/root/lvm lvsleft \
+ | grep '^d_.*_hda$' \
+ | grep -v -xf <(vmstolvs <runningvms) \
+ > offvmlvs
+for lv in $(offvmlvs); do
+  LVM_SYSTEM_DIR=/root/lvm movelv $lv $DISK
+done
 #FOREACH host:
-for lv in $(lvs -o lv_name --noheadings $VG); do
-  movelv $VG/$lv $DISK
+for lv in $(invirt-listvms | yamlkeys | vmstolvs \
+             | grep -xf <(LVM_SYSTEM_DIR=/root/lvm lvsleft)); do
+  LVM_SYSTEM_DIR=/root/lvm movelv $lv $DISK
 done
 #done
 
-# hopefully empty:
-lvs $VG -o lv_name,devices | grep $DISK
-# if not, do some more movelv
+ssh root@xvm remctl remote web listvms \
+ | perl -lne 'print if (s/^  cdrom: //)' \
+ > usedcdroms
+LVM_SYSTEM_DIR=/root/lvm lvsleft \
+ | grep ^image_ \
+ | grep -v -xf <(perl -pe "s|/dev/$VG/||" usedcdroms) \
+ > offcdlvs
+for lv in $(offcdlvs); do
+  LVM_SYSTEM_DIR=/root/lvm movelv $lv $DISK
+done
+
+# deal with $(cat usedcdroms)
+# deal with s_* LVs
+# deal with any remaining $(lvsleft)
 
-# This is possible if some LVs were used on more than one host during
-# migration.
+[ -z $(lvsleft) ]
 
 
 #  - pvremove the old PV
-vgreduce $VG $DISK
-pvremove $DISK
+LVM_SYSTEM_DIR=lvm vgreduce $VG $DISK
+dmsetup create $TMPDM2 --table "0 $((2 * 1024 * 20)) linear $DISK 0"
+pvremove $TMPDEV2
 
 #  - pvcreate a new PV in the old space,
 #     with --setphysicalvolumesize <half size>
 #     and with --metadatasize <huge>    (the point of this exercise)
 shortsize=$(python -c "print $HALFSIZETiB - 0.01")t
-dmsetup create $TMPDM2 --table "0 $((2 * 1024 * 4)) linear $DISK 0"
 pvcreate $TMPDEV2 --setphysicalvolumesize $shortsize --metadatasize $METADATASIZE
 dmsetup remove $TMPDM2
 pvscan
-vgextend $VG $DISK
+LVM_SYSTEM_DIR=lvm vgextend $VG $DISK
 
 #  - pvmove all the LVs back