Add DB/LVM disk consistency checker and web/checkdisks remctl 0.4.12
authorMitchell E Berger <mitchb@mit.edu>
Wed, 9 Nov 2011 02:58:02 +0000 (21:58 -0500)
committerMitchell E Berger <mitchb@mit.edu>
Wed, 9 Nov 2011 03:20:20 +0000 (22:20 -0500)
debian/changelog
debian/control
host/usr/sbin/invirt-check-disks [new file with mode: 0755]
host/usr/sbin/invirt-remote
server/usr/sbin/invirt-remote-proxy

index 1ad3152..32bc4a7 100644 (file)
@@ -1,3 +1,9 @@
+invirt-remote (0.4.12) unstable; urgency=low
+
+  * Add DB/LVM disk consistency checker and web/checkdisks remctl
+
+ -- Mitchell Berger <mitchb@mit.edu>  Tue, 08 Nov 2011 21:52:00 -0500
+
 invirt-remote (0.4.11) unstable; urgency=low
 
   * Don't let the janitor try to cleanup nonexistent LVs
index 69dceb9..4d8bd96 100644 (file)
@@ -22,8 +22,8 @@ Description: Invirt remote-control server
 Package: invirt-remote-host
 Architecture: all
 Depends: ${misc:Depends}, daemon, remctl-server, invirt-console-host,
- invirt-vnc-server, python-cjson, python-pyinotify, python-yaml,
- util-linux, openbsd-inetd
+ invirt-vnc-server, python-cjson, python-pyinotify, python-sqlalchemy,
+ python-yaml, util-linux, openbsd-inetd
 Description: Installs the Invirt host remctl configuration
  This is the remctl configuration for an Invirt host. It allows any
  commands to be run from the Invirt remote server
diff --git a/host/usr/sbin/invirt-check-disks b/host/usr/sbin/invirt-check-disks
new file mode 100755 (executable)
index 0000000..b118dfa
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+
+from invirt import database as db
+from invirt.config import structs as config
+import sqlalchemy as sa
+from subprocess import Popen, PIPE
+
+prefix = 'd_'
+
+# First figure out what the database thinks our sets of disks and sizes are
+db.connect()
+s = sa.sql.select([db.machine_table.c.name, db.disk_table.c.guest_device_name,
+                   db.disk_table.c.size],
+                  db.machine_table.c.machine_id == db.disk_table.c.machine_id,
+                  [db.machine_table, db.disk_table])
+dbresult = db.session.execute(s)
+db_disks = {}
+for (machine, device, size) in dbresult.fetchall():
+    db_disks['d_' + machine + '_' + device] = int(size)
+
+# Now figure out what the disk images actually in existence look like
+p = Popen(['/sbin/lvs', '--noheadings', '-o', 'lv_name,lv_size', '--units', 'm',
+           '--unbuffered', '--nosuffix', '--separator', ':', config.lvm.vg],
+          stdout=PIPE)
+lvresult = p.communicate()[0]
+lv_disks = {}
+for lv in lvresult.split():
+    (lvname, size) = lv.split(':')
+    if not lvname.startswith(prefix):
+        continue
+    # We only want the whole number of MiB, to match the database
+    lv_disks[lvname] = int(float(size))
+
+missing_disks = []
+orphaned_disks = []
+size_discrepancies = []
+
+for disk in db_disks:
+    if disk not in lv_disks:
+        missing_disks.append(disk)
+    elif db_disks[disk] != lv_disks[disk]:
+        size_discrepancies.append(disk)
+for disk in lv_disks:
+    if disk not in db_disks:
+        orphaned_disks.append(disk)
+
+if missing_disks:
+    print '===== The following disks are in the DB but the LVs do not exist'
+    missing_disks.sort()
+    for disk in missing_disks:
+        print disk.ljust(45) + 'DB: %s' % str(db_disks[disk]).rjust(6)
+    print '\n'
+if orphaned_disks:
+    print '===== The following LVs exist but are not assigned to a VM'
+    orphaned_disks.sort()
+    for disk in orphaned_disks:
+        print disk.ljust(59) + 'LVM: %s' % str(lv_disks[disk]).rjust(6)
+    print '\n'
+if size_discrepancies:
+    print '===== The following disks have different sizes in the DB and LVM'
+    size_discrepancies.sort()
+    for disk in size_discrepancies:
+        print disk.ljust(45) +\
+              'DB: %s    LVM: %s' % (str(db_disks[disk]).rjust(6),
+                                     str(lv_disks[disk]).rjust(6))
+    print '\n'
+print 'There are %i inconsistencies between the DB and LVM at this time.' %\
+      (missing_disks.__len__() +
+       orphaned_disks.__len__() +
+       size_discrepancies.__len__())
+
index ceb8182..5168da8 100755 (executable)
@@ -26,6 +26,9 @@ case "$TYPE" in
             vnccert)
                 COMMAND=/usr/bin/invirt-vnc-getcert
                 ;;
+            checkdisks)
+                COMMAND=/usr/sbin/invirt-check-disks
+                ;;
             *)
                 echo "ERROR: invalid subcommand"
                 exit 34
index b70eb4d..ca7dcf8 100755 (executable)
@@ -18,7 +18,7 @@ case "$TYPE/$SERVICE" in
         invirt-remote-vnccert "$@" ;;
     web/availability | web/avail )
         invirt-remote-availability "$@" ;;
-    web/lvcreate | web/lvremove | web/lvrename | web/lvresize | web/vgcapacity )
+    web/lvcreate | web/lvremove | web/lvrename | web/lvresize | web/vgcapacity | web/checkdisks )
         invirt-remote-lvm "$SERVICE" "$@"
         ;;
     control/help )