Commit d05d7aa3 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[master] Merge branch 'trac2854'

parents 10955067 cef64b54
......@@ -1192,6 +1192,8 @@ AC_CONFIG_FILES([Makefile
src/bin/loadzone/Makefile
src/bin/loadzone/tests/Makefile
src/bin/loadzone/tests/correct/Makefile
src/bin/memmgr/Makefile
src/bin/memmgr/tests/Makefile
src/bin/msgq/Makefile
src/bin/msgq/tests/Makefile
src/bin/auth/Makefile
......@@ -1264,6 +1266,8 @@ AC_CONFIG_FILES([Makefile
src/lib/python/isc/bind10/tests/Makefile
src/lib/python/isc/ddns/Makefile
src/lib/python/isc/ddns/tests/Makefile
src/lib/python/isc/memmgr/Makefile
src/lib/python/isc/memmgr/tests/Makefile
src/lib/python/isc/xfrin/Makefile
src/lib/python/isc/xfrin/tests/Makefile
src/lib/python/isc/server_common/Makefile
......@@ -1377,6 +1381,8 @@ AC_OUTPUT([doc/version.ent
src/bin/loadzone/loadzone.py
src/bin/usermgr/run_b10-cmdctl-usermgr.sh
src/bin/usermgr/b10-cmdctl-usermgr.py
src/bin/memmgr/memmgr.py
src/bin/memmgr/memmgr.spec.pre
src/bin/msgq/msgq.py
src/bin/msgq/run_msgq.sh
src/bin/auth/auth.spec.pre
......@@ -1395,6 +1401,7 @@ AC_OUTPUT([doc/version.ent
src/lib/python/isc/notify/tests/notify_out_test
src/lib/python/isc/log/tests/log_console.py
src/lib/python/isc/log_messages/work/__init__.py
src/lib/python/isc/server_common/bind10_server.py
src/lib/dns/gen-rdatacode.py
src/lib/python/bind10_config.py
src/lib/cc/session_config.h.pre
......
SUBDIRS = bind10 bindctl cfgmgr ddns loadzone msgq cmdctl auth xfrin \
xfrout usermgr zonemgr stats tests resolver sockcreator dhcp4 dhcp6 d2\
dbutil sysinfo
dbutil sysinfo memmgr
check-recursive: all-recursive
......@@ -20,7 +20,7 @@ export PYTHON_EXEC
BIND10_PATH=@abs_top_builddir@/src/bin/bind10
PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:@abs_top_builddir@/src/bin/ddns:@abs_top_builddir@/src/bin/dhcp6:@abs_top_builddir@/src/bin/sockcreator:$PATH
PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:@abs_top_builddir@/src/bin/ddns:@abs_top_builddir@/src/bin/dhcp6:@abs_top_builddir@/src/bin/sockcreator:@abs_top_builddir@/src/bin/memmgr:$PATH
export PATH
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
......
/b10-memmgr
/memmgr.py
/memmgr.spec
/b10-memmgr.8
SUBDIRS = . tests
pkglibexecdir = $(libexecdir)/@PACKAGE@
pkglibexec_SCRIPTS = b10-memmgr
b10_memmgrdir = $(pkgdatadir)
b10_memmgr_DATA = memmgr.spec
nodist_pylogmessage_PYTHON = $(PYTHON_LOGMSGPKG_DIR)/work/memmgr_messages.py
pylogmessagedir = $(pyexecdir)/isc/log_messages/
CLEANFILES = b10-memmgr memmgr.pyc
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/memmgr_messages.py
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/memmgr_messages.pyc
CLEANFILES += memmgr.spec
EXTRA_DIST = memmgr_messages.mes
man_MANS = b10-memmgr.8
DISTCLEANFILES = $(man_MANS)
EXTRA_DIST += $(man_MANS) b10-memmgr.xml
if GENERATE_DOCS
b10-memmgr.8: b10-memmgr.xml
@XSLTPROC@ --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-memmgr.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/memmgr_messages.py : memmgr_messages.mes
$(top_builddir)/src/lib/log/compiler/message \
-d $(PYTHON_LOGMSGPKG_DIR)/work -p $(srcdir)/memmgr_messages.mes
memmgr.spec: memmgr.spec.pre
$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" memmgr.spec.pre > $@
# this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
b10-memmgr: memmgr.py $(PYTHON_LOGMSGPKG_DIR)/work/memmgr_messages.py
$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" memmgr.py >$@
chmod a+x $@
CLEANDIRS = __pycache__
# install the default directory for memory-mapped files. Note that the
# path must be identical to the default value in memmgr.spec. We'll make
# it readable only for the owner to minimize the risk of accidents.
install-data-local:
$(mkinstalldirs) $(DESTDIR)@localstatedir@/@PACKAGE@/mapped_files
install-data-hook:
-chmod 700 $(DESTDIR)@localstatedir@/@PACKAGE@/mapped_files
clean-local:
rm -rf $(CLEANDIRS)
<!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>June 11, 2013</date>
</refentryinfo>
<refmeta>
<refentrytitle>b10-memmgr</refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo>BIND10</refmiscinfo>
</refmeta>
<refnamediv>
<refname>b10-memmgr</refname>
<refpurpose>BIND 10 memory manager daemon</refpurpose>
</refnamediv>
<docinfo>
<copyright>
<year>2013</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
<refsynopsisdiv>
<cmdsynopsis>
<command>b10-memmgr</command>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>The <command>b10-memmgr</command> daemon manages shared
memory segments storing in-memory DNS zone data, and
communicates with other BIND 10 modules about the segment
information so the entire system will use these segments
in a consistent manner.
</para>
</refsect1>
<refsect1>
<title>ARGUMENTS</title>
<para>The <command>b10-memmgr</command> daemon does not take
any command line arguments.
</para>
</refsect1>
<refsect1>
<title>CONFIGURATION AND COMMANDS</title>
<para>
The configurable settings are:
</para>
<para>
<varname>mapped_file_dir</varname>
A path to store files to be mapped to memory. This must be
writable to the <command>b10-memmgr</command> daemon.
</para>
<para>
The module commands are:
</para>
<para>
<command>shutdown</command> exits <command>b10-memmgr</command>.
</para>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>
<citerefentry>
<refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<citetitle>BIND 10 Guide</citetitle>.
</para>
</refsect1>
<refsect1>
<title>HISTORY</title>
<para>
The <command>b10-memmgr</command> daemon was first implemented
in 2013 for the ISC BIND 10 project.
</para>
</refsect1>
</refentry><!--
- Local variables:
- mode: sgml
- End:
-->
#!@PYTHON@
# Copyright (C) 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.
import copy
import os
import sys
import signal
sys.path.append('@@PYTHONPATH@@')
import isc.log
from isc.config import ModuleSpecError, ModuleCCSessionError
from isc.log_messages.memmgr_messages import *
from isc.server_common.bind10_server import BIND10Server, BIND10ServerFatal
from isc.server_common.datasrc_clients_mgr \
import DataSrcClientsMgr, ConfigError
from isc.memmgr.datasrc_info import DataSrcInfo
import isc.util.process
MODULE_NAME = 'memmgr'
isc.log.init('b10-memmgr', buffer=True)
logger = isc.log.Logger(MODULE_NAME)
isc.util.process.rename()
class ConfigError(Exception):
"""An exception class raised for configuration errors of Memmgr."""
pass
class Memmgr(BIND10Server):
def __init__(self):
# Running configurable parameters: on initial configuration this will
# be a dict: str=>config_value.
# This is defined as "protected" so tests can inspect it; others
# shouldn't use it directly.
self._config_params = None
# The manager to keep track of data source configuration. Allow
# tests to inspect/tweak it.
self._datasrc_clients_mgr = DataSrcClientsMgr(use_cache=True)
# List of DataSrcInfo. Used as a queue to maintain info for all
# active configuration generations. Allow tests to inspec it.
self._datasrc_info_list = []
def _config_handler(self, new_config):
"""Configuration handler, called via BIND10Server.
This method must be exception free. We assume minimum validity
about the parameter, though: it should be a valid dict, and conform
to the type specification of the spec file.
"""
logger.debug(logger.DBGLVL_TRACE_BASIC, MEMMGR_CONFIG_UPDATE)
# Default answer:
answer = isc.config.create_answer(0)
# If this is the first time, initialize the local attributes with the
# latest full config data, which consist of the defaults with
# possibly overridden by user config. Otherwise, just apply the latest
# diff.
if self._config_params is None:
new_config = self.mod_ccsession.get_full_config()
try:
self.__update_config(new_config)
except Exception as ex:
logger.error(MEMMGR_CONFIG_FAIL, ex)
answer = isc.config.create_answer(
1, 'Memmgr failed to apply configuration updates: ' + str(ex))
return answer
def __update_config(self, new_config):
"""Apply config changes to local attributes.
This is a subroutine of _config_handler. It's supposed to provide
strong exception guarantee: either all changes successfully apply
or, if any error is found, none applies. In the latter case the
entire original configuration should be kept.
Errors are to be reported as an exception.
"""
# If this is the first time, build everything from the scratch.
# Otherwise, make a full local copy and update it.
if self._config_params is None:
new_config_params = {}
else:
new_config_params = copy.deepcopy(self._config_params)
new_mapped_file_dir = new_config.get('mapped_file_dir')
if new_mapped_file_dir is not None:
if not os.path.isdir(new_mapped_file_dir):
raise ConfigError('mapped_file_dir is not a directory: ' +
new_mapped_file_dir)
if not os.access(new_mapped_file_dir, os.W_OK):
raise ConfigError('mapped_file_dir is not writable: ' +
new_mapped_file_dir)
new_config_params['mapped_file_dir'] = new_mapped_file_dir
# All copy, switch to the new configuration.
self._config_params = new_config_params
def _setup_module(self):
"""Module specific initialization for BIND10Server."""
try:
# memmgr isn't usable if data source is not configured, and
# as long as cfgmgr is ready there's no timing issue. So we
# immediately shut it down if it's missing. See ddns.py.in
# about exceptions to catch.
self.mod_ccsession.add_remote_config_by_name(
'data_sources', self._datasrc_config_handler)
except (ModuleSpecError, ModuleCCSessionError) as ex:
logger.error(MEMMGR_NO_DATASRC_CONF, ex)
raise BIND10ServerFatal('failed to setup memmgr module')
def _datasrc_config_handler(self, new_config, config_data):
"""Callback of data_sources configuration update.
This method must be exception free, so we catch all expected
exceptions internally; unexpected ones should mean a programming
error and will terminate the program.
"""
try:
self._datasrc_clients_mgr.reconfigure(new_config, config_data)
genid, clients_map = self._datasrc_clients_mgr.get_clients_map()
datasrc_info = DataSrcInfo(genid, clients_map, self._config_params)
self._datasrc_info_list.append(datasrc_info)
# Full datasrc reconfig will be rare, so would be worth logging
# at the info level.
logger.info(MEMMGR_DATASRC_RECONFIGURED, genid)
except isc.server_common.datasrc_clients_mgr.ConfigError as ex:
logger.error(MEMMGR_DATASRC_CONFIG_ERROR, ex)
if '__main__' == __name__:
mgr = Memmgr()
sys.exit(mgr.run(MODULE_NAME))
{
"module_spec": {
"module_name": "Memmgr",
"config_data": [
{ "item_name": "mapped_file_dir",
"item_type": "string",
"item_optional": true,
"item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/mapped_files"
}
],
"commands": [
{
"command_name": "shutdown",
"command_description": "Shut down Memmgr",
"command_args": [
{
"item_name": "pid",
"item_type": "integer",
"item_optional": true
}
]
}
]
}
}
# 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.
# 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.
% MEMMGR_CONFIG_FAIL failed to apply configuration updates: %1
The memmgr daemon tried to apply configuration updates but found an error.
The cause of the error is included in the message. None of the received
updates applied, and the daemon keeps running with the previous configuration.
% MEMMGR_CONFIG_UPDATE received new configuration
A debug message. The memmgr daemon receives configuratiopn updates
and is now applying them to its running configurations.
% MEMMGR_DATASRC_CONFIG_ERROR failed to update data source configuration: %1
Configuration for the global data sources is updated, but the update
cannot be applied to memmgr. The memmgr module will still keep running
with the previous configuration, but the cause of the failure and
other log messages must be carefully examined because if only memmgr
rejects the new configuration then the entire BIND 10 system will have
inconsistent state among different modules. If other modules accept
the update but memmgr produces this error, it's quite likely that the
system isn't working as expected, and is probably better to be shut down
to figure out and fix the cause.
% MEMMGR_DATASRC_RECONFIGURED data source configuration has been updated, generation ID %1
The memmgr daemon received a new version of data source configuration,
and has successfully applied it to the local state. Loading of new zone
data into memory will possibly take place.
% MEMMGR_NO_DATASRC_CONF failed to add data source configuration: %1
The memmgr daemon tried to incorporate data source configuration on
its startup but failed to do so. Due to internal implementation
details this shouldn't happen as long as the BIND 10 system has been
installed correctly. So, if this error message is logged, you should
probably reinstall the entire system, preferably from the scratch, and
see if it still happens. The memmgr daemon cannot do any meaningful
work without data sources, so it immediately terminates itself.
PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
PYTESTS = memmgr_test.py
EXTRA_DIST = $(PYTESTS)
# If necessary (rare cases), explicitly specify paths to dynamic libraries
# required by loadable python modules.
LIBRARY_PATH_PLACEHOLDER =
if SET_ENV_LIBRARY_PATH
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.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/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$(abs_top_builddir)/src/lib/datasrc/.libs:$(abs_top_builddir)/src/lib/acl/.libs:$$$(ENV_LIBRARY_PATH)
endif
# test using command-line arguments, so use check-local target instead of TESTS
# We set B10_FROM_BUILD below, so that the test can refer to the in-source
# spec file.
check-local:
if ENABLE_PYTHON_COVERAGE
touch $(abs_top_srcdir)/.coverage
rm -f .coverage
${LN_S} $(abs_top_srcdir)/.coverage .coverage
endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
B10_FROM_SOURCE=$(abs_top_srcdir) \
B10_FROM_BUILD=$(abs_top_builddir) \
$(LIBRARY_PATH_PLACEHOLDER) \
PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/bin/memmgr:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/util/io/.libs \
TESTDATASRCDIR=$(abs_srcdir)/testdata/ \
TESTDATA_PATH=$(abs_top_srcdir)/src/lib/testutils/testdata \
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
# Copyright (C) 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.
import unittest
import os
import re
import isc.log
from isc.dns import RRClass
import isc.config
from isc.config import parse_answer
import memmgr
from isc.testutils.ccsession_mock import MockModuleCCSession
class MyCCSession(MockModuleCCSession, isc.config.ConfigData):
def __init__(self, specfile, config_handler, command_handler):
super().__init__()
specfile = os.environ['B10_FROM_BUILD'] + '/src/bin/memmgr/memmgr.spec'
module_spec = isc.config.module_spec_from_file(specfile)
isc.config.ConfigData.__init__(self, module_spec)
self.add_remote_params = [] # for inspection
self.add_remote_exception = None # to raise exception from the method
def start(self):
pass
def add_remote_config_by_name(self, mod_name, handler):
if self.add_remote_exception is not None:
raise self.add_remote_exception
self.add_remote_params.append((mod_name, handler))
class MockMemmgr(memmgr.Memmgr):
def _setup_ccsession(self):
orig_cls = isc.config.ModuleCCSession
isc.config.ModuleCCSession = MyCCSession
try:
super()._setup_ccsession()
finally:
isc.config.ModuleCCSession = orig_cls
# Defined for easier tests with DataSrcClientsMgr.reconfigure(), which
# only needs get_value() method
class MockConfigData:
def __init__(self, data):
self.__data = data
def get_value(self, identifier):
return self.__data[identifier], False
class TestMemmgr(unittest.TestCase):
def setUp(self):
# Some tests use this directory. Make sure it doesn't pre-exist.
self.__test_mapped_file_dir = \
os.environ['B10_FROM_BUILD'] + \
'/src/bin/memmgr/tests/test_mapped_files'
if os.path.isdir(self.__test_mapped_file_dir):
os.rmdir(self.__test_mapped_file_dir)
self.__mgr = MockMemmgr()
# Fake some 'os' module functions for easier tests
self.__orig_os_access = os.access
self.__orig_isdir = os.path.isdir
def tearDown(self):
# Restore faked values
os.access = self.__orig_os_access
os.path.isdir = self.__orig_isdir
# If at test created a mapped-files directory, delete it.
if os.path.isdir(self.__test_mapped_file_dir):
os.rmdir(self.__test_mapped_file_dir)
def test_init(self):
"""Check some initial conditions"""
self.assertIsNone(self.__mgr._config_params)
self.assertEqual([], self.__mgr._datasrc_info_list)
# Try to configure a data source clients with the manager. This
# should confirm the manager object is instantiated enabling in-memory
# cache.
cfg_data = MockConfigData(
{"classes": {"IN": [{"type": "MasterFiles",
"cache-enable": True, "params": {}}]}})
self.__mgr._datasrc_clients_mgr.reconfigure({}, cfg_data)
clist = \
self.__mgr._datasrc_clients_mgr.get_client_list(RRClass.IN)
self.assertEqual(1, len(clist.get_status()))
def test_configure(self):
self.__mgr._setup_ccsession()
# Pretend specified directories exist and writable
os.path.isdir = lambda x: True
os.access = lambda x, y: True
# At the initial configuration, if mapped_file_dir isn't specified,
# the default value will be set.
self.assertEqual((0, None),
parse_answer(self.__mgr._config_handler({})))
self.assertEqual('mapped_files',
self.__mgr._config_params['mapped_file_dir'].
split('/')[-1])
# Update the configuration.
user_cfg = {'mapped_file_dir': '/some/path/dir'}
self.assertEqual((0, None),
parse_answer(self.__mgr._config_handler(user_cfg)))
self.assertEqual('/some/path/dir',
self.__mgr._config_params['mapped_file_dir'])
# Bad update: diretory doesn't exist (we assume it really doesn't
# exist in the tested environment). Update won't be made.
os.path.isdir = self.__orig_isdir # use real library
user_cfg = {'mapped_file_dir': '/another/path/dir'}
answer = parse_answer(self.__mgr._config_handler(user_cfg))
self.assertEqual(1, answer[0])
self.assertIsNotNone(re.search('not a directory', answer[1]))
# Bad update: directory exists but is not readable.
os.mkdir(self.__test_mapped_file_dir, 0o500) # drop writable bit
os.access = self.__orig_os_access
user_cfg = {'mapped_file_dir': self.__test_mapped_file_dir}