| #!/usr/bin/env python |
| import sys |
| import os |
| import time |
| import ConfigParser |
| import tempfile |
| import codecs |
| from StringIO import StringIO |
| from xml_util import Xml |
| |
| default_config = \ |
| """ |
| """ |
| |
| XOS_DIR = "/opt/xos" |
| DEFAULT_CONFIG_FN = os.path.join(XOS_DIR, "xos_configuration/") |
| |
| # warning for now, remove once we're sure everyone has made the change |
| if (os.path.exists("/opt/planetstack/plstackapi_config") and (not os.path.exists(DEFAULT_CONFIG_FN))): |
| print >> sys.stderr, "WARNING: did you forget to rename plstackapi_config to xos_config ??" |
| |
| def isbool(v): |
| return v.lower() in ("true", "false") |
| |
| def str2bool(v): |
| return v.lower() in ("true", "1") |
| |
| # allow the test framework to apply global overrides to the config framework |
| override = {} |
| def set_override(name, value): |
| override[name] = value |
| |
| class Config: |
| |
| def __init__(self, config_file=None): |
| if (config_file==None): |
| config_file = self.get_config_fn() |
| |
| self._files = [] |
| self.config_path = os.path.dirname(config_file) |
| self.config = ConfigParser.ConfigParser() |
| self.filename = config_file |
| if not os.path.isfile(self.filename) and not os.path.isdir(self.filename): |
| self.create(self.filename) |
| self.load(self.filename) |
| |
| def get_config_fn(self): |
| # Look for "-C <something>" to get the |
| # name of the config file. Using a real OptionParser here is |
| # problematic as it will throw 'no such option' errors for options |
| # that it does not understand. |
| |
| last = None |
| for arg in sys.argv: |
| if (last=="-C"): |
| return arg |
| last = arg |
| |
| return DEFAULT_CONFIG_FN |
| |
| def _header(self): |
| header = """ |
| DO NOT EDIT. This file was automatically generated at |
| %s from: |
| |
| %s |
| """ % (time.asctime(), os.linesep.join(self._files)) |
| |
| # Get rid of the surrounding newlines |
| return header.strip().split(os.linesep) |
| |
| def create(self, filename): |
| if not os.path.exists(os.path.dirname(filename)): |
| os.makedirs(os.path.dirname(filename)) |
| configfile = open(filename, 'w') |
| configfile.write(default_config) |
| configfile.close() |
| |
| |
| def load(self, filename): |
| if filename: |
| try: |
| if os.path.isdir(filename): |
| config_list = list(reversed(os.listdir(filename))) |
| config_list.remove('README.md') |
| config_list = [os.path.join(filename, s) for s in config_list] |
| self.config.read(config_list) |
| else: |
| self.config.read(filename) |
| except ConfigParser.MissingSectionHeaderError: |
| if filename.endswith('.xml'): |
| self.load_xml(filename) |
| else: |
| self.load_shell(filename) |
| self._files.append(filename) |
| self.set_attributes() |
| |
| def load_xml(self, filename): |
| xml = XML(filename) |
| categories = xml.xpath('//configuration/variables/category') |
| for category in categories: |
| section_name = category.get('id') |
| if not self.config.has_section(section_name): |
| self.config.add_section(section_name) |
| options = category.xpath('./variablelist/variable') |
| for option in options: |
| option_name = option.get('id') |
| value = option.xpath('./value')[0].text |
| if not value: |
| value = "" |
| self.config.set(section_name, option_name, value) |
| |
| def load_shell(self, filename): |
| f = open(filename, 'r') |
| for line in f: |
| try: |
| if line.startswith('#'): |
| continue |
| parts = line.strip().split("=") |
| if len(parts) < 2: |
| continue |
| option = parts[0] |
| value = parts[1].replace('"', '').replace("'","") |
| section, var = self.locate_varname(option, strict=False) |
| if section and var: |
| self.set(section, var, value) |
| except: |
| pass |
| f.close() |
| |
| def locate_varname(self, varname, strict=True): |
| varname = varname.lower() |
| sections = self.config.sections() |
| section_name = "" |
| var_name = "" |
| for section in sections: |
| if varname.startswith(section.lower()) and len(section) > len(section_name): |
| section_name = section.lower() |
| var_name = varname.replace(section_name, "")[1:] |
| if strict and not self.config.has_option(section_name, var_name): |
| raise ConfigParser.NoOptionError(var_name, section_name) |
| return (section_name, var_name) |
| |
| def set_attributes(self): |
| sections = self.config.sections() |
| for section in sections: |
| for item in self.config.items(section): |
| name = "%s_%s" % (section, item[0]) |
| value = item[1] |
| if isbool(value): |
| value = str2bool(value) |
| elif value.isdigit(): |
| value = int(value) |
| setattr(self, name, value) |
| setattr(self, name.upper(), value) |
| |
| |
| def verify(self, config1, config2, validate_method): |
| return True |
| |
| def validate_type(self, var_type, value): |
| return True |
| |
| @staticmethod |
| def is_xml(config_file): |
| try: |
| x = Xml(config_file) |
| return True |
| except: |
| return False |
| |
| @staticmethod |
| def is_ini(config_file): |
| try: |
| c = ConfigParser.ConfigParser() |
| c.read(config_file) |
| return True |
| except ConfigParser.MissingSectionHeaderError: |
| return False |
| |
| |
| def dump(self, sections = []): |
| sys.stdout.write(output_python()) |
| |
| def output_python(self, encoding = "utf-8"): |
| buf = codecs.lookup(encoding)[3](StringIO()) |
| buf.writelines(["# " + line + os.linesep for line in self._header()]) |
| |
| for section in self.sections(): |
| buf.write("[%s]%s" % (section, os.linesep)) |
| for (name,value) in self.items(section): |
| buf.write("%s=%s%s" % (name,value,os.linesep)) |
| buf.write(os.linesep) |
| return buf.getvalue() |
| |
| def output_shell(self, show_comments = True, encoding = "utf-8"): |
| """ |
| Return variables as a shell script. |
| """ |
| |
| buf = codecs.lookup(encoding)[3](StringIO()) |
| buf.writelines(["# " + line + os.linesep for line in self._header()]) |
| |
| for section in self.sections(): |
| for (name,value) in self.items(section): |
| # bash does not have the concept of NULL |
| if value: |
| option = "%s_%s" % (section.upper(), name.upper()) |
| if isbool(value): |
| value = str(str2bool(value)) |
| elif not value.isdigit(): |
| value = '"%s"' % value |
| buf.write(option + "=" + value + os.linesep) |
| return buf.getvalue() |
| |
| def output_php(self, encoding = "utf-8"): |
| """ |
| Return variables as a PHP script. |
| """ |
| |
| buf = codecs.lookup(encoding)[3](StringIO()) |
| buf.write("<?php" + os.linesep) |
| buf.writelines(["// " + line + os.linesep for line in self._header()]) |
| |
| for section in self.sections(): |
| for (name,value) in self.items(section): |
| option = "%s_%s" % (section, name) |
| buf.write(os.linesep) |
| buf.write("// " + option + os.linesep) |
| if value is None: |
| value = 'NULL' |
| buf.write("define('%s', %s);" % (option, value) + os.linesep) |
| |
| buf.write("?>" + os.linesep) |
| |
| return buf.getvalue() |
| |
| def output_xml(self, encoding = "utf-8"): |
| pass |
| |
| def output_variables(self, encoding="utf-8"): |
| """ |
| Return list of all variable names. |
| """ |
| |
| buf = codecs.lookup(encoding)[3](StringIO()) |
| for section in self.sections(): |
| for (name,value) in self.items(section): |
| option = "%s_%s" % (section,name) |
| buf.write(option + os.linesep) |
| |
| return buf.getvalue() |
| pass |
| |
| def write(self, filename=None): |
| if not filename: |
| filename = self.filename |
| configfile = open(filename, 'w') |
| self.config.write(configfile) |
| |
| def save(self, filename=None): |
| self.write(filename) |
| |
| def __getattr__(self, attr): |
| if attr in override: |
| return override[attr] |
| return getattr(self.config, attr) |
| |
| if __name__ == '__main__': |
| filename = None |
| if len(sys.argv) > 1: |
| filename = sys.argv[1] |
| config = Config(filename) |
| else: |
| config = Config() |
| config.dump() |