# Copyright (c) 2013, Red Hat, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of the FreeBSD Project.
#
# Authors: Michal Minar <miminar@redhat.com>
#
"""
Module for Configuration class.
Configuration
---------------------
.. autoclass:: Configuration
:members:
"""
import os
from lmi.base.BaseConfiguration import BaseConfiguration
LISTER_FORMATS = ['csv', 'table']
[docs]class Configuration(BaseConfiguration):
"""
Configuration class specific to software providers.
*OpenLMI* configuration file should reside in: ::
/etc/openlmi/scripts/lmi.conf
:param string user_config_file_path: Path to the user configuration
options.
"""
USER_CONFIG_FILE_PATH = "~/.lmirc"
OUTPUT_SILENT = -1
OUTPUT_WARNING = 0
OUTPUT_INFO = 1
OUTPUT_DEBUG = 2
# indexes to LISTER_FORMATS
LISTER_FORMAT_CSV = 0
LISTER_FORMAT_TABLE = 1
def __init__(self, user_config_file_path=USER_CONFIG_FILE_PATH, **kwargs):
self._user_config_file_path = os.path.expanduser(user_config_file_path)
BaseConfiguration.__init__(self, **kwargs)
self._verbosity = None
self._trace = None
self._verify_server_cert = None
self._cim_namespace = None
self._human_friendly = None
self._lister_format = None
self._no_headings = None
self._log_file = None
@classmethod
def provider_prefix(cls):
return "scripts"
@classmethod
[docs] def default_options(cls):
"""
:returns: Dictionary of default values.
:rtype: dictionary
"""
defaults = BaseConfiguration.default_options().copy()
# [Main] options
defaults["CommandNamespace"] = 'lmi.scripts.cmd'
defaults["Trace"] = "False"
defaults["Verbosity"] = "0"
# [Log] options
defaults['ConsoleFormat'] = "%(levelname)s: %(message)s"
defaults['FileFormat'] = \
"%(asctime)s:%(levelname)-8s:%(name)s:%(lineno)d - %(message)s"
defaults['LogToConsole'] = 'True'
defaults['OutputFile'] = ''
# [SSL] options
defaults['VerifyServerCertificate'] = 'True'
# [Format] options
defaults['HumanFriendly'] = 'False' # be ugly by default
defaults['ListerFormat'] = 'table'
defaults['NoHeadings'] = 'False'
return defaults
@classmethod
def mandatory_sections(cls):
sects = set(BaseConfiguration.mandatory_sections())
sects.add('Main')
sects.add('SSL')
sects.add('Format')
return list(sects)
[docs] def load(self):
""" Read additional user configuration file if it exists. """
BaseConfiguration.load(self)
self.config.read(self._user_config_file_path)
# *************************************************************************
# [CIM] options
# *************************************************************************
@property
def namespace(self):
if self._cim_namespace is None:
return BaseConfiguration.namespace.fget(self)
return self._cim_namespace
@namespace.setter
def namespace(self, namespace):
if not isinstance(namespace, basestring) and namespace is not None:
raise TypeError("namespace must be a string")
self._cim_namespace = namespace
# *************************************************************************
# [Main] options
# *************************************************************************
@property
[docs] def silent(self):
""" Whether to suppress all output messages except for errors. """
return self.verbosity <= self.OUTPUT_SILENT
@property
def trace(self):
""" Whether the tracebacks shall be printed upon errors. """
if self._trace is not None:
return self._trace
return self.get_safe('Main', 'Trace', bool)
@trace.setter
[docs] def trace(self, trace):
""" Allow to override configuration option Trace. """
if trace is not None:
trace = bool(trace)
self._trace = trace
@property
[docs] def verbose(self):
""" Whether to output more details. """
return self.verbosity >= self.OUTPUT_INFO
@property
def verbosity(self):
""" Return integer indicating verbosity level of output to console. """
if self._verbosity is None:
return self.get_safe('Main', 'Verbosity', int)
return self._verbosity
@verbosity.setter
[docs] def verbosity(self, level):
""" Allow to set verbosity without modifying configuration values. """
if not isinstance(level, (long, int)) and level is not None:
raise TypeError("level must be integer")
if level is not None:
if level < self.OUTPUT_SILENT:
level = self.OUTPUT_SILENT
elif level > self.OUTPUT_DEBUG:
level = self.OUTPUT_DEBUG
self._verbosity = level
# *************************************************************************
# [Log] options
# *************************************************************************
@property
def log_file(self):
""" Path to a file, where logging messages shall be written. """
if self._log_file is None:
return self.get_safe('Log', 'OutputFile')
return self._log_file
@log_file.setter
[docs] def log_file(self, log_file):
""" Override logging file path. """
if log_file is not None and not isinstance(log_file, basestring):
raise TypeError("log_file must be a string")
self._log_file = log_file
# *************************************************************************
# [SSL] options
# *************************************************************************
@property
def verify_server_cert(self):
"""
Return boolean saying, whether the server-side certificate should be
checked.
"""
if self._verify_server_cert is None:
return self.get_safe('SSL', 'VerifyServerCertificate', bool)
return self._verify_server_cert
@verify_server_cert.setter
[docs] def verify_server_cert(self, value):
""" Allows to override configuration option value. """
if value is not None:
value = bool(value)
self._verify_server_cert = value
# *************************************************************************
# [Format] options
# *************************************************************************
@property
def human_friendly(self):
""" Whether to print human-friendly values. """
if self._human_friendly is None:
return self.get_safe('Format', 'HumanFriendly', bool)
return self._human_friendly
@human_friendly.setter
[docs] def human_friendly(self, value):
""" Allows to override configuration option value. """
if value is not None:
value = bool(value)
self._human_friendly = value
@property
def lister_format(self):
"""
Output format used for lister commands. Returns one of
* LISTER_FORMAT_CSV
* LISTER_FORMAT_TABLE
:rtype: integer
"""
if self._lister_format is None:
value = self.get_safe('Format', 'ListerFormat')
try:
return LISTER_FORMATS.index(value.lower())
except ValueError:
value = self.default_options()['ListerFormat']
return LISTER_FORMATS.index(value.lower())
return self._lister_format
@lister_format.setter
@property
def no_headings(self):
""" Whether to print headings of tables. """
if self._no_headings is None:
return self.get_safe('Format', 'NoHeadings', bool)
return self._no_headings
@no_headings.setter
[docs] def no_headings(self, value):
""" Allows to override configuration option. """
if value is not None:
value = bool(value)
self._no_headings = value
# There were some path changes in BaseConfiguration after 0.2.0 release.
# Let's fallback to older variable name when the new one is not present.
if hasattr(BaseConfiguration, 'CONFIG_DIRECTORY_TEMPLATE_PROVIDER'):
setattr( Configuration
, 'CONFIG_FILE_PATH_TEMPLATE_PROVIDER'
, getattr(BaseConfiguration, 'CONFIG_DIRECTORY_TEMPLATE_PROVIDER')
+ 'lmi.conf')
else: # fallback
setattr( Configuration
, 'CONFIG_FILE_PATH_TEMPLATE'
, getattr(BaseConfiguration, 'CONFIG_DIRECTORY_TEMPLATE')
+ 'lmi.conf')