Parcourir la source

Merge #322

git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@3052 e5f2f494-b856-4b98-b285-d166d9295462
Michal Vaner il y a 14 ans
Parent
commit
af8ede1820

+ 22 - 0
configure.ac

@@ -48,6 +48,12 @@ if test $enable_shared = no; then
 	AC_MSG_ERROR([BIND 10 requires shared libraries to be built])
 fi
 
+# allow configuring without setproctitle.
+AC_ARG_ENABLE(setproctitle-check,
+AC_HELP_STRING([--disable-setproctitle-check],
+  [do not check for python setproctitle module (used to give nice names to python processes)]),
+  setproctitle_check=$enableval, setproctitle_check=yes)
+
 # OS dependent configuration
 SET_ENV_LIBRARY_PATH=no
 ENV_LIBRARY_PATH=LD_LIBRARY_PATH
@@ -162,6 +168,18 @@ fi
 AC_SUBST(PYTHON_LIB)
 LDFLAGS=$LDFLAGS_SAVED
 
+# Check for the setproctitle module
+if test "$setproctitle_check" = "yes" ; then
+    AC_MSG_CHECKING(for setproctitle module)
+    if "$PYTHON" -c 'import setproctitle' 2>/dev/null ; then
+        AC_MSG_RESULT(ok)
+    else
+        AC_MSG_RESULT(missing)
+        AC_MSG_ERROR([Missing setproctitle module. Either install it or provide --disable-setproctitle-check.
+In that case we will continue, but naming of python processes will not work.])
+    fi
+fi
+
 # TODO: check for _sqlite3.py module
 
 # Compiler dependent settings: define some mandatory CXXFLAGS here.
@@ -451,6 +469,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/zonemgr/Makefile
                  src/bin/zonemgr/tests/Makefile
                  src/bin/usermgr/Makefile
+                 src/bin/tests/Makefile
                  src/lib/Makefile
                  src/lib/bench/Makefile
                  src/lib/bench/example/Makefile
@@ -459,6 +478,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/cc/tests/Makefile
                  src/lib/python/Makefile
                  src/lib/python/isc/Makefile
+                 src/lib/python/isc/utils/Makefile
+                 src/lib/python/isc/utils/tests/Makefile
                  src/lib/python/isc/datasrc/Makefile
                  src/lib/python/isc/cc/Makefile
                  src/lib/python/isc/cc/tests/Makefile
@@ -517,6 +538,7 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
            src/bin/msgq/run_msgq.sh
            src/bin/auth/auth.spec.pre
            src/bin/auth/spec_config.h.pre
+           src/bin/tests/process_rename_test.py
            src/lib/config/tests/data_def_unittests_config.h
            src/lib/python/isc/config/tests/config_test
            src/lib/python/isc/cc/tests/cc_test

+ 4 - 1
src/bin/Makefile.am

@@ -1 +1,4 @@
-SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout usermgr zonemgr
+SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout \
+	usermgr zonemgr tests
+
+check-recursive: all-recursive

+ 20 - 2
src/bin/bind10/bind10.8

@@ -1,7 +1,7 @@
 '\" t
 .\"     Title: bind10
 .\"    Author: [see the "AUTHORS" section]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.76.0 <http://docbook.sf.net/>
 .\"      Date: July 29, 2010
 .\"    Manual: BIND10
 .\"    Source: BIND10
@@ -9,6 +9,15 @@
 .\"
 .TH "BIND10" "8" "July 29, 2010" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
 .\" disable hyphenation
@@ -22,7 +31,7 @@
 bind10 \- BIND 10 boss process
 .SH "SYNOPSIS"
 .HP \w'\fBbind10\fR\ 'u
-\fBbind10\fR [\fB\-a\ \fR\fB\fIaddress\fR\fR] [\fB\-m\ \fR\fB\fIfile\fR\fR] [\fB\-n\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-\-address\ \fR\fB\fIaddress\fR\fR] [\fB\-\-msgq\-socket\-file\ \fR\fB\fIfile\fR\fR] [\fB\-\-no\-cache\fR] [\fB\-\-port\ \fR\fB\fInumber\fR\fR] [\fB\-\-user\ \fR\fB\fIuser\fR\fR] [\fB\-\-verbose\fR]
+\fBbind10\fR [\fB\-a\ \fR\fB\fIaddress\fR\fR] [\fB\-m\ \fR\fB\fIfile\fR\fR] [\fB\-n\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-\-address\ \fR\fB\fIaddress\fR\fR] [\fB\-\-msgq\-socket\-file\ \fR\fB\fIfile\fR\fR] [\fB\-\-no\-cache\fR] [\fB\-\-port\ \fR\fB\fInumber\fR\fR] [\fB\-\-user\ \fR\fB\fIuser\fR\fR] [\fB\-\-pretty\-name\ \fR\fB\fIname\fR\fR] [\fB\-\-verbose\fR]
 .SH "DESCRIPTION"
 .PP
 The
