196 lines
6.0 KiB
Python
196 lines
6.0 KiB
Python
# Lint as: python2, python3
|
|
"""
|
|
Wrapper around ConfigParser to manage testcases configuration.
|
|
|
|
@author rsalveti@linux.vnet.ibm.com (Ricardo Salveti de Araujo)
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
from six.moves.configparser import ConfigParser
|
|
from six.moves import range
|
|
from six import StringIO
|
|
from os import path
|
|
import re, six, string
|
|
from autotest_lib.client.common_lib import utils
|
|
|
|
__all__ = ['config_loader']
|
|
|
|
class config_loader:
|
|
"""
|
|
Base class of the configuration parser
|
|
"""
|
|
def __init__(self, cfg, tmpdir='/tmp', raise_errors=False):
|
|
"""
|
|
Instantiate ConfigParser and provide the file like object that we'll
|
|
use to read configuration data from.
|
|
@param cfg: Where we'll get configuration data. It can be either:
|
|
* A URL containing the file
|
|
* A valid file path inside the filesystem
|
|
* A string containing configuration data
|
|
@param tmpdir: Where we'll dump the temporary conf files.
|
|
@param raise_errors: Whether config value absences will raise
|
|
ValueError exceptions.
|
|
"""
|
|
# Base Parser
|
|
self.parser = ConfigParser()
|
|
# Raise errors when lacking values
|
|
self.raise_errors = raise_errors
|
|
# File is already a file like object
|
|
if hasattr(cfg, 'read'):
|
|
self.cfg = cfg
|
|
self.parser.readfp(self.cfg)
|
|
elif isinstance(cfg, six.string_types):
|
|
# Config file is a URL. Download it to a temp dir
|
|
if cfg.startswith('http') or cfg.startswith('ftp'):
|
|
self.cfg = path.join(tmpdir, path.basename(cfg))
|
|
utils.urlretrieve(cfg, self.cfg)
|
|
self.parser.read(self.cfg)
|
|
# Config is a valid filesystem path to a file.
|
|
elif path.exists(path.abspath(cfg)):
|
|
if path.isfile(cfg):
|
|
self.cfg = path.abspath(cfg)
|
|
self.parser.read(self.cfg)
|
|
else:
|
|
e_msg = 'Invalid config file path: %s' % cfg
|
|
raise IOError(e_msg)
|
|
# Config file is just a string, convert it to a python file like
|
|
# object using StringIO
|
|
else:
|
|
self.cfg = StringIO(cfg)
|
|
self.parser.readfp(self.cfg)
|
|
|
|
|
|
def get(self, section, option, default=None):
|
|
"""
|
|
Get the value of a option.
|
|
|
|
Section of the config file and the option name.
|
|
You can pass a default value if the option doesn't exist.
|
|
|
|
@param section: Configuration file section.
|
|
@param option: Option we're looking after.
|
|
@default: In case the option is not available and raise_errors is set
|
|
to False, return the default.
|
|
"""
|
|
if not self.parser.has_option(section, option):
|
|
if self.raise_errors:
|
|
raise ValueError('No value for option %s. Please check your '
|
|
'config file "%s".' % (option, self.cfg))
|
|
else:
|
|
return default
|
|
|
|
return self.parser.get(section, option)
|
|
|
|
|
|
def set(self, section, option, value):
|
|
"""
|
|
Set an option.
|
|
|
|
This change is not persistent unless saved with 'save()'.
|
|
"""
|
|
if not self.parser.has_section(section):
|
|
self.parser.add_section(section)
|
|
return self.parser.set(section, option, value)
|
|
|
|
|
|
def remove(self, section, option):
|
|
"""
|
|
Remove an option.
|
|
"""
|
|
if self.parser.has_section(section):
|
|
self.parser.remove_option(section, option)
|
|
|
|
|
|
def save(self):
|
|
"""
|
|
Save the configuration file with all modifications
|
|
"""
|
|
if not self.cfg:
|
|
return
|
|
fileobj = open(self.cfg, 'w')
|
|
try:
|
|
self.parser.write(fileobj)
|
|
finally:
|
|
fileobj.close()
|
|
|
|
|
|
def check(self, section):
|
|
"""
|
|
Check if the config file has valid values
|
|
"""
|
|
if not self.parser.has_section(section):
|
|
return False, "Section not found: %s"%(section)
|
|
|
|
options = self.parser.items(section)
|
|
for i in range(options.__len__()):
|
|
param = options[i][0]
|
|
aux = string.split(param, '.')
|
|
|
|
if aux.__len__ < 2:
|
|
return False, "Invalid parameter syntax at %s"%(param)
|
|
|
|
if not self.check_parameter(aux[0], options[i][1]):
|
|
return False, "Invalid value at %s"%(param)
|
|
|
|
return True, None
|
|
|
|
|
|
def check_parameter(self, param_type, parameter):
|
|
"""
|
|
Check if a option has a valid value
|
|
"""
|
|
if parameter == '' or parameter == None:
|
|
return False
|
|
elif param_type == "ip" and self.__isipaddress(parameter):
|
|
return True
|
|
elif param_type == "int" and self.__isint(parameter):
|
|
return True
|
|
elif param_type == "float" and self.__isfloat(parameter):
|
|
return True
|
|
elif param_type == "str" and self.__isstr(parameter):
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def __isipaddress(self, parameter):
|
|
"""
|
|
Verify if the ip address is valid
|
|
|
|
@param ip String: IP Address
|
|
@return True if a valid IP Address or False
|
|
"""
|
|
octet1 = "([1-9][0-9]{,1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
|
|
octet = "([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
|
|
pattern = "^" + octet1 + "\.(" + octet + "\.){2}" + octet + "$"
|
|
if re.match(pattern, parameter) == None:
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
|
|
def __isint(self, parameter):
|
|
try:
|
|
int(parameter)
|
|
except Exception as e_stack:
|
|
return False
|
|
return True
|
|
|
|
|
|
def __isfloat(self, parameter):
|
|
try:
|
|
float(parameter)
|
|
except Exception as e_stack:
|
|
return False
|
|
return True
|
|
|
|
|
|
def __isstr(self, parameter):
|
|
try:
|
|
str(parameter)
|
|
except Exception as e_stack:
|
|
return False
|
|
return True
|