changeset 91:3ed079a7174a

Implement a way to stop a running treepackager.
author Bernhard Herzog <bh@intevation.de>
date Tue, 11 Sep 2007 17:24:56 +0000 (2007-09-11)
parents 6ed1c881ee1b
children 1c74e3b56a63
files bin/telltreepkg.py test/test_packager.py treepkg/packager.py treepkg/readconfig.py
diffstat 4 files changed, 136 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/telltreepkg.py	Tue Sep 11 17:24:56 2007 +0000
@@ -0,0 +1,31 @@
+#! /usr/bin/python2.4
+# Copyright (C) 2007 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh@intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Sends instructions to a running packager"""
+
+import sys
+
+import treepkgcmd
+from treepkg.options import create_parser
+from treepkg.readconfig import read_config
+from treepkg.util import writefile
+
+def main():
+    options, args = create_parser().parse_args()
+
+    if len(args) != 1:
+        print >>sys.stderr, "The command to send to treepkg must be given"
+        sys.exit(1)
+
+    treepkg_opts, packager_opts = read_config(options.config_file)
+
+    filename = treepkg_opts.get("instructions_file")
+    if filename:
+        writefile(filename, args[0])
+
+main()
--- a/test/test_packager.py	Tue Sep 11 13:58:28 2007 +0000
+++ b/test/test_packager.py	Tue Sep 11 17:24:56 2007 +0000
@@ -131,6 +131,75 @@
                           ["testpkg_2-kk1_all.deb",
                            "testpkg_2-kk1_i386.changes"])
 
+class StoppingPackager(treepkg.packager.RevisionPackager):
+
+    def package(self):
+        pass
+
+class StoppingTrack(treepkg.packager.PackageTrack):
+
+    def __init__(self, do_package, do_stop, instructions_file, name, trackdir):
+        super(StoppingTrack, self).__init__(name, trackdir, "", "", "",
+                                            "", "")
+        self.do_package = do_package
+        self.do_stop = do_stop
+        self.instructions_file = instructions_file
+
+    def package_if_updated(self, revision):
+        if self.do_stop:
+            writefile(self.instructions_file, "stop")
+        if self.do_package:
+            return StoppingPackager(self, 1)
+        else:
+            return None
+
+
+class TestPackageGroupStop(unittest.TestCase, FileTestMixin):
+
+    def setUp(self):
+        self.trackdir = self.create_temp_dir(self.id() + "-track")
+        self.instructions_file = os.path.join(self.trackdir, "instructions")
+
+    def group(self, do_package=True, do_stop=True):
+        return PackagerGroup([StoppingTrack(do_package, do_stop,
+                                            self.instructions_file,
+                                            "test", self.trackdir)],
+                             1, instructions_file=self.instructions_file)
+
+    def test_stop(self):
+        group = self.group(do_package=True, do_stop=True)
+        self.failUnless(group.check_package_tracks())
+
+    def test_no_stop(self):
+        group = self.group(do_package=True, do_stop=False)
+        self.failIf(group.check_package_tracks())
+
+    def test_instruction_removal(self):
+        # run once with stopping
+        group = self.group(do_package=True, do_stop=True)
+        self.failUnless(group.check_package_tracks())
+
+        # run again without stopping but using the same files.  The
+        # instructions file should be removed automatically
+        group = self.group(do_package=True, do_stop=False)
+        self.failIf(group.check_package_tracks())
+
+    def test_stopping_without_packaging(self):
+        group = self.group(do_package=False, do_stop=True)
+        self.failUnless(group.check_package_tracks())
+
+    def test_stopping_between_checks(self):
+        group = self.group(do_package=False, do_stop=False)
+        # run check_package_tracks once
+        self.failIf(group.check_package_tracks())
+
+        # tell treepkg to stop
+        writefile(self.instructions_file, "stop")
+
+        # check again.  The check_package_tracks() may remove the
+        # instructions file but it must do so only the first time
+        self.failUnless(group.check_package_tracks())
+
 
 class TestPackageTrack(unittest.TestCase, FileTestMixin):
 
--- a/treepkg/packager.py	Tue Sep 11 13:58:28 2007 +0000
+++ b/treepkg/packager.py	Tue Sep 11 17:24:56 2007 +0000
@@ -396,10 +396,13 @@
 
 class PackagerGroup(object):
 
-    def __init__(self, package_tracks, check_interval, revision=None):
+    def __init__(self, package_tracks, check_interval, revision=None,
+                 instructions_file=None):
         self.package_tracks = package_tracks
         self.check_interval = check_interval
         self.revision = revision
+        self.instructions_file = instructions_file
+        self.instructions_file_removed = False
 
     def run(self):
         """Runs the packager group indefinitely"""
@@ -409,7 +412,8 @@
         while 1:
             now = time.time()
             if now > last_check + self.check_interval:
-                self.check_package_tracks()
+                if self.check_package_tracks():
+                    break
                 last_check = now
                 next_check = now + self.check_interval
                 to_sleep = next_check - time.time()
@@ -420,14 +424,21 @@
                     time.sleep(to_sleep)
                 else:
                     logging.info("Next check now")
+                if self.should_stop():
+                    logging.info("Received stop instruction.  Stopping.")
+                    return
 
     def check_package_tracks(self):
         logging.info("Checking package tracks")
+        self.clear_instruction()
         for track in self.package_tracks:
             try:
                 packager = track.package_if_updated(revision=self.revision)
                 if packager:
                     packager.package()
+                if self.should_stop():
+                    logging.info("Received stop instruction.  Stopping.")
+                    return True
             except:
                 logging.exception("An error occurred while"
                                   " checking packager track %r", track.name)
@@ -435,3 +446,25 @@
 
     def get_package_tracks(self):
         return self.package_tracks
+
+    def read_instruction(self):
+        if not self.instructions_file:
+            return ""
+        try:
+            f = open(self.instructions_file)
+        except (IOError, OSError):
+            return ""
+        try:
+            return f.read().strip()
+        finally:
+            f.close()
+            self.clear_instruction()
+
+    def clear_instruction(self, force=False):
+        if self.instructions_file and (not self.instructions_file_removed
+                                       or force):
+            util.writefile(self.instructions_file, "")
+            self.instructions_file_removed = True
+
+    def should_stop(self):
+        return self.read_instruction() == "stop"
--- a/treepkg/readconfig.py	Tue Sep 11 13:58:28 2007 +0000
+++ b/treepkg/readconfig.py	Tue Sep 11 17:24:56 2007 +0000
@@ -23,6 +23,7 @@
 
 treepkg_desc = [
     ("check_interval", int),
+    "instructions_file",
     ]
 
 
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)