-
Anael Beutot authoredAnael Beutot authored
config.py 5.70 KiB
# This file is part of CloudControl.
#
# CloudControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CloudControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with CloudControl. If not, see <http://www.gnu.org/licenses/>.
import logging
import logging.config
from StringIO import StringIO
from itertools import ifilterfalse
from ConfigParser import SafeConfigParser, NoOptionError, NoSectionError
from cloudcontrol.common.client.exc import ConfigError
logger = logging.getLogger(__name__)
class _ConfigProxy(object):
"""Simple ConfigParser proxy that provide default values for get* methods.
"""
def __init__(self, config_parser):
self.config = config_parser
@staticmethod
def config_error(msg):
logger.error(msg)
raise ConfigError(msg)
def __getattr__(self, name):
if name.startswith('get'):
def getter(section, option, *default):
assert not default or len(default) == 1
try:
return getattr(self.config, name)(section, option)
except NoSectionError:
self.config_error('Section "%s" is not present in config'
' file' % section)
except NoOptionError:
if default:
return default[0]
self.config_error(
'Attribute "%s" not specified in config'
' file (section "%s")' % (option, section))
except ValueError:
self.config_error(
'Configuration attribute "%s" value is invalid'
' (section "%s")' % (option, section))
return getter
# else
return getattr(self.config, name)
class NodeConfigParser(object):
"""ConfigParser for ccnode config file."""
def __init__(self, file_path):
config = _ConfigProxy(SafeConfigParser())
config.read(file_path)
# ccserver settings
self.server_host = config.get('node', 'address')
self.server_port = config.getint('node', 'port', 1984)
self.server_user = config.get('node', 'login')
self.server_passwd = config.get('node', 'password')
# node settings
try:
self.logging_level = config.getint('node', 'verbosity', 0)
except ConfigError:
try:
self.logging_level = dict(
debug=3,
info=2,
warning=1,
error=0,
)[config.get('node', 'verbosity')]
except KeyError:
_ConfigProxy.config_error(
'Configuration attribute "verbosity"'
' is invalid (section "node")')
self.debug = config.getboolean('node', 'debug', False)
self.logging_output = 'console' if self.debug else 'syslog'
# path settings
self.jobs_store_path = config.get('node', 'jobs_store_path',
'/var/lib/cc-node/jobs')
# plugins persistance
self.plugins_store_path = config.get('node', 'plugins_store_path',
'/var/lib/cc-node/plugins')
# RPC handler ACLs
acl_section_name = 'node_handler'
if config.has_section(acl_section_name):
self.forbidden_handlers = set(ifilterfalse(
lambda o: config.getboolean(acl_section_name, o, True),
config.options(acl_section_name),
))
else:
self.forbidden_handlers = set()
# backward compatibility
command_execution_handlers = set(('shutdown', 'execute'))
if config.getboolean('node', 'command_execution', None) == False:
self.forbidden_handlers |= command_execution_handlers
else:
self.forbidden_handlers -= command_execution_handlers
# deprecated options
for o in ('detect_hypervisor', 'force_xen'):
if config.get('node', o, None) is not None:
logger.warning('%s config option is not supported anymore', o)
def configure_logging(level, output):
level = {
0: 'ERROR', 1: 'WARNING',
2: 'INFO', 3: 'DEBUG',
}[level]
output = dict(
console="""
[handler_output]
class=StreamHandler
formatter=simpleFormatter
args=(sys.stderr,)
[formatter_simpleFormatter]
format=cc-node - %(asctime)s - %(name)s - %(levelname)s - %(message)s
""",
syslog="""
[handler_output]
class=handlers.SysLogHandler
formatter=simpleFormatter
args=('/dev/log', handlers.SysLogHandler.LOG_DAEMON)
[formatter_simpleFormatter]
class=cloudcontrol.common.helpers.formatter.EncodingFormatter
format=cc-node - %(name)s - %(levelname)s - %(message)s
""",
)[output]
# create config parser for logging configuration
logging.config.fileConfig(StringIO("""
[loggers]
keys=root,ccnode,cccommon,sjrpc
[handlers]
keys=output
[formatters]
keys=simpleFormatter
[logger_root]
level=ERROR
handlers=output
[logger_ccnode]
level=%(level)s
handlers=
qualname=cloudcontrol.node
[logger_cccommon]
level=%(level)s
handlers=
qualname=cloudcontrol.common
[logger_sjrpc]
level=ERROR
handlers=
qualname=sjrpc
%(output)s
""" % dict(level=level, output=output)))