@@ -86,6 +95,15 @@ to run as\&.
 must be initially ran as the root user to use this option\&. The default is to run as the current user\&.
 .RE
 .PP
+\fB\-\-pretty\-name \fR\fB\fIname\fR\fR
+.RS 4
+The name this process should have in tools like
+\fBps\fR
+or
+\fBtop\fR\&. This is handy if you have multiple versions/installations of
+\fBbind10\fR\&.
+.RE
+.PP
 \fB\-v\fR, \fB\-\-verbose\fR
 .RS 4
 Display more about what is going on for

+ 12 - 1
src/bin/bind10/bind10.py.in

@@ -63,6 +63,10 @@ import pwd
 import posix
 
 import isc.cc
+import isc.utils.process
+
+# Assign this process some longer name
+isc.utils.process.rename(sys.argv[0])
 
 # This is the version that gets displayed to the user.
 # The VERSION string consists of the module name, the module version
@@ -620,7 +624,11 @@ def check_addr(option, opt_str, value, parser):
         parser.values.address = value
     else:
         raise OptionValueError("Unknown option " + opt_str)
-  
+
+def process_rename(option, opt_str, value, parser):
+    """Function that renames the process if it is requested by a option."""
+    isc.utils.process.rename(value)
+
 def main():
     global options
     global boss_of_bind
@@ -646,6 +654,9 @@ def main():
                       help="Change user after startup (must run as root)")
     parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                       help="display more about what is going on")
+    parser.add_option("--pretty-name", type="string", action="callback",
+                      callback=process_rename,
+                      help="Set the process name (displayed in ps, top, ...)")
     (options, args) = parser.parse_args()
     if args:
         parser.print_help()

+ 12 - 0
src/bin/bind10/bind10.xml

@@ -56,6 +56,7 @@
       <arg><option>--no-cache</option></arg>
       <arg><option>--port <replaceable>number</replaceable></option></arg>
       <arg><option>--user <replaceable>user</replaceable></option></arg>
+      <arg><option>--pretty-name <replaceable>name</replaceable></option></arg>
       <arg><option>--verbose</option></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -149,6 +150,17 @@
       </varlistentry>
 
       <varlistentry>
+        <term><option>--pretty-name <replaceable>name</replaceable></option></term>
+
+        <listitem>
+          <para>The name this process should have in tools like
+          <command>ps</command> or <command>top</command>. This
+          is handy if you have multiple versions/installations
+          of <command>bind10</command>.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><option>-v</option>, <option>--verbose</option></term>
         <listitem>
 	  <para>Display more about what is going on for

+ 23 - 0
src/bin/bind10/tests/args_test.py

@@ -130,5 +130,28 @@ class TestBossArgs(unittest.TestCase):
         x = bob.wait()
         self.assertTrue(bob.wait() == 0)
 
