• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Lint as: python2, python3
2"""
3Wrapper around ConfigParser to manage testcases configuration.
4
5@author rsalveti@linux.vnet.ibm.com (Ricardo Salveti de Araujo)
6"""
7
8from __future__ import absolute_import
9from __future__ import division
10from __future__ import print_function
11from six.moves.configparser import ConfigParser
12from six.moves import range
13from six import StringIO
14from os import path
15import re, six, string
16from autotest_lib.client.common_lib import utils
17
18__all__ = ['config_loader']
19
20class config_loader:
21    """
22    Base class of the configuration parser
23    """
24    def __init__(self, cfg, tmpdir='/tmp', raise_errors=False):
25        """
26        Instantiate ConfigParser and provide the file like object that we'll
27        use to read configuration data from.
28        @param cfg: Where we'll get configuration data. It can be either:
29                * A URL containing the file
30                * A valid file path inside the filesystem
31                * A string containing configuration data
32        @param tmpdir: Where we'll dump the temporary conf files.
33        @param raise_errors: Whether config value absences will raise
34                ValueError exceptions.
35        """
36        # Base Parser
37        self.parser = ConfigParser()
38        # Raise errors when lacking values
39        self.raise_errors = raise_errors
40        # File is already a file like object
41        if hasattr(cfg, 'read'):
42            self.cfg = cfg
43            self.parser.readfp(self.cfg)
44        elif isinstance(cfg, six.string_types):
45            # Config file is a URL. Download it to a temp dir
46            if cfg.startswith('http') or cfg.startswith('ftp'):
47                self.cfg = path.join(tmpdir, path.basename(cfg))
48                utils.urlretrieve(cfg, self.cfg)
49                self.parser.read(self.cfg)
50            # Config is a valid filesystem path to a file.
51            elif path.exists(path.abspath(cfg)):
52                if path.isfile(cfg):
53                    self.cfg = path.abspath(cfg)
54                    self.parser.read(self.cfg)
55                else:
56                    e_msg = 'Invalid config file path: %s' % cfg
57                    raise IOError(e_msg)
58            # Config file is just a string, convert it to a python file like
59            # object using StringIO
60            else:
61                self.cfg = StringIO(cfg)
62                self.parser.readfp(self.cfg)
63
64
65    def get(self, section, option, default=None):
66        """
67        Get the value of a option.
68
69        Section of the config file and the option name.
70        You can pass a default value if the option doesn't exist.
71
72        @param section: Configuration file section.
73        @param option: Option we're looking after.
74        @default: In case the option is not available and raise_errors is set
75                to False, return the default.
76        """
77        if not self.parser.has_option(section, option):
78            if self.raise_errors:
79                raise ValueError('No value for option %s. Please check your '
80                                 'config file "%s".' % (option, self.cfg))
81            else:
82                return default
83
84        return self.parser.get(section, option)
85
86
87    def set(self, section, option, value):
88        """
89        Set an option.
90
91        This change is not persistent unless saved with 'save()'.
92        """
93        if not self.parser.has_section(section):
94            self.parser.add_section(section)
95        return self.parser.set(section, option, value)
96
97
98    def remove(self, section, option):
99        """
100        Remove an option.
101        """
102        if self.parser.has_section(section):
103            self.parser.remove_option(section, option)
104
105
106    def save(self):
107        """
108        Save the configuration file with all modifications
109        """
110        if not self.cfg:
111            return
112        fileobj = open(self.cfg, 'w')
113        try:
114            self.parser.write(fileobj)
115        finally:
116            fileobj.close()
117
118
119    def check(self, section):
120        """
121        Check if the config file has valid values
122        """
123        if not self.parser.has_section(section):
124            return False, "Section not found: %s"%(section)
125
126        options = self.parser.items(section)
127        for i in range(options.__len__()):
128            param = options[i][0]
129            aux = string.split(param, '.')
130
131            if aux.__len__ < 2:
132                return False, "Invalid parameter syntax at %s"%(param)
133
134            if not self.check_parameter(aux[0], options[i][1]):
135                return False, "Invalid value at %s"%(param)
136
137        return True, None
138
139
140    def check_parameter(self, param_type, parameter):
141        """
142        Check if a option has a valid value
143        """
144        if parameter == '' or parameter == None:
145            return False
146        elif param_type == "ip" and self.__isipaddress(parameter):
147            return True
148        elif param_type == "int" and self.__isint(parameter):
149            return True
150        elif param_type == "float" and self.__isfloat(parameter):
151            return True
152        elif param_type == "str" and self.__isstr(parameter):
153            return True
154
155        return False
156
157
158    def __isipaddress(self, parameter):
159        """
160        Verify if the ip address is valid
161
162        @param ip String: IP Address
163        @return True if a valid IP Address or False
164        """
165        octet1 = "([1-9][0-9]{,1}|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
166        octet = "([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
167        pattern = "^" + octet1 + "\.(" + octet + "\.){2}" + octet + "$"
168        if re.match(pattern, parameter) == None:
169            return False
170        else:
171            return True
172
173
174    def __isint(self, parameter):
175        try:
176            int(parameter)
177        except Exception as e_stack:
178            return False
179        return True
180
181
182    def __isfloat(self, parameter):
183        try:
184            float(parameter)
185        except Exception as e_stack:
186            return False
187        return True
188
189
190    def __isstr(self, parameter):
191        try:
192            str(parameter)
193        except Exception as e_stack:
194            return False
195        return True
196