global_config.py revision da8fb97be0353f54eb7e62e132482d728684f200
1ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh"""A singleton class for accessing global config values 2ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh 3ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighprovides access to global configuration file 4ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh""" 5ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh 6ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh__author__ = 'raphtee@google.com (Travis Miller)' 7ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh 8da8fb97be0353f54eb7e62e132482d728684f200lmrimport os, sys, ConfigParser, logging 911788296e58691a3149355a4fc4a3fa1084c689dmblighfrom autotest_lib.client.common_lib import error 10ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh 11104e9ce7a74041fd673ceac5c8b0bc67c74edcd5mbligh 12ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighclass ConfigError(error.AutotestError): 130afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski pass 14ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh 15ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh 16104e9ce7a74041fd673ceac5c8b0bc67c74edcd5mblighclass ConfigValueError(ConfigError): 170afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski pass 18104e9ce7a74041fd673ceac5c8b0bc67c74edcd5mbligh 19104e9ce7a74041fd673ceac5c8b0bc67c74edcd5mbligh 206d08b3c3fc2858ccd60a323008703179f93ae38blmr 216d08b3c3fc2858ccd60a323008703179f93ae38blmrcommon_lib_dir = os.path.dirname(sys.modules[__name__].__file__) 226d08b3c3fc2858ccd60a323008703179f93ae38blmrclient_dir = os.path.dirname(common_lib_dir) 236d08b3c3fc2858ccd60a323008703179f93ae38blmrroot_dir = os.path.dirname(client_dir) 246d08b3c3fc2858ccd60a323008703179f93ae38blmr 256d08b3c3fc2858ccd60a323008703179f93ae38blmr# Check if the config files are at autotest's root dir 266d08b3c3fc2858ccd60a323008703179f93ae38blmr# This will happen if client is executing inside a full autotest tree, or if 276d08b3c3fc2858ccd60a323008703179f93ae38blmr# other entry points are being executed 286d08b3c3fc2858ccd60a323008703179f93ae38blmrglobal_config_path_root = os.path.join(root_dir, 'global_config.ini') 296d08b3c3fc2858ccd60a323008703179f93ae38blmrshadow_config_path_root = os.path.join(root_dir, 'shadow_config.ini') 306d08b3c3fc2858ccd60a323008703179f93ae38blmrconfig_in_root = (os.path.exists(global_config_path_root) and 316d08b3c3fc2858ccd60a323008703179f93ae38blmr os.path.exists(shadow_config_path_root)) 326d08b3c3fc2858ccd60a323008703179f93ae38blmr 336d08b3c3fc2858ccd60a323008703179f93ae38blmr# Check if the config files are at autotest's client dir 346d08b3c3fc2858ccd60a323008703179f93ae38blmr# This will happen if a client stand alone execution is happening 356d08b3c3fc2858ccd60a323008703179f93ae38blmrglobal_config_path_client = os.path.join(client_dir, 'global_config.ini') 366d08b3c3fc2858ccd60a323008703179f93ae38blmrconfig_in_client = os.path.exists(global_config_path_client) 376d08b3c3fc2858ccd60a323008703179f93ae38blmr 386d08b3c3fc2858ccd60a323008703179f93ae38blmrif config_in_root: 396d08b3c3fc2858ccd60a323008703179f93ae38blmr DEFAULT_CONFIG_FILE = global_config_path_root 406d08b3c3fc2858ccd60a323008703179f93ae38blmr DEFAULT_SHADOW_FILE = shadow_config_path_root 416d08b3c3fc2858ccd60a323008703179f93ae38blmr RUNNING_STAND_ALONE_CLIENT = False 426d08b3c3fc2858ccd60a323008703179f93ae38blmrelif config_in_client: 436d08b3c3fc2858ccd60a323008703179f93ae38blmr DEFAULT_CONFIG_FILE = global_config_path_client 446d08b3c3fc2858ccd60a323008703179f93ae38blmr DEFAULT_SHADOW_FILE = None 456d08b3c3fc2858ccd60a323008703179f93ae38blmr RUNNING_STAND_ALONE_CLIENT = True 466d08b3c3fc2858ccd60a323008703179f93ae38blmrelse: 47da8fb97be0353f54eb7e62e132482d728684f200lmr DEFAULT_CONFIG_FILE = None 48da8fb97be0353f54eb7e62e132482d728684f200lmr DEFAULT_SHADOW_FILE = None 49da8fb97be0353f54eb7e62e132482d728684f200lmr RUNNING_STAND_ALONE_CLIENT = True 506d08b3c3fc2858ccd60a323008703179f93ae38blmr 51ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighclass global_config(object): 52893db3d528e4c7d10ef5b7073dbf63670dffbccashoward _NO_DEFAULT_SPECIFIED = object() 53893db3d528e4c7d10ef5b7073dbf63670dffbccashoward 540afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski config = None 550afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski config_file = DEFAULT_CONFIG_FILE 560afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski shadow_file = DEFAULT_SHADOW_FILE 576d08b3c3fc2858ccd60a323008703179f93ae38blmr running_stand_alone_client = RUNNING_STAND_ALONE_CLIENT 586d08b3c3fc2858ccd60a323008703179f93ae38blmr 596d08b3c3fc2858ccd60a323008703179f93ae38blmr 606d08b3c3fc2858ccd60a323008703179f93ae38blmr def check_stand_alone_client_run(self): 616d08b3c3fc2858ccd60a323008703179f93ae38blmr return self.running_stand_alone_client 620afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 630afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 640afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski def set_config_files(self, config_file=DEFAULT_CONFIG_FILE, 650afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski shadow_file=DEFAULT_SHADOW_FILE): 660afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski self.config_file = config_file 670afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski self.shadow_file = shadow_file 680afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski self.config = None 690afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 700afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 71d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward def _handle_no_value(self, section, key, default): 72893db3d528e4c7d10ef5b7073dbf63670dffbccashoward if default is self._NO_DEFAULT_SPECIFIED: 73d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward msg = ("Value '%s' not found in section '%s'" % 74d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward (key, section)) 75d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward raise ConfigError(msg) 76d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward else: 77d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward return default 78d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward 79d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward 806d08b3c3fc2858ccd60a323008703179f93ae38blmr def get_section_values(self, section): 816d08b3c3fc2858ccd60a323008703179f93ae38blmr """ 826d08b3c3fc2858ccd60a323008703179f93ae38blmr Return a config parser object containing a single section of the 836d08b3c3fc2858ccd60a323008703179f93ae38blmr global configuration, that can be later written to a file object. 846d08b3c3fc2858ccd60a323008703179f93ae38blmr 856d08b3c3fc2858ccd60a323008703179f93ae38blmr @param section: Section we want to turn into a config parser object. 866d08b3c3fc2858ccd60a323008703179f93ae38blmr @return: ConfigParser() object containing all the contents of section. 876d08b3c3fc2858ccd60a323008703179f93ae38blmr """ 886d08b3c3fc2858ccd60a323008703179f93ae38blmr cfgparser = ConfigParser.ConfigParser() 896d08b3c3fc2858ccd60a323008703179f93ae38blmr cfgparser.add_section(section) 906d08b3c3fc2858ccd60a323008703179f93ae38blmr for option, value in self.config.items(section): 916d08b3c3fc2858ccd60a323008703179f93ae38blmr cfgparser.set(section, option, value) 926d08b3c3fc2858ccd60a323008703179f93ae38blmr return cfgparser 936d08b3c3fc2858ccd60a323008703179f93ae38blmr 946d08b3c3fc2858ccd60a323008703179f93ae38blmr 95893db3d528e4c7d10ef5b7073dbf63670dffbccashoward def get_config_value(self, section, key, type=str, 96893db3d528e4c7d10ef5b7073dbf63670dffbccashoward default=_NO_DEFAULT_SPECIFIED, allow_blank=False): 9750c0e71efd37c04c5f441c7e4dd095632b54c35fshoward self._ensure_config_parsed() 980afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 990afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski try: 1000afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski val = self.config.get(section, key) 101d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward except ConfigParser.Error: 102d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward return self._handle_no_value(section, key, default) 103d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward 104d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward if not val.strip() and not allow_blank: 105d1ee1dd3f3e5ac44f00d7a96deb815dbe1beedadshoward return self._handle_no_value(section, key, default) 1060afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 107893db3d528e4c7d10ef5b7073dbf63670dffbccashoward return self._convert_value(key, section, val, type) 1080afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 1090afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 11050c0e71efd37c04c5f441c7e4dd095632b54c35fshoward def override_config_value(self, section, key, new_value): 11150c0e71efd37c04c5f441c7e4dd095632b54c35fshoward """ 11250c0e71efd37c04c5f441c7e4dd095632b54c35fshoward Override a value from the config file with a new value. 11350c0e71efd37c04c5f441c7e4dd095632b54c35fshoward """ 11450c0e71efd37c04c5f441c7e4dd095632b54c35fshoward self._ensure_config_parsed() 11550c0e71efd37c04c5f441c7e4dd095632b54c35fshoward self.config.set(section, key, new_value) 11650c0e71efd37c04c5f441c7e4dd095632b54c35fshoward 11750c0e71efd37c04c5f441c7e4dd095632b54c35fshoward 11850c0e71efd37c04c5f441c7e4dd095632b54c35fshoward def reset_config_values(self): 11950c0e71efd37c04c5f441c7e4dd095632b54c35fshoward """ 12050c0e71efd37c04c5f441c7e4dd095632b54c35fshoward Reset all values to those found in the config files (undoes all 12150c0e71efd37c04c5f441c7e4dd095632b54c35fshoward overrides). 12250c0e71efd37c04c5f441c7e4dd095632b54c35fshoward """ 12350c0e71efd37c04c5f441c7e4dd095632b54c35fshoward self.parse_config_file() 12450c0e71efd37c04c5f441c7e4dd095632b54c35fshoward 12550c0e71efd37c04c5f441c7e4dd095632b54c35fshoward 12650c0e71efd37c04c5f441c7e4dd095632b54c35fshoward def _ensure_config_parsed(self): 127d876f459fff6cc4994cab329b1f80c99a86edcbdmbligh if self.config is None: 12850c0e71efd37c04c5f441c7e4dd095632b54c35fshoward self.parse_config_file() 12950c0e71efd37c04c5f441c7e4dd095632b54c35fshoward 13050c0e71efd37c04c5f441c7e4dd095632b54c35fshoward 1310afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski def merge_configs(self, shadow_config): 1320afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # overwrite whats in config with whats in shadow_config 1330afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski sections = shadow_config.sections() 1340afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski for section in sections: 1350afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # add the section if need be 1360afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski if not self.config.has_section(section): 1370afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski self.config.add_section(section) 1380afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # now run through all options and set them 1390afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski options = shadow_config.options(section) 1400afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski for option in options: 1410afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski val = shadow_config.get(section, option) 1420afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski self.config.set(section, option, val) 1430afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 1440afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 1450afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski def parse_config_file(self): 1460afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski self.config = ConfigParser.ConfigParser() 147da8fb97be0353f54eb7e62e132482d728684f200lmr if self.config_file and os.path.exists(self.config_file): 148da8fb97be0353f54eb7e62e132482d728684f200lmr self.config.read(self.config_file) 149da8fb97be0353f54eb7e62e132482d728684f200lmr else: 150da8fb97be0353f54eb7e62e132482d728684f200lmr raise ConfigError('%s not found' % (self.config_file)) 1510afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 1520afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # now also read the shadow file if there is one 1530afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # this will overwrite anything that is found in the 1540afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # other config 1556d08b3c3fc2858ccd60a323008703179f93ae38blmr if self.shadow_file and os.path.exists(self.shadow_file): 1560afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski shadow_config = ConfigParser.ConfigParser() 1570afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski shadow_config.read(self.shadow_file) 1580afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # now we merge shadow into global 1590afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski self.merge_configs(shadow_config) 1600afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 1610afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 1620afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # the values that are pulled from ini 1630afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # are strings. But we should attempt to 1640afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # convert them to other types if needed. 165893db3d528e4c7d10ef5b7073dbf63670dffbccashoward def _convert_value(self, key, section, value, value_type): 1660afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # strip off leading and trailing white space 1670afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski sval = value.strip() 1680afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 1690afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski # if length of string is zero then return None 1700afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski if len(sval) == 0: 171a5f30c207b211e2bf57c6d4297734da54055af90showard if value_type == str: 1720afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return "" 173a5f30c207b211e2bf57c6d4297734da54055af90showard elif value_type == bool: 1740afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return False 175a5f30c207b211e2bf57c6d4297734da54055af90showard elif value_type == int: 1760afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return 0 177a5f30c207b211e2bf57c6d4297734da54055af90showard elif value_type == float: 1780afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return 0.0 179a5f30c207b211e2bf57c6d4297734da54055af90showard elif value_type == list: 180c5ddfd1f71caef9ec0c84c53ef7db42fcdc33e1cmbligh return [] 1810afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski else: 1820afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return None 1830afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 184a5f30c207b211e2bf57c6d4297734da54055af90showard if value_type == bool: 1850afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski if sval.lower() == "false": 1860afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return False 1870afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski else: 1880afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return True 1890afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 190a5f30c207b211e2bf57c6d4297734da54055af90showard if value_type == list: 191c5ddfd1f71caef9ec0c84c53ef7db42fcdc33e1cmbligh # Split the string using ',' and return a list 192c5ddfd1f71caef9ec0c84c53ef7db42fcdc33e1cmbligh return [val.strip() for val in sval.split(',')] 193c5ddfd1f71caef9ec0c84c53ef7db42fcdc33e1cmbligh 1940afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski try: 195a5f30c207b211e2bf57c6d4297734da54055af90showard conv_val = value_type(sval) 1960afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski return conv_val 1970afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski except: 198a5f30c207b211e2bf57c6d4297734da54055af90showard msg = ("Could not convert %s value %r in section %s to type %s" % 199a5f30c207b211e2bf57c6d4297734da54055af90showard (key, sval, section, value_type)) 2000afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski raise ConfigValueError(msg) 2010afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 2020afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski 2030afbb6369aa5aa9a75ea67dd9e95ec4b21c0c181jadmanski# insure the class is a singleton. Now the symbol global_config 204ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mbligh# will point to the one and only one instace of the class 205ed4d6ddc79993492b22aeeb36574b3cb7c8bad44mblighglobal_config = global_config() 206