summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKamil Kisiel <kamil@kamilkisiel.net>2009-07-18 19:46:38 +0000
committerKamil Kisiel <kamil@kamilkisiel.net>2009-07-18 19:46:38 +0000
commit4819a99405a77e4fa8a710427304fac042375277 (patch)
tree829c89b0fe5d3c44344d8812f21e02aa1cc39353
parenta38b64f764bd3c77eaa95fce55c2e9065763d33f (diff)
downloadbcfg2-4819a99405a77e4fa8a710427304fac042375277.tar.gz
bcfg2-4819a99405a77e4fa8a710427304fac042375277.tar.bz2
bcfg2-4819a99405a77e4fa8a710427304fac042375277.zip
Merged bcfg2-admin init fixes in from my branch.
git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@5362 ce84e21b-d406-0410-9b95-82705330c041
-rw-r--r--src/lib/Server/Admin/Init.py289
-rwxr-xr-xsrc/sbin/bcfg2-admin74
2 files changed, 204 insertions, 159 deletions
diff --git a/src/lib/Server/Admin/Init.py b/src/lib/Server/Admin/Init.py
index b93f21825..e3ea6d7c0 100644
--- a/src/lib/Server/Admin/Init.py
+++ b/src/lib/Server/Admin/Init.py
@@ -8,13 +8,6 @@ import Bcfg2.Server.Admin
import Bcfg2.Server.Plugin
import Bcfg2.Options
-from Bcfg2.Server.Plugins import (Account, Base, Bundler, Cfg,
- Decisions, Deps, Metadata,
- Packages, Pkgmgr, Probes,
- Properties, Rules, Snapshots,
- SSHbase, Svcmgr, TCheetah,
- TGenshi)
-
# default config file
config = '''
[server]
@@ -48,6 +41,7 @@ key = %s/bcfg2.key
bcfg2 = %s
'''
+# Default groups
groups = '''<Groups version='3.0'>
<Group profile='true' public='true' default='true' name='basic'>
<Group name='%s'/>
@@ -63,11 +57,13 @@ groups = '''<Groups version='3.0'>
</Groups>
'''
+# Default contents of clients.xml
clients = '''<Clients version="3.0">
<Client profile="basic" pingable="Y" pingtime="0" name="%s"/>
</Clients>
'''
+# Mapping of operating system names to groups
os_list = [
('Redhat/Fedora/RHEL/RHAS/Centos', 'redhat'),
('SUSE/SLES', 'suse'),
@@ -78,6 +74,48 @@ os_list = [
('FreeBSD', 'freebsd')
]
+# Complete list of plugins
+plugin_list = ['Account', 'Base', 'Bundler', 'Cfg',
+ 'Decisions', 'Deps', 'Metadata', 'Packages',
+ 'Pkgmgr', 'Probes', 'Properties', 'Rules',
+ 'Snapshots', 'SSHbase', 'Statistics', 'Svcmgr',
+ 'TCheetah', 'TGenshi']
+
+# Default list of plugins to use
+default_plugins = ['SSHbase', 'Cfg', 'Pkgmgr', 'Rules',
+ 'Metadata', 'Base', 'Bundler']
+
+def gen_password(length):
+ """Generates a random alphanumeric password with length characters"""
+ chars = string.letters + string.digits
+ newpasswd = ''
+ for i in range(length):
+ newpasswd = newpasswd + random.choice(chars)
+ return newpasswd
+
+def create_key(keypath):
+ """Creates a bcfg2.key at the directory specifed by keypath"""
+ subprocess.call(("openssl " \
+ "req -x509 -nodes -days 1000 -newkey rsa:1024 " \
+ "-out %s/bcfg2.key -keyout %s/bcfg2.key" % \
+ (keypath, keypath)), shell=True)
+ os.chmod('%s/bcfg2.key' % keypath, 0600)
+
+def create_conf(confpath, confdata):
+ # don't overwrite existing bcfg2.conf file
+ if os.path.exists(confpath):
+ print("\nWarning: %s already exists. Will not be "
+ "overwritten...\n" % confpath)
+ else:
+ try:
+ open(confpath, "w").write(confdata)
+ os.chmod(confpath, 0600)
+ except Exception, e:
+ print("Error %s occured while trying to write configuration "
+ "file to '%s'\n" %
+ (e, confpath))
+ raise SystemExit(1)
+
class Init(Bcfg2.Server.Admin.Mode):
__shorthelp__ = ("Interactively initialize a new repository")
@@ -92,134 +130,133 @@ class Init(Bcfg2.Server.Admin.Mode):
}
repopath = ""
response = ""
-
+ def __init__(self, configfile):
+ Bcfg2.Server.Admin.Mode.__init__(self, configfile)
+
+ def _set_defaults(self):
+ """Set default parameters"""
+ self.configfile = self.opts['configfile']
+ self.repopath = self.opts['repo']
+ self.password = gen_password(8)
+ self.server_uri = "https://%s:6789" % socket.getfqdn()
+ self.plugins = default_plugins
+
def __call__(self, args):
Bcfg2.Server.Admin.Mode.__call__(self, args)
- opts = Bcfg2.Options.OptionParser(self.options)
- opts.parse([])
-
- configfile = raw_input("Store bcfg2 configuration in [%s]: " %
- opts['configfile'])
- if configfile == '':
- configfile = opts['configfile']
-
- self.repopath = raw_input("Location of bcfg2 repository [%s]: " %
- opts['repo'])
- if self.repopath == '':
- self.repopath = opts['repo']
- if os.path.isdir(self.repopath):
- self.response = raw_input("Directory %s exists. Overwrite? [Y/n]:"\
- % self.repopath)
-
- password = getpass.getpass(
+
+ # Parse options
+ self.opts = Bcfg2.Options.OptionParser(self.options)
+ self.opts.parse(args)
+ self._set_defaults()
+
+ # Prompt the user for input
+ self._prompt_config()
+ self._prompt_repopath()
+ self._prompt_password()
+ self._prompt_server()
+ self._prompt_groups()
+
+ # Initialize the repository
+ self.init_repo()
+
+ def _prompt_config(self):
+ """Ask for the configuration file path"""
+ newconfig = raw_input("Store bcfg2 configuration in [%s]: " %
+ self.configfile)
+ if newconfig != '':
+ self.configfile = newconfig
+
+ def _prompt_repopath(self):
+ """Ask for the repository path"""
+ while True:
+ newrepo = raw_input("Location of bcfg2 repository [%s]: " %
+ self.repopath)
+ if newrepo != '':
+ self.repopath = newrepo
+ if os.path.isdir(self.repopath):
+ response = raw_input("Directory %s exists. Overwrite? [y/N]:"\
+ % self.repopath)
+ if response.lower().strip() == 'y':
+ break
+ else:
+ break
+
+ def _prompt_password(self):
+ """Ask for a password or generate one if none is provided"""
+ newpassword = getpass.getpass(
"Input password used for communication verification "
- "(without echoing; leave blank for a random): ")
- if len(password.strip()) == 0:
- password = self.genPassword()
+ "(without echoing; leave blank for a random): ").strip()
+ if len(newpassword) != 0:
+ self.password = newpassword
- server = "https://%s:6789" % socket.getfqdn()
- rs = raw_input( "Input the server location [%s]: " % server)
- if rs:
- server = rs
-
- # create the groups.xml file
+ def _prompt_server(self):
+ """Ask for the server name"""
+ newserver = raw_input( "Input the server location [%s]: " % self.server_uri)
+ if newserver != '':
+ self.server_uri = newserver
+
+ def _prompt_groups(self):
+ """Create the groups.xml file"""
prompt = '''Input base Operating System for clients:\n'''
for entry in os_list:
prompt += "%d: %s\n" % (os_list.index(entry) + 1, entry[0])
prompt += ': '
- os_sel = os_list[int(raw_input(prompt))-1][1]
- self.initializeRepo(configfile, self.repopath, server,
- password, os_sel, opts)
-
- def genPassword(self):
- chars = string.letters + string.digits
- newpasswd = ''
- for i in range(8):
- newpasswd = newpasswd + random.choice(chars)
- return newpasswd
-
- def initializeRepo(self, configfile, repo, server_uri,
- password, os_selection, opts):
- '''Setup a new repo'''
- keypath = os.path.dirname(os.path.abspath(configfile))
+ while True:
+ try:
+ self.os_sel = os_list[int(raw_input(prompt))-1][1]
+ break
+ except ValueError:
+ continue
+
+ def _prompt_plugins(self):
+ default = raw_input("Use default plugins? (%s) [Y/n]: " % ''.join(default_plugins)).lower()
+ if default != 'y' or default != '':
+ while True:
+ plugins_are_valid = True
+ plug_str = raw_input("Specify plugins: ")
+ plugins = plug_str.split(',')
+ for plugin in plugins:
+ plugin = plugin.strip()
+ if not plugin in plugin_list:
+ plugins_are_valid = False
+ print "ERROR: plugin %s not recognized" % plugin
+ if plugins_are_valid:
+ break
+ def _init_plugins(self):
+ # Initialize each plugin-specific portion of the repository
+ for plugin in self.plugins:
+ if plugin == 'Metadata':
+ Bcfg2.Server.Plugins.Metadata.Metadata.init_repo(self.repopath, groups, self.os_sel, clients)
+ else:
+ try:
+ module = __import__("Bcfg2.Server.Plugins.%s" % plugin, fromlist=["Bcfg2.Server.Plugins"])
+ cls = getattr(module, plugin)
+ cls.init_repo(self.repopath)
+ except Exception, e:
+ print 'Plugin setup for %s failed: %s\n Check that dependencies are installed?' % (plugin, e)
+
+ def init_repo(self):
+ '''Setup a new repo'''
+ # Create the contents of the configuration file
+ keypath = os.path.dirname(os.path.abspath(self.configfile))
confdata = config % (
- repo, ','.join(opts['plugins']),
- opts['sendmail'], opts['proto'],
- password, keypath, keypath, server_uri
+ self.repopath,
+ ','.join(self.opts['plugins']),
+ self.opts['sendmail'],
+ self.opts['proto'],
+ self.password,
+ keypath,
+ keypath,
+ self.server_uri
)
- # don't overwrite existing bcfg2.conf file
- if os.path.exists(configfile):
- print("\nWarning: %s already exists. Will not be "
- "overwritten...\n" % configfile)
- else:
- try:
- open(configfile, "w").write(confdata)
- os.chmod(configfile, 0600)
- except Exception, e:
- print("Error %s occured while trying to write configuration "
- "file to '%s'\n" %
- (e, configfile))
-
- # FIXME automate ssl key generation
- # FIXME key generation may fail as non-root user
- subprocess.call(("openssl " \
- "req -x509 -nodes -days 1000 -newkey rsa:1024 " \
- "-out %s/bcfg2.key -keyout %s/bcfg2.key" % \
- (keypath, keypath)), shell=True)
- try:
- os.chmod('%s/bcfg2.key'% keypath, 0600)
- except:
- pass
-
- # Overwrite existing directory/repo?
- if self.response == "n":
- print "Kept old repository in %s" % (self.repopath)
- return
- else:
- # FIXME repo creation may fail as non-root user
- plug_list = ['Account', 'Base', 'Bundler', 'Cfg',
- 'Decisions', 'Deps', 'Metadata', 'Packages',
- 'Pkgmgr', 'Probes', 'Properties', 'Rules',
- 'Snapshots', 'SSHbase', 'Statistics', 'Svcmgr',
- 'TCheetah', 'TGenshi']
- default_repo = ['SSHbase', 'Cfg', 'Pkgmgr', 'Rules',
- 'Metadata', 'Base', 'Bundler']
- plugins = []
- print 'Repository configuration, choose plugins:'
- default = raw_input("Use default plugins? [Y/n]: ").lower()
- if default == 'y' or default == '':
- plugins = default_repo
- else:
- while True:
- plugins_are_valid = True
- plug_str = raw_input("Specify plugins: ")
- plugins = plug_str.split(',')
- for plugin in plugins:
- plugin = plugin.strip()
- if not plugin in plug_list:
- plugins_are_valid = False
- print "ERROR: plugin %s not recognized" % plugin
- if plugins_are_valid:
- break
-
- path = "%s/%s" % (repo, 'etc')
- newpath = ''
- for subdir in path.split('/'):
- newpath = newpath + subdir + '/'
- try:
- os.mkdir(newpath)
- except:
- continue
-
- for plugin in plugins:
- if plugin == 'Metadata':
- Bcfg2.Server.Plugins.Metadata.Metadata.init_repo(repo, groups, os_selection, clients)
- else:
- try:
- getattr(getattr(getattr(Bcfg2.Server.Plugins, plugin), plugin), 'init_repo')(repo)
- except:
- print 'Plugin setup for %s failed. Check that dependencies are installed?' % plugin
-
- print "Repository created successfuly in %s" % (self.repopath)
+ # Create the configuration file and SSL key
+ create_conf(self.configfile, confdata)
+ create_key(keypath)
+
+ # Create the repository
+ path = "%s/%s" % (self.repopath, 'etc')
+ os.makedirs(path)
+ self._init_plugins()
+ print "Repository created successfuly in %s" % (self.repopath)
diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin
index dcbe6b48a..c5c03c4cd 100755
--- a/src/sbin/bcfg2-admin
+++ b/src/sbin/bcfg2-admin
@@ -1,14 +1,15 @@
#!/usr/bin/env python
'''bcfg2-admin is a script that helps to administrate a bcfg2 deployment'''
-import getopt
+from optparse import OptionParser
+from StringIO import StringIO
import logging
import sys
import Bcfg2.Server.Core
import Bcfg2.Logger
import Bcfg2.Options
-log = logging.getLogger('bcfg-admin')
+log = logging.getLogger('bcfg2-admin')
import Bcfg2.Server.Admin
@@ -19,50 +20,57 @@ def mode_import(modename):
(modname)).Server.Admin, modname)
return getattr(mod, modname)
-if __name__ == '__main__':
- Bcfg2.Logger.setup_logging('bcfg2-admin', to_console=True, level=40)
- avail_opts = {'-C <configfile>': 'Set alternate bcfg2.conf location'}
- # Get config file path
- configfile = Bcfg2.Options.CFILE.default
- try:
- opts, args = getopt.getopt(sys.argv[1:], 'hC:', ['help', 'configfile='])
- except getopt.GetoptError, msg:
- print(msg)
- raise SystemExit(1)
+def get_modes():
+ """Get all available modes, except for the base mode"""
+ return [x.lower() for x in Bcfg2.Server.Admin.__all__ if x != 'mode']
+def create_description():
+ """Create the description string from the list of modes"""
+ modes = get_modes()
+ description = StringIO()
+ description.write("Available modes are:\n\n")
+ for mode in modes:
+ try:
+ description.write((" %-15s %s\n" %
+ (mode, mode_import(mode).__shorthelp__)))
+ except ImportError:
+ continue
+ return description.getvalue()
- # First get the options...
- for opt, arg in opts:
- if opt in ("-C", "--configfile"):
- configfile = arg
-
- modes = [x.lower() for x in Bcfg2.Server.Admin.__all__]
- modes.remove('mode')
+def main():
+ Bcfg2.Logger.setup_logging('bcfg2-admin', to_console=True, level=40)
+ usage="Usage: %prog [options] MODE [args]"
+ parser = OptionParser(usage=usage)
+ parser.set_defaults(configfile=Bcfg2.Options.CFILE.default)
+ parser.add_option("-C", "--configfile", dest="configfile", help="Path to bcfg2.conf", metavar="FILE")
+ parser.disable_interspersed_args()
+ (options, args) = parser.parse_args()
+ # Provide help if requested or no args were specified
if len(args) < 1 or args[0] == 'help':
- print ("Usage: bcfg2-admin [OPTIONS] MODE [ARGS]\n\n"
- "Available options are:")
- for (opt, arg) in list(avail_opts.items()):
- print((" %-15s " % opt + arg))
- print ("\nAvailable modes are:")
if len(args) > 1:
+ # Get help for a specific mode by passing it the help argument
args = [args[1], args[0]]
else:
- for mode in modes:
- try:
- print((" %-15s %s" %
- (mode, mode_import(mode).__shorthelp__)))
- except ImportError:
- continue
+ # Print short help for all modes
+ parser.print_help()
+ print create_description()
raise SystemExit(0)
- if args[0] in modes:
+
+ if args[0] in get_modes():
modname = args[0].capitalize()
try:
mode_cls = mode_import(modname)
except ImportError, e:
log.error("Failed to load admin mode %s: %s" % (modname, e))
- mode = mode_cls(configfile)
+ raise SystemExit(1)
+ mode = mode_cls(options.configfile)
mode(args[1:])
else:
- print("unknown mode %s" % args[0])
+ log.error("Unknown mode %s" % args[0])
+ parser.print_help()
+ print create_description()
+ raise SystemExit(1)
+if __name__ == '__main__':
+ main()