source: trunk/packages/invirt-remote/host/usr/sbin/invirt-janitor @ 2437

Last change on this file since 2437 was 2437, checked in by broder, 15 years ago

In the invirt-janitor, ignore errors from the dd.

In the normal case, it's erroring out because of ENOSPC, but its
return code isn't useful enough to make sure that's what happened.

  • Property svn:executable set to *
File size: 3.4 KB
Line 
1#!/usr/bin/python
2
3"""Clean-up after people's deleted VMs.
4
5The Invirt janitor goes through and finds virtual disk images that
6users have requested we delete. For their privacy, it writes over the
7entire disk with /dev/zero, then removes the logical volume, restoring
8the space to the pool.
9
10A request is indicated to the janitor by creating a file in
11/var/lib/invirt-remote/cleanup/ corresponding to the name of the LV to
12delete. The janitor notices these requests using inotify.
13"""
14
15
16import os
17import subprocess
18import syslog
19import traceback
20
21import pyinotify
22
23
24_JANITOR_DIR = '/var/lib/invirt-remote/cleanup'
25
26
27def cleanup():
28    """Actually cleanup deleted LVs.
29
30    When triggered, continue to iterate over cleanup queue files,
31    deleting LVs one at a time, until there are no more pending
32    cleanups.
33    """
34    while True:
35        lvs = os.listdir(_JANITOR_DIR)
36        if not lvs:
37            break
38
39        lv = lvs.pop()
40        lv_path = '/dev/xenvg/%s' % lv
41
42        try:
43            syslog.syslog(syslog.LOG_INFO, "Cleaning up LV '%s'" % lv_path)
44
45            # In a perfect world, this should be erroring out with
46            # ENOSPC, so we ignore errors
47            subprocess.call(['/usr/bin/ionice',
48                             '-c', '2',
49                             '-n', '7',
50                             '/bin/dd',
51                             'if=/dev/zero',
52                             'of=%s' % lv_path,
53                             'bs=1M'])
54
55            # Ignore any errors here, because there's really just not
56            # anything we can do.
57            subprocess.call(['/sbin/lvchange', '-a', 'n', lv_path])
58            subprocess.call(['/sbin/lvchange', '-a', 'ey', lv_path])
59            subprocess.check_call(['/sbin/lvremove', '--force', lv_path])
60
61            syslog.syslog(syslog.LOG_INFO, "Successfully cleaned up LV '%s'" % lv_path)
62        except:
63            syslog.syslog(syslog.LOG_ERR, "Error cleaning up LV '%s':" % lv_path)
64
65            for line in traceback.format_exc().split('\n'):
66                syslog.syslog(syslog.LOG_ERR, line)
67        finally:
68            # Regardless of what happens, we always want to remove the
69            # cleanup queue file, because even if there's an error, we
70            # don't want to waste time wiping the same disk repeatedly
71            os.unlink(os.path.join(_JANITOR_DIR, lv))
72
73
74class Janitor(pyinotify.ProcessEvent):
75    """Process inotify events by wiping and deleting LVs.
76
77    The Janitor class receives inotify events when a new file is
78    created in the state directory.
79    """
80    def process_IN_CREATE(self, event):
81        """Handle a created file or directory.
82
83        When an IN_CREATE event comes in, trigger a cleanup.
84        """
85        cleanup()
86
87
88def main():
89    """Initialize the inotifications and start the main loop."""
90    syslog.openlog('invirt-janitor', syslog.LOG_PID, syslog.LOG_DAEMON)
91
92    watch_manager = pyinotify.WatchManager()
93    janitor = Janitor()
94    notifier = pyinotify.Notifier(watch_manager, janitor)
95    watch_manager.add_watch(_JANITOR_DIR,
96                            pyinotify.EventsCodes.ALL_FLAGS['IN_CREATE'])
97
98    # Before inotifying, run any pending cleanups; otherwise we won't
99    # get notified for them.
100    cleanup()
101
102    while True:
103        notifier.process_events()
104        if notifier.check_events():
105            notifier.read_events()
106
107
108if __name__ == '__main__':
109    main()
Note: See TracBrowser for help on using the repository browser.