+    def testPrettyName(self):
+        """Try the --pretty-name option."""
+        CMD_PRETTY_NAME = b'bob-name-test'
+        bob = subprocess.Popen(args=(BIND10_EXE, '--pretty-name',
+            CMD_PRETTY_NAME), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+        started_ok = self._waitForString(bob, '[bind10] BIND 10 started')
+        self.assertTrue(started_ok)
+        ps = subprocess.Popen(args=("ps", "axo", "pid,comm"),
+                              stdout=subprocess.PIPE)
+        s = ps.stdout.readline()
+        command = None
+        while True:
+            s = ps.stdout.readline()
+            if s == '': break
+            (pid,comm) = s.split(None, 1)
+            if int(pid) == bob.pid:
+                command = comm
+                break
+        self.assertEqual(command, CMD_PRETTY_NAME + b'\n')
+        time.sleep(0.1)
+        bob.terminate()
+        bob.wait()
+
 if __name__ == '__main__':
     unittest.main()

+ 3 - 0
src/bin/bindctl/bindctl-source.py.in

@@ -24,6 +24,9 @@ from bindctl.moduleinfo import *
 from bindctl.bindcmd import *
 import pprint
 from optparse import OptionParser, OptionValueError
+import isc.utils.process
+
+isc.utils.process.rename()
 
 __version__ = 'Bindctl'
 

+ 3 - 0
src/bin/cfgmgr/b10-cfgmgr.py.in

@@ -21,9 +21,12 @@ import sys; sys.path.append ('@@PYTHONPATH@@')
 
 from isc.config.cfgmgr import ConfigManager, ConfigManagerDataReadError
 from isc.cc import SessionError
+import isc.utils.process
 import signal
 import os
 
+isc.utils.process.rename()
+
 # If B10_FROM_SOURCE is set in the environment, we use data files
 # from a directory relative to that, otherwise we use the ones
 # installed on the system

+ 3 - 0
src/bin/cmdctl/cmdctl.py.in

@@ -42,6 +42,7 @@ import random
 import time
 import signal
 from isc.config import ccsession
+import isc.utils.process
 from optparse import OptionParser, OptionValueError
 from hashlib import sha1
 try:
@@ -49,6 +50,8 @@ try:
 except ImportError:
     import dummy_threading as threading
 
+isc.utils.process.rename()
+
 __version__ = 'BIND10'
 URL_PATTERN = re.compile('/([\w]+)(?:/([\w]+))?/?')
 CONFIG_DATA_URL = 'config_data'

+ 4 - 0
src/bin/loadzone/b10-loadzone.py.in

@@ -18,9 +18,13 @@
 import sys; sys.path.append ('@@PYTHONPATH@@')
 import re, getopt
 import isc.datasrc
+import isc.utils.process
 from isc.datasrc.master import MasterFile
 import time
 import os
+
+isc.utils.process.rename()
+
 #########################################################################
 # usage: print usage note and exit
 #########################################################################

+ 3 - 0
src/bin/msgq/msgq.py.in

@@ -31,9 +31,12 @@ import select
 import pprint
 import random
 from optparse import OptionParser, OptionValueError
+import isc.utils.process
 
 import isc.cc
 
+isc.utils.process.rename()
+
 # This is the version that gets displayed to the user.
 __version__ = "v20091030 (Paving the DNS Parking Lot)"
 

+ 12 - 0
src/bin/tests/Makefile.am

@@ -0,0 +1,12 @@
+PYTESTS = process_rename_test.py
+EXTRA_DIST = $(PYTESTS)
+
+# later will have configure option to choose this, like: coverage run --branch
+PYCOVERAGE = $(PYTHON)
+# test using command-line arguments, so use check-local target instead of TESTS
+check-local:
+	for pytest in $(PYTESTS) ; do \
+	echo Running test: $$pytest ; \
+	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+	done

+ 3 - 0
src/bin/tests/README

@@ -0,0 +1,3 @@
+This directory does not contain any code a user might want to run. It contains
+"global" tests -- tests that are not specific to a single library or program.
+Do not expect to find b10-tests here, there's no such program.

+ 61 - 0
src/bin/tests/process_rename_test.py.in

@@ -0,0 +1,61 @@
+# Copyright (C) 2010  CZ NIC
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""Tests to see if every python process renames itself."""
+import unittest
+import os
+import os.path
+import isc.utils.process
+import re
+
+class TestRename(unittest.TestCase):
+    """Test scanning all python scripts if they rename themself."""
+    def __scan(self, directory, script, fun):
+        # Scan one script if it contains call to the renaming function
+        filename = os.path.join(directory, script)
+        data = ''.join(open(filename).readlines())
+        prettyname = 'src' + filename[filename.rfind('../') + 2:]
+        self.assertTrue(fun.search(data),
+            "Didn't find a call to isc.utils.process.rename in " + prettyname)
+
+    def test_calls(self):
+        """
+        Test if every script renames itself.
+
+        Scan all Makefile.in and look for scripts.
+        Then scan them by looking at the source text
+        (without actually running them)
+        """
+        # Regexp to find all the *_SCRIPTS = something lines,
+        # including line continuations (backslash and newline)
+        lines = re.compile(r'^\w+_SCRIPTS\s*=\s*((.|\\\n)*)$',
+            re.MULTILINE)
+        # Script name regular expression
+        scripts = re.compile(r'((\w|[-.0-9])+)')
+        # Line with the call
+        fun = re.compile(r'^\s*isc\.utils\.process\.rename\s*\(.*\)\s*(|#.*)$',
+            re.MULTILINE)
+
+        # Find all Makefile.in and extract names of scripts
+        for (d, _, fs) in os.walk('@top_srcdir@'):
+            if 'Makefile.in' in fs:
+                makefile = ''.join(open(os.path.join(d,
+                    "Makefile.in")).readlines())
+                for (var, _) in lines.findall(makefile):
+                    for (script, _) in scripts.findall(var):
+                        self.__scan(d, script, fun)
+
+if __name__ == "__main__":
+    unittest.main()

+ 3 - 0
src/bin/usermgr/b10-cmdctl-usermgr.py.in

@@ -25,6 +25,9 @@ import csv
 import getpass
 import getopt
 import sys
+import isc.utils.process
+
+isc.utils.process.rename()
 
 VERSION_NUMBER = 'bind10'
 DEFAULT_FILE = 'cmdctl-accounts.csv'

+ 3 - 0
src/bin/xfrin/xfrin.py.in

@@ -29,6 +29,7 @@ import random
 from optparse import OptionParser, OptionValueError
 from isc.config.ccsession import *
 from isc.notify import notify_out
+import isc.utils.process
 try:
     from pydnspp import *
 except ImportError as e:
@@ -36,6 +37,8 @@ except ImportError as e:
     # must keep running, so we warn about it and move forward.
     sys.stderr.write('[b10-xfrin] failed to import DNS module: %s\n' % str(e))
 
+isc.utils.process.rename()
+
 # If B10_FROM_BUILD is set in the environment, we use data files
 # from a directory relative to that, otherwise we use the ones
 # installed on the system

+ 3 - 0
src/bin/xfrout/xfrout.py.in

@@ -29,6 +29,7 @@ from isc.config.ccsession import *
 from isc.log.log import *
 from isc.cc import SessionError, SessionTimeout
 from isc.notify import notify_out
+import isc.utils.process
 import socket
 import select
 import errno
@@ -41,6 +42,8 @@ except ImportError as e:
     # must keep running, so we warn about it and move forward.
     sys.stderr.write('[b10-xfrout] failed to import DNS or XFR module: %s\n' % str(e))
 
+isc.utils.process.rename()
+
 if "B10_FROM_BUILD" in os.environ:
     SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/xfrout"
     AUTH_SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/auth"

+ 3 - 0
src/bin/zonemgr/zonemgr.py.in

@@ -36,6 +36,9 @@ import errno
 from isc.datasrc import sqlite3_ds
 from optparse import OptionParser, OptionValueError
 from isc.config.ccsession import *
+import isc.utils.process
+
+isc.utils.process.rename()
 
 # If B10_FROM_BUILD is set in the environment, we use data files
 # from a directory relative to that, otherwise we use the ones

+ 1 - 1
src/lib/python/isc/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = datasrc cc config log notify # Util
+SUBDIRS = datasrc cc config log notify utils # Util
 
 python_PYTHON = __init__.py
 

+ 5 - 0
src/lib/python/isc/utils/Makefile.am

@@ -0,0 +1,5 @@
+SUBDIRS = tests
+
+python_PYTHON = __init__.py process.py
+
+pythondir = $(pyexecdir)/isc/utils

+ 0 - 0
src/lib/python/isc/utils/__init__.py


+ 37 - 0
src/lib/python/isc/utils/process.py

@@ -0,0 +1,37 @@
+# Copyright (C) 2010  CZ NIC
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+Module to manipulate the python processes.
+
+It contains only function to rename the process, which is currently
+wrapper around setproctitle library. Does not fail if the setproctitle
+module is missing, but does nothing in that case.
+"""
+try:
+    from setproctitle import setproctitle
+except ImportError:
+    def setproctitle(_): pass
+import sys
+import os.path
+
+"""
+Rename the current process to given name (so it can be found in ps).
+If name is None, use zero'th command line argument.
+"""
+def rename(name=None):
+    if name is None:
+        name = os.path.basename(sys.argv[0])
+    setproctitle(name)

+ 12 - 0
src/lib/python/isc/utils/tests/Makefile.am

@@ -0,0 +1,12 @@
+PYTESTS = process_test.py
+EXTRA_DIST = $(PYTESTS)
+
+# later will have configure option to choose this, like: coverage run --branch
+PYCOVERAGE = $(PYTHON)
+# test using command-line arguments, so use check-local target instead of TESTS
+check-local:
+	for pytest in $(PYTESTS) ; do \
+	echo Running test: $$pytest ; \
+	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
+	$(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+	done

+ 39 - 0
src/lib/python/isc/utils/tests/process_test.py

@@ -0,0 +1,39 @@
+# Copyright (C) 2010  CZ NIC
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""Tests for isc.utils.process."""
+import unittest
+import isc.utils.process
+run_tests = True
+try:
+    import setproctitle
+except ImportError:
+    run_tests = False
+
+class TestRename(unittest.TestCase):
+    """Testcase for isc.process.rename."""
+    def __get_self_name(self):
+        return setproctitle.getproctitle()
+
+    @unittest.skipIf(not run_tests, "Setproctitle not installed, not testing")
+    def test_rename(self):
+        """Test if the renaming function works."""
+        isc.utils.process.rename("rename-test")
+        self.assertEqual("rename-test", self.__get_self_name())
+        isc.utils.process.rename()
+        self.assertEqual("process_test.py", self.__get_self_name())
+
+if __name__ == "__main__":
+    unittest.main()