Parcourir la source

[master] Merge branch 'trac3413' (BIND10/Bundy framework removal)

Conflicts:
	ChangeLog
	configure.ac
	src/bin/cmdctl/Makefile.am
	src/bin/cmdctl/botan-certgen.cc
	src/bin/cmdctl/tests/Makefile.am
	src/bin/cmdctl/tests/botan-certgen_test.py
	src/bin/d2/tests/Makefile.am
	src/bin/d2/tests/d2_test.py
	src/bin/dhcp4/tests/Makefile.am
	src/bin/dhcp6/tests/Makefile.am
	src/bin/tests/process_rename_test.py.in
Tomek Mrugalski il y a 10 ans
Parent
commit
d7b297ac47
100 fichiers modifiés avec 39 ajouts et 15577 suppressions
  1. 8 0
      ChangeLog
  2. 27 284
      configure.ac
  3. 0 1
      m4macros/Makefile.am
  4. 0 20
      m4macros/ax_python_sqlite3.m4
  5. 0 42
      m4macros/ax_sqlite3_for_bind10.m4
  6. 1 3
      src/bin/Makefile.am
  7. 0 6
      src/bin/bind10/.gitignore
  8. 0 64
      src/bin/bind10/Makefile.am
  9. 0 16
      src/bin/bind10/README
  10. 0 14
      src/bin/bind10/TODO
  11. 0 519
      src/bin/bind10/b10-init.xml
  12. 0 11
      src/bin/bind10/bind10.in
  13. 0 76
      src/bin/bind10/bind10.xml
  14. 0 123
      src/bin/bind10/creatorapi.txt
  15. 0 1389
      src/bin/bind10/init.py.in
  16. 0 92
      src/bin/bind10/init.spec
  17. 0 334
      src/bin/bind10/init_messages.mes
  18. 0 49
      src/bin/bind10/run_bind10.sh.in
  19. 0 1
      src/bin/bind10/tests/.gitignore
  20. 0 29
      src/bin/bind10/tests/Makefile.am
  21. 0 172
      src/bin/bind10/tests/args_test.py
  22. 0 2489
      src/bin/bind10/tests/init_test.py.in
  23. 0 4
      src/bin/bindctl/.gitignore
  24. 0 41
      src/bin/bindctl/Makefile.am
  25. 0 2
      src/bin/bindctl/README
  26. 0 21
      src/bin/bindctl/TODO
  27. 0 1
      src/bin/bindctl/__init__.py
  28. 0 945
      src/bin/bindctl/bindcmd.py
  29. 0 348
      src/bin/bindctl/bindctl.xml
  30. 0 167
      src/bin/bindctl/bindctl_main.py.in
  31. 0 175
      src/bin/bindctl/cmdparse.py
  32. 0 94
      src/bin/bindctl/command_sets.py
  33. 0 124
      src/bin/bindctl/exception.py
  34. 0 249
      src/bin/bindctl/moduleinfo.py
  35. 0 82
      src/bin/bindctl/mycollections.py
  36. 0 41
      src/bin/bindctl/run_bindctl.sh.in
  37. 0 1
      src/bin/bindctl/tests/.gitignore
  38. 0 24
      src/bin/bindctl/tests/Makefile.am
  39. 0 27
      src/bin/bindctl/tests/bindctl_test.in
  40. 0 694
      src/bin/bindctl/tests/bindctl_test.py
  41. 0 88
      src/bin/bindctl/tests/cmdparse_test.py
  42. 0 3
      src/bin/cfgmgr/.gitignore
  43. 0 43
      src/bin/cfgmgr/Makefile.am
  44. 0 132
      src/bin/cfgmgr/b10-cfgmgr.py.in
  45. 0 174
      src/bin/cfgmgr/b10-cfgmgr.xml
  46. 0 1
      src/bin/cfgmgr/local_plugins/.gitignore
  47. 0 11
      src/bin/cfgmgr/local_plugins/Makefile.am
  48. 0 2
      src/bin/cfgmgr/plugins/.gitignore
  49. 0 18
      src/bin/cfgmgr/plugins/Makefile.am
  50. 0 34
      src/bin/cfgmgr/plugins/README
  51. 0 109
      src/bin/cfgmgr/plugins/b10logging.py
  52. 0 85
      src/bin/cfgmgr/plugins/datasrc.spec.pre.in
  53. 0 80
      src/bin/cfgmgr/plugins/datasrc_config_plugin.py
  54. 0 81
      src/bin/cfgmgr/plugins/logging.spec
  55. 0 30
      src/bin/cfgmgr/plugins/tests/Makefile.am
  56. 0 245
      src/bin/cfgmgr/plugins/tests/datasrc_test.py
  57. 0 135
      src/bin/cfgmgr/plugins/tests/logging_test.py
  58. 0 103
      src/bin/cfgmgr/plugins/tests/tsig_keys_test.py
  59. 0 50
      src/bin/cfgmgr/plugins/tsig_keys.py
  60. 0 21
      src/bin/cfgmgr/plugins/tsig_keys.spec
  61. 0 1
      src/bin/cfgmgr/tests/.gitignore
  62. 0 33
      src/bin/cfgmgr/tests/Makefile.am
  63. 0 215
      src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in
  64. 0 34
      src/bin/cfgmgr/tests/testdata/plugins/testplugin.py
  65. 0 10
      src/bin/cmdctl/.gitignore
  66. 0 97
      src/bin/cmdctl/Makefile.am
  67. 0 22
      src/bin/cmdctl/README
  68. 0 7
      src/bin/cmdctl/TODO
  69. 0 217
      src/bin/cmdctl/b10-certgen.xml
  70. 0 232
      src/bin/cmdctl/b10-cmdctl.xml
  71. 0 429
      src/bin/cmdctl/botan-certgen.cc
  72. 0 1
      src/bin/cmdctl/cmdctl-accounts.csv
  73. 0 718
      src/bin/cmdctl/cmdctl.py.in
  74. 0 41
      src/bin/cmdctl/cmdctl.spec.pre.in
  75. 0 94
      src/bin/cmdctl/cmdctl_messages.mes
  76. 0 37
      src/bin/cmdctl/run_b10-cmdctl.sh.in
  77. 0 1
      src/bin/cmdctl/tests/.gitignore
  78. 0 42
      src/bin/cmdctl/tests/Makefile.am
  79. 0 253
      src/bin/cmdctl/tests/botan-certgen_test.py
  80. 0 27
      src/bin/cmdctl/tests/cmdctl_test.in
  81. 0 790
      src/bin/cmdctl/tests/cmdctl_test.py
  82. 0 21
      src/bin/cmdctl/tests/testdata/expired-certfile.pem
  83. 0 21
      src/bin/cmdctl/tests/testdata/mangled-certfile.pem
  84. 0 19
      src/bin/cmdctl/tests/testdata/noca-certfile.pem
  85. 1 21
      src/bin/d2/tests/Makefile.am
  86. 0 167
      src/bin/d2/tests/d2_test.py
  87. 1 22
      src/bin/dhcp4/tests/Makefile.am
  88. 0 211
      src/bin/dhcp4/tests/dhcp4_test.py
  89. 1 20
      src/bin/dhcp6/tests/Makefile.am
  90. 0 214
      src/bin/dhcp6/tests/dhcp6_test.py
  91. 0 4
      src/bin/msgq/.gitignore
  92. 0 49
      src/bin/msgq/Makefile.am
  93. 0 12
      src/bin/msgq/TODO
  94. 0 886
      src/bin/msgq/msgq.py.in
  95. 0 20
      src/bin/msgq/msgq.spec
  96. 0 169
      src/bin/msgq/msgq.xml
  97. 0 154
      src/bin/msgq/msgq_messages.mes
  98. 0 46
      src/bin/msgq/run_msgq.sh.in
  99. 0 1
      src/bin/msgq/tests/.gitignore
  100. 0 0
      src/bin/msgq/tests/Makefile.am

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+797.	[build]		tomek
+	Removed a lot of remaining BIND10 framework: bind10, bindctl,
+	cfgmgr, cmdctl, msgq, stats, sysinfo, tests, usermgr from src/bin
+	directory, also src/lib/python directory. There are still some
+	components that require Python3, but they are expected to be
+	removed in the near future.
+	(Trac #3413, git 8f8886ba93e9dfc714494b843deb1b3e14e58d67)
+
 796.	[doc]		tomek
 796.	[doc]		tomek
 	User's Guide renamed to Kea Administrator Reference Manual,
 	User's Guide renamed to Kea Administrator Reference Manual,
 	removed sections specific to BIND10/Bundy framework, rewritten
 	removed sections specific to BIND10/Bundy framework, rewritten

+ 27 - 284
configure.ac

@@ -214,12 +214,6 @@ if test $enable_shared = no; then
 	AC_MSG_ERROR([BIND 10 requires shared libraries to be built])
 	AC_MSG_ERROR([BIND 10 requires shared libraries to be built])
 fi
 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
 # OS dependent configuration
 SET_ENV_LIBRARY_PATH=no
 SET_ENV_LIBRARY_PATH=no
 ENV_LIBRARY_PATH=LD_LIBRARY_PATH
 ENV_LIBRARY_PATH=LD_LIBRARY_PATH
@@ -305,7 +299,7 @@ AC_HELP_STRING([--with-pythonpath=PATH],
   [specify an absolute path to python executable when automatic version check (incorrectly) fails]),
   [specify an absolute path to python executable when automatic version check (incorrectly) fails]),
   [python_path="$withval"], [python_path="auto"])
   [python_path="$withval"], [python_path="auto"])
 if test "$python_path" = auto; then
 if test "$python_path" = auto; then
-	AM_PATH_PYTHON([3.1])
+	AM_PATH_PYTHON([3.1],,[PYTHON=no])
 else
 else
 	# Older versions of automake can't handle python3 well.  This is an
 	# Older versions of automake can't handle python3 well.  This is an
 	# in-house workaround for them.
 	# in-house workaround for them.
@@ -332,154 +326,6 @@ else
 	AC_SUBST(pkgpyexecdir)
 	AC_SUBST(pkgpyexecdir)
 fi
 fi
 
 
-# We need to store the default pyexecdir in a separate variable so that
-# we can specify in Makefile.am the install directory of various BIND 10
-# python scripts and loadable modules; in Makefile.am we cannot replace
-# $(pyexecdir) using itself, e.g, this doesn't work:
-# pyexecdir = $(pyexecdir)/isc/some_module
-# The separate variable makes this setup possible as follows:
-# pyexecdir = $(PYTHON_SITEPKG_DIR)/isc/some_module
-PYTHON_SITEPKG_DIR=${pyexecdir}
-AC_SUBST(PYTHON_SITEPKG_DIR)
-
-# This will be commonly used in various Makefile.am's that need to generate
-# python log messages.
-PYTHON_LOGMSGPKG_DIR="\$(top_builddir)/src/lib/python/isc/log_messages"
-AC_SUBST(PYTHON_LOGMSGPKG_DIR)
-
-# This is python package paths commonly used in python tests.  See
-# README of log_messages for why it's included.
-# lib/dns/python/.libs is necessary because __init__.py of isc package
-# automatically imports isc.datasrc, which then requires the DNS loadable
-# module.  #2145 should eliminate the need for it.
-COMMON_PYTHON_PATH="\$(abs_top_builddir)/src/lib/python/isc/log_messages:\$(abs_top_builddir)/src/lib/python/isc/cc:\$(abs_top_srcdir)/src/lib/python:\$(abs_top_builddir)/src/lib/python:\$(abs_top_builddir)/src/lib/dns/python/.libs"
-AC_SUBST(COMMON_PYTHON_PATH)
-
-# Check for python development environments
-if test -x ${PYTHON}-config; then
-	PYTHON_INCLUDES=`${PYTHON}-config --includes`
-
-	# Add any '-L..." flags to PYTHON_LDFLAGS.  We first make a copy of
-	# python-config --ldflags, removing any spaces and tabs
-	# between "-L" and its argument (some instances of python-config
-	# insert a space, which would confuse the code below).
-	# Notes: if -L isn't contained at all we can simply skip this process,
-	# so we only go through the flag if it's contained; also, protecting
-	# the output with [] seems necessary for environment to avoid getting
-	# an empty output accidentally.
-	python_config_ldflags=[`${PYTHON}-config --ldflags | ${SED} -ne 's/\([ \t]*-L\)[ ]*\([^ \t]*[ \t]*\)/\1\2/gp'`]
-	for flag in $python_config_ldflags; do
-		flag=`echo $flag | ${SED} -ne 's/^\(\-L.*\)$/\1/p'`
-		if test "X${flag}" != X; then
-			PYTHON_LDFLAGS="$PYTHON_LDFLAGS ${flag}"
-		fi
-	done
-	# on some platforms, ${PYTHON}-config --ldflags doesn't provide a -L
-	# option while having the library under a non trivial directory.
-	# as a workaround we try the "lib" sub directory under the common
-	# prefix for this python.
-	if test -z "${PYTHON_LDFLAGS}"; then
-		PYTHON_LDFLAGS="-L`${PYTHON}-config --prefix`/lib"
-	fi
-else
-	if test "X$PYTHON_INCLUDES" = X -o "X$PYTHON_LDFLAGS" = X; then
-		AC_MSG_WARN([${PYTHON}-config does not exist or is not executable, so we could not detect python development environment.  Your system may require an additional package (e.g. "python3-dev").  Alternatively, if you are sure you have python headers and libraries, define PYTHON_INCLUDES and PYTHON_LDFLAGS and run this script.])
-	fi
-fi
-
-# Some OSes including NetBSD don't install libpython.so in a well known path.
-# To avoid requiring dynamic library path with our python wrapper loadable
-# modules, we embed the path to the modules when possible.  We do this even
-# when the path is known in the common operational environment (e.g. when
-# it's stored in a common "hint" file) for simplicity.
-if test "x$ISC_RPATH_FLAG" != "x"; then
-	python_rpath=
-	for flag in ${PYTHON_LDFLAGS}; do
-		python_rpath="${python_rpath} `echo $flag | ${SED} -ne "s/^\(\-L\)/${ISC_RPATH_FLAG}/p"`"
-	done
-	PYTHON_LDFLAGS="${PYTHON_LDFLAGS} ${python_rpath}"
-fi
-
-AC_SUBST(PYTHON_INCLUDES)
-AC_SUBST(PYTHON_LDFLAGS)
-
-CPPFLAGS_SAVED="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS ${PYTHON_INCLUDES}"
-AC_CHECK_HEADERS([Python.h],, AC_MSG_ERROR([Missing Python.h]))
-CPPFLAGS="$CPPFLAGS_SAVED"
-
-# Check for python library.  Needed for Python-wrapper libraries.
-LDFLAGS_SAVED="$LDFLAGS"
-LDFLAGS="$LDFLAGS $PYTHON_LDFLAGS"
-python_bin="python${PYTHON_VERSION}"
-AC_CHECK_LIB($python_bin, main, python_lib=$python_bin, python_lib=no)
-if test $python_lib != "no"; then
-	PYTHON_LIB="-l$python_lib"
-fi
-AC_SUBST(PYTHON_LIB)
-LDFLAGS=$LDFLAGS_SAVED
-
-# Python 3.2 changed the return type of internal hash function to
-# Py_hash_t and some platforms (such as Solaris) strictly check for long
-# vs Py_hash_t. So we detect and use the appropriate return type.
-# Remove this test (and associated changes in pydnspp_config.h.in) when
-# we require Python 3.2.
-have_py_hash_t=0
-CPPFLAGS_SAVED="$CPPFLAGS"
-CPPFLAGS=${PYTHON_INCLUDES}
-AC_MSG_CHECKING(for Py_hash_t)
-AC_TRY_COMPILE([#include <Python.h>
-                Py_hash_t h;],,
-    [AC_MSG_RESULT(yes)
-     have_py_hash_t=1],
-    [AC_MSG_RESULT(no)])
-CPPFLAGS="$CPPFLAGS_SAVED"
-HAVE_PY_HASH_T=$have_py_hash_t
-AC_SUBST(HAVE_PY_HASH_T)
-
-# 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_WARN([Missing setproctitle python module.
-Use --disable-setproctitle-check to skip this check.
-In this case we will continue, but naming of python processes will not work.])
-    fi
-fi
-
-# (g++ only check)
-# Python 3.2 has an unused parameter in one of its headers. This
-# has been reported, but not fixed as of yet, so we check if we need
-# to set -Wno-unused-parameter.
-if test "X$GXX" = "Xyes" -a "$werror_ok" = 1; then
-	CPPFLAGS_SAVED="$CPPFLAGS"
-	CPPFLAGS=${PYTHON_INCLUDES}
-	CXXFLAGS_SAVED="$CXXFLAGS"
-	CXXFLAGS="$CXXFLAGS $B10_CXXFLAGS -Werror"
-	AC_MSG_CHECKING([whether we need -Wno-unused-parameter for python])
-	AC_TRY_COMPILE(
-		[#include <Python.h>],
-		[],
-		[AC_MSG_RESULT(no)],
-		[
-		CXXFLAGS="$CXXFLAGS -Wno-unused-parameter"
-		AC_TRY_COMPILE([#include <Python.h>],
-		[],
-		[AC_MSG_RESULT(yes)
-		 PYTHON_CXXFLAGS="${PYTHON_CXXFLAGS} -Wno-unused-parameter"
-		 AC_SUBST(PYTHON_CXXFLAGS)
-		],
-		[AC_MSG_ERROR([Can't compile against Python.h.  If you're using MacOS X and have installed Python with Homebrew, see http://kea.isc.org/wiki/SystemNotesMacOSX])]
-                )
-                ]
-	)
-	CXXFLAGS="$CXXFLAGS_SAVED"
-	CPPFLAGS="$CPPFLAGS_SAVED"
-fi
-
 # produce PIC unless we disable shared libraries. need this for python bindings.
 # produce PIC unless we disable shared libraries. need this for python bindings.
 if test $enable_shared != "no" -a "X$GXX" = "Xyes"; then
 if test $enable_shared != "no" -a "X$GXX" = "Xyes"; then
    B10_CXXFLAGS="$B10_CXXFLAGS -fPIC"
    B10_CXXFLAGS="$B10_CXXFLAGS -fPIC"
@@ -552,29 +398,6 @@ AC_TRY_COMPILE([
         AC_DEFINE(HAVE_SA_LEN, 1, [Define to 1 if sockaddr has a sa_len member, and corresponding sin_len and sun_len])],
         AC_DEFINE(HAVE_SA_LEN, 1, [Define to 1 if sockaddr has a sa_len member, and corresponding sin_len and sun_len])],
         AC_MSG_RESULT(no))
         AC_MSG_RESULT(no))
 
 
-AC_ARG_WITH(pycoverage,
-[  --with-pycoverage[=PROGRAM]         enable python code coverage using the specified coverage], pycoverage="$withval", pycoverage="no")
-if test "$pycoverage" = "no" ; then
-	# just run the tests normally with python
-	PYCOVERAGE_RUN="${PYTHON}"
-	USE_PYCOVERAGE="no"
-elif test "$pycoverage" = "yes" ; then
-	PYCOVERAGE="coverage"
-	PYCOVERAGE_RUN="${PYCOVERAGE} run --branch --append"
-	USE_PYCOVERAGE="yes"
-else
-	PYCOVERAGE="$pycoverage"
-	PYCOVERAGE_RUN="${PYCOVERAGE} run --branch --append"
-	USE_PYCOVERAGE="yes"
-fi
-AM_CONDITIONAL(ENABLE_PYTHON_COVERAGE, test x$USE_PYCOVERAGE != xno)
-AC_SUBST(PYCOVERAGE)
-AC_SUBST(PYCOVERAGE_RUN)
-AC_SUBST(USE_PYCOVERAGE)
-
-
-
-
 enable_gtest="no"
 enable_gtest="no"
 GTEST_INCLUDES=
 GTEST_INCLUDES=
 
 
@@ -1370,13 +1193,6 @@ if test "x$HAVE_PKG_CONFIG" = "xno" ; then
   AC_MSG_ERROR(Please install pkg-config)
   AC_MSG_ERROR(Please install pkg-config)
 fi
 fi
 
 
-AX_SQLITE3_FOR_BIND10
-if test "x$have_sqlite" = "xyes" ; then
-  enable_features="$enable_features SQLite3"
-
-  AX_PYTHON_SQLITE3
-fi
-
 #
 #
 # ASIO: we extensively use it as the C++ event management module.
 # ASIO: we extensively use it as the C++ event management module.
 #
 #
@@ -1448,8 +1264,12 @@ AC_ARG_ENABLE(generate_docs, [AC_HELP_STRING([--enable-generate-docs],
   [regenerate documentation using Docbook [default=no]])],
   [regenerate documentation using Docbook [default=no]])],
   enable_generate_docs=$enableval, enable_generate_docs=no)
   enable_generate_docs=$enableval, enable_generate_docs=no)
 
 
-# Check for xsltproc
 if test "x$enable_generate_docs" != xno ; then
 if test "x$enable_generate_docs" != xno ; then
+  if test "$PYTHON" == "no" ; then
+    AC_MSG_ERROR("Python3 is required for enable-generate-docs")
+  fi
+
+# Check for xsltproc
   AC_PATH_PROG([XSLTPROC], [xsltproc])
   AC_PATH_PROG([XSLTPROC], [xsltproc])
   if test -z "$XSLTPROC"; then
   if test -z "$XSLTPROC"; then
     AC_MSG_ERROR("xsltproc not found; it is required for --enable-generate-docs")
     AC_MSG_ERROR("xsltproc not found; it is required for --enable-generate-docs")
@@ -1543,31 +1363,6 @@ AC_CONFIG_FILES([compatcheck/Makefile
                  ext/Makefile
                  ext/Makefile
                  m4macros/Makefile
                  m4macros/Makefile
                  Makefile
                  Makefile
-                 src/bin/bind10/bind10
-                 src/bin/bind10/init.py
-                 src/bin/bind10/Makefile
-                 src/bin/bind10/run_bind10.sh
-                 src/bin/bind10/tests/init_test.py
-                 src/bin/bind10/tests/Makefile
-                 src/bin/bindctl/bindctl_main.py
-                 src/bin/bindctl/Makefile
-                 src/bin/bindctl/run_bindctl.sh
-                 src/bin/bindctl/tests/bindctl_test
-                 src/bin/bindctl/tests/Makefile
-                 src/bin/cfgmgr/b10-cfgmgr.py
-                 src/bin/cfgmgr/local_plugins/Makefile
-                 src/bin/cfgmgr/Makefile
-                 src/bin/cfgmgr/plugins/datasrc.spec.pre
-                 src/bin/cfgmgr/plugins/Makefile
-                 src/bin/cfgmgr/plugins/tests/Makefile
-                 src/bin/cfgmgr/tests/b10-cfgmgr_test.py
-                 src/bin/cfgmgr/tests/Makefile
-                 src/bin/cmdctl/cmdctl.py
-                 src/bin/cmdctl/cmdctl.spec.pre
-                 src/bin/cmdctl/Makefile
-                 src/bin/cmdctl/run_b10-cmdctl.sh
-                 src/bin/cmdctl/tests/cmdctl_test
-                 src/bin/cmdctl/tests/Makefile
                  src/bin/d2/Makefile
                  src/bin/d2/Makefile
                  src/bin/d2/spec_config.h.pre
                  src/bin/d2/spec_config.h.pre
                  src/bin/d2/tests/Makefile
                  src/bin/d2/tests/Makefile
@@ -1594,26 +1389,8 @@ AC_CONFIG_FILES([compatcheck/Makefile
                  src/bin/keactrl/tests/keactrl_tests.sh
                  src/bin/keactrl/tests/keactrl_tests.sh
                  src/bin/keactrl/tests/Makefile
                  src/bin/keactrl/tests/Makefile
                  src/bin/Makefile
                  src/bin/Makefile
-                 src/bin/msgq/Makefile
-                 src/bin/msgq/msgq.py
-                 src/bin/msgq/run_msgq.sh
-                 src/bin/msgq/tests/Makefile
                  src/bin/sockcreator/Makefile
                  src/bin/sockcreator/Makefile
                  src/bin/sockcreator/tests/Makefile
                  src/bin/sockcreator/tests/Makefile
-                 src/bin/stats/Makefile
-                 src/bin/stats/stats_httpd.py
-                 src/bin/stats/stats.py
-                 src/bin/stats/tests/Makefile
-                 src/bin/stats/tests/testdata/Makefile
-                 src/bin/sysinfo/Makefile
-                 src/bin/sysinfo/run_sysinfo.sh
-                 src/bin/sysinfo/sysinfo.py
-                 src/bin/tests/Makefile
-                 src/bin/tests/process_rename_test.py
-                 src/bin/usermgr/b10-cmdctl-usermgr.py
-                 src/bin/usermgr/Makefile
-                 src/bin/usermgr/run_b10-cmdctl-usermgr.sh
-                 src/bin/usermgr/tests/Makefile
                  src/hooks/dhcp/Makefile
                  src/hooks/dhcp/Makefile
                  src/hooks/dhcp/user_chk/Makefile
                  src/hooks/dhcp/user_chk/Makefile
                  src/hooks/dhcp/user_chk/tests/Makefile
                  src/hooks/dhcp/user_chk/tests/Makefile
@@ -1643,9 +1420,6 @@ AC_CONFIG_FILES([compatcheck/Makefile
                  src/lib/dhcp/tests/Makefile
                  src/lib/dhcp/tests/Makefile
                  src/lib/dns/gen-rdatacode.py
                  src/lib/dns/gen-rdatacode.py
                  src/lib/dns/Makefile
                  src/lib/dns/Makefile
-                 src/lib/dns/python/Makefile
-                 src/lib/dns/python/pydnspp_config.h
-                 src/lib/dns/python/tests/Makefile
                  src/lib/dns/tests/Makefile
                  src/lib/dns/tests/Makefile
                  src/lib/dns/tests/testdata/Makefile
                  src/lib/dns/tests/testdata/Makefile
                  src/lib/exceptions/Makefile
                  src/lib/exceptions/Makefile
@@ -1668,44 +1442,13 @@ AC_CONFIG_FILES([compatcheck/Makefile
                  src/lib/log/tests/severity_test.sh
                  src/lib/log/tests/severity_test.sh
                  src/lib/log/tests/tempdir.h
                  src/lib/log/tests/tempdir.h
                  src/lib/Makefile
                  src/lib/Makefile
-                 src/lib/python/bind10_config.py
-                 src/lib/python/isc/bind10/Makefile
-                 src/lib/python/isc/bind10/tests/Makefile
-                 src/lib/python/isc/cc/cc_generated/Makefile
-                 src/lib/python/isc/cc/Makefile
-                 src/lib/python/isc/cc/tests/cc_test
-                 src/lib/python/isc/cc/tests/Makefile
-                 src/lib/python/isc/config/Makefile
-                 src/lib/python/isc/config/tests/config_test
-                 src/lib/python/isc/config/tests/Makefile
-                 src/lib/python/isc/dns/Makefile
-                 src/lib/python/isc/log/Makefile
-                 src/lib/python/isc/log_messages/Makefile
-                 src/lib/python/isc/log_messages/work/__init__.py
-                 src/lib/python/isc/log_messages/work/Makefile
-                 src/lib/python/isc/log/tests/log_console.py
-                 src/lib/python/isc/log/tests/Makefile
-                 src/lib/python/isc/Makefile
-                 src/lib/python/isc/net/Makefile
-                 src/lib/python/isc/net/tests/Makefile
-                 src/lib/python/isc/sysinfo/Makefile
-                 src/lib/python/isc/sysinfo/tests/Makefile
-                 src/lib/python/isc/testutils/Makefile
-                 src/lib/python/isc/util/cio/Makefile
-                 src/lib/python/isc/util/cio/tests/Makefile
-                 src/lib/python/isc/util/Makefile
-                 src/lib/python/isc/util/tests/Makefile
-                 src/lib/python/Makefile
                  src/lib/testutils/dhcp_test_lib.sh
                  src/lib/testutils/dhcp_test_lib.sh
                  src/lib/testutils/Makefile
                  src/lib/testutils/Makefile
                  src/lib/testutils/testdata/Makefile
                  src/lib/testutils/testdata/Makefile
                  src/lib/util/io/Makefile
                  src/lib/util/io/Makefile
                  src/lib/util/Makefile
                  src/lib/util/Makefile
-                 src/lib/util/python/doxygen2pydoc.py
                  src/lib/util/python/gen_wiredata.py
                  src/lib/util/python/gen_wiredata.py
                  src/lib/util/python/Makefile
                  src/lib/util/python/Makefile
-                 src/lib/util/python/mkpywrapper.py
-                 src/lib/util/pyunittests/Makefile
                  src/lib/util/tests/Makefile
                  src/lib/util/tests/Makefile
                  src/lib/util/threads/Makefile
                  src/lib/util/threads/Makefile
                  src/lib/util/threads/tests/Makefile
                  src/lib/util/threads/tests/Makefile
@@ -1719,19 +1462,10 @@ AC_CONFIG_FILES([compatcheck/Makefile
 ])
 ])
 
 
  AC_CONFIG_COMMANDS([permissions], [
  AC_CONFIG_COMMANDS([permissions], [
-           chmod +x src/bin/bind10/bind10
-           chmod +x src/bin/bind10/run_bind10.sh
-           chmod +x src/bin/bindctl/run_bindctl.sh
-           chmod +x src/bin/bindctl/tests/bindctl_test
-           chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
-           chmod +x src/bin/cmdctl/tests/cmdctl_test
            chmod +x src/bin/dhcp4/tests/dhcp4_process_tests.sh
            chmod +x src/bin/dhcp4/tests/dhcp4_process_tests.sh
            chmod +x src/bin/dhcp6/tests/dhcp6_process_tests.sh
            chmod +x src/bin/dhcp6/tests/dhcp6_process_tests.sh
            chmod +x src/bin/keactrl/keactrl
            chmod +x src/bin/keactrl/keactrl
            chmod +x src/bin/keactrl/tests/keactrl_tests.sh
            chmod +x src/bin/keactrl/tests/keactrl_tests.sh
-           chmod +x src/bin/msgq/run_msgq.sh
-           chmod +x src/bin/sysinfo/run_sysinfo.sh
-           chmod +x src/bin/usermgr/run_b10-cmdctl-usermgr.sh
            chmod +x src/lib/dns/gen-rdatacode.py
            chmod +x src/lib/dns/gen-rdatacode.py
            chmod +x src/lib/log/tests/console_test.sh
            chmod +x src/lib/log/tests/console_test.sh
            chmod +x src/lib/log/tests/destination_test.sh
            chmod +x src/lib/log/tests/destination_test.sh
@@ -1739,10 +1473,7 @@ AC_CONFIG_FILES([compatcheck/Makefile
            chmod +x src/lib/log/tests/local_file_test.sh
            chmod +x src/lib/log/tests/local_file_test.sh
            chmod +x src/lib/log/tests/logger_lock_test.sh
            chmod +x src/lib/log/tests/logger_lock_test.sh
            chmod +x src/lib/log/tests/severity_test.sh
            chmod +x src/lib/log/tests/severity_test.sh
-           chmod +x src/lib/python/isc/log/tests/log_console.py
-           chmod +x src/lib/util/python/doxygen2pydoc.py
            chmod +x src/lib/util/python/gen_wiredata.py
            chmod +x src/lib/util/python/gen_wiredata.py
-           chmod +x src/lib/util/python/mkpywrapper.py
 ])
 ])
 
 
 AC_OUTPUT
 AC_OUTPUT
@@ -1769,14 +1500,29 @@ C++ Compiler:
   CXXFLAGS:        ${CXXFLAGS}
   CXXFLAGS:        ${CXXFLAGS}
   LDFLAGS:         ${LDFLAGS}
   LDFLAGS:         ${LDFLAGS}
   B10_CXXFLAGS:    ${B10_CXXFLAGS}
   B10_CXXFLAGS:    ${B10_CXXFLAGS}
+END
 
 
-Python:
+if test "$PYTHON" != "no" ; then
+cat >> config.report << END
+
+Python3:
   PYTHON_VERSION:  ${PYTHON_VERSION}
   PYTHON_VERSION:  ${PYTHON_VERSION}
   PYTHON_INCLUDES: ${PYTHON_INCLUDES}
   PYTHON_INCLUDES: ${PYTHON_INCLUDES}
   PYTHON_CXXFLAGS: ${PYTHON_CXXFLAGS}
   PYTHON_CXXFLAGS: ${PYTHON_CXXFLAGS}
   PYTHON_LDFLAGS:  ${PYTHON_LDFLAGS}
   PYTHON_LDFLAGS:  ${PYTHON_LDFLAGS}
   PYTHON_LIB:      ${PYTHON_LIB}
   PYTHON_LIB:      ${PYTHON_LIB}
 
 
+END
+else
+cat >> config.report << END
+
+Python3:
+  not installed
+
+END
+fi
+
+cat >> config.report << END
 Boost:
 Boost:
   BOOST_VERSION:   ${BOOST_VERSION}
   BOOST_VERSION:   ${BOOST_VERSION}
   BOOST_INCLUDES:  ${BOOST_INCLUDES}
   BOOST_INCLUDES:  ${BOOST_INCLUDES}
@@ -1795,13 +1541,8 @@ Log4cplus:
   LOG4CPLUS_INCLUDES: ${LOG4CPLUS_INCLUDES}
   LOG4CPLUS_INCLUDES: ${LOG4CPLUS_INCLUDES}
   LOG4CPLUS_LIBS:  ${LOG4CPLUS_LIBS}
   LOG4CPLUS_LIBS:  ${LOG4CPLUS_LIBS}
 
 
-SQLite:
-  SQLITE_VERSION:  ${SQLITE_VERSION}
-  SQLITE_CFLAGS:   ${SQLITE_CFLAGS}
-  SQLITE_LIBS:     ${SQLITE_LIBS}
-
 Kea config backend:
 Kea config backend:
-  CONFIG_BACKEND: ${CONFIG_BACKEND}
+  CONFIG_BACKEND:  ${CONFIG_BACKEND}
 END
 END
 
 
 # Avoid confusion on DNS/DHCP and only mention MySQL if it
 # Avoid confusion on DNS/DHCP and only mention MySQL if it
@@ -1817,7 +1558,8 @@ END
 else
 else
 cat >> config.report << END
 cat >> config.report << END
 
 
-MySQL: no
+MySQL:
+  no
 END
 END
 fi
 fi
 
 
@@ -1832,7 +1574,8 @@ END
 else
 else
 cat >> config.report << END
 cat >> config.report << END
 
 
-PostgreSQL: no
+PostgreSQL:
+  no
 END
 END
 fi
 fi
 
 

+ 0 - 1
m4macros/Makefile.am

@@ -1,2 +1 @@
 EXTRA_DIST  = ax_boost_for_bind10.m4
 EXTRA_DIST  = ax_boost_for_bind10.m4
-EXTRA_DIST += ax_sqlite3_for_bind10.m4

+ 0 - 20
m4macros/ax_python_sqlite3.m4

@@ -1,20 +0,0 @@
-dnl @synopsis AX_PYTHON_SQLITE3
-dnl
-dnl Test for the Python sqlite3 module used by BIND10's datasource
-dnl
-
-AC_DEFUN([AX_PYTHON_SQLITE3], [
-
-# Check for the python sqlite3 module
-AC_MSG_CHECKING(for python sqlite3 module)
-if "$PYTHON" -c 'import sqlite3' 2>/dev/null ; then
-    AC_MSG_RESULT(ok)
-else
-    AC_MSG_RESULT(missing)
-
-    if test "x$want_dns" = "xyes" ; then
-        AC_MSG_ERROR([Missing sqlite3 python module that is required by DNS components.])
-    fi
-fi
-
-])dnl AX_PYTHON_SQLITE3

+ 0 - 42
m4macros/ax_sqlite3_for_bind10.m4

@@ -1,42 +0,0 @@
-dnl @synopsis AX_SQLITE3_FOR_BIND10
-dnl
-dnl Test for the sqlite3 library and program, intended to be used within
-dnl BIND 10, and to test BIND 10.
-dnl
-dnl We use pkg-config to look for the sqlite3 library, so the sqlite3
-dnl development package with the .pc file must be installed.
-dnl
-dnl This macro sets SQLITE_CFLAGS and SQLITE_LIBS. It also sets
-dnl SQLITE3_PROGRAM to the path of the sqlite3 program, if it is found
-dnl in PATH.
-
-AC_DEFUN([AX_SQLITE3_FOR_BIND10], [
-
-PKG_CHECK_MODULES(SQLITE, sqlite3 >= 3.3.9,
-    [have_sqlite="yes"
-dnl Determine the SQLite version, used mainly for config.report.
-CPPFLAGS_SAVED="$CPPFLAGS"
-CPPFLAGS="${CPPFLAGS} $SQLITE_CFLAGS"
-AC_MSG_CHECKING([SQLite version])
-cat > conftest.c << EOF
-#include <sqlite3.h>
-AUTOCONF_SQLITE_VERSION=SQLITE_VERSION
-EOF
-
-SQLITE_VERSION=`$CPP $CPPFLAGS conftest.c | grep '^AUTOCONF_SQLITE_VERSION=' | $SED -e 's/^AUTOCONF_SQLITE_VERSION=//' -e 's/"//g' 2> /dev/null`
-if test -z "$SQLITE_VERSION"; then
-  SQLITE_VERSION="unknown"
-fi
-$RM -f conftest.c
-AC_MSG_RESULT([$SQLITE_VERSION])
-
-CPPFLAGS="$CPPFLAGS_SAVED"
-    ],have_sqlite="no (sqlite3 not detected)")
-
-# Check for sqlite3 program
-AC_PATH_PROG(SQLITE3_PROGRAM, sqlite3, no)
-AM_CONDITIONAL(HAVE_SQLITE3_PROGRAM, test "x$SQLITE3_PROGRAM" != "xno")
-
-# TODO: check for _sqlite3.py module
-
-])dnl AX_SQLITE3_FOR_BIND10

+ 1 - 3
src/bin/Makefile.am

@@ -1,7 +1,5 @@
 # The following build order must be maintained.
 # The following build order must be maintained.
-SUBDIRS = bind10 bindctl cfgmgr msgq cmdctl \
-	usermgr stats tests  sockcreator dhcp4 dhcp6 \
-	d2 sysinfo
+SUBDIRS = sockcreator dhcp4 dhcp6 d2
 
 
 if CONFIG_BACKEND_JSON
 if CONFIG_BACKEND_JSON
 SUBDIRS += keactrl
 SUBDIRS += keactrl

+ 0 - 6
src/bin/bind10/.gitignore

@@ -1,6 +0,0 @@
-/run_bind10.sh
-/bind10
-/bind10.8
-/b10-init
-/b10-init.8
-/init.py

+ 0 - 64
src/bin/bind10/Makefile.am

@@ -1,64 +0,0 @@
-SUBDIRS = . tests
-
-sbin_SCRIPTS = bind10
-pkglibexec_SCRIPTS = b10-init
-CLEANFILES = b10-init b10-init.pyc init.pyc
-CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/init_messages.py
-CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/init_messages.pyc
-
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-
-nodist_pylogmessage_PYTHON = $(PYTHON_LOGMSGPKG_DIR)/work/init_messages.py
-pylogmessagedir = $(pyexecdir)/isc/log_messages/
-
-noinst_SCRIPTS = run_bind10.sh
-
-bind10dir = $(pkgdatadir)
-bind10_DATA = init.spec
-EXTRA_DIST = init.spec bind10.in
-
-man_MANS = b10-init.8 bind10.8
-DISTCLEANFILES = $(man_MANS) bind10
-EXTRA_DIST += $(man_MANS) b10-init.xml bind10.xml init_messages.mes
-
-if GENERATE_DOCS
-
-bind10.8: bind10.xml
-	@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/bind10.xml
-
-b10-init.8: b10-init.xml
-	@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-init.xml
-
-#dist-local-check-mans-enabled:
-#	@if grep "Man generation disabled" $(man_MANS) >/dev/null; then $(RM) $(man_MANS); fi
-
-else
-
-$(man_MANS):
-	@echo Man generation disabled.  Creating dummy $@.  Configure with --enable-generate-docs to enable it.
-	@echo Man generation disabled.  Remove this file, configure with --enable-generate-docs, and rebuild BIND 10 > $@
-
-#dist-local-check-mans-enabled:
-#	@echo "*** --enable-generate-docs must be used in order to make dist"
-#	@false
-
-endif
-
-$(PYTHON_LOGMSGPKG_DIR)/work/init_messages.py : init_messages.mes
-	$(top_builddir)/src/lib/log/compiler/message \
-	-d $(PYTHON_LOGMSGPKG_DIR)/work -p $(srcdir)/init_messages.mes
-
-# this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
-b10-init: init.py $(PYTHON_LOGMSGPKG_DIR)/work/init_messages.py
-	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
-	       -e "s|@@LIBDIR@@|$(libdir)|" \
-	       -e "s|@@LIBEXECDIR@@|$(pkglibexecdir)|" init.py >$@
-	chmod a+x $@
-
-pytest:
-	$(SHELL) tests/bind10_test
-
-CLEANDIRS = __pycache__
-
-clean-local:
-	rm -rf $(CLEANDIRS)

+ 0 - 16
src/bin/bind10/README

@@ -1,16 +0,0 @@
-This directory contains the source for the "b10-init" program, as well as
-the "bind10" script that runs it.
-
-Files:
-  Makefile.am      - build information
-  README           - this file
-  TODO             - remaining development tasks for this program
-  bind10.py.in     - used to make bind10.py with proper Python paths
-  init.spec        - defines the options and commands
-  run_bind10.sh.in - use to make run_bind10.sh with proper Python paths
-
-The "tests" directory contains unit tests for the application.
-
-If you want to run the bind10 program from the source directory, then
-use the "run_bind10.sh" script. To run it in the installed location,
-use the "bind10" program.

+ 0 - 14
src/bin/bind10/TODO

@@ -1,14 +0,0 @@
-- Read msgq configuration from configuration manager (Trac #213)
-  https://bind10.isc.org/ticket/213
-- Provide more administrator options:
-  - Get information on a process (returns list of times started & stopped, 
-    plus current information such as PID)
-  - Stop a component
-  - Force-stop a component
-- Mechanism to wait for child to start before continuing
-- Use .spec file to define commands
-- Rename "c-channel" stuff to msgq for clarity
-- Reply to shutdown message?
-- Some sort of group creation so termination signals can be sent to
-  children of children processes (if any)
-

+ 0 - 519
src/bin/bind10/b10-init.xml

@@ -1,519 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	       [<!ENTITY mdash "&#8212;">]>
-<!--
- - Copyright (C) 2010-2012  Internet Systems Consortium, Inc. ("ISC")
- -
- - Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
- - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- - AND FITNESS.  IN NO EVENT SHALL ISC 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.
--->
-
-<refentry>
-
-  <refentryinfo>
-    <date>February 5, 2013</date>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>b10-init</refentrytitle>
-    <manvolnum>8</manvolnum>
-    <refmiscinfo>BIND10</refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>b10-init</refname>
-    <refpurpose>BIND 10 Init process</refpurpose>
-  </refnamediv>
-
-  <docinfo>
-    <copyright>
-      <year>2010-2013</year>
-      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
-    </copyright>
-  </docinfo>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>b10-init</command>
-      <arg><option>-c <replaceable>config-filename</replaceable></option></arg>
-      <arg><option>-i</option></arg>
-      <arg><option>-m <replaceable>file</replaceable></option></arg>
-      <arg><option>-p <replaceable>data_path</replaceable></option></arg>
-      <arg><option>-u <replaceable>user</replaceable></option></arg>
-      <arg><option>-v</option></arg>
-      <arg><option>-w <replaceable>wait_time</replaceable></option></arg>
-      <arg><option>--clear-config</option></arg>
-      <arg><option>--cmdctl-port</option> <replaceable>port</replaceable></arg>
-      <arg><option>--config-file</option> <replaceable>config-filename</replaceable></arg>
-      <arg><option>--data-path</option> <replaceable>directory</replaceable></arg>
-      <arg><option>--msgq-socket-file <replaceable>file</replaceable></option></arg>
-      <arg><option>--no-kill</option></arg>
-      <arg><option>--pid-file</option> <replaceable>filename</replaceable></arg>
-      <arg><option>--pretty-name <replaceable>name</replaceable></option></arg>
-      <arg><option>--user <replaceable>user</replaceable></option></arg>
-      <arg><option>--verbose</option></arg>
-      <arg><option>--wait <replaceable>wait_time</replaceable></option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>DESCRIPTION</title>
-
-    <para>The <command>b10-init</command> daemon starts up other
-    BIND 10 required daemons.  It handles restarting of exiting
-    programs and also the shutdown of all managed daemons.</para>
-
-<!-- TODO: list what it starts here? -->
-
-<!-- TODO
-    <para>The configuration of the <command>b10-init</command> daemon
-    is defined in the TODO configuration file, as described in the
-    <citerefentry><refentrytitle>TODO</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-    manual page.</para>
--->
-
-  </refsect1>
-
-  <refsect1>
-    <title>ARGUMENTS</title>
-
-    <para>The arguments are as follows:</para>
-
-    <variablelist>
-
-      <varlistentry>
-        <term>
-          <option>-c</option> <replaceable>config-filename</replaceable>,
-          <option>--config-file</option> <replaceable>config-filename</replaceable>
-        </term>
-        <listitem>
-          <para>The configuration filename to use. Can be either absolute or
-          relative to data path. In case it is absolute, value of data path is
-          not considered.
-          Defaults to <filename>b10-config.db</filename>.</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>
-          <option>--clear-config</option>
-        </term>
-        <listitem>
-	  <para>
-	    This will create a backup of the existing configuration
-	    file, remove it and start
-	    <refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum>
-            with the default configuration.
-	    The name of the backup file can be found in the logs
-	    (<varname>CFGMGR_BACKED_UP_CONFIG_FILE</varname>).
-	    (It will append a number to the backup filename if a
-	    previous backup file exists.)
-
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>
-          <option>--cmdctl-port</option> <replaceable>port</replaceable>
-        </term>
-        <listitem>
-	  <para>The <command>b10-cmdctl</command> daemon will listen
-	    on this port.
-	    (See
-	    <refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum>
-            for the default.)
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>
-          <option>-p</option> <replaceable>directory</replaceable>,
-          <option>--data-path</option> <replaceable>directory</replaceable>
-        </term>
-        <listitem>
-          <para>The path where BIND 10 programs look for various data files.
-	  Currently only
-	  <citerefentry><refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-	  uses it to locate the configuration file, but the usage
-	  might be extended for other programs and other types of
-	  files.</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-m</option> <replaceable>file</replaceable>,
-           <option>--msgq-socket-file</option> <replaceable>file</replaceable></term>
-
-        <listitem>
-          <para>The UNIX domain socket file for the
-	    <citerefentry><refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-            daemon to use.
-            The default is
-            <filename>/usr/local/var/bind10/msg_socket</filename>.
-<!-- @localstatedir@/@PACKAGE_NAME@/msg_socket -->
-           </para>
-         </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-i</option>, <option>--no-kill</option></term>
-        <listitem>
-	  <para>When this option is passed, <command>b10-init</command>
-	  does not send SIGTERM and SIGKILL signals to modules during
-	  shutdown. (This option was introduced for use during
-	  testing.)</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-u</option> <replaceable>user</replaceable>, <option>--user</option> <replaceable>name</replaceable></term>
-<!-- TODO: example more detail. -->
-        <listitem>
-          <para>The username for <command>b10-init</command> to run as.
-            <command>b10-init</command> must be initially ran as the
-            root user to use this option.
-            The default is to run as the current user.</para>
-         </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>--pid-file</option> <replaceable>filename</replaceable></term>
-        <listitem>
-          <para>If defined, the PID of the <command>b10-init</command> is stored
-             in this file.
-          </para>
-         </listitem>
-      </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>b10-init</command>.
-<!-- TODO: only supported with setproctitle feature
-The default is the basename of ARG 0.
--->
-</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-v</option>, <option>--verbose</option></term>
-        <listitem>
-	  <para>Display more about what is going on for
-	  <command>b10-init</command> and its child processes.</para>
-<!-- TODO: not true about all children yet -->
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-w</option> <replaceable>wait_time</replaceable>, <option>--wait</option> <replaceable>wait_time</replaceable></term>
-        <listitem>
-	  <para>Sets the amount of time that BIND 10 will wait for
-	  the configuration manager (a key component of BIND 10)
-	  to initialize itself before abandoning the start up and
-	  terminating with an error.  The
-	  <replaceable>wait_time</replaceable> is specified in
-	  seconds and has a default value of 10.
-          </para>
-        </listitem>
-      </varlistentry>
-
-    </variablelist>
-  </refsect1>
-
-<!--
-TODO: configuration section
--->
-
-  <refsect1>
-    <title>CONFIGURATION AND COMMANDS</title>
-
-    <para>
-      The configuration provides settings for components for
-      <command>b10-init</command> to manage under
-      <varname>/Init/components/</varname>.
-      The default elements are:
-    </para>
-
-    <itemizedlist>
-
-      <listitem>
-        <para> <varname>/Init/components/b10-cmdctl</varname> </para>
-      </listitem>
-
-      <listitem>
-        <para> <varname>/Init/components/b10-stats</varname> </para>
-      </listitem>
-
-    </itemizedlist>
-
-    <para>
-      (Note that the startup of <command>b10-sockcreator</command>,
-      <command>b10-cfgmgr</command>, and <command>b10-msgq</command>
-      is not configurable. They are hardcoded and <command>b10-init</command>
-      will not run without them.)
-    </para>
-
-    <para>
-      The named sets for components contain the following settings:
-    </para>
-
-    <variablelist>
-
-      <varlistentry>
-        <term><varname>address</varname></term>
-        <listitem>
-	  <para>The name used for communicating to it on the message
-	  bus.</para>
-<!-- NOTE: vorner said:
-These can be null, because the components are special ones, and
-the special class there already knows the address. It is (I hope)
-explained in the guide. I'd like to get rid of the special components
-sometime and I'd like it to teach to guess the address.
--->
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><varname>kind</varname></term>
-        <listitem>
-          <para>
-            This defines how required a component is.
-            The possible settings for <varname>kind</varname> are:
-            <varname>core</varname> (system won't start if it won't
-            start and <command>b10-init</command> will shutdown if
-            a <quote>core</quote> component crashes),
-            <varname>dispensable</varname> (<command>b10-init</command>
-            will restart failing component),
-            and
-	    <varname>needed</varname> (<command>b10-init</command>
-	    will shutdown if component won't initially start, but
-	    if crashes later, it will attempt to restart).
-            This setting is required.
-<!-- TODO: formatting -->
-          </para>
-        </listitem>
-      </varlistentry>
-
-<!--
-TODO: currently not used
-      <varlistentry>
-        <term> <varname>params</varname> </term>
-        <listitem>
-          <para>
-list
-</para>
-        </listitem>
-      </varlistentry>
--->
-
-      <varlistentry>
-        <term> <varname>priority</varname> </term>
-        <listitem>
-          <para>This is an integer. <command>b10-init</command>
-            will start the components with largest priority numbers first.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-          <term> <varname>process</varname> </term>
-        <listitem>
-          <para>This is the filename of the executable to be started.
-            If not defined, then <command>b10-init</command> will
-            use the component name instead.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-          <term> <varname>special</varname> </term>
-        <listitem>
-          <para>
-            This defines if the component is started a special, hardcoded
-            way.
-<!--
-TODO: document this ... but maybe some of these will be removed
-once we get rid of some using switches for components?
-
-auth
-cfgmgr
-cmdctl
-msgq
-resolver
-sockcreator
-xfrin
--->
-
-</para>
-        </listitem>
-      </varlistentry>
-
-    </variablelist>
-
-<!-- TODO: formating -->
-    <para>
-      The <varname>Init</varname> configuration commands are:
-    </para>
-
-<!-- TODO -->
-<!--
-    <para>
-      <command>drop_socket</command>
-      This is an internal command and not exposed to the administrator.
-    </para>
--->
-
-<!-- TODO -->
-<!--
-    <para>
-      <command>get_socket</command>
-      This is an internal command and not exposed to the administrator.
-    </para>
--->
-
-    <para>
-      <command>getstats</command> tells <command>b10-init</command>
-      to send its statistics data to the <command>b10-stats</command>
-      daemon.
-      This is an internal command and not exposed to the administrator.
-<!-- not defined in spec -->
-    </para>
-
-    <para>
-      <command>ping</command> is used to check the connection with the
-      <command>b10-init</command> daemon.
-      It returns the text <quote>pong</quote>.
-    </para>
-
-    <para>
-      <command>show_processes</command> lists the current processes
-      managed by <command>b10-init</command>.
-      The output is an array in JSON format containing the process
-      ID, the name for each and the address name used on each message bus.
-<!-- TODO: what is name? -->
-<!-- TODO: change to JSON object format? -->
-<!-- TODO: ticket #1406 -->
-    </para>
-
-    <para>
-      <command>shutdown</command> tells <command>b10-init</command>
-      to shutdown the BIND 10 servers.
-      It will tell each process it manages to shutdown and, when
-      complete, <command>b10-init</command> will exit.
-    </para>
-
-  </refsect1>
-
-  <refsect1>
-    <title>STATISTICS DATA</title>
-
-    <para>
-      The statistics data collected by the <command>b10-stats</command>
-      daemon for <quote>Init</quote> include:
-    </para>
-
-    <variablelist>
-
-      <varlistentry>
-        <term>boot_time</term>
-        <listitem><para>
-          The date and time that the <command>b10-init</command>
-          process started.
-          This is represented in ISO 8601 format.
-        </para></listitem>
-      </varlistentry>
-
-    </variablelist>
-
-  </refsect1>
-
-  <refsect1>
-    <title>FILES</title>
-    <para><filename>sockcreator-XXXXXX/sockcreator</filename>
-    &mdash;
-    the Unix Domain socket located in a temporary file directory for
-    <command>b10-sockcreator</command>
-<!--    <citerefentry><refentrytitle>b10-sockcreator</refentrytitle><manvolnum>8</manvolnum></citerefentry> -->
-    communication.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>bindctl</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-auth</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-xfrin</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-xfrout</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-zonemgr</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-stats-httpd</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citetitle>BIND 10 Guide</citetitle>.
-    </para>
-  </refsect1>
-<!-- <citerefentry>
-        <refentrytitle>b10-sockcreator</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>, -->
-
-  <refsect1 id='history'><title>HISTORY</title>
-    <para>The development of <command>b10-init</command>
-      was started in October 2009.
-      It was renamed and its configuration identifier changed
-      in February 2013.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>AUTHORS</title>
-    <para>
-      The <command>b10-init</command>
-      daemon was initially designed by Shane Kerr of ISC.
-    </para>
-  </refsect1>
-</refentry><!--
- - Local variables:
- - mode: sgml
- - End:
--->

+ 0 - 11
src/bin/bind10/bind10.in

@@ -1,11 +0,0 @@
-#!/bin/sh
-
-# We use this wrapper script both for production and in-source tests; in
-# the latter case B10_FROM_BUILD environment is expected to be defined.
-if test -n "${B10_FROM_BUILD}"; then
-	exec ${B10_FROM_BUILD}/src/bin/bind10/b10-init $*
-else
-	prefix=@prefix@
-	exec_prefix=@exec_prefix@
-	exec @libexecdir@/@PACKAGE@/b10-init $*
-fi

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

@@ -1,76 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	       [<!ENTITY mdash "&#8212;">]>
-<!--
- - Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
- -
- - Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
- - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- - AND FITNESS.  IN NO EVENT SHALL ISC 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.
--->
-
-<refentry>
-
-  <refentryinfo>
-    <date>February 5, 2013</date>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>bind10</refentrytitle>
-    <manvolnum>8</manvolnum>
-    <refmiscinfo>BIND10</refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>bind10</refname>
-    <refpurpose>BIND 10 start script</refpurpose>
-  </refnamediv>
-
-  <docinfo>
-    <copyright>
-      <year>2013</year>
-      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
-    </copyright>
-  </docinfo>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>bind10</command>
-      <arg><option>options</option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>DESCRIPTION</title>
-
-    <para>The <command>bind10</command> script is a simple wrapper that
-    starts BIND 10 by running the <command>b10-init</command> daemon. All
-    options passed to <command>bind10</command> are directly passed on to
-    <command>b10-init</command>.</para>
-
-  </refsect1>
-
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citetitle>BIND 10 Guide</citetitle>.
-    </para>
-  </refsect1>
-
-  <refsect1 id='history'><title>HISTORY</title>
-    <para>The <command>bind10</command> script was added in February 2013.
-    </para>
-  </refsect1>
-
-</refentry>

+ 0 - 123
src/bin/bind10/creatorapi.txt

@@ -1,123 +0,0 @@
-Socket creator API
-==================
-
-This API is between Init and other modules to allow them requesting of sockets.
-For simplicity, we will use the socket creator for all (even non-privileged)
-ports for now, but we should have some function where we can abstract it later.
-
-Goals
------
-* Be able to request a socket of any combination IPv4/IPv6 UDP/TCP bound to given
-  port and address (sockets that are not bound to anything can be created
-  without privileges, therefore are not requested from the socket creator).
-* Allow to provide the same socket to multiple modules (eg. multiple running
-  auth servers).
-* Allow releasing the sockets (in case all modules using it give it up,
-  terminate or crash).
-* Allow restricting of the sharing (don't allow shared socket between auth
-  and recursive, as the packets would often get to the wrong application,
-  show error instead).
-* Get the socket to the application.
-
-Transport of sockets
---------------------
-It seems we are stuck with current msgq for a while and there's a chance the
-new replacement will not be able to send sockets inbound. So, we need another
-channel.
-
-b10-init will create a unix-domain socket and listen on it. When something
-requests a socket over the command channel and the socket is created, some kind
-of token is returned to the application (which will represent the future
-socket). The application then connects to the unix-domain socket, sends the
-token over the connection (so Init will know which socket to send there, in case
-multiple applications ask for sockets simultaneously) and Init sends the socket
-in return.
-
-In theory, we could send the requests directly over the unix-domain
-socket, but it has two disadvantages:
-* The msgq handles serializing/deserializing of structured
-  information (like the parameters to be used), we would have to do it
-  manually on the socket.
-* We could place some kind of security in front of msgq (in case file
-  permissions are not enough, for example if they are not honored on
-  socket files, as indicated in the first paragraph of:
-  http://lkml.indiana.edu/hypermail/linux/kernel/0505.2/0008.html).
-  The socket would have to be secured separately. With the tokens,
-  there's some level of security already - someone not having the
-  token can't request a priviledged socket.
-
-Caching of sockets
-------------------
-To allow sending the same socket to multiple application, the Init process will
-hold a cache. Each socket that is created and sent is kept open in Init and
-preserved there as well. A reference count is kept with each of them.
-
-When another application asks for the same socket, it is simply sent from the
-cache instead of creating it again by the creator.
-
-When application gives the socket willingly (by sending a message over the
-command channel), the reference count can be decreased without problems. But
-when the application terminates or crashes, we need to decrease it as well.
-There's a problem, since we don't know which command channel connection (eg.
-lname) belongs to which PID. Furthermore, the applications don't need to be
-started by b10-init.
-
-There are two possibilities:
-* Let the msgq send messages about disconnected clients (eg. group message to
-  some name). This one is better if we want to migrate to dbus, since dbus
-  already has this capability as well as sending the sockets inbound (at least it
-  seems so on unix) and we could get rid of the unix-domain socket completely.
-* Keep the unix-domain connections open forever. Init can remember which socket
-  was sent to which connection and when the connection closes (because the
-  application crashed), it can drop all the references on the sockets. This
-  seems easier to implement.
-
-The commands
-------------
-* Command to release a socket. This one would have single parameter, the token
-  used to get the socket. After this, b10-init would decrease its reference
-  count and if it drops to zero, close its own copy of the socket. This
-  should be used when the module stops using the socket (and after closes
-  it). The library could remember the file-descriptor to token mapping (for
-  common applications that don't request the same socket multiple times in
-  parallel).
-* Command to request a socket. It would have parameters to specify which socket
-  (IP address, address family, port) and how to allow sharing. Sharing would be
-  one of:
-  - None
-  - Same kind of application (however, it is not entirely clear what
-    this means, in case it won't work out intuitively, we'll need to
-    define it somehow)
-  - Any kind of application
-  And a kind of application would be provided, to decide if the sharing is
-  possible (eg. if auth allows sharing with the same kind and something else
-  allows sharing with anything, the sharing is not possible, two auths can).
-
-  It would return either error (the socket can't be created or sharing is not
-  possible) or the token. Then there would be some time for the application to
-  pick up the requested socket.
-
-Examples
---------
-We probably would have a library with blocking calls to request the
-sockets, so a code could look like:
-
-(socket_fd, token) = request_socket(address, port, 'UDP', SHARE_SAMENAME, 'test-application')
-sock = socket.fromfd(socket_fd)
-
-# Some sock.send and sock.recv stuff here
-
-sock.close()
-release_socket(socket_fd) # or release_socket(token)
-
-Known limitations
------------------
-Currently the socket creator doesn't support specifying any socket
-options. If it turns out there are any options that need to be set
-before bind(), we'll need to extend it (and extend the protocol as
-well). If we want to support them, we'll have to solve a possible
-conflict (what to do when two applications request the same socket and
-want to share it, but want different options).
-
-The current socket creator doesn't know raw sockets, but if they are
-needed, it should be easy to add.

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 1389
src/bin/bind10/init.py.in


+ 0 - 92
src/bin/bind10/init.spec

@@ -1,92 +0,0 @@
-{
-  "module_spec": {
-    "module_name": "Init",
-    "module_description": "Init process",
-    "config_data": [
-      {
-        "item_name": "components",
-        "item_type": "named_set",
-        "item_optional": false,
-        "item_default": {
-          "b10-stats": { "address": "Stats", "kind": "dispensable" },
-          "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
-        },
-        "named_set_item_spec": {
-          "item_name": "component",
-          "item_type": "map",
-          "item_optional": false,
-          "item_default": { },
-          "map_item_spec": [
-            {
-              "item_name": "special",
-              "item_optional": true,
-              "item_type": "string"
-            },
-            {
-              "item_name": "process",
-              "item_optional": true,
-              "item_type": "string"
-            },
-            {
-              "item_name": "kind",
-              "item_optional": false,
-              "item_type": "string",
-              "item_default": "dispensable"
-            },
-            {
-              "item_name": "address",
-              "item_optional": true,
-              "item_type": "string"
-            },
-            {
-              "item_name": "params",
-              "item_optional": true,
-              "item_type": "list",
-              "list_item_spec": {
-                "item_name": "param",
-                "item_optional": false,
-                "item_type": "string",
-                "item_default": ""
-              }
-            },
-            {
-              "item_name": "priority",
-              "item_optional": true,
-              "item_type": "integer"
-            }
-          ]
-        }
-      }
-    ],
-    "commands": [
-      {
-        "command_name": "shutdown",
-        "command_description": "Shut down BIND 10",
-        "command_args": []
-      },
-      {
-        "command_name": "ping",
-        "command_description": "Ping the b10-init process",
-        "command_args": []
-      },
-      {
-        "command_name": "show_processes",
-        "command_description": "List the running BIND 10 processes",
-        "command_args": []
-      }
-    ],
-    "statistics": [
-      {
-        "item_name": "boot_time",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "1970-01-01T00:00:00Z",
-        "item_title": "Boot time",
-        "item_description": "A date time when bind10 process starts initially",
-        "item_format": "date-time"
-      }
-    ]
-  }
-}
-
-

+ 0 - 334
src/bin/bind10/init_messages.mes

@@ -1,334 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
-#
-# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
-# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-# AND FITNESS.  IN NO EVENT SHALL ISC 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.
-
-# No namespace declaration - these constants go in the global namespace
-# of the xfrin messages python module.
-
-% BIND10_CHECK_MSGQ_ALREADY_RUNNING checking if msgq is already running
-The b10-init process is starting up and will now check if the message bus
-daemon is already running. If so, it will not be able to start, as it
-needs a dedicated message bus.
-
-% BIND10_COMPONENT_FAILED component %1 (pid %2) failed: %3
-The process terminated, but b10-init didn't expect it to, which means
-it must have failed.
-
-% BIND10_COMPONENT_RESTART component %1 is about to restart
-The named component failed previously and we will try to restart it to provide
-as flawless service as possible, but it should be investigated what happened,
-as it could happen again.
-
-% BIND10_COMPONENT_SHUTDOWN_ERROR An error occurred stopping component %1
-An attempt to gracefully shutdown a component failed.
-
-% BIND10_COMPONENT_START component %1 is starting
-The named component is about to be started by the b10-init process.
-
-% BIND10_COMPONENT_START_EXCEPTION component %1 failed to start: %2
-An exception (mentioned in the message) happened during the startup of the
-named component. The component is not considered started and further actions
-will be taken about it.
-
-% BIND10_COMPONENT_STOP component %1 is being stopped
-A component is about to be asked to stop willingly by the b10-init.
-
-% BIND10_COMPONENT_UNSATISFIED component %1 is required to run and failed
-A component failed for some reason (see previous messages). It is either a core
-component or needed component that was just started. In any case, the system
-can't continue without it and will terminate.
-
-% BIND10_CONFIGURATOR_BUILD building plan '%1' -> '%2'
-A debug message. This indicates that the configurator is building a plan
-how to change configuration from the older one to newer one. This does no
-real work yet, it just does the planning what needs to be done.
-
-% BIND10_CONFIGURATOR_PLAN_INTERRUPTED configurator plan interrupted, only %1 of %2 done
-There was an exception during some planned task. The plan will not continue and
-only some tasks of the plan were completed. The rest is aborted. The exception
-will be propagated.
-
-% BIND10_CONFIGURATOR_RECONFIGURE reconfiguring running components
-A different configuration of which components should be running is being
-installed. All components that are no longer needed will be stopped and
-newly introduced ones started. This happens at startup, when the configuration
-is read the first time, or when an operator changes configuration of the b10-init.
-
-% BIND10_CONFIGURATOR_RUN running plan of %1 tasks
-A debug message. The configurator is about to execute a plan of actions it
-computed previously.
-
-% BIND10_CONFIGURATOR_START bind10 component configurator is starting up
-The part that cares about starting and stopping the right component from
-the b10-init process is starting up. This happens only once at the startup
-of the b10-init process. It will start the basic set of processes now (the
-ones b10-init needs to read the configuration), the rest will be started
-after the configuration is known.
-
-% BIND10_CONFIGURATOR_STOP bind10 component configurator is shutting down
-The part that cares about starting and stopping processes in the b10-init is
-shutting down. All started components will be shut down now (more precisely,
-asked to terminate by their own, if they fail to comply, other parts of
-the b10-init process will try to force them).
-
-% BIND10_CONFIGURATOR_TASK performing task %1 on %2
-A debug message. The configurator is about to perform one task of the plan it
-is currently executing on the named component.
-
-% BIND10_CONNECTING_TO_CC_FAIL failed to connect to configuration/command channel; try -v to see output from msgq
-The b10-init process tried to connect to the communication channel for
-commands and configuration updates during initialization, but it
-failed.  This is a fatal startup error, and process will soon
-terminate after some cleanup.  There can be several reasons for the
-failure, but the most likely cause is that the msgq daemon failed to
-start, and the most likely cause of the msgq failure is that it
-doesn't have a permission to create a socket file for the
-communication.  To confirm that, you can see debug messages from msgq
-by starting BIND 10 with the -v command line option.  If it indicates
-permission problem for msgq, make sure the directory where the socket
-file is to be created is writable for the msgq process.  Note that if
-you specify the -u option to change process users, the directory must
-be writable for that user.
-
-% BIND10_INVALID_STATISTICS_DATA invalid specification of statistics data specified
-An error was encountered when the b10-init module specified
-statistics data which is invalid for the b10-init specification file.
-
-% BIND10_INVALID_USER invalid user: %1
-The b10-init process was started with the -u option, to drop root privileges
-and continue running as the specified user, but the user is unknown.
-
-% BIND10_KILLING_ALL_PROCESSES killing all started processes
-The b10-init module was not able to start every process it needed to start
-during startup, and will now kill the processes that did get started.
-
-% BIND10_LOST_SOCKET_CONSUMER consumer %1 of sockets disconnected, considering all its sockets closed
-A connection from one of the applications which requested a socket was
-closed. This means the application has terminated, so all the sockets it was
-using are now closed and bind10 process can release them as well, unless the
-same sockets are used by yet another application.
-
-% BIND10_MSGQ_ALREADY_RUNNING msgq daemon already running, cannot start
-There already appears to be a message bus daemon running. Either an
-old process was not shut down correctly, and needs to be killed, or
-another instance of BIND10, with the same msgq domain socket, is
-running, which needs to be stopped.
-
-% BIND10_MSGQ_DISAPPEARED msgq channel disappeared
-While listening on the message bus channel for messages, it suddenly
-disappeared. The msgq daemon may have died. This might lead to an
-inconsistent state of the system, and BIND 10 will now shut down.
-
-% BIND10_NO_SOCKET couldn't send a socket for token %1 because of error: %2
-An error occurred when the bind10 process was asked to send a socket file
-descriptor. The error is mentioned, most common reason is that the request
-is invalid and may not come from bind10 process at all.
-
-% BIND10_PROCESS_ENDED process %2 of %1 ended with status %3
-This indicates a process started previously terminated. The process id
-and component owning the process are indicated, as well as the exit code.
-This doesn't distinguish if the process was supposed to terminate or not.
-
-% BIND10_READING_INIT_CONFIGURATION reading b10-init configuration
-The b10-init process is starting up, and will now process the initial
-configuration, as received from the configuration manager.
-
-% BIND10_RECEIVED_COMMAND received command: %1
-The b10-init module received a command and shall now process it. The command
-is printed.
-
-% BIND10_RECEIVED_NEW_CONFIGURATION received new configuration: %1
-The b10-init module received a configuration update and is going to apply
-it now. The new configuration is printed.
-
-% BIND10_RECEIVED_SIGNAL received signal %1
-The b10-init module received the given signal.
-
-% BIND10_RECONFIGURE_ERROR Error applying new config: %1
-A new configuration was received, but there was an error doing the
-re-configuration.
-
-% BIND10_RESTART_COMPONENT_SKIPPED Skipped restarting a component %1
-The b10-init module tried to restart a component after it failed (crashed)
-unexpectedly, but the b10-init then found that the component had been removed
-from its local configuration of components to run.  This is an unusual
-situation but can happen if the administrator removes the component from
-the configuration after the component's crash and before the restart time.
-The b10-init module simply skipped restarting that module, and the whole system
-went back to the expected state (except that the crash itself is likely
-to be a bug).
-
-% BIND10_RESURRECTED_PROCESS resurrected %1 (PID %2)
-The given process has been restarted successfully, and is now running
-with the given process id.
-
-% BIND10_RESURRECTING_PROCESS resurrecting dead %1 process...
-The given process has ended unexpectedly, and is now restarted.
-
-% BIND10_SELECT_ERROR error in select() call: %1
-There was a fatal error in the call to select(), used to see if a child
-process has ended or if there is a message on the message bus. This
-should not happen under normal circumstances and is considered fatal,
-so BIND 10 will now shut down. The specific error is printed.
-
-% BIND10_SEND_SIGKILL sending SIGKILL to %1 (PID %2)
-The b10-init module is sending a SIGKILL signal to the given process.
-
-% BIND10_SEND_SIGNAL_FAIL sending %1 to %2 (PID %3) failed: %4
-The b10-init module sent a single (either SIGTERM or SIGKILL) to a process,
-but it failed due to some system level error.  There are two major cases:
-the target process has already terminated but the b10-init module had sent
-the signal before it noticed the termination.  In this case an error
-message should indicate something like "no such process".  This can be
-safely ignored.  The other case is that the b10-init module doesn't have
-the privilege to send a signal to the process.  It can typically
-happen when the b10-init module started as a privileged process, spawned a
-subprocess, and then dropped the privilege.  It includes the case for
-the socket creator when the b10-init process runs with the -u command line
-option.  In this case, the b10-init module simply gives up to terminate
-the process explicitly because it's unlikely to succeed by keeping
-sending the signal.  Although the socket creator is implemented so
-that it will terminate automatically when the b10-init process exits
-(and that should be the case for any other future process running with
-a higher privilege), but it's recommended to check if there's any
-remaining BIND 10 process if this message is logged.  For all other
-cases, the b10-init module will keep sending the signal until it confirms
-all child processes terminate.  Although unlikely, this could prevent
-the b10-init module from exiting, just keeping sending the signals.  So,
-again, it's advisable to check if it really terminates when this
-message is logged.
-
-% BIND10_SEND_SIGTERM sending SIGTERM to %1 (PID %2)
-The b10-init module is sending a SIGTERM signal to the given process.
-
-% BIND10_SETGID setting GID to %1
-The b10-init switches the process group ID to the given value.  This happens
-when BIND 10 starts with the -u option, and the group ID will be set to
-that of the specified user.
-
-% BIND10_SETUID setting UID to %1
-The b10-init switches the user it runs as to the given UID.
-
-% BIND10_SHUTDOWN stopping the server
-The b10-init process received a command or signal telling it to shut down.
-It will send a shutdown command to each process. The processes that do
-not shut down will then receive a SIGTERM signal. If that doesn't work,
-it shall send SIGKILL signals to the processes still alive.
-
-% BIND10_SHUTDOWN_COMPLETE all processes ended, shutdown complete
-All child processes have been stopped, and the b10-init process will now
-stop itself.
-
-% BIND10_SOCKCREATOR_BAD_CAUSE unknown error cause from socket creator: %1
-The socket creator reported an error when creating a socket. But the function
-which failed is unknown (not one of 'S' for socket or 'B' for bind).
-
-% BIND10_SOCKCREATOR_BAD_RESPONSE unknown response for socket request: %1
-The b10-init requested a socket from the creator, but the answer is unknown. This
-looks like a programmer error.
-
-% BIND10_SOCKCREATOR_EOF eof while expecting data from socket creator
-There should be more data from the socket creator, but it closed the socket.
-It probably crashed.
-
-% BIND10_SOCKCREATOR_INIT initializing socket creator parser
-The b10-init module initializes routines for parsing the socket creator
-protocol.
-
-% BIND10_SOCKCREATOR_KILL killing the socket creator
-The socket creator is being terminated the aggressive way, by sending it
-sigkill. This should not happen usually.
-
-% BIND10_SOCKCREATOR_TERMINATE terminating socket creator
-The b10-init module sends a request to terminate to the socket creator.
-
-% BIND10_SOCKCREATOR_TRANSPORT_ERROR transport error when talking to the socket creator: %1
-Either sending or receiving data from the socket creator failed with the given
-error. The creator probably crashed or some serious OS-level problem happened,
-as the communication happens only on local host.
-
-% BIND10_SOCKET_CREATED successfully created socket %1
-The socket creator successfully created and sent a requested socket, it has
-the given file number.
-
-% BIND10_SOCKET_ERROR error on %1 call in the creator: %2/%3
-The socket creator failed to create the requested socket. It failed on the
-indicated OS API function with given error.
-
-% BIND10_SOCKET_GET requesting socket [%1]:%2 of type %3 from the creator
-The b10-init forwards a request for a socket to the socket creator.
-
-% BIND10_STARTED_CC started configuration/command session
-Debug message given when BIND 10 has successfully started the object that
-handles configuration and commands.
-
-% BIND10_STARTED_PROCESS started %1
-The given process has successfully been started.
-
-% BIND10_STARTED_PROCESS_PID started %1 (PID %2)
-The given process has successfully been started, and has the given PID.
-
-% BIND10_STARTING starting BIND10: %1
-Informational message on startup that shows the full version.
-
-% BIND10_STARTING_CC starting configuration/command session
-Informational message given when BIND 10 is starting the session object
-that handles configuration and commands.
-
-% BIND10_STARTING_PROCESS starting process %1
-The b10-init module is starting the given process.
-
-% BIND10_STARTING_PROCESS_PORT starting process %1 (to listen on port %2)
-The b10-init module is starting the given process, which will listen on the
-given port number.
-
-% BIND10_STARTING_PROCESS_PORT_ADDRESS starting process %1 (to listen on %2)
-The b10-init module is starting the given process, which will listen on the
-given address and port number (written as <address>:<port>).
-
-% BIND10_STARTUP_COMPLETE BIND 10 started
-All modules have been successfully started, and BIND 10 is now running.
-
-% BIND10_STARTUP_ERROR error during startup: %1
-There was a fatal error when BIND10 was trying to start. The error is
-shown, and BIND10 will now shut down.
-
-% BIND10_STARTUP_UNEXPECTED_MESSAGE unrecognised startup message %1
-During the startup process, a number of messages are exchanged between the
-Init process and the processes it starts.  This error is output when a
-message received by the Init process is recognised as being of the
-correct format but is unexpected.  It may be that processes are starting
-of sequence.
-
-% BIND10_STARTUP_UNRECOGNISED_MESSAGE unrecognised startup message %1
-During the startup process, a number of messages are exchanged between the
-Init process and the processes it starts.  This error is output when a
-message received by the Init process is not recognised.
-
-% BIND10_STOP_PROCESS asking %1 to shut down
-The b10-init module is sending a shutdown command to the given module over
-the message channel.
-
-% BIND10_UNKNOWN_CHILD_PROCESS_ENDED unknown child pid %1 exited
-An unknown child process has exited. The PID is printed, but no further
-action will be taken by the b10-init process.
-
-% BIND10_WAIT_CFGMGR waiting for configuration manager process to initialize
-The configuration manager process is so critical to operation of BIND 10
-that after starting it, the Init module will wait for it to initialize
-itself before continuing.  This debug message is produced during the
-wait and may be output zero or more times depending on how long it takes
-the configuration manager to start up.  The total length of time Init
-will wait for the configuration manager before reporting an error is
-set with the command line --wait switch, which has a default value of
-ten seconds.

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 49
src/bin/bind10/run_bind10.sh.in


+ 0 - 1
src/bin/bind10/tests/.gitignore

@@ -1 +0,0 @@
-/init_test.py

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 29
src/bin/bind10/tests/Makefile.am


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

@@ -1,172 +0,0 @@
-# Copyright (C) 2010,2013  Internet Systems Consortium.
-#
-# 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.
-
-"""
-This program tests the b10-init process to make sure that it runs while
-dropping permissions. It must be run as a user that can set permission.
-"""
-import unittest
-import os
-import sys
-import subprocess
-import select
-import time
-import pwd
-
-# Set to a valid user name on the system to run setuid() test
-#SUID_USER=None
-SUID_USER="shane"
-
-BIND10_EXE="../run_bind10.sh"
-TIMEOUT=3
-
-class TestInitArgs(unittest.TestCase):
-    def _waitForString(self, init, s):
-        found_string = False
-        start_time = time.time()
-        while time.time() < start_time + TIMEOUT:
-            (r,w,x) = select.select((init.stdout,), (), (), TIMEOUT)
-            if init.stdout in r:
-                s = init.stdout.readline()
-                if s == '':
-                    break
-                if s.startswith(s):
-                    found_string = True
-                    break
-        return found_string
-
-    def testNoArgs(self):
-        """Run bind10 without any arguments"""
-        init = subprocess.Popen(args=(BIND10_EXE,),
-                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        started_ok = self._waitForString(init, '[bind10] BIND 10 started')
-        time.sleep(0.1)
-        init.terminate()
-        init.wait()
-        self.assertTrue(started_ok)
-
-    def testBadOption(self):
-        """Run bind10 with a bogus option"""
-        init = subprocess.Popen(args=(BIND10_EXE, "--badoption"),
-                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        failed = self._waitForString(init, 'bind10: error: no such option: --badoption')
-        time.sleep(0.1)
-        init.terminate()
-        self.assertTrue(init.wait() == 2)
-        self.assertTrue(failed)
-
-    def testArgument(self):
-        """Run bind10 with an argument (this is not allowed)"""
-        init = subprocess.Popen(args=(BIND10_EXE, "argument"),
-                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        failed = self._waitForString(init, 'Usage: bind10 [options]')
-        time.sleep(0.1)
-        init.terminate()
-        self.assertTrue(init.wait() == 1)
-        self.assertTrue(failed)
-
-    def testBadUser(self):
-        """Run bind10 with a bogus user"""
-        init = subprocess.Popen(args=(BIND10_EXE, "-u", "bogus_user"),
-                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        failed = self._waitForString(init, "bind10: invalid user: 'bogus_user'")
-        time.sleep(0.1)
-        init.terminate()
-        self.assertTrue(init.wait() == 1)
-        self.assertTrue(failed)
-
-    def testBadUid(self):
-        """Run bind10 with a bogus user ID"""
-        init = subprocess.Popen(args=(BIND10_EXE, "-u", "999999999"),
-                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        failed = self._waitForString(init, "bind10: invalid user: '999999999'")
-        time.sleep(0.1)
-        init.terminate()
-        self.assertTrue(init.wait() == 1)
-        self.assertTrue(failed)
-
-    def testFailSetUser(self):
-        """Try the -u option when we don't run as root"""
-        global SUID_USER
-        if SUID_USER is None:
-            self.skipTest("test needs a valid user (set when run)")
-        if os.getuid() == 0:
-            self.skipTest("test must not be run as root (uid is 0)")
-        # XXX: we depend on the "nobody" user
-        init = subprocess.Popen(args=(BIND10_EXE, "-u", "nobody"),
-                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        failed = self._waitForString(init, "[bind10] Error on startup: Unable to start b10-msgq; Unable to change to user nobody")
-        time.sleep(0.1)
-        init.terminate()
-        self.assertTrue(init.wait() == 1)
-        self.assertTrue(failed)
-
-    def testSetUser(self):
-        """Try the -u option"""
-        global SUID_USER
-        if SUID_USER is None:
-            self.skipTest("test needs a valid user (set when run)")
-        if os.getuid() != 0:
-            self.skipTest("test must run as root (uid is not 0)")
-        if os.geteuid() != 0:
-            self.skipTest("test must run as root (euid is not 0)")
-
-        init = subprocess.Popen(args=(BIND10_EXE, "-u", SUID_USER),
-                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        started_ok = self._waitForString(init, '[bind10] BIND 10 started')
-        self.assertTrue(started_ok)
-        ps = subprocess.Popen(args=("ps", "axo", "user,pid"),
-                              stdout=subprocess.PIPE)
-        s = ps.stdout.readline()
-        ps_user = None
-        while True:
-            s = ps.stdout.readline()
-            if s == '': break
-            (user, pid) = s.split()
-            if int(pid) == init.pid:
-                ps_user = user.decode()
-                break
-        self.assertTrue(ps_user is not None)
-        self.assertTrue(ps_user == SUID_USER)
-        time.sleep(0.1)
-        init.terminate()
-        x = init.wait()
-        self.assertTrue(init.wait() == 0)
-
-    def testPrettyName(self):
-        """Try the --pretty-name option."""
-        CMD_PRETTY_NAME = b'init-name-test'
-        init = subprocess.Popen(args=(BIND10_EXE, '--pretty-name',
-            CMD_PRETTY_NAME), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        started_ok = self._waitForString(init, '[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) == init.pid:
-                command = comm
-                break
-        self.assertEqual(command, CMD_PRETTY_NAME + b'\n')
-        time.sleep(0.1)
-        init.terminate()
-        init.wait()
-
-if __name__ == '__main__':
-    unittest.main()

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 2489
src/bin/bind10/tests/init_test.py.in


+ 0 - 4
src/bin/bindctl/.gitignore

@@ -1,4 +0,0 @@
-/bindctl
-/bindctl_main.py
-/run_bindctl.sh
-/bindctl.1

+ 0 - 41
src/bin/bindctl/Makefile.am

@@ -1,41 +0,0 @@
-SUBDIRS = . tests
-
-bin_SCRIPTS = bindctl
-man_MANS = bindctl.1
-
-EXTRA_DIST = $(man_MANS) bindctl.xml
-
-noinst_SCRIPTS = run_bindctl.sh
-
-python_PYTHON = __init__.py bindcmd.py cmdparse.py exception.py moduleinfo.py \
-		mycollections.py command_sets.py
-pythondir = $(pyexecdir)/bindctl
-
-bindctldir = $(pkgdatadir)
-
-CLEANFILES = bindctl bindctl_main.pyc
-DISTCLEANFILES = $(man_MANS)
-
-if GENERATE_DOCS
-
-bindctl.1: bindctl.xml
-	@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/bindctl.xml
-
-else
-
-$(man_MANS):
-	@echo Man generation disabled.  Creating dummy $@.  Configure with --enable-generate-docs to enable it.
-	@echo Man generation disabled.  Remove this file, configure with --enable-generate-docs, and rebuild BIND 10 > $@
-
-endif
-
-bindctl: bindctl_main.py
-	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
-	       -e "s|@@SYSCONFDIR@@|@sysconfdir@|" \
-	       -e "s|@@LIBEXECDIR@@|$(pkglibexecdir)|" bindctl_main.py >$@
-	chmod a+x $@
-
-CLEANDIRS = __pycache__
-
-clean-local:
-	rm -rf $(CLEANDIRS)

+ 0 - 2
src/bin/bindctl/README

@@ -1,2 +0,0 @@
-1. Start bindctl by run command "sh bindctl".
-2. Login to b10-cmdctl with the username and password. The username and password will be saved in file default_user.csv automatically after logining successfully, so next time bindctl will login with the username and password saved in default_user.csv. For more usage information, please turn to "man bindctl".

+ 0 - 21
src/bin/bindctl/TODO

@@ -1,21 +0,0 @@
-1. Refactor the code for bindctl.
-2. Update man page for bindctl provided by jreed.
-3. Add more unit tests.
-4. Need Review(When command line syntax is changed later, the following 
-functions should be updated first.):
-        bindcmd.py:
-            apply_config_cmd()
-            _validate_cmd()
-            complete()
-            
-        cmdparse.py:
-            _parse_params
-
-        moduleinfo.py:
-            get_param_name_by_position
-5. Understandable error message when cert_file is missing.
-6. Pick location to save default user. Or use the cfgmgr for this.
-   If the default user is saved in file, its password shouldn't be saved in plaintext.
-7. Need to think of what exactly to do with responses received to commands
-   (currently it simply print the map)
-8. Remove bindctl-source.py.in(replace with bindctl-source.py) when merging to trunk.

+ 0 - 1
src/bin/bindctl/__init__.py

@@ -1 +0,0 @@
-__all__ = ['mycollections', 'exception', 'moduleinfo', 'command', 'bindctl']

+ 0 - 945
src/bin/bindctl/bindcmd.py

@@ -1,945 +0,0 @@
-# Copyright (C) 2009  Internet Systems Consortium.
-#
-# 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.
-
-"""This module holds the BindCmdInterpreter class. This provides the
-   core functionality for bindctl. It maintains a session with
-   b10-cmdctl, holds local configuration and module information, and
-   handles command line interface commands"""
-
-import sys
-from cmd import Cmd
-from bindctl.exception import *
-from bindctl.moduleinfo import *
-from bindctl.cmdparse import BindCmdParser
-from bindctl import command_sets
-from xml.dom import minidom
-import isc.config
-import isc.cc.data
-import http.client
-import json
-import inspect
-import pprint
-import ssl, socket
-import os, time, random, re
-import os.path
-import getpass
-from hashlib import sha1
-import csv
-import pwd
-import getpass
-import copy
-import errno
-
-try:
-    from collections import OrderedDict
-except ImportError:
-    from bindctl.mycollections import OrderedDict
-
-# if we have readline support, use that, otherwise use normal stdio
-try:
-    import readline
-    # Only consider spaces as word boundaries; identifiers can contain
-    # '/' and '[]', and configuration item names can in theory use any
-    # printable  character. See the discussion in tickets #1345 and
-    # #2254 for more information.
-    readline.set_completer_delims(' ')
-
-    my_readline = readline.get_line_buffer
-except ImportError:
-    my_readline = sys.stdin.readline
-
-# Used for tab-completion of 'identifiers' (i.e. config values)
-# If a command parameter has this name, the tab completion hints
-# are derived from config data
-CFGITEM_IDENTIFIER_PARAM = 'identifier'
-
-CSV_FILE_NAME = 'default_user.csv'
-CONFIG_MODULE_NAME = 'config'
-CONST_BINDCTL_HELP = """
-usage: <module name> <command name> [param1 = value1 [, param2 = value2]]
-Type Tab character to get the hint of module/command/parameters.
-Type \"help(? h)\" for help on bindctl.
-Type \"<module_name> help\" for help on the specific module.
-Type \"<module_name> <command_name> help\" for help on the specific command.
-\nAvailable module names: """
-
-class ValidatedHTTPSConnection(http.client.HTTPSConnection):
-    '''Overrides HTTPSConnection to support certification
-    validation. '''
-    def __init__(self, host, ca_certs):
-        http.client.HTTPSConnection.__init__(self, host)
-        self.ca_certs = ca_certs
-
-    def connect(self):
-        ''' Overrides the connect() so that we do
-        certificate validation. '''
-        sock = socket.create_connection((self.host, self.port),
-                                        self.timeout)
-        if self._tunnel_host:
-            self.sock = sock
-            self._tunnel()
-
-        req_cert = ssl.CERT_NONE
-        if self.ca_certs:
-            req_cert = ssl.CERT_REQUIRED
-        self.sock = ssl.wrap_socket(sock, self.key_file,
-                                    self.cert_file,
-                                    cert_reqs=req_cert,
-                                    ca_certs=self.ca_certs)
-
-class BindCmdInterpreter(Cmd):
-    """simple bindctl example."""
-
-    def __init__(self, server_port='localhost:8080', pem_file=None,
-                 csv_file_dir=None):
-        Cmd.__init__(self)
-        self.location = ""
-        self.prompt_end = '> '
-        if sys.stdin.isatty():
-            self.prompt = self.prompt_end
-        else:
-            self.prompt = ""
-        self.ruler = '-'
-        self.modules = OrderedDict()
-        self.add_module_info(ModuleInfo("help", desc = "Get help for bindctl."))
-        self.server_port = server_port
-        self.conn = ValidatedHTTPSConnection(self.server_port,
-                                             ca_certs=pem_file)
-        self.session_id = self._get_session_id()
-        self.config_data = None
-        if csv_file_dir is not None:
-            self.csv_file_dir = csv_file_dir
-        else:
-            self.csv_file_dir = pwd.getpwnam(getpass.getuser()).pw_dir + \
-                os.sep + '.bind10' + os.sep
-
-    def _print(self, *args):
-        '''Simple wrapper around calls to print that can be overridden in
-           unit tests.'''
-        print(*args)
-
-    def _get_session_id(self):
-        '''Generate one session id for the connection. '''
-        rand = os.urandom(16)
-        now = time.time()
-        session_id = sha1(("%s%s%s" %(rand, now,
-                                      socket.gethostname())).encode())
-        digest = session_id.hexdigest()
-        return digest
-
-    def run(self):
-        '''Parse commands from user and send them to cmdctl.'''
-
-        # Show helper warning about a well known issue.  We only do this
-        # when stdin is attached to a terminal, because otherwise it doesn't
-        # matter and is just noisy, and could even be harmful if the output
-        # is processed by a script that expects a specific format.
-        if my_readline == sys.stdin.readline and sys.stdin.isatty():
-            sys.stdout.write("""\
-WARNING: The Python readline module isn't available, so some command line
-         editing features (including command history management) will not
-         work.  See the BIND 10 guide for more details.\n\n""")
-
-        try:
-            if not self.login_to_cmdctl():
-                return 1
-
-            self.cmdloop()
-            self._print('\nExit from bindctl')
-            return 0
-        except FailToLogin as err:
-            # error already printed when this was raised, ignoring
-            return 1
-        except KeyboardInterrupt:
-            self._print('\nExit from bindctl')
-            return 0
-        except socket.error as err:
-            self._print('Failed to send request, the connection is closed')
-            return 1
-        except http.client.CannotSendRequest:
-            self._print('Can not send request, the connection is busy')
-            return 1
-
-    def _get_saved_user_info(self, dir, file_name):
-        ''' Read all the available username and password pairs saved in
-        file(path is "dir + file_name"), Return value is one list of elements
-        ['name', 'password'], If get information failed, empty list will be
-        returned.'''
-        if (not dir) or (not os.path.exists(dir)):
-            return []
-
-        try:
-            csvfile = None
-            users = []
-            csvfile = open(dir + file_name)
-            users_info = csv.reader(csvfile)
-            for row in users_info:
-                users.append([row[0], row[1]])
-        except (IOError, IndexError) as err:
-            self._print("Error reading saved username and password "
-                        "from %s%s: %s" % (dir, file_name, err))
-        finally:
-            if csvfile:
-                csvfile.close()
-            return users
-
-    def _save_user_info(self, username, passwd, dir, file_name):
-        ''' Save username and password in file "dir + file_name"
-        If it's saved properly, return True, or else return False. '''
-        try:
-            if not os.path.exists(dir):
-                os.mkdir(dir, 0o700)
-
-            csvfilepath = dir + file_name
-            csvfile = open(csvfilepath, 'w')
-            os.chmod(csvfilepath, 0o600)
-            writer = csv.writer(csvfile)
-            writer.writerow([username, passwd])
-            csvfile.close()
-        except IOError as err:
-            self._print("Error saving user information:", err)
-            self._print("user info file name: %s%s" % (dir, file_name))
-            return False
-
-        return True
-
-    def _try_login(self, username, password):
-        '''
-        Attempts to log into cmdctl by sending a POST with the given
-        username and password. On success of the POST (not the login,
-        but the network operation), it returns a tuple (response, data).
-        We check for some failures such as SSL errors and socket errors
-        which could happen due to the environment in which BIND 10 runs.
-        On failure, it raises a FailToLogin exception and prints some
-        information on the failure.  This call is essentially 'private',
-        but made 'protected' for easier testing.
-        '''
-        param = {'username': username, 'password' : password}
-        try:
-            response = self.send_POST('/login', param)
-            data = response.read().decode()
-            # return here (will raise error after try block)
-            return (response, data)
-        except (ssl.SSLError, socket.error) as err:
-            self._print('Error while sending login information:', err)
-            pass
-        raise FailToLogin()
-
-    def login_to_cmdctl(self):
-        '''Login to cmdctl with the username and password given by
-        the user. After the login is sucessful, the username and
-        password will be saved in 'default_user.csv', when run the next
-        time, username and password saved in 'default_user.csv' will be
-        used first.
-        '''
-        # Look at existing username/password combinations and try to log in
-        users = self._get_saved_user_info(self.csv_file_dir, CSV_FILE_NAME)
-        for row in users:
-            response, data = self._try_login(row[0], row[1])
-
-            if response.status == http.client.OK:
-                # Is interactive?
-                if sys.stdin.isatty():
-                    self._print(data + ' login as ' + row[0])
-                return True
-
-        # No valid logins were found, prompt the user for a username/password
-        count = 0
-        if not os.path.exists(self.csv_file_dir + CSV_FILE_NAME):
-            self._print('\nNo stored password file found.\n\n'
-                        'When the system is first set up you need to create '
-                        'at least one user account.\n'
-                        'For information on how to set up a BIND 10 system, '
-                        'please check see the\n'
-                        'BIND 10 Guide: \n\n'
-                        'http://bind10.isc.org/docs/bind10-guide.html#quick-start-auth-dns\n\n'
-
-                        'If a user account has been set up, please check the '
-                        'b10-cmdctl log for other\n'
-                        'information.\n')
-        else:
-            self._print('Login failed: either the user name or password is '
-                        'invalid.\n')
-
-        # If this was not an interactive session do not prompt for login info.
-        if not sys.stdin.isatty():
-            return False
-
-        while True:
-            count = count + 1
-            if count > 3:
-                self._print("Too many authentication failures")
-                return False
-
-            username = input("Username: ")
-            passwd = getpass.getpass()
-
-            response, data = self._try_login(username, passwd)
-            self._print(data)
-
-            if response.status == http.client.OK:
-                self._save_user_info(username, passwd, self.csv_file_dir,
-                                     CSV_FILE_NAME)
-                return True
-
-    def _update_commands(self):
-        '''Update the commands of all modules. '''
-        for module_name in self.config_data.get_config_item_list():
-            self._prepare_module_commands(self.config_data.get_module_spec(module_name))
-
-    def _send_message(self, url, body):
-        headers = {"cookie" : self.session_id}
-        self.conn.request('GET', url, body, headers)
-        res = self.conn.getresponse()
-        return res.status, res.read()
-
-    def send_GET(self, url, body = None):
-        '''Send GET request to cmdctl, session id is send with the name
-        'cookie' in header.
-        '''
-        status, reply_msg = self._send_message(url, body)
-        if status == http.client.UNAUTHORIZED:
-            if self.login_to_cmdctl():
-                # successful, so try send again
-                status, reply_msg = self._send_message(url, body)
-
-        if reply_msg:
-            return json.loads(reply_msg.decode())
-        else:
-            return {}
-
-
-    def send_POST(self, url, post_param=None):
-        '''Send POST request to cmdctl, session id is send with the name
-        'cookie' in header.
-        Format: /module_name/command_name
-        parameters of command is encoded as a map
-        '''
-        param = None
-        if post_param is not None and len(post_param) != 0:
-            param = json.dumps(post_param)
-
-        headers = {"cookie" : self.session_id}
-        self.conn.request('POST', url, param, headers)
-        return self.conn.getresponse()
-
-    def _update_all_modules_info(self):
-        ''' Get all modules' information from cmdctl, including
-        specification file and configuration data. This function
-        should be called before interpreting command line or complete-key
-        is entered. This may not be the best way to keep bindctl
-        and cmdctl share same modules information, but it works.'''
-        if self.config_data is not None:
-            self.config_data.update_specs_and_config()
-        else:
-            self.config_data = isc.config.UIModuleCCSession(self)
-        self._update_commands()
-
-    def precmd(self, line):
-        if line != 'EOF':
-            self._update_all_modules_info()
-        return line
-
-    def postcmd(self, stop, line):
-        '''Update the prompt after every command, but only if we
-           have a tty as output'''
-        if sys.stdin.isatty():
-            self.prompt = self.location + self.prompt_end
-        return stop
-
-    def _prepare_module_commands(self, module_spec):
-        '''Prepare the module commands'''
-        module = ModuleInfo(name = module_spec.get_module_name(),
-                            desc = module_spec.get_module_description())
-        for command in module_spec.get_commands_spec():
-            cmd = CommandInfo(name = command["command_name"],
-                              desc = command["command_description"])
-            for arg in command["command_args"]:
-                param = ParamInfo(name = arg["item_name"],
-                                  type = arg["item_type"],
-                                  optional = bool(arg["item_optional"]),
-                                  param_spec = arg)
-                if ("item_default" in arg):
-                    param.default = arg["item_default"]
-                if ("item_description" in arg):
-                    param.desc = arg["item_description"]
-                cmd.add_param(param)
-            module.add_command(cmd)
-        self.add_module_info(module)
-
-    def _validate_cmd(self, cmd):
-        '''validate the parameters and merge some parameters together,
-        merge algorithm is based on the command line syntax, later, if
-        a better command line syntax come out, this function should be
-        updated first.
-        '''
-        if not cmd.module in self.modules:
-            raise CmdUnknownModuleSyntaxError(cmd.module)
-
-        module_info = self.modules[cmd.module]
-        if not module_info.has_command_with_name(cmd.command):
-            raise CmdUnknownCmdSyntaxError(cmd.module, cmd.command)
-
-        command_info = module_info.get_command_with_name(cmd.command)
-        manda_params = command_info.get_mandatory_param_names()
-        all_params = command_info.get_param_names()
-
-        # If help is entered, don't do further parameter validation.
-        for val in cmd.params.keys():
-            if val == "help":
-                return
-
-        params = cmd.params.copy()
-        if not params and manda_params:
-            raise CmdMissParamSyntaxError(cmd.module, cmd.command, manda_params[0])
-        elif params and not all_params:
-            raise CmdUnknownParamSyntaxError(cmd.module, cmd.command,
-                                             list(params.keys())[0])
-        elif params:
-            param_name = None
-            param_count = len(params)
-            for name in params:
-                # either the name of the parameter must be known, or
-                # the 'name' must be an integer (ie. the position of
-                # an unnamed argument
-                if type(name) == int:
-                    # lump all extraneous arguments together as one big final one
-                    # todo: check if last param type is a string?
-                    while (param_count > 2 and
-                           param_count > len(command_info.params) - 1):
-                        params[param_count - 2] += " " + params[param_count - 1]
-                        del(params[param_count - 1])
-                        param_count = len(params)
-                        cmd.params = params.copy()
-
-                    # (-1, help is always in the all_params list)
-                    if name >= len(all_params) - 1:
-                        # add to last known param
-                        if param_name:
-                            cmd.params[param_name] += cmd.params[name]
-                        else:
-                            raise CmdUnknownParamSyntaxError(cmd.module, cmd.command, cmd.params[name])
-                    else:
-                        # replace the numbered items by named items
-                        param_name = command_info.get_param_name_by_position(name, param_count)
-                        cmd.params[param_name] = cmd.params[name]
-                        del cmd.params[name]
-
-                elif not name in all_params:
-                    raise CmdUnknownParamSyntaxError(cmd.module, cmd.command, name)
-
-            param_nr = 0
-            for name in manda_params:
-                if not name in params and not param_nr in params:
-                    raise CmdMissParamSyntaxError(cmd.module, cmd.command, name)
-                param_nr += 1
-
-        # Convert parameter value according to parameter spec
-        # file. Ignore check for commands belonging to module 'config'
-        # or 'execute'.
-        if cmd.module != CONFIG_MODULE_NAME and\
-           cmd.module != command_sets.EXECUTE_MODULE_NAME:
-            for param_name in cmd.params:
-                param_spec = command_info.get_param_with_name(param_name).param_spec
-                try:
-                    cmd.params[param_name] = isc.config.config_data.convert_type(param_spec, cmd.params[param_name])
-                except isc.cc.data.DataTypeError as e:
-                    raise isc.cc.data.DataTypeError('Invalid parameter value for \"%s\", the type should be \"%s\" \n'
-                                                     % (param_name, param_spec['item_type']) + str(e))
-
-    def _handle_cmd(self, cmd):
-        '''Handle a command entered by the user'''
-        if cmd.command == "help" or ("help" in cmd.params.keys()):
-            self._handle_help(cmd)
-        elif cmd.module == CONFIG_MODULE_NAME:
-            self.apply_config_cmd(cmd)
-        elif cmd.module == command_sets.EXECUTE_MODULE_NAME:
-            self.apply_execute_cmd(cmd)
-        else:
-            self.apply_cmd(cmd)
-
-    def add_module_info(self, module_info):
-        '''Add the information about one module'''
-        self.modules[module_info.name] = module_info
-
-    def get_module_names(self):
-        '''Return the names of all known modules'''
-        return list(self.modules.keys())
-
-    #override methods in cmd
-    def default(self, line):
-        self._parse_cmd(line)
-
-    def emptyline(self):
-        pass
-
-    def do_help(self, name):
-        self._print(CONST_BINDCTL_HELP)
-        for k in self.modules.values():
-            n = k.get_name()
-            if len(n) >= CONST_BINDCTL_HELP_INDENT_WIDTH:
-                self._print("    %s" % n)
-                self._print(textwrap.fill(k.get_desc(),
-                            initial_indent="            ",
-                            subsequent_indent="    " +
-                            " " * CONST_BINDCTL_HELP_INDENT_WIDTH,
-                            width=70))
-            else:
-                self._print(textwrap.fill("%s%s%s" %
-                            (k.get_name(),
-                            " "*(CONST_BINDCTL_HELP_INDENT_WIDTH -
-                                 len(k.get_name())),
-                            k.get_desc()),
-                            initial_indent="    ",
-                            subsequent_indent="    " +
-                            " " * CONST_BINDCTL_HELP_INDENT_WIDTH,
-                            width=70))
-
-    def onecmd(self, line):
-        if line == 'EOF' or line.lower() == "quit":
-            self.conn.close()
-            return True
-
-        if line == 'h':
-            line = 'help'
-
-        Cmd.onecmd(self, line)
-
-    def _get_identifier_startswith(self, id_text):
-        """Return the tab-completion hints for identifiers starting with
-           id_text.
-
-           Parameters:
-           id_text (string): the currently entered identifier part, which
-           is to be completed.
-        """
-        # Strip starting "/" from id_text
-        if id_text.startswith('/'):
-            id_text = id_text[1:]
-        # Get all items from the given module (up to the first /)
-        list = self.config_data.get_config_item_list(
-                        id_text.rpartition("/")[0], recurse=True)
-        # filter out all possibilities that don't match currently entered
-        # text part
-        hints = [val for val in list if val.startswith(id_text)]
-        return hints
-
-    def _cmd_has_identifier_param(self, cmd):
-        """
-        Returns True if the given (parsed) command is known and has a
-        parameter which points to a config data identifier
-
-        Parameters:
-        cmd (cmdparse.BindCmdParser): command context, including given params
-
-        """
-        if cmd.module not in self.modules:
-            return False
-        command = self.modules[cmd.module].get_command_with_name(cmd.command)
-        return command.has_param_with_name(CFGITEM_IDENTIFIER_PARAM)
-
-    def complete(self, text, state):
-        """
-        Returns tab-completion hints. See the python documentation of the
-        readline and Cmd modules for more information.
-
-        The first time this is called (within one 'completer' action), it
-        has state 0, and a list of possible completions is made. This list
-        is stored; complete() will then be called with increasing values of
-        state, until it returns None. For each call it returns the state'th
-        element of the hints it collected in the first call.
-
-        The hints list contents depend on which part of the full command
-        line; if no module is given yet, it will list all modules. If a
-        module is given, but no command, it will complete with module
-        commands. If both have been given, it will create the hints based on
-        the command parameters.
-
-        If module and command have already been specified, and the command
-        has a parameter 'identifier', the configuration data is used to
-        create the hints list.
-
-        Parameters:
-        text (string): The text entered so far in the 'current' part of
-                       the command (module, command, parameters)
-        state (int): state used in the readline tab-completion logic;
-                     0 on first call, increasing by one until there are
-                     no (more) hints to return.
-
-        Returns the string value of the hints list with index 'state',
-        or None if no (more) hints are available.
-        """
-        if state == 0:
-            self._update_all_modules_info()
-            text = text.strip()
-            hints = []
-            cur_line = my_readline()
-            try:
-                cmd = BindCmdParser(cur_line)
-                if not cmd.params and text:
-                    hints = self._get_command_startswith(cmd.module, text)
-                elif self._cmd_has_identifier_param(cmd):
-                    # If the command has an argument that is a configuration
-                    # identifier (currently, this is only a subset of
-                    # the config commands), then don't tab-complete with
-                    # hints derived from command parameters, but from
-                    # possible configuration identifiers.
-                    #
-                    # This solves the issue reported in #2254, where
-                    # there were hints such as 'argument' and 'identifier'.
-                    #
-                    # Since they are replaced, the tab-completion no longer
-                    # adds 'help' as an option (but it still works)
-                    #
-                    # Also, currently, tab-completion does not work
-                    # together with 'config go' (it does not take 'current
-                    # position' into account). But config go currently has
-                    # problems by itself, unrelated to completion.
-                    hints = self._get_identifier_startswith(text)
-                else:
-                    hints = self._get_param_startswith(cmd.module, cmd.command,
-                                                       text)
-
-            except CmdModuleNameFormatError:
-                if not text:
-                    hints = self.get_module_names()
-
-            except CmdMissCommandNameFormatError as e:
-                if not text.strip(): # command name is empty
-                    hints = self.modules[e.module].get_command_names()
-                else:
-                    hints = self._get_module_startswith(text)
-
-            except CmdCommandNameFormatError as e:
-                if e.module in self.modules:
-                    hints = self._get_command_startswith(e.module, text)
-
-            except CmdParamFormatError as e:
-                hints = self._get_param_startswith(e.module, e.command, text)
-
-            except BindCtlException:
-                hints = []
-
-            self.hint = hints
-
-        if state < len(self.hint):
-            return self.hint[state]
-        else:
-            return None
-
-
-    def _get_module_startswith(self, text):
-        return [module
-                for module in self.modules
-                if module.startswith(text)]
-
-
-    def _get_command_startswith(self, module, text):
-        if module in self.modules:
-            return [command
-                    for command in self.modules[module].get_command_names()
-                    if command.startswith(text)]
-
-        return []
-
-
-    def _get_param_startswith(self, module, command, text):
-        if module in self.modules:
-            module_info = self.modules[module]
-            if command in module_info.get_command_names():
-                cmd_info = module_info.get_command_with_name(command)
-                params = cmd_info.get_param_names()
-                hint = []
-                if text:
-                    hint = [val for val in params if val.startswith(text)]
-                else:
-                    hint = list(params)
-
-                if len(hint) == 1 and hint[0] != "help":
-                    hint[0] = hint[0] + " ="
-
-                return hint
-
-        return []
-
-    def _parse_cmd(self, line):
-        try:
-            cmd = BindCmdParser(line)
-            self._validate_cmd(cmd)
-            self._handle_cmd(cmd)
-        except (IOError, http.client.HTTPException) as err:
-            self._print('Error: ', err)
-        except BindCtlException as err:
-            self._print("Error! ", err)
-            self._print_correct_usage(err)
-        except isc.cc.data.DataTypeError as err:
-            self._print("Error! ", err)
-        except isc.cc.data.DataTypeError as dte:
-            self._print("Error: " + str(dte))
-        except isc.cc.data.DataNotFoundError as dnfe:
-            self._print("Error: " + str(dnfe))
-        except isc.cc.data.DataAlreadyPresentError as dape:
-            self._print("Error: " + str(dape))
-        except KeyError as ke:
-            self._print("Error: missing " + str(ke))
-
-    def _print_correct_usage(self, ept):
-        if isinstance(ept, CmdUnknownModuleSyntaxError):
-            self.do_help(None)
-
-        elif isinstance(ept, CmdUnknownCmdSyntaxError):
-            self.modules[ept.module].module_help()
-
-        elif isinstance(ept, CmdMissParamSyntaxError) or \
-             isinstance(ept, CmdUnknownParamSyntaxError):
-             self.modules[ept.module].command_help(ept.command)
-
-
-    def _append_space_to_hint(self):
-        """Append one space at the end of complete hint."""
-        self.hint = [(val + " ") for val in self.hint]
-
-
-    def _handle_help(self, cmd):
-        if cmd.command == "help":
-            self.modules[cmd.module].module_help()
-        else:
-            self.modules[cmd.module].command_help(cmd.command)
-
-
-    def apply_config_cmd(self, cmd):
-        '''Handles a configuration command.
-           Raises a DataTypeError if a wrong value is set.
-           Raises a DataNotFoundError if a wrong identifier is used.
-           Raises a KeyError if the command was not complete
-        '''
-        identifier = self.location
-        if 'identifier' in cmd.params:
-            if not identifier.endswith("/"):
-                identifier += "/"
-            if cmd.params['identifier'].startswith("/"):
-                identifier = cmd.params['identifier']
-            else:
-                if cmd.params['identifier'].startswith('['):
-                    identifier = identifier[:-1]
-                identifier += cmd.params['identifier']
-
-            # Check if the module is known; for unknown modules
-            # we currently deny setting preferences, as we have
-            # no way yet to determine if they are ok.
-            module_name = identifier.split('/')[1]
-            if module_name != "" and (self.config_data is None or \
-               not self.config_data.have_specification(module_name)):
-                self._print("Error: Module '" + module_name +
-                            "' unknown or not running")
-                return
-
-        if cmd.command == "show":
-            # check if we have the 'all' argument
-            show_all = False
-            if 'argument' in cmd.params:
-                if cmd.params['argument'] == 'all':
-                    show_all = True
-                elif 'identifier' not in cmd.params:
-                    # no 'all', no identifier, assume this is the
-                    #identifier
-                    identifier += cmd.params['argument']
-                else:
-                    self._print("Error: unknown argument " +
-                                cmd.params['argument'] +
-                                ", or multiple identifiers given")
-                    return
-            values = self.config_data.get_value_maps(identifier, show_all)
-            for value_map in values:
-                line = value_map['name']
-                if value_map['type'] in [ 'module', 'map' ]:
-                    line += "/"
-                elif value_map['type'] == 'list' \
-                     and value_map['value'] != []:
-                    # do not print content of non-empty lists if
-                    # we have more data to show
-                    line += "/"
-                else:
-                    # if type is named_set, don't print value if None
-                    # (it is either {} meaning empty, or None, meaning
-                    # there actually is data, but not to be shown with
-                    # the current command
-                    if value_map['type'] == 'named_set' and\
-                       value_map['value'] is None:
-                        line += "/\t"
-                    else:
-                        line += "\t" + json.dumps(value_map['value'])
-                line += "\t" + value_map['type']
-                line += "\t"
-                if value_map['default']:
-                    line += "(default)"
-                if value_map['modified']:
-                    line += "(modified)"
-                self._print(line)
-        elif cmd.command == "show_json":
-            if identifier == "":
-                self._print("Need at least the module to show the "
-                            "configuration in JSON format")
-            else:
-                data, default = self.config_data.get_value(identifier)
-                self._print(json.dumps(data))
-        elif cmd.command == "add":
-            self.config_data.add_value(identifier,
-                                       cmd.params.get('value_or_name'),
-                                       cmd.params.get('value_for_set'))
-        elif cmd.command == "remove":
-            if 'value' in cmd.params:
-                self.config_data.remove_value(identifier, cmd.params['value'])
-            else:
-                self.config_data.remove_value(identifier, None)
-        elif cmd.command == "set":
-            if 'identifier' not in cmd.params:
-                self._print("Error: missing identifier or value")
-            else:
-                parsed_value = None
-                try:
-                    parsed_value = json.loads(cmd.params['value'])
-                except Exception as exc:
-                    # ok could be an unquoted string, interpret as such
-                    parsed_value = cmd.params['value']
-                self.config_data.set_value(identifier, parsed_value)
-        elif cmd.command == "unset":
-            self.config_data.unset(identifier)
-        elif cmd.command == "revert":
-            self.config_data.clear_local_changes()
-        elif cmd.command == "commit":
-            try:
-                self.config_data.commit()
-            except isc.config.ModuleCCSessionError as mcse:
-                self._print(str(mcse))
-        elif cmd.command == "diff":
-            self._print(self.config_data.get_local_changes())
-        elif cmd.command == "go":
-            self.go(identifier)
-
-    def go(self, identifier):
-        '''Handles the config go command, change the 'current' location
-           within the configuration tree. '..' will be interpreted as
-           'up one level'.'''
-        id_parts = isc.cc.data.split_identifier(identifier)
-
-        new_location = ""
-        for id_part in id_parts:
-            if (id_part == ".."):
-                # go 'up' one level
-                new_location, a, b = new_location.rpartition("/")
-            else:
-                new_location += "/" + id_part
-        # check if exists, if not, revert and error
-        v,d = self.config_data.get_value(new_location)
-        if v is None:
-            self._print("Error: " + identifier + " not found")
-            return
-
-        self.location = new_location
-
-    def apply_execute_cmd(self, command):
-        '''Handles the 'execute' command, which executes a number of
-           (preset) statements. The command set to execute is either
-           read from a file (e.g. 'execute file <file>'.) or one
-           of the sets as defined in command_sets.py'''
-        if command.command == 'file':
-            try:
-                with open(command.params['filename']) as command_file:
-                    commands = command_file.readlines()
-            except IOError as ioe:
-                self._print("Error: " + str(ioe))
-                return
-        elif command_sets.has_command_set(command.command):
-            commands = command_sets.get_commands(command.command)
-        else:
-            # Should not be reachable; parser should've caught this
-            raise Exception("Unknown execute command type " + command.command)
-
-        # We have our set of commands now, depending on whether 'show' was
-        # specified, show or execute them
-        if 'show' in command.params and command.params['show'] == 'show':
-            self.__show_execute_commands(commands)
-        else:
-            self.__apply_execute_commands(commands)
-
-    def __show_execute_commands(self, commands):
-        '''Prints the command list without executing them'''
-        for line in commands:
-            self._print(line.strip())
-
-    def __apply_execute_commands(self, commands):
-        '''Applies the configuration commands from the given iterator.
-           This is the method that catches, comments, echo statements, and
-           other directives. All commands not filtered by this method are
-           interpreted as if they are directly entered in an active session.
-           Lines starting with any of the following characters are not
-           passed directly:
-           # - These are comments
-           ! - These are directives
-               !echo: print the rest of the line
-               !verbose on/off: print the commands themselves too
-               Unknown directives are ignored (with a warning)
-           The execution is stopped if there are any errors.
-        '''
-        verbose = False
-        try:
-            for line in commands:
-                line = line.strip()
-                if verbose:
-                    self._print(line)
-                if line.startswith('#') or len(line) == 0:
-                    continue
-                elif line.startswith('!'):
-                    if re.match('^!echo ', line, re.I) and len(line) > 6:
-                        self._print(line[6:])
-                    elif re.match('^!verbose\s+on\s*$', line, re.I):
-                        verbose = True
-                    elif re.match('^!verbose\s+off$', line, re.I):
-                        verbose = False
-                    else:
-                        self._print("Warning: ignoring unknown directive: " +
-                                    line)
-                else:
-                    cmd = BindCmdParser(line)
-                    self._validate_cmd(cmd)
-                    self._handle_cmd(cmd)
-        except (isc.config.ModuleCCSessionError,
-                IOError, http.client.HTTPException,
-                BindCtlException, isc.cc.data.DataTypeError,
-                isc.cc.data.DataNotFoundError,
-                isc.cc.data.DataAlreadyPresentError,
-                KeyError) as err:
-            self._print('Error: ', err)
-            self._print()
-            self._print('Depending on the contents of the script, and which')
-            self._print('commands it has called, there can be committed and')
-            self._print('local changes. It is advised to check your settings')
-            self._print(', and revert local changes with "config revert".')
-
-    def apply_cmd(self, cmd):
-        '''Handles a general module command'''
-        url = '/' + cmd.module + '/' + cmd.command
-        cmd_params = None
-        if (len(cmd.params) != 0):
-            cmd_params = json.dumps(cmd.params)
-
-        reply = self.send_POST(url, cmd.params)
-        data = reply.read().decode()
-        # The reply is a string containing JSON data,
-        # parse it, then prettyprint
-        if data != "" and data != "{}":
-            self._print(json.dumps(json.loads(data), sort_keys=True,
-                                   indent=4))

+ 0 - 348
src/bin/bindctl/bindctl.xml

@@ -1,348 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	       [<!ENTITY mdash "&#8212;">]>
-<!--
- - Copyright (C) 2010-2012  Internet Systems Consortium, Inc. ("ISC")
- -
- - Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
- - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- - AND FITNESS.  IN NO EVENT SHALL ISC 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.
--->
-
-<refentry>
-
-  <refentryinfo>
-    <date>June 20, 2012</date>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>bindctl</refentrytitle>
-    <manvolnum>1</manvolnum>
-    <refmiscinfo>BIND10</refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>bindctl</refname>
-    <refpurpose>control and configure BIND 10</refpurpose>
-  </refnamediv>
-
-  <docinfo>
-    <copyright>
-      <year>2010</year>
-      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
-    </copyright>
-  </docinfo>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>bindctl</command>
-      <arg><option>-a <replaceable>address</replaceable></option></arg>
-      <arg><option>-h</option></arg>
-      <arg><option>-c <replaceable>file</replaceable></option></arg>
-      <arg><option>-p <replaceable>number</replaceable></option></arg>
-      <arg><option>--address <replaceable>address</replaceable></option></arg>
-      <arg><option>--help</option></arg>
-      <arg><option>--certificate-chain <replaceable>file</replaceable></option></arg>
-      <arg><option>--csv-file-dir<replaceable>file</replaceable></option></arg>
-      <arg><option>--port <replaceable>number</replaceable></option></arg>
-      <arg><option>--version</option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>DESCRIPTION</title>
-    <para>
-      The <command>bindctl</command> tool is a user interface to
-      the BIND 10 services.  The program can be used to control
-      the components and configure the BIND 10 options.  The options
-      may be specified
-<!-- TODO: as command-line arguments, or --> via its
-      interactive command interpreter.
-    </para>
-
-    <para>
-      <command>bindctl</command> communicates over a HTTPS REST-ful
-      interface provided by
-      <citerefentry><refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
-      The
-<citerefentry><refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-      daemon stores the configurations.
-    </para>
-
-  </refsect1>
-
-  <refsect1>
-    <title>ARGUMENTS</title>
-
-    <para>The arguments are as follows:</para>
-
-    <variablelist>
-
-      <varlistentry>
-        <term><option>-a</option> <replaceable>address</replaceable>, <option>--address</option> <replaceable>address</replaceable></term>
-
-        <listitem>
-          <para>The IPv4 or IPv6 address to use to connect to the running
-            <citerefentry><refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-            daemon.
-            The default is 127.0.0.1.
-          </para>
-         </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-c</option> <replaceable>file</replaceable>,
-        <option>--certificate-chain</option> <replaceable>file</replaceable></term>
-
-        <listitem>
-          <para>The PEM formatted server certificate validation chain file.
-          </para>
-<!-- TODO: any default? -->
-<!-- TODO: any way to choose this for cmdctl? -->
-         </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>
-	  <option>--csv-file-dir</option><replaceable>file</replaceable>
-	</term>
-
-        <listitem>
-          <para>
-	    The directory name in which the user/password CSV file
-            is stored (see AUTHENTICATION).
-	    By default this option doesn't have any value,
-	    in which case the "<filename>.bind10</filename>" directory
-            under the user's home directory will be used.
-          </para>
-         </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-h</option>,
-          <option>--help</option></term>
-        <listitem><para>
-          Display command usage.</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-p</option> <replaceable>number</replaceable>, <option>--port</option> <replaceable>number</replaceable></term>
-
-        <listitem>
-          <para>The port number to use to connect to the running
-            <citerefentry><refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-            daemon.
-            The default is 8080.</para>
-<!-- TODO: -->
-            <note><simpara>This default port number may change.</simpara></note>
-         </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>
-          <option>--version</option></term>
-        <listitem><para>
-          Display the version number and exit.</para>
-        </listitem>
-      </varlistentry>
-
-    </variablelist>
-
-  </refsect1>
-
-  <refsect1>
-    <title>AUTHENTICATION</title>
-
-    <para>
-      The tool will authenticate using a username and password.
-      On the first successful login, it will save the details to
-      a comma-separated-value (CSV) file
-      which will be used for later uses of <command>bindctl</command>.
-      The file name is "<filename>default_user.csv</filename>"
-      located under the directory specified by the
-      <option>--csv-file-dir</option> option.
-    </para>
-
-<!-- TODO: mention HTTPS? -->
-
-  </refsect1>
-
-  <refsect1>
-    <title>USAGE</title>
-
-    <para>
-      The <command>bindctl</command> prompt shows
-      <quote>&gt; </quote>.
-       The prompt will also display the location if changed.
-       The options are based on the module in use.
-       The usage is:
-       <command>module</command> <command>command</command> <replaceable>param1 = value1 , <replaceable>param2 = value2</replaceable></replaceable>
-     </para>
-
-     <para>
-       <command>bindctl</command>'s
-       interactive interface provides command-line completion and
-       hints.  Press the Tab key to get a hint for the module,
-       command, and/or parameters.
-<!-- TODO: no hints at a blank line though ? -->
-
-      The arrow keys and Emacs-style editing keys may be used to edit
-      and recall previous lines.
-<!-- TODO:  all Emacs-style editing keys? -->
-     </para>
-
-     <para>
-       You can use the <command>help</command>
-       keyword to receive usage assistance for a module or a module's
-       command.
-     </para>
-
-     <para>
-       The <command>quit</command>
-       command is used to exit
-       <command>bindctl</command>.
-       (It doesn't stop the BIND 10 services.)
-     </para>
-
-     <para>
-       The following module is available by default:
-       <command>config</command> for Configuration commands.
-<!-- TODO: or is config from the cfgmgr module? -->
-       Additional modules may be available, such as
-       <command>Init</command>, <command>Xfrin</command>, and
-       <command>Auth</command>.
-     </para>
-
-<!--
-.Sh CONFIGURATION COMMANDS
-The following configuration commands are recognized by
-.Nm :
-.Bl -tag -width Ic
-.It Ic add Ar identifier Ar value
-Add a value to a list.
-.\" TODO: explain better
-.\" TODO: define list, map, others ...
-.\" TODO: why the value?
-.It Ic commit
-Commit all local changes.
-.\" TODO: what does this do?
-.It Ic go Ar identifier
-Go to the specified location within the configuration.
-.\" TODO: explain this
-.It Ic help
-Get help for the
-.Em config
-module.
-.It Ic remove Ar identifier Ar value
-Remove a value from a list.
-.\" TODO: why the value?
-.It Ic revert
-Revert all local changes (that have not been committed).
-.\" TODO: what does this do?
-.It Ic set Ar identifier Ar value
-Set a configuration value.
-.\" TODO
-.It Ic show Op Ar identifier.
-.\" TODO
-Show the currently set configuration values.
-If no
-.Ar identifier
-is given, the current location is used (as set by the
-.Ic go
-command).
-If a config option is a list or a map, the value is not
-shown directly, but must be requested separately.
-.\" TODO: example of this list or map
-.It Ic unset Ar identifier
-Remove a configuration value.
-If the option is mandatory, it will reset to the default value.
-.\" TODO: how to know default values before?
-.El
-.\" This manual page only covers builtin commands.
-.\" .Sh PARKINGLOT COMMANDS
-.\" .Bl -tag -width Ic
-.\" .It Ic help
-.\" Get help for the
-.\" .Em ParkingLot
-.\" module.
-.\"
-.\" TODO: Command arguments which have embedded spaces may be quoted with
-.\" quote
-.\" .Sq \&"
-.\" marks.
-.Pp
-.Pp command-line editing?
-.Pp
-.Sh EXAMPLES
-The following are some
-.Nm
-examples:
-.Bl -tag -width abcde
-.It Ic "config help"
-Show the commands for the
-.Em config
-module.
-.It Ic "config go ParkingLot/"
-Go to the
-.Dq ParkingLot/
-configuration location.
--->
-
-  </refsect1>
-
-<!-- TODO: any options? -->
-
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citetitle>BIND 10 Guide</citetitle>.
-    </para>
-<!-- TODO: point to developer docs -->
-  </refsect1>
-
-  <refsect1>
-    <title>AUTHORS</title>
-    <para>
-      The <command>bindctl</command>
-      tool and library were initially coded by Zhang Likun of CNNIC
-      for the BIND 10 project.
-      The initial manual page was written by Jeremy C. Reed of ISC.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>HISTORY</title>
-    <para>
-       The initial version (with internal name of
-       <command>BigTool</command>)
-       was started in October 2009.
-    </para>
-  </refsect1>
-
-</refentry><!--
- - Local variables:
- - mode: sgml
- - End:
--->
-

+ 0 - 167
src/bin/bindctl/bindctl_main.py.in

@@ -1,167 +0,0 @@
-#!@PYTHON@
-
-# Copyright (C) 2009  Internet Systems Consortium.
-#
-# 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.
-
-"""This is the main calling class for the bindctl configuration and
-   command tool. It sets up a command interpreter and runs that."""
-
-import sys; sys.path.append ('@@PYTHONPATH@@')
-
-from bindctl.moduleinfo import *
-from bindctl.bindcmd import *
-from bindctl import command_sets
-import pprint
-from optparse import OptionParser, OptionValueError
-import isc.util.process
-import isc.util.traceback_handler
-
-isc.util.process.rename()
-
-# This is the version that gets displayed to the user.
-# The VERSION string consists of the module name, the module version
-# number, and the overall BIND 10 version number (set in configure.ac).
-VERSION = "bindctl 20110217 (BIND 10 @PACKAGE_VERSION@)"
-
-DEFAULT_IDENTIFIER_DESC = "The identifier specifies the config item. Child elements are separated with the '/' character. List indices can be specified with '[i]', where i is an integer specifying the index, starting with 0. Examples: 'Init/start_auth', 'Auth/listen_on[0]/address'. If no identifier is given, shows the item at the current location."
-
-def prepare_config_commands(tool):
-    '''Prepare fixed commands for local configuration editing'''
-    module = ModuleInfo(name = CONFIG_MODULE_NAME, desc = "Configuration commands.")
-    cmd = CommandInfo(name = "show", desc = "Show configuration.")
-    param = ParamInfo(name = "argument", type = "string", optional=True, desc = "If you specify the argument 'all' (before the identifier), recursively show all child elements for the given identifier.")
-    cmd.add_param(param)
-    param = ParamInfo(name=CFGITEM_IDENTIFIER_PARAM, type="string",
-                      optional=True, desc=DEFAULT_IDENTIFIER_DESC)
-    cmd.add_param(param)
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="show_json",
-                      desc="Show full configuration in JSON format.")
-    param = ParamInfo(name=CFGITEM_IDENTIFIER_PARAM, type="string",
-                      optional=True, desc=DEFAULT_IDENTIFIER_DESC)
-    cmd.add_param(param)
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="add", desc=
-        "Add an entry to configuration list or a named set. "
-        "When adding to a list, the command has one optional argument, "
-        "a value to add to the list. The value must be in correct JSON "
-        "and complete. When adding to a named set, it has one "
-        "mandatory parameter (the name to add), and an optional "
-        "parameter value, similar to when adding to a list. "
-        "In either case, when no value is given, an entry will be "
-        "constructed with default values.")
-    param = ParamInfo(name=CFGITEM_IDENTIFIER_PARAM, type="string",
-                      optional=True, desc=DEFAULT_IDENTIFIER_DESC)
-    cmd.add_param(param)
-    param = ParamInfo(name="value_or_name", type="string", optional=True,
-                      desc="Specifies a value to add to the list, or the name when adding to a named set. It must be in correct JSON format and complete.")
-    cmd.add_param(param)
-    module.add_command(cmd)
-    param = ParamInfo(name="value_for_set", type="string", optional=True,
-                      desc="Specifies an optional value to add to the named map. It must be in correct JSON format and complete.")
-    cmd.add_param(param)
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="remove", desc="Remove entry from configuration list or named set.")
-    param = ParamInfo(name=CFGITEM_IDENTIFIER_PARAM, type="string",
-                      optional=True, desc=DEFAULT_IDENTIFIER_DESC)
-    cmd.add_param(param)
-    param = ParamInfo(name = "value", type = "string", optional=True, desc = "When identifier is a list, specifies a value to remove from the list. It must be in correct JSON format and complete. When it is a named set, specifies the name to remove.")
-    cmd.add_param(param)
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="set", desc="Set a configuration value.")
-    param = ParamInfo(name=CFGITEM_IDENTIFIER_PARAM, type="string",
-                      optional=True, desc=DEFAULT_IDENTIFIER_DESC)
-    cmd.add_param(param)
-    param = ParamInfo(name="value", type="string", optional=False,
-                      desc="Specifies a value to set. It must be in correct JSON format and complete.")
-    cmd.add_param(param)
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="unset", desc="Unset a configuration value (i.e. revert to the default, if any).")
-    param = ParamInfo(name=CFGITEM_IDENTIFIER_PARAM, type="string",
-                      optional=False, desc=DEFAULT_IDENTIFIER_DESC)
-    cmd.add_param(param)
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="diff", desc="Show all local changes that have not been committed.")
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="revert", desc="Revert all local changes.")
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="commit", desc="Commit all local changes.")
-    module.add_command(cmd)
-
-    cmd = CommandInfo(name="go", desc="Go to a specific configuration part.")
-    param = ParamInfo(name=CFGITEM_IDENTIFIER_PARAM, type="string",
-                      optional=False, desc=DEFAULT_IDENTIFIER_DESC)
-    cmd.add_param(param)
-    module.add_command(cmd)
-
-    tool.add_module_info(module)
-
-def check_port(option, opt_str, value, parser):
-    if (value < 0) or (value > 65535):
-        raise OptionValueError('%s requires a port number (0-65535)' % opt_str)
-    parser.values.port = value
-
-def check_addr(option, opt_str, value, parser):
-    ipstr = value
-    ip_family = socket.AF_INET
-    if (ipstr.find(':') != -1):
-        ip_family = socket.AF_INET6
-
-    try:
-        socket.inet_pton(ip_family, ipstr)
-    except:
-        raise OptionValueError("%s invalid ip address" % ipstr)
-
-    parser.values.addr = value
-
-def set_bindctl_options(parser):
-    parser.add_option('-p', '--port', dest='port', type='int',
-                      action='callback', callback=check_port,
-                      default='8080', help='port for cmdctl of bind10')
-
-    parser.add_option('-a', '--address', dest='addr', type='string',
-                      action='callback', callback=check_addr,
-                      default='127.0.0.1', help='IP address for cmdctl of bind10')
-
-    parser.add_option('-c', '--certificate-chain', dest='cert_chain',
-                      type='string', action='store',
-                      help='PEM formatted server certificate validation chain file')
-
-    parser.add_option('--csv-file-dir', dest='csv_file_dir', type='string',
-                      default=None, action='store',
-                      help='Directory to store the password CSV file')
-
-def main():
-    parser = OptionParser(version = VERSION)
-    set_bindctl_options(parser)
-    (options, args) = parser.parse_args()
-    server_addr = options.addr + ':' + str(options.port)
-    tool = BindCmdInterpreter(server_addr, pem_file=options.cert_chain,
-                              csv_file_dir=options.csv_file_dir)
-    prepare_config_commands(tool)
-    command_sets.prepare_execute_commands(tool)
-    result = tool.run()
-    sys.exit(result)
-
-if __name__ == '__main__':
-    isc.util.traceback_handler.traceback_handler(main)

+ 0 - 175
src/bin/bindctl/cmdparse.py

@@ -1,175 +0,0 @@
-# Copyright (C) 2009  Internet Systems Consortium.
-#
-# 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.
-
-
-"""This module holds the command parser class for bindctl"""
-
-import re
-from bindctl.exception import *
-try:
-    from collections import OrderedDict
-except ImportError:
-    from bindctl.mycollections import OrderedDict
-
-param_name_str = "^\s*(?P<param_name>[\w]+)\s*=\s*"
-
-# The value string can be a sequence without space or comma
-# characters, or a string surroundedby quotation marks(such marks
-# can be part of string in an escaped form)
-#param_value_str  = "(?P<param_value>[\"\'].+?(?<!\\\)[\"\']|[^\'\"][^, ]+)"
-param_value_str  = "(?P<param_value>[^\'\" ][^, ]+)"
-param_value_with_quota_str  = "[\"\'](?P<param_value>.+?)(?<!\\\)[\"\']"
-next_params_str = "(?P<blank>\s*)(?P<comma>,?)(?P<next_params>.*)$"
-
-
-PARAM_WITH_QUOTA_PATTERN = re.compile(param_name_str +
-                                      param_value_with_quota_str +
-                                      next_params_str)
-PARAM_PATTERN = re.compile(param_name_str + param_value_str + next_params_str)
-# Used for module and command name
-NAME_PATTERN = re.compile("^\s*(?P<name>[\w]+)(?P<blank>\s*)(?P<others>.*)$")
-
-# this removes all whitespace in the given string, except when
-# between " quotes
-_remove_unquoted_whitespace = \
-    lambda text:'"'.join( it if i%2 else ''.join(it.split())
-        for i,it in enumerate(text.split('"'))  )
-
-
-def _remove_list_and_map_whitespace(text):
-    """Returns a string where the whitespace between matching [ and ]
-       is removed, unless quoted"""
-    # regular expression aren't really the right tool, since we may have
-    # nested structures
-    result = []
-    start_pos = 0
-    pos = 0
-    list_count = 0
-    map_count = 0
-    cur_start_list_pos = None
-    cur_start_map_pos = None
-    for i in text:
-        if i == '[' and map_count == 0:
-            if list_count == 0:
-                result.append(text[start_pos:pos + 1])
-                cur_start_list_pos = pos + 1
-            list_count = list_count + 1
-        elif i == ']' and map_count == 0:
-            if list_count > 0:
-                list_count = list_count - 1
-                if list_count == 0:
-                    result.append(_remove_unquoted_whitespace(text[cur_start_list_pos:pos + 1]))
-                    start_pos = pos + 1
-        if i == '{' and list_count == 0:
-            if map_count == 0:
-                result.append(text[start_pos:pos + 1])
-                cur_start_map_pos = pos + 1
-            map_count = map_count + 1
-        elif i == '}' and list_count == 0:
-            if map_count > 0:
-                map_count = map_count - 1
-                if map_count == 0:
-                    result.append(_remove_unquoted_whitespace(text[cur_start_map_pos:pos + 1]))
-                    start_pos = pos + 1
-
-
-        pos = pos + 1
-    if start_pos <= len(text):
-        result.append(text[start_pos:len(text)])
-    return "".join(result)
-
-
-class BindCmdParser:
-    """ This class will parse the command line user input into three parts:
-    module name, command, parameters
-    the first two parts are strings and parameter is one hash,
-    parameters part is optional
-
-    Example: zone reload, zone_name=example.com
-    module == zone
-    command == reload
-    params == [zone_name = 'example.com']
-    """
-
-    def __init__(self, cmd):
-        self.params = OrderedDict()
-        self.module = ''
-        self.command = ''
-        self._parse_cmd(cmd)
-
-    def _parse_cmd(self, text_str):
-        '''Parse command line. '''
-        # Get module name
-        groups = NAME_PATTERN.match(text_str)
-        if not groups:
-            raise CmdModuleNameFormatError
-
-        self.module = groups.group('name')
-        cmd_str = groups.group('others')
-        if cmd_str:
-            if not groups.group('blank'):
-                raise CmdModuleNameFormatError
-        else:
-            raise CmdMissCommandNameFormatError(self.module)
-
-        # Get command name
-        groups = NAME_PATTERN.match(cmd_str)
-        if (not groups):
-            raise CmdCommandNameFormatError(self.module)
-
-        self.command = groups.group('name')
-        param_str = groups.group('others')
-        if param_str:
-            if not groups.group('blank'):
-                raise CmdCommandNameFormatError(self.module)
-
-            self._parse_params(param_str)
-
-    def _remove_list_whitespace(self, text):
-        return ""
-
-    def _parse_params(self, param_text):
-        """convert a=b,c=d into one hash """
-        param_text = _remove_list_and_map_whitespace(param_text)
-
-        # Check parameter name "help"
-        param = NAME_PATTERN.match(param_text)
-        if param and param.group('name') == "help":
-            self.params["help"] = "help"
-            return
-
-        while True:
-            if not param_text.strip():
-                break
-
-            groups = PARAM_PATTERN.match(param_text) or \
-                     PARAM_WITH_QUOTA_PATTERN.match(param_text)
-            if not groups:
-                # ok, fill in the params in the order entered
-                params = re.findall("([^\" ]+|\".*\")", param_text)
-                i = 0
-                for p in params:
-                    self.params[i] = p
-                    i += 1
-                break
-            else:
-                self.params[groups.group('param_name')] = groups.group('param_value')
-                param_text = groups.group('next_params')
-                if not param_text or (not param_text.strip()):
-                    break
-
-                if not groups.group('blank') and \
-                   not groups.group('comma'):
-                    raise CmdParamFormatError(self.module, self.command)

+ 0 - 94
src/bin/bindctl/command_sets.py

@@ -1,94 +0,0 @@
-# Copyright (C) 2012  Internet Systems Consortium.
-#
-# 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.
-
-# This file provides a built-in set of 'execute' commands, for common
-# functions, such as adding an initial auth server.
-# By calling the function prepare_execute_commands, the
-# commands in the command_sets map are added to the virtual
-# component called 'execute'. This is done in bindctl_main.
-
-from bindctl.moduleinfo import *
-# The name of the 'virtual' command set execution module in bindctl
-EXECUTE_MODULE_NAME = 'execute'
-
-# This is a map of command names to lists
-# Each element in the set should itself be a dict containing:
-# 'description': A string with a description of the command set
-# 'commands': A list of bindctl commands
-command_sets = {
-    'init_authoritative_server': {
-        'description':
-            'Configure and run a basic Authoritative server, with default '+
-            'SQLite3 backend, and xfrin and xfrout functionality',
-        'commands':
-            [
-            '!echo adding Authoritative server component',
-            'config add /Init/components b10-auth',
-            'config set /Init/components/b10-auth/kind needed',
-            'config set /Init/components/b10-auth/special auth',
-            '!echo adding Xfrin component',
-            'config add /Init/components b10-xfrin',
-            'config set /Init/components/b10-xfrin/address Xfrin',
-            'config set /Init/components/b10-xfrin/kind dispensable',
-            '!echo adding Xfrout component',
-            'config add /Init/components b10-xfrout',
-            'config set /Init/components/b10-xfrout/address Xfrout',
-            'config set /Init/components/b10-xfrout/kind dispensable',
-            '!echo adding Zone Manager component',
-            'config add /Init/components b10-zonemgr',
-            'config set /Init/components/b10-zonemgr/address Zonemgr',
-            'config set /Init/components/b10-zonemgr/kind dispensable',
-            '!echo Components added. Please enter "config commit" to',
-            '!echo finalize initial setup and run the components.'
-            ]
-    }
-}
-
-def has_command_set(name):
-    return name in command_sets
-
-def get_commands(name):
-    return command_sets[name]['commands']
-
-def get_description(name):
-    return command_sets[name]['description']
-
-# For each
-def prepare_execute_commands(tool):
-    """This function is called by bindctl_main, and sets up the commands
-       defined here for use in bindctl."""
-    # common parameter
-    param_show = ParamInfo(name="show", type="string", optional=True,
-        desc="Show the list of commands without executing them")
-
-    # The command module
-    module = ModuleInfo(name=EXECUTE_MODULE_NAME,
-                        desc="Execute a given set of commands")
-
-    # Command to execute a file
-    cmd = CommandInfo(name="file", desc="Read commands from file")
-    param = ParamInfo(name="filename", type="string", optional=False,
-                      desc="File to read the set of commands from.")
-    cmd.add_param(param)
-    cmd.add_param(param_show)
-    module.add_command(cmd)
-
-    # and loop through all command sets defined above
-    for name in command_sets:
-        cmd = CommandInfo(name=name, desc=get_description(name))
-        cmd.add_param(param_show)
-        module.add_command(cmd)
-
-    tool.add_module_info(module)

+ 0 - 124
src/bin/bindctl/exception.py

@@ -1,124 +0,0 @@
-# Copyright (C) 2009  Internet Systems Consortium.
-#
-# 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.
-
-"""This module holds exception classes specific for bindctl"""
-class BindCtlException(Exception):
-    """Abstract base class shared by all bindctl exceptions"""
-    def __str__(self):
-        return "Big tool has problem"
-
-# Begin define Format exception
-
-class CmdFormatError(BindCtlException):
-    """Command is malformed"""
-    def __str__(self):
-        return "Command is malformed"
-
-        
-class CmdModuleNameFormatError(CmdFormatError):
-    """module name format error"""
-
-    def __str__(self):
-        return "Module name format error: the character of name can only be '0-9a-zA-Z_'" 
-                      
-                
-class CmdCommandNameFormatError(CmdFormatError):
-    """command name format error"""
-    
-    def __init__(self, module):
-        self.module = module        
-        
-    def __str__(self):
-        return "Command name format error: the character of name can only be '0-9a-zA-Z_'"      
-        
-        
-class CmdMissCommandNameFormatError(CmdFormatError):
-    """Module name isn't finished"""
-    
-    def __init__(self, module):
-        self.module = module
-        
-    def __str__(self):
-        return "command name is missed"   
-
-
-class CmdParamFormatError(CmdFormatError):
-    """Command is malformed which parameter isn't key value pair"""
-    
-    def __init__(self, module, command):        
-        self.module = module
-        self.command = command        
-
-    def __str__(self):
-        return  "Parameter format error, it should be 'key = value'"         
-        
-# Begin define the exception for syntax
-
-class CmdSyntaxError(BindCtlException):
-    """Command line has syntax error"""
-    
-    def __str__(self):
-        return "Command line has syntax error"
-
-
-class CmdUnknownModuleSyntaxError(CmdSyntaxError):
-    """Command is unknown"""
-    def __init__(self, module):
-        self.module = module
-
-    def __str__(self):
-        return str("Unknown module '%s'" % self.module)
-        
-
-class CmdUnknownCmdSyntaxError(CmdSyntaxError):
-    """Command is unknown"""
-    def __init__(self, module, command):
-        self.module = module
-        self.command = command
-
-    def __str__(self):
-        return str("Unknown command '%s' to module '%s'" % 
-                    (self.command, self.module))
-                    
-
-class CmdUnknownParamSyntaxError(CmdSyntaxError):
-    """The parameter of command is unknown"""
-    def __init__(self, module, command, param):
-        self.module = module
-        self.command = command
-        self.param = param
-
-    def __str__(self):
-        return str("Unknown parameter '%s' to command '%s' of module '%s'" %
-                   (self.param, self.command, self.module))
-                   
-
-class CmdMissParamSyntaxError(CmdSyntaxError):
-    """The parameter of one command is missed"""
-    def __init__(self, module, command, param):
-        self.module = module
-        self.command = command
-        self.param = param
-
-    def __str__(self):
-        return str("Parameter '%s' is missed for command '%s' of module '%s'" % 
-                   (self.param, self.command, self.module))
-
-
-class FailToLogin(BindCtlException):
-    def __str__(self):
-        return "Fail to login to cmdctl"
-
-

+ 0 - 249
src/bin/bindctl/moduleinfo.py

@@ -1,249 +0,0 @@
-# Copyright (C) 2009  Internet Systems Consortium.
-#
-# 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.
-
-"""This module holds classes representing modules, commands and
-   parameters for use in bindctl"""
-
-import textwrap
-
-try:
-    from collections import OrderedDict
-except ImportError:
-    from bindctl.mycollections import OrderedDict
-
-# Define value type
-STRING_TYPE = "string"
-LIST_TYPE = "list"
-INT_TYPE = "int"
-
-MODULE_NODE_NAME = 'module'
-COMMAND_NODE_NAME = 'command'
-PARAM_NODE_NAME = 'param'
-
-# this is used to align the descriptions in help output
-CONST_BINDCTL_HELP_INDENT_WIDTH=12
-
-
-class ParamInfo:
-    """One parameter of one command.
-    Each command parameter has five attributes:
-    parameter name, parameter type, parameter value,
-    parameter description and paramter's spec(got from
-    module spec file). 
-    """
-    def __init__(self, name, desc = '', type = STRING_TYPE, 
-                 optional = False, value = '', default_value = '', 
-                 param_spec = None):
-        self.name = name
-        self.type = type
-        self.value = value
-        self.default_value = default_value                           
-        self.desc = desc
-        self.is_optional = optional
-        self.param_spec = param_spec
-    
-    def __str__(self):        
-        return str("\t%s <type: %s> \t(%s)" % (self.name, self.type, self.desc))
-
-    def get_basic_info(self):
-        if self.is_optional:
-            opt_str = "optional"
-        else:
-            opt_str = "mandatory"
-        return "%s (%s, %s)" % (self.name, self.type, opt_str)
-
-    def get_desc(self):
-        return self.desc
-
-class CommandInfo:
-    """One command which is provided by one bind10 module, it has zero
-       or more parameters
-    """
-
-    def __init__(self, name, desc = ""):
-        self.name = name
-        self.desc = desc
-        self.params = OrderedDict()        
-        # Set default parameter "help"
-        self.add_param(ParamInfo("help", 
-                                  desc = "Get help for command.",
-                                  optional = True))
-                
-    def __str__(self):
-        return str("%s \t(%s)" % (self.name, self.desc))
-
-    def get_name(self):
-        return self.name
-
-    def get_desc(self):
-        return self.desc;
-    
-    def add_param(self, paraminfo):
-        """Add a ParamInfo object to this CommandInfo"""
-        self.params[paraminfo.name] = paraminfo
-        
-
-    def has_param_with_name(self, param_name):
-        """Returns true if the parameter with param_name exists"""
-        return param_name in self.params
-        
-
-    def get_param_with_name(self, param_name):
-        """Returns the ParamInfo with the given name. Raises a
-           KeyError if it doesn't exist"""
-        return self.params[param_name]
-        
-
-    def get_params(self):
-        """Returns a list of all ParamInfo objects for this CommandInfo"""
-        return list(self.params.values())
-        
-
-    def get_param_names(self):
-        """Returns a list of the names of all parameters for this command"""
-        return list(self.params.keys())
-        
-        
-    def get_mandatory_param_names(self):
-        """Returns a list of the names of all mandatory parameters for
-           this command"""
-        all_names = self.params.keys()
-        return [name for name in all_names 
-                if not self.params[name].is_optional]        
-        
-    def get_param_name_by_position(self, pos, param_count):
-        """
-        Find a proper parameter name for the position 'pos':
-        If param_count is equal to the count of mandatory parameters of command,
-        and there is some optional parameter, find the first mandatory parameter 
-        from the position 'pos' to the end. Else, return the name on position pos.
-        (This function will be changed if bindctl command line syntax is changed
-        in the future. )
-        """
-        if type(pos) != int:
-            raise KeyError(str(pos) + " is not an integer")
-
-        else:
-            params = self.params.copy()
-            del params['help']
-            count = len(params)
-            if (pos >= count):
-                raise KeyError(str(pos) + " out of range")
-
-            mandatory_count = len(self.get_mandatory_param_names())
-            param_names = list(params.keys())
-            if (param_count == mandatory_count) and (param_count < count):
-                while pos < count:
-                    if not params[param_names[pos]].is_optional:
-                        return param_names[pos]
-                    pos += 1
-                
-                raise KeyError(str(pos) + "parameters have error")
-            else:
-                return param_names[pos]
-
-
-    def command_help(self):
-        """Prints the help info for this command to stdout"""
-        print("Command ", self)
-        print("\t\thelp (Get help for command)")
-
-        params = self.params.copy()
-        del params["help"]
-
-        if len(params) == 0:
-            print("This command has no parameters")
-            return
-
-        print("Parameters:")
-        for info in params.values():
-            print("    %s" % info.get_basic_info())
-            description = info.get_desc()
-            if description != "":
-                print(textwrap.fill(description,
-                      initial_indent="        ",
-                      subsequent_indent="        ",
-                      width=70))
-
-class ModuleInfo:
-    """Define the information of one module, include module name, 
-    module supporting commands.
-    """    
-    
-    def __init__(self, name, desc = ""):
-        self.name = name
-        self.desc = desc
-        self.commands = OrderedDict()         
-        self.add_command(CommandInfo(name = "help", 
-                                     desc = "Get help for module."))
-        
-    def __str__(self):
-        return str("%s \t%s" % (self.name, self.desc))
-
-    def get_name(self):
-        return self.name
-
-    def get_desc(self):
-        return self.desc
-
-    def add_command(self, command_info):
-        """Add a CommandInfo to this ModuleInfo."""
-        self.commands[command_info.name] = command_info
-        
-    def has_command_with_name(self, command_name):
-        """Returns true if this module has a command with the given name."""
-        return command_name in self.commands
-        
-    def get_command_with_name(self, command_name):
-        """Returns the CommandInfo for the command with the given name.
-           Raises a KeyError if not found"""
-        return self.commands[command_name]
-        
-    def get_commands(self):
-        """Returns a list of all CommandInfo objects for this module."""
-        return list(self.commands.values())
-        
-    def get_command_names(self):
-        """Returns a list of the names of all commands for this module."""
-        return list(self.commands.keys())
-
-    def module_help(self):
-        """Prints the help info for this module to stdout"""
-        print("Module " + str(self))
-        print("Available commands:")
-        for k in self.commands.values():
-            n = k.get_name()
-            if len(n) >= CONST_BINDCTL_HELP_INDENT_WIDTH:
-                print("    %s" % n)
-                print(textwrap.fill(k.get_desc(),
-                      initial_indent="            ",
-                      subsequent_indent="    " +
-                      " " * CONST_BINDCTL_HELP_INDENT_WIDTH,
-                      width=70))
-            else:
-                print(textwrap.fill("%s%s%s" %
-                    (k.get_name(),
-                     " "*(CONST_BINDCTL_HELP_INDENT_WIDTH - len(k.get_name())),
-                     k.get_desc()),
-                    initial_indent="    ",
-                    subsequent_indent="    " +
-                    " " * CONST_BINDCTL_HELP_INDENT_WIDTH,
-                    width=70))
-            
-    def command_help(self, command):
-        """Prints the help info for the command with the given name.
-           Raises KeyError if not found"""
-        self.commands[command].command_help()    
-

+ 0 - 82
src/bin/bindctl/mycollections.py

@@ -1,82 +0,0 @@
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-from collections import MutableMapping
-
-class OrderedDict(dict, MutableMapping):
-
-    # Methods with direct access to underlying attributes
-
-    def __init__(self, *args, **kwds):
-        if len(args) > 1:
-            raise TypeError('expected at 1 argument, got %d', len(args))
-        if not hasattr(self, '_keys'):
-            self._keys = []
-        self.update(*args, **kwds)
-
-    def clear(self):
-        del self._keys[:]
-        dict.clear(self)
-
-    def __setitem__(self, key, value):
-        if key not in self:
-            self._keys.append(key)
-        dict.__setitem__(self, key, value)
-
-    def __delitem__(self, key):
-        dict.__delitem__(self, key)
-        self._keys.remove(key)
-
-    def __iter__(self):
-        return iter(self._keys)
-
-    def __reversed__(self):
-        return reversed(self._keys)
-
-    def popitem(self):
-        if not self:
-            raise KeyError
-        key = self._keys.pop()
-        value = dict.pop(self, key)
-        return key, value
-
-    def __reduce__(self):
-        items = [[k, self[k]] for k in self]
-        inst_dict = vars(self).copy()
-        inst_dict.pop('_keys', None)
-        return (self.__class__, (items,), inst_dict)
-
-    # Methods with indirect access via the above methods
-
-    setdefault = MutableMapping.setdefault
-    update = MutableMapping.update
-    pop = MutableMapping.pop
-    keys = MutableMapping.keys
-    values = MutableMapping.values
-    items = MutableMapping.items
-
-    def __repr__(self):
-        pairs = ', '.join(map('%r: %r'.__mod__, self.items()))
-        return '%s({%s})' % (self.__class__.__name__, pairs)
-
-    def copy(self):
-        return self.__class__(self)
-
-    @classmethod
-    def fromkeys(cls, iterable, value=None):
-        d = cls()
-        for key in iterable:
-            d[key] = value
-        return d

+ 0 - 41
src/bin/bindctl/run_bindctl.sh.in

@@ -1,41 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
-export PYTHON_EXEC
-
-BINDCTL_PATH=@abs_top_builddir@/src/bin/bindctl
-
-PYTHONPATH=@abs_top_srcdir@/src/bin:@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python/isc/cc:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/bin:@abs_top_srcdir@/src/lib/python
-export PYTHONPATH
-
-# If necessary (rare cases), explicitly specify paths to dynamic libraries
-# required by loadable python modules.
-SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
-if test $SET_ENV_LIBRARY_PATH = yes; then
-	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/threads/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:@abs_top_builddir@/src/lib/datasrc/.libs:$@ENV_LIBRARY_PATH@
-	export @ENV_LIBRARY_PATH@
-fi
-
-B10_FROM_SOURCE=@abs_top_srcdir@
-export B10_FROM_SOURCE
-
-BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
-export BIND10_MSGQ_SOCKET_FILE
-
-cd ${BINDCTL_PATH}
-exec ${PYTHON_EXEC} -O bindctl "$@"

+ 0 - 1
src/bin/bindctl/tests/.gitignore

@@ -1 +0,0 @@
-/bindctl_test

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 24
src/bin/bindctl/tests/Makefile.am


+ 0 - 27
src/bin/bindctl/tests/bindctl_test.in

@@ -1,27 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
-export PYTHON_EXEC
-
-BINDCTL_TEST_PATH=@abs_top_srcdir@/src/bin/bindctl/tests
-PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_srcdir@/src/bin
-export PYTHONPATH
-
-cd ${BINDCTL_TEST_PATH}
-exec ${PYTHON_EXEC} -O bindctl_test.py $*
-

+ 0 - 694
src/bin/bindctl/tests/bindctl_test.py

@@ -1,694 +0,0 @@
-# Copyright (C) 2009  Internet Systems Consortium.
-#
-# 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.
-
-
-import unittest
-import isc.cc.data
-import os
-import io
-import errno
-import sys
-import socket
-import ssl
-import http.client
-import pwd
-import getpass
-import re
-import json
-from optparse import OptionParser
-from isc.config.config_data import ConfigData, MultiConfigData
-from isc.config.module_spec import ModuleSpec
-from isc.testutils.parse_args import TestOptParser, OptsError
-from bindctl_main import set_bindctl_options
-from bindctl import cmdparse
-from bindctl import bindcmd
-from bindctl.moduleinfo import *
-from bindctl.exception import *
-try:
-    from collections import OrderedDict
-except ImportError:
-    from mycollections import OrderedDict
-
-class TestCmdLex(unittest.TestCase):
-
-    def my_assert_raise(self, exception_type, cmd_line):
-        self.assertRaises(exception_type, cmdparse.BindCmdParser, cmd_line)
-
-
-    def testCommandWithoutParameter(self):
-        cmd_parser = cmdparse.BindCmdParser("zone add")
-        assert cmd_parser.module == "zone"
-        assert cmd_parser.command == "add"
-        self.assertEqual(len(cmd_parser.params), 0)
-
-
-    def testCommandWithParameters(self):
-        lines = {"zone add zone_name = cnnic.cn, file = cnnic.cn.file master=1.1.1.1",
-                 "zone add zone_name = \"cnnic.cn\", file ='cnnic.cn.file' master=1.1.1.1  ",
-                 "zone add zone_name = 'cnnic.cn\", file ='cnnic.cn.file' master=1.1.1.1, " }
-
-        for cmd_line in lines:
-            cmd_parser = cmdparse.BindCmdParser(cmd_line)
-            assert cmd_parser.module == "zone"
-            assert cmd_parser.command == "add"
-            assert cmd_parser.params["zone_name"] == "cnnic.cn"
-            assert cmd_parser.params["file"] == "cnnic.cn.file"
-            assert cmd_parser.params["master"] == '1.1.1.1'
-
-    def testCommandWithParamters_2(self):
-        '''Test whether the parameters in key=value can be parsed properly.'''
-        cmd_parser = cmdparse.BindCmdParser('zone cmd name = 1:34::2')
-        self.assertEqual(cmd_parser.params['name'], '1:34::2')
-
-        cmd_parser = cmdparse.BindCmdParser('zone cmd name = 1\"\'34**&2'
-                                            ' value=44\"\'\"')
-        self.assertEqual(cmd_parser.params['name'], '1\"\'34**&2')
-        self.assertEqual(cmd_parser.params['value'], '44\"\'\"')
-
-        cmd_parser = cmdparse.BindCmdParser('zone cmd name = 1\"\'34**&2'
-                                            ',value=  44\"\'\"')
-        self.assertEqual(cmd_parser.params['name'], '1\"\'34**&2')
-        self.assertEqual(cmd_parser.params['value'], '44\"\'\"')
-
-        cmd_parser = cmdparse.BindCmdParser('zone cmd name =  1\'34**&2'
-                                            'value=44\"\'\" value = '
-                                            '\"==============\'')
-        self.assertEqual(cmd_parser.params['name'], '1\'34**&2value=44\"\'\"')
-        self.assertEqual(cmd_parser.params['value'], '==============')
-
-        cmd_parser = cmdparse.BindCmdParser('zone cmd name =    \"1234, '
-                                            '567890 \" value ==&*/')
-        self.assertEqual(cmd_parser.params['name'], '1234, 567890 ')
-        self.assertEqual(cmd_parser.params['value'], '=&*/')
-
-    def testCommandWithListParam(self):
-        cmd_parser = cmdparse.BindCmdParser("zone set zone_name='cnnic.cn', "
-                                            "master='1.1.1.1, 2.2.2.2'")
-        assert cmd_parser.params["master"] == '1.1.1.1, 2.2.2.2'
-
-    def testCommandWithHelpParam(self):
-        cmd_parser = cmdparse.BindCmdParser("zone add help")
-        assert cmd_parser.params["help"] == "help"
-
-        cmd_parser = cmdparse.BindCmdParser("zone add help *&)&)*&&$#$^%")
-        assert cmd_parser.params["help"] == "help"
-        self.assertEqual(len(cmd_parser.params), 1)
-
-
-    def testCmdModuleNameFormatError(self):
-        self.my_assert_raise(CmdModuleNameFormatError, "zone=good")
-        self.my_assert_raise(CmdModuleNameFormatError, "zo/ne")
-        self.my_assert_raise(CmdModuleNameFormatError, "")
-        self.my_assert_raise(CmdModuleNameFormatError, "=zone")
-        self.my_assert_raise(CmdModuleNameFormatError, "zone,")
-
-
-    def testCmdMissCommandNameFormatError(self):
-        self.my_assert_raise(CmdMissCommandNameFormatError, "zone")
-        self.my_assert_raise(CmdMissCommandNameFormatError, "zone ")
-        self.my_assert_raise(CmdMissCommandNameFormatError, "help ")
-
-
-    def testCmdCommandNameFormatError(self):
-        self.my_assert_raise(CmdCommandNameFormatError, "zone =d")
-        self.my_assert_raise(CmdCommandNameFormatError, "zone z=d")
-        self.my_assert_raise(CmdCommandNameFormatError, "zone z-d ")
-        self.my_assert_raise(CmdCommandNameFormatError, "zone zdd/")
-        self.my_assert_raise(CmdCommandNameFormatError, "zone zdd/ \"")
-
-class TestCmdSyntax(unittest.TestCase):
-
-    def _create_bindcmd(self):
-        """Create one bindcmd"""
-
-        tool = bindcmd.BindCmdInterpreter()
-        string_spec = { 'item_type' : 'string',
-                       'item_optional' : False,
-                       'item_default' : ''}
-        int_spec = { 'item_type' : 'integer',
-                       'item_optional' : False,
-                       'item_default' : 10}
-        zone_file_param = ParamInfo(name = "zone_file",
-                                    param_spec = string_spec)
-        zone_name = ParamInfo(name = 'zone_name', param_spec = string_spec)
-        load_cmd = CommandInfo(name = "load")
-        load_cmd.add_param(zone_file_param)
-        load_cmd.add_param(zone_name)
-
-        param_master = ParamInfo(name = "master", optional = True,
-                                 param_spec = string_spec)
-        param_master = ParamInfo(name = "port", optional = True,
-                                 param_spec = int_spec)
-        param_allow_update = ParamInfo(name = "allow_update",
-                                       optional = True,
-                                       param_spec = string_spec)
-        set_cmd = CommandInfo(name = "set")
-        set_cmd.add_param(param_master)
-        set_cmd.add_param(param_allow_update)
-        set_cmd.add_param(zone_name)
-
-        reload_all_cmd = CommandInfo(name = "reload_all")
-
-        zone_module = ModuleInfo(name = "zone")
-        zone_module.add_command(load_cmd)
-        zone_module.add_command(set_cmd)
-        zone_module.add_command(reload_all_cmd)
-
-        tool.add_module_info(zone_module)
-        return tool
-
-
-    def setUp(self):
-        self.bindcmd = self._create_bindcmd()
-
-
-    def no_assert_raise(self, cmd_line):
-        cmd_parser = cmdparse.BindCmdParser(cmd_line)
-        self.bindcmd._validate_cmd(cmd_parser)
-
-
-    def my_assert_raise(self, exception_type, cmd_line):
-        cmd_parser = cmdparse.BindCmdParser(cmd_line)
-        self.assertRaises(exception_type, self.bindcmd._validate_cmd,
-                          cmd_parser)
-
-
-    def testValidateSuccess(self):
-        self.no_assert_raise("zone load zone_file='cn' zone_name='cn'")
-        self.no_assert_raise("zone load zone_file='cn', zone_name='cn', ")
-        self.no_assert_raise("zone help ")
-        self.no_assert_raise("zone load help ")
-        self.no_assert_raise("zone help help='dd' ")
-        self.no_assert_raise("zone set allow_update='1.1.1.1' zone_name='cn'")
-        self.no_assert_raise("zone set zone_name='cn'")
-        self.my_assert_raise(isc.cc.data.DataTypeError,
-                             "zone set zone_name ='cn', port='cn'")
-        self.no_assert_raise("zone reload_all")
-
-    def testCmdUnknownModuleSyntaxError(self):
-        self.my_assert_raise(CmdUnknownModuleSyntaxError, "zoned d")
-        self.my_assert_raise(CmdUnknownModuleSyntaxError, "dd dd  ")
-
-    def testCmdUnknownCmdSyntaxError(self):
-        self.my_assert_raise(CmdUnknownCmdSyntaxError, "zone dd")
-
-    def testCmdMissParamSyntaxError(self):
-        self.my_assert_raise(CmdMissParamSyntaxError,
-                             "zone load zone_file='cn'")
-        self.my_assert_raise(CmdMissParamSyntaxError,
-                             "zone load zone_name='cn'")
-        self.my_assert_raise(CmdMissParamSyntaxError,
-                             "zone set allow_update='1.1.1.1'")
-        self.my_assert_raise(CmdMissParamSyntaxError,
-                             "zone set ")
-
-    def testCmdUnknownParamSyntaxError(self):
-        self.my_assert_raise(CmdUnknownParamSyntaxError,
-                             "zone load zone_d='cn'")
-        self.my_assert_raise(CmdUnknownParamSyntaxError,
-                             "zone reload_all zone_name = 'cn'")
-        self.my_assert_raise(CmdUnknownParamSyntaxError,
-                             "zone help a b c")
-
-class TestModuleInfo(unittest.TestCase):
-
-    def test_get_param_name_by_position(self):
-        cmd = CommandInfo('command')
-        cmd.add_param(ParamInfo('name'))
-        cmd.add_param(ParamInfo('age'))
-        cmd.add_param(ParamInfo('data', optional = True))
-        cmd.add_param(ParamInfo('sex'))
-        self.assertEqual('name', cmd.get_param_name_by_position(0, 2))
-        self.assertEqual('age', cmd.get_param_name_by_position(1, 2))
-        self.assertEqual('sex', cmd.get_param_name_by_position(2, 3))
-        self.assertEqual('data', cmd.get_param_name_by_position(2, 4))
-        self.assertEqual('data', cmd.get_param_name_by_position(2, 4))
-
-        self.assertRaises(KeyError, cmd.get_param_name_by_position, 4, 4)
-
-
-
-class TestNameSequence(unittest.TestCase):
-    """
-    Test if the module/command/parameters is saved in the order creation
-    """
-
-    def _create_bindcmd(self):
-        """Create one bindcmd"""
-
-        self._cmd = CommandInfo(name = "load")
-        self.module = ModuleInfo(name = "zone")
-        self.tool = bindcmd.BindCmdInterpreter()
-        for random_str in self.random_names:
-            self._cmd.add_param(ParamInfo(name = random_str))
-            self.module.add_command(CommandInfo(name = random_str))
-            self.tool.add_module_info(ModuleInfo(name = random_str))
-
-    def setUp(self):
-        self.random_names = ['1erdfeDDWsd', '3fe', '2009erd',
-                             'Fe231', 'tere142', 'rei8WD']
-        self._create_bindcmd()
-
-    def testSequence(self):
-        param_names = self._cmd.get_param_names()
-        cmd_names = self.module.get_command_names()
-        module_names = self.tool.get_module_names()
-
-        i = 0
-        while i < len(self.random_names):
-            assert self.random_names[i] == param_names[i+1]
-            assert self.random_names[i] == cmd_names[i+1]
-            assert self.random_names[i] == module_names[i+1]
-            i = i + 1
-
-# tine class to fake a UIModuleCCSession, but only the config data
-# parts for the next set of tests
-class FakeCCSession(MultiConfigData):
-    def __init__(self):
-        self._local_changes = {}
-        self._current_config = {}
-        self._specifications = {}
-        self.add_foo_spec()
-
-    def add_foo_spec(self):
-        spec = { "module_name": "foo",
-                 "config_data": [
-                 { "item_name": "an_int",
-                   "item_type": "integer",
-                   "item_optional": False,
-                   "item_default": 1
-                 },
-                 { "item_name": "a_list",
-                   "item_type": "list",
-                   "item_optional": False,
-                   "item_default": [],
-                   "list_item_spec":
-                   { "item_name": "a_string",
-                     "item_type": "string",
-                     "item_optional": False,
-                     "item_default": "bar"
-                   }
-                 }
-                 ]
-               }
-        self.set_specification(ModuleSpec(spec))
-
-
-# fake socket
-class FakeSocket():
-    def __init__(self):
-        self.run = True
-
-    def connect(self, to):
-        if not self.run:
-            raise socket.error
-
-    def close(self):
-        self.run = False
-
-    def send(self, data):
-        if not self.run:
-            raise socket.error
-        return len(data)
-
-    def makefile(self, type):
-        return self
-
-    def sendall(self, data):
-        if not self.run:
-            raise socket.error
-        return len(data)
-
-
-class TestConfigCommands(unittest.TestCase):
-    def setUp(self):
-        self.tool = bindcmd.BindCmdInterpreter()
-        mod_info = ModuleInfo(name = "foo")
-        self.tool.add_module_info(mod_info)
-        self.tool.config_data = FakeCCSession()
-        self.stdout_backup = sys.stdout
-        self.printed_messages = []
-        self.tool._print = self.store_print
-
-    def test_precmd(self):
-        def update_all_modules_info():
-            raise socket.error
-        def precmd(line):
-            self.tool.precmd(line)
-        self.tool._update_all_modules_info = update_all_modules_info
-        # If line is equals to 'EOF', _update_all_modules_info()
-        # shouldn't be called
-        precmd('EOF')
-        self.assertRaises(socket.error, precmd, 'continue')
-
-    def store_print(self, *args):
-        '''Method to override _print in BindCmdInterpreter.
-           Instead of printing the values, appends the argument tuple
-           to the list in self.printed_messages'''
-        self.printed_messages.append(" ".join(map(str, args)))
-
-    def __check_printed_message(self, expected_message, printed_message):
-        self.assertIsNotNone(re.match(expected_message, printed_message),
-                             "Printed message '" + printed_message +
-                             "' does not match '" + expected_message + "'")
-
-    def __check_printed_messages(self, expected_messages):
-        '''Helper test function to check the printed messages against a list
-           of regexps'''
-        self.assertEqual(len(expected_messages), len(self.printed_messages))
-        for _ in map(self.__check_printed_message,
-                     expected_messages,
-                     self.printed_messages):
-            pass
-
-    def test_try_login(self):
-        # Make sure __try_login raises the correct exception
-        # upon failure of either send_POST or the read() on the
-        # response
-
-        orig_send_POST = self.tool.send_POST
-        expected_printed_messages = []
-        try:
-            def send_POST_raiseImmediately(self, params):
-                raise socket.error("test error")
-
-            self.tool.send_POST = send_POST_raiseImmediately
-            self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
-            expected_printed_messages.append(
-                'Error while sending login information: test error')
-            self.__check_printed_messages(expected_printed_messages)
-
-            def create_send_POST_raiseOnRead(exception):
-                '''Create a replacement send_POST() method that raises
-                   the given exception when read() is called on the value
-                   returned from send_POST()'''
-                def send_POST_raiseOnRead(self, params):
-                    class MyResponse:
-                        def read(self):
-                            raise exception
-                    return MyResponse()
-                return send_POST_raiseOnRead
-
-            # basic socket error
-            self.tool.send_POST =\
-                create_send_POST_raiseOnRead(socket.error("read error"))
-            self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
-            expected_printed_messages.append(
-                'Error while sending login information: read error')
-            self.__check_printed_messages(expected_printed_messages)
-
-            # connection reset
-            exc = socket.error("connection reset")
-            exc.errno = errno.ECONNRESET
-            self.tool.send_POST =\
-                create_send_POST_raiseOnRead(exc)
-            self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
-            expected_printed_messages.append(
-                'Error while sending login information: connection reset')
-            self.__check_printed_messages(expected_printed_messages)
-
-            # 'normal' SSL error
-            exc = ssl.SSLError()
-            self.tool.send_POST =\
-                create_send_POST_raiseOnRead(exc)
-            self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
-            expected_printed_messages.append(
-                'Error while sending login information: .*')
-            self.__check_printed_messages(expected_printed_messages)
-
-            # 'EOF' SSL error
-            exc = ssl.SSLError()
-            exc.errno = ssl.SSL_ERROR_EOF
-            self.tool.send_POST =\
-                create_send_POST_raiseOnRead(exc)
-            self.assertRaises(FailToLogin, self.tool._try_login, "foo", "bar")
-            expected_printed_messages.append(
-                'Error while sending login information: .*')
-            self.__check_printed_messages(expected_printed_messages)
-
-            # any other exception should be passed through
-            self.tool.send_POST =\
-                create_send_POST_raiseOnRead(ImportError())
-            self.assertRaises(ImportError, self.tool._try_login, "foo", "bar")
-            self.__check_printed_messages(expected_printed_messages)
-
-        finally:
-            self.tool.send_POST = orig_send_POST
-
-    def test_try_login_calls_cmdctl(self):
-        # Make sure _try_login() makes the right API call to cmdctl.
-        orig_conn = self.tool.conn
-        try:
-            class MyConn:
-                def __init__(self):
-                    self.method = None
-                    self.url = None
-                    self.param = None
-                    self.headers = None
-
-                def request(self, method, url, param, headers):
-                    self.method = method
-                    self.url = url
-                    self.param = param
-                    self.headers = headers
-
-                def getresponse(self):
-                    class MyResponse:
-                        def __init__(self):
-                            self.status = http.client.OK
-                        def read(self):
-                            class MyData:
-                                def decode(self):
-                                    return json.dumps(True)
-                            return MyData()
-                    return MyResponse()
-
-            self.tool.conn = MyConn()
-            self.assertTrue(self.tool._try_login('user32', 'pass64'))
-            self.assertEqual(self.tool.conn.method, 'POST')
-            self.assertEqual(self.tool.conn.url, '/login')
-            self.assertEqual(json.loads(self.tool.conn.param),
-                             {"password": "pass64", "username": "user32"})
-            self.assertIn('cookie', self.tool.conn.headers)
-        finally:
-            self.tool.conn = orig_conn
-
-    def test_run(self):
-        def login_to_cmdctl():
-            return True
-        def cmd_loop():
-            self.tool._send_message("/module_spec", None)
-
-        self.tool.login_to_cmdctl = login_to_cmdctl
-        # rewrite cmdloop() to avoid interactive mode
-        self.tool.cmdloop = cmd_loop
-
-        self.tool.conn.sock = FakeSocket()
-        self.tool.conn.sock.close()
-
-        self.assertEqual(1, self.tool.run())
-
-        # First few lines may be some kind of heading, or a warning that
-        # Python readline is unavailable, so we do a sub-string check.
-        self.assertIn("Failed to send request, the connection is closed",
-                      self.printed_messages)
-        self.assertEqual(1, len(self.printed_messages))
-
-        # validate log message for http.client.CannotSendRequest
-        self.assertEqual(1, self.tool.run())
-
-        # First few lines may be some kind of heading, or a warning that
-        # Python readline is unavailable, so we do a sub-string check.
-        self.assertIn("Can not send request, the connection is busy",
-                      self.printed_messages)
-        self.assertEqual(2, len(self.printed_messages))
-
-    def test_apply_cfg_command_int(self):
-        self.tool.location = '/'
-
-        self.assertEqual((1, MultiConfigData.DEFAULT),
-                         self.tool.config_data.get_value("/foo/an_int"))
-
-        cmd_parser = cmdparse.BindCmdParser('config set identifier='
-                                            '"foo/an_int" value="5"')
-        self.tool.apply_config_cmd(cmd_parser)
-        self.assertEqual((5, MultiConfigData.LOCAL),
-                         self.tool.config_data.get_value("/foo/an_int"))
-
-        cmd_parser = cmdparse.BindCmdParser('config unset identifier='
-                                            '"foo/an_int"')
-        self.tool.apply_config_cmd(cmd_parser)
-
-        self.assertEqual((1, MultiConfigData.DEFAULT),
-                         self.tool.config_data.get_value("/foo/an_int"))
-
-        # this should raise a NotFoundError
-        cmd_parser = cmdparse.BindCmdParser('config set identifier='
-                                            '"foo/bar" value="[]"')
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.tool.apply_config_cmd, cmd_parser)
-
-        cmd_parser = cmdparse.BindCmdParser('config unset identifier='
-                                            '"foo/bar"')
-        self.assertRaises(isc.cc.data.DataNotFoundError,
-                          self.tool.apply_config_cmd, cmd_parser)
-
-        # this should raise a TypeError
-        cmd_parser = cmdparse.BindCmdParser('config set identifier='
-                                            '"foo/an_int" value="[]"')
-        self.assertRaises(isc.cc.data.DataTypeError,
-                          self.tool.apply_config_cmd, cmd_parser)
-
-    # this is a very specific one for use with a set of list tests
-    # to try out the flexibility of the parser (only in the next test)
-    def clt(self, full_cmd_string, item_value):
-        cmd_parser = cmdparse.BindCmdParser(full_cmd_string)
-        self.tool.apply_config_cmd(cmd_parser)
-        self.assertEqual(([item_value], MultiConfigData.LOCAL),
-                         self.tool.config_data.get_value("/foo/a_list"))
-
-    def test_apply_cfg_command_list(self):
-        self.tool.location = '/'
-
-        self.assertEqual(([], MultiConfigData.DEFAULT),
-                         self.tool.config_data.get_value("/foo/a_list"))
-
-        self.clt("config set identifier=\"foo/a_list\" value=[\"a\"]", "a")
-        self.clt("config set identifier=\"foo/a_list\" value =[\"b\"]", "b")
-        self.clt("config set identifier=\"foo/a_list\" value= [\"c\"]", "c")
-        self.clt("config set identifier=\"foo/a_list\" value = [\"d\"]", "d")
-        self.clt("config set identifier =\"foo/a_list\" value=[\"e\"]", "e")
-        self.clt("config set identifier= \"foo/a_list\" value=[\"f\"]", "f")
-        self.clt("config set identifier = \"foo/a_list\" value=[\"g\"]", "g")
-        self.clt("config set identifier = \"foo/a_list\" value = [\"h\"]", "h")
-        self.clt("config set identifier = \"foo/a_list\" value=[\"i\" ]", "i")
-        self.clt("config set identifier = \"foo/a_list\" value=[ \"j\"]", "j")
-        self.clt("config set identifier = \"foo/a_list\" value=[ \"k\" ]", "k")
-
-        # this should raise a TypeError
-        cmd_parser = cmdparse.BindCmdParser('config set identifier='
-                                            '"foo/a_list" value="a"')
-        self.assertRaises(isc.cc.data.DataTypeError,
-                          self.tool.apply_config_cmd, cmd_parser)
-
-        cmd_parser = cmdparse.BindCmdParser('config set identifier='
-                                            '"foo/a_list" value=[1]')
-        self.assertRaises(isc.cc.data.DataTypeError,
-                          self.tool.apply_config_cmd, cmd_parser)
-
-    def tearDown(self):
-        sys.stdout = self.stdout_backup
-
-    def test_cmd_has_identifier_param(self):
-        module = ModuleInfo(name="test_module")
-
-        cmd = CommandInfo(name="command_with_identifier")
-        param = ParamInfo(name=bindcmd.CFGITEM_IDENTIFIER_PARAM)
-        cmd.add_param(param)
-        module.add_command(cmd)
-
-        cmd = CommandInfo(name="command_without_identifier")
-        param = ParamInfo(name="some_argument")
-        cmd.add_param(param)
-        module.add_command(cmd)
-
-        self.tool.add_module_info(module)
-
-        cmd_parser = cmdparse.BindCmdParser('test_module '
-                                            'command_with_identifier')
-        self.assertTrue(self.tool._cmd_has_identifier_param(cmd_parser))
-
-        cmd_parser = cmdparse.BindCmdParser('test_module '
-                                            'command_without_identifier')
-        self.assertFalse(self.tool._cmd_has_identifier_param(cmd_parser))
-
-        cmd_parser = cmdparse.BindCmdParser('badmodule '
-                                            'command_without_identifier')
-        self.assertFalse(self.tool._cmd_has_identifier_param(cmd_parser))
-
-    def test_get_identifier_startswith(self):
-        hints = self.tool._get_identifier_startswith("/")
-        self.assertEqual(['foo/an_int', 'foo/a_list'], hints)
-
-        hints = self.tool._get_identifier_startswith("/foo/an")
-        self.assertEqual(['foo/an_int'], hints)
-
-        hints = self.tool._get_identifier_startswith("/bar")
-        self.assertEqual([], hints)
-
-class FakeBindCmdInterpreter(bindcmd.BindCmdInterpreter):
-    def __init__(self):
-        pass
-
-class TestBindCmdInterpreter(unittest.TestCase):
-
-    def setUp(self):
-        self.old_stdout = sys.stdout
-
-    def tearDown(self):
-        sys.stdout = self.old_stdout
-
-    def _create_invalid_csv_file(self, csvfilename):
-        import csv
-        csvfile = open(csvfilename, 'w')
-        writer = csv.writer(csvfile)
-        writer.writerow(['name1'])
-        writer.writerow(['name2'])
-        csvfile.close()
-
-    def test_csv_file_dir(self):
-        # Checking default value
-        home_dir = pwd.getpwnam(getpass.getuser()).pw_dir
-        self.assertEqual(home_dir + os.sep + '.bind10' + os.sep,
-                         bindcmd.BindCmdInterpreter().csv_file_dir)
-
-        new_csv_dir = '/something/different/'
-        custom_cmd = bindcmd.BindCmdInterpreter(csv_file_dir=new_csv_dir)
-        self.assertEqual(new_csv_dir, custom_cmd.csv_file_dir)
-
-    def test_get_saved_user_info(self):
-        with open(os.devnull, 'w') as f:
-            sys.stdout = f
-            cmd = bindcmd.BindCmdInterpreter()
-            users = cmd._get_saved_user_info('/notexist', 'csv_file.csv')
-            self.assertEqual([], users)
-
-            csvfilename = 'csv_file.csv'
-            self._create_invalid_csv_file(csvfilename)
-            users = cmd._get_saved_user_info('./', csvfilename)
-            self.assertEqual([], users)
-            os.remove(csvfilename)
-
-class TestCommandLineOptions(unittest.TestCase):
-    def setUp(self):
-        self.parser = TestOptParser()
-        set_bindctl_options(self.parser)
-
-    def test_csv_file_dir(self):
-        # by default the option is "undefined"
-        (options, _) = self.parser.parse_args([])
-        self.assertEqual(None, options.csv_file_dir)
-
-        # specify the option, valid case.
-        (options, _) = self.parser.parse_args(['--csv-file-dir', 'some_dir'])
-        self.assertEqual('some_dir', options.csv_file_dir)
-
-        # missing option arg; should trigger parser error.
-        self.assertRaises(OptsError, self.parser.parse_args,
-                          ['--csv-file-dir'])
-
-if __name__== "__main__":
-    unittest.main()
-

+ 0 - 88
src/bin/bindctl/tests/cmdparse_test.py

@@ -1,88 +0,0 @@
-# Copyright (C) 2009  Internet Systems Consortium.
-#
-# 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.
-
-
-import unittest
-from bindctl import cmdparse
-
-class TestCmdParse(unittest.TestCase):
-
-    def test_remove_unquoted_whitespace(self):
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("a"), "a")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace(" a"), "a")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("a "), "a")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace(" a "), "a")
-        self.assertNotEqual(cmdparse._remove_unquoted_whitespace("a"), "a ")
-        self.assertNotEqual(cmdparse._remove_unquoted_whitespace(" a"), " a")
-        self.assertNotEqual(cmdparse._remove_unquoted_whitespace("a "), "a ")
-        self.assertNotEqual(cmdparse._remove_unquoted_whitespace(" a "), " a ")
-        self.assertNotEqual(cmdparse._remove_unquoted_whitespace(" a "), "b")
-
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("\"abc\""), "\"abc\"")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace(" \"abc\""), "\"abc\"")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("\"abc\" "), "\"abc\"")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace(" \"abc\" "), "\"abc\"")
-        
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("\" abc\""), "\" abc\"")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace(" \"a bc\""), "\"a bc\"")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("\"ab c\" "), "\"ab c\"")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace(" \"abc \" "), "\"abc \"")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace(" \" a b c \" "), "\" a b c \"")
-        
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("a\" abc\"a"), "a\" abc\"a")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("a \"a bc\"a"), "a\"a bc\"a")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("a\"ab c\" a"), "a\"ab c\"a")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("a \"abc \" a"), "a\"abc \"a")
-        self.assertEqual(cmdparse._remove_unquoted_whitespace("a \" a b c \" a"), "a\" a b c \"a")
-
-    # short-hand function to make the set of tests more readable
-    def rws(self, a, b):
-        self.assertEqual(cmdparse._remove_list_and_map_whitespace(a), b)
-
-    def test_remove_list_whitespace(self):
-        self.rws("a", "a")
-        self.rws(" a ", " a ")
-        self.rws(" [a] ", " [a] ")
-        self.rws(" [ a] ", " [a] ")
-        self.rws(" [ a ] ", " [a] ")
-        self.rws(" [ a b c ] ", " [abc] ")
-        self.rws(" [ a \"b c\" ] ", " [a\"b c\"] ")
-        self.rws("a [ a \"b c\" ] a", "a [a\"b c\"] a")
-        self.rws("a] [ a \"b c\" ] a", "a] [a\"b c\"] a")
-        self.rws(" [ a [b c] ] ", " [a[bc]] ")
-        self.rws(" [ a b][ c d ] ", " [ab][cd] ")
-        self.rws(" [ a b] [ c d ] ", " [ab] [cd] ")
-        
-        self.rws("a", "a")
-        self.rws(" a ", " a ")
-        self.rws(" {a} ", " {a} ")
-        self.rws(" { a} ", " {a} ")
-        self.rws(" { a } ", " {a} ")
-        self.rws(" { a b c } ", " {abc} ")
-        self.rws(" { a \"b c\" } ", " {a\"b c\"} ")
-        self.rws("a { a \"b c\" } a", "a {a\"b c\"} a")
-        self.rws("a} { a \"b c\" } a", "a} {a\"b c\"} a")
-        self.rws(" { a {b c} } ", " {a{bc}} ")
-        self.rws(" { a b}{ c d } ", " {ab}{cd} ")
-        self.rws(" { a b} { c d } ", " {ab} {cd} ")
-
-        self.rws(" [ a b]{ c d } ", " [ab]{cd} ")
-        self.rws(" [ a b{ c d }] ", " [ab{cd}] ")
-        self.rws(" [ a b{ \"c d\" }] ", " [ab{\"c d\"}] ")
-        
-
-if __name__== "__main__":
-    unittest.main()
-    

+ 0 - 3
src/bin/cfgmgr/.gitignore

@@ -1,3 +0,0 @@
-/b10-cfgmgr
-/b10-cfgmgr.py
-/b10-cfgmgr.8

+ 0 - 43
src/bin/cfgmgr/Makefile.am

@@ -1,43 +0,0 @@
-SUBDIRS = . plugins local_plugins tests
-
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-
-pkglibexec_SCRIPTS = b10-cfgmgr
-
-CLEANFILES = b10-cfgmgr b10-cfgmgr.pyc
-
-b10_cfgmgrdir = @localstatedir@/@PACKAGE@
-#B10_cfgmgr_DATA = 
-
-man_MANS = b10-cfgmgr.8
-DISTCLEANFILES = $(man_MANS)
-EXTRA_DIST = $(man_MANS) b10-cfgmgr.xml
-
-if GENERATE_DOCS
-
-b10-cfgmgr.8: b10-cfgmgr.xml
-	@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-cfgmgr.xml
-
-else
-
-$(man_MANS):
-	@echo Man generation disabled.  Creating dummy $@.  Configure with --enable-generate-docs to enable it.
-	@echo Man generation disabled.  Remove this file, configure with --enable-generate-docs, and rebuild BIND 10 > $@
-
-endif
-
-# this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
-b10-cfgmgr: b10-cfgmgr.py
-	$(SED) "s|@@PYTHONPATH@@|@pyexecdir@|" b10-cfgmgr.py >$@
-	chmod a+x $@
-
-install-data-local:
-	$(mkinstalldirs) $(DESTDIR)/@localstatedir@/@PACKAGE@
-
-install-data-hook:
-	-chmod 2770 $(DESTDIR)/@localstatedir@/@PACKAGE@
-
-CLEANDIRS = __pycache__
-
-clean-local:
-	rm -rf $(CLEANDIRS)

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

@@ -1,132 +0,0 @@
-#!@PYTHON@
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-import sys; sys.path.append ('@@PYTHONPATH@@')
-
-import bind10_config
-from isc.cc import SessionError
-import isc.util.process
-import signal
-import os
-from optparse import OptionParser
-import glob
-import os.path
-import imp
-import isc.log
-isc.log.init("b10-cfgmgr", buffer=True)
-from isc.config.cfgmgr import ConfigManager, ConfigManagerDataReadError, logger
-from isc.log_messages.cfgmgr_messages import *
-import isc.util.traceback_handler
-
-isc.util.process.rename()
-
-# Import some paths from our configuration
-DATA_PATH = bind10_config.DATA_PATH
-PLUGIN_PATHS = bind10_config.PLUGIN_PATHS
-PREFIX = bind10_config.PREFIX
-DEFAULT_CONFIG_FILE = "b10-config.db"
-
-cm = None
-
-def parse_options(args=sys.argv[1:], Parser=OptionParser):
-    parser = Parser()
-    parser.add_option("-p", "--data-path", dest="data_path",
-                      help="Directory to search for configuration files " +
-                      "(default=" + DATA_PATH + ")", default=None)
-    parser.add_option("-c", "--config-filename", dest="config_file",
-                      help="Configuration database filename " +
-                      "(default=" + DEFAULT_CONFIG_FILE + ")",
-                      default=None)
-    parser.add_option("--clear-config", action="store_true",
-                      dest="clear_config", default=False,
-                      help="Back up the configuration file and start with " +
-                           "a clean one")
-    (options, args) = parser.parse_args(args)
-    if args:
-        parser.error("No non-option arguments allowed")
-    return options
-
-def signal_handler(signal, frame):
-    global cm
-    if cm:
-        cm.running = False
-
-def load_plugins(path, cm):
-    """Load all python files in the given path and treat them as plugins."""
-    # Find the python files
-    plugins = glob.glob(path + os.sep + '*.py')
-    for plugin in plugins:
-        # Generate the name of the plugin
-        filename = os.path.basename(plugin)
-        name = filename[:-3]
-        # Load it
-        module = imp.load_source(name, plugin)
-        # Ask it to provide the spec and checking function
-        (spec, check_func) = module.load()
-        # And insert it into the manager
-        cm.set_virtual_module(spec, check_func)
-
-
-def determine_path_and_file(data_path_option, config_file_option):
-    """Given the data path and config file as specified on the command line
-       (or not specified, as may be the case), determine the full path and
-       file to use when starting the config manager;
-       - if neither are given, use defaults
-       - if both are given, use both
-       - if only data path is given, use default file in that path
-       - if only file is given, use cwd() + file (if file happens to
-         be an absolute file name, path will be ignored)
-       Arguments are either a string, or None.
-       Returns a tuple containing (result_path, result_file).
-    """
-    data_path = data_path_option
-    config_file = config_file_option
-    if config_file is None:
-        config_file = DEFAULT_CONFIG_FILE
-        if data_path is None:
-            data_path = DATA_PATH
-    else:
-        if data_path is None:
-            data_path = os.getcwd()
-    return (data_path, config_file)
-
-def main():
-    options = parse_options()
-    global cm
-    try:
-        (data_path, config_file) = determine_path_and_file(options.data_path,
-                                                           options.config_file)
-        cm = ConfigManager(data_path, config_file, None, options.clear_config)
-        signal.signal(signal.SIGINT, signal_handler)
-        signal.signal(signal.SIGTERM, signal_handler)
-        cm.read_config()
-        for ppath in PLUGIN_PATHS:
-            load_plugins(ppath, cm)
-        cm.notify_b10_init()
-        cm.run()
-    except SessionError as se:
-        logger.fatal(CFGMGR_CC_SESSION_ERROR, se)
-        return 1
-    except KeyboardInterrupt as kie:
-        logger.info(CFGMGR_STOPPED_BY_KEYBOARD)
-    except ConfigManagerDataReadError as cmdre:
-        logger.fatal(CFGMGR_DATA_READ_ERROR, cmdre)
-        return 2
-    return 0
-
-if __name__ == "__main__":
-    sys.exit(isc.util.traceback_handler.traceback_handler(main))

+ 0 - 174
src/bin/cfgmgr/b10-cfgmgr.xml

@@ -1,174 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	       [<!ENTITY mdash "&#8212;">]>
-<!--
- - Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
- -
- - Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
- - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- - AND FITNESS.  IN NO EVENT SHALL ISC 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.
--->
-
-<refentry>
-
-  <refentryinfo>
-    <date>June 20, 2012</date>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>b10-cfgmgr</refentrytitle>
-    <manvolnum>8</manvolnum>
-    <refmiscinfo>BIND10</refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>b10-cfgmgr</refname>
-    <refpurpose>Configuration manager</refpurpose>
-  </refnamediv>
-
-  <docinfo>
-    <copyright>
-      <year>2010</year>
-      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
-    </copyright>
-  </docinfo>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>b10-cfgmgr</command>
-      <arg><option>-c <replaceable>config-filename</replaceable></option></arg>
-      <arg><option>-p <replaceable>data_path</replaceable></option></arg>
-      <arg><option>--clear-config</option></arg>
-      <arg><option>--config-filename <replaceable>config-filename</replaceable></option></arg>
-      <arg><option>--data-path <replaceable>data_path</replaceable></option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>DESCRIPTION</title>
-    <para>
-      The <command>b10-cfgmgr</command> daemon handles all BIND 10
-      system configuration. It provides persistent storage for
-      configuration, and notifies running BIND 10 modules of
-      configuration changes.
-    </para>
-
-    <para>
-      The <command>bindctl</command> can be used to talk to this
-      configuration manager via a <command>b10-cmdctl</command> connection.
-    </para>
-
-<!-- TODO: briefly explain why both msqg channel and cmdctl communication -->
-    <para>
-      This daemon communicates over a <command>b10-msgq</command> C-Channel
-      connection.  If this connection is not established,
-      <command>b10-cfgmgr</command> will exit.
-    </para>
-<!-- TODO: will it exit?  -->
-
-    <para>
-      The daemon may be cleanly stopped by sending the SIGTERM
-      signal to the process.  This shutdown does not notify the
-      subscribers.
-    </para>
-
-<!-- TODO: add a verbose or quiet switch so it is not so noisy -->
-  </refsect1>
-
-  <refsect1>
-    <title>ARGUMENTS</title>
-
-    <para>The arguments are as follows:</para>
-
-    <variablelist>
-      <varlistentry>
-        <term>
-          <option>--clear-config</option>
-        </term>
-        <listitem>
-          <para>
-            This will create a backup of the existing configuration
-            file, remove it, and
-            <refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum>
-            will use the default configurations.
-            The name of the backup file can be found in the logs
-            (<varname>CFGMGR_BACKED_UP_CONFIG_FILE</varname>).
-            (It will append a number to the backup filename if a
-            previous backup file exists.)
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>
-          <option>-c</option> <replaceable>config-filename</replaceable>,
-          <option>--config-filename</option> <replaceable>config-filename</replaceable>
-        </term>
-        <listitem>
-          <para>The configuration database filename to use. Can be either
-          absolute or relative to data path.
-          It defaults to "<filename>b10-config.db</filename>".</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>
-          <option>-p</option> <replaceable>data-path</replaceable>,
-          <option>--data-path</option> <replaceable>data-path</replaceable>
-        </term>
-        <listitem>
-          <para>The path where BIND 10 looks for files. The
-          configuration file is looked for here, if it is relative. If it is
-          absolute, the path is ignored.</para>
-        </listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>FILES</title>
-<!-- TODO: fix path -->
-    <para><filename>/usr/local/var/bind10/b10-config.db</filename>
-      &mdash; Configuration storage file.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>.
-      <citerefentry>
-        <refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>HISTORY</title>
-    <para>
-      The <command>b10-cfgmgr</command> daemon and configuration
-      specification were initially designed by Jelte Jansen of ISC.
-      Its development began in October 2009.
-    </para>
-  </refsect1>
-</refentry><!--
- - Local variables:
- - mode: sgml
- - End:
--->

+ 0 - 1
src/bin/cfgmgr/local_plugins/.gitignore

@@ -1 +0,0 @@
-/datasrc.spec

+ 0 - 11
src/bin/cfgmgr/local_plugins/Makefile.am

@@ -1,11 +0,0 @@
-# Nothing is installed from this directory.  This local_plugins
-# directory overrides the plugins directory when lettuce is run, and the
-# spec file here is used to serve the static zone from the source tree
-# for testing (instead of installation prefix).
-
-noinst_DATA = datasrc.spec
-
-datasrc.spec: ../plugins/datasrc.spec.pre
-	$(SED) -e "s|@@STATIC_ZONE_FILE@@|$(abs_top_builddir)/src/lib/datasrc/static.zone|;s|@@SQLITE3_DATABASE_FILE@@|$(abs_top_builddir)/local.zone.sqlite3|" ../plugins/datasrc.spec.pre >$@
-
-CLEANFILES = datasrc.spec

+ 0 - 2
src/bin/cfgmgr/plugins/.gitignore

@@ -1,2 +0,0 @@
-/datasrc.spec
-/datasrc.spec.pre

+ 0 - 18
src/bin/cfgmgr/plugins/Makefile.am

@@ -1,18 +0,0 @@
-SUBDIRS = tests
-
-EXTRA_DIST = README logging.spec tsig_keys.spec
-
-datasrc.spec: datasrc.spec.pre
-	$(SED) -e "s|@@STATIC_ZONE_FILE@@|$(pkgdatadir)/static.zone|;s|@@SQLITE3_DATABASE_FILE@@|$(localstatedir)/$(PACKAGE)/zone.sqlite3|" datasrc.spec.pre >$@
-
-config_plugindir = @prefix@/share/@PACKAGE@/config_plugins
-config_plugin_DATA = logging.spec tsig_keys.spec
-
-python_PYTHON = b10logging.py tsig_keys.py
-pythondir = $(config_plugindir)
-
-CLEANFILES = b10logging.pyc tsig_keys.pyc datasrc.spec
-CLEANDIRS = __pycache__
-
-clean-local:
-	rm -rf $(CLEANDIRS)

+ 0 - 34
src/bin/cfgmgr/plugins/README

@@ -1,34 +0,0 @@
-How to write a configuration plugin
-===================================
-
-The plugins are used to describe configuration modules that have no hosting
-process. Therefore there's no process to provide their specification and to
-check them for correctness. So the plugin takes this responsibility.
-
-Each plugin is a python file installed into the
-`@prefix@/share/@PACKAGE@/config_plugins` directory (usually
-`/usr/share/bind10/config_plugins`). It is loaded automatically at startup.
-
-The entrypoint of a plugin is function called `load()`. It should return a
-tuple, first value should be the module specification (usually instance of
-`isc.config.module_spec.ModuleSpec`, loaded by `module_spec_from_file()`).
-
-The second value is a callable object. It will be called whenever the
-configuration of module needs to be checked. The only parameter will be the new
-config (as python dictionary). To accept the new configuration, return None. If
-you return a string, it is taken as an error message. If you raise an
-exception, the config is rejected as well, however it is not considered a
-graceful rejection, but a failure of the module.
-
-So, this is how a plugin could look like:
-
-  from isc.config.module_spec import module_spec_from_file
-
-  def check(config):
-      if config['bogosity'] > 1:
-          return "Too bogus to live with"
-      else:
-          return None
-
-  def load():
-      return (module_spec_from_file('module_spec.spec'), check)

+ 0 - 109
src/bin/cfgmgr/plugins/b10logging.py

@@ -1,109 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium.
-#
-# 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.
-
-# This is the configuration plugin for logging options
-# The name is 'b10logging' because logging.py is an existing module
-#
-# For a technical background, see
-# http://bind10.isc.org/wiki/LoggingCppApiDesign
-#
-
-from isc.config.module_spec import module_spec_from_file
-from isc.util.file import path_search
-from bind10_config import PLUGIN_PATHS
-spec = module_spec_from_file(path_search('logging.spec', PLUGIN_PATHS))
-
-ALLOWED_SEVERITIES = [ 'default',
-                       'debug',
-                       'info',
-                       'warn',
-                       'error',
-                       'fatal',
-                       'none' ]
-ALLOWED_DESTINATIONS = [ 'console',
-                         'file',
-                         'syslog' ]
-ALLOWED_STREAMS = [ 'stdout',
-                    'stderr' ]
-
-def check(config):
-    # Check the data layout first
-    errors=[]
-    if not spec.validate_config(False, config, errors):
-        return ' '.join(errors)
-    # The 'layout' is ok, now check for specific values
-    if 'loggers' in config:
-        for logger in config['loggers']:
-            # name should always be present
-            name = logger['name']
-            # report an error if name starts with * but not *.,
-            # or if * is not the first character.
-            # TODO: we might want to also warn or error if the
-            # logger name is not an existing module, but we can't
-            # really tell that from here at this point
-            star_pos = name.find('*')
-            if star_pos > 0 or\
-               name == '*.' or\
-               (star_pos == 0 and len(name) > 1 and name[1] != '.'):
-                errors.append("Bad logger name: '" + name + "': * can "
-                              "only be used instead of the full "
-                              "first-level name, e.g. '*' or "
-                              "'*.subsystem'")
-
-            if 'severity' in logger and\
-               logger['severity'].lower() not in ALLOWED_SEVERITIES:
-                errors.append("bad severity value for logger " + name +
-                              ": " + logger['severity'])
-            if 'output_options' in logger:
-                for output_option in logger['output_options']:
-                    if 'destination' in output_option:
-                        destination = output_option['destination'].lower()
-                        if destination not in ALLOWED_DESTINATIONS:
-                            errors.append("bad destination for logger " +
-                            name + ": " + output_option['destination'])
-                        else:
-                            # if left to default, output is stdout, and
-                            # it will not show in the updated config,
-                            # so 1. we only need to check it if present,
-                            # and 2. if destination is changed, so should
-                            # output. So first check checks 'in', and the
-                            # others 'not in' for 'output'
-                            if destination == "console" and\
-                               'output' in output_option and\
-                               output_option['output'] not in ALLOWED_STREAMS:
-                                errors.append("bad output for logger " + name +
-                                              ": " + output_option['output'] +
-                                              ", must be stdout or stderr")
-                            elif destination == "file" and\
-                                 ('output' not in output_option or\
-                                  output_option['output'] == ""):
-                                    errors.append("destination set to file but "
-                                                  "output not set to any "
-                                                  "filename for logger "
-                                                  + name)
-                            elif destination == "syslog" and\
-                                 'output' not in output_option or\
-                                 output_option['output'] == "":
-                                    errors.append("destination set to syslog but "
-                                                  "output not set to any facility"
-                                                  " for logger " + name)
-
-    if errors:
-        return ', '.join(errors)
-    return None
-
-def load():
-    return (spec, check)
-

+ 0 - 85
src/bin/cfgmgr/plugins/datasrc.spec.pre.in

@@ -1,85 +0,0 @@
-{
-    "module_spec": {
-        "module_name": "data_sources",
-        "module_description": "The sources of authoritative DNS data",
-        "config_data": [
-            {
-                "item_name": "classes",
-                "item_type": "named_set",
-                "item_optional": false,
-                "item_default": {
-                    "IN": [
-                        {
-                            "type": "sqlite3",
-                            "params": {
-                                "database_file": "@@SQLITE3_DATABASE_FILE@@"
-                            }
-                        }
-                    ],
-                    "CH": [
-                        {
-                            "type": "MasterFiles",
-                            "cache-enable": true,
-                            "params": {"BIND": "@@STATIC_ZONE_FILE@@"}
-                        }
-                    ]
-                },
-                "named_set_item_spec": {
-                    "item_name": "class",
-                    "item_type": "list",
-                    "item_optional": false,
-                    "item_default": [],
-                    "list_item_spec": {
-                        "item_name": "source",
-                        "item_type": "map",
-                        "item_optional": false,
-                        "item_default": {},
-                        "map_item_spec": [
-                            {
-                                "item_name": "type",
-                                "item_type": "string",
-                                "item_optional": false,
-                                "item_default": ""
-                            },
-                            {
-                                "item_name": "params",
-                                "item_type": "any",
-                                "item_optional": false,
-                                "item_default": null
-                            },
-                            {
-                                "item_name": "cache-enable",
-                                "item_type": "boolean",
-                                "item_optional": false,
-                                "item_default": false
-                            },
-                            {
-                                "item_name": "cache-zones",
-                                "item_type": "list",
-                                "item_optional": true,
-                                "list_item_spec": {
-                                    "item_name": "zone",
-                                    "item_type": "string",
-                                    "item_optional": false,
-                                    "item_default": ""
-                                }
-                            },
-                            {
-                                "item_name": "name",
-                                "item_type": "string",
-                                "item_optional": true
-                            },
-                            {
-                                "item_name": "cache-type",
-                                "item_type": "string",
-                                "item_optional": true,
-                                "item_default": "local"
-                            }
-                        ]
-                    }
-                }
-            }
-        ],
-        "commands": []
-    }
-}

+ 0 - 80
src/bin/cfgmgr/plugins/datasrc_config_plugin.py

@@ -1,80 +0,0 @@
-# Copyright (C) 2012  Internet Systems Consortium.
-#
-# 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.
-
-from isc.config.module_spec import module_spec_from_file
-from isc.util.file import path_search
-from bind10_config import PLUGIN_PATHS
-import isc.dns
-import isc.datasrc
-import json
-import os.path
-import copy
-
-spec = module_spec_from_file(path_search('datasrc.spec', PLUGIN_PATHS))
-
-def check(config):
-    """
-    Check the configuration.
-    """
-    # Check the data layout first
-    errors=[]
-    if not spec.validate_config(False, config, errors):
-        return ' '.join(errors)
-
-    classes = config.get('classes')
-    # Nothing passed here
-    if classes is None:
-        return None
-
-    for rr_class_str in classes:
-        try:
-            rr_class = isc.dns.RRClass(rr_class_str)
-        except isc.dns.InvalidRRClass as irc:
-            return "The class '" + rr_class_str + "' is invalid"
-
-        dlist = isc.datasrc.ConfigurableClientList(rr_class)
-        # We get a copy here, as we are going to mangle the configuration.
-        # But we don't want our changes to propagate outside, to the real
-        # configuration.
-        client_config = copy.deepcopy(classes.get(rr_class_str))
-
-        for client in client_config:
-            if client['type'] == 'MasterFiles':
-                if not client.get('cache-enable', False):
-                    return 'The cache must be enabled in MasterFiles type'
-                params = client.get('params')
-                if type(params) != dict:
-                    return 'Params of MasterFiles must be a named set'
-                for name in params:
-                    try:
-                        isc.dns.Name(name)
-                    except Exception as e: # There are many related exceptions
-                        return str(e)
-                    if not os.path.exists(params[name]):
-                        return "Master file " + params[name] + " does not exist"
-                # We remove the list of zones locally. We already checked them,
-                # and the client list would have skipped them anyway, as we
-                # forbid cache. But it would produce a warning and we don't
-                # want that here.
-                client['params'] = {}
-
-        try:
-            dlist.configure(json.dumps(client_config), False)
-        except isc.datasrc.Error as dse:
-            return str(dse)
-    return None
-
-def load():
-    return (spec, check)

+ 0 - 81
src/bin/cfgmgr/plugins/logging.spec

@@ -1,81 +0,0 @@
-{
-    "module_spec": {
-        "module_name": "Logging",
-        "module_description": "Logging options",
-        "config_data": [
-            {
-                "item_name": "loggers",
-                "item_type": "list",
-                "item_optional": false,
-                "item_default": [],
-                "list_item_spec": {
-                  "item_name": "logger",
-                  "item_type": "map",
-                  "item_optional": false,
-                  "item_default": {},
-                  "map_item_spec": [
-                  {  "item_name": "name",
-                     "item_type": "string",
-                     "item_optional": false,
-                     "item_default": ""
-                  },
-                  {  "item_name": "severity",
-                     "item_type": "string",
-                     "item_optional": false,
-                     "item_default": "INFO"
-                  },
-                  {  "item_name": "debuglevel",
-                     "item_type": "integer",
-                     "item_optional": false,
-                     "item_default": 0
-                  },
-                  {  "item_name": "additive",
-                     "item_type": "boolean",
-                     "item_optional": false,
-                     "item_default": false
-                  },
-                  { "item_name": "output_options",
-                    "item_type": "list",
-                    "item_optional": false,
-                    "item_default": [],
-                    "list_item_spec": {
-                      "item_name": "output_option",
-                      "item_type": "map",
-                      "item_optional": false,
-                      "item_default": {},
-                      "map_item_spec": [
-                      { "item_name": "destination",
-                        "item_type": "string",
-                        "item_optional": false,
-                        "item_default": "console"
-                      },
-                      { "item_name": "output",
-                        "item_type": "string",
-                        "item_optional": false,
-                        "item_default": "stdout"
-                      },
-                      { "item_name": "flush",
-                        "item_type": "boolean",
-                        "item_optional": false,
-                        "item_default": true
-                      },
-                      { "item_name": "maxsize",
-                        "item_type": "integer",
-                        "item_optional": false,
-                        "item_default": 0
-                      },
-                      { "item_name": "maxver",
-                        "item_type": "integer",
-                        "item_optional": false,
-                        "item_default": 0
-                      }
-                      ]
-                    }
-                  }
-                  ]
-                }
-            }
-        ],
-        "commands": []
-    }
-}

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 30
src/bin/cfgmgr/plugins/tests/Makefile.am


+ 0 - 245
src/bin/cfgmgr/plugins/tests/datasrc_test.py

@@ -1,245 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium.
-#
-# 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.
-
-# Make sure we can load the module, put it into path
-import sys
-import os
-import unittest
-import json
-sys.path.extend(os.environ["B10_TEST_PLUGIN_DIR"].split(':'))
-import isc.log
-
-import datasrc_config_plugin
-
-class DatasrcTest(unittest.TestCase):
-    def reject(self, config):
-        """
-        Just a shortcut to check the config is rejected.
-        """
-        old = json.dumps(config)
-        self.assertIsNotNone(datasrc_config_plugin.check({"classes":
-                                                         config}))
-        # There's some data mangling inside the plugin. Check it does
-        # not propagate out, as it could change the real configuration.
-        self.assertEqual(old, json.dumps(config))
-
-    def accept(self, config):
-        """
-        Just a shortcut to check the config is accepted.
-        """
-        old = json.dumps(config)
-        self.assertIsNone(datasrc_config_plugin.check({"classes":
-                                                      config}))
-        # There's some data mangling inside the plugin. Check it does
-        # not propagate out, as it could change the real configuration.
-        self.assertEqual(old, json.dumps(config))
-
-    def test_load(self):
-        """
-        Checks the entry point returns the correct values.
-        """
-        (spec, check) = datasrc_config_plugin.load()
-        # It returns the checking function
-        self.assertEqual(check, datasrc_config_plugin.check)
-        # The plugin stores it's spec
-        self.assertEqual(spec, datasrc_config_plugin.spec)
-
-    def test_empty(self):
-        """
-        Check an empty input is OK.
-        """
-        self.accept({})
-
-    def test_invalid_spec(self):
-        """
-        Check it rejects stuff that is not well-formed according
-        to the spec.
-        """
-        self.reject("test")
-        self.reject(13)
-        self.reject([])
-        self.reject({"IN": {}})
-        self.reject({"IN": [{"bad-name": True}]})
-
-    def test_class(self):
-        """
-        The class is rejected, if it is wrong.
-        """
-        self.reject({"BAD": []})
-        self.reject({"": []})
-        # But with a good one, it works
-        for c in ["IN", "CH", "HS"]:
-            self.accept({c: []})
-
-    def test_mem_ok(self):
-        """
-        Test we accept an in-memory data source. It doesn't really matter
-        which one it is. We just want to make sure we accept something
-        and this one does not need any kind of path mangling to find
-        plugins.
-        """
-        self.accept({"IN": [{
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {}
-        }]})
-
-    def test_invalid_mem_params(self):
-        """
-        The client list skips in-memory sources. So we check it locally that
-        invalid things are rejected.
-        """
-        # The 'params' key is mandatory for MasterFiles
-        self.reject({"IN": [{
-            "type": "MasterFiles",
-            "cache-enable": True
-        }]})
-        # The cache must be enabled
-        self.reject({"IN": [{
-            "type": "MasterFiles",
-            "cache-enable": False,
-            "params": {}
-        }]})
-        self.reject({"IN": [{
-            "type": "MasterFiles",
-            "params": {}
-        }]})
-        # Bad params type
-        self.reject({"IN": [{
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": []
-        }]})
-        # Bad name
-        self.reject({"IN": [{
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {
-                "example....org.": '/file/does/not/exist'
-            }
-        }]})
-
-    def test_no_such_file_mem(self):
-        """
-        We also check the existence of master files. Not the actual content,
-        though.
-        """
-        self.reject({"IN": [{
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {
-                "example.org.": '/file/does/not/exist'
-            }
-        }]})
-
-    def test_names_present(self):
-        """
-        Test we don't choke on configuration with the "name" being present on
-        some items.
-        """
-        self.accept({"IN": [{
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {},
-            "name": "Whatever"
-        }]})
-
-    def test_names_default_classes(self):
-        """
-        Test we can have a client of the same type in different classes
-        without specified name. The defaults should be derived both from
-        the type and the class.
-        """
-        self.accept({
-        "IN": [{
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {}
-        }],
-        "CH": [{
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {}
-        }]})
-
-    def test_names_collision(self):
-        """
-        Reject when two names are the same.
-
-        Cases are:
-        - Explicit names.
-        - Two default names turn out to be the same (same type and class).
-        - One explicit is set to the same as the default one.
-        """
-        self.reject({"IN": [
-        {
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {},
-            "name": "Whatever"
-        },
-        {
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {},
-            "name": "Whatever"
-        }]})
-        # The same, but across different classes is allowed (we would
-        # identify the data source by class+name tuple)
-        self.accept({
-        "IN": [
-            {
-                "type": "MasterFiles",
-                "cache-enable": True,
-                "params": {},
-                "name": "Whatever"
-            }
-        ],
-        "CH": [
-            {
-                "type": "MasterFiles",
-                "cache-enable": True,
-                "params": {},
-                "name": "Whatever"
-            }
-        ]})
-        self.reject({"IN": [
-        {
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {}
-        },
-        {
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {}
-        }]})
-        self.reject({"IN": [
-        {
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {},
-            "name": "MasterFiles"
-        },
-        {
-            "type": "MasterFiles",
-            "cache-enable": True,
-            "params": {}
-        }]})
-
-if __name__ == '__main__':
-    isc.log.init("bind10")
-    isc.log.resetUnitTestRootLogger()
-    unittest.main()

+ 0 - 135
src/bin/cfgmgr/plugins/tests/logging_test.py

@@ -1,135 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium.
-#
-# 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.
-
-# Make sure we can load the module, put it into path
-import sys
-import os
-sys.path.extend(os.environ["B10_TEST_PLUGIN_DIR"].split(':'))
-
-import b10logging
-import unittest
-
-class LoggingConfCheckTest(unittest.TestCase):
-    def test_load(self):
-        """
-        Checks the entry point returns the correct values.
-        """
-        (spec, check) = b10logging.load()
-        # It returns the checking function
-        self.assertEqual(check, b10logging.check)
-        # The plugin stores it's spec
-        self.assertEqual(spec, b10logging.spec)
-
-    def test_logger_conf(self):
-        self.assertEqual(None,
-                         b10logging.check({'loggers':
-                                          [{'name': '*',
-                                            'severity': 'DEBUG',
-                                            'debuglevel': 50,
-                                            'output_options':
-                                            [{'destination': 'file',
-                                              'output': '/some/file'
-                                            }]
-                                           },
-                                           {'name': 'b10-resolver',
-                                            'severity': 'WARN',
-                                            'additive': True,
-                                            'output_options':
-                                            [{'destination': 'console',
-                                              'output': 'stderr',
-                                              'flush': True
-                                            }]
-                                           },
-                                           {'name': 'b10-resolver.resolver',
-                                            'severity': 'ERROR',
-                                            'output_options': []
-                                           },
-                                           {'name': '*.cache',
-                                            'severity': 'INFO'
-                                           }
-                                          ]}))
-    def do_bad_name_test(self, name):
-        err_str = "Bad logger name: '" + name + "': * can only be "\
-                  "used instead of the full first-level name, e.g. "\
-                  "'*' or '*.subsystem'"
-        self.assertEqual(err_str,
-                         b10logging.check({'loggers':
-                                          [{'name': name,
-                                            'severity': 'DEBUG'},
-                                          ]}))
-        
-    def test_logger_bad_name(self):
-        self.do_bad_name_test("*.")
-        self.do_bad_name_test("*foo")
-        self.do_bad_name_test("*foo.lib")
-        self.do_bad_name_test("foo*")
-        self.do_bad_name_test("foo*.lib")
-
-    def test_logger_bad_severity(self):
-        self.assertEqual('bad severity value for logger *: BADVAL',
-                         b10logging.check({'loggers':
-                                          [{'name': '*',
-                                            'severity': 'BADVAL'}]}))
-
-    def test_logger_bad_destination(self):
-        self.assertEqual('bad destination for logger *: baddest',
-                         b10logging.check({'loggers':
-                                          [{'name': '*',
-                                            'severity': 'INFO',
-                                            'output_options': [
-                                            { 'destination': 'baddest' }
-                                            ]}]}))
-
-    def test_logger_bad_console_output(self):
-        self.assertEqual('bad output for logger *: bad_output, must be stdout or stderr',
-                         b10logging.check({'loggers':
-                                          [{'name': '*',
-                                            'severity': 'INFO',
-                                            'output_options': [
-                                            { 'destination': 'console',
-                                              'output': 'bad_output'
-                                            }
-                                            ]}]}))
-
-    def test_logger_bad_file_output(self):
-        self.assertEqual('destination set to file but output not set to any filename for logger *',
-                         b10logging.check({'loggers':
-                                          [{'name': '*',
-                                            'severity': 'INFO',
-                                            'output_options': [
-                                            { 'destination': 'file' }
-                                            ]}]}))
-
-    def test_logger_bad_syslog_output(self):
-        self.assertEqual('destination set to syslog but output not set to any facility for logger *',
-                         b10logging.check({'loggers':
-                                          [{'name': '*',
-                                            'severity': 'INFO',
-                                            'output_options': [
-                                            { 'destination': 'syslog' }
-                                            ]}]}))
-
-    def test_logger_bad_type(self):
-        self.assertEqual('123 should be a string',
-                         b10logging.check({'loggers':
-                                          [{'name': 123,
-                                            'severity': 'INFO'}]}))
-        self.assertEqual('123 should be a string',
-                         b10logging.check({'loggers':
-                                          [{'name': 'bind10',
-                                            'severity': 123}]}))
-
-if __name__ == '__main__':
-        unittest.main()

+ 0 - 103
src/bin/cfgmgr/plugins/tests/tsig_keys_test.py

@@ -1,103 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium.
-#
-# 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.
-
-# Make sure we can load the module, put it into path
-import sys
-import os
-sys.path.extend(os.environ["B10_TEST_PLUGIN_DIR"].split(':'))
-
-import tsig_keys
-import unittest
-import isc.config.module_spec
-
-class TSigKeysTest(unittest.TestCase):
-    def test_load(self):
-        """
-        Checks the entry point returns the correct values.
-        """
-        (spec, check) = tsig_keys.load()
-        # It returns the checking function
-        self.assertEqual(check, tsig_keys.check)
-        # The plugin stores it's spec
-        self.assertEqual(spec, tsig_keys.spec)
-
-    def test_spec(self):
-        """
-        Checks the spec is looking sane (doesn't do really deep check here).
-        """
-        spec = tsig_keys.spec
-        # In python, we don't generally check the type of something, because
-        # of the duck typing.
-        # But this is unittest, so we check it does what we intend and
-        # supplying that's behaving the same but is different is not our
-        # intention
-        self.assertTrue(isinstance(spec, isc.config.module_spec.ModuleSpec))
-        # Correct name
-        self.assertEqual("tsig_keys", spec.get_module_name())
-        # There are no commands, nobody would handle them anyway
-        self.assertEqual([], spec.get_commands_spec())
-        # There's some nonempty configuration
-        self.assertNotEqual({}, spec.get_config_spec())
-
-    def test_missing_keys(self):
-        """
-        Test that missing keys doesn't kill us. There are just no keys there.
-        """
-        self.assertEqual(None, tsig_keys.check({}))
-
-    def test_data_empty(self):
-        """Check we accept valid config with empty set of tsig keys."""
-        self.assertEqual(None, tsig_keys.check({'keys': []}))
-
-    def test_keys_valid(self):
-        """
-        Check we accept some valid keys (we don't check all the algorithms,
-        that's the job of isc.dns.TSIGKey).
-        """
-        self.assertEqual(None, tsig_keys.check({'keys':
-            ['testkey:QklORCAxMCBpcyBjb29sCg==',
-             'test.key:QklORCAxMCBpcyBjb29sCg==:hmac-sha1']}))
-
-    def test_keys_same_name(self):
-        """
-        Test we reject when we have multiple keys with the same name.
-        """
-        self.assertEqual("Multiple TSIG keys with name 'test.key.'",
-                         tsig_keys.check({'keys':
-                                         ['test.key:QklORCAxMCBpcyBjb29sCg==',
-                                          'test.key:b3RoZXIK']}))
-
-    def test_invalid_key(self):
-        """
-        Test we reject invalid key.
-        """
-        self.assertEqual("TSIG: Invalid TSIG key string: invalid.key",
-                         tsig_keys.check({'keys': ['invalid.key']}))
-        self.assertEqual(
-            "TSIG: Incomplete input for base64: 123",
-            tsig_keys.check({'keys': ['invalid.key:123']}))
-
-    def test_bad_format(self):
-        """
-        Test we fail on bad format. We don't really care much how here, though,
-        as this should not get in through config manager anyway.
-        """
-        self.assertNotEqual(None, tsig_keys.check({'bad_name': {}}))
-        self.assertNotEqual(None, tsig_keys.check({'keys': 'not_list'}))
-        self.assertNotEqual(None, tsig_keys.check({'keys': 42}))
-        self.assertNotEqual(None, tsig_keys.check({'keys': {}}))
-
-if __name__ == '__main__':
-        unittest.main()

+ 0 - 50
src/bin/cfgmgr/plugins/tsig_keys.py

@@ -1,50 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium.
-#
-# 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.
-
-# This is the plugin for tsig_keys configuration section. The TSIG keyring
-# lives there (eg. all the shared secrets, with some exceptions where there
-# are some TSIG keys elsewhere, but these should be removed soon). We do
-# sanity checking of user configuration here, simply by trying to construct
-# all the keys here.
-
-from isc.config.module_spec import module_spec_from_file
-from isc.util.file import path_search
-from pydnspp import TSIGKey, InvalidParameter
-from bind10_config import PLUGIN_PATHS
-spec = module_spec_from_file(path_search('tsig_keys.spec', PLUGIN_PATHS))
-
-def check(config):
-    # Check the data layout first
-    errors=[]
-    if not spec.validate_config(False, config, errors):
-        return ' '.join(errors)
-    # Get the list of keys, if any
-    keys = config.get('keys', [])
-    # Run through them, check they can be constructed and there are no
-    # duplicates
-    keyNames = set()
-    for key in keys:
-        try:
-            name = str(TSIGKey(key).get_key_name())
-        except InvalidParameter as e:
-            return "TSIG: " + str(e)
-        if name in keyNames:
-            return "Multiple TSIG keys with name '" + name + "'"
-        keyNames.add(name)
-    # No error found, so let's assume it's OK
-    return None
-
-def load():
-    return (spec, check)

+ 0 - 21
src/bin/cfgmgr/plugins/tsig_keys.spec

@@ -1,21 +0,0 @@
-{
-    "module_spec": {
-        "module_name": "tsig_keys",
-        "module_description": "The TSIG keyring is stored here",
-        "config_data": [
-            {
-                "item_name": "keys",
-                "item_type": "list",
-                "item_optional": false,
-                "item_default": [],
-                "list_item_spec": {
-                    "item_name": "key",
-                    "item_type": "string",
-                    "item_optional": false,
-                    "item_default": ""
-                }
-            }
-        ],
-        "commands": []
-    }
-}

+ 0 - 1
src/bin/cfgmgr/tests/.gitignore

@@ -1 +0,0 @@
-/b10-cfgmgr_test.py

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 33
src/bin/cfgmgr/tests/Makefile.am


+ 0 - 215
src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in

@@ -1,215 +0,0 @@
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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 the configuration manager run script
-#
-
-import unittest
-import os
-import sys
-import bind10_config
-from isc.testutils.parse_args import OptsError, TestOptParser
-
-class MyConfigManager:
-    def __init__(self, path, filename, session=None, rename_config_file=False):
-        self._path = path
-        self.read_config_called = False
-        self.notify_b10_init_called = False
-        self.run_called = False
-        self.write_config_called = False
-        self.rename_config_called = False
-        self.running = True
-        self.virtual_modules = []
-
-    def read_config(self):
-        self.read_config_called = True
-
-    def notify_b10_init(self):
-        self.notify_b10_init_called = True
-
-    def run(self):
-        self.run_called = True
-
-    def write_config(self):
-        self.write_config_called = True
-
-    def rename_config_file(self, ofile, nfile):
-        self.rename_config_called = True
-
-    def set_virtual_module(self, spec, function):
-        self.virtual_modules.append((spec, function))
-
-class TestPlugins(unittest.TestCase):
-    def test_load_plugins(self):
-        """Test we can successfully find and load the mock plugin."""
-        # Let it load the plugin
-        b = __import__("b10-cfgmgr")
-        # The parameters aren't important for this test
-        cm = MyConfigManager(None, None)
-        b.load_plugins(os.environ['TESTDATA_PATH'] + os.sep + 'plugins', cm)
-        # Check exactly one plugin was loaded and the right data were fed into
-        # the cm
-        self.assertEqual(len(cm.virtual_modules), 1)
-        (spec, check) = cm.virtual_modules[0]
-        self.assertEqual(spec.get_module_name(), "mock_config_plugin")
-        self.assertEqual(check(None), "Mock config plugin")
-
-class TestConfigManagerStartup(unittest.TestCase):
-    def test_cfgmgr(self):
-        # some creative module use;
-        # b10-cfgmgr has a hyphen, so we use __import__
-        # this also gives us the chance to override the imported
-        # module ConfigManager in it.
-        b = __import__("b10-cfgmgr")
-        orig_load = b.load_plugins
-        b.PLUGIN_PATHS = ["/plugin/path"]
-        self.loaded_plugins = False
-        def load_plugins(path, cm):
-            # Check it's called with proper arguments
-            self.assertEqual(path, "/plugin/path")
-            self.assertTrue(isinstance(cm, MyConfigManager))
-            self.loaded_plugins = True
-        b.load_plugins = load_plugins
-        b.ConfigManager = MyConfigManager
-
-        b.main()
-        b.load_plugins = orig_load
-
-        self.assertTrue(b.cm.read_config_called)
-        self.assertTrue(b.cm.notify_b10_init_called)
-        self.assertTrue(b.cm.run_called)
-        self.assertTrue(self.loaded_plugins)
-        # if there are no changes, config is not written
-        self.assertFalse(b.cm.write_config_called)
-        self.assertFalse(b.cm.rename_config_called)
-
-        self.assertTrue(b.cm.running)
-        b.signal_handler(None, None)
-        self.assertFalse(b.cm.running)
-
-        # TODO: take value from the 'global config module'
-        # (and rename the .in away from this file again)
-        data_path = "@localstatedir@/@PACKAGE@".replace("${prefix}", "@prefix@")
-        self.assertEqual(data_path, b.DATA_PATH)
-
-        # remove the 'module' again, or later tests may fail
-        # (if it is already present it won't be loaded again)
-        sys.modules.pop("b10-cfgmgr")
-
-    def test_cfgmgr_from_source(self):
-        tmp_env_var = "/just/some/dir"
-        env_var = None
-        if "B10_FROM_SOURCE" in os.environ:
-            env_var = os.environ["B10_FROM_SOURCE"]
-
-        os.environ["B10_FROM_SOURCE"] = tmp_env_var
-        bind10_config.reload()
-        b = __import__("b10-cfgmgr", globals(), locals())
-        b.PLUGIN_PATH = [] # It's enough to test plugins in one test
-        b.ConfigManager = MyConfigManager
-        self.assertEqual(tmp_env_var, b.DATA_PATH)
-
-        if env_var != None:
-            os.environ["B10_FROM_SOURCE"] = env_var
-        bind10_config.reload()
-
-        sys.modules.pop("b10-cfgmgr")
-
-class TestParseArgs(unittest.TestCase):
-    """
-    Test for the parsing of command line arguments. We provide a different
-    array to parse instead.
-    """
-
-    def test_defaults(self):
-        """
-        Test the default values when no options are provided.
-        """
-        # Pass it empty array, not our arguments
-        b = __import__("b10-cfgmgr")
-        parsed = b.parse_options([], TestOptParser)
-        self.assertEqual(None, parsed.data_path)
-        self.assertEqual(None, parsed.config_file)
-
-    def test_wrong_args(self):
-        """
-        Test it fails when we pass invalid option.
-        """
-        b = __import__("b10-cfgmgr")
-        self.assertRaises(OptsError, b.parse_options, ['--wrong-option'],
-                          TestOptParser)
-
-    def test_not_arg(self):
-        """
-        Test it fails when there's an argument that's not option
-        (eg. without -- at the beginning).
-        """
-        b = __import__("b10-cfgmgr")
-        self.assertRaises(OptsError, b.parse_options, ['not-option'],
-                          TestOptParser)
-
-    def test_datapath(self):
-        """
-        Test overwriting the data path.
-        """
-        b = __import__("b10-cfgmgr")
-        parsed = b.parse_options(['--data-path=/path'], TestOptParser)
-        self.assertEqual('/path', parsed.data_path)
-        self.assertEqual(None, parsed.config_file)
-        parsed = b.parse_options(['-p', '/path'], TestOptParser)
-        self.assertEqual('/path', parsed.data_path)
-        self.assertEqual(None, parsed.config_file)
-        self.assertRaises(OptsError, b.parse_options, ['-p'], TestOptParser)
-        self.assertRaises(OptsError, b.parse_options, ['--data-path'],
-                          TestOptParser)
-
-    def test_db_filename(self):
-        """
-        Test setting the configuration database file.
-        """
-        b = __import__("b10-cfgmgr")
-        parsed = b.parse_options(['--config-filename=filename'],
-                                 TestOptParser)
-        self.assertEqual(None, parsed.data_path)
-        self.assertEqual("filename", parsed.config_file)
-        parsed = b.parse_options(['-c', 'filename'], TestOptParser)
-        self.assertEqual(None, parsed.data_path)
-        self.assertEqual("filename", parsed.config_file)
-        self.assertRaises(OptsError, b.parse_options, ['-c'], TestOptParser)
-        self.assertRaises(OptsError, b.parse_options, ['--config-filename'],
-                          TestOptParser)
-
-    def test_determine_path_and_file(self):
-        b = __import__("b10-cfgmgr")
-        self.assertEqual((b.DATA_PATH, b.DEFAULT_CONFIG_FILE),
-                         b.determine_path_and_file(None, None))
-        self.assertEqual(("/foo", b.DEFAULT_CONFIG_FILE),
-                         b.determine_path_and_file("/foo", None))
-        self.assertEqual((os.getcwd(), "file.config"),
-                         b.determine_path_and_file(None, "file.config"))
-        self.assertEqual(("/foo", "bar"),
-                         b.determine_path_and_file("/foo", "bar"))
-
-    def test_clear_config(self):
-        b = __import__("b10-cfgmgr")
-        parsed = b.parse_options([], TestOptParser)
-        self.assertFalse(parsed.clear_config)
-        parsed = b.parse_options(['--clear-config'], TestOptParser)
-        self.assertTrue(parsed.clear_config)
-
-if __name__ == '__main__':
-    unittest.main()
-

+ 0 - 34
src/bin/cfgmgr/tests/testdata/plugins/testplugin.py

@@ -1,34 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium.
-#
-# 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.
-
-# A test plugin. It does mostly nothing, just provides a function we can
-# recognize from the test. However, it looks like a real plugin, with the
-# (almost) correct interface, even when it's not used.
-
-class MockSpec:
-    """Mock spec, contains no data, it can only provide it's name.
-       It'll not really be used for anything."""
-    def get_module_name(self):
-        return "mock_config_plugin"
-
-def mock_check_config(config):
-    """Mock function to check config. Does nothing, only returns
-       an "error" string to indicate it's this one."""
-    return "Mock config plugin"
-
-def load():
-    """When a plugin is loaded, this is called to provide the spec and
-       checking function."""
-    return (MockSpec(), mock_check_config)

+ 0 - 10
src/bin/cmdctl/.gitignore

@@ -1,10 +0,0 @@
-/b10-certgen
-/b10-certgen.1
-/b10-cmdctl
-/b10-cmdctl.8
-/cmdctl-certfile.pem
-/cmdctl-keyfile.pem
-/cmdctl.py
-/cmdctl.spec
-/cmdctl.spec.pre
-/run_b10-cmdctl.sh

+ 0 - 97
src/bin/cmdctl/Makefile.am

@@ -1,97 +0,0 @@
-SUBDIRS = . tests
-
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-
-pkglibexec_SCRIPTS = b10-cmdctl
-
-bin_PROGRAMS = b10-certgen
-
-nodist_pylogmessage_PYTHON = $(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.py
-pylogmessagedir = $(pyexecdir)/isc/log_messages/
-
-b10_cmdctldir = $(pkgdatadir)
-
-CERTFILES = cmdctl-keyfile.pem cmdctl-certfile.pem
-
-b10_cmdctl_DATA = cmdctl.spec
-
-CLEANFILES= b10-cmdctl cmdctl.pyc cmdctl.spec
-CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.py
-CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.pyc
-
-man_MANS = b10-cmdctl.8 b10-certgen.1
-DISTCLEANFILES = $(man_MANS) cmdctl-certfile.pem cmdctl-keyfile.pem
-EXTRA_DIST  = $(man_MANS) b10-certgen.xml b10-cmdctl.xml cmdctl_messages.mes
-EXTRA_DIST += cmdctl-accounts.csv
-
-if GENERATE_DOCS
-
-b10-cmdctl.8: b10-cmdctl.xml
-	@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-cmdctl.xml
-
-b10-certgen.1: b10-certgen.xml
-	@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-certgen.xml
-
-else
-
-$(man_MANS):
-	@echo Man generation disabled.  Creating dummy $@.  Configure with --enable-generate-docs to enable it.
-	@echo Man generation disabled.  Remove this file, configure with --enable-generate-docs, and rebuild BIND 10 > $@
-
-endif
-
-cmdctl.spec: cmdctl.spec.pre
-	$(SED) -e "s|@@SYSCONFDIR@@|$(sysconfdir)|" cmdctl.spec.pre >$@
-
-$(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.py : cmdctl_messages.mes
-	$(top_builddir)/src/lib/log/compiler/message \
-	-d $(PYTHON_LOGMSGPKG_DIR)/work -p $(srcdir)/cmdctl_messages.mes
-
-# this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
-b10-cmdctl: cmdctl.py $(PYTHON_LOGMSGPKG_DIR)/work/cmdctl_messages.py $(CERTFILES)
-	$(SED) "s|@@PYTHONPATH@@|@pyexecdir@|" cmdctl.py >$@
-	chmod a+x $@
-
-if HAVE_BOTAN
-b10_certgen_SOURCES = botan-certgen.cc
-EXTRA_DIST += openssl-certgen.cc
-endif
-if HAVE_OPENSSL
-b10_certgen_SOURCES = openssl-certgen.cc
-EXTRA_DIST += botan-certgen.cc
-endif
-b10_certgen_CXXFLAGS = $(CRYPTO_CFLAGS) $(CRYPTO_INCLUDES)
-b10_certgen_LDFLAGS = $(CRYPTO_LIBS)
-
-# Generate the initial certificates immediately
-cmdctl-keyfile.pem: b10-certgen
-	./b10-certgen -q -w
-
-# This is a hack, as b10-certgen creates both cmdctl-keyfile.pem and
-# cmdctl-certfile.pem, and in a parallel make, making these targets
-# simultaneously may result in corrupted files. With GNU make, there is
-# a non-portable way of working around this with pattern rules, but we
-# adopt this hack instead. The downside is that cmdctl-certfile.pem will
-# not be re-generated if cmdctl-keyfile.pem exists and is older. See
-# Trac ticket #2962.
-cmdctl-certfile.pem: cmdctl-keyfile.pem
-	touch $(builddir)/cmdctl-keyfile.pem
-
-if INSTALL_CONFIGURATIONS
-
-# Below we intentionally use ${INSTALL} -m 640 instead of $(INSTALL_DATA)
-# because these file will contain sensitive information.
-install-data-local:
-	$(mkinstalldirs) $(DESTDIR)/@sysconfdir@/@PACKAGE@
-	for f in $(CERTFILES) ; do	\
-	  if test ! -f $(DESTDIR)$(sysconfdir)/@PACKAGE@/$$f; then	\
-	    ${INSTALL} -m 640 $$f $(DESTDIR)$(sysconfdir)/@PACKAGE@/ ;	\
-	  fi ;	\
-	done
-
-endif
-
-CLEANDIRS = __pycache__
-
-clean-local:
-	rm -rf $(CLEANDIRS)

+ 0 - 22
src/bin/cmdctl/README

@@ -1,22 +0,0 @@
-When b10-cmdctrl runs, user should provide one certificate and create one account for bindctl. 
-
-
-1. Get a certificate
-
-b10-cmdctrl is a https server, so a certificate should be acquired for the SSL-encrypted connection services it provides.
-There are many ways of acquiring appropriate cetificates, such as buying one from a certification authority. Another common practice is to generate a self-signed certificate. The simplest way to do this is with the OpenSSL package, using something like the following:
-      
-   openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem
-   
-   copy the content from the generated cert.pem. to create_your_cert.pem.   
-
-2. Generate one account for bindctl or other web client tools.
-
-    run command:
-    python \parkinglot\tools\usr_mgr\usr_mgr.py
-
-    The account information is saved in passwd.csv
-
-
-
-

+ 0 - 7
src/bin/cmdctl/TODO

@@ -1,7 +0,0 @@
-. Add return code for RESTful API document of b10-cmdctl.
-. Update man page for b10-cmdctl?
-. Add check for the content of key/certificate file
-  (when cmdctl starts or is configured by bindctl).
-. Use only one msgq/session to communicate with other modules?
-. Add more test cases, especially about the cases where CmdctlException
-  is raised

+ 0 - 217
src/bin/cmdctl/b10-certgen.xml

@@ -1,217 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	       [<!ENTITY mdash "&#8212;">]>
-<!--
- - Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
- -
- - Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
- - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- - AND FITNESS.  IN NO EVENT SHALL ISC 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.
--->
-
-<refentry>
-
-  <refentryinfo>
-    <date>November 15, 2012</date>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>b10-certgen</refentrytitle>
-    <manvolnum>1</manvolnum>
-    <refmiscinfo>BIND10</refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>b10-certgen</refname>
-    <refpurpose>X509 Certificate generation tool for use with b10-cmdctl</refpurpose>
-  </refnamediv>
-
-  <docinfo>
-    <copyright>
-      <year>2012</year>
-      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
-    </copyright>
-  </docinfo>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>b10-certgen</command>
-        <group choice="opt">
-          <arg choice="[OPTION]..."><option>-</option></arg>
-        </group>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>DESCRIPTION</title>
-    <para>The <command>b10-certgen</command> tool validates, creates, or
-      updates a self-signed X509 certificate for use in b10-cmdctl.
-    </para>
-
-    <para>
-      The connection between <command>bindctl</command> and
-      <command>b10-cmdctl</command> is done over HTTPS, and therefore
-      <command>b10-cmdctl</command> needs a certificate. Since these
-      certificates have expiry dates, they also need to be regenerated at
-      some point.
-
-      There are many tools to do so, but for ease of use, <command>
-      b10-certgen</command> can create a simple self-signed certificate.
-
-      By default, it will not create anything, but it will merely check an
-      existing certificate (if not specified, cmdctl-certfile.pem, in the
-      current working directory). And print whether it is valid, and
-      whether it would update if the option '-w' is given.
-
-      With that option, the certificate could then be replaced by a newly
-      created one. If the certificate is still valid, it would still not
-      be overwritten (however, if it is found to be invalid, for example
-      because it has expired, it would create a new one).
-
-      A new certificate is always created if the certificate file does
-      not exist, or if creation is forced (with the -f option).
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>ARGUMENTS</title>
-
-    <para>The arguments are as follows:</para>
-
-    <variablelist>
-
-      <varlistentry>
-        <term>
-          <option>-c <replaceable>file</replaceable></option>,
-          <option>--certfile=<replaceable>file</replaceable></option>
-        </term>
-        <listitem>
-          <para>
-            File to read the certificate from, or write the certificate to.
-            If <option>-w</option> and <option>-c</option> are used,
-            <option>-k</option> is mandatory as well.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term>
-          <option>-f</option>,
-          <option>--force</option>
-        </term>
-        <listitem>
-          <para>
-            Force updating of certificate when <option>-w</option> is used,
-            even if the existing certificate is still valid.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term>
-          <option>-h</option>,
-          <option>--help</option>
-        </term>
-        <listitem>
-          <para>
-            Print the command line arguments and exit.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term>
-          <option>-k <replaceable>file</replaceable></option>,
-          <option>--keyfile=<replaceable>file</replaceable></option>
-        </term>
-        <listitem>
-          <para>
-            File to write the private key to. This option is only valid when <option>-w</option> is used, and if this option is used, <option>-c</option> is mandatory as well.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term>
-          <option>-w</option>,
-          <option>--write</option>
-        </term>
-        <listitem>
-          <para>
-            Check the given certificate file. If it does not exist, a new
-            private key and certificate are created. If it does exist, the
-            certificate is validated. If it is not valid (for instance
-            because it has expired), it is overwritten with a newly created
-            certificate. If it is valid, nothing happens (use
-            <option>-f</option> to force an update in that case).
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term>
-          <option>-q</option>,
-          <option>--quiet</option>
-        </term>
-        <listitem>
-          <para>
-            Don't print informational messages (only command-line errors are
-            printed). Useful in scripts when only the return code is needed.
-          </para>
-        </listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>bindctl</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citetitle>BIND 10 Guide</citetitle>.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>HISTORY</title>
-    <para>
-      The <command>b10-certgen</command> tool was first implemented
-      in November 2012 for the ISC BIND 10 project.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>EXAMPLE</title>
-    <para>
-      To update an expired certificate in BIND 10 that has been installed to
-      /usr/local:
-      <screen>
-$> cd /usr/local/etc/bind10/
-
-$> b10-certgen
-cmdctl-certfile.pem failed to verify: certificate has expired
-Running with -w would overwrite the certificate
-
-$> b10-certgen --write
-cmdctl-certfile.pem failed to verify: certificate has expired
-Creating key file cmdctl-keyfile.pem
-Creating certificate file cmdctl-certfile.pem
-
-$> b10-certgen --write
-cmdctl-certfile.pem is valid
-Not creating a new certificate (use -f to force)
-      </screen>
-    </para>
-  </refsect1>
-</refentry><!--
- - Local variables:
- - mode: sgml
- - End:
--->

+ 0 - 232
src/bin/cmdctl/b10-cmdctl.xml

@@ -1,232 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	       [<!ENTITY mdash "&#8212;">]>
-<!--
- - Copyright (C) 2010-2012  Internet Systems Consortium, Inc. ("ISC")
- -
- - Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
- - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- - AND FITNESS.  IN NO EVENT SHALL ISC 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.
--->
-
-<refentry>
-
-  <refentryinfo>
-    <date>February 28, 2012</date>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>b10-cmdctl</refentrytitle>
-    <manvolnum>8</manvolnum>
-    <refmiscinfo>BIND10</refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>b10-cmdctl</refname>
-    <refpurpose>BIND 10 remote control daemon</refpurpose>
-<!-- TODO: is that okay? -->
-  </refnamediv>
-
-  <docinfo>
-    <copyright>
-      <year>2010-2012</year>
-      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
-    </copyright>
-  </docinfo>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>b10-cmdctl</command>
-
-      <arg><option>-a <replaceable>string</replaceable></option></arg>
-      <arg><option>-h</option></arg>
-      <arg><option>-i <replaceable>number</replaceable></option></arg>
-      <arg><option>-p <replaceable>number</replaceable></option></arg>
-      <arg><option>-v</option></arg>
-      <arg><option>--address <replaceable>string</replaceable></option></arg>
-      <arg><option>--help</option></arg>
-      <arg><option>--idle-timeout <replaceable>number</replaceable></option></arg>
-      <arg><option>--port <replaceable>number</replaceable></option></arg>
-      <arg><option>--verbose</option></arg>
-      <arg><option>--version</option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>DESCRIPTION</title>
-    <para>The <command>b10-cmdctl</command> daemon provides an entry
-      for commands sent to the BIND 10 services.
-      For example, the <command>bindctl</command> user interface
-      communicates via <command>b10-cmdctl</command>.
-    </para>
-
-    <para>
-      It is a lightweight HTTPS server with HTTP Digest Authentication
-      (username and password validation).
-      It offers a RESTful style interface.
-<!-- TODO: document the RESTful APIs -->
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>OPTIONS</title>
-
-    <para>The arguments are as follows:</para>
-
-    <variablelist>
-
-      <varlistentry>
-        <term><option>-a <replaceable>string</replaceable></option>,
-          <option>--address <replaceable>string</replaceable></option></term>
-        <listitem><para>
-          The IP address that <command>b10-cmdctl</command> will listen on.
-          The default is 127.0.0.1.</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-h</option>,
-          <option>--help</option></term>
-        <listitem><para>
-          Display command usage.</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-i <replaceable>number</replaceable></option>,
-          <option>--idle-timeout <replaceable>number</replaceable></option></term>
-        <listitem><para>
-          The socket idle timeout for the HTTPS connection in seconds.
-          The default is 1200 seconds.</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-p <replaceable>number</replaceable></option>,
-          <option>--port <replaceable>number</replaceable></option></term>
-        <listitem><para>
-          The port number <command>b10-cmdctl</command> will listen on.
-          The default is 8080.</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-v</option></term>
-        <term><option>--verbose</option></term>
-        <listitem><para>
-          Enable verbose mode.</para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>
-          <option>--version</option></term>
-        <listitem><para>
-          Display the version number and exit.</para>
-        </listitem>
-      </varlistentry>
-    </variablelist>
-
-  </refsect1>
-
-  <refsect1>
-    <title>CONFIGURATION AND COMMANDS</title>
-    <para>
-      The configurable settings are:
-    </para>
-
-    <para>
-      <varname>accounts_file</varname> defines the path to the
-      user accounts database.
-      The default is
-      <filename>/usr/local/etc/bind10/cmdctl-accounts.csv</filename>.
-    </para>
-
-    <para>
-      <varname>cert_file</varname> defines the path to the
-      PEM certificate file.
-      The default is
-      <filename>/usr/local/etc/bind10/cmdctl-certfile.pem</filename>.
-    </para>
-
-    <para>
-      <varname>key_file</varname> defines the path to the PEM private key
-      file.
-      The default is
-      <filename>/usr/local/etc/bind10/cmdctl-keyfile.pem</filename>.
-    </para>
-
-<!-- TODO: formating -->
-    <para>
-      The configuration command is:
-    </para>
-
-    <para>
-      <command>shutdown</command> exits <command>b10-cmdctl</command>.
-      This has an optional <varname>pid</varname> argument to
-      select the process ID to stop.
-      (Note that the b10-init process may restart this service
-      if configured.)
-    </para>
-
-  </refsect1>
-
-  <refsect1>
-    <title>FILES</title>
-<!-- TODO: replace /usr/local -->
-<!-- TODO: permissions -->
-<!-- TODO: what about multiple accounts? -->
-<!-- TODO: shouldn't the password file name say cmdctl in it? -->
-    <para><filename>/usr/local/etc/bind10/cmdctl-accounts.csv</filename>
-      &mdash; account database containing the name, hashed password,
-      and the salt.
-    </para>
-<!-- TODO: replace /usr/local -->
-<!-- TODO: permissions -->
-<!-- TODO: shouldn't have both in same file, will be configurable -->
-    <para><filename>/usr/local/etc/bind10/cmdctl-keyfile.pem</filename>
-      &mdash; contains the Private key.
-    </para>
-    <para><filename>/usr/local/etc/bind10/cmdctl-certfile.pem</filename>
-      &mdash; contains the Certificate.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>b10-cfgmgr</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>bindctl</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>AUTHORS</title>
-    <para>
-      The <command>b10-cmdctl</command> daemon was initially designed
-      and coded by Zhang Likun of CNNIC.
-    </para>
-  </refsect1>
-</refentry><!--
- - Local variables:
- - mode: sgml
- - End:
--->

+ 0 - 429
src/bin/cmdctl/botan-certgen.cc

@@ -1,429 +0,0 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC 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.
-
-#include <botan/botan.h>
-#include <botan/x509self.h>
-#include <botan/x509stor.h>
-#include <botan/rsa.h>
-#include <botan/dsa.h>
-#include <botan/data_src.h>
-using namespace Botan;
-
-#include <iostream>
-#include <fstream>
-#include <memory>
-#include <getopt.h>
-
-// For cleaner 'does not exist or is not readable' output than
-// botan provides
-#include <unistd.h>
-#include <errno.h>
-
-// This is a simple tool that creates a self-signed PEM certificate
-// for use with BIND 10. It creates a simple certificate for initial
-// setup. Currently, all values are hardcoded defaults. For future
-// versions, we may want to add more options for administrators.
-
-// It will create a PEM file containing a certificate with the following
-// values:
-// common name: localhost
-// organization: BIND10
-// country code: US
-
-// Additional error return codes; these are specifically
-// chosen to be distinct from validation error codes as
-// provided by Botan. Their main use is to distinguish
-// error cases in the unit tests.
-const int DECODING_ERROR = 100;
-const int BAD_OPTIONS = 101;
-const int READ_ERROR = 102;
-const int WRITE_ERROR = 103;
-const int UNKNOWN_ERROR = 104;
-const int NO_SUCH_FILE = 105;
-const int FILE_PERMISSION_ERROR = 106;
-
-void
-usage() {
-    std::cout << "Usage: b10-certgen [OPTION]..." << std::endl;
-    std::cout << "Validate, create, or update a self-signed certificate for "
-                 "use with b10-cmdctl" << std::endl;
-    std::cout << "" << std::endl;
-    std::cout << "Options:" << std::endl;
-    std::cout << "-c, --certfile=FILE\t\tfile to read or store the certificate"
-              << std::endl;
-    std::cout << "-f, --force\t\t\toverwrite existing certificate even if it"
-              << std::endl <<"\t\t\t\tis valid" << std::endl;
-    std::cout << "-h, --help\t\t\tshow this help" << std::endl;
-    std::cout << "-k, --keyfile=FILE\t\tfile to store the generated private key"
-              << std::endl;
-    std::cout << "-w, --write\t\t\tcreate a new certificate if the given file"
-              << std::endl << "\t\t\t\tdoes not exist, or if is is not valid"
-              << std::endl;
-    std::cout << "-q, --quiet\t\t\tprint no output when creating or validating"
-              << std::endl;
-}
-
-/// \brief Returns true if the given file exists
-///
-/// \param filename The file to check
-/// \return true if file exists
-bool
-fileExists(const std::string& filename) {
-    return (access(filename.c_str(), F_OK) == 0);
-}
-
-/// \brief Returns true if the given file exists and is readable
-///
-/// \param filename The file to check
-/// \return true if file exists and is readable
-bool
-fileIsReadable(const std::string& filename) {
-    return (access(filename.c_str(), R_OK) == 0);
-}
-
-/// \brief Returns true if the given file exists and is writable
-///
-/// \param filename The file to check
-/// \return true if file exists and is writable
-bool
-fileIsWritable(const std::string& filename) {
-    return (access(filename.c_str(), W_OK) == 0);
-}
-
-/// \brief Helper function for readable error output;
-///
-/// Returns string representation of X509 result code
-/// This does not appear to be provided by Botan itself
-///
-/// \param code An \c X509_Code instance
-/// \return A human-readable c string
-const char*
-X509CodeToString(const X509_Code& code) {
-    // note that this list provides more than we would
-    // need in this context, it is just the enum from
-    // the source code of Botan.
-    switch (code) {
-    case VERIFIED:
-        return ("verified");
-    case UNKNOWN_X509_ERROR:
-        return ("unknown x509 error");
-    case CANNOT_ESTABLISH_TRUST:
-        return ("cannot establish trust");
-    case CERT_CHAIN_TOO_LONG:
-        return ("certificate chain too long");
-    case SIGNATURE_ERROR:
-        return ("signature error");
-    case POLICY_ERROR:
-        return ("policy error");
-    case INVALID_USAGE:
-        return ("invalid usage");
-    case CERT_FORMAT_ERROR:
-        return ("certificate format error");
-    case CERT_ISSUER_NOT_FOUND:
-        return ("certificate issuer not found");
-    case CERT_NOT_YET_VALID:
-        return ("certificate not yet valid");
-    case CERT_HAS_EXPIRED:
-        return ("certificate has expired");
-    case CERT_IS_REVOKED:
-        return ("certificate has been revoked");
-    case CRL_FORMAT_ERROR:
-        return ("crl format error");
-    case CRL_NOT_YET_VALID:
-        return ("crl not yet valid");
-    case CRL_HAS_EXPIRED:
-        return ("crl has expired");
-    case CA_CERT_CANNOT_SIGN:
-        return ("CA cert cannot sign");
-    case CA_CERT_NOT_FOR_CERT_ISSUER:
-        return ("CA certificate not for certificate issuer");
-    case CA_CERT_NOT_FOR_CRL_ISSUER:
-        return ("CA certificate not for crl issuer");
-    default:
-        return ("Unknown X509 code");
-    }
-}
-
-class CertificateTool {
-public:
-    CertificateTool(bool quiet) : quiet_(quiet) {}
-
-    int
-    createKeyAndCertificate(const std::string& key_file_name,
-                            const std::string& cert_file_name) {
-        try {
-            AutoSeeded_RNG rng;
-
-            // Create and store a private key
-            print("Creating key file " + key_file_name);
-            RSA_PrivateKey key(rng, 2048);
-            std::ofstream key_file(key_file_name.c_str());
-            if (!key_file.good()) {
-                print(std::string("Error writing to ") + key_file_name +
-                      ": " + std::strerror(errno));
-                return (WRITE_ERROR);
-            }
-            key_file << PKCS8::PEM_encode(key, rng, "");
-            if (!key_file.good()) {
-                print(std::string("Error writing to ") + key_file_name +
-                      ": " + std::strerror(errno));
-                return (WRITE_ERROR);
-            }
-            key_file.close();
-
-            // Certificate options, currently hardcoded.
-            // For a future version we may want to make these
-            // settable.
-            X509_Cert_Options opts;
-            opts.common_name = "localhost";
-            opts.organization = "UNKNOWN";
-            opts.country = "XX";
-
-            opts.CA_key();
-
-            print("Creating certificate file " + cert_file_name);
-
-            // The exact call changed after 1.8, adding the
-            // hash function option
-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,0)
-            X509_Certificate cert =
-            X509::create_self_signed_cert(opts, key, "SHA-256", rng);
-#else
-            X509_Certificate cert =
-            X509::create_self_signed_cert(opts, key, rng);
-#endif
-
-            std::ofstream cert_file(cert_file_name.c_str());
-            if (!cert_file.good()) {
-                print(std::string("Error writing to ") + cert_file_name +
-                      ": " + std::strerror(errno));
-                return (WRITE_ERROR);
-            }
-            cert_file << cert.PEM_encode();
-            if (!cert_file.good()) {
-                print(std::string("Error writing to ") + cert_file_name +
-                      ": " + std::strerror(errno));
-                return (WRITE_ERROR);
-            }
-            cert_file.close();
-        } catch(std::exception& e) {
-            std::cout << "Error creating key or certificate: " << e.what()
-                      << std::endl;
-            return (UNKNOWN_ERROR);
-        }
-        return (0);
-    }
-
-    int
-    validateCertificate(const std::string& certfile) {
-        // Since we are dealing with a self-signed certificate here, we
-        // also use the certificate to check itself; i.e. we add it
-        // as a trusted certificate, then validate the certificate itself.
-        //const X509_Certificate cert(certfile);
-        try {
-            X509_Store store;
-            DataSource_Stream in(certfile);
-            store.add_trusted_certs(in);
-
-            const X509_Code result = store.validate_cert(certfile);
-
-            if (result == VERIFIED) {
-                print(certfile + " is valid");
-            } else {
-                print(certfile + " failed to verify: " +
-                      X509CodeToString(result));
-            }
-            return (result);
-        } catch (const Botan::Decoding_Error& bde) {
-            print(certfile + " failed to verify: " + bde.what());
-            return (DECODING_ERROR);
-        } catch (const Botan::Stream_IO_Error& bsie) {
-            print(certfile + " not read: " + bsie.what());
-            return (READ_ERROR);
-        }
-    }
-
-    /// \brief Runs the tool
-    ///
-    /// \param create_cert  Create certificate if true, validate if false.
-    ///                     Does nothing if certificate exists and is valid.
-    /// \param force_create Create new certificate even if it is valid.
-    /// \param certfile     Certificate file to read to or write from.
-    /// \param keyfile      Key file to write if certificate is created.
-    ///                     Ignored if create_cert is false
-    /// \return zero on success, non-zero on failure
-    int
-    run(bool create_cert, bool force_create, const std::string& certfile,
-        const std::string& keyfile)
-    {
-        if (create_cert) {
-            // Unless force is given, only create it if the current
-            // one is not OK
-
-            // First do some basic permission checks; both files
-            // should either not exist, or be both readable
-            // and writable
-            // The checks are done one by one so all errors can
-            // be enumerated in one go
-            if (fileExists(certfile)) {
-                if (!fileIsReadable(certfile)) {
-                    print(certfile + " not readable: " + std::strerror(errno));
-                    create_cert = false;
-                }
-                if (!fileIsWritable(certfile)) {
-                    print(certfile + " not writable: " + std::strerror(errno));
-                    create_cert = false;
-                }
-            }
-            // The key file really only needs write permissions (for
-            // b10-certgen that is)
-            if (fileExists(keyfile)) {
-                if (!fileIsWritable(keyfile)) {
-                    print(keyfile + " not writable: " + std::strerror(errno));
-                    create_cert = false;
-                }
-            }
-            if (!create_cert) {
-                print("Not creating new certificate, "
-                      "check file permissions");
-                return (FILE_PERMISSION_ERROR);
-            }
-
-            // If we reach this, we know that if they exist, we can both
-            // read and write them, so now it's up to content checking
-            // and/or force_create
-
-            if (force_create || !fileExists(certfile) ||
-                validateCertificate(certfile) != VERIFIED) {
-                return (createKeyAndCertificate(keyfile, certfile));
-            } else {
-                print("Not creating a new certificate (use -f to force)");
-            }
-        } else {
-            if (!fileExists(certfile)) {
-                print(certfile + ": " + std::strerror(errno));
-                return (NO_SUCH_FILE);
-            }
-            if (!fileIsReadable(certfile)) {
-                print(certfile + " not readable: " + std::strerror(errno));
-                return (FILE_PERMISSION_ERROR);
-            }
-            int result = validateCertificate(certfile);
-            if (result != 0) {
-                print("Running with -w would overwrite the certificate");
-            }
-            return (result);
-        }
-        return (0);
-    }
-private:
-    /// Prints the message to stdout unless quiet_ is true
-    void print(const std::string& msg) {
-        if (!quiet_) {
-            std::cout << msg << std::endl;
-        }
-    }
-
-    bool quiet_;
-};
-
-int
-main(int argc, char* argv[])
-{
-    Botan::LibraryInitializer init;
-
-    // create or check certificate
-    bool create_cert = false;
-    // force creation even if not necessary
-    bool force_create = false;
-    // don't print any output
-    bool quiet = false;
-
-    // default certificate file
-    std::string certfile("cmdctl-certfile.pem");
-    // default key file
-    std::string keyfile("cmdctl-keyfile.pem");
-
-    // whether or not the above values have been
-    // overridden (used in command line checking)
-    bool certfile_default = true;
-    bool keyfile_default = true;
-
-    // It would appear some environments insist on
-    // char* here (Sunstudio on Solaris), so we const_cast
-    // them to get rid of compiler warnings.
-    const struct option long_options[] = {
-        { const_cast<char*>("certfile"), required_argument, NULL, 'c' },
-        { const_cast<char*>("force"), no_argument, NULL, 'f' },
-        { const_cast<char*>("help"), no_argument, NULL, 'h' },
-        { const_cast<char*>("keyfile"), required_argument, NULL, 'k' },
-        { const_cast<char*>("write"), no_argument, NULL, 'w' },
-        { const_cast<char*>("quiet"), no_argument, NULL, 'q' },
-        { NULL, 0, NULL, 0 }
-    };
-
-    int opt, option_index;
-    while ((opt = getopt_long(argc, argv, "c:fhk:wq", long_options,
-                              &option_index)) != -1) {
-        switch (opt) {
-            case 'c':
-                certfile = optarg;
-                certfile_default = false;
-                break;
-            case 'f':
-                force_create = true;
-                break;
-            case 'h':
-                usage();
-                return (0);
-                break;
-            case 'k':
-                keyfile = optarg;
-                keyfile_default = false;
-                break;
-            case 'w':
-                create_cert = true;
-                break;
-            case 'q':
-                quiet = true;
-                break;
-            default:
-                // A message will have already been output about the error.
-                return (BAD_OPTIONS);
-        }
-    }
-
-    if (optind < argc) {
-        std::cout << "Error: extraneous arguments" << std::endl << std::endl;
-        usage();
-        return (BAD_OPTIONS);
-    }
-
-    // Some sanity checks on option combinations
-    if (create_cert && (certfile_default ^ keyfile_default)) {
-        std::cout << "Error: keyfile and certfile must both be specified "
-                     "if one of them is when calling b10-certgen in write "
-                     "mode." << std::endl;
-        return (BAD_OPTIONS);
-    }
-    if (!create_cert && !keyfile_default) {
-        std::cout << "Error: keyfile is not used when not in write mode"
-                  << std::endl;
-        return (BAD_OPTIONS);
-    }
-
-    // Initialize the tool and perform the appropriate action(s)
-    CertificateTool tool(quiet);
-    return (tool.run(create_cert, force_create, certfile, keyfile));
-}

+ 0 - 1
src/bin/cmdctl/cmdctl-accounts.csv

@@ -1 +0,0 @@
-root,6f0c73bd33101a5ec0294b3ca39fec90ef4717fe,"{5hV&$^(]!uV,3H>E~=f`I;,HgMl""`Eyao4^0l|Nlz|%R9Y0v)#/t'u@CzJ$U)"

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

@@ -1,718 +0,0 @@
-#!@PYTHON@
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-''' cmdctl module is the configuration entry point for all commands from bindctl
-or some other web tools client of bind10. cmdctl is pure https server which provi-
-des RESTful API. When command client connecting with cmdctl, it should first login
-with legal username and password.
-    When cmdctl starting up, it will collect command specification and
-configuration specification/data of other available modules from configmanager, then
-wait for receiving request from client, parse the request and resend the request to
-the proper module. When getting the request result from the module, send back the
-resut to client.
-'''
-
-import sys; sys.path.append ('@@PYTHONPATH@@')
-import os
-import socketserver
-import http.server
-import urllib.parse
-import json
-import re
-import ssl, socket
-import isc
-import pprint
-import csv
-import random
-import time
-import signal
-import errno
-from isc.config import ccsession
-import isc.cc.proto_defs
-import isc.util.process
-import isc.net.parse
-from optparse import OptionParser, OptionValueError
-from hashlib import sha1
-from isc.util import socketserver_mixin
-from isc.log_messages.cmdctl_messages import *
-import isc.util.traceback_handler
-
-isc.log.init("b10-cmdctl", buffer=True)
-logger = isc.log.Logger("cmdctl")
-
-# Debug level for communication with BIND10
-DBG_CMDCTL_MESSAGING = logger.DBGLVL_COMMAND
-
-try:
-    import threading
-except ImportError:
-    import dummy_threading as threading
-
-isc.util.process.rename()
-
-__version__ = 'BIND10'
-URL_PATTERN = re.compile('/([\w]+)(?:/([\w]+))?/?')
-CONFIG_DATA_URL = 'config_data'
-MODULE_SPEC_URL = 'module_spec'
-
-
-# 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
-if "B10_FROM_BUILD" in os.environ:
-    SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/cmdctl"
-else:
-    PREFIX = "@prefix@"
-    DATAROOTDIR = "@datarootdir@"
-    SPECFILE_PATH = "@datadir@/@PACKAGE@".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
-SPECFILE_LOCATION = SPECFILE_PATH + os.sep + "cmdctl.spec"
-
-class CmdctlException(Exception):
-    pass
-
-def check_file(file_name):
-    # TODO: Check contents of certificate file
-    if not os.path.exists(file_name):
-        raise CmdctlException("'%s' does not exist" % file_name)
-
-    if not os.path.isfile(file_name):
-        raise CmdctlException("'%s' is not a file" % file_name)
-
-    if not os.access(file_name, os.R_OK):
-        raise CmdctlException("'%s' is not readable" % file_name)
-
-
-class SecureHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
-    '''https connection request handler.
-    Currently only GET and POST are supported.  '''
-    def __init__(self, request, client_address, server):
-        http.server.BaseHTTPRequestHandler.__init__(self, request,
-                                                    client_address, server)
-        self.session_id = None
-
-    def do_GET(self):
-        '''The client should send its session id in header with
-        the name 'cookie'
-        '''
-        self.session_id = self.headers.get('cookie')
-        rcode, reply = http.client.OK, []
-        if self._is_session_valid():
-            if self._is_user_logged_in():
-                rcode, reply = self._handle_get_request()
-            else:
-                rcode, reply = http.client.UNAUTHORIZED, ["please login"]
-        else:
-            rcode = http.client.BAD_REQUEST
-
-        self.send_response(rcode)
-        self.end_headers()
-        self.wfile.write(json.dumps(reply).encode())
-
-    def _handle_get_request(self):
-        '''Currently only support the following three url GET request '''
-        id, module = self._parse_request_path()
-        return self.server.get_reply_data_for_GET(id, module)
-
-    def _is_session_valid(self):
-        return self.session_id is not None
-
-    def _is_user_logged_in(self):
-        login_time = self.server.user_sessions.get(self.session_id)
-        if not login_time:
-            return False
-
-        idle_time = time.time() - login_time
-        if idle_time > self.server.idle_timeout:
-            return False
-        # Update idle time
-        self.server.user_sessions[self.session_id] = time.time()
-        return True
-
-    def _parse_request_path(self):
-        '''Parse the url, the legal url should like /ldh or /ldh/ldh '''
-        groups = URL_PATTERN.match(self.path)
-        if not groups:
-            return (None, None)
-        else:
-            return (groups.group(1), groups.group(2))
-
-    def do_POST(self):
-        '''Process POST request. '''
-        '''Process user login and send command to proper module
-        The client should send its session id in header with
-        the name 'cookie'
-        '''
-        self.session_id = self.headers.get('cookie')
-        rcode, reply = http.client.OK, []
-        if self._is_session_valid():
-            if self.path == '/login':
-                rcode, reply = self._handle_login()
-            elif self._is_user_logged_in():
-                rcode, reply = self._handle_post_request()
-            else:
-                rcode, reply = http.client.UNAUTHORIZED, ["please login"]
-        else:
-            rcode, reply = http.client.BAD_REQUEST, ["session isn't valid"]
-
-        self.send_response(rcode)
-        self.end_headers()
-        self.wfile.write(json.dumps(reply).encode())
-
-    def _handle_login(self):
-        if self._is_user_logged_in():
-            return http.client.OK, ["user has already login"]
-        is_user_valid, error_info = self._check_user_name_and_pwd()
-        if is_user_valid:
-            self.server.save_user_session_id(self.session_id)
-            return http.client.OK, ["login success"]
-        else:
-            return http.client.UNAUTHORIZED, error_info
-
-    def _check_user_name_and_pwd(self):
-        '''Check user name and its password '''
-        length = self.headers.get('Content-Length')
-
-        if not length:
-            return False, ["invalid username or password"]
-
-        try:
-            user_info = json.loads((self.rfile.read(int(length))).decode())
-        except:
-            return False, ["invalid username or password"]
-
-        user_name = user_info.get('username')
-        if not user_name:
-            return False, ["need user name"]
-        if not self.server.get_user_info(user_name):
-            logger.info(CMDCTL_NO_SUCH_USER, user_name)
-            return False, ["username or password error"]
-
-        user_pwd = user_info.get('password')
-        if not user_pwd:
-            return False, ["need password"]
-        local_info = self.server.get_user_info(user_name)
-        pwd_hashval = sha1((user_pwd + local_info[1]).encode())
-        if pwd_hashval.hexdigest() != local_info[0]:
-            logger.info(CMDCTL_BAD_PASSWORD, user_name)
-            return False, ["username or password error"]
-
-        return True, None
-
-
-    def _handle_post_request(self):
-        '''Handle all the post request from client. '''
-        mod, cmd = self._parse_request_path()
-        if (not mod) or (not cmd):
-            return http.client.BAD_REQUEST, ['malformed url']
-
-        param = None
-        len = self.headers.get('Content-Length')
-        if len:
-            try:
-                post_str = str(self.rfile.read(int(len)).decode())
-                param = json.loads(post_str)
-            except:
-                pass
-
-        rcode, reply = self.server.send_command_to_module(mod, cmd, param)
-        ret = http.client.OK
-        if rcode != 0:
-            ret = http.client.BAD_REQUEST
-        return ret, reply
-
-    def log_request(self, code='-', size='-'):
-        '''Rewrite the log request function, log nothing.'''
-        pass
-
-
-class CommandControl():
-    '''Get all modules' config data/specification from configmanager.
-    receive command from client and resend it to proper module.
-    '''
-    def __init__(self, httpserver, verbose = False):
-        ''' httpserver: the http server which use the object of
-        CommandControl to communicate with other modules. '''
-        self._verbose = verbose
-        self._httpserver = httpserver
-        self.__msg_handler_thread = None # set in _start_msg_handle_thread
-        self._lock = threading.Lock()
-        self._setup_session()
-        self.modules_spec = self._get_modules_specification()
-        self._config_data = self._get_config_data_from_config_manager()
-        self._serving = True
-        self._start_msg_handle_thread()
-
-    def _setup_session(self):
-        '''Setup the session for receving the commands
-        sent from other modules. There are two sessions
-        for cmdctl, one(self.module_cc) is used for receiving
-        commands sent from other modules, another one (self._cc)
-        is used to send the command from Bindctl or other tools
-        to proper modules.'''
-        self._cc = isc.cc.Session()
-        self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
-                                              self.config_handler,
-                                              self.command_handler)
-        self._module_name = self._module_cc.get_module_spec().get_module_name()
-        self._cmdctl_config_data = self._module_cc.get_full_config()
-        self._module_cc.start()
-
-    def _accounts_file_check(self, filepath):
-        ''' Check whether the accounts file is valid, each row
-        should be a list with 3 items.'''
-        csvfile = None
-        errstr = None
-        try:
-            csvfile = open(filepath)
-            reader = csv.reader(csvfile)
-            for row in reader:
-                a = (row[0], row[1], row[2])
-        except (IOError, IndexError) as e:
-            errstr = 'Invalid accounts file: ' + str(e)
-        finally:
-            if csvfile:
-                csvfile.close()
-
-        return errstr
-
-    def _config_data_check(self, new_config):
-        ''' Check whether the new config data is valid or
-        not. '''
-        errstr = None
-        for key in new_config:
-            if key == 'version':
-                continue
-            elif key in ['key_file', 'cert_file']:
-                # TODO: we only check whether the file exist, is a
-                # file, and is readable; but further check need to be done:
-                # eg. whether the private/certificate is valid.
-                path = new_config[key]
-                try:
-                    check_file(path)
-                except CmdctlException as cce:
-                    errstr = str(cce)
-            elif key == 'accounts_file':
-                errstr = self._accounts_file_check(new_config[key])
-            else:
-                errstr = 'unknown config item: ' + key
-
-            if errstr != None:
-                logger.error(CMDCTL_BAD_CONFIG_DATA, errstr);
-                return ccsession.create_answer(1, errstr)
-
-        return ccsession.create_answer(0)
-
-    def config_handler(self, new_config):
-        answer = self._config_data_check(new_config)
-        rcode, val = ccsession.parse_answer(answer)
-        if rcode != 0:
-            return answer
-
-        with self._lock:
-            for key in new_config:
-                if key in self._cmdctl_config_data:
-                    self._cmdctl_config_data[key] = new_config[key]
-        return answer
-
-    def _get_current_thread(self):
-        """A simple wrapper of returning the 'current' thread object.
-
-        This is extracted as a 'protected' method so tests can override for
-        their convenience.
-
-        """
-        return threading.currentThread()
-
-    def command_handler(self, command, args):
-        """Handle commands from other modules.
-
-        This method must not be called by any other threads than
-        __msg_handler_thread invoked at the intialization of the class;
-        otherwise it would cause critical race or dead locks.
-
-        """
-        # Check the restriction described above.
-        assert self._get_current_thread() == self.__msg_handler_thread
-
-        answer = ccsession.create_answer(0)
-        if command == ccsession.COMMAND_MODULE_SPECIFICATION_UPDATE:
-            # The 'value' of a specification update can be either
-            # a specification, or None. In the first case, simply
-            # set it. If it is None, delete the module if it is
-            # known.
-            with self._lock:
-                if args[1] is None:
-                    if args[0] in self.modules_spec:
-                        del self.modules_spec[args[0]]
-                    else:
-                        answer = ccsession.create_answer(1,
-                                                         'No such module: ' +
-                                                         args[0])
-                else:
-                    self.modules_spec[args[0]] = args[1]
-
-        elif command == ccsession.COMMAND_SHUTDOWN:
-            #When cmdctl get 'shutdown' command from b10-init,
-            #shutdown the outer httpserver.
-            self._module_cc.send_stopping()
-            self._httpserver.shutdown()
-            self._serving = False
-
-        else:
-            answer = ccsession.create_answer(1, 'unknown command: ' + command)
-
-        return answer
-
-    def _start_msg_handle_thread(self):
-        ''' Start one thread to handle received message from msgq.'''
-        td = threading.Thread(target=self._handle_msg_from_msgq)
-        td.daemon = True
-        self.__msg_handler_thread = td
-        td.start()
-
-    def _handle_msg_from_msgq(self):
-        '''Process all the received commands with module session. '''
-        while self._serving:
-            self._module_cc.check_command(False)
-
-    def _parse_command_result(self, rcode, reply):
-        '''Ignore the error reason when command rcode isn't 0, '''
-        if rcode != 0:
-            return {}
-        return reply
-
-    def _get_config_data_from_config_manager(self):
-        '''Get config data for all modules from configmanager '''
-        rcode, reply = self.send_command('ConfigManager', ccsession.COMMAND_GET_CONFIG)
-        return self._parse_command_result(rcode, reply)
-
-    def _update_config_data(self, module_name, command_name):
-        '''Get lastest config data for all modules from configmanager '''
-        if module_name == 'ConfigManager' and command_name == ccsession.COMMAND_SET_CONFIG:
-            data = self._get_config_data_from_config_manager()
-            with self._lock:
-                self._config_data = data
-
-    def get_config_data(self):
-        with self._lock:
-            data = self._config_data
-        return data
-
-    def get_modules_spec(self):
-        with self._lock:
-            spec = self.modules_spec
-        return spec
-
-    def _get_modules_specification(self):
-        '''Get all the modules' specification files. '''
-        rcode, reply = self.send_command('ConfigManager', ccsession.COMMAND_GET_MODULE_SPEC)
-        return self._parse_command_result(rcode, reply)
-
-    def send_command_with_check(self, module_name, command_name, params=None):
-        '''Before send the command to modules, check if module_name, command_name
-        parameters are legal according the spec file of the module.
-        Return rcode, dict. TODO, the rcode should be defined properly.
-        rcode = 0: dict is the correct returned value.
-        rcode > 0: dict is : { 'error' : 'error reason' }
-        '''
-        # core module ConfigManager does not have a specification file
-        if module_name == 'ConfigManager':
-            return self.send_command(module_name, command_name, params)
-
-        specs = self.get_modules_spec()
-        if module_name not in specs.keys():
-            return 1, {'error' : 'unknown module'}
-
-        spec_obj = isc.config.module_spec.ModuleSpec(specs[module_name], False)
-        errors = []
-        if not spec_obj.validate_command(command_name, params, errors):
-            return 1, {'error': errors[0]}
-
-        return self.send_command(module_name, command_name, params)
-
-    def send_command(self, module_name, command_name, params=None):
-        """Send the command from bindctl to proper module.
-
-        Note that commands sent to Cmdctl itself are also delivered via the
-        CC session.  Since this method is called from a thread handling a
-        particular HTTP session, it cannot directly call command_handler().
-
-        """
-        errstr = 'unknown error'
-        answer = None
-        logger.debug(DBG_CMDCTL_MESSAGING, CMDCTL_SEND_COMMAND,
-                     command_name, module_name)
-
-        # FIXME: Due to the fact that we use a separate session
-        # from the module one (due to threads and blocking), and
-        # because the plain cc session does not have the high-level
-        # rpc-call method, we use the low-level way and create the
-        # command ourselves.
-        msg = ccsession.create_command(command_name, params)
-        seq = self._cc.group_sendmsg(msg, module_name, want_answer=True)
-        logger.debug(DBG_CMDCTL_MESSAGING, CMDCTL_COMMAND_SENT, command_name,
-                     module_name)
-        # TODO, it may be blocked, msqg need to add a new interface waiting
-        # in timeout.
-        try:
-            answer, env = self._cc.group_recvmsg(False, seq)
-        except isc.cc.session.SessionTimeout:
-            errstr = "Module '%s' not responding" % module_name
-
-        if answer:
-            try:
-                rcode, arg = ccsession.parse_answer(answer)
-                if rcode == 0:
-                    self._update_config_data(module_name, command_name)
-                    if arg != None:
-                        return rcode, arg
-                    else:
-                        return rcode, {}
-                else:
-                    errstr = \
-                        str(answer[isc.cc.proto_defs.CC_PAYLOAD_RESULT][1])
-            except ccsession.ModuleCCSessionError as mcse:
-                errstr = str("Error in ccsession answer:") + str(mcse)
-
-        logger.error(CMDCTL_COMMAND_ERROR, command_name, module_name, errstr)
-        return 1, {'error': errstr}
-
-    def get_cmdctl_config_data(self):
-        ''' If running in source code tree, use keyfile, certificate
-        and user accounts file in source code. '''
-        if "B10_FROM_SOURCE" in os.environ:
-            sysconf_path = os.environ["B10_FROM_SOURCE"] + "/src/bin/cmdctl/"
-            accountsfile  = sysconf_path + "cmdctl-accounts.csv"
-            keyfile = sysconf_path + "cmdctl-keyfile.pem"
-            certfile = sysconf_path + "cmdctl-certfile.pem"
-            return (keyfile, certfile, accountsfile)
-
-        with self._lock:
-            keyfile = self._cmdctl_config_data.get('key_file')
-            certfile = self._cmdctl_config_data.get('cert_file')
-            accountsfile = self._cmdctl_config_data.get('accounts_file')
-
-        return (keyfile, certfile, accountsfile)
-
-class SecureHTTPServer(socketserver_mixin.NoPollMixIn,
-                       socketserver.ThreadingMixIn,
-                       http.server.HTTPServer):
-    '''Make the server address can be reused.'''
-    allow_reuse_address = True
-
-    def __init__(self, server_address, RequestHandlerClass,
-                 CommandControlClass,
-                 idle_timeout = 1200, verbose = False):
-        '''idle_timeout: the max idle time for login'''
-        socketserver_mixin.NoPollMixIn.__init__(self)
-        try:
-            http.server.HTTPServer.__init__(self, server_address, RequestHandlerClass)
-            logger.debug(DBG_CMDCTL_MESSAGING, CMDCTL_STARTED,
-                         server_address[0], server_address[1])
-        except socket.error as err:
-            if err.errno == errno.EADDRINUSE:
-                raise CmdctlException(("Error creating server, because " +\
-                                       "port %d on address %s is " +\
-                                       "already in use. Please stop " +\
-                                       "the application that uses it or " +\
-                                       "see the guide about using a " +\
-                                       "different port for b10-cmdctl.") % \
-                                      (server_address[1], \
-                                       server_address[0]))
-            else:
-                raise CmdctlException("Error creating server, because: %s" % str(err))
-
-        self.user_sessions = {}
-        self.idle_timeout = idle_timeout
-        self.cmdctl = CommandControlClass(self, verbose)
-        self._verbose = verbose
-        self._lock = threading.Lock()
-        self._user_infos = {}
-        self.__accounts_file = None
-        self.__accounts_file_mtime = 0
-
-    def _create_user_info(self, accounts_file):
-        '''Read all user's name and its' salt, hashed password
-        from accounts file.'''
-
-        # If the file does not exist, set accounts to empty, and return
-        if not os.path.exists(accounts_file):
-            self._user_infos = {}
-            self.__accounts_file = None
-            self.__accounts_file_mtime = 0
-            return
-
-        # If the filename hasn't changed, and the file itself
-        # has neither, do nothing
-        accounts_file_mtime = os.stat(accounts_file).st_mtime
-        if self.__accounts_file == accounts_file and\
-           accounts_file_mtime <= self.__accounts_file_mtime:
-            return
-
-        with self._lock:
-            self._user_infos = {}
-            csvfile = None
-            try:
-                csvfile = open(accounts_file)
-                reader = csv.reader(csvfile)
-                for row in reader:
-                    self._user_infos[row[0]] = [row[1], row[2]]
-            except (IOError, IndexError) as e:
-                logger.error(CMDCTL_USER_DATABASE_READ_ERROR,
-                             accounts_file, e)
-            finally:
-                if csvfile:
-                    csvfile.close()
-
-        self.__accounts_file = accounts_file
-        self.__accounts_file_mtime = accounts_file_mtime
-        if len(self._user_infos) == 0:
-            logger.error(CMDCTL_NO_USER_ENTRIES_READ)
-
-    def get_user_info(self, username):
-        '''Get user's salt and hashed string. If the user
-        doesn't exist, return None, or else, the list
-        [salt, hashed password] will be returned.'''
-        with self._lock:
-            info = self._user_infos.get(username)
-        return info
-
-    def save_user_session_id(self, session_id):
-        ''' Record user's id and login time. '''
-        self.user_sessions[session_id] = time.time()
-
-    def _check_key_and_cert(self, key, cert):
-        check_file(key)
-        check_file(cert);
-
-    def _wrap_socket_in_ssl_context(self, sock, key, cert):
-        try:
-            self._check_key_and_cert(key, cert)
-            ssl_sock = ssl.wrap_socket(sock,
-                                       server_side=True,
-                                       certfile=cert,
-                                       keyfile=key,
-                                       ssl_version=ssl.PROTOCOL_SSLv23)
-            # Return here (if control leaves this blocks it will raise an
-            # error)
-            return ssl_sock
-        except ssl.SSLError as err:
-            self.close_request(sock)
-            logger.error(CMDCTL_SSL_SETUP_FAILURE_USER_DENIED, err)
-            raise
-        except (CmdctlException, IOError, socket.error) as cce:
-            self.close_request(sock)
-            logger.error(CMDCTL_SSL_SETUP_FAILURE_READING_CERT, cce)
-            raise
-
-    def get_request(self):
-        '''Get client request socket and wrap it in SSL context. '''
-        key, cert, account_file = self.cmdctl.get_cmdctl_config_data()
-        self._create_user_info(account_file)
-        newsocket, fromaddr = self.socket.accept()
-        ssl_sock = self._wrap_socket_in_ssl_context(newsocket, key, cert)
-        return (ssl_sock, fromaddr)
-
-    def get_reply_data_for_GET(self, id, module):
-        '''Currently only support the following three url GET request '''
-        rcode, reply = http.client.NO_CONTENT, []
-        if not module:
-            if id == CONFIG_DATA_URL:
-                rcode, reply = http.client.OK, self.cmdctl.get_config_data()
-            elif id == MODULE_SPEC_URL:
-                rcode, reply = http.client.OK, self.cmdctl.get_modules_spec()
-
-        return rcode, reply
-
-    def send_command_to_module(self, module_name, command_name, params):
-        return self.cmdctl.send_command_with_check(module_name, command_name, params)
-
-httpd = None
-
-def signal_handler(signal, frame):
-    if httpd:
-        httpd.shutdown()
-    sys.exit(0)
-
-def set_signal_handler():
-    signal.signal(signal.SIGTERM, signal_handler)
-    signal.signal(signal.SIGINT, signal_handler)
-
-def run(addr = 'localhost', port = 8080, idle_timeout = 1200, verbose = False):
-    ''' Start cmdctl as one https server. '''
-    httpd = SecureHTTPServer((addr, port), SecureHTTPRequestHandler,
-                             CommandControl, idle_timeout, verbose)
-
-    httpd.serve_forever()
-
-def check_port(option, opt_str, value, parser):
-    try:
-        parser.values.port = isc.net.parse.port_parse(value)
-    except ValueError as e:
-        raise OptionValueError(str(e))
-
-def check_addr(option, opt_str, value, parser):
-    try:
-        isc.net.parse.addr_parse(value)
-        parser.values.addr = value
-    except ValueError as e:
-        raise OptionValueError(str(e))
-
-def set_cmd_options(parser):
-    parser.add_option('-p', '--port', dest = 'port', type = 'int',
-            action = 'callback', callback=check_port,
-            default = '8080', help = 'port cmdctl will use')
-
-    parser.add_option('-a', '--address', dest = 'addr', type = 'string',
-            action = 'callback', callback=check_addr,
-            default = '127.0.0.1', help = 'IP address cmdctl will use')
-
-    parser.add_option('-i', '--idle-timeout', dest = 'idle_timeout', type = 'int',
-            default = '1200', help = 'login idle time out')
-
-    parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False,
-            help="display more about what is going on")
-
-def main():
-    set_signal_handler()
-    parser = OptionParser(version = __version__)
-    set_cmd_options(parser)
-    (options, args) = parser.parse_args()
-    result = 1                  # in case of failure
-    try:
-        if options.verbose:
-            logger.set_severity("DEBUG", 99)
-        run(options.addr, options.port, options.idle_timeout, options.verbose)
-        result = 0
-    except isc.cc.SessionError as err:
-        logger.fatal(CMDCTL_CC_SESSION_ERROR, err)
-    except isc.cc.SessionTimeout:
-        logger.fatal(CMDCTL_CC_SESSION_TIMEOUT)
-    except KeyboardInterrupt:
-        logger.info(CMDCTL_STOPPED_BY_KEYBOARD)
-    except CmdctlException as err:
-        logger.fatal(CMDCTL_UNCAUGHT_EXCEPTION, err);
-
-    if httpd:
-        httpd.shutdown()
-
-    logger.info(CMDCTL_EXITING)
-
-    sys.exit(result)
-
-if __name__ == '__main__':
-    isc.util.traceback_handler.traceback_handler(main)

+ 0 - 41
src/bin/cmdctl/cmdctl.spec.pre.in

@@ -1,41 +0,0 @@
-{
-  "module_spec": {
-    "module_name": "Cmdctl",
-    "module_description": "Interface for command and control",
-    "config_data": [
-      {
-        "item_name": "key_file",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-keyfile.pem"
-      },
-      {
-        "item_name": "cert_file",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-certfile.pem"
-      },
-      {
-        "item_name": "accounts_file",
-        "item_type": "string",
-        "item_optional": false,
-        "item_default": "@@SYSCONFDIR@@/@PACKAGE@/cmdctl-accounts.csv"
-      }
-    ],
-    "commands": [
-      {
-        "command_name": "shutdown",
-        "command_description": "shutdown cmdctl",
-        "command_args": [
-          {
-            "item_name": "pid",
-            "item_type": "integer",
-            "item_optional": true
-          }
-        ]
-      }
-    ]
-  }
-}
-
-

+ 0 - 94
src/bin/cmdctl/cmdctl_messages.mes

@@ -1,94 +0,0 @@
-# Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
-#
-# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
-# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-# AND FITNESS.  IN NO EVENT SHALL ISC 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.
-
-# No namespace declaration - these constants go in the global namespace
-# of the cmdctl_messages python module.
-
-% CMDCTL_BAD_CONFIG_DATA error in config data: %1
-There was an error reading the updated configuration data. The specific
-error is printed.
-
-% CMDCTL_BAD_PASSWORD bad password for user: %1
-A login attempt was made to b10-cmdctl, but the password was wrong.
-Users can be managed with the tool b10-cmdctl-usermgr.
-
-% CMDCTL_CC_SESSION_ERROR error reading from cc channel: %1
-There was a problem reading from the command and control channel. The
-most likely cause is that the message bus daemon is not running.
-
-% CMDCTL_CC_SESSION_TIMEOUT timeout on cc channel
-A timeout occurred when waiting for essential data from the cc session.
-This usually occurs when b10-cfgmgr is not running or not responding.
-Since we are waiting for essential information, this is a fatal error,
-and the cmdctl daemon will now shut down.
-
-% CMDCTL_COMMAND_ERROR error in command %1 to module %2: %3
-An error was encountered sending the given command to the given module.
-Either there was a communication problem with the module, or the module
-was not able to process the command, and sent back an error. The
-specific error is printed in the message.
-
-% CMDCTL_COMMAND_SENT command '%1' to module '%2' was sent
-This debug message indicates that the given command has been sent to
-the given module.
-
-% CMDCTL_EXITING exiting
-The b10-cmdctl daemon is exiting.
-
-% CMDCTL_NO_SUCH_USER username not found in user database: %1
-A login attempt was made to b10-cmdctl, but the username was not known.
-Users can be added with the tool b10-cmdctl-usermgr.
-
-% CMDCTL_NO_USER_ENTRIES_READ failed to read user information, all users will be denied
-The b10-cmdctl daemon was unable to find any user data in the user
-database file. Either it was unable to read the file (in which case
-this message follows a message CMDCTL_USER_DATABASE_READ_ERROR
-containing a specific error), or the file was empty. Users can be added
-with the tool b10-cmdctl-usermgr.
-
-% CMDCTL_SEND_COMMAND sending command %1 to module %2
-This debug message indicates that the given command is being sent to
-the given module.
-
-% CMDCTL_SSL_SETUP_FAILURE_READING_CERT failed to read certificate or key: %1
-The b10-cmdctl daemon is unable to read either the certificate file or
-the private key file, and is therefore unable to accept any SSL connections.
-The specific error is printed in the message.
-The administrator should solve the issue with the files, or recreate them
-with the b10-certgen tool.
-
-% CMDCTL_SSL_SETUP_FAILURE_USER_DENIED failed to create an SSL connection (user denied): %1
-The user was denied because the SSL connection could not successfully
-be set up. The specific error is given in the log message. Possible
-causes may be that the ssl request itself was bad, or the local key or
-certificate file could not be read.
-
-% CMDCTL_STARTED cmdctl is listening for connections on %1:%2
-The cmdctl daemon has started and is now listening for connections.
-
-% CMDCTL_STOPPED_BY_KEYBOARD keyboard interrupt, shutting down
-There was a keyboard interrupt signal to stop the cmdctl daemon. The
-daemon will now shut down.
-
-% CMDCTL_UNCAUGHT_EXCEPTION uncaught exception: %1
-The b10-cmdctl daemon encountered an uncaught exception and
-will now shut down. This is indicative of a programming error and
-should not happen under normal circumstances. The exception message
-is printed.
-
-% CMDCTL_USER_DATABASE_READ_ERROR failed to read user database file %1: %2
-The b10-cmdctl daemon was unable to read the user database file. The
-file may be unreadable for the daemon, or it may be corrupted. In the
-latter case, it can be recreated with b10-cmdctl-usermgr. The specific
-error is printed in the log message.

+ 0 - 37
src/bin/cmdctl/run_b10-cmdctl.sh.in

@@ -1,37 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
-export PYTHON_EXEC
-
-CMD_CTRLD_PATH=@abs_top_builddir@/src/bin/cmdctl
-PYTHONPATH=@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python/isc/cc:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/python/isc/config:@abs_top_builddir@/src/lib/python/isc/acl/.libs:@abs_top_builddir@/src/lib/python/isc/datasrc/.libs
-export PYTHONPATH
-
-# If necessary (rare cases), explicitly specify paths to dynamic libraries
-# required by loadable python modules.
-SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
-if test $SET_ENV_LIBRARY_PATH = yes; then
-        @ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/threads/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:@abs_top_builddir@/src/lib/datasrc/.libs:$@ENV_LIBRARY_PATH@
-        export @ENV_LIBRARY_PATH@
-fi
-
-BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
-export BIND10_MSGQ_SOCKET_FILE
-
-cd ${CMD_CTRLD_PATH}
-exec ${PYTHON_EXEC} b10-cmdctl "$@"

+ 0 - 1
src/bin/cmdctl/tests/.gitignore

@@ -1 +0,0 @@
-/cmdctl_test

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 42
src/bin/cmdctl/tests/Makefile.am


+ 0 - 253
src/bin/cmdctl/tests/botan-certgen_test.py

@@ -1,253 +0,0 @@
-# Copyright (C) 2012  Internet Systems Consortium.
-#
-# 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.
-
-# Note: the main code is in C++, but what we are mostly testing is
-# options and behaviour (output/file creation, etc), which is easier
-# to test in python.
-
-import unittest
-import os
-from subprocess import call
-import subprocess
-import ssl
-import stat
-
-def run(command):
-    """
-    Small helper function that returns a tuple of (rcode, stdout, stderr) after
-    running the given command (an array of command and arguments, as passed on
-    to subprocess).
-    """
-    subp = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-    (stdout, stderr) = subp.communicate()
-    return (subp.returncode, stdout, stderr)
-
-class FileDeleterContext:
-    """
-    Simple Context Manager that deletes a given set of files when the context
-    is left.
-    """
-    def __init__(self, files):
-        self.files = files
-
-    def __enter__(self):
-        pass
-
-    def __exit__(self, type, value, traceback):
-        for f in self.files:
-            if os.path.exists(f):
-                os.unlink(f)
-
-class FilePermissionContext:
-    """
-    Simple Context Manager that temporarily modifies file permissions for
-    a given file
-    """
-    def __init__(self, f, unset_flags = [], set_flags = []):
-        """
-        Initialize file permission context.
-        See the stat module for possible flags to set or unset.
-        The flags are changed when the context is entered (i.e.
-        you can create the context first without any change)
-        The flags are changed back when the context is left.
-
-        Parameters:
-        f: string, file to change permissions for
-        unset_flags: list of flags to unset
-        set_flags: list of flags to set
-        """
-        self.file = f
-        self.orig_mode = os.stat(f).st_mode
-        new_mode = self.orig_mode
-        for flag in unset_flags:
-            new_mode = new_mode & ~flag
-        for flag in set_flags:
-            new_mode = new_mode | flag
-        self.new_mode = new_mode
-
-    def __enter__(self):
-        os.chmod(self.file, self.new_mode)
-
-    def __exit__(self, type, value, traceback):
-        os.chmod(self.file, self.orig_mode)
-
-def read_file_data(filename):
-    """
-    Simple text file reader that returns its contents as an array
-    """
-    with open(filename) as f:
-        return f.readlines()
-
-class TestCertGenTool(unittest.TestCase):
-    TOOL = '../b10-certgen'
-
-    def run_check(self, expected_returncode, expected_stdout, expected_stderr, command):
-        """
-        Runs the given command, and checks return code, and outputs (if provided).
-        Arguments:
-        expected_returncode, return code of the command
-        expected_stdout, (multiline) string that is checked agains stdout.
-                         May be None, in which case the check is skipped.
-        expected_stderr, (multiline) string that is checked agains stderr.
-                         May be None, in which case the check is skipped.
-        """
-        (returncode, stdout, stderr) = run(command)
-        self.assertEqual(expected_returncode, returncode, " ".join(command))
-        if expected_stdout is not None:
-            self.assertEqual(expected_stdout, stdout.decode())
-        if expected_stderr is not None:
-            self.assertEqual(expected_stderr, stderr.decode())
-
-    def validate_certificate(self, expected_result, certfile):
-        """
-        Validate a certificate, using the quiet option of the tool; it runs
-        the check option (-c) for the given base name of the certificate (-f
-        <certfile>), and compares the return code to the given
-        expected_result value
-        """
-        self.run_check(expected_result, '', '',
-                       [self.TOOL, '-q', '-c', certfile])
-        # Same with long options
-        self.run_check(expected_result, '', '',
-                       [self.TOOL, '--quiet', '--certfile', certfile])
-
-
-    def test_basic_creation(self):
-        """
-        Tests whether basic creation with no arguments (except output
-        file name) successfully creates a key and certificate
-        """
-        keyfile = 'test-keyfile.pem'
-        certfile = 'test-certfile.pem'
-        command = [ self.TOOL, '-q', '-w', '-c', certfile, '-k', keyfile ]
-        self.creation_helper(command, certfile, keyfile)
-        # Do same with long options
-        command = [ self.TOOL, '--quiet', '--write', '--certfile=' + certfile, '--keyfile=' + keyfile ]
-        self.creation_helper(command, certfile, keyfile)
-
-    def creation_helper(self, command, certfile, keyfile):
-        """
-        Helper method for test_basic_creation.
-        Performs the actual checks
-        """
-        with FileDeleterContext([keyfile, certfile]):
-            self.assertFalse(os.path.exists(keyfile))
-            self.assertFalse(os.path.exists(certfile))
-            self.run_check(0, '', '', command)
-            self.assertTrue(os.path.exists(keyfile))
-            self.assertTrue(os.path.exists(certfile))
-
-            # Validate the certificate that was just created
-            self.validate_certificate(0, certfile)
-
-            # When run with the same options, it should *not* create it again,
-            # as the current certificate should still be valid
-            certdata = read_file_data(certfile)
-            keydata = read_file_data(keyfile)
-
-            self.run_check(0, '', '', command)
-
-            self.assertEqual(certdata, read_file_data(certfile))
-            self.assertEqual(keydata, read_file_data(keyfile))
-
-            # but if we add -f, it should force a new creation
-            command.append('-f')
-            self.run_check(0, '', '', command)
-            self.assertNotEqual(certdata, read_file_data(certfile))
-            self.assertNotEqual(keydata, read_file_data(keyfile))
-
-    def test_check_bad_certificates(self):
-        """
-        Tests a few pre-created certificates with the -c option
-        """
-        path = os.environ['CMDCTL_SRC_PATH'] + '/tests/testdata/'
-        self.validate_certificate(10, path + 'expired-certfile.pem')
-        self.validate_certificate(100, path + 'mangled-certfile.pem')
-        self.validate_certificate(17, path + 'noca-certfile.pem')
-
-    def test_bad_options(self):
-        """
-        Tests some combinations of commands that should fail.
-        """
-        # specify -c but not -k
-        self.run_check(101,
-                       'Error: keyfile and certfile must both be specified '
-                       'if one of them is when calling b10-certgen in write '
-                       'mode.\n',
-                       '', [self.TOOL, '-w', '-c', 'foo'])
-        self.run_check(101,
-                       'Error: keyfile and certfile must both be specified '
-                       'if one of them is when calling b10-certgen in write '
-                       'mode.\n',
-                       '', [self.TOOL, '-w', '-k', 'foo'])
-        self.run_check(101,
-                       'Error: keyfile is not used when not in write mode\n',
-                       '', [self.TOOL, '-k', 'foo'])
-        # Extraneous argument
-        self.run_check(101, None, None, [self.TOOL, 'foo'])
-        # No such file
-        self.run_check(105, None, None, [self.TOOL, '-c', 'foo'])
-
-    @unittest.skipIf(os.getuid() == 0,
-                     'test cannot be run as root user')
-    def test_permissions(self):
-        """
-        Test some combinations of correct and bad permissions.
-        """
-        keyfile = 'mod-keyfile.pem'
-        certfile = 'mod-certfile.pem'
-        command = [ self.TOOL, '-q', '-w', '-c', certfile, '-k', keyfile ]
-        # Delete them at the end
-        with FileDeleterContext([keyfile, certfile]):
-            # Create the two files first
-            self.run_check(0, '', '', command)
-            self.validate_certificate(0, certfile)
-
-            # Make the key file unwritable
-            with FilePermissionContext(keyfile, unset_flags = [stat.S_IWUSR]):
-                self.run_check(106, '', '', command)
-                # Should have no effect on validation
-                self.validate_certificate(0, certfile)
-
-            # Make the cert file unwritable
-            with FilePermissionContext(certfile, unset_flags = [stat.S_IWUSR]):
-                self.run_check(106, '', '', command)
-                # Should have no effect on validation
-                self.validate_certificate(0, certfile)
-
-            # Make the key file unreadable (this should not matter)
-            with FilePermissionContext(keyfile, unset_flags = [stat.S_IRUSR]):
-                self.run_check(0, '', '', command)
-
-                # unreadable key file should also not have any effect on
-                # validation
-                self.validate_certificate(0, certfile)
-
-            # Make the cert file unreadable (this should matter)
-            with FilePermissionContext(certfile, unset_flags = [stat.S_IRUSR]):
-                self.run_check(106, '', '', command)
-
-                # Unreadable cert file should also fail validation
-                self.validate_certificate(106, certfile)
-
-        # Not directly a permission problem, but trying to check or create
-        # in a nonexistent directory returns different error codes
-        self.validate_certificate(105, 'fakedir/cert')
-        self.run_check(103, '', '', [ self.TOOL, '-q', '-w', '-c',
-                                      'fakedir/cert', '-k', 'fakedir/key' ])
-
-if __name__== '__main__':
-    unittest.main()
-

+ 0 - 27
src/bin/cmdctl/tests/cmdctl_test.in

@@ -1,27 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
-export PYTHON_EXEC
-
-CMDCTL_TEST_PATH=@abs_top_srcdir@/src/bin/cmdctl/tests
-PYTHONPATH=@abs_top_srcdir@/src/bin/cmdctl
-export PYTHONPATH
-
-cd ${CMDCTL_TEST_PATH}
-exec ${PYTHON_EXEC} -O cmdctl_test.py $*
-

+ 0 - 790
src/bin/cmdctl/tests/cmdctl_test.py

@@ -1,790 +0,0 @@
-# Copyright (C) 2009  Internet Systems Consortium.
-#
-# 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.
-
-
-import unittest
-import ssl, socket
-import tempfile
-import time
-import stat
-import sys
-from cmdctl import *
-import isc.log
-
-assert 'CMDCTL_SRC_PATH' in os.environ,\
-       "Please run this test with 'make check'"
-SRC_FILE_PATH = os.environ['CMDCTL_SRC_PATH'] + os.sep
-
-assert 'CMDCTL_BUILD_PATH' in os.environ,\
-       "Please run this test with 'make check'"
-BUILD_FILE_PATH = os.environ['CMDCTL_BUILD_PATH'] + os.sep
-
-# Rewrite the class for unittest.
-class MySecureHTTPRequestHandler(SecureHTTPRequestHandler):
-    def __init__(self):
-        self.session_id = None
-
-    def send_response(self, rcode):
-        self.rcode = rcode
-
-    def end_headers(self):
-        pass
-
-class FakeSecureHTTPServer(SecureHTTPServer):
-    def __init__(self):
-        self.user_sessions = {}
-        self.cmdctl = FakeCommandControlForTestRequestHandler()
-        self._verbose = True
-        self._user_infos = {}
-        self.idle_timeout = 1200
-        self._lock = threading.Lock()
-
-class FakeCommandControlForTestRequestHandler(CommandControl):
-    def __init__(self):
-        self._config_data = {}
-        self.modules_spec = {}
-        self._lock = threading.Lock()
-
-    def send_command(self, mod, cmd, param):
-        return 0, {}
-
-# context to temporarily make a file unreadable
-class UnreadableFile:
-    def __init__(self, file_name):
-        self.file_name = file_name
-        self.orig_mode = os.stat(file_name).st_mode
-
-    def __enter__(self):
-        os.chmod(self.file_name, self.orig_mode & ~stat.S_IRUSR)
-
-    def __exit__(self, type, value, traceback):
-        os.chmod(self.file_name, self.orig_mode)
-
-class TmpTextFile:
-    """
-    Context class for temporarily creating a text file with some
-    lines of content.
-
-    The file is automatically deleted if the context is left, so
-    make sure to not use the path of an existing file!
-    """
-    def __init__(self, path, contents):
-        self.__path = path
-        self.__contents = contents
-
-    def __enter__(self):
-        with open(self.__path, 'w') as f:
-            f.write("\n".join(self.__contents) + "\n")
-
-    def __exit__(self, type, value, traceback):
-        os.unlink(self.__path)
-
-
-class TestSecureHTTPRequestHandler(unittest.TestCase):
-    def setUp(self):
-        self.old_stdout = sys.stdout
-        sys.stdout = open(os.devnull, 'w')
-        self.handler = MySecureHTTPRequestHandler()
-        self.handler.server = FakeSecureHTTPServer()
-        self.handler.server.user_sessions = {}
-        self.handler.server._user_infos = {}
-        self.handler.headers = {}
-        self.handler.rfile = open('input.tmp', 'w+b')
-        self.handler.wfile = open('output.tmp', 'w+b')
-
-    def tearDown(self):
-        sys.stdout.close()
-        sys.stdout = self.old_stdout
-        self.handler.wfile.close()
-        os.remove('output.tmp')
-        self.handler.rfile.close()
-        os.remove('input.tmp')
-
-    def test_is_session_valid(self):
-        self.assertIsNone(self.handler.session_id)
-        self.assertFalse(self.handler._is_session_valid())
-        self.handler.session_id = 4234
-        self.assertTrue(self.handler._is_session_valid())
-
-    def test_parse_request_path(self):
-        self.handler.path = ''
-        mod, cmd = self.handler._parse_request_path()
-        self.assertTrue((mod == None) and (cmd == None))
-
-        self.handler.path = '/abc'
-        mod, cmd = self.handler._parse_request_path()
-        self.assertTrue((mod == 'abc') and (cmd == None))
-
-        self.handler.path = '/abc/edf'
-        mod, cmd = self.handler._parse_request_path()
-        self.assertTrue((mod == 'abc') and (cmd == 'edf'))
-
-        self.handler.path = '/abc/edf/ghi'
-        mod, cmd = self.handler._parse_request_path()
-        self.assertTrue((mod == 'abc') and (cmd == 'edf'))
-
-    def test_parse_request_path_1(self):
-        self.handler.path = '/ab*c'
-        mod, cmd = self.handler._parse_request_path()
-        self.assertTrue((mod == 'ab') and cmd == None)
-
-        self.handler.path = '/abc/ed*fdd/ddd'
-        mod, cmd = self.handler._parse_request_path()
-        self.assertTrue((mod == 'abc') and cmd == 'ed')
-
-        self.handler.path = '/-*/edfdd/ddd'
-        mod, cmd = self.handler._parse_request_path()
-        self.assertTrue((mod == None) and (cmd == None))
-
-        self.handler.path = '/-*/edfdd/ddd'
-        mod, cmd = self.handler._parse_request_path()
-        self.assertTrue((mod == None) and (cmd == None))
-
-    def test_do_GET(self):
-        self.handler.do_GET()
-        self.assertEqual(self.handler.rcode, http.client.BAD_REQUEST)
-
-    def test_do_GET_1(self):
-        self.handler.headers['cookie'] = 12345
-        self.handler.do_GET()
-        self.assertEqual(self.handler.rcode, http.client.UNAUTHORIZED)
-
-    def test_do_GET_2(self):
-        self.handler.headers['cookie'] = 12345
-        self.handler.server.user_sessions[12345] = time.time() + 1000000
-        self.handler.path = '/how/are'
-        self.handler.do_GET()
-        self.assertEqual(self.handler.rcode, http.client.NO_CONTENT)
-
-    def test_do_GET_3(self):
-        self.handler.headers['cookie'] = 12346
-        self.handler.server.user_sessions[12346] = time.time() + 1000000
-        path_vec = ['config_data', 'module_spec']
-        for path in path_vec:
-            self.handler.path = '/' + path
-            self.handler.do_GET()
-            self.assertEqual(self.handler.rcode, http.client.OK)
-
-    def test_is_user_logged_in(self):
-        self.handler.server.user_sessions = {}
-        self.handler.session_id = 12345
-        self.assertTrue(self.handler._is_user_logged_in() == False)
-
-        self.handler.server.user_sessions[12345] = time.time()
-        self.assertTrue(self.handler._is_user_logged_in())
-
-        self.handler.server.user_sessions[12345] = time.time() - 1500
-        self.handler.idle_timeout = 1200
-        self.assertTrue(self.handler._is_user_logged_in() == False)
-
-    def test_check_user_name_and_pwd(self):
-        self.handler.headers = {}
-        ret, msg = self.handler._check_user_name_and_pwd()
-        self.assertFalse(ret)
-        self.assertEqual(msg, ['invalid username or password'])
-
-    def test_check_user_name_and_pwd_1(self):
-        user_info = {'username':'root', 'password':'abc123'}
-        len = self.handler.rfile.write(json.dumps(user_info).encode())
-        self.handler.headers['Content-Length'] = len
-        self.handler.rfile.seek(0, 0)
-
-        self.handler.server._user_infos['root'] = ['aa', 'aaa']
-        ret, msg = self.handler._check_user_name_and_pwd()
-        self.assertFalse(ret)
-        self.assertEqual(msg, ['username or password error'])
-
-    def test_check_user_name_and_pwd_2(self):
-        user_info = {'username':'root', 'password':'abc123'}
-        len = self.handler.rfile.write(json.dumps(user_info).encode())
-        self.handler.headers['Content-Length'] = len - 1
-        self.handler.rfile.seek(0, 0)
-
-        ret, msg = self.handler._check_user_name_and_pwd()
-        self.assertFalse(ret)
-        self.assertEqual(msg, ['invalid username or password'])
-
-    def test_check_user_name_and_pwd_3(self):
-        user_info = {'usernae':'root', 'password':'abc123'}
-        len = self.handler.rfile.write(json.dumps(user_info).encode())
-        self.handler.headers['Content-Length'] = len
-        self.handler.rfile.seek(0, 0)
-
-        ret, msg = self.handler._check_user_name_and_pwd()
-        self.assertFalse(ret)
-        self.assertEqual(msg, ['need user name'])
-
-    def test_check_user_name_and_pwd_4(self):
-        user_info = {'username':'root', 'pssword':'abc123'}
-        len = self.handler.rfile.write(json.dumps(user_info).encode())
-        self.handler.headers['Content-Length'] = len
-        self.handler.rfile.seek(0, 0)
-
-        self.handler.server._user_infos['root'] = ['aa', 'aaa']
-        ret, msg = self.handler._check_user_name_and_pwd()
-        self.assertFalse(ret)
-        self.assertEqual(msg, ['need password'])
-
-    def test_check_user_name_and_pwd_5(self):
-        user_info = {'username':'root', 'password':'abc123'}
-        len = self.handler.rfile.write(json.dumps(user_info).encode())
-        self.handler.headers['Content-Length'] = len
-        self.handler.rfile.seek(0, 0)
-
-        ret, msg = self.handler._check_user_name_and_pwd()
-        self.assertFalse(ret)
-        self.assertEqual(msg, ['username or password error'])
-
-    def test_do_POST(self):
-        self.handler.headers = {}
-        self.handler.do_POST()
-        self.assertEqual(self.handler.rcode, http.client.BAD_REQUEST)
-
-    def test_do_POST_1(self):
-        self.handler.headers = {}
-        self.handler.headers['cookie'] = 12345
-        self.handler.path = '/'
-        self.handler.do_POST()
-        self.assertEqual(self.handler.rcode, http.client.UNAUTHORIZED)
-
-    def test_handle_post_request(self):
-        self.handler.path = '/cfgmgr/revert'
-        self.handler.headers = {}
-        rcode, reply = self.handler._handle_post_request()
-        self.assertEqual(http.client.BAD_REQUEST, rcode)
-
-    def test_handle_post_request_1(self):
-        self.handler.path = '/*d/revert'
-        self.handler.headers = {}
-        rcode, reply = self.handler._handle_post_request()
-        self.assertEqual(http.client.BAD_REQUEST, rcode)
-
-    def _gen_module_spec(self):
-        spec = { 'commands': [
-                  { 'command_name' :'command',
-                    'command_args': [ {
-                            'item_name' : 'param1',
-                            'item_type' : 'integer',
-                            'item_optional' : False,
-                            'item_default' : 0
-                           } ],
-                    'command_description' : 'cmd description'
-                  }
-                ]
-               }
-
-        return spec
-
-    def test_handle_post_request_2(self):
-        params = {'param1':123}
-        len = self.handler.rfile.write(json.dumps(params).encode())
-        self.handler.headers['Content-Length'] = len
-
-        self.handler.rfile.seek(0, 0)
-        self.handler.path = '/module/command'
-        self.handler.server.cmdctl.modules_spec = {}
-        self.handler.server.cmdctl.modules_spec['module'] = self._gen_module_spec()
-        rcode, reply = self.handler._handle_post_request()
-        self.assertEqual(http.client.OK, rcode)
-
-    def test_handle_post_request_3(self):
-        params = {'param1':'abc'}
-        len = self.handler.rfile.write(json.dumps(params).encode())
-        self.handler.headers['Content-Length'] = len
-
-        self.handler.rfile.seek(0, 0)
-        self.handler.path = '/module/command'
-        self.handler.server.cmdctl.modules_spec = {}
-        self.handler.server.cmdctl.modules_spec['module'] = self._gen_module_spec()
-        rcode, reply = self.handler._handle_post_request()
-        self.assertEqual(http.client.BAD_REQUEST, rcode)
-
-    def test_handle_login(self):
-        orig_is_user_logged_in = self.handler._is_user_logged_in
-        orig_check_user_name_and_pwd = self.handler._check_user_name_and_pwd
-        try:
-            def create_is_user_logged_in(status):
-                '''Create a replacement _is_user_logged_in() method.'''
-                def my_is_user_logged_in():
-                    return status
-                return my_is_user_logged_in
-
-            # Check case where _is_user_logged_in() returns True
-            self.handler._is_user_logged_in = create_is_user_logged_in(True)
-            self.handler.headers['cookie'] = 12345
-            self.handler.path = '/login'
-            self.handler.do_POST()
-            self.assertEqual(self.handler.rcode, http.client.OK)
-            self.handler.wfile.seek(0, 0)
-            d = self.handler.wfile.read()
-            self.assertEqual(json.loads(d.decode()),
-                             ['user has already login'])
-
-            # Clear the output
-            self.handler.wfile.seek(0, 0)
-            self.handler.wfile.truncate()
-
-            # Check case where _is_user_logged_in() returns False
-            self.handler._is_user_logged_in = create_is_user_logged_in(False)
-
-            def create_check_user_name_and_pwd(status, error_info=None):
-                '''Create a replacement _check_user_name_and_pwd() method.'''
-                def my_check_user_name_and_pwd():
-                    return status, error_info
-                return my_check_user_name_and_pwd
-
-            # (a) Check case where _check_user_name_and_pwd() returns
-            # valid user status
-            self.handler._check_user_name_and_pwd = \
-                create_check_user_name_and_pwd(True)
-            self.handler.do_POST()
-            self.assertEqual(self.handler.rcode, http.client.OK)
-            self.handler.wfile.seek(0, 0)
-            d = self.handler.wfile.read()
-            self.assertEqual(json.loads(d.decode()), ['login success'])
-
-            # Clear the output
-            self.handler.wfile.seek(0, 0)
-            self.handler.wfile.truncate()
-
-            # (b) Check case where _check_user_name_and_pwd() returns
-            # invalid user status
-            self.handler._check_user_name_and_pwd = \
-                create_check_user_name_and_pwd(False, ['login failed'])
-            self.handler.do_POST()
-            self.assertEqual(self.handler.rcode, http.client.UNAUTHORIZED)
-            self.handler.wfile.seek(0, 0)
-            d = self.handler.wfile.read()
-            self.assertEqual(json.loads(d.decode()), ['login failed'])
-
-        finally:
-            self.handler._is_user_logged_in = orig_is_user_logged_in
-            self.handler._check_user_name_and_pwd = orig_check_user_name_and_pwd
-
-class MockSession:
-    """Act like isc.cc.Session, stealing group_sendmsg/recvmsg().
-
-    The initial simple version only records given parameters in
-    group_sendmsg() for later inspection and raise a timeout exception
-    from recvmsg().  As we see the need for more test cases these methods
-    should be extended.
-
-    """
-    def __init__(self, sent_messages):
-        self.__sent_messages = sent_messages
-
-    def group_sendmsg(self, msg, module_name, want_answer):
-        self.__sent_messages.append((msg, module_name))
-
-    def group_recvmsg(self, nonblock, seq):
-        raise isc.cc.session.SessionTimeout('dummy timeout')
-
-class MyCommandControl(CommandControl):
-    def __init__(self, httpserver, verbose):
-        super().__init__(httpserver, verbose)
-        self.sent_messages = [] # for inspection; allow tests to see it
-        self._cc = MockSession(self.sent_messages)
-
-    def _get_modules_specification(self):
-        return {}
-
-    def _get_config_data_from_config_manager(self):
-        return {}
-
-    def _setup_session(self):
-        spec_file = BUILD_FILE_PATH + 'cmdctl.spec'
-        module_spec = isc.config.module_spec_from_file(spec_file)
-        config = isc.config.config_data.ConfigData(module_spec)
-        self._module_name = 'Cmdctl'
-        self._cmdctl_config_data = config.get_full_config()
-
-    def _handle_msg_from_msgq(self):
-        pass
-
-    def _start_msg_handle_thread(self): # just not bother to be threads
-        pass
-
-    def _get_current_thread(self):
-        return None
-
-class TestCommandControl(unittest.TestCase):
-
-    def setUp(self):
-        self.old_stdout = sys.stdout
-        sys.stdout = open(os.devnull, 'w')
-        self.cmdctl = MyCommandControl(None, True)
-
-    def tearDown(self):
-        sys.stdout.close()
-        sys.stdout = self.old_stdout
-
-    def _check_config(self, cmdctl):
-        key, cert, account = cmdctl.get_cmdctl_config_data()
-        self.assertIsNotNone(key)
-        self.assertIsNotNone(cert)
-        self.assertIsNotNone(account)
-
-    def test_get_cmdctl_config_data(self):
-        old_env = os.environ
-        if 'B10_FROM_SOURCE' in os.environ:
-            del os.environ['B10_FROM_SOURCE']
-        self.cmdctl.get_cmdctl_config_data()
-        self._check_config(self.cmdctl)
-        os.environ = old_env
-
-        old_env = os.environ
-        os.environ['B10_FROM_SOURCE'] = '../'
-        self._check_config(self.cmdctl)
-        os.environ = old_env
-
-    def test_parse_command_result(self):
-        self.assertEqual({}, self.cmdctl._parse_command_result(1, {'error' : 1}))
-        self.assertEqual({'a': 1}, self.cmdctl._parse_command_result(0, {'a' : 1}))
-
-    def _check_answer(self, answer, rcode_, msg_):
-        rcode, msg = ccsession.parse_answer(answer)
-        self.assertEqual(rcode, rcode_)
-        self.assertEqual(msg, msg_)
-
-    def test_command_handler(self):
-        answer = self.cmdctl.command_handler('unknown-command', None)
-        self._check_answer(answer, 1, 'unknown command: unknown-command')
-
-        # Send a real command. Mock stuff so the shutdown command doesn't
-        # cause an exception.
-        class ModuleCC:
-            def send_stopping():
-                pass
-        self.cmdctl._module_cc = ModuleCC
-        called = []
-        class Server:
-            def shutdown():
-                called.append('shutdown')
-        self.cmdctl._httpserver = Server
-        answer = self.cmdctl.command_handler('shutdown', None)
-        rcode, msg = ccsession.parse_answer(answer)
-        self.assertEqual(rcode, 0)
-        self.assertIsNone(msg)
-        self.assertEqual(['shutdown'], called)
-
-    def test_command_handler_spec_update(self):
-        # Should not be present
-        self.assertFalse("foo" in self.cmdctl.modules_spec)
-
-        answer = self.cmdctl.command_handler(
-            ccsession.COMMAND_MODULE_SPECIFICATION_UPDATE, [ "foo", {} ])
-        rcode, msg = ccsession.parse_answer(answer)
-        self.assertEqual(rcode, 0)
-        self.assertEqual(msg, None)
-
-        # Should now be present
-        self.assertTrue("foo" in self.cmdctl.modules_spec)
-
-        # When sending specification 'None', it should be removed
-        answer = self.cmdctl.command_handler(
-            ccsession.COMMAND_MODULE_SPECIFICATION_UPDATE, [ "foo", None ])
-        rcode, msg = ccsession.parse_answer(answer)
-        self.assertEqual(rcode, 0)
-        self.assertEqual(msg, None)
-
-        # Should no longer be present
-        self.assertFalse("foo" in self.cmdctl.modules_spec)
-
-        # Don't store 'None' if it wasn't there in the first place!
-        answer = self.cmdctl.command_handler(
-            ccsession.COMMAND_MODULE_SPECIFICATION_UPDATE, [ "foo", None ])
-        rcode, msg = ccsession.parse_answer(answer)
-        self.assertEqual(rcode, 1)
-        self.assertEqual(msg, "No such module: foo")
-
-        # Should still not present
-        self.assertFalse("foo" in self.cmdctl.modules_spec)
-
-
-    def test_check_config_handler(self):
-        answer = self.cmdctl.config_handler({'non-exist': 123})
-        self._check_answer(answer, 1, 'unknown config item: non-exist')
-
-        old_env = os.environ
-        os.environ['B10_FROM_SOURCE'] = '../'
-        self._check_config(self.cmdctl)
-        os.environ = old_env
-
-        answer = self.cmdctl.config_handler({'key_file': '/user/non-exist_folder'})
-        self._check_answer(answer, 1, "'/user/non-exist_folder' does not exist")
-
-        answer = self.cmdctl.config_handler({'cert_file': '/user/non-exist_folder'})
-        self._check_answer(answer, 1, "'/user/non-exist_folder' does not exist")
-
-        answer = self.cmdctl.config_handler({'accounts_file': '/user/non-exist_folder'})
-        self._check_answer(answer, 1,
-                "Invalid accounts file: [Errno 2] No such file or directory: '/user/non-exist_folder'")
-
-        # Test with invalid accounts file
-        file_name = 'tmp.account.file'
-        temp_file = open(file_name, 'w')
-        writer = csv.writer(temp_file)
-        writer.writerow(['a', 'b'])
-        temp_file.close()
-        answer = self.cmdctl.config_handler({'accounts_file': file_name})
-        self._check_answer(answer, 1, "Invalid accounts file: list index out of range")
-        os.remove(file_name)
-
-    def test_send_command(self):
-        # Send a command to other module.  We check an expected message
-        # is sent via the session (cmdct._cc).  Due to the behavior of
-        # our mock session object the anser will be "fail", but it's not
-        # the subject of this test, and so it's okay.
-        # TODO: more detailed cases should be tested.
-        rcode, value = self.cmdctl.send_command('Init', 'shutdown', None)
-        self.assertEqual(1, len(self.cmdctl.sent_messages))
-        self.assertEqual(({'command': ['shutdown']}, 'Init'),
-                         self.cmdctl.sent_messages[-1])
-        self.assertEqual(1, rcode)
-
-        # Send a command to cmdctl itself.  Should be the same effect.
-        rcode, value = self.cmdctl.send_command('Cmdctl', 'shutdown',
-                                                None)
-        self.assertEqual(2, len(self.cmdctl.sent_messages))
-        self.assertEqual(({'command': ['shutdown']}, 'Cmdctl'),
-                         self.cmdctl.sent_messages[-1])
-        self.assertEqual(1, rcode)
-
-class MySecureHTTPServer(SecureHTTPServer):
-    def server_bind(self):
-        pass
-
-class TestSecureHTTPServer(unittest.TestCase):
-    def setUp(self):
-        self.old_stdout = sys.stdout
-        self.old_stderr = sys.stderr
-        sys.stdout = open(os.devnull, 'w')
-        sys.stderr = sys.stdout
-        self.server = MySecureHTTPServer(('localhost', 8080),
-                                         MySecureHTTPRequestHandler,
-                                         MyCommandControl, verbose=True)
-
-    def tearDown(self):
-        # both sys.stdout and sys.stderr are the same, so closing one is
-        # sufficient
-        sys.stdout.close()
-        sys.stdout = self.old_stdout
-        sys.stderr = self.old_stderr
-
-    def test_addr_in_use(self):
-        server_one = None
-        try:
-            server_one = SecureHTTPServer(('localhost', 53531),
-                                        MySecureHTTPRequestHandler,
-                                        MyCommandControl)
-        except CmdctlException:
-            pass
-        else:
-            self.assertRaises(CmdctlException, SecureHTTPServer,
-                              ('localhost', 53531),
-                              MySecureHTTPRequestHandler, MyCommandControl)
-        if server_one:
-            server_one.server_close()
-
-    def test_create_user_info(self):
-        self.server._create_user_info('/local/not-exist')
-        self.assertEqual(0, len(self.server._user_infos))
-
-        self.server._create_user_info(SRC_FILE_PATH + 'cmdctl-accounts.csv')
-        self.assertEqual(1, len(self.server._user_infos))
-        self.assertTrue('root' in self.server._user_infos)
-
-    def test_get_user_info(self):
-        self.assertIsNone(self.server.get_user_info('root'))
-        self.server._create_user_info(SRC_FILE_PATH + 'cmdctl-accounts.csv')
-        self.assertIn('6f0c73bd33101a5ec0294b3ca39fec90ef4717fe',
-                      self.server.get_user_info('root'))
-
-        # When the file is not changed calling _create_user_info() again
-        # should have no effect. In order to test this, we overwrite the
-        # user-infos that were just set and make sure it isn't touched by
-        # the call (so make sure it isn't set to some empty value)
-        fake_users_val = { 'notinfile': [] }
-        self.server._user_infos = fake_users_val
-        self.server._create_user_info(SRC_FILE_PATH + 'cmdctl-accounts.csv')
-        self.assertEqual(fake_users_val, self.server._user_infos)
-
-    def test_create_user_info_changing_file_time(self):
-        self.assertEqual(0, len(self.server._user_infos))
-
-        # Create a file
-        accounts_file = BUILD_FILE_PATH + 'new_file.csv'
-        with TmpTextFile(accounts_file, ['root,foo,bar']):
-            self.server._create_user_info(accounts_file)
-            self.assertEqual(1, len(self.server._user_infos))
-            self.assertTrue('root' in self.server._user_infos)
-
-            # Make sure re-reading is a noop if file was not modified
-            fake_users_val = { 'notinfile': [] }
-            self.server._user_infos = fake_users_val
-            self.server._create_user_info(accounts_file)
-            self.assertEqual(fake_users_val, self.server._user_infos)
-
-        # create the file again, this time read should not be a noop
-        with TmpTextFile(accounts_file, ['otherroot,foo,bar']):
-            # Set mtime in future
-            stat = os.stat(accounts_file)
-            os.utime(accounts_file, (stat.st_atime, stat.st_mtime + 10))
-            self.server._create_user_info(accounts_file)
-            self.assertEqual(1, len(self.server._user_infos))
-            self.assertTrue('otherroot' in self.server._user_infos)
-
-    def test_create_user_info_changing_file_name(self):
-        """
-        Check that the accounts file is re-read if the file name is different
-        """
-        self.assertEqual(0, len(self.server._user_infos))
-
-        # Create two files
-        accounts_file1 = BUILD_FILE_PATH + 'new_file.csv'
-        accounts_file2 = BUILD_FILE_PATH + 'new_file2.csv'
-        with TmpTextFile(accounts_file2, ['otherroot,foo,bar']):
-            with TmpTextFile(accounts_file1, ['root,foo,bar']):
-                self.server._create_user_info(accounts_file1)
-                self.assertEqual(1, len(self.server._user_infos))
-                self.assertTrue('root' in self.server._user_infos)
-
-                # Make sure re-reading is a noop if file was not modified
-                fake_users_val = { 'notinfile': [] }
-                self.server._user_infos = fake_users_val
-                self.server._create_user_info(accounts_file1)
-                self.assertEqual(fake_users_val, self.server._user_infos)
-
-                # But a different file should be read
-                self.server._create_user_info(accounts_file2)
-                self.assertEqual(1, len(self.server._user_infos))
-                self.assertTrue('otherroot' in self.server._user_infos)
-
-    def test_create_user_info_nonexistent_file(self):
-        # Even if there was data initially, if set to a nonexistent
-        # file it should result in no users
-        accounts_file = BUILD_FILE_PATH + 'new_file.csv'
-        self.assertFalse(os.path.exists(accounts_file))
-        fake_users_val = { 'notinfile': [] }
-        self.server._user_infos = fake_users_val
-        self.server._create_user_info(accounts_file)
-        self.assertEqual({}, self.server._user_infos)
-
-        # Should it now be created it should be read
-        with TmpTextFile(accounts_file, ['root,foo,bar']):
-            self.server._create_user_info(accounts_file)
-            self.assertEqual(1, len(self.server._user_infos))
-            self.assertTrue('root' in self.server._user_infos)
-
-    def test_check_file(self):
-        # Just some file that we know exists
-        file_name = BUILD_FILE_PATH + 'cmdctl-keyfile.pem'
-        check_file(file_name)
-        self.assertRaises(CmdctlException, check_file, '/local/not-exist')
-        self.assertRaises(CmdctlException, check_file, '/')
-
-    @unittest.skipIf(os.getuid() == 0,
-                     'test cannot be run as root user')
-    def test_check_file_for_unreadable(self):
-        file_name = BUILD_FILE_PATH + 'cmdctl-keyfile.pem'
-        with UnreadableFile(file_name):
-            self.assertRaises(CmdctlException, check_file, file_name)
-
-    def test_check_key_and_cert(self):
-        keyfile = BUILD_FILE_PATH + 'cmdctl-keyfile.pem'
-        certfile = BUILD_FILE_PATH + 'cmdctl-certfile.pem'
-
-        # no exists
-        self.assertRaises(CmdctlException, self.server._check_key_and_cert,
-                          keyfile, '/local/not-exist')
-        self.assertRaises(CmdctlException, self.server._check_key_and_cert,
-                         '/local/not-exist', certfile)
-
-        # not a file
-        self.assertRaises(CmdctlException, self.server._check_key_and_cert,
-                          keyfile, '/')
-        self.assertRaises(CmdctlException, self.server._check_key_and_cert,
-                         '/', certfile)
-
-        # All OK (also happens to check the context code above works)
-        self.server._check_key_and_cert(keyfile, certfile)
-
-    @unittest.skipIf(os.getuid() == 0,
-                     'test cannot be run as root user')
-    def test_check_key_and_cert_for_unreadable(self):
-        keyfile = BUILD_FILE_PATH + 'cmdctl-keyfile.pem'
-        certfile = BUILD_FILE_PATH + 'cmdctl-certfile.pem'
-
-        # no read permission
-        with UnreadableFile(certfile):
-            self.assertRaises(CmdctlException,
-                              self.server._check_key_and_cert,
-                              keyfile, certfile)
-
-        with UnreadableFile(keyfile):
-            self.assertRaises(CmdctlException,
-                              self.server._check_key_and_cert,
-                              keyfile, certfile)
-
-    def test_wrap_sock_in_ssl_context(self):
-        sock = socket.socket()
-
-        # Bad files should result in a CmdctlException in the basic file
-        # checks
-        self.assertRaises(CmdctlException,
-                          self.server._wrap_socket_in_ssl_context,
-                          sock,
-                          'no_such_file', 'no_such_file')
-
-        # Using a non-certificate file would cause an SSLError
-        self.assertRaises(socket.error,
-                          self.server._wrap_socket_in_ssl_context,
-                          sock,
-                          BUILD_FILE_PATH + 'cmdctl.py',
-                          BUILD_FILE_PATH + 'cmdctl-certfile.pem')
-
-        # Should succeed
-        sock1 = socket.socket()
-        ssl_sock = self.server._wrap_socket_in_ssl_context(sock1,
-                                   BUILD_FILE_PATH + 'cmdctl-keyfile.pem',
-                                   BUILD_FILE_PATH + 'cmdctl-certfile.pem')
-        self.assertTrue(isinstance(ssl_sock, ssl.SSLSocket))
-
-        # wrap_socket can also raise IOError, which should be caught and
-        # handled like the other errors.
-        # Force this by temporarily disabling our own file checks
-        orig_check_func = self.server._check_key_and_cert
-        try:
-            self.server._check_key_and_cert = lambda x,y: None
-            self.assertRaises(IOError,
-                              self.server._wrap_socket_in_ssl_context,
-                              sock,
-                              'no_such_file', 'no_such_file')
-        finally:
-            self.server._check_key_and_cert = orig_check_func
-
-class TestFuncNotInClass(unittest.TestCase):
-    def test_check_port(self):
-        self.assertRaises(OptionValueError, check_port, None, 'port', -1, None)
-        self.assertRaises(OptionValueError, check_port, None, 'port', 65536, None)
-        self.assertRaises(OptionValueError, check_addr, None, 'ipstr', 'a.b.d', None)
-        self.assertRaises(OptionValueError, check_addr, None, 'ipstr', '1::0:a.b', None)
-
-
-if __name__== "__main__":
-    isc.log.resetUnitTestRootLogger()
-    unittest.main()
-
-

+ 0 - 21
src/bin/cmdctl/tests/testdata/expired-certfile.pem

@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDhzCCAvCgAwIBAgIJALwngNFik7ONMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYD
-VQQGEwJjbjEQMA4GA1UECBMHYmVpamluZzEQMA4GA1UEBxMHYmVpamluZzEOMAwG
-A1UEChMFY25uaWMxDjAMBgNVBAsTBWNubmljMRMwEQYDVQQDEwp6aGFuZ2xpa3Vu
-MSIwIAYJKoZIhvcNAQkBFhN6aGFuZ2xpa3VuQGNubmljLmNuMB4XDTEwMDEwNzEy
-NDcxOFoXDTExMDEwNzEyNDcxOFowgYoxCzAJBgNVBAYTAmNuMRAwDgYDVQQIEwdi
-ZWlqaW5nMRAwDgYDVQQHEwdiZWlqaW5nMQ4wDAYDVQQKEwVjbm5pYzEOMAwGA1UE
-CxMFY25uaWMxEzARBgNVBAMTCnpoYW5nbGlrdW4xIjAgBgkqhkiG9w0BCQEWE3po
-YW5nbGlrdW5AY25uaWMuY24wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOkg
-JbEkYoy9SEsU9t/mfxlaiCqNhxCqqgeodVEdiPKJ7LoVl21mRjazWBiHQbQ1e2Ka
-UiCJz68RwV7u92bIqe1bsNgNqoCPQqsQPtEoCPzfbiM1tIke0s/h6+8l6ne+yg21
-O825x5Anjq+6THLGCDcO4L2RWo+4PwJnVGrgBPKLAgMBAAGjgfIwge8wHQYDVR0O
-BBYEFJKM/O0ViGlwtb3JEci/DLTO/7DaMIG/BgNVHSMEgbcwgbSAFJKM/O0ViGlw
-tb3JEci/DLTO/7DaoYGQpIGNMIGKMQswCQYDVQQGEwJjbjEQMA4GA1UECBMHYmVp
-amluZzEQMA4GA1UEBxMHYmVpamluZzEOMAwGA1UEChMFY25uaWMxDjAMBgNVBAsT
-BWNubmljMRMwEQYDVQQDEwp6aGFuZ2xpa3VuMSIwIAYJKoZIhvcNAQkBFhN6aGFu
-Z2xpa3VuQGNubmljLmNuggkAvCeA0WKTs40wDAYDVR0TBAUwAwEB/zANBgkqhkiG
-9w0BAQUFAAOBgQBh5N6isMAQAFFD+pbfpppjQlO4vUNcEdzPdeuBFaf9CsX5ZdxV
-jmn1ZuGm6kRzqUPwPSxvCIAY0wuSu1g7YREPAZ3XBVwcg6262iGOA6n7E+nv5PLz
-EuZ1oUg+IfykUIoflKH6xZB4MyPL+EgkMT+i9BrngaXHXF8tEO30YppMiA==
------END CERTIFICATE-----

+ 0 - 21
src/bin/cmdctl/tests/testdata/mangled-certfile.pem

@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDhzCCAvCgAwIBAgIJALwngNFik7ONMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYD
-VQQGEwJjbjEQMA4GA1UECBMHYmVpamluZzEQMA4GA1UEBxMHYmVpamluZzEOMAwG
-A1UEChMFY25uaWMxDjAMBgNVBAsTBWNubmljMRMwEQYDVQQDEwp6aGFuZ2xpa3Vu
-MSIwIAYJKoZIhvcNAQkBFhN6aGFuZ2xpa3VuQGNubmljLmNuMB4XDTEwMDEwNzEy
-NDcxOFoXDTExMDEwNzEyNDcxOFowgYoxCzAJBgNVBAYTAmNuMRAwDgYDVQQIEwdi
-ZWlqaW5nMraWDgYDVQQHEwdiZWlqaW5nMQ4wDAYDVQQKEwVjbm5pYzEOMAwGA1UE
-CxMFY25uaWMxeZaRBgNVBAMTCnpoYW5nbGlrdW4xIjAgBgkqhkiG9w0BCQEWE3po
-YW5nbGlrdW5AY25UAwMuY24wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOkg
-JbEkYoy9SEsU9t/mfxLAICqNhxCqqgeodVEdiPKJ7LoVl21mRjazWBiHQbQ1e2Ka
-UiCJz68RwV7u92bIqe1bsNgNqoCPQqsQPtEoCPzfbiM1tIke0s/h6+8l6ne+yg21
-O825x5Anjq+6THLGCDcO4L2RWo+4PwJnVGrgBPKLAgMBAAGjgfIwge8wHQYDVR0O
-BBYEFJKM/O0ViGlwtb3JEci/DLTO/7DaMIG/BgNVHSMEgbcwgbSAFJKM/O0ViGlw
-tb3JEci/DLTO/7DaoYGQpIGNMIGKMQswCQYDVQQGEwJjbjEQMA4GA1UECBMHYmVp
-amluZzEQMA4GA1UEBxMHYmVpamluZzEOMAwGA1UEChMFY25uaWMxDjAMBgNVBAsT
-BWNubmljMRMwEQYDVQQDEwp6aGFuZ2xpa3VuMSIwIAYJKoZIhvcNAQkBFhN6aGFu
-Z2xpa3VuQGNubmljLmNuggkAvCeA0WKTs40wDAYDVR0TBAUwAwEB/zANBgkqhkiG
-9w0BAQUFAAOBgQBh5N6isMAQAFFD+pbfpppjQlO4vUNcEdzPdeuBFaf9CsX5ZdxV
-jmn1ZuGm6kRzqUPwPSxvCIAY0wuSu1g7YREPAZ3XBVwcg6262iGOA6n7E+nv5PLz
-EuZ1oUg+IfykUIoflKH6xZB4MyPL+EgkMT+i9BrngaXHXF8tEO30YppMiA==
------END CERTIFICATE-----

+ 0 - 19
src/bin/cmdctl/tests/testdata/noca-certfile.pem

@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDBjCCAe6gAwIBAgIRALUIj3nnW5uDE/+fglPvUDwwDQYJKoZIhvcNAQELBQAw
-HjELMAkGA1UEBhMCVVMxDzANBgNVBAMTBkJJTkQxMDAeFw0xMjExMTQxMjQ5MjVa
-Fw0xMzExMTQxMjQ5MjVaMB4xCzAJBgNVBAYTAlVTMQ8wDQYDVQQDEwZCSU5EMTAw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkIOPfs3Aw9kNDu1JqA2w3
-84/n9oUgAwAlHVmuJv7ZDw1MDaIKHjsh3DW09z+nv67GVksI7pFtAw5O4mnTDxpa
-JT0NKzhvYGfe8VdV/hWDogTIdk1QBJNZ2/id8z0h8z5001sARXPf+4mHBJslenH3
-YtZs22BG5RBLULtZ/2Nr7JkdfLlc6D5PCoDG22r1OiFkYVdCWfLDjisVIbSYPBtY
-BlKAIrvbmOtWcaGM+vQAhl0T5N8WRCKhaQH0DEmzQNckkYd7rSECo57KYiuvOdzp
-d+3bWTgGGy2ff0o3LZypv0O5s0TDC2H6hYtN4bUbcChUJbFu9b5sVZaOEVZtUsyD
-AgMBAAGjPzA9MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgTwMB0GA1UdDgQW
-BBSqGzsEDNs9E7gBL5pD6XVAwUo4DTANBgkqhkiG9w0BAQsFAAOCAQEAMTNB8NCU
-dnLFZ0jNpvecbECkX/OWGlBYU4/CsoNiibwp4CtUYS2A4NFVjWAyuzLSHhRQi0vJ
-CCWLpKL4VTkaDN5Oft42iUhvEXMnriJqpfXHnjCiBwFFSPl5WKfMIaRNK+tF4zbB
-F+FGNEEmYG3t/ni82orDLq4oy+7CoQwzZNzj5yoV6q7O9kLR9OMPNwJrc27A4erB
-7VMRZslSrNA4uA6YhMZl8iEvO1H801ct0zTxawrCihPOZOCSLew35xjztO7d3YH8
-YavOu5kzeu7AgZ2n75H/qU47ZgBjbonn9Osvrct+RIwZuWTB2bDML8JhNaZCq0aA
-TDBC0QWqIYypLg==
------END CERTIFICATE-----

Fichier diff supprimé car celui-ci est trop grand
+ 1 - 21
src/bin/d2/tests/Makefile.am


+ 0 - 167
src/bin/d2/tests/d2_test.py

@@ -1,167 +0,0 @@
-# Copyright (C) 2013-2014 Internet Systems Consortium.
-#
-# 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.
-
-from init import ProcessInfo, parse_args, dump_pid, unlink_pid_file, _BASETIME
-
-import unittest
-import sys
-import os
-import signal
-import socket
-from isc.net.addr import IPAddr
-import time
-import isc
-import fcntl
-
-class TestD2Daemon(unittest.TestCase):
-    def setUp(self):
-        # Don't redirect stdout/stderr here as we want to print out things
-        # during the test
-        #
-        # However, we do want to set the logging lock directory to somewhere
-        # to which we can write - use the current working directory.  We then
-        # set the appropriate environment variable.  os.putenv() may be not
-        # supported on some platforms as suggested in
-        # http://docs.python.org/release/3.2/library/os.html?highlight=putenv#os.environ:
-        # "If the platform supports the putenv() function...". It was checked
-        # that it does not work on Ubuntu. To overcome this problem we access
-        # os.environ directly.
-        lockdir_envvar = "B10_LOCKFILE_DIR_FROM_BUILD"
-        if lockdir_envvar not in os.environ:
-            os.environ[lockdir_envvar] = os.getcwd()
-
-    def tearDown(self):
-        pass
-
-    def readPipe(self, pipe_fd):
-        """
-        Reads bytes from a pipe and returns a character string.  If nothing is
-        read, or if there is an error, an empty string is returned.
-
-        pipe_fd - Pipe file descriptor to read
-        """
-        try:
-            data = os.read(pipe_fd, 16384)
-            # Make sure we have a string
-            if (data is None):
-                data = ""
-            else:
-                data = str(data)
-        except OSError:
-            data = ""
-
-        return data
-
-    def runCommand(self, params, wait=1):
-        """
-        This method runs a command and returns a tuple: (returncode, stdout, stderr)
-        """
-        ## @todo: Convert this into generic method and reuse it in dhcp4 and dhcp6
-
-        print("Running command: %s" % (" ".join(params)))
-
-        # redirect stdout to a pipe so we can check that our
-        # process spawning is doing the right thing with stdout
-        self.stdout_old = os.dup(sys.stdout.fileno())
-        self.stdout_pipes = os.pipe()
-        os.dup2(self.stdout_pipes[1], sys.stdout.fileno())
-        os.close(self.stdout_pipes[1])
-
-        # do the same trick for stderr:
-        self.stderr_old = os.dup(sys.stderr.fileno())
-        self.stderr_pipes = os.pipe()
-        os.dup2(self.stderr_pipes[1], sys.stderr.fileno())
-        os.close(self.stderr_pipes[1])
-
-        # note that we use dup2() to restore the original stdout
-        # to the main program ASAP in each test... this prevents
-        # hangs reading from the child process (as the pipe is only
-        # open in the child), and also insures nice pretty output
-
-        pi = ProcessInfo('Test Process', params)
-        pi.spawn()
-        time.sleep(wait)
-        os.dup2(self.stdout_old, sys.stdout.fileno())
-        os.dup2(self.stderr_old, sys.stderr.fileno())
-        self.assertNotEqual(pi.process, None)
-        self.assertTrue(type(pi.pid) is int)
-
-        # Set non-blocking read on pipes. Process may not print anything
-        # on specific output and the we would hang without this.
-        fd = self.stdout_pipes[0]
-        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
-        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
-
-        fd = self.stderr_pipes[0]
-        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
-        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
-
-        # As we don't know how long the subprocess will take to start and
-        # produce output, we'll loop and sleep for 250 ms between each
-        # iteration.  To avoid an infinite loop, we'll loop for a maximum
-        # of five seconds: that should be enough.
-        for count in range(20):
-            # Read something from stderr and stdout (these reads don't block).
-            output = self.readPipe(self.stdout_pipes[0])
-            error  = self.readPipe(self.stderr_pipes[0])
-
-            # If the process has already exited, or if it has output something,
-            # quit the loop now.
-            if pi.process.poll() is not None or len(error) > 0 or len(output) > 0:
-                break
-
-            # Process still running, try again in 250 ms.
-            time.sleep(0.25)
-
-        # Exited loop, kill the process if it is still running
-        if pi.process.poll() is None:
-            try:
-                pi.process.terminate()
-            except OSError:
-                print("Ignoring failed kill attempt. Process is dead already.")
-
-        # call this to get returncode, process should be dead by now
-        rc = pi.process.wait()
-
-        # Clean up our stdout/stderr munging.
-        os.dup2(self.stdout_old, sys.stdout.fileno())
-        os.close(self.stdout_old)
-        os.close(self.stdout_pipes[0])
-
-        os.dup2(self.stderr_old, sys.stderr.fileno())
-        os.close(self.stderr_old)
-        os.close(self.stderr_pipes[0])
-
-        # Free up resources (file descriptors) from the ProcessInfo object
-        # TODO: For some reason, this gives an error if the process has ended,
-        #       although it does cause all descriptors still allocated to the
-        #       object to be freed.
-        pi = None
-
-        print ("Process finished, return code=%d, stdout=%d bytes, stderr=%d bytes"
-               % (rc, len(output), len(error)) )
-
-        return (rc, output, error)
-
-    def test_alive(self):
-        print("Note: Simple test to verify that D2 server can be started.")
-        # note that "-s" for stand alone is necessary in order to flush the log output
-        # soon enough to catch it.
-        (returncode, output, error) = self.runCommand(["../b10-dhcp-ddns", "-v"])
-        output_text = str(output) + str(error)
-        self.assertEqual(output_text.count("DCTL_STARTING"), 1)
-
-if __name__ == '__main__':
-    unittest.main()

Fichier diff supprimé car celui-ci est trop grand
+ 1 - 22
src/bin/dhcp4/tests/Makefile.am


+ 0 - 211
src/bin/dhcp4/tests/dhcp4_test.py

@@ -1,211 +0,0 @@
-# Copyright (C) 2012 Internet Systems Consortium.
-#
-# 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.
-
-from init import ProcessInfo
-
-import unittest
-import sys
-import os
-import signal
-import socket
-from isc.net.addr import IPAddr
-import time
-import isc
-import fcntl
-
-class TestDhcpv4Daemon(unittest.TestCase):
-    def setUp(self):
-        # Don't redirect stdout/stderr here as we want to print out things
-        # during the test
-        #
-        # However, we do want to set the logging lock directory to somewhere
-        # to which we can write - use the current working directory.  We then
-        # set the appropriate environment variable.  os.putenv() may be not
-        # supported on some platforms as suggested in
-        # http://docs.python.org/release/3.2/library/os.html?highlight=putenv#os.environ:
-        # "If the platform supports the putenv() function...". It was checked
-        # that it does not work on Ubuntu. To overcome this problem we access
-        # os.environ directly.
-        lockdir_envvar = "B10_LOCKFILE_DIR_FROM_BUILD"
-        if lockdir_envvar not in os.environ:
-            os.environ[lockdir_envvar] = os.getcwd()
-
-    def tearDown(self):
-        pass
-
-    def readPipe(self, pipe_fd):
-        """
-        Reads bytes from a pipe and returns a character string.  If nothing is
-        read, or if there is an error, an empty string is returned.
-
-        pipe_fd - Pipe file descriptor to read
-        """
-        try:
-            data = os.read(pipe_fd, 16384)
-            # Make sure we have a string
-            if (data is None):
-                data = ""
-            else:
-                data = str(data)
-        except OSError:
-            data = ""
-
-        return data
-
-    def runCommand(self, params, wait=1):
-        """
-        This method runs a command and returns a tuple: (returncode, stdout, stderr)
-        """
-        ## @todo: Convert this into generic method and reuse it in dhcp4 and dhcp6
-
-        print("Running command: %s" % (" ".join(params)))
-
-        # redirect stdout to a pipe so we can check that our
-        # process spawning is doing the right thing with stdout
-        self.stdout_old = os.dup(sys.stdout.fileno())
-        self.stdout_pipes = os.pipe()
-        os.dup2(self.stdout_pipes[1], sys.stdout.fileno())
-        os.close(self.stdout_pipes[1])
-
-        # do the same trick for stderr:
-        self.stderr_old = os.dup(sys.stderr.fileno())
-        self.stderr_pipes = os.pipe()
-        os.dup2(self.stderr_pipes[1], sys.stderr.fileno())
-        os.close(self.stderr_pipes[1])
-
-        # note that we use dup2() to restore the original stdout
-        # to the main program ASAP in each test... this prevents
-        # hangs reading from the child process (as the pipe is only
-        # open in the child), and also insures nice pretty output
-
-        pi = ProcessInfo('Test Process', params)
-        pi.spawn()
-        time.sleep(wait)
-        os.dup2(self.stdout_old, sys.stdout.fileno())
-        os.dup2(self.stderr_old, sys.stderr.fileno())
-        self.assertNotEqual(pi.process, None)
-        self.assertTrue(type(pi.pid) is int)
-
-        # Set non-blocking read on pipes. Process may not print anything
-        # on specific output and the we would hang without this.
-        fd = self.stdout_pipes[0]
-        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
-        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
-
-        fd = self.stderr_pipes[0]
-        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
-        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
-
-        # As we don't know how long the subprocess will take to start and
-        # produce output, we'll loop and sleep for 250 ms between each
-        # iteration.  To avoid an infinite loop, we'll loop for a maximum
-        # of five seconds: that should be enough.
-        for count in range(20):
-            # Read something from stderr and stdout (these reads don't block).
-            output = self.readPipe(self.stdout_pipes[0])
-            error  = self.readPipe(self.stderr_pipes[0])
-
-            # If the process has already exited, or if it has output something,
-            # quit the loop now.
-            if pi.process.poll() is not None or len(error) > 0 or len(output) > 0:
-                break
-
-            # Process still running, try again in 250 ms.
-            time.sleep(0.25)
-
-        # Exited loop, kill the process if it is still running
-        if pi.process.poll() is None:
-            try:
-                pi.process.terminate()
-            except OSError:
-                print("Ignoring failed kill attempt. Process is dead already.")
-
-        # call this to get returncode, process should be dead by now
-        rc = pi.process.wait()
-
-        # Clean up our stdout/stderr munging.
-        os.dup2(self.stdout_old, sys.stdout.fileno())
-        os.close(self.stdout_old)
-        os.close(self.stdout_pipes[0])
-
-        os.dup2(self.stderr_old, sys.stderr.fileno())
-        os.close(self.stderr_old)
-        os.close(self.stderr_pipes[0])
-
-        # Free up resources (file descriptors) from the ProcessInfo object
-        # TODO: For some reason, this gives an error if the process has ended,
-        #       although it does cause all descriptors still allocated to the
-        #       object to be freed.
-        pi = None
-
-        print ("Process finished, return code=%d, stdout=%d bytes, stderr=%d bytes"
-               % (rc, len(output), len(error)) )
-
-        return (rc, output, error)
-
-    def test_alive(self):
-        print("Note: Purpose of some of the tests is to check if DHCPv4 server can be started,")
-        print("      not that is can bind sockets correctly. Please ignore binding errors.")
-
-        (returncode, output, error) = self.runCommand(["../b10-dhcp4", "-v"])
-        output_text = str(output) + str(error)
-        self.assertEqual(output_text.count("DHCP4_STARTING"), 1)
-
-    def test_portnumber_0(self):
-        print("Check that specifying port number 0 is not allowed.")
-
-        (returncode, output, error) = self.runCommand(['../b10-dhcp4', '-v', '-p', '0'])
-
-        # When invalid port number is specified, return code must not be success
-        self.assertTrue(returncode != 0)
-
-        # Check that there is an error message about invalid port number printed on stderr
-        self.assertEqual( str(error).count("Failed to parse port number"), 1)
-
-    def test_portnumber_missing(self):
-        print("Check that -p option requires a parameter.")
-
-        (returncode, output, error) = self.runCommand(['../b10-dhcp4', '-p'])
-
-        # When invalid port number is specified, return code must not be success
-        self.assertTrue(returncode != 0)
-
-        # Check that there is an error message about invalid port number printed on stderr
-        self.assertEqual( str(error).count("option requires an argument"), 1)
-
-    def test_portnumber_invalid1(self):
-        print("Check that -p option is check against bogus port number (999999).")
-
-        (returncode, output, error) = self.runCommand(['../b10-dhcp4', '-p','999999'])
-
-        # When invalid port number is specified, return code must not be success
-        self.assertTrue(returncode != 0)
-
-        # Check that there is an error message about invalid port number printed on stderr
-        self.assertEqual( str(error).count("Failed to parse port number"), 1)
-
-    def test_portnumber_invalid2(self):
-        print("Check that -p option is check against bogus port number (123garbage).")
-
-        (returncode, output, error) = self.runCommand(['../b10-dhcp4', '-p','123garbage'])
-
-        # When invalid port number is specified, return code must not be success
-        self.assertTrue(returncode != 0)
-
-        # Check that there is an error message about invalid port number printed on stderr
-        self.assertEqual( str(error).count("Failed to parse port number"), 1)
-
-if __name__ == '__main__':
-    unittest.main()

Fichier diff supprimé car celui-ci est trop grand
+ 1 - 20
src/bin/dhcp6/tests/Makefile.am


+ 0 - 214
src/bin/dhcp6/tests/dhcp6_test.py

@@ -1,214 +0,0 @@
-# copyright (C) 2011,2012 Internet Systems Consortium.
-#
-# 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.
-
-from init import ProcessInfo, parse_args, dump_pid, unlink_pid_file, _BASETIME
-
-import unittest
-import sys
-import os
-import signal
-import socket
-from isc.net.addr import IPAddr
-import time
-import isc
-import fcntl
-
-class TestDhcpv6Daemon(unittest.TestCase):
-    def setUp(self):
-        # Don't redirect stdout/stderr here as we want to print out things
-        # during the test
-        #
-        # However, we do want to set the logging lock directory to somewhere
-        # to which we can write - use the current working directory.  We then
-        # set the appropriate environment variable.  os.putenv() may be not
-        # supported on some platforms as suggested in
-        # http://docs.python.org/release/3.2/library/os.html?highlight=putenv#os.environ:
-        # "If the platform supports the putenv() function...". It was checked
-        # that it does not work on Ubuntu. To overcome this problem we access
-        # os.environ directly.
-        lockdir_envvar = "B10_LOCKFILE_DIR_FROM_BUILD"
-        if lockdir_envvar not in os.environ:
-            os.environ[lockdir_envvar] = os.getcwd()
-
-    def tearDown(self):
-        pass
-
-    def readPipe(self, pipe_fd):
-        """
-        Reads bytes from a pipe and returns a character string.  If nothing is
-        read, or if there is an error, an empty string is returned.
-
-        pipe_fd - Pipe file descriptor to read
-        """
-        try:
-            data = os.read(pipe_fd, 16384)
-            # Make sure we have a string
-            if (data is None):
-                data = ""
-            else:
-                data = str(data)
-        except OSError:
-            data = ""
-
-        return data
-
-    def runCommand(self, params, wait=1):
-        """
-        This method runs a command and returns a tuple: (returncode, stdout, stderr)
-        """
-        ## @todo: Convert this into generic method and reuse it in dhcp4 and dhcp6
-
-        print("Running command: %s" % (" ".join(params)))
-
-        # redirect stdout to a pipe so we can check that our
-        # process spawning is doing the right thing with stdout
-        self.stdout_old = os.dup(sys.stdout.fileno())
-        self.stdout_pipes = os.pipe()
-        os.dup2(self.stdout_pipes[1], sys.stdout.fileno())
-        os.close(self.stdout_pipes[1])
-
-        # do the same trick for stderr:
-        self.stderr_old = os.dup(sys.stderr.fileno())
-        self.stderr_pipes = os.pipe()
-        os.dup2(self.stderr_pipes[1], sys.stderr.fileno())
-        os.close(self.stderr_pipes[1])
-
-        # note that we use dup2() to restore the original stdout
-        # to the main program ASAP in each test... this prevents
-        # hangs reading from the child process (as the pipe is only
-        # open in the child), and also insures nice pretty output
-
-        pi = ProcessInfo('Test Process', params)
-        pi.spawn()
-        time.sleep(wait)
-        os.dup2(self.stdout_old, sys.stdout.fileno())
-        os.dup2(self.stderr_old, sys.stderr.fileno())
-        self.assertNotEqual(pi.process, None)
-        self.assertTrue(type(pi.pid) is int)
-
-        # Set non-blocking read on pipes. Process may not print anything
-        # on specific output and the we would hang without this.
-        fd = self.stdout_pipes[0]
-        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
-        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
-
-        fd = self.stderr_pipes[0]
-        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
-        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
-
-        # As we don't know how long the subprocess will take to start and
-        # produce output, we'll loop and sleep for 250 ms between each
-        # iteration.  To avoid an infinite loop, we'll loop for a maximum
-        # of five seconds: that should be enough.
-        for count in range(20):
-            # Read something from stderr and stdout (these reads don't block).
-            output = self.readPipe(self.stdout_pipes[0])
-            error  = self.readPipe(self.stderr_pipes[0])
-
-            # If the process has already exited, or if it has output something,
-            # quit the loop now.
-            if pi.process.poll() is not None or len(error) > 0 or len(output) > 0:
-                break
-
-            # Process still running, try again in 250 ms.
-            time.sleep(0.25)
-
-        # Exited loop, kill the process if it is still running
-        if pi.process.poll() is None:
-            try:
-                pi.process.terminate()
-            except OSError:
-                print("Ignoring failed kill attempt. Process is dead already.")
-
-        # call this to get returncode, process should be dead by now
-        rc = pi.process.wait()
-
-        # Clean up our stdout/stderr munging.
-        os.dup2(self.stdout_old, sys.stdout.fileno())
-        os.close(self.stdout_old)
-        os.close(self.stdout_pipes[0])
-
-        os.dup2(self.stderr_old, sys.stderr.fileno())
-        os.close(self.stderr_old)
-        os.close(self.stderr_pipes[0])
-
-        # Free up resources (file descriptors) from the ProcessInfo object
-        # TODO: For some reason, this gives an error if the process has ended,
-        #       although it does cause all descriptors still allocated to the
-        #       object to be freed.
-        pi = None
-
-        print ("Process finished, return code=%d, stdout=%d bytes, stderr=%d bytes"
-               % (rc, len(output), len(error)) )
-
-        return (rc, output, error)
-
-    def test_alive(self):
-        """
-        Simple test. Checks that b10-dhcp6 can be started and prints out info
-        about starting DHCPv6 operation.
-        """
-        print("Note: Purpose of some of the tests is to check if DHCPv6 server can be started,")
-        print("      not that is can bind sockets correctly. Please ignore binding errors.")
-        (returncode, output, error) = self.runCommand(["../b10-dhcp6", "-v"])
-        output_text = str(output) + str(error)
-        self.assertEqual(output_text.count("DHCP6_STARTING"), 1)
-
-    def test_portnumber_0(self):
-        print("Check that specifying port number 0 is not allowed.")
-
-        (returncode, output, error) = self.runCommand(['../b10-dhcp6', '-p', '0'])
-
-        # When invalid port number is specified, return code must not be success
-        self.assertTrue(returncode != 0)
-
-        # Check that there is an error message about invalid port number printed on stderr
-        self.assertEqual( str(error).count("Failed to parse port number"), 1)
-
-    def test_portnumber_missing(self):
-        print("Check that -p option requires a parameter.")
-
-        (returncode, output, error) = self.runCommand(['../b10-dhcp6', '-p'])
-
-        # When invalid port number is specified, return code must not be success
-        self.assertTrue(returncode != 0)
-
-        # Check that there is an error message about invalid port number printed on stderr
-        self.assertEqual( str(error).count("option requires an argument"), 1)
-
-    def test_portnumber_invalid1(self):
-        print("Check that -p option is check against bogus port number (999999).")
-
-        (returncode, output, error) = self.runCommand(['../b10-dhcp6', '-p','999999'])
-
-        # When invalid port number is specified, return code must not be success
-        self.assertTrue(returncode != 0)
-
-        # Check that there is an error message about invalid port number printed on stderr
-        self.assertEqual( str(error).count("Failed to parse port number"), 1)
-
-    def test_portnumber_invalid2(self):
-        print("Check that -p option is check against bogus port number (123garbage).")
-
-        (returncode, output, error) = self.runCommand(['../b10-dhcp6', '-p','123garbage'])
-
-        # When invalid port number is specified, return code must not be success
-        self.assertTrue(returncode != 0)
-
-        # Check that there is an error message about invalid port number printed on stderr
-        self.assertEqual( str(error).count("Failed to parse port number"), 1)
-
-if __name__ == '__main__':
-    unittest.main()

+ 0 - 4
src/bin/msgq/.gitignore

@@ -1,4 +0,0 @@
-/b10-msgq
-/msgq.py
-/run_msgq.sh
-/b10-msgq.8

+ 0 - 49
src/bin/msgq/Makefile.am

@@ -1,49 +0,0 @@
-SUBDIRS = . tests
-
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-
-pkglibexec_SCRIPTS = b10-msgq
-
-b10_msgqdir = $(pkgdatadir)
-b10_msgq_DATA = msgq.spec
-
-CLEANFILES = b10-msgq msgq.pyc
-CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.py
-CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.pyc
-CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.pyo
-
-man_MANS = b10-msgq.8
-DISTCLEANFILES = $(man_MANS)
-EXTRA_DIST = $(man_MANS) msgq.xml msgq_messages.mes msgq.spec
-
-nodist_pylogmessage_PYTHON = $(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.py
-pylogmessagedir = $(pyexecdir)/isc/log_messages/
-BUILT_SOURCES = $(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.py
-
-if GENERATE_DOCS
-
-b10-msgq.8: msgq.xml
-	@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/msgq.xml
-
-else
-
-$(man_MANS):
-	@echo Man generation disabled.  Creating dummy $@.  Configure with --enable-generate-docs to enable it.
-	@echo Man generation disabled.  Remove this file, configure with --enable-generate-docs, and rebuild BIND 10 > $@
-
-endif
-
-# Define rule to build logging source files from message file
-$(PYTHON_LOGMSGPKG_DIR)/work/msgq_messages.py : msgq_messages.mes
-	$(top_builddir)/src/lib/log/compiler/message \
-	-d $(PYTHON_LOGMSGPKG_DIR)/work -p $(srcdir)/msgq_messages.mes
-
-# this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
-b10-msgq: msgq.py
-	$(SED) "s|@@PYTHONPATH@@|@pyexecdir@|" msgq.py >$@
-	chmod a+x $@
-
-CLEANDIRS = __pycache__
-
-clean-local:
-	rm -rf $(CLEANDIRS)

+ 0 - 12
src/bin/msgq/TODO

@@ -1,12 +0,0 @@
-== TODO for MsgQ
-
-* The code could use some refactoring.
-
-* Refactor:  Right now, the MsgQ class manages each connection using several
-lists.  There should be a Client class which holds most of this per-client
-data.  Some will need to remain in the main "driver" MsgQ class (such as the
-list of clients and their lnames) but buffer management, reading from a
-socket, etc. could all go into this client class.
-
-* More tests:  A test to send to strange locations should be added, to test
-that code path (a bug which I am committing with this file...)

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

@@ -1,886 +0,0 @@
-#!@PYTHON@
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-import sys; sys.path.append ('@@PYTHONPATH@@')
-
-"""This code implements the msgq daemon."""
-
-import subprocess
-import signal
-import os
-import socket
-import sys
-import struct
-import errno
-import time
-import select
-import random
-import threading
-import isc.config.ccsession
-from optparse import OptionParser, OptionValueError
-import isc.util.process
-import isc.util.traceback_handler
-from isc.cc.proto_defs import *
-import isc.log
-from isc.log_messages.msgq_messages import *
-
-import isc.cc
-
-isc.util.process.rename()
-
-isc.log.init("b10-msgq", buffer=True)
-# Logger that is used in the actual msgq handling - startup, shutdown and the
-# poller thread.
-logger = isc.log.Logger("msgq")
-# A separate copy for the master/config thread when the poller thread runs.
-# We use a separate instance, since the logger itself doesn't have to be
-# thread safe.
-config_logger = isc.log.Logger("msgq")
-TRACE_START = logger.DBGLVL_START_SHUT
-TRACE_BASIC = logger.DBGLVL_TRACE_BASIC
-TRACE_DETAIL = logger.DBGLVL_TRACE_DETAIL
-
-# This is the version that gets displayed to the user.
-# The VERSION string consists of the module name, the module version
-# number, and the overall BIND 10 version number (set in configure.ac).
-VERSION = "b10-msgq 20110127 (BIND 10 @PACKAGE_VERSION@)"
-
-# 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
-if "B10_FROM_SOURCE" in os.environ:
-    SPECFILE_PATH = os.environ["B10_FROM_SOURCE"] + "/src/bin/msgq"
-else:
-    PREFIX = "@prefix@"
-    DATAROOTDIR = "@datarootdir@"
-    SPECFILE_PATH = "@datadir@/@PACKAGE@".replace("${datarootdir}",
-                                                  DATAROOTDIR). \
-                                                  replace("${prefix}", PREFIX)
-SPECFILE_LOCATION = SPECFILE_PATH + "/msgq.spec"
-
-class MsgQReceiveError(Exception): pass
-
-class MsgQRunningError(Exception): pass
-
-class MsgQCloseOnReceive(Exception):
-    """Exception raised when reading data from a socket results in 'shutdown'.
-
-    This happens when msgq received 0-length data.  This class holds whether
-    it happens in the middle of reading (i.e. after reading some) via
-    partial_read parameter, which is set to True if and only if so.
-    This will be used by an upper layer catching the exception to distinguish
-    the severity of the event.
-
-    """
-    def __init__(self, reason, partial_read):
-        self.partial_read = partial_read
-        self.__reason = reason
-
-    def __str__(self):
-        return self.__reason
-
-class SubscriptionManager:
-    def __init__(self, cfgmgr_ready):
-        """
-        Initialize the subscription manager.
-        parameters:
-        * cfgmgr_ready: A callable object run once the config manager
-            subscribes. This is a hackish solution, but we can't read
-            the configuration sooner.
-        """
-        self.subscriptions = {}
-        self.__cfgmgr_ready = cfgmgr_ready
-        self.__cfgmgr_ready_called = False
-
-    def subscribe(self, group, instance, socket):
-        """Add a subscription."""
-        target = ( group, instance )
-        if target in self.subscriptions:
-            logger.debug(TRACE_BASIC, MSGQ_SUBS_APPEND_TARGET, group, instance)
-            if socket not in self.subscriptions[target]:
-                self.subscriptions[target].append(socket)
-        else:
-            logger.debug(TRACE_BASIC, MSGQ_SUBS_NEW_TARGET, group, instance)
-            self.subscriptions[target] = [ socket ]
-        if group == "ConfigManager" and not self.__cfgmgr_ready_called:
-            logger.debug(TRACE_BASIC, MSGQ_CFGMGR_SUBSCRIBED)
-            self.__cfgmgr_ready_called = True
-            self.__cfgmgr_ready()
-
-    def unsubscribe(self, group, instance, socket):
-        """Remove the socket from the one specific subscription."""
-        target = ( group, instance )
-        if target in self.subscriptions:
-            if socket in self.subscriptions[target]:
-                self.subscriptions[target].remove(socket)
-                return True
-        return False
-
-    def unsubscribe_all(self, socket):
-        """Remove the socket from all subscriptions."""
-        removed_from = []
-        for subs, socklist in self.subscriptions.items():
-            if socket in socklist:
-                socklist.remove(socket)
-                removed_from.append(subs)
-        return removed_from
-
-    def find_sub(self, group, instance):
-        """Return an array of sockets which want this specific group,
-        instance."""
-        target = (group, instance)
-        if target in self.subscriptions:
-            return self.subscriptions[target]
-        else:
-            return []
-
-    def find(self, group, instance):
-        """Return an array of sockets who should get something sent to
-        this group, instance pair.  This includes wildcard subscriptions."""
-        target = (group, instance)
-        partone = self.find_sub(group, instance)
-        parttwo = self.find_sub(group, CC_INSTANCE_WILDCARD)
-        return list(set(partone + parttwo))
-
-class MsgQ:
-    """Message Queue class."""
-    # did we find a better way to do this?
-    SOCKET_FILE = os.path.join("@localstatedir@",
-                               "@PACKAGE_NAME@",
-                               "msgq_socket").replace("${prefix}",
-                                                      "@prefix@")
-
-    def __init__(self, socket_file=None, verbose=False):
-        """Initialize the MsgQ master.
-
-        The socket_file specifies the path to the UNIX domain socket
-        that the msgq process listens on. If it is None, the
-        environment variable BIND10_MSGQ_SOCKET_FILE is used. If that
-        is not set, it will default to
-        @localstatedir@/@PACKAGE_NAME@/msg_socket.
-        If verbose is True, then the MsgQ reports
-        what it is doing.
-        """
-
-        if socket_file is None:
-            if "BIND10_MSGQ_SOCKET_FILE" in os.environ:
-                self.socket_file = os.environ["BIND10_MSGQ_SOCKET_FILE"]
-            else:
-                self.socket_file = self.SOCKET_FILE
-        else:
-            self.socket_file = socket_file
-
-        self.verbose = verbose
-        self.runnable = False
-        self.listen_socket = False
-        self.sockets = {}
-        self.connection_counter = random.random()
-        self.hostname = socket.gethostname()
-        self.subs = SubscriptionManager(self.cfgmgr_ready)
-        self.lnames = {}
-        self.fd_to_lname = {}
-        self.sendbuffs = {}
-        self.running = False
-        self.__cfgmgr_ready = None
-        self.__cfgmgr_ready_cond = threading.Condition()
-        # A lock used when the message queue does anything more complicated.
-        # It is mostly a safety measure, the threads doing so should be mostly
-        # independent, and the one with config session should be read only,
-        # but with threads, one never knows. We use threads for concurrency,
-        # not for performance, so we use wide lock scopes to be on the safe
-        # side.
-        self.__lock = threading.Lock()
-        self._session = None
-        self.__poller_sock = None
-
-    def members_notify(self, event, params):
-        """
-        Thin wrapper around ccs's notify. Send a notification about change
-        of some list that can be requested by the members command.
-
-        The event is one of:
-        - connected (client connected to MsgQ)
-        - disconected (client disconnected from MsgQ)
-        - subscribed (client subscribed to a group)
-        - unsubscribed (client unsubscribed from a group)
-
-        The params is dict containing:
-        - client: The lname of the client in question.
-        - group (for 'subscribed' and 'unsubscribed' events):
-          The group the client subscribed or unsubscribed from.
-
-        The notification occurs after the event, so client a subscribing for
-        notifications will get a notification about its own subscription, but
-        will not get a notification when it unsubscribes.
-        """
-        # Due to the interaction between threads (and fear it might influence
-        # sending stuff), we test this method in msgq_run_test, instead of
-        # mocking the ccs.
-        if self._session: # Don't send before we have started up
-            self._session.notify('cc_members', event, params)
-
-    def cfgmgr_ready(self, ready=True):
-        """Notify that the config manager is either subscribed, or
-           that the msgq is shutting down and it won't connect, but
-           anybody waiting for it should stop anyway.
-
-           The ready parameter signifies if the config manager is subscribed.
-
-           This method can be called multiple times, but second and any
-           following call is simply ignored. This means the "abort" version
-           of the call can be used on any stop unconditionally, even when
-           the config manager already connected.
-        """
-        with self.__cfgmgr_ready_cond:
-            if self.__cfgmgr_ready is not None:
-                # This is a second call to this method. In that case it does
-                # nothing.
-                return
-            self.__cfgmgr_ready = ready
-            self.__cfgmgr_ready_cond.notify_all()
-
-    def wait_cfgmgr(self):
-        """Wait for msgq to subscribe.
-
-           When this returns, the config manager is either subscribed, or
-           msgq gave up waiting for it. Success is signified by the return
-           value.
-        """
-        with self.__cfgmgr_ready_cond:
-            # Wait until it either aborts or subscribes
-            while self.__cfgmgr_ready is None:
-                self.__cfgmgr_ready_cond.wait()
-            return self.__cfgmgr_ready
-
-    def setup_listener(self):
-        """Set up the listener socket.  Internal function."""
-        logger.debug(TRACE_BASIC, MSGQ_LISTENER_SETUP, self.socket_file)
-
-        if os.path.exists(self.socket_file):
-            # Rather than just blindly removing the socket file, attempt to
-            # connect to the existing socket to see if there is an existing
-            # msgq running. Only if that fails do we remove the file and
-            # attempt to create a new socket.
-            existing_msgq = None
-            try:
-                existing_msgq = isc.cc.Session(self.socket_file)
-            except isc.cc.session.SessionError:
-                existing_msgq = None
-
-            if existing_msgq:
-                existing_msgq.close()
-                logger.fatal(MSGQ_ALREADY_RUNNING)
-                raise MsgQRunningError("b10-msgq already running")
-
-            os.remove(self.socket_file)
-
-        try:
-            self.listen_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            self.listen_socket.bind(self.socket_file)
-            self.listen_socket.listen(1024)
-        except Exception as e:
-            # remove the file again if something goes wrong
-            # (note this is a catch-all, but we reraise it)
-            if os.path.exists(self.socket_file):
-                os.remove(self.socket_file)
-            self.listen_socket.close()
-            logger.fatal(MSGQ_LISTENER_FAILED, self.socket_file, e)
-            raise e
-
-    def setup_signalsock(self):
-        """Create a socket pair used to signal when we want to finish.
-           Using a socket is easy and thread/signal safe way to signal
-           the termination.
-        """
-        # The __poller_sock will be the end in the poller. When it is
-        # closed, we should shut down.
-        (self.__poller_sock, self.__control_sock) = socket.socketpair()
-
-    def setup(self):
-        """Configure listener socket, polling, etc.
-           Raises a socket.error if the socket_file cannot be
-           created.
-        """
-
-        self.setup_signalsock()
-        self.setup_listener()
-
-        logger.debug(TRACE_START, MSGQ_LISTENER_STARTED);
-
-        self.runnable = True
-
-    def process_accept(self):
-        """Process an accept on the listening socket."""
-        newsocket, ipaddr = self.listen_socket.accept()
-        # TODO: When we have logging, we might want
-        # to add a debug message here that a new connection
-        # was made
-        self.register_socket(newsocket)
-
-    def register_socket(self, newsocket):
-        """
-        Internal function to insert a socket. Used by process_accept and some
-        tests.
-        """
-        self.sockets[newsocket.fileno()] = newsocket
-        lname = self.newlname()
-        self.lnames[lname] = newsocket
-        self.fd_to_lname[newsocket.fileno()] = lname
-
-        logger.debug(TRACE_BASIC, MSGQ_SOCKET_REGISTERED, newsocket.fileno(),
-                     lname)
-
-        self.members_notify('connected', {'client': lname})
-
-    def kill_socket(self, fd, sock):
-        """Fully close down the socket."""
-
-        unsubscribed_from = self.subs.unsubscribe_all(sock)
-        lname = self.fd_to_lname[fd]
-        del self.fd_to_lname[fd]
-        del self.lnames[lname]
-        sock.close()
-        del self.sockets[fd]
-        if fd in self.sendbuffs:
-            del self.sendbuffs[fd]
-        logger.debug(TRACE_BASIC, MSGQ_SOCK_CLOSE, fd)
-        # Filter out just the groups.
-        unsubscribed_from_groups = set(map(lambda x: x[0], unsubscribed_from))
-        for group in unsubscribed_from_groups:
-            self.members_notify('unsubscribed', {
-                                    'client': lname,
-                                    'group': group
-                                })
-        self.members_notify('disconnected', {'client': lname})
-
-    def __getbytes(self, fd, sock, length, continued):
-        """Get exactly the requested bytes, or raise an exception if
-           EOF.
-
-           continued is set to True if this method is called to complete
-           already read data.
-           """
-        received = b''
-        while len(received) < length:
-            try:
-                data = sock.recv(length - len(received))
-
-            except socket.error as err:
-                # This case includes ECONNRESET, which seems to happen when
-                # the remote client has closed its socket at some subtle
-                # timing (it should normally result in receiving empty data).
-                # Since we didn't figure out how exactly that could happen,
-                # we treat it just like other really-unexpected socket errors.
-                raise MsgQReceiveError(str(err))
-            if len(data) == 0:
-                raise MsgQCloseOnReceive("EOF", continued)
-            received += data
-            continued = True
-        return received
-
-    def read_packet(self, fd, sock):
-        """Read a correctly formatted packet.  Will raise exceptions if
-           something fails."""
-        lengths = self.__getbytes(fd, sock, 6, False)
-        overall_length, routing_length = struct.unpack(">IH", lengths)
-        if overall_length < 2:
-            raise MsgQReceiveError("overall_length < 2")
-        overall_length -= 2
-        if routing_length > overall_length:
-            raise MsgQReceiveError("routing_length > overall_length")
-        if routing_length == 0:
-            raise MsgQReceiveError("routing_length == 0")
-        data_length = overall_length - routing_length
-        # probably need to sanity check lengths here...
-        routing = self.__getbytes(fd, sock, routing_length, True)
-        if data_length > 0:
-            data = self.__getbytes(fd, sock, data_length, True)
-        else:
-            data = None
-        return (routing, data)
-
-    def process_packet(self, fd, sock):
-        """Process one packet."""
-        try:
-            routing, data = self.read_packet(fd, sock)
-        except (MsgQReceiveError, MsgQCloseOnReceive) as err:
-            # If it's MsgQCloseOnReceive and that happens without reading
-            # any data, it basically means the remote client has closed the
-            # socket, so we log it as debug information.  Otherwise, it's
-            # a somewhat unexpected event, so we consider it an "error".
-            if isinstance(err, MsgQCloseOnReceive) and not err.partial_read:
-                logger.debug(TRACE_BASIC, MSGQ_CLOSE_ON_RECV, fd)
-            else:
-                logger.error(MSGQ_RECV_ERROR, fd, err)
-            self.kill_socket(fd, sock)
-            return
-
-        try:
-            routingmsg = isc.cc.message.from_wire(routing)
-        except DecodeError as err:
-            self.kill_socket(fd, sock)
-            logger.error(MSGQ_HDR_DECODE_ERROR, fd, err)
-            return
-
-        self.process_command(fd, sock, routingmsg, data)
-
-    def process_command(self, fd, sock, routing, data):
-        """Process a single command.  This will split out into one of the
-           other functions."""
-        logger.debug(TRACE_DETAIL, MSGQ_RECV_HDR, routing)
-        cmd = routing[CC_HEADER_TYPE]
-        if cmd == CC_COMMAND_SEND:
-            self.process_command_send(sock, routing, data)
-        elif cmd == CC_COMMAND_SUBSCRIBE:
-            self.process_command_subscribe(sock, routing, data)
-        elif cmd == CC_COMMAND_UNSUBSCRIBE:
-            self.process_command_unsubscribe(sock, routing, data)
-        elif cmd == CC_COMMAND_GET_LNAME:
-            self.process_command_getlname(sock, routing, data)
-        elif cmd == CC_COMMAND_PING:
-            # Command for testing purposes
-            self.process_command_ping(sock, routing, data)
-        elif cmd == CC_COMMAND_STOP:
-            self.stop()
-        else:
-            logger.error(MSGQ_INVALID_CMD, cmd)
-
-    def preparemsg(self, env, msg = None):
-        if type(env) == dict:
-            env = isc.cc.message.to_wire(env)
-        if type(msg) == dict:
-            msg = isc.cc.message.to_wire(msg)
-        length = 2 + len(env);
-        if msg:
-            length += len(msg)
-        ret = struct.pack("!IH", length, len(env))
-        ret += env
-        if msg:
-            ret += msg
-        return ret
-
-    def sendmsg(self, sock, env, msg = None):
-        self.send_prepared_msg(sock, self.preparemsg(env, msg))
-
-    def _send_data(self, sock, data):
-        """
-        Send a piece of data to the given socket.  This method is
-        essentially "private" to MsgQ, but defined as if it were "protected"
-        for easier access from tests.
-
-        Parameters:
-        sock: The socket to send to
-        data: The list of bytes to send
-        Returns:
-        An integer or None. If an integer (which can be 0), it signals
-        the number of bytes sent. If None, the socket appears to have
-        been closed on the other end, and it has been killed on this
-        side too.
-        """
-        try:
-            # We set the socket nonblocking, MSG_DONTWAIT doesn't exist
-            # on some OSes
-            sock.setblocking(0)
-            return sock.send(data)
-        except socket.error as e:
-            if e.errno in [ errno.EAGAIN, errno.EWOULDBLOCK, errno.EINTR ]:
-                return 0
-            elif e.errno in [ errno.EPIPE, errno.ECONNRESET, errno.ENOBUFS ]:
-                # EPIPE happens if the remote module has terminated by the time
-                # of this send; its severity can vary, but in many cases it
-                # shouldn't be critical, so we log it separately as a warning.
-                if e.errno == errno.EPIPE:
-                    logger.warn(MSGQ_CLOSE_ON_SEND, sock.fileno())
-                else:
-                    logger.error(MSGQ_SEND_ERROR, sock.fileno(),
-                                 errno.errorcode[e.errno])
-                self.kill_socket(sock.fileno(), sock)
-                return None
-            else:
-                raise e
-        finally:
-            # And set it back again
-            sock.setblocking(1)
-
-    def send_prepared_msg(self, sock, msg):
-        '''
-        Add a message to the queue. If there's nothing waiting, try
-        to send it right away.
-
-        Return if the socket is still alive. It can return false if the
-        socket dies (for example due to EPIPE in the attempt to send).
-        Returning true does not guarantee the message will be delivered,
-        but returning false means it won't.
-        '''
-        # Try to send the data, but only if there's nothing waiting
-        fileno = sock.fileno()
-        if fileno in self.sendbuffs:
-            amount_sent = 0
-        else:
-            amount_sent = self._send_data(sock, msg)
-            if amount_sent is None:
-                # Socket has been killed, drop the send
-                return False
-
-        # Still something to send, add it to outgoing queue
-        if amount_sent < len(msg):
-            now = time.clock()
-            # Append it to buffer (but check the data go away)
-            if fileno in self.sendbuffs:
-                (last_sent, buff) = self.sendbuffs[fileno]
-                tdelta = now - last_sent
-                if tdelta > 0.1:
-                    logger.error(MSGQ_SOCKET_TIMEOUT_ERROR, fileno, tdelta)
-                    self.kill_socket(fileno, sock)
-                    return False
-                buff += msg
-            else:
-                buff = msg[amount_sent:]
-                last_sent = now
-            self.sendbuffs[fileno] = (last_sent, buff)
-        return True
-
-    def _process_write(self, fileno):
-        # Try to send some data from the buffer
-        (_, msg) = self.sendbuffs[fileno]
-        sock = self.sockets[fileno]
-        amount_sent = self._send_data(sock, msg)
-        if amount_sent is not None:
-            # Keep the rest
-            msg = msg[amount_sent:]
-            if len(msg) == 0:
-                # If there's no more, stop requesting for write availability
-                del self.sendbuffs[fileno]
-            else:
-                self.sendbuffs[fileno] = (time.clock(), msg)
-
-    def newlname(self):
-        """Generate a unique connection identifier for this socket.
-        This is done by using an increasing counter and the current
-        time."""
-        self.connection_counter += 1
-        return "%x_%x@%s" % (time.time(), self.connection_counter,
-                             self.hostname)
-
-    def process_command_ping(self, sock, routing, data):
-        self.sendmsg(sock, { CC_HEADER_TYPE : CC_COMMAND_PONG }, data)
-
-    def process_command_getlname(self, sock, routing, data):
-        lname = [ k for k, v in self.lnames.items() if v == sock ][0]
-        self.sendmsg(sock, { CC_HEADER_TYPE : CC_COMMAND_GET_LNAME },
-                     { CC_PAYLOAD_LNAME : lname })
-
-    def process_command_send(self, sock, routing, data):
-        group = routing[CC_HEADER_GROUP]
-        instance = routing[CC_HEADER_INSTANCE]
-        to = routing[CC_HEADER_TO]
-        if group == None or instance == None:
-            # FIXME: Should we log them instead?
-            return  # ignore invalid packets entirely
-
-        if to == CC_TO_WILDCARD:
-            sockets = self.subs.find(group, instance)
-        else:
-            if to in self.lnames:
-                sockets = [ self.lnames[to] ]
-            else:
-                sockets = []
-
-        msg = self.preparemsg(routing, data)
-
-        if sock in sockets:
-            # Don't bounce to self
-            sockets.remove(sock)
-
-        has_recipient = False
-        for socket in sockets:
-            if self.send_prepared_msg(socket, msg):
-                has_recipient = True
-        if not has_recipient and routing.get(CC_HEADER_WANT_ANSWER) and \
-            CC_HEADER_REPLY not in routing:
-            # We have no recipients. But the sender insists on a reply
-            # (and the message isn't a reply itself). We need to send
-            # an error to satisfy the request, since there's nobody
-            # else who can.
-            #
-            # We omit the replies on purpose. The recipient might generate
-            # the response by copying and mangling the header of incoming
-            # message (just like we do below) and would include the want_answer
-            # by accident. And we want to avoid loops of errors. Also, it
-            # is unclear if the knowledge of undeliverable reply would be
-            # of any use to the sender, and it should be much rarer situation.
-
-            # The real errors would be positive, 1 most probably. We use
-            # negative errors for delivery errors to distinguish them a
-            # little. We probably should have a way to provide more data
-            # in the error message.
-            payload = isc.config.ccsession.create_answer(CC_REPLY_NO_RECPT,
-                                                         "No such recipient")
-            # We create the header based on the current one. But we don't
-            # want to mangle it for the caller, so we get a copy. A shallow
-            # one should be enough, we modify the dict only.
-            header = routing.copy()
-            header[CC_HEADER_REPLY] = routing[CC_HEADER_SEQ]
-            # Dummy lname not assigned to clients
-            header[CC_HEADER_FROM] = "msgq"
-            header[CC_HEADER_TO] = routing[CC_HEADER_FROM]
-            # We keep the seq as it is. We don't need to track the message
-            # and we will not confuse the sender. The sender would use an
-            # unique id for each message, so we won't return one twice to it.
-            errmsg = self.preparemsg(header, payload)
-            # Send it back.
-            self.send_prepared_msg(sock, errmsg)
-
-    def process_command_subscribe(self, sock, routing, data):
-        group = routing[CC_HEADER_GROUP]
-        instance = routing[CC_HEADER_INSTANCE]
-        if group == None or instance == None:
-            return  # ignore invalid packets entirely
-        self.subs.subscribe(group, instance, sock)
-        lname = self.fd_to_lname[sock.fileno()]
-        self.members_notify('subscribed',
-                            {
-                                'client': lname,
-                                'group': group
-                            })
-
-    def process_command_unsubscribe(self, sock, routing, data):
-        group = routing[CC_HEADER_GROUP]
-        instance = routing[CC_HEADER_INSTANCE]
-        if group == None or instance == None:
-            return  # ignore invalid packets entirely
-        if self.subs.unsubscribe(group, instance, sock):
-            lname = self.fd_to_lname[sock.fileno()]
-            self.members_notify('unsubscribed',
-                                {
-                                    'client': lname,
-                                    'group': group
-                                })
-
-    def run(self):
-        """Process messages.  Forever.  Mostly."""
-        self.running = True
-
-        self.run_select()
-
-    def run_select(self):
-        while self.running:
-            reads = list(self.fd_to_lname.keys())
-            if self.listen_socket.fileno() != -1: # Skip in tests
-                reads.append(self.listen_socket.fileno())
-            if self.__poller_sock and self.__poller_sock.fileno() != -1:
-                reads.append(self.__poller_sock.fileno())
-            writes = list(self.sendbuffs.keys())
-            (read_ready, write_ready) = ([], [])
-            try:
-                (read_ready, write_ready, _) = select.select(reads, writes,
-                                                             []);
-            except select.error as err:
-                if err.args[0] == errno.EINTR:
-                    continue # Just try it again if interrupted.
-                else:
-                    logger.fatal(MSGQ_SELECT_ERROR, err)
-                    break
-            with self.__lock:
-                write_ready = set(write_ready)
-                for fd in read_ready:
-                    # Do only one operation per loop iteration on the given fd.
-                    # It could be possible to perform both, but it may have
-                    # undesired side effects in special situations (like, if the
-                    # read closes the socket).
-                    if fd in write_ready:
-                        write_ready.remove(fd)
-                    if fd == self.listen_socket.fileno():
-                        self.process_accept()
-                    elif self.__poller_sock and fd == \
-                        self.__poller_sock.fileno():
-                        # The signal socket. We should terminate now.
-                        self.running = False
-                        break
-                    else:
-                        self.process_packet(fd, self.sockets[fd])
-                for fd in write_ready:
-                    self._process_write(fd)
-
-    def stop(self):
-        # Signal it should terminate.
-        self.__control_sock.close()
-        self.__control_sock = None
-        # Abort anything waiting on the condition, just to make sure it's not
-        # blocked forever
-        self.cfgmgr_ready(False)
-
-    def cleanup_signalsock(self):
-        """Close the signal sockets. We could do it directly in shutdown,
-           but this part is reused in tests.
-        """
-        if self.__poller_sock:
-            self.__poller_sock.close()
-            self.__poller_sock = None
-        if self.__control_sock:
-            self.__control_sock.close()
-            self.__control_sock = None
-
-    def shutdown(self):
-        """Stop the MsgQ master."""
-        logger.debug(TRACE_START, MSGQ_SHUTDOWN)
-        self.listen_socket.close()
-        self.cleanup_signalsock()
-        # Close all the sockets too. In real life, there should be none now,
-        # as Msgq should be the last one. But some tests don't adhere to this
-        # and create a new Msgq for each test, which led to huge socket leaks.
-        # Some other threads put some other things in instead of sockets, so
-        # we catch whatever exceptions there we can. This should be safe,
-        # because in real operation, we will terminate now anyway, implicitly
-        # closing anything anyway.
-        for sock in self.sockets.values():
-            try:
-                sock.close()
-            except Exception:
-                pass
-        if os.path.exists(self.socket_file):
-            os.remove(self.socket_file)
-
-    def config_handler(self, new_config):
-        """The configuration handler (run in a separate thread).
-           Not tested, currently effectively empty.
-        """
-        config_logger.debug(TRACE_DETAIL, MSGQ_CONFIG_DATA, new_config)
-
-        with self.__lock:
-            if not self.running:
-                return
-
-            # TODO: Any config handling goes here.
-
-            return isc.config.create_answer(0)
-
-    def command_handler(self, command, args):
-        """The command handler (run in a separate thread)."""
-        config_logger.debug(TRACE_DETAIL, MSGQ_COMMAND, command, args)
-
-        with self.__lock:
-            if not self.running:
-                return
-
-            # TODO: Who does validation? The ModuleCCSession or must we?
-
-            if command == 'members':
-                # List all members of MsgQ or of a group.
-                if args is None:
-                    args = {}
-                group = args.get('group')
-                if group:
-                    return isc.config.create_answer(0,
-                        list(map(lambda sock: self.fd_to_lname[sock.fileno()],
-                                 self.subs.find(group, ''))))
-                else:
-                    return isc.config.create_answer(0,
-                                                    list(self.lnames.keys()))
-
-            config_logger.error(MSGQ_COMMAND_UNKNOWN, command)
-            return isc.config.create_answer(1, 'unknown command: ' + command)
-
-def signal_handler(msgq, signal, frame):
-    if msgq:
-        msgq.stop()
-
-def main():
-    def check_port(option, opt_str, value, parser):
-        """Function to insure that the port we are passed is actually
-        a valid port number. Used by OptionParser() on startup."""
-        intval = int(value)
-        if (intval < 0) or (intval > 65535):
-            raise OptionValueError("%s requires a port number (0-65535)" %
-                                   opt_str)
-        parser.values.msgq_port = intval
-
-    # Parse any command-line options.
-    parser = OptionParser(version=VERSION)
-    # TODO: Should we remove the option?
-    parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
-                      help="display more about what is going on")
-    parser.add_option("-s", "--socket-file", dest="msgq_socket_file",
-                      type="string", default=None,
-                      help="UNIX domain socket file the msgq daemon will use")
-    (options, args) = parser.parse_args()
-
-    # Announce startup.
-    logger.debug(TRACE_START, MSGQ_START, VERSION)
-
-    msgq = MsgQ(options.msgq_socket_file, options.verbose)
-
-    signal.signal(signal.SIGTERM,
-                  lambda signal, frame: signal_handler(msgq, signal, frame))
-
-    # Ignore SIGPIPE. We handle errors writing to children using try in the
-    # appropriate places and the delivery of a signal is very heavy handed.
-    # Windows doesn't support SIGPIPE so don't try it there.
-    if not sys.platform.startswith('win'):
-        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
-
-    try:
-        msgq.setup()
-    except Exception as e:
-        logger.fatal(MSGQ_START_FAIL, e)
-        sys.exit(1)
-
-    # We run the processing in a separate thread. This is because we want to
-    # connect to the msgq ourself. But the cc library is unfortunately blocking
-    # in many places and waiting for the processing part to answer, it would
-    # deadlock.
-    poller_thread = threading.Thread(target=msgq.run)
-    poller_thread.daemon = True
-    try:
-        poller_thread.start()
-        if msgq.wait_cfgmgr():
-            # Once we get the config manager, we can read our own config.
-            session = isc.config.ModuleCCSession(SPECFILE_LOCATION,
-                                                 msgq.config_handler,
-                                                 msgq.command_handler,
-                                                 None, True,
-                                                 msgq.socket_file)
-            msgq._session = session
-            session.start()
-            # And we create a thread that'll just wait for commands and
-            # handle them. We don't terminate the thread, we set it to
-            # daemon. Once the main thread terminates, it'll just die.
-            def run_session():
-                while True:
-                    # As the check_command has internal mutex that is shared
-                    # with sending part (which includes notify). So we don't
-                    # want to hold it long-term and block using select.
-                    fileno = session.get_socket().fileno()
-                    try:
-                        (reads, _, _) = select.select([fileno], [], [])
-                    except select.error as se:
-                        if se.args[0] != errno.EINTR:
-                            raise
-                    session.check_command(True)
-            background_thread = threading.Thread(target=run_session)
-            background_thread.daemon = True
-            background_thread.start()
-        poller_thread.join()
-    except KeyboardInterrupt:
-        pass
-
-    msgq.shutdown()
-
-    logger.info(MSGQ_EXITING)
-
-if __name__ == "__main__":
-    isc.util.traceback_handler.traceback_handler(main)

+ 0 - 20
src/bin/msgq/msgq.spec

@@ -1,20 +0,0 @@
-{
-  "module_spec": {
-    "module_name": "Msgq",
-    "module_description": "The message queue",
-    "config_data": [],
-    "commands": [
-      {
-        "command_name": "members",
-        "command_description": "Provide the list of members of a group or of the whole MsgQ if no group is given.",
-        "command_args": [
-          {
-            "item_name": "group",
-            "item_optional": true,
-            "item_type": "string"
-          }
-        ]
-      }
-    ]
-  }
-}

+ 0 - 169
src/bin/msgq/msgq.xml

@@ -1,169 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-	       [<!ENTITY mdash "&#8212;">]>
-<!--
- - Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
- -
- - Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
- - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- - AND FITNESS.  IN NO EVENT SHALL ISC 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.
--->
-
-<refentry>
-
-  <refentryinfo>
-    <date>June 25, 2012</date>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>b10-msgq</refentrytitle>
-    <manvolnum>8</manvolnum>
-    <refmiscinfo>BIND10</refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>b10-msgq</refname>
-    <refpurpose>message routing daemon for the Command Channel</refpurpose>
-  </refnamediv>
-
-  <docinfo>
-    <copyright>
-      <year>2010</year>
-      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
-    </copyright>
-  </docinfo>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>b10-msgq</command>
-      <arg><option>-s <replaceable>file</replaceable></option></arg>
-      <arg><option>-v</option></arg>
-      <arg><option>--socket-file <replaceable>file</replaceable></option></arg>
-      <arg><option>--verbose</option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>DESCRIPTION</title>
-    <para>
-      The <command>b10-msgq</command>
-      daemon provides message routing for the Command Channel.
-    </para>
-
-    <para>
-      The Command Channel is a message bus and subscription manager.
-      Programs may subscribe to certain groups to receive messages
-      for that group.
-      Every new connection to <command>b10-msgq</command> is
-      assigned a unique identifier -- this is the local name.
-      The commands it handles are:
-      <itemizedlist>
-
-      <listitem><para>
-        <command>getlname</command>
-        &mdash; receive local name.
-      </para></listitem>
-
-      <listitem><para>
-        <command>send</command>
-        &mdash; send a message to defined subscribers.
-      </para></listitem>
-
-      <listitem><para>
-        <command>subscribe</command>
-	&mdash; add a subscription. This means it is a listener
-	for messages for a specific group.
-      </para></listitem>
-
-      <listitem><para>
-        <command>unsubscribe</command>
-        &mdash; remove a subscription.
-      </para></listitem>
-
-      </itemizedlist>
-    </para>
-
-    <para>
-      The <command>b10-msgq</command> daemon may be cleanly stopped by
-      sending the SIGTERM signal to the process.
-      This shutdown does not notify the subscribers.
-    </para>
-
-  </refsect1>
-
-  <refsect1>
-    <title>OPTIONS</title>
-
-    <para>The arguments are as follows:</para>
-
-    <variablelist>
-      <varlistentry>
-        <term><option>-s <replaceable>file</replaceable></option>,
-          <option>--socket-file <replaceable>file</replaceable></option></term>
-        <listitem><para>
-          The UNIX domain socket file this daemon will use.
-          The default is
-          <filename>/usr/local/var/bind10/msg_socket</filename>.
-<!-- @localstatedir@/@PACKAGE_NAME@/msg_socket -->
-          </para></listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><option>-v</option>, <option>--verbose</option></term>
-        <listitem><para>
-          Enabled verbose mode. This enables diagnostic messages to
-          STDERR.  Displays more about what <command>b10-msgq</command>
-          is doing.
-<!-- TODO: is STDERR correct? -->
-        </para></listitem>
-      </varlistentry>
-
-    </variablelist>
-
-  </refsect1>
-
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>b10-init</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citetitle>BIND 10 Guide</citetitle>.
-    </para>
-<!-- TODO: point to developer docs -->
-  </refsect1>
-
-  <refsect1>
-    <title>AUTHORS</title>
-    <para>
-      The <command>b10-msgq</command> daemon and Control Channel specification
-      were initially designed by Michael Graff of ISC.
-    </para>
-  </refsect1>
-
-  <refsect1>
-    <title>HISTORY</title>
-    <para>
-       The python version was first coded in December 2009.
-       The C version with now deprecated wire format was coded in September
-       2009.
-    </para>
-  </refsect1>
-
-</refentry><!--
- - Local variables:
- - mode: sgml
- - End:
--->
-

+ 0 - 154
src/bin/msgq/msgq_messages.mes

@@ -1,154 +0,0 @@
-# Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
-#
-# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
-# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-# AND FITNESS.  IN NO EVENT SHALL ISC 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.
-
-# No namespace declaration - these constants go in the global namespace
-# of the ddns messages python module.
-
-# When you add a message to this file, it is a good idea to run
-# <topsrcdir>/tools/reorder_message_file.py to make sure the
-# messages are in the correct order.
-
-% MSGQ_ALREADY_RUNNING Another copy of b10-msgq is already running.
-Only a single instance of b10-msgq should ever be run at one time.
-This instance will now terminate.
-
-% MSGQ_CFGMGR_SUBSCRIBED The config manager subscribed to message queue
-This is a debug message. The message queue has little bit of special handling
-for the configuration manager. This special handling is happening now.
-
-% MSGQ_CLOSE_ON_RECV Reading from socket canceled as it's closed: FD=%1
-A debug message.  The msgq daemon was notified of a read event on a
-socket, but its initial read operation failed because the remote
-client has closed its socket.  This is possible in a normal operation
-when a module shuts down.
-
-% MSGQ_CLOSE_ON_SEND Sending to socket failed as already closed (okay to ignore on shutdown): FD=%1
-The msgq daemon tries to send some data to a client module, but it
-failed because the socket has been closed.  This normally means the
-client terminates (for some reason - either gracefully or as a crash)
-while other modules try to send a message to the terminated module.
-Since msgq doesn't keep track of the status of client modules, this
-can happen and is not really an error for msgq; however, it can still
-be an unexpected event for the BIND 10 system as a whole in that this
-particular message is lost, so it's logged as a warning.  If this
-message is logged for a running BIND 10 system, it's suggested to
-check other log messages; there may be an error from other modules
-reporting a missing response message.  One common, less critical case
-where this message is logged is during shutdown.  The ordering of
-process shutdown is basically arbitrary at this moment, so it's
-possible that some module tries to send a "quitting" message to some
-other module but the latter has already shut down.  Such cases are
-generally non critical, but you may want to check other possible error
-messages.
-
-% MSGQ_COMMAND Running command %1 with arguments %2
-Debug message. The message queue received a command and it is running it.
-
-% MSGQ_COMMAND_UNKNOWN Unknown command '%1'
-The message queue received a command from other module, but it doesn't
-recognize it. This is probably either a coding error or inconsistency between
-the message queue version and version of the module.
-
-% MSGQ_CONFIG_DATA Received configuration update for the msgq: %1
-Debug message. The message queue received a configuration update, handling it.
-
-% MSGQ_EXITING exiting
-The msgq daemon is exiting.
-
-% MSGQ_HDR_DECODE_ERROR Error decoding header received from socket %1: %2
-The socket with mentioned file descriptor sent a packet. However, it was not
-possible to decode the routing header of the packet. The packet is ignored.
-This may be caused by a programmer error (one of the components sending invalid
-data) or possibly by incompatible version of msgq and the component (but that's
-unlikely, as the protocol is not changed often).
-
-% MSGQ_INVALID_CMD Received invalid command: %1
-An unknown command listed in the log has been received. It is ignored. This
-indicates either a programmer error (eg. a typo in the command name) or
-incompatible version of a module and message queue daemon.
-
-% MSGQ_LISTENER_FAILED Failed to initialize listener on socket file '%1': %2
-The message queue daemon tried to listen on a file socket (the path is in the
-message), but it failed. The error from the operating system is logged.
-
-% MSGQ_LISTENER_SETUP Starting to listen on socket file '%1'
-Debug message. The listener is trying to open a listening socket.
-
-% MSGQ_LISTENER_STARTED Successfully started to listen
-Debug message. The message queue successfully opened a listening socket and
-waits for incoming connections.
-
-% MSGQ_RECV_ERROR Error reading from socket %1: %2
-There was a low-level error when reading from a socket. The error is logged and
-the corresponding socket is dropped.  The errors include receiving
-broken or (non empty but) incomplete data.  In either case it usually suggests
-something unexpected happens within the BIND 10 system; it's probably
-better to restart the system, and if it continues it should be
-reported as a bug.  One known, probably non critical case is
-the "connection reset by peer" (or its variants) socket error appearing
-on shutdown.  It's known this happens when the remote client closes the
-connection as part of shutdown process.  Such cases are normally expected
-to be reported as receiving empty data (which we log it at the debug level
-as the MSGQ_CLOSE_ON_RECV message), but for some (yet) unknown reason
-it can also be reported as the system error.  At shutdown time it's expected
-that connections are closed, so it's probably safe to ignore these messages
-in such a case.  We still log them as an error as we've not figured out
-how exactly that can happen.  In future, we may make the shutdown process
-more robust so the msgq daemon can explicitly know when a client shuts down
-more reliably.  If and when it's implemented this error message won't appear
-on shutdown unless there's really something unexpected.
-
-% MSGQ_RECV_HDR Received header: %1
-Debug message. This message includes the whole routing header of a packet.
-
-% MSGQ_SELECT_ERROR Error while waiting for events: %1
-A low-level error happened when waiting for events, the error is logged. The
-reason for this varies, but it usually means the system is short on some
-resources.
-
-% MSGQ_SEND_ERROR Error while sending to socket %1: %2
-There was a low-level error when sending data to a socket. The error is logged
-and the corresponding socket is dropped.
-
-% MSGQ_SHUTDOWN Stopping Msgq
-Debug message. The message queue is shutting down.
-
-% MSGQ_SOCKET_REGISTERED Registered a socket descriptor %1 with lname %2
-Debug message. The msgq daemon accepted a session request on the
-shown descriptor of socket and assigned a unique identifier (lname)
-for the client on that socket.
-
-% MSGQ_SOCKET_TIMEOUT_ERROR Killing socket %1 because timeout exceeded (%2)
-Outgoing data was queued up on a socket connected to msgq, but the other
-side is not reading it. It could be deadlocked, or may not be monitoring
-it. Both cases are programming errors and should be corrected. The socket
-is closed on the msgq side.
-
-% MSGQ_SOCK_CLOSE Closing socket fd %1
-Debug message. Closing the mentioned socket.
-
-% MSGQ_START Msgq version %1 starting
-Debug message. The message queue is starting up.
-
-% MSGQ_START_FAIL Error during startup: %1
-There was an error during early startup of the daemon. More concrete error is
-in the log. The daemon terminates as a result.
-
-% MSGQ_SUBS_APPEND_TARGET Appending to existing target for subscription to group '%1' for instance '%2'
-Debug message. Creating a new subscription by appending it to already existing
-data structure.
-
-% MSGQ_SUBS_NEW_TARGET Creating new target for subscription to group '%1' for instance '%2'
-Debug message. Creating a new subscription. Also creating a new data structure
-to hold it.

+ 0 - 46
src/bin/msgq/run_msgq.sh.in

@@ -1,46 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2010  Internet Systems Consortium.
-#
-# 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.
-
-PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
-export PYTHON_EXEC
-
-MYPATH_PATH=@abs_top_builddir@/src/bin/msgq
-
-PYTHONPATH=@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python/isc/cc:@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs
-export PYTHONPATH
-
-# If necessary (rare cases), explicitly specify paths to dynamic libraries
-# required by loadable python modules.
-SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
-if test $SET_ENV_LIBRARY_PATH = yes; then
-    @ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/acl/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:@abs_top_builddir@/src/lib/datasrc/.libs:$@ENV_LIBRARY_PATH@
-    export @ENV_LIBRARY_PATH@
-fi
-
-B10_FROM_SOURCE=@abs_top_srcdir@
-export B10_FROM_SOURCE
-# TODO: We need to do this feature based (ie. no general from_source)
-# But right now we need a second one because some spec files are
-# generated and hence end up under builddir
-B10_FROM_BUILD=@abs_top_builddir@
-export B10_FROM_BUILD
-
-BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
-export BIND10_MSGQ_SOCKET_FILE
-
-cd ${MYPATH_PATH}
-exec ${PYTHON_EXEC} -O b10-msgq "$@"

+ 0 - 1
src/bin/msgq/tests/.gitignore

@@ -1 +0,0 @@
-/msgq_test

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


Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff