summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/Client/Proxy.py62
-rw-r--r--src/lib/Component.py39
-rw-r--r--src/lib/Options.py25
-rw-r--r--src/lib/Server/Admin/__init__.py2
-rw-r--r--src/lib/Server/Core.py23
-rw-r--r--src/lib/Server/Plugins/Metadata.py6
-rw-r--r--src/lib/Settings.py145
-rwxr-xr-xsrc/sbin/bcfg210
-rwxr-xr-xsrc/sbin/bcfg2-info10
-rwxr-xr-xsrc/sbin/bcfg2-server9
10 files changed, 217 insertions, 114 deletions
diff --git a/src/lib/Client/Proxy.py b/src/lib/Client/Proxy.py
index b56ccbfa5..8e34a0fb5 100644
--- a/src/lib/Client/Proxy.py
+++ b/src/lib/Client/Proxy.py
@@ -6,6 +6,7 @@ from Bcfg2.tlslite.integration.XMLRPCTransport import XMLRPCTransport
from Bcfg2.tlslite.integration.HTTPTLSConnection import HTTPTLSConnection
from Bcfg2.tlslite.TLSConnection import TLSConnection
import Bcfg2.tlslite.errors
+from Bcfg2.Settings import settings
#FIXME need to reimplement _binadaddress support for XMLRPCTransport
@@ -49,63 +50,36 @@ class SafeProxy:
_retries = 4
_authinfo = ()
- _components = {}
def __init__(self, component, args={}):
self.component = component
self.log = logging.getLogger(component)
- if args.has_key('server'):
- # processing from command line args
- self._components[component] = args['server']
- else:
- if args.has_key('setup'):
- # processing from specified config file
- _cfpath = args['setup']
- else:
- _cfpath = '/etc/bcfg2.conf'
- self._cfile = ConfigParser.ConfigParser()
- self._cfile.read([_cfpath])
- try:
- self._components = self._cfile._sections['components']
- except:
- self.log.error("%s doesn't contain a valid components section" % (_cfpath))
- raise SystemExit, 1
- if args.has_key('password'):
- # get passwd from cmdline
+ password = settings.COMMUNICATION_PASSWORD
+ if args['password']:
password = args['password']
- else:
- try:
- password = self._cfile.get('communication', 'password')
- except:
- self.log.error("%s doesn't contain a valid password" % (_cfpath))
- raise SystemExit, 1
- if args.has_key('user'):
+
+ user = settings.COMMUNICATION_USER
+ if args['user']:
user = args['user']
- else:
- try:
- user = self._cfile.get('communication', 'user')
- except:
- user = 'root'
self._authinfo = (user, password)
- if args.has_key('fingerprint'):
+ self.fingerprint = False
+ if args['fingerprint']:
self.fingerprint = args['fingerprint']
- else:
- self.fingerprint = False
- _bindaddress = ""
- try:
- _bindaddress = self._cfile.get('communication', 'bindaddress')
- except:
- pass
-
- if args.has_key('server'):
+ address = settings.COMPONENTS_BCFG2
+ if args['server']:
address = args['server']
- else:
- address = self.__get_location(component)
-
+
+ # NOT USED
+ #_bindaddress = ""
+ #try:
+ # _bindaddress = self._cfile.get('communication', 'bindaddress')
+ #except:
+ # pass
try:
+ # NOT USED
# if _bindaddress != "":
# self.log.info("Binding client to address %s" % _bindaddress)
# self.proxy = xmlrpclib.ServerProxy(address, transport=Bcfg2SafeTransport())
diff --git a/src/lib/Component.py b/src/lib/Component.py
index a6f3e9aa2..442ea8112 100644
--- a/src/lib/Component.py
+++ b/src/lib/Component.py
@@ -3,6 +3,7 @@ __revision__ = '$Revision$'
import atexit, logging, select, signal, socket, sys, time, urlparse, xmlrpclib, cPickle, ConfigParser, os
from base64 import decodestring
+
import BaseHTTPServer, SimpleXMLRPCServer
import Bcfg2.tlslite.errors
import Bcfg2.tlslite.api
@@ -10,6 +11,8 @@ import Bcfg2.tlslite.api
import Bcfg2.Client.Proxy as Proxy
from Bcfg2.tlslite.TLSConnection import TLSConnection
+from Bcfg2.Settings import settings
+
log = logging.getLogger('Component')
class ComponentInitError(Exception):
@@ -144,34 +147,20 @@ class Component(TLSServer,
signal.signal(signal.SIGINT, self.start_shutdown)
signal.signal(signal.SIGTERM, self.start_shutdown)
self.logger = logging.getLogger('Component')
- self.cfile = ConfigParser.ConfigParser()
self.children = []
- if setup['configfile']:
- cfilename = setup['configfile']
- else:
- cfilename = '/etc/bcfg2.conf'
- self.cfile.read([cfilename])
- if not self.cfile.has_section('communication'):
- print "Configfile missing communication section"
- raise SystemExit, 1
- self.static = False
- if not self.cfile.has_section('components'):
- print "Configfile missing components section"
- raise SystemExit, 1
- if self.cfile._sections['components'].has_key(self.__name__):
- self.static = True
- location = urlparse.urlparse(self.cfile.get('components', self.__name__))[1].split(':')
+ self.static = True
+
+ location = settings.COMPONENTS_BCFG2
+ if settings.COMPONENTS_BCFG2_STATIC:
+ location = urlparse.urlparse(settings.COMPONENTS_BCFG2)[1].split(':')
location = (location[0], int(location[1]))
- else:
- location = (socket.gethostname(), 0)
- try:
- keyfile = self.cfile.get('communication', 'key')
- #keyfile = '/tmp/keys/server.pkey'
- except ConfigParser.NoOptionError:
- print "No key specified in cobalt.conf"
+
+ if not settings.COMMUNICATION_KEY:
+ print "No key specified in '%s'" % settings.CONFIG_FILE
raise SystemExit, 1
+ keyfile = settings.COMMUNICATION_KEY
- self.password = self.cfile.get('communication', 'password')
+ self.password = settings.COMMUNICATION_PASSWORD
try:
TLSServer.__init__(self, location, keyfile, CobaltXMLRPCRequestHandler)
@@ -182,7 +171,7 @@ class Component(TLSServer,
self.logger.error("Failed to parse key" % (keyfile))
raise ComponentInitError
except:
- self.logger.error("Failed to load ssl key %s" % (keyfile), exc_info=1)
+ self.logger.error("Failed to load ssl key '%s'" % (keyfile), exc_info=1)
raise ComponentInitError
try:
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self)
diff --git a/src/lib/Options.py b/src/lib/Options.py
index 4c97b1ca5..aab329f4d 100644
--- a/src/lib/Options.py
+++ b/src/lib/Options.py
@@ -2,20 +2,15 @@
__revision__ = '$Revision$'
import getopt, os, sys, ConfigParser
-# (option, env, cfpath, default value, option desc, boolean, arg desc)
-# ((option, arg desc, opt desc), env, cfpath, default, boolean)
-bootstrap = {'configfile': (('-C', '<configfile>', 'Path to config file'),
- 'BCFG2_CONF', False, '/etc/bcfg2.conf', False)}
class OptionFailure(Exception):
pass
class BasicOptionParser:
'''Basic OptionParser takes input from command line arguments, environment variables, and defaults'''
- def __init__(self, name, optionspec, configfile=False, dogetopt=False):
+ def __init__(self, name, optionspec, dogetopt=False):
self.name = name
self.dogetopt = dogetopt
- self.configfile = configfile
self.optionspec = optionspec
if dogetopt:
self.shortopt = ''
@@ -52,13 +47,6 @@ class BasicOptionParser:
print "%s Usage:" % (self.name)
print self.helpmsg
raise SystemExit, 1
- if self.configfile:
- cf = ConfigParser.ConfigParser()
- try:
- cf.readfp(open(self.configfile))
- except Exception, e:
- print "Failed to read configfile: %s\n%s\n" % (self.configfile, e)
- raise SystemExit, 1
for key, (option, envvar, cfpath, default, boolean) in self.optionspec.iteritems():
if self.dogetopt:
optinfo = [opt[1] for opt in opts if opt[0] == option[0]]
@@ -77,19 +65,10 @@ class BasicOptionParser:
if envvar and os.environ.has_key(envvar):
ret[key] = os.environ[envvar]
continue
- if self.configfile and cfpath:
- try:
- value = apply(cf.get, cfpath)
- ret[key] = value
- continue
- except:
- pass
ret[key] = default
return ret
class OptionParser(BasicOptionParser):
'''OptionParser bootstraps option parsing, getting the value of the config file'''
def __init__(self, name, ospec):
- # first find the cf file
- cfpath = BasicOptionParser('bootstrap', bootstrap).parse()['configfile']
- BasicOptionParser.__init__(self, name, ospec, cfpath, dogetopt=True)
+ BasicOptionParser.__init__(self, name, ospec, dogetopt=True)
diff --git a/src/lib/Server/Admin/__init__.py b/src/lib/Server/Admin/__init__.py
index d059e0a1d..57b9d2a86 100644
--- a/src/lib/Server/Admin/__init__.py
+++ b/src/lib/Server/Admin/__init__.py
@@ -1,4 +1,4 @@
-__revision__ = '$Revision: $'
+__revision__ = '$Revision$'
__all__ = ['Mode', 'Client', 'Compare', 'Fingerprint', 'Init', 'Minestruct',
'Pull', 'Tidy', 'Viz']
diff --git a/src/lib/Server/Core.py b/src/lib/Server/Core.py
index 76cbb8073..7e347bc23 100644
--- a/src/lib/Server/Core.py
+++ b/src/lib/Server/Core.py
@@ -4,6 +4,7 @@ __revision__ = '$Revision$'
from time import time
from Bcfg2.Server.Plugin import PluginInitError, PluginExecutionError
from Bcfg2.Server.Statistics import Statistics
+from Bcfg2.Settings import settings
import logging, lxml.etree, os, stat, ConfigParser
import Bcfg2.Server.Plugins.Metadata
@@ -198,11 +199,9 @@ except ImportError:
class Core(object):
'''The Core object is the container for all Bcfg2 Server logic, and modules'''
- def __init__(self, setup, configfile):
+ def __init__(self):
object.__init__(self)
- self.cfile = ConfigParser.ConfigParser()
- self.cfile.read([configfile])
- self.datastore = self.cfile.get('server','repository')
+ self.datastore = settings.SERVER_REPOSITORY
try:
self.fam = monitor()
except IOError:
@@ -211,20 +210,22 @@ class Core(object):
self.generators = []
self.structures = []
self.cron = {}
- self.setup = setup
self.plugins = {}
self.revision = '-1'
+
try:
- self.svn = self.cfile.get('server', 'svn') == 'yes'
- self.read_svn_revision()
+ if settings.SERVER_SVN:
+ self.read_svn_revision()
except:
- self.svn = False
+ settings.SERVER_SVN = False
+
+ self.svn = settings.SERVER_SVN
- mpath = self.cfile.get('server','repository')
+ mpath = settings.SERVER_REPOSITORY
self.stats = Statistics("%s/etc/statistics.xml" % (mpath))
- structures = self.cfile.get('server', 'structures').replace(' ', '').split(',')
- generators = self.cfile.get('server', 'generators').replace(' ', '').split(',')
+ structures = settings.SERVER_STRUCTURES
+ generators = settings.SERVER_GENERATORS
[data.remove('') for data in [structures, generators] if '' in data]
for plugin in structures + generators + ['Metadata']:
diff --git a/src/lib/Server/Plugins/Metadata.py b/src/lib/Server/Plugins/Metadata.py
index ce9d18f7a..5f3262ec0 100644
--- a/src/lib/Server/Plugins/Metadata.py
+++ b/src/lib/Server/Plugins/Metadata.py
@@ -1,7 +1,9 @@
'''This file stores persistent metadata for the BCFG Configuration Repository'''
__revision__ = '$Revision$'
-import lxml.etree, re, socket, time, sys, ConfigParser
+from Bcfg2.Settings import settings
+
+import lxml.etree, re, socket, time, sys
import Bcfg2.Server.Plugin
class MetadataConsistencyError(Exception):
@@ -67,7 +69,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin):
self.ptimes = {}
self.pctime = 0
self.extra = {'groups.xml':[], 'clients.xml':[]}
- self.password = core.cfile.get('communication', 'password')
+ self.password = settings.COMMUNICATION_PASSWORD
def HandleEvent(self, event):
'''Handle update events for data files'''
diff --git a/src/lib/Settings.py b/src/lib/Settings.py
new file mode 100644
index 000000000..4a47c6f8d
--- /dev/null
+++ b/src/lib/Settings.py
@@ -0,0 +1,145 @@
+"""
+Settings for bcfg2.
+FIXME: simplify code!
+FIXME: add statistics configuration
+"""
+
+__revision__ = '$Revision$'
+
+import logging, socket, ConfigParser
+
+class Settings(object):
+
+ def __init__(self):
+ self.CONFIG_FILE = self.default_config_file()
+
+ self.SERVER_GENERATORS = self.default_server_generators()
+ self.SERVER_REPOSITORY = self.default_server_repository()
+ self.SERVER_STRUCTURES = self.default_server_structures()
+ self.SERVER_SVN = self.default_server_svn()
+
+ self.COMMUNICATION_KEY = self.default_communication_key()
+ self.COMMUNICATION_PASSWORD = self.default_communication_password()
+ self.COMMUNICATION_PROTOCOL = self.default_communication_protocol()
+ self.COMMUNICATION_USER = self.default_communication_user()
+
+ self.COMPONENTS_BCFG2 = self.default_components_bcfg2()
+ self.COMPONENTS_BCFG2_STATIC = self.default_components_bcfg2_static()
+
+
+ def __getattr__(self, name):
+ print "name = %s\n" % name
+ if name == '__members__':
+ return self.name()
+ return getattr(self, name)
+
+ def read_config_file(self, filename):
+
+ logger = logging.getLogger('bcfg2 settings')
+
+ # set config file
+ if not filename:
+ logger.info("No config file given. Trying default config file '%s'." % self.CONFIG_FILE)
+ else:
+ logger.debug("Trying user specified config file '%s'." % filename)
+ self.CONFIG_FILE = filename
+
+ # open config file
+ try:
+ cf = open(self.CONFIG_FILE)
+ except IOError:
+ logger.info("Skipping not accessable config file '%s'." % self.CONFIG_FILE)
+ return
+
+ # parse config file
+ cfp = ConfigParser.ConfigParser()
+ try:
+ cfp.readfp(cf)
+ except Exception, e:
+ logger.error("Content of config file '%s' is not valid. Correct it!\n%s\n" % (self.CONFIG_FILE, e))
+ raise SystemExit, 1
+ # communication config
+ if cfp.has_section('communication'):
+ try:
+ self.COMMUNICATION_PROTOCOL = cfp.get('communication','protocol')
+ except:
+ pass
+ try:
+ self.COMMUNICATION_PASSWORD = cfp.get('communication','password')
+ except:
+ pass
+ try:
+ self.COMMUNICATION_KEY = cfp.get('communication','key')
+ except:
+ pass
+ try:
+ self.COMMUNICATION_USER = cfp.get('communication','user')
+ except:
+ pass
+ # components config
+ if cfp.has_section('components'):
+ try:
+ self.COMPONENTS_BCFG2 = cfp.get('components', 'bcfg2')
+ self.COMPONENTS_BCFG2_STATIC = True
+ except:
+ pass
+ # server config
+ if cfp.has_section('server'):
+ try:
+ self.SERVER_GENERATORS = cfp.get('server','generators').replace(' ','').split(',')
+ except:
+ pass
+ try:
+ self.SERVER_REPOSITORY = cfp.get('server','repository')
+ except:
+ pass
+ try:
+ self.SERVER_STRUCTURES = cfp.get('server','structures').replace(' ','').split(',')
+ except:
+ pass
+ try:
+ self.SERVER_SVN = cfp.get('server','svn')
+ except:
+ pass
+
+ return
+
+ def default_config_file(self):
+ return '/etc/bcfg2.conf'
+
+ def default_server_generators(self):
+ return ['SSHbase', 'Cfg', 'Pkgmgr', 'Rules']
+
+ def default_server_structures(self):
+ return ['Bundler', 'Base']
+
+ def default_server_repository(self):
+ return '/var/lib/bcfg2/'
+
+ def default_communication_key(self):
+ return False
+
+ def default_communication_password(self):
+ return 'password'
+
+ def default_communication_protocol(self):
+ return 'xmlrpc/ssl'
+
+ def default_communication_user(self):
+ return 'root'
+
+ def default_components_bcfg2(self):
+ return (socket.gethostname(), 0)
+
+ def default_components_bcfg2_static(self):
+ return False
+
+ def default_sendmail_path(self):
+ return '/usr/sbin/sendmail'
+
+ def default_server_svn(self):
+ return None
+
+
+
+settings = Settings()
diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2
index a25bab65f..62f2e1775 100755
--- a/src/sbin/bcfg2
+++ b/src/sbin/bcfg2
@@ -78,11 +78,11 @@ class Client:
'setup': (('-C', '<configfile>', "use given config file (default /etc/bcfg2.conf)"),
False, False, '/etc/bcfg2.conf', False),
'server': (('-S', '<server url>', 'the server hostname to connect to'),
- False, ('components', 'bcfg2'), 'https://localhost:6789', False),
+ False, ('components', 'bcfg2'), False, False),
'user': (('-u', '<user>', 'the user to provide for authentication'),
- False, ('communication', 'user'), 'root', False),
+ False, ('communication', 'user'), False, False),
'password': (('-x', '<password>', 'the password to provide for authentication'),
- False, ('communication', 'password'), 'password', False),
+ False, ('communication', 'password'), False, False),
'retries': (('-R', '<numretries>', 'the number of times to retry network communication'),
False, ('communication', 'retries'), '3', False),
'kevlar': (('-k', False, "run in kevlar (bulletproof) mode"),
@@ -99,6 +99,10 @@ class Client:
optparser = Bcfg2.Options.OptionParser('bcfg2', optinfo)
self.setup = optparser.parse()
+
+ # override default settings
+ settings.read_config_file(self.setup['setup'])
+
if getopt.getopt(sys.argv[1:],
optparser.shortopt, optparser.longopt)[1]:
print "Bcfg2 takes no arguments, only options"
diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info
index f40ef3e60..6693efea2 100755
--- a/src/sbin/bcfg2-info
+++ b/src/sbin/bcfg2-info
@@ -6,6 +6,7 @@ import copy, logging, lxml.etree, sys, time, cmd
import Bcfg2.Logging, Bcfg2.Server.Core, os
import Bcfg2.Server.Plugins.Metadata, Bcfg2.Server.Plugin
import Bcfg2.Options
+from Bcfg2.Settings import settings
logger = logging.getLogger('bcfg2-info')
@@ -23,10 +24,10 @@ def printTabular(rows):
print fstring % row
class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core):
- def __init__(self, cfpath):
+ def __init__(self):
cmd.Cmd.__init__(self)
try:
- Bcfg2.Server.Core.Core.__init__(self, {}, cfpath)
+ Bcfg2.Server.Core.Core.__init__(self)
except Bcfg2.Server.Core.CoreInitError, msg:
print "Core load failed because %s" % msg
raise SystemExit(1)
@@ -270,6 +271,9 @@ if __name__ == '__main__':
optparser = Bcfg2.Options.OptionParser('bcfg2-info', optinfo)
setup = optparser.parse()
- loop = infoCore(setup['configfile'])
+ # override default settings
+ settings.read_config_file(setup['configfile'])
+
+ loop = infoCore()
loop.plugins['Metadata'].load_probedata()
loop.do_loop()
diff --git a/src/sbin/bcfg2-server b/src/sbin/bcfg2-server
index e6a00efbc..554a5ae24 100755
--- a/src/sbin/bcfg2-server
+++ b/src/sbin/bcfg2-server
@@ -5,6 +5,7 @@ __revision__ = '$Revision$'
import Bcfg2.Server.Plugins.Metadata
+from Bcfg2.Settings import settings
from Bcfg2.Server.Core import Core, CoreInitError
from xmlrpclib import Fault
from lxml.etree import XML, Element, tostring
@@ -39,7 +40,7 @@ class Bcfg2Serv(Bcfg2.Component.Component):
raise SetupError
try:
- self.Core = Core(setup, setup['configfile'])
+ self.Core = Core()
except CoreInitError, msg:
logger.critical("Fatal error: %s" % (msg))
raise SystemExit, 1
@@ -184,7 +185,7 @@ if __name__ == '__main__':
'daemon': (('-D', '<pidfile>', 'daemonize the server, storing PID'),
False, False, False, False),
'configfile': (('-C', '<conffile>', 'use this config file'),
- False, False, '/etc/bcfg2.conf', False),
+ False, False, False, False),
}
SSETUP = Bcfg2.Options.OptionParser('bcfg2', OPTINFO).parse()
@@ -195,6 +196,10 @@ if __name__ == '__main__':
Bcfg2.Logging.setup_logging('bcfg2-server', level=level)
if SSETUP['daemon']:
Bcfg2.Daemon.daemonize(SSETUP['daemon'])
+
+ # override default settings
+ settings.read_config_file(SSETUP['configfile'])
+
try:
BSERV = Bcfg2Serv(SSETUP)
except SetupError: