RPKI Engine 1.0

config.py (3620)

Go to the documentation of this file.
00001 """
00002 Configuration file parsing utilities, layered on top of stock Python
00003 ConfigParser module.
00004 
00005 $Id: config.py 3620 2011-01-20 19:59:13Z sra $
00006 
00007 Copyright (C) 2009--2010  Internet Systems Consortium ("ISC")
00008 
00009 Permission to use, copy, modify, and distribute this software for any
00010 purpose with or without fee is hereby granted, provided that the above
00011 copyright notice and this permission notice appear in all copies.
00012 
00013 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00014 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00015 AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00016 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00017 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00018 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00019 PERFORMANCE OF THIS SOFTWARE.
00020 
00021 Portions copyright (C) 2007--2008  American Registry for Internet Numbers ("ARIN")
00022 
00023 Permission to use, copy, modify, and distribute this software for any
00024 purpose with or without fee is hereby granted, provided that the above
00025 copyright notice and this permission notice appear in all copies.
00026 
00027 THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH
00028 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00029 AND FITNESS.  IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT,
00030 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00031 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00032 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00033 PERFORMANCE OF THIS SOFTWARE.
00034 """
00035 
00036 import ConfigParser, os, re
00037 
00038 ## @var default_filename
00039 # Default name of config file if caller doesn't specify one explictly.
00040 
00041 default_filename = "rpki.conf"
00042 
00043 ## @var default_dirname
00044 # Default name of directory to check for global config file, or None
00045 # if no global config file.  Autoconf-generated code may set this to a
00046 # non-None value during script startup.
00047 
00048 default_dirname = None
00049 
00050 ## @var default_envname
00051 # Name of environment variable containing config file name.
00052 
00053 default_envname = "RPKI_CONF"
00054 
00055 class parser(object):
00056   """
00057   Extensions to stock Python ConfigParser:
00058 
00059   Read config file and set default section while initializing parser object.
00060 
00061   Support for OpenSSL-style subscripted options and a limited form of
00062   OpenSSL-style indirect variable references (${section::option}).
00063 
00064   get-methods with default values and default section name.
00065 
00066   If no filename is given to the constructor (filename = None), we
00067   check for an environment variable naming the config file, then we
00068   check for a default filename in the current directory, then finally
00069   we check for a global config file if autoconf provided a directory
00070   name to check.
00071   """
00072 
00073   def __init__(self, filename = None, section = None, allow_missing = False):
00074 
00075     self.cfg = ConfigParser.RawConfigParser()
00076     self.default_section = section
00077 
00078     filenames = []
00079     if filename is not None:
00080       filenames.append(filename)
00081     else:
00082       if default_envname in os.environ:
00083         filenames.append(os.environ[default_envname])
00084       filenames.append(default_filename)
00085       if default_dirname is not None:
00086         filenames.append("%s/%s" % (default_dirname, default_filename))
00087 
00088     for fn in filenames:
00089       try:
00090         f = open(fn)
00091         break
00092       except IOError:
00093         f = None
00094 
00095     if f is not None:
00096       self.filename = fn
00097       self.cfg.readfp(f, fn)
00098     elif allow_missing:
00099       self.filename = None
00100     else:
00101       raise
00102 
00103   def has_section(self, section):
00104     """
00105     Test whether a section exists.
00106     """
00107 
00108     return self.cfg.has_section(section)
00109 
00110   def has_option(self, option, section = None):
00111     """
00112     Test whether an option exists.
00113     """
00114 
00115     if section is None:
00116       section = self.default_section
00117     return self.cfg.has_option(section, option)
00118 
00119   def multiget(self, option, section = None):
00120     """
00121     Parse OpenSSL-style foo.0, foo.1, ... subscripted options.
00122 
00123     Returns a list of values matching the specified option name.
00124     """
00125 
00126     matches = []
00127     if section is None:
00128       section = self.default_section
00129     if self.cfg.has_option(section, option):
00130       matches.append((-1, self.get(option, section = section)))
00131     for key, value in self.cfg.items(section):
00132       s = key.rsplit(".", 1)
00133       if len(s) == 2 and s[0] == option and s[1].isdigit():
00134         matches.append((int(s[1]), self.get(option, section = section)))
00135     matches.sort()
00136     return [match[1] for match in matches]
00137 
00138   _regexp = re.compile("\\${(.*?)::(.*?)}")
00139 
00140   def _repl(self, m):
00141     """
00142     Replacement function for indirect variable substitution.
00143     This is intended for use with re.subn().
00144     """
00145     section, option = m.group(1, 2)
00146     if section == "ENV":
00147       return os.getenv(option, "")
00148     else:
00149       return self.cfg.get(section, option)
00150 
00151   def get(self, option, default = None, section = None):
00152     """
00153     Get an option, perhaps with a default value.
00154     """
00155     if section is None:
00156       section = self.default_section
00157     if default is not None and not self.cfg.has_option(section, option):
00158       return default
00159     val = self.cfg.get(section, option)
00160     while True:
00161       val, modified = self._regexp.subn(self._repl, val, 1)
00162       if not modified:
00163         return val
00164 
00165   def getboolean(self, option, default = None, section = None):
00166     """
00167     Get a boolean option, perhaps with a default value.
00168     """
00169     v = self.get(option, default, section)
00170     if isinstance(v, str):
00171       v = v.lower()
00172       if v not in self.cfg._boolean_states:
00173         raise ValueError, "Not a boolean: %s" % v
00174       v = self.cfg._boolean_states[v]
00175     return v
00176 
00177   def getint(self, option, default = None, section = None):
00178     """
00179     Get an integer option, perhaps with a default value.
00180     """
00181     return int(self.get(option, default, section))
00182 
00183   def getlong(self, option, default = None, section = None):
00184     """
00185     Get a long integer option, perhaps with a default value.
00186     """
00187     return long(self.get(option, default, section))
00188 
00189   def set_global_flags(self):
00190     """
00191     Consolidated control for all the little global control flags
00192     scattered through the libraries.  This isn't a particularly good
00193     place for this function to live, but it has to live somewhere and
00194     making it a method of the config parser from which it gets all of
00195     its data is less silly than the available alternatives.
00196     """
00197 
00198     import rpki.http, rpki.x509, rpki.sql, rpki.async
00199 
00200     try:
00201       rpki.http.debug_http = self.getboolean("debug_http")
00202     except ConfigParser.NoOptionError:
00203       pass
00204 
00205     try:
00206       rpki.http.want_persistent_client = self.getboolean("want_persistent_client")
00207     except ConfigParser.NoOptionError:
00208       pass
00209 
00210     try:
00211       rpki.http.want_persistent_server = self.getboolean("want_persistent_server")
00212     except ConfigParser.NoOptionError:
00213       pass
00214 
00215     try:
00216       rpki.http.use_adns = self.getboolean("use_adns")
00217     except ConfigParser.NoOptionError:
00218       pass
00219 
00220     try:
00221       rpki.http.enable_ipv6_clients = self.getboolean("enable_ipv6_clients")
00222     except ConfigParser.NoOptionError:
00223       pass
00224 
00225     try:
00226       rpki.http.enable_ipv6_servers = self.getboolean("enable_ipv6_servers")
00227     except ConfigParser.NoOptionError:
00228       pass
00229 
00230     try:
00231       rpki.x509.CMS_object.debug_cms_certs = self.getboolean("debug_cms_certs")
00232     except ConfigParser.NoOptionError:
00233       pass
00234 
00235     try:
00236       rpki.sql.sql_persistent.sql_debug = self.getboolean("sql_debug")
00237     except ConfigParser.NoOptionError:
00238       pass
00239 
00240     try:
00241       rpki.async.timer.gc_debug = self.getboolean("gc_debug")
00242     except ConfigParser.NoOptionError:
00243       pass
00244 
00245     try:
00246       rpki.async.timer.run_debug = self.getboolean("timer_debug")
00247     except ConfigParser.NoOptionError:
00248       pass
00249 
00250     try:
00251       rpki.x509.XML_CMS_object.dump_outbound_cms = rpki.x509.DeadDrop(self.get("dump_outbound_cms"))
00252     except ConfigParser.NoOptionError:
00253       pass
00254 
00255     try:
00256       rpki.x509.XML_CMS_object.dump_inbound_cms = rpki.x509.DeadDrop(self.get("dump_inbound_cms"))
00257     except ConfigParser.NoOptionError:
00258       pass
00259 
00260     try:
00261       rpki.async.gc_summary(self.getint("gc_summary"), self.getint("gc_summary_threshold", 0))
00262     except ConfigParser.NoOptionError:
00263       pass
 All Classes Namespaces Files Functions Variables