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