Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Separate home/ for standalone broker. Some code dupe at the moment bu…

…t pynimbusconfig should be what everything uses going foward.
  • Loading branch information...
commit dd82e1a6abab67621fdc7c1e60b46fff6aeb1038 1 parent b4def17
@timf timf authored
Showing with 3,293 additions and 0 deletions.
  1. +38 −0 ctx-broker/home/bin/broker-configure
  2. +28 −0 ctx-broker/home/bin/brokerctl
  3. +594 −0 ctx-broker/home/lib/ProcessManager.py
  4. +83 −0 ctx-broker/home/lib/brokerctl.py
  5. +3 −0  ctx-broker/home/lib/pynimbusconfig/README
  6. 0  ctx-broker/home/lib/pynimbusconfig/__init__.py
  7. +273 −0 ctx-broker/home/lib/pynimbusconfig/autoca.py
  8. 0  ctx-broker/home/lib/pynimbusconfig/broker/__init__.py
  9. +579 −0 ctx-broker/home/lib/pynimbusconfig/broker/main.py
  10. +92 −0 ctx-broker/home/lib/pynimbusconfig/checkssl.py
  11. +72 −0 ctx-broker/home/lib/pynimbusconfig/ezpz_ca.py
  12. +29 −0 ctx-broker/home/lib/pynimbusconfig/forcessl.py
  13. +133 −0 ctx-broker/home/lib/pynimbusconfig/gtcontainer.py
  14. 0  ctx-broker/home/lib/pynimbusconfig/iaas/__init__.py
  15. +85 −0 ctx-broker/home/lib/pynimbusconfig/iaas/derbyutil.py
  16. +169 −0 ctx-broker/home/lib/pynimbusconfig/iaas/groupauthz.py
  17. +422 −0 ctx-broker/home/lib/pynimbusconfig/iaas/main.py
  18. +39 −0 ctx-broker/home/lib/pynimbusconfig/javautil.py
  19. +194 −0 ctx-broker/home/lib/pynimbusconfig/pathutil.py
  20. +196 −0 ctx-broker/home/lib/pynimbusconfig/runutil.py
  21. +57 −0 ctx-broker/home/lib/pynimbusconfig/setuperrors.py
  22. 0  ctx-broker/home/lib/pynimbusconfig/test/__init__.py
  23. +73 −0 ctx-broker/home/lib/pynimbusconfig/test/test_groupauthz.py
  24. 0  ctx-broker/home/lib/pynimbusconfig/web/__init__.py
  25. +95 −0 ctx-broker/home/lib/pynimbusconfig/web/newconf.py
  26. +17 −0 ctx-broker/home/lib/run-broker.sh
  27. +22 −0 ctx-broker/home/lib/run-pynimbusconfig-tests.sh
View
38 ctx-broker/home/bin/broker-configure
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+PYTHON_EXE="/usr/bin/env python -Wignore::DeprecationWarning"
+
+NIMBUS_HOME_REL="`dirname $0`/.."
+NIMBUS_HOME=`cd $NIMBUS_HOME_REL; pwd`
+
+if [ -d $NIMBUS_HOME/lib/pynimbusconfig ]; then
+ NIMBUS_PYLIB=$NIMBUS_HOME/lib
+else
+ echo "Cannot locate Python lib directory"
+ exit 1
+fi
+
+PYTHONPATH="$NIMBUS_PYLIB:$PYTHONPATH"
+export PYTHONPATH
+
+# returns 0 if Python 2.5+
+$PYTHON_EXE -c "import sys; sys.exit(sys.version_info < (2,5))"
+if [ $? -ne 0 ]; then
+ echo "ERROR: Your system must have Python version 2.5 or later."
+ exit 1
+fi
+
+$PYTHON_EXE $NIMBUS_HOME/lib/pynimbusconfig/broker/main.py --basedir $NIMBUS_HOME $@
+EXITCODE=$?
+if [ $EXITCODE -ne 42 ]; then
+
+ if [ $EXITCODE -eq 0 ]; then
+ exit 0
+ else
+ echo ""
+ echo "Nimbus is not set up properly, exiting."
+ exit 2
+ fi
+fi
+
+
View
28 ctx-broker/home/bin/brokerctl
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+PYTHON_EXE="/usr/bin/env python -Wignore::DeprecationWarning"
+
+NIMBUS_HOME_REL="`dirname $0`/.."
+NIMBUS_HOME=`cd $NIMBUS_HOME_REL; pwd`
+
+export NIMBUS_HOME
+
+if [ -d $NIMBUS_HOME/lib/pynimbusconfig ]; then
+ NIMBUS_PYLIB=$NIMBUS_HOME/lib
+else
+ echo "Cannot locate Python lib directory"
+ exit 1
+fi
+
+PYTHONPATH="$NIMBUS_PYLIB:$PYTHONPATH"
+export PYTHONPATH
+
+# returns 0 if Python 2.5+
+$PYTHON_EXE -c "import sys; sys.exit(sys.version_info < (2,5))"
+if [ $? -ne 0 ]; then
+ echo "ERROR: Your system must have Python version 2.5 or later."
+ exit 1
+fi
+
+$PYTHON_EXE $NIMBUS_HOME/lib/brokerctl.py $@
+exit $?
View
594 ctx-broker/home/lib/ProcessManager.py
@@ -0,0 +1,594 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2006, Humanized, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+#
+# * Neither the name of Humanized, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+#
+# ProcessManager.py
+# Author: Atul Varma <atul@humanized.com>
+#
+# Python Version - 2.4
+#
+# ----------------------------------------------------------------------------
+
+"""
+ A simple module for process management. Please see the file
+ README.txt, included with this distribution, for more
+ information. This file is also available at the following
+ location:
+
+ http://www.humanized.com/ProcessManager
+"""
+
+# ----------------------------------------------------------------------------
+# TODO's
+#
+# * Document the public methods better.
+#
+# * Don't require ProcessManager to be run as root, but do raise
+# exceptions if the user tries to control a process that requires
+# changing the user ID and it can't be done.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Imports
+# ----------------------------------------------------------------------------
+
+import os
+import sys
+import time
+
+
+# ----------------------------------------------------------------------------
+# Public Names and Version Information
+# ----------------------------------------------------------------------------
+
+__all__ = [
+ "Process",
+ "init",
+ "add",
+ "rcScriptMain",
+ "main"
+ ]
+
+__version__ = "0.0.4"
+
+
+# ----------------------------------------------------------------------------
+# Constants
+# ----------------------------------------------------------------------------
+
+# Amount of time we wait in seconds after starting a process to see if
+# it's still alive.
+POST_PROCESS_START_DELAY = 5
+
+# Amount of time we wait in seconds after killing a process to see if
+# it's dead.
+POST_PROCESS_STOP_DELAY = 2
+
+# A list of all valid commands, accessible from the command-line; they
+# map directly to public instance methods of the Process class.
+COMMANDS = {
+ "stop" : "stop the target",
+ "start" : "start the target",
+ "restart" : "restart (stop, then start) the target",
+ "status" : "show status of the target"
+ }
+
+# Usage string when running the module's main() function.
+USAGE_TEXT = """\
+
+ %(scriptName)s <target> <command> [options]
+
+targets:
+%(targets)s\
+ all (this target applies the command to all
+ of the above targets)
+
+commands:
+%(commands)s\
+"""
+
+# Usage string when running the module's rcScriptMain() function.
+RC_SCRIPT_USAGE_TEXT = """\
+
+ %(scriptName)s <command> [options]
+
+This script controls %(targetDesc)s.
+
+commands:
+%(commands)s\
+"""
+
+# ----------------------------------------------------------------------------
+# Module Variables
+# ----------------------------------------------------------------------------
+
+# Directory where all intermediate data files are kept.
+_dataDir = None
+
+# Our process registry; keys are the name identifiers for processes,
+# and the values are Process objects.
+_processes = {}
+
+# OptionParser object representing command-line options parser.
+_parser = None
+
+# object storing command-line options, created by an OptionParser
+# object.
+_options = None
+
+
+# ----------------------------------------------------------------------------
+# Process Class
+# ----------------------------------------------------------------------------
+
+class Process:
+ """
+ Encapsulates a process that can be stopped, started, and
+ restarted.
+ """
+
+ def __init__( self,
+ name,
+ desc,
+ program,
+ args,
+ workingDir,
+ uid = None,
+ gid = None,
+ stopSignal = None,
+ postStartDelay = POST_PROCESS_START_DELAY):
+ """
+ Creates a process with the given name/identifier, description,
+ program executable path, argument tuple, and working
+ directory. When it is run, it will run with the given user
+ and group ID privileges. When it is stopped, the given signal
+ will be sent to tell it to do so.
+ """
+
+ if stopSignal == None:
+ import signal
+ stopSignal = signal.SIGKILL
+
+ self.name = name
+ self.desc = desc
+ self.program = program
+ self.args = [ program ]
+ self.args.extend( args )
+ self.workingDir = workingDir
+ self.stopSignal = stopSignal
+ self.postStartDelay = postStartDelay
+
+ if gid:
+ import grp
+ self.gid = grp.getgrnam( gid )[2]
+ else:
+ self.gid = None
+
+ if uid:
+ import pwd
+ self.uid = pwd.getpwnam( uid )[2]
+ else:
+ self.uid = None
+
+ def _pidfile( self ):
+ """
+ Returns the filename of the pid file for this process. A pid
+ file just contains the pid of the process, if it's believed to
+ be currently running.
+ """
+
+ return os.path.join( _dataDir, "%s.pid" % self.name )
+
+ def _readpid( self ):
+ """
+ Opens the pid file for this process and gets the pid for
+ it. If the pid file doesn't exist, this method returns None.
+ """
+
+ if not os.path.exists( self._pidfile() ):
+ return None
+ f = open( self._pidfile(), "r" )
+ pid = int( f.read() )
+ f.close()
+ return pid
+
+ def status( self ):
+ """
+ Public method that prints out what this process' status is
+ (running, stopped, etc).
+ """
+ status = self._getStatus()
+ print "%-30s%s" % ( self.desc, status )
+ if status != 'running':
+ raise ProcessStatusError()
+
+ def _getStatus( self ):
+ """
+ Returns a single word indicating the status of this process.
+ """
+
+ pid = self._readpid()
+ if pid == None:
+ return "stopped"
+ elif _isPidRunning( pid ):
+ return "running"
+ else:
+ return "crashed"
+
+ def start( self, warnCrashed = False ):
+ """
+ Public method that starts the process. If the process is
+ already deemed to be running, nothing happens.
+
+ If the process fails to launch, raise a
+ ProcessStartupError exception.
+ """
+
+ pid = self._readpid()
+ if pid != None:
+ if _isPidRunning( pid ):
+ print "Process '%s' is already running!" % self.name
+ return
+ elif warnCrashed:
+ print "Process '%s' may have died prematurely." % self.name
+
+ # Start the process now.
+ leftColumnText = "Launching %s..." % self.desc
+ print "%-30s" % leftColumnText,
+ sys.stdout.flush()
+
+ self._doStart()
+
+ def _doStart( self ):
+ """
+ Protected implementation method that starts the actual
+ process.
+ """
+
+ forkResult = os.fork()
+ if forkResult == 0:
+ # We're the child process.
+
+ if self.gid:
+ os.setgid( self.gid )
+
+ if self.uid:
+ os.setuid( self.uid )
+
+ os.chdir( self.workingDir )
+
+ nullFile = os.open( "/dev/null", os.O_RDWR )
+
+ # Replace stdin.
+ os.dup2( nullFile, 0 )
+
+ # Replace stdout
+ os.dup2( nullFile, 1 )
+
+ # Replace stderr
+ os.dup2( nullFile, 2 )
+
+ os.close( nullFile )
+
+ # Launch the program.
+ os.execv( self.program, self.args )
+ else:
+ # We're the parent process.
+ pid = forkResult
+ f = open( self._pidfile(), "w" )
+ f.write( "%d" % pid )
+ f.close()
+
+ if self.postStartDelay:
+ time.sleep(self.postStartDelay)
+
+ retVal = os.waitpid( pid, os.WNOHANG )
+ if retVal == (0, 0):
+ print "OK"
+ else:
+ print "FAILED"
+ try:
+ os.remove(self._pidfile())
+ except:
+ pass
+ raise ProcessStartupError()
+
+ def stop( self, warnCrashed = True ):
+ """
+ Public method that stops the process if it's currently
+ running.
+ """
+
+ pid = self._readpid()
+ if pid != None:
+ if _isPidRunning( pid ):
+ leftColumnText = "Stopping %s..." % self.desc
+ print "%-30s" % leftColumnText,
+ sys.stdout.flush()
+
+ os.kill( pid, self.stopSignal )
+
+ time.sleep( POST_PROCESS_STOP_DELAY )
+
+ if not _isPidRunning( pid ):
+ print "OK"
+ else:
+ print "FAILED"
+ elif warnCrashed:
+ print "Process '%s' may have died prematurely." % self.name
+ os.remove( self._pidfile() )
+ else:
+ print "Process '%s' is not running." % self.name
+
+ def restart( self ):
+ """
+ Public method that stops the process and then starts it again.
+ """
+
+ self.stop( warnCrashed = False )
+ self.start()
+
+class ProcessStartupError( Exception ):
+ """
+ Exception raised when a process fails to start.
+ """
+
+ pass
+
+class ProcessStatusError( Exception ):
+ """
+ Exception raised when a process is not running.
+ """
+ pass
+
+# ----------------------------------------------------------------------------
+# Module Functions
+# ----------------------------------------------------------------------------
+
+def init( dataDir ):
+ """
+ Initializes the module.
+
+ dataDir is the directory where all intermediate data files are
+ stored (e.g., pidfiles).
+ """
+
+ global _dataDir
+
+ _dataDir = dataDir
+
+def _isPidRunning( pid ):
+ """
+ Returns whether or not a process with the given pid is running.
+ """
+ try:
+ os.kill(pid, 0)
+ except OSError:
+ return False
+ else:
+ return True
+
+def add( process ):
+ """
+ Adds the given Process object as a target for the registry of
+ processes to manage.
+ """
+
+ if _processes.has_key( process.name ):
+ raise TargetAlreadyExistsError()
+ _processes[process.name] = process
+
+class TargetAlreadyExistsError( Exception ):
+ """
+ Exception raised when a target is added to the ProcessManager
+ whose name already exists.
+ """
+
+ pass
+
+def _runCommandOnTarget( command, target ):
+ """
+ Runs the given command on the given target.
+ """
+
+ if _dataDir == None:
+ print "Error! ProcessManager not initialized."
+ print "Please use ProcessManager.init()."
+ sys.exit( -1 )
+
+ errorOccurred = False
+
+ if target == "all":
+ for process in _processes.values():
+ method = getattr( process, command )
+ try:
+ method()
+ except (ProcessStartupError, ProcessStatusError):
+ errorOccurred = True
+ else:
+ method = getattr( _processes[target], command )
+ try:
+ method()
+ except (ProcessStartupError, ProcessStatusError):
+ errorOccurred = True
+
+ if errorOccurred:
+ sys.exit(1)
+
+def _checkPrivileges():
+ """
+ Checks to ensure that the current user has the proper privileges
+ to run the ProcessManager; exits the program if not.
+ """
+
+ needRoot = False
+ for process in _processes.values():
+ if process.gid or process.uid:
+ needRoot = True
+ break
+
+ if not needRoot:
+ return
+
+ if os.getuid() != 0:
+ print "ERROR: This script must be run as root."
+ sys.exit( -1 )
+
+def _generateTargetHelpText():
+ """
+ Returns a string containing a list of available targets with their
+ descriptions.
+ """
+
+ targets = ""
+ for key in _processes.keys():
+ targets += " %-21s%s\n" % ( key, _processes[key].desc )
+ return targets
+
+def _generateCommandHelpText():
+ """
+ Returns a string containing a list of available commands with a
+ description of what they do.
+ """
+
+ commands = ""
+ for command in COMMANDS.keys():
+ commands += " %-21s%s\n" % ( command, COMMANDS[command] )
+ commands = commands[:-1]
+ return commands
+
+def rcScriptMain():
+ """
+ The main function of the rc-script use of the Process Manager,
+ whereby the name of the script determines the target, and the
+ first command-line parameter determines the command.
+ """
+
+ _checkPrivileges()
+
+ target = os.path.split( sys.argv[0] )[1]
+ if not _processes.has_key( target ):
+ # If we're in a rc.d directory, we may have 3 characters
+ # prepended to our name, such as "S01foo". So let's try
+ # stripping off the first 3 characters of our name and seeing
+ # if that works as a target.
+ if target[0] in ["K", "S"]:
+ ordering = target[1:3]
+ try:
+ # See if these characters constitute a number.
+ int( ordering )
+ # If so, let's try reinterpreting our target.
+ target = target[3:]
+ except ValueError:
+ pass
+
+ if not _processes.has_key( target ):
+ print "ERROR: Target '%s' does not exist!" % target
+ print "Consider renaming this script to match one"
+ print "of the following targets:"
+ print
+ print _generateTargetHelpText()
+ sys.exit( -1 )
+
+ usageTextDict = {
+ "scriptName" : target,
+ "targetDesc" : _processes[ target ].desc,
+ "commands" : _generateCommandHelpText(),
+ }
+
+ usageText = RC_SCRIPT_USAGE_TEXT % usageTextDict
+
+ _processCmdLineOptions( usageText )
+
+ if len( sys.argv ) == 1:
+ command = ""
+ else:
+ command = sys.argv[1]
+
+ if not command in COMMANDS.keys():
+ _parser.print_help()
+ sys.exit( -1 )
+
+ _runCommandOnTarget( command, target )
+
+def _processCmdLineOptions( usageText, args=None ):
+ """
+ Parses and processes standard command-line options.
+ """
+
+ import optparse
+
+ global _parser
+ global _options
+ global _args
+
+ _parser = optparse.OptionParser( usage = usageText )
+
+ ( _options, _args ) = _parser.parse_args(args=args)
+
+def main(argv=sys.argv, usage=USAGE_TEXT):
+ """
+ The main function of the Process Manager which processes
+ command-line arguments and acts on them.
+ """
+
+ _checkPrivileges()
+
+ usageTextDict = {
+ "scriptName" : os.path.split( argv[0] )[1],
+ "targets" : _generateTargetHelpText(),
+ "commands" : _generateCommandHelpText(),
+ }
+
+ usageText = usage % usageTextDict
+
+ _processCmdLineOptions( usageText, args=argv[1:] )
+
+ if len( _args ) < 2:
+ _parser.print_help()
+ sys.exit( -1 )
+
+ target = _args[0]
+ command = _args[1]
+
+ if target not in _processes.keys() and target != "all":
+ print "Invalid target: '%s'" % target
+ sys.exit( -1 )
+ if command not in COMMANDS.keys():
+ print "Invalid command: '%s'" % command
+ sys.exit( -1 )
+
+ _runCommandOnTarget( command, target )
+
View
83 ctx-broker/home/lib/brokerctl.py
@@ -0,0 +1,83 @@
+#! /usr/bin/env python
+
+import os
+import sys
+
+import ProcessManager
+from ProcessManager import Process
+import ConfigParser
+
+USAGE_TEXT = """\
+
+ nimbusctl [target] command
+
+Omit the target to perform the command for all targets.
+
+Targets:
+%(targets)s\
+
+Commands:
+%(commands)s\
+"""
+
+
+NIMBUS_HOME = os.getenv("NIMBUS_HOME")
+
+if not NIMBUS_HOME:
+ sys.exit("The NIMBUS_HOME environment variable is not set!")
+
+if not os.path.isdir(NIMBUS_HOME):
+ sys.exit("$NIMBUS_HOME does not exist: "+ NIMBUS_HOME)
+
+
+CONFIG_PATH = os.path.join(NIMBUS_HOME, 'nimbus-setup.conf')
+_NO_CONFIG_ERROR = """
+Could not find the Nimbus setup config file:
+ %s
+This file is created after successful completion of the nimbus-configure
+program. You should try running nimbus-configure before using this program.
+""" % CONFIG_PATH
+config = ConfigParser.SafeConfigParser()
+if not config.read(CONFIG_PATH):
+ sys.exit(_NO_CONFIG_ERROR)
+broker_enabled = config.getboolean('nimbussetup', 'broker.enabled')
+
+if not (broker_enabled):
+ sys.exit("Broker is not enabled. "+
+ "See the '%s' config file to adjust this setting." % CONFIG_PATH)
+
+try:
+ services_wait = config.getint('nimbussetup', 'services.wait')
+except ConfigParser.NoOptionError:
+ services_wait = 10
+
+NIMBUS_RUN_DIR = os.path.join(NIMBUS_HOME, 'var/run/')
+if not os.path.isdir(NIMBUS_RUN_DIR):
+ try:
+ os.mkdir(NIMBUS_RUN_DIR)
+ except:
+ sys.exit("Failed to create run directory: %s" % NIMBUS_RUN_DIR)
+
+ProcessManager.init(dataDir = NIMBUS_RUN_DIR)
+
+if broker_enabled:
+ NIMBUS_BROKER_EXE = os.path.join(NIMBUS_HOME, 'lib/run-broker.sh')
+ if not os.path.exists(NIMBUS_BROKER_EXE):
+ sys.exit("The broker executable does not exist: " +
+ NIMBUS_BROKER_EXE)
+ ProcessManager.add( Process(
+ name = "broker",
+ desc = "Nimbus Context Broker",
+ program = NIMBUS_BROKER_EXE,
+ args = [],
+ workingDir = NIMBUS_HOME,
+ postStartDelay=services_wait
+ ))
+
+
+argv = sys.argv
+if len(argv) == 2:
+ argv = argv[:]
+ argv.insert(1, 'all')
+
+ProcessManager.main(argv=argv, usage=USAGE_TEXT)
View
3  ctx-broker/home/lib/pynimbusconfig/README
@@ -0,0 +1,3 @@
+In the next release, the configuration libraries for use with ctx-broker, web, and IaaS will all be housed in a common library.
+
+This is an interim solution, the future library will be this new "pynimbusconfig" library and it will be accessible from any install's home dir venv (iaas or ctx-broker only).
View
0  ctx-broker/home/lib/pynimbusconfig/__init__.py
No changes.
View
273 ctx-broker/home/lib/pynimbusconfig/autoca.py
@@ -0,0 +1,273 @@
+import os
+import shutil
+import sys
+
+from pynimbusconfig import javautil
+from pynimbusconfig import pathutil
+from pynimbusconfig import runutil
+from pynimbusconfig.setuperrors import *
+
+# Make this False if you want to keep stuff around for examining, otherwise it
+# would be in an inconsistent state after an exception during CA creation.
+WIPE_NEW_CA_DIRECTORY_ON_ERRORS = True
+
+
+EXE_HOSTGUESS="org.nimbustools.auto_common.HostGuess"
+EXE_NEW_HOSTCERTFILE="org.nimbustools.auto_common.confmgr.ReplaceCertFile"
+EXE_NEW_HOSTKEYFILE="org.nimbustools.auto_common.confmgr.ReplaceKeyFile"
+EXE_CREATE_NEW_CA="org.nimbustools.auto_common.ezpz_ca.GenerateNewCA"
+EXE_CREATE_CRL="org.nimbustools.auto_common.ezpz_ca.GenerateCRL"
+EXE_CREATE_NEW_CERT="org.nimbustools.auto_common.ezpz_ca.GenerateNewCert"
+EXE_FIND_CA_PUBPEM="org.nimbustools.auto_common.ezpz_ca.FindCAPubFile"
+EXE_FIND_CA_PRIVPEM="org.nimbustools.auto_common.ezpz_ca.FindCAPrivFile"
+EXE_GET_HASHED_CERT_NAME="org.nimbustools.auto_common.ezpz_ca.CertFilenameHash"
+EXE_GET_CERT_DN="org.nimbustools.auto_common.ezpz_ca.CertDN"
+EXE_WRITE_SIGNING_POLICY="org.nimbustools.auto_common.ezpz_ca.SigningPolicy"
+EXE_KEYSTORE_FROM_PEM="org.nimbustools.auto_common.ezpz_ca.KeystoreFromPEM"
+
+def createCert(CN, basedir, cadir, certtarget, keytarget, log,
+ allow_overwrite=False):
+
+ if not allow_overwrite and pathutil.check_path_exists(certtarget):
+ msg = "Certificate file present already: " + certtarget
+ raise IncompatibleEnvironment(msg)
+ if not allow_overwrite and pathutil.check_path_exists(keytarget):
+ msg = "Key file present already: " + keytarget
+ raise IncompatibleEnvironment(msg)
+
+ cacert_path = findCAcert(basedir, cadir, log)
+ cakey_path = findCAkey(basedir, cadir, log)
+
+ # Create temp directory.
+ uuid = pathutil.uuidgen()
+ tempdir = pathutil.pathjoin(cadir, uuid)
+ os.mkdir(tempdir)
+ pathutil.ensure_dir_exists(tempdir, "temp certs directory")
+ log.debug("Created %s" % tempdir)
+
+ args = [tempdir, CN, "pub", "priv", cacert_path, cakey_path]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_CREATE_NEW_CERT, args=args)
+ runutil.generic_bailout("Problem creating certificate.", exitcode, stdout, stderr)
+
+ pub_DN = stdout.strip()
+
+ temp_pub_path = pathutil.pathjoin(tempdir, "pub")
+ pathutil.ensure_file_exists(temp_pub_path, "temp cert")
+ log.debug("temp cert exists: " + temp_pub_path)
+
+ # copy that to user-cert records
+ args = [temp_pub_path]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_GET_HASHED_CERT_NAME, args=args)
+ runutil.generic_bailout("Problem finding hashed cert name.", exitcode, stdout, stderr)
+ usercertfilehash = stdout.strip()
+ log.debug("user cert file hash is '%s'" % usercertfilehash)
+ cert_records_path = pathutil.pathjoin(cadir, "user-certs")
+ cert_records_path = pathutil.pathjoin(cert_records_path,
+ usercertfilehash + ".0")
+ shutil.copyfile(temp_pub_path, cert_records_path)
+ pathutil.ensure_file_exists(cert_records_path, "new certificate (record)")
+ log.debug("cert exists at target: " + cert_records_path)
+
+ temp_priv_path = pathutil.pathjoin(tempdir, "priv")
+ pathutil.ensure_file_exists(temp_priv_path, "temp key")
+ log.debug("temp key exists: " + temp_priv_path)
+
+ log.debug("Created certificate: %s" % pub_DN)
+
+ # Those user-supplied targets still don't exist, right? :-)
+ if not allow_overwrite and pathutil.check_path_exists(certtarget):
+ msg = "Certificate file present already: " + certtarget
+ raise IncompatibleEnvironment(msg)
+ if not allow_overwrite and pathutil.check_path_exists(keytarget):
+ msg = "Key file present already: " + keytarget
+ raise IncompatibleEnvironment(msg)
+
+ shutil.copyfile(temp_pub_path, certtarget)
+ pathutil.ensure_file_exists(certtarget, "new certificate")
+ log.debug("cert exists at target: " + certtarget)
+
+ shutil.copyfile(temp_priv_path, keytarget)
+ pathutil.ensure_file_exists(keytarget, "new key")
+ log.debug("key exists at target: " + keytarget)
+
+ pathutil.make_path_rw_private(keytarget)
+ pathutil.ensure_path_private(keytarget, "new key")
+ log.debug("file made private: %s" % keytarget)
+
+ shutil.rmtree(tempdir)
+
+ return pub_DN
+
+class KeystoreMismatchError(Exception):
+ pass
+
+def ensureKeystore(certpath, keypath, storepath, password, basedir, log):
+ """
+ Creates or validates a Java keystore from PEM-encoded certificate and key
+ """
+
+ if not pathutil.check_path_exists(certpath):
+ msg = "Certificate file does not exist: " + certpath
+ raise IncompatibleEnvironment(msg)
+
+ if not pathutil.check_path_exists(keypath):
+ msg = "Private key file does not exist: " + keypath
+ raise IncompatibleEnvironment(msg)
+
+ if pathutil.check_path_exists(storepath):
+ log.debug("Keystore file exists: %s." % storepath,
+ "Ensuring that it contains right cert/key")
+
+ args = [certpath, keypath, storepath, password]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log,
+ EXE_KEYSTORE_FROM_PEM, args=args)
+ if exitcode == 2:
+ raise KeystoreMismatchError(stderr)
+ runutil.generic_bailout("Problem creating keystore",
+ exitcode, stdout, stderr)
+
+def getCertDN(certpath, basedir, log):
+
+ if not pathutil.check_path_exists(certpath):
+ msg = "Certificate file does not exist: " + certpath
+ raise IncompatibleEnvironment(msg)
+
+ args = [certpath]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log,
+ EXE_GET_CERT_DN, args=args)
+ runutil.generic_bailout("Problem finding cert DN",
+ exitcode, stdout, stderr)
+
+ return stdout.strip()
+
+def findCAcert(basedir, cadir, log):
+ cacertdir = pathutil.pathjoin(cadir, "ca-certs")
+ args = [cacertdir]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_FIND_CA_PUBPEM, args=args)
+ runutil.generic_bailout("Problem finding CA certificate.", exitcode, stdout, stderr)
+ if not stdout:
+ raise UnexpectedError("Path is not present for CA certificate")
+ certpath = stdout.strip()
+ pathutil.ensure_file_exists(certpath, "CA certificate")
+ return certpath
+
+def findCAkey(basedir, cadir, log):
+ cacertdir = pathutil.pathjoin(cadir, "ca-certs")
+ args = [cacertdir]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_FIND_CA_PRIVPEM, args=args)
+ runutil.generic_bailout("Problem finding CA key.", exitcode, stdout, stderr)
+ if not stdout:
+ raise UnexpectedError("Path is not present for CA key")
+ keypath = stdout.strip()
+ pathutil.ensure_file_exists(keypath, "CA key")
+ return keypath
+
+def createCA(ca_name, basedir, cadir, log):
+ if pathutil.check_path_exists(cadir):
+ raise IncompatibleEnvironment("cannot create a CA at a directory that exists already")
+ try:
+ _createCA(ca_name, basedir, cadir, log)
+ except:
+ if not WIPE_NEW_CA_DIRECTORY_ON_ERRORS:
+ raise
+ # wipe the whole directory
+ print >>sys.stderr, "Error, wiping the unfinished '%s' directory" % cadir
+ shutil.rmtree(cadir)
+ raise
+
+def _createCA(ca_name, basedir, cadir, log):
+
+ javautil.check(basedir, log)
+
+ # mkdir $cadir
+ # mkdir $cadir/ca-certs
+ # mkdir $cadir/trusted-certs
+ # mkdir $cadir/user-certs
+
+ os.mkdir(cadir)
+ pathutil.ensure_dir_exists(cadir, "New CA directory")
+ log.debug("Created %s" % cadir)
+
+ cacertdir = pathutil.pathjoin(cadir, "ca-certs")
+ os.mkdir(cacertdir)
+ pathutil.ensure_dir_exists(cacertdir, "New CA certs directory")
+ log.debug("Created %s" % cacertdir)
+
+ trustedcertdir = pathutil.pathjoin(cadir, "trusted-certs")
+ os.mkdir(trustedcertdir)
+ pathutil.ensure_dir_exists(trustedcertdir, "New CA trusted certs directory")
+ log.debug("Created %s" % trustedcertdir)
+
+ usercertdir = pathutil.pathjoin(cadir, "user-certs")
+ os.mkdir(usercertdir)
+ pathutil.ensure_dir_exists(usercertdir, "New CA user certs directory")
+ log.debug("Created %s" % usercertdir)
+
+ # Create the cert via autocommon
+
+ args = [cacertdir, ca_name]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_CREATE_NEW_CA, args=args)
+ runutil.generic_bailout("Problem creating CA.", exitcode, stdout, stderr)
+
+
+ # Make the private key owner-readable only
+
+ privkeyname = "private-key-" + ca_name + ".pem"
+ cakeyfile = pathutil.pathjoin(cacertdir, privkeyname)
+ pathutil.ensure_file_exists(cakeyfile, "New CA key")
+ log.debug("file exists: %s" % cakeyfile)
+ pathutil.make_path_rw_private(cakeyfile)
+ pathutil.ensure_path_private(cakeyfile, "New CA key")
+ log.debug("file made private: %s" % cakeyfile)
+
+
+ # Copy the new certificate file to the "hash.0" version that some toolings
+ # will expect.
+
+ cacertfile = pathutil.pathjoin(cacertdir, ca_name + ".pem")
+ pathutil.ensure_file_exists(cacertfile, "New CA cert")
+ log.debug("file exists: %s" % cacertfile)
+
+ args = [cacertfile]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_GET_HASHED_CERT_NAME, args=args)
+ runutil.generic_bailout("Problem finding hashed cert name.", exitcode, stdout, stderr)
+ cacertfilehash = stdout.strip()
+ log.debug("cert file hash is '%s'" % cacertfilehash)
+
+ newpath = pathutil.pathjoin(cacertdir, cacertfilehash + ".0")
+ shutil.copyfile(cacertfile, newpath)
+ pathutil.ensure_file_exists(newpath, "New CA cert (hashed #1)")
+ log.debug("file exists: %s" % newpath)
+
+ newpath = pathutil.pathjoin(trustedcertdir, cacertfilehash + ".0")
+ shutil.copyfile(cacertfile, newpath)
+ pathutil.ensure_file_exists(newpath, "New CA cert (hashed #2)")
+ log.debug("file exists: %s" % newpath)
+
+ # Signing policy
+
+ signing1 = pathutil.pathjoin(cacertdir, cacertfilehash + ".signing_policy")
+ args = [cacertfile, signing1]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_WRITE_SIGNING_POLICY, args=args)
+ runutil.generic_bailout("Problem creating signing_policy file.", exitcode, stdout, stderr)
+ pathutil.ensure_file_exists(signing1, "signing_policy file #1")
+ log.debug("file exists: %s" % signing1)
+
+ signing2 = pathutil.pathjoin(trustedcertdir, cacertfilehash + ".signing_policy")
+ shutil.copyfile(signing1, signing2)
+ pathutil.ensure_file_exists(signing2, "signing_policy file #2")
+ log.debug("file exists: %s" % signing2)
+
+ # CRL
+
+ crl1 = pathutil.pathjoin(cacertdir, cacertfilehash + ".r0")
+ args = [crl1, cacertfile, cakeyfile]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_CREATE_CRL, args=args)
+ runutil.generic_bailout("Problem creating revocation file.", exitcode, stdout, stderr)
+ pathutil.ensure_file_exists(crl1, "revocation file #1")
+ log.debug("file exists: %s" % crl1)
+
+ crl2 = pathutil.pathjoin(trustedcertdir, cacertfilehash + ".r0")
+ shutil.copyfile(crl1, crl2)
+ pathutil.ensure_file_exists(crl2, "revocation file #2")
+ log.debug("file exists: %s" % crl2)
View
0  ctx-broker/home/lib/pynimbusconfig/broker/__init__.py
No changes.
View
579 ctx-broker/home/lib/pynimbusconfig/broker/main.py
@@ -0,0 +1,579 @@
+#!/usr/bin/env python
+
+import logging
+import optparse
+import os
+import socket
+import sys
+import traceback
+import ConfigParser
+from StringIO import StringIO
+import readline
+import shutil
+import string
+import time
+from random import Random
+
+from pynimbusconfig import autoca
+from pynimbusconfig import checkssl
+from pynimbusconfig import gtcontainer
+from pynimbusconfig import javautil
+from pynimbusconfig import pathutil
+from pynimbusconfig.setuperrors import *
+
+
+CONFIGSECTION = 'nimbussetup'
+DEFAULTCONFIG = """
+[nimbussetup]
+
+# relative to base directory
+hostcert: var/hostcert.pem
+hostkey: var/hostkey.pem
+ca.dir: var/ca
+ca.trustedcerts.dir: var/ca/trusted-certs
+
+gridmap: services/etc/nimbus/nimbus-grid-mapfile
+
+keystore: var/keystore.jks
+keystore.pass: changeit
+
+services.enabled: True
+services.wait: 10
+"""
+CONFIG_STATE_PATH = 'nimbus-setup.conf'
+
+CONFIG_KEY_CA_DIR="ca.dir"
+CONFIG_KEY_HOSTCERT="hostcert"
+CONFIG_KEY_HOSTKEY="hostkey"
+CONFIG_KEY_KEYSTORE="keystore"
+CONFIG_KEY_GRIDMAP="gridmap"
+CONFIG_KEY_TRUSTED_CERTS="ca.trustedcerts.dir"
+CONFIG_KEY_ENVFILE="envfile"
+
+CA_NAME_QUESTION = """
+Nimbus uses an internal Certificate Authority (CA) for some services. This CA
+is also used to generate host and user certificates if you do not have your own.
+
+This CA will be created in %(ca.dir)s
+
+Please pick a unique, one word CA name or hit ENTER to use a UUID.
+
+For example, if you are installing this on the "Jupiter" cluster, you might use
+"JupiterNimbusCA" as the name.
+"""
+
+CONFIG_HEADER = """
+# Autogenerated at %(time)s
+#
+# This file contains configuration values used by the nimbus-configure program.
+# If you want to change any of these values, you may edit this file, but you
+# must run nimbus-configure before the change will take effect.
+
+"""
+
+ENVFILE_BODY = """
+# Autogenerated at %(time)s
+#
+# This file contains environment variables which are necessary to use some of
+# the Nimbus internal tools directly
+
+NIMBUS_HOME=%(NIMBUS_HOME)s
+export NIMBUS_HOME
+
+GLOBUS_LOCATION=%(GLOBUS_LOCATION)s
+export GLOBUS_LOCATION
+
+X509_CERT_DIR=%(X509_CERT_DIR)s
+export X509_CERT_DIR
+"""
+
+KEYSTORE_MISMATCH_MSG = """
+A Java keystore already exists at:
+ %(keystore)s
+However, it does not contain the host certificate and private key which are
+being configured.
+ Certificate: %(hostcert)s
+ Private key: %(hostkey)s
+This may be because you have switched certificates and the keystore contains
+the old version. If so, the best solution is to delete (or relocate) the
+keystore and rerun nimbus-configure to generate a new one.
+"""
+
+def getlog(override=None):
+ """Allow developer to replace logging mechanism, e.g. if this
+ module is incorporated into another program as an API.
+
+ Keyword arguments:
+
+ * override -- Custom logger (default None, uses global variable)
+
+ """
+ global _log
+ if override:
+ _log = override
+ try:
+ _log
+ except:
+ _log = logging.getLogger("nimbussetup")
+ _log.setLevel(logging.DEBUG)
+ return _log
+
+def configureLogging(level, formatstring=None, logger=None):
+ """Configure the logging format and mechanism. Sets global 'log' variable.
+
+ Required parameter:
+
+ * level -- log level
+
+ Keyword arguments:
+
+ * formatstring -- Custom logging format (default None, uses time+level+msg)
+
+ * logger -- Custom logger (default None)
+ """
+
+ global log
+
+ logger = getlog(override=logger)
+
+ if not formatstring:
+ formatstring = "%(asctime)s (%(filename)s:%(lineno)d): %(message)s"
+
+ formatter = logging.Formatter(formatstring)
+ ch = logging.StreamHandler()
+ ch.setLevel(level)
+ ch.setFormatter(formatter)
+ logger.addHandler(ch)
+
+ # set global variable
+ log = logger
+
+ log.debug("debug enabled")
+
+def getconfig(filepaths=None):
+ config = ConfigParser.SafeConfigParser()
+
+ fh = StringIO(DEFAULTCONFIG)
+ config.readfp(fh)
+ if filepaths:
+ for path in config.read(filepaths):
+ log.debug("Read config from: '%s'" % path)
+ return config
+
+class ARGS:
+ """Class for command-line argument constants"""
+
+ BASEDIR_LONG = "--basedir"
+ BASEDIR = "-b"
+ BASEDIR_HELP = "Path to base Nimbus directory"
+
+ CONFIGPATH_LONG = "--conf"
+ CONFIGPATH = "-c"
+ CONFIGPATH_HELP = "Path to configuration file"
+
+ DEBUG_LONG = "--debug"
+ DEBUG = "-d"
+ DEBUG_HELP = "Log debug messages"
+
+ HOSTNAME_LONG = "--hostname"
+ HOSTNAME = "-H"
+ HOSTNAME_HELP = "Fully qualified hostname of machine"
+
+ CANAME_LONG= "--caname"
+ CANAME = "-n"
+ CANAME_HELP = "Unique name to give CA"
+
+ HOSTKEY_LONG = "--hostkey"
+ HOSTKEY = "-k"
+ HOSTKEY_HELP = "Path to PEM-encoded host private key"
+
+ HOSTCERT_LONG = "--hostcert"
+ HOSTCERT = "-C"
+ HOSTCERT_HELP = "Path to PEM-encoded host certificate"
+
+ PRINT_HOSTNAME_LONG = "--print-hostname"
+ PRINT_HOSTNAME = "-Z"
+ PRINT_HOSTNAME_HELP = "Print chosen hostname or error if none chosen"
+
+def validateargs(opts):
+
+ seeh = "see help (-h)"
+
+ if not opts.basedir:
+ raise InvalidInput("%s required, %s." % (ARGS.BASEDIR_LONG, seeh))
+
+ if opts.configpath and not os.path.exists(opts.configpath):
+ raise InvalidInput("%s file specified does not exist: '%s'" %
+ (ARGS.CONFIGPATH_LONG, opts.configpath))
+
+ if opts.hostkey or opts.hostcert:
+ if not (opts.hostkey and opts.hostcert):
+ raise InvalidInput(
+ "You must specify both %s and %s paths, or neither" %
+ (ARGS.HOSTCERT_LONG, ARGS.HOSTKEY_LONG))
+ if not os.path.exists(opts.hostkey):
+ raise InvalidInput("The specified host key does not exist: %s" %
+ opts.hostkey)
+ if not os.path.exists(opts.hostcert):
+ raise InvalidInput("The specified host cert does not exist: %s" %
+ opts.hostcert)
+
+def parsersetup():
+ """Return configured command-line parser."""
+
+ ver = "Nimbus Context Broker setup"
+ usage = "see help (-h)."
+ parser = optparse.OptionParser(version=ver, usage=usage)
+
+ group = optparse.OptionGroup(parser, "Misc options", "-------------")
+
+ group.add_option(ARGS.PRINT_HOSTNAME, ARGS.PRINT_HOSTNAME_LONG,
+ action="store_true", dest="print_chosen_hostname",
+ default=False, help=ARGS.PRINT_HOSTNAME_HELP)
+
+ group.add_option(ARGS.DEBUG, ARGS.DEBUG_LONG,
+ action="store_true", dest="debug", default=False,
+ help=ARGS.DEBUG_HELP)
+
+ group.add_option(ARGS.CONFIGPATH, ARGS.CONFIGPATH_LONG,
+ dest="configpath", metavar="PATH",
+ help=ARGS.CONFIGPATH_HELP)
+
+ group.add_option(ARGS.BASEDIR, ARGS.BASEDIR_LONG,
+ dest="basedir", metavar="PATH",
+ help=ARGS.BASEDIR_HELP)
+
+ parser.add_option_group(group)
+
+ group = optparse.OptionGroup(parser, "Configuration options",
+ "-------------")
+
+ group.add_option(ARGS.HOSTNAME, ARGS.HOSTNAME_LONG,
+ dest="hostname", metavar="HOST", help=ARGS.HOSTNAME_HELP)
+
+ group.add_option(ARGS.CANAME, ARGS.CANAME_LONG,
+ dest="ca_name", metavar="NAME", help=ARGS.CANAME_HELP)
+
+ group.add_option(ARGS.HOSTKEY, ARGS.HOSTKEY_LONG,
+ dest="hostkey", metavar="PATH", help=ARGS.HOSTKEY_HELP)
+
+ group.add_option(ARGS.HOSTCERT, ARGS.HOSTCERT_LONG,
+ dest="hostcert", metavar="PATH", help=ARGS.HOSTCERT_HELP)
+ parser.add_option_group(group)
+ return parser
+
+def fold_opts_to_config(opts, config):
+ if opts.hostname:
+ config.set(CONFIGSECTION, 'hostname', opts.hostname)
+ if opts.ca_name:
+ config.set(CONFIGSECTION, 'ca.name', opts.ca_name)
+ if opts.hostkey:
+ config.set(CONFIGSECTION, CONFIG_KEY_HOSTKEY, opts.hostkey)
+ if opts.hostcert:
+ config.set(CONFIGSECTION, CONFIG_KEY_HOSTCERT, opts.hostcert)
+
+def get_user_input(valuename, default=None, required=True):
+ answer = None
+ question = valuename + (default and ("(%s): " % default) or ": ")
+ while not answer:
+ value = raw_input(valuename+": ")
+ if value:
+ answer = value.strip()
+ elif default:
+ answer = default
+ if not answer:
+ if required:
+ print "Invalid input. You must specify a value. Or hit Ctrl-C to give up."
+ else:
+ return None
+
+ return answer
+
+class NimbusSetup(object):
+ def __init__(self, basedir, config, interactive=True):
+ self.basedir = basedir
+ self.config = config
+ self.interactive = interactive
+
+ self.gtdir = self.resolve_path('services/')
+ self.cadir = self.resolve_config_path(CONFIG_KEY_CA_DIR)
+ self.trustedcertsdir = self.resolve_config_path(CONFIG_KEY_TRUSTED_CERTS)
+ self.hostcert_path = self.resolve_config_path(CONFIG_KEY_HOSTCERT)
+ self.hostkey_path = self.resolve_config_path(CONFIG_KEY_HOSTKEY)
+ self.keystore_path = self.resolve_config_path(CONFIG_KEY_KEYSTORE)
+ self.gridmap_path = self.resolve_config_path(CONFIG_KEY_GRIDMAP)
+ try:
+ self.envfile_path = self.resolve_config_path(CONFIG_KEY_ENVFILE)
+ except:
+ self.envfile_path = self.resolve_path('libexec/environment.sh')
+
+ def __getitem__(self, key):
+ try:
+ return self.config.get(CONFIGSECTION, key)
+ except ConfigParser.NoOptionError:
+ return None
+
+ def __setitem__(self, key, value):
+ return self.config.set(CONFIGSECTION, key, value)
+
+ def validate_environment(self):
+ if not pathutil.is_absolute_path(self.basedir):
+ raise IncompatibleEnvironment(
+ "Base directory setting is not absolute")
+ pathutil.ensure_dir_exists(self.basedir, "base")
+ pathutil.ensure_dir_exists(self.gtdir, "GT container")
+
+ # check that we have some java
+ javautil.check(self.basedir, log)
+
+ def resolve_path(self, path):
+ """
+ Resolves a path relative to base directory. If absolute, returns as-is.
+ If relative, joins with self.basedir and returns.
+ """
+ if os.path.isabs(path):
+ return path
+ return os.path.join(self.basedir, path)
+
+ def resolve_config_path(self, config):
+ """
+ Resolves a path, like resolve_path(), but from a config key.
+ """
+ path = self[config]
+ if path:
+ return self.resolve_path(path)
+ return None
+
+ def is_config_present(self, configkey):
+ path = self[configkey]
+ if path:
+ return True
+ else:
+ return False
+
+ def is_config_relative(self, configkey):
+ """
+ Resolves if a config is a relative path or not.
+ """
+ path = self[configkey]
+ if not path:
+ return False
+ return not os.path.isabs(path)
+
+ def ask_hostname(self):
+ hostguess = self['hostname']
+ if not hostguess:
+ hostguess = socket.getfqdn()
+
+ if self.interactive:
+ print "\nWhat is the fully qualified hostname of this machine?\n"
+ print "Press ENTER to use the detected value (%s)\n" % hostguess
+ hostname = get_user_input("Hostname", default=hostguess)
+ else:
+ print "Using hostname: '%s'" % hostguess
+ hostname = hostguess
+ return hostname
+
+ def ask_ca_name(self):
+ ca_name_config = self['ca.name']
+
+ if self.interactive:
+ print CA_NAME_QUESTION % {CONFIG_KEY_CA_DIR : self.cadir}
+ ca_name = get_user_input("CA Name", default=ca_name_config,
+ required=False)
+ if not ca_name:
+ ca_name = pathutil.uuidgen()
+ print "You did not enter a name, using '%s'" % ca_name
+ else:
+ ca_name = ca_name_config or pathutil.uuidgen()
+ print "Creating CA with name: '%s'" % ca_name
+ return ca_name
+
+ def write_env_file(self):
+ """Writes an environment file users can source."""
+ f = None
+ try:
+ f = open(self.envfile_path,'w')
+ text = ENVFILE_BODY % {
+ 'time' : time.strftime('%c'),
+ 'NIMBUS_HOME' : self.basedir,
+ 'GLOBUS_LOCATION' : self.gtdir,
+ 'X509_CERT_DIR' : self.trustedcertsdir
+ }
+ f.write(text)
+ finally:
+ if f:
+ f.close()
+
+ def get_hostname_or_ask(self):
+ if self['hostname']:
+ hostname = self['hostname']
+ log.debug('Using configured hostname: "%s". Run with %s to change.',
+ hostname, ARGS.HOSTNAME_LONG)
+ else:
+ hostname = self.ask_hostname()
+ self['hostname'] = hostname
+ return hostname
+
+ def get_hostname_no_asking(self):
+ # could be None
+ return self['hostname']
+
+ def get_repobucket_no_asking(self):
+ # at least get this to one exact place, can determine dynamically later
+ return "Repo"
+
+ def perform_setup(self):
+ # first, set up CA and host cert/key
+ ca_name = self["ca.name"]
+ if not os.path.exists(self.cadir):
+ ca_name = self.ask_ca_name()
+ self['ca.name'] = ca_name
+ autoca.createCA(ca_name, self.basedir, self.cadir, log)
+ if not ca_name:
+ raise InvalidConfig("CA name is unknown")
+
+ ca_cert = os.path.join(self.cadir, 'ca-certs/%s.pem' % ca_name)
+ ca_key = os.path.join(self.cadir, 'ca-certs/private-key-%s.pem' % ca_name)
+ pathutil.ensure_file_exists(ca_cert, "CA certificate")
+ pathutil.ensure_file_exists(ca_key, "CA private key")
+
+ hostname = self.get_hostname_or_ask()
+
+ #TODO the hostcert/key creation should be extracted from here
+ # right now it just does a bunch of redundant checks first
+ checkssl.run(self.basedir, self.hostcert_path, self.hostkey_path, log,
+ cadir=self.cadir, hostname=hostname)
+
+ password = self['keystore.pass']
+ if not password:
+ raise InvalidConfig("Keystore password is unknown")
+
+ try:
+ autoca.ensureKeystore(self.hostcert_path, self.hostkey_path,
+ self.keystore_path, password, self.basedir, log)
+ except autoca.KeystoreMismatchError:
+ raise IncompatibleEnvironment(KEYSTORE_MISMATCH_MSG % {
+ 'keystore' : self.keystore_path,
+ 'hostcert' : self.hostcert_path,
+ 'hostkey' : self.hostkey_path })
+ pathutil.make_path_rw_private(self.keystore_path)
+
+ # then setup GT container
+ gtcontainer.adjust_hostname(hostname, self.basedir, self.gtdir, log)
+ gtcontainer.adjust_secdesc_path(self.basedir, self.gtdir, log)
+ gtcontainer.adjust_host_cert(self.hostcert_path, self.hostkey_path,
+ self.basedir, self.gtdir, log)
+ gtcontainer.adjust_gridmap_file(self.gridmap_path, self.basedir,
+ self.gtdir, log)
+
+ # and context broker
+ gtcontainer.adjust_broker_config(ca_cert, ca_key, self.keystore_path,
+ password, self.basedir, self.gtdir, log)
+
+ # write an enviroment file
+ self.write_env_file()
+
+def main(argv=None):
+ if os.name != 'posix':
+ print >>sys.stderr, "\nERROR: Only runs on POSIX systems."
+ return 3
+
+ if sys.version_info < (2,4):
+ print >>sys.stderr, "\nERROR: Your system must have Python version 2.4 or later. "
+ print >>sys.stderr, 'Detected version: "'+sys.version+'"'
+ return 4
+
+ parser = parsersetup()
+
+ if argv:
+ (opts, args) = parser.parse_args(argv[1:])
+ else:
+ (opts, args) = parser.parse_args()
+
+ global log
+ log = None
+
+ try:
+ configureLogging(opts.debug and logging.DEBUG or logging.INFO)
+
+ validateargs(opts)
+
+ basedir = opts.basedir
+ log.debug("base directory: %s" % basedir)
+ config_state_path = os.path.join(basedir, CONFIG_STATE_PATH)
+ paths = [config_state_path]
+ if opts.configpath:
+ paths.append(opts.configpath)
+ config = getconfig(filepaths=paths)
+ #Some command line options are folded into the config object
+ fold_opts_to_config(opts, config)
+
+ setup = NimbusSetup(basedir, config)
+ setup.validate_environment()
+
+ if opts.print_chosen_hostname:
+ hostname = setup.get_hostname_no_asking()
+ if not hostname:
+ return 1
+ else:
+ print hostname
+ return 0
+ else:
+ setup.perform_setup()
+
+ log.debug("saving settings to %s" % config_state_path)
+ try:
+ f = None
+ try:
+ f = open(config_state_path, 'wb')
+ f.write(CONFIG_HEADER % {'time' : time.strftime('%c')})
+ config.write(f)
+ except:
+ log.info("Failed to save settings to %s!" % config_state_path)
+ finally:
+ if f:
+ f.close()
+
+ # using instead of 0 for now, as a special signal to the wrapper program
+ return 42
+
+ except InvalidInput, e:
+ msg = "\nProblem with input: %s" % e.msg
+ print >>sys.stderr, msg
+ return 1
+
+ except InvalidConfig, e:
+ msg = "\nProblem with configuration: %s" % e.msg
+ print >>sys.stderr, msg
+ return 2
+
+ except IncompatibleEnvironment, e:
+ msg = "\nCannot validate environment: %s" % e.msg
+ print >>sys.stderr, msg
+ if opts.debug:
+ print >>sys.stderr, "\n---------- stacktrace ----------"
+ traceback.print_tb(sys.exc_info()[2])
+ print >>sys.stderr, "--------------------------------"
+ return 3
+
+if __name__ == "__main__":
+ try:
+ sys.exit(main())
+ except SystemExit:
+ raise
+ except KeyboardInterrupt:
+ print "\n\nReceived keyboard interrupt. Aborting!\n"
+ sys.exit(5)
+ except:
+ exception_type = sys.exc_type
+ try:
+ exceptname = exception_type.__name__
+ except AttributeError:
+ exceptname = exception_type
+ name = str(exceptname)
+ err = str(sys.exc_value)
+ errmsg = "\n==> Uncaught problem, please report all following output:\n %s: %s" % (name, err)
+ print >>sys.stderr, errmsg
+ traceback.print_tb(sys.exc_info()[2])
+ sys.exit(97)
View
92 ctx-broker/home/lib/pynimbusconfig/checkssl.py
@@ -0,0 +1,92 @@
+import os
+import sys
+
+from pynimbusconfig import autoca
+from pynimbusconfig import pathutil
+from pynimbusconfig.setuperrors import *
+
+def run(basedir, certconf, keyconf, log, cadir=None, hostname=None):
+ log.debug("Checking SSL")
+
+ # If the configurations themselves are missing, we cannot continue.
+ if not certconf:
+ raise IncompatibleEnvironment("There is no 'ssl.cert' configuration")
+ if not keyconf:
+ raise IncompatibleEnvironment("There is no 'ssl.key' configuration")
+
+ # If the configurations are relative, they are assumed to be relative from
+ # the base directory.
+ if not pathutil.is_absolute_path(certconf):
+ certconf = pathutil.pathjoin(basedir, certconf)
+ log.debug("ssl.cert was a relative path, converted to '%s'" % certconf)
+ if not pathutil.is_absolute_path(keyconf):
+ keyconf = pathutil.pathjoin(basedir, keyconf)
+ log.debug("ssl.key was a relative path, converted to '%s'" % keyconf)
+
+ # If the configured certificate exists, check the key permissions, then
+ # exit.
+ missingcert = None
+ missingkey = None
+ if not pathutil.check_path_exists(certconf):
+ missingcert = "Configured 'ssl.cert' does not exist at '%s'" % certconf
+ if not pathutil.check_path_exists(keyconf):
+ missingkey = "Configured 'ssl.key' does not exist at '%s'" % keyconf
+
+ if not missingcert and not missingkey:
+ log.debug("cert and key confs exist already, checking key perms")
+ # check key permission
+ if pathutil.is_path_private(keyconf):
+ log.debug("key is owner-read only: %s" % keyconf)
+ else:
+ print >>sys.stderr, "***"
+ print >>sys.stderr, "*** WARNING ***"
+ print >>sys.stderr, "***"
+ print >>sys.stderr, "SSL key has bad permissions, should only be readable by the file owner. ssl.key: '%s'" % keyconf
+ return
+
+ # If only one of the cert/key files exists, we cannot reason about
+ # what to do: error.
+ prefix = "Only one of the SSL cert/key file exists, cannot continue. "
+ if missingcert and not missingkey:
+ raise IncompatibleEnvironment(prefix + missingcert)
+ if missingkey and not missingcert:
+ raise IncompatibleEnvironment(prefix + missingkey)
+
+
+ # The configured certificate and key do not exist; create them.
+
+ print "Cannot find configured certificate and key for HTTPS, creating these for you."
+
+ # If the internal CA does not exist, create that first.
+ if not cadir:
+ cadir = pathutil.pathjoin(basedir, "var/ca")
+ if not pathutil.check_path_exists(cadir):
+ print "\nCannot find internal CA, creating this for you.\n"
+ print "Please pick a unique, one word CA name or hit return to use a UUID.\n"
+ print "For example, if you are installing this on the \"Jupiter\" cluster, you could perhaps use \"JupiterNimbusCA\" as the name.\n"
+
+ ca_name = raw_input("Enter a name: ")
+
+ if not ca_name:
+ ca_name = pathutil.uuidgen()
+ print "You did not enter a name, using '%s'" % ca_name
+ else:
+ ca_name = ca_name.split()[0]
+ print "Using '%s'" % ca_name
+
+ autoca.createCA(ca_name, basedir, cadir, log)
+ print "\nCreated internal CA: %s" % cadir
+
+ if not hostname:
+ print "\nEnter the fully qualified hostname of this machine. If you don't know or care right now, hit return to use 'localhost'.\n"
+
+ hostname = raw_input("Hostname: ")
+ if not hostname:
+ hostname = "localhost"
+ print "Using '%s'" % hostname
+
+ autoca.createCert(hostname, basedir, cadir, certconf, keyconf, log)
+ print "\nCreated certificate: %s" % certconf
+ print "Created key: %s\n" % keyconf
+
+
View
72 ctx-broker/home/lib/pynimbusconfig/ezpz_ca.py
@@ -0,0 +1,72 @@
+import os
+import tempfile
+
+from pynimbusconfig import autoca
+
+class EzPzCA(object):
+ """
+ Exposes CA functionality by wrapping java ezpz CA
+ """
+
+ def __init__(self, cadir, webdir, tmpdir=None, log=None):
+ self.cadir = cadir
+ self.webdir = webdir
+ self.tmpdir = tmpdir
+
+ if log:
+ self.log = log
+ else:
+ import logging
+ self.log = logging
+
+ def create_cert(self, cn):
+ """
+ Creates a new certificate with the specified CN.
+
+ Returns a tuple (DN, cert, key)
+ """
+
+ (cert_fd, cert_path) = tempfile.mkstemp(dir=self.tmpdir)
+ (key_fd, key_path) = tempfile.mkstemp(dir=self.tmpdir)
+
+ cert_file = os.fdopen(cert_fd)
+ key_file = os.fdopen(key_fd)
+
+ try:
+ dn = autoca.createCert(cn, self.webdir, self.cadir, cert_path,
+ key_path, self.log, allow_overwrite=True)
+
+ cert = cert_file.read()
+ key = key_file.read()
+
+ return (dn, cert, key)
+
+ finally:
+ # best-effort cleanup
+
+ cert_file.close()
+ key_file.close()
+ os.remove(cert_path)
+ os.remove(key_path)
+
+ def get_cert_dn(self, cert):
+ """
+ Determines the DN of a provided certificate.
+ """
+
+ (cert_fd, cert_path) = tempfile.mkstemp(dir=self.tmpdir)
+
+ try:
+ cert_file = os.fdopen(cert_fd, 'wb')
+ cert_file.write(cert)
+ cert_file.close() # make sure write is buffered out
+
+ return autoca.getCertDN(cert_path, self.webdir, self.log)
+
+ finally:
+ try:
+ os.close(cert_fd)
+ except:
+ pass # FD may have been never opened-- or closed above
+
+ os.remove(cert_path)
View
29 ctx-broker/home/lib/pynimbusconfig/forcessl.py
@@ -0,0 +1,29 @@
+import os
+import sys
+
+from pynimbusconfig import autoca
+from pynimbusconfig import pathutil
+from pynimbusconfig.setuperrors import *
+
+def run(basedir, cadir, certconf, keyconf, hostnameconf, log):
+ log.debug("Forcing a CA/hostcert install")
+
+ # Reject relative paths
+ if not pathutil.is_absolute_path(cadir):
+ raise IncompatibleEnvironment("CA directory path is not absolute")
+
+ if not pathutil.is_absolute_path(certconf):
+ raise IncompatibleEnvironment("certificate path is not absolute")
+
+ if not pathutil.is_absolute_path(keyconf):
+ raise IncompatibleEnvironment("key path is not absolute")
+
+ # The CA dir must not exist, create that first.
+ autoca.createCA(pathutil.uuidgen(), basedir, cadir, log)
+ print "Created auto CA: %s" % cadir
+
+ # The configured certificate and key must not exist; create them.
+ autoca.createCert(hostnameconf, basedir, cadir, certconf, keyconf, log)
+ print "\nCreated hostcert: %s" % certconf
+ print "Created hostkey: %s\n" % keyconf
+
View
133 ctx-broker/home/lib/pynimbusconfig/gtcontainer.py
@@ -0,0 +1,133 @@
+from pynimbusconfig import javautil
+from pynimbusconfig import pathutil
+from pynimbusconfig import runutil
+from pynimbusconfig.setuperrors import IncompatibleEnvironment
+
+EXE_LOGICAL_HOST = "org.nimbustools.auto_common.confmgr.AddOrReplaceLogicalHost"
+EXE_PUBLISH_HOST = "org.nimbustools.auto_common.confmgr.AddOrReplacePublishHostname"
+EXE_GLOBUS_SECDESC = "org.nimbustools.auto_common.confmgr.AddOrReplaceGlobalSecDesc"
+EXE_NEW_GRIDMAPFILE = "org.nimbustools.auto_common.confmgr.ReplaceGridmap"
+EXE_NEW_HOSTCERTFILE = "org.nimbustools.auto_common.confmgr.ReplaceCertFile"
+EXE_NEW_HOSTKEYFILE = "org.nimbustools.auto_common.confmgr.ReplaceKeyFile"
+EXE_SERVICE_RESOURCE = "org.nimbustools.auto_common.confmgr.ServiceResourceAdjust"
+
+# config paths, relative to $GLOBUS_LOCATION
+CONF_SERVERCONFIG = "etc/globus_wsrf_core/server-config.wsdd"
+CONF_SECDESC = "etc/globus_wsrf_core/global_security_descriptor.xml"
+CONF_BROKERCONFIG = "etc/nimbus-context-broker/jndi-config.xml"
+
+def adjust_hostname(hostname, basedir, gtdir, log):
+ serverconfig = get_serverconfig_path(gtdir)
+ pathutil.ensure_file_exists(serverconfig, "GT server config")
+
+ args = [hostname, serverconfig]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_LOGICAL_HOST,
+ args=args)
+ runutil.generic_bailout("Problem adjusting logical host in GT container",
+ exitcode, stdout, stderr)
+
+ log.debug("Adjusted GT container logical host to %s" % hostname)
+
+ args = ['true', serverconfig]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_PUBLISH_HOST,
+ args=args)
+ runutil.generic_bailout("Problem setting GT container to publish hostname",
+ exitcode, stdout, stderr)
+
+ log.debug("Adjusted GT container to publish hostname in URLs")
+
+def adjust_gridmap_file(gridmap, basedir, gtdir, log):
+ if not pathutil.is_absolute_path(gridmap):
+ raise IncompatibleEnvironment("gridmap path must be absolute")
+
+ pathutil.ensure_file_exists(gridmap, "gridmap")
+
+ secdesc = get_secdesc_path(gtdir)
+ pathutil.ensure_file_exists(secdesc, "container security settings")
+
+ args = [gridmap, secdesc]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_NEW_GRIDMAPFILE,
+ args=args)
+ runutil.generic_bailout("Problem setting new gridmap file location",
+ exitcode, stdout, stderr)
+
+ log.debug("Adjusted GT container gridmap file to %s" % gridmap)
+
+def adjust_secdesc_path(basedir, gtdir, log):
+
+ secdesc = get_secdesc_path(gtdir)
+ pathutil.ensure_file_exists(secdesc, "container security settings")
+
+ serverconfig = get_serverconfig_path(gtdir)
+ pathutil.ensure_file_exists(serverconfig, "GT server config")
+
+ args = [secdesc, serverconfig]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_GLOBUS_SECDESC,
+ args=args)
+ runutil.generic_bailout("Problem activating new security settings in GT container",
+ exitcode, stdout, stderr)
+
+ log.debug("Activated new security settings file in GT container: %s" %
+ secdesc)
+
+def adjust_host_cert(cert, key, basedir, gtdir, log):
+
+ pathutil.ensure_file_exists(cert, "host certificate")
+ pathutil.ensure_file_exists(key, "host private key")
+
+ secdesc = get_secdesc_path(gtdir)
+ pathutil.ensure_file_exists(secdesc, "container security settings")
+
+ args = [cert, secdesc]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_NEW_HOSTCERTFILE,
+ args=args)
+ runutil.generic_bailout("Problem activating host certificate",
+ exitcode, stdout, stderr)
+ log.debug("Activated host certificate file in GT container: %s" % cert)
+
+ args = [key, secdesc]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log, EXE_NEW_HOSTKEYFILE,
+ args=args)
+ runutil.generic_bailout("Problem activating host key",
+ exitcode, stdout, stderr)
+ log.debug("Activated host key file in GT container: %s" % cert)
+
+def adjust_broker_config(cacert, cakey, keystore, keystore_pass, basedir, gtdir, log):
+ brokerconfig = get_brokerconfig_path(gtdir)
+
+ pathutil.ensure_file_exists(cacert, "CA certificate")
+ pathutil.ensure_file_exists(cakey, "CA private key")
+ pathutil.ensure_file_exists(brokerconfig, "Nimbus Context Broker config")
+ pathutil.ensure_file_exists(keystore, "Java keystore")
+
+ # is some BS
+ restbroker_xml = pathutil.pathjoin(gtdir,
+ 'etc/nimbus-context-broker/other/main.xml')
+ pathutil.ensure_file_exists(restbroker_xml,
+ "Context Broker REST interface config")
+
+ args = [brokerconfig, 'NimbusContextBroker', 'ctxBrokerBootstrapFactory',
+ 'caCertPath', cacert, 'caKeyPath', cakey]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log,
+ EXE_SERVICE_RESOURCE, args=args)
+ runutil.generic_bailout("Problem adjusting broker config",
+ exitcode, stdout, stderr)
+
+ args = [brokerconfig, 'NimbusContextBroker', 'rest',
+ 'keystoreLocation', keystore, 'keystorePassword', keystore_pass,
+ 'springConfig', restbroker_xml]
+ (exitcode, stdout, stderr) = javautil.run(basedir, log,
+ EXE_SERVICE_RESOURCE, args=args)
+ runutil.generic_bailout("Problem adjusting broker config",
+ exitcode, stdout, stderr)
+ log.debug("Ensured Context Broker CA config: %s" % brokerconfig)
+
+def get_brokerconfig_path(gtdir):
+ return pathutil.pathjoin(gtdir, CONF_BROKERCONFIG)
+
+def get_serverconfig_path(gtdir):
+ return pathutil.pathjoin(gtdir, CONF_SERVERCONFIG)
+
+def get_secdesc_path(gtdir):
+ return pathutil.pathjoin(gtdir, CONF_SECDESC)
+
View
0  ctx-broker/home/lib/pynimbusconfig/iaas/__init__.py
No changes.
View
85 ctx-broker/home/lib/pynimbusconfig/iaas/derbyutil.py
@@ -0,0 +1,85 @@
+import os
+import re
+import sys
+import time
+import shutil
+import tempfile
+from subprocess import Popen, PIPE
+
+def update_db(ij_path, old_db, new_db):
+ """
+ ij_path -- assumes that this exists
+ old_db -- path to 2.2 or 2.3 accounting db
+ new_db -- path to 2.4 accounting db
+ """
+
+ def _run_sql_on_db(ij_path, database, sql, user=None, password=None):
+ script = "connect 'jdbc:derby:%s' " % database
+ if user and password:
+ script += "user '%s' " % user
+ script += "password '%s' " % password
+ script += ";"
+ script += sql
+ script += "disconnect; exit;"
+
+ (script_file, script_filename) = tempfile.mkstemp()
+ os.write(script_file, script)
+ os.close(script_file)
+
+ ij_args = ij_path.split()
+ ij_args.append(script_filename)
+ output = Popen(ij_args, stdout=PIPE).communicate()[0]
+ os.remove(script_filename)
+
+ return output
+
+ # Check that the databases exist
+ if not os.path.exists(old_db):
+ print >> sys.stderr, "Error in db-update: %s doesn't exist" % old_db
+ return 1
+
+ if not os.path.exists(new_db):
+ print >> sys.stderr, "Error in db-update: %s doesn't exist" % new_db
+ return 1
+
+ # determine schema of deployments table
+ tables_sql = "SHOW TABLES;"
+ output = _run_sql_on_db(ij_path, old_db, tables_sql)
+ find_schema = re.compile(".*(APP|NIMBUS)\s*\|DEPLOYMENTS", re.DOTALL)
+ schema = find_schema.match(output).group(1)
+
+ # Pull data out of old database
+ select_sql = """
+ SELECT uuid, workspaceid, creator_dn, creation_time,\
+ requested_duration, active, elapsed_minutes\
+ FROM %s.deployments;
+ """ % schema
+ output = _run_sql_on_db(ij_path, old_db, select_sql)
+ if re.match(".*error", output, re.IGNORECASE | re.DOTALL):
+ print >> sys.stderr, "Error in db-update: Problem getting old data"
+ print >> sys.stderr, output
+ return 1
+
+
+ insert_sql = ""
+ for line in output.splitlines():
+ # disgard lines that aren't data
+ if line.startswith("ij") or line.startswith("UUID ") \
+ or line.startswith("-------") or line.endswith("selected")\
+ or line == "":
+ continue
+
+ elements = line.split("|")
+ elements = [element.strip() for element in elements]
+
+ insert_sql += "INSERT INTO nimbus.deployments (uuid, workspaceid, creator_dn,"\
+ "creation_time, requested_duration, active, elapsed_minutes) "\
+ "VALUES ('%s', %s, '%s', %s, %s, %s, %s);\n" %\
+ (elements[0], elements[1], elements[2], elements[3],
+ elements[4], elements[5], elements[6])
+
+ output = _run_sql_on_db(ij_path, new_db, insert_sql)
+ if re.match(".*error", output, re.IGNORECASE | re.DOTALL):
+ print >> sys.stderr, "Error in db-update: Problem inserting data"
+ print >> sys.stderr, output
+ return 1
View
169 ctx-broker/home/lib/pynimbusconfig/iaas/groupauthz.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+
+"""Provides basic management of Nimbus groupauthz members.
+"""
+
+import os
+import tempfile
+from itertools import groupby
+import shutil
+
+_GROUP_FILE_PREFIX = 'group'
+_GROUP_PROPS_EXT = '.properties'
+_GROUP_MEMBERS_EXT = '.txt'
+
+def all_groups(groupauthz_dir):
+ """Returns a list of all valid groups
+ """
+ groups = []
+ files = [f for f in os.listdir(groupauthz_dir)
+ if f.startswith(_GROUP_FILE_PREFIX) and (f.endswith(_GROUP_PROPS_EXT) or f.endswith(_GROUP_MEMBERS_EXT))]
+ files.sort()
+ for name, group_files in groupby(files, lambda f: os.path.splitext(f)[0]):
+ members_path = None
+ props_path = None
+ for f in group_files:
+ ext = os.path.splitext(f)[1].lower()
+ if ext == _GROUP_PROPS_EXT:
+ props_path = os.path.join(groupauthz_dir, f)
+ elif ext == _GROUP_MEMBERS_EXT:
+ members_path = os.path.join(groupauthz_dir, f)
+ group_id = int(name[len(_GROUP_FILE_PREFIX):])
+
+ if members_path and props_path:
+ groups.append(Group(group_id, props_path, members_path))
+ return groups
+
+def one_group(groupauthz_dir, group_id):
+ """Returns the specified group, or raises an InvalidGroupError
+ """
+ group_id = _assure_group_id(group_id)
+ # inefficient, meh
+ for group in all_groups(groupauthz_dir):
+ if group.group_id == group_id:
+ return group
+ raise InvalidGroupError('group %s was not found' % group_id)
+
+def group_members(groupauthz_dir, group_id):
+ """Returns a list of DNs authorized in specified group
+ """
+ group_id = _assure_group_id(group_id)
+ g = one_group(groupauthz_dir, group_id)
+ return g.get_members()
+
+def find_member(groupauthz_dir, dn):
+ """Finds the group containing a DN, or None
+ """
+ for group in all_groups(groupauthz_dir):
+ if group.has_member(dn):
+ return group
+ return None
+
+def add_member(groupauthz_dir, dn, group_id=1):
+ """Adds a DN to a group. if the group already contains DN, do nothing
+ """
+ group_id = _assure_group_id(group_id)
+ g = one_group(groupauthz_dir, group_id)
+ return g.add_member(dn)
+
+def remove_member(groupauthz_dir, dn, group_id=None):
+ """Removes a DN from all groups, or a specified group
+ """
+
+ if group_id:
+ group_id = _assure_group_id(group_id)
+ g = one_group(groupauthz_dir, group_id)
+ return g.remove_member(dn)
+ removed = False
+ for group in all_groups(groupauthz_dir):
+ if group.remove_member(dn):
+ removed = True
+ return removed
+
+def _assure_group_id(group_id):
+ """Ensures that group ID is an integer
+ """
+ try:
+ return int(group_id)
+ except (ValueError, TypeError):
+ raise InvalidGroupError("Group ID is invalid, must be an integer")
+
+
+class Group(object):
+ """A single group definition
+ """
+ def __init__(self, group_id, props_path, members_path):
+ self.group_id = group_id
+ self.props_path = props_path
+ self.members_path = members_path
+ # later we could parse the properties file and grab the group info
+
+ def __str__(self):
+ return self.group_id
+
+ def get_members(self):
+ """Returns list of member DNs in this group"""
+ f = None
+ members = []
+ try:
+ f = file(self.members_path)
+ for line in f:
+ line = line.strip()
+ if line:
+ members.append(line)
+ finally:
+ if f: f.close()
+ return members
+
+ def has_member(self, dn):
+ """Whether specified DN is a member of group
+ """
+ for member in self.get_members():
+ if member == dn:
+ return True
+ return False
+
+ def add_member(self, dn):
+ """Add specified DN to group, if it isn't already a member.
+ Returns update status.
+ """
+ if self.has_member(dn):
+ return False
+ f = None
+ try:
+ f = file(self.members_path, 'a')
+ f.write(dn+'\n')
+ finally:
+ if f: f.close()
+ return True
+
+ def remove_member(self, dn):
+ """Removes specified DN from group. Returns update status.
+ """
+ f = None
+ tempf = None
+ try:
+ removed = False
+ f = file(self.members_path)
+ tempfd, temppath = tempfile.mkstemp(text=True)
+ tempf = os.fdopen(tempfd,'w')
+ for line in f:
+ if line.strip() != dn.strip():
+ tempf.write(line)
+ else:
+ removed = True
+ f.close()
+ tempf.close()
+ shutil.move(temppath, self.members_path)
+
+ return removed
+
+ finally:
+ if f: f.close()
+ if tempf: tempf.close()
+
+class InvalidGroupError(Exception):
+ """Group does not exist or is invalid
+ """
+ pass
+
View
422 ctx-broker/home/lib/pynimbusconfig/iaas/main.py
@@ -0,0 +1,422 @@
+#!/usr/bin/env python
+
+import ConfigParser
+import logging
+import optparse
+import os
+import sys
+import traceback
+
+from pynimbusconfig import checkssl
+from pynimbusconfig import forcessl
+from pynimbusconfig.web import newconf
+from pynimbusconfig import pathutil
+from pynimbusconfig.setuperrors import *
+
+def getlog(override=None):
+ """Allow developer to replace logging mechanism, e.g. if this
+ module is incorporated into another program as an API.
+
+ Keyword arguments:
+
+ * override -- Custom logger (default None, uses global variable)
+
+ """
+ global _log
+ if override:
+ _log = override
+ try:
+ _log
+ except:
+ _log = logging.getLogger("nimbussetup")
+ _log.setLevel(logging.DEBUG)
+ return _log
+
+def configureLogging(level, formatstring=None, logger=None):
+ """Configure the logging format and mechanism. Sets global 'log' variable.
+
+ Required parameter:
+
+ * level -- log level
+
+ Keyword arguments:
+
+ * formatstring -- Custom logging format (default None, uses time+level+msg)
+
+ * logger -- Custom logger (default None)
+ """
+
+ global log
+
+ logger = getlog(override=logger)
+
+ if not formatstring:
+ formatstring = "%(asctime)s (%(filename)s:%(lineno)d): %(message)s"
+
+ formatter = logging.Formatter(formatstring)
+ ch = logging.StreamHandler()
+ ch.setLevel(level)
+ ch.setFormatter(formatter)
+ logger.addHandler(ch)
+
+ # set global variable
+ log = logger
+
+ log.debug("debug enabled")
+
+def getconfig(filepath):
+ if not filepath:
+ raise InvalidConfig("filepath was not supplied to getconfig()")
+ config = ConfigParser.SafeConfigParser()
+ config.read(filepath)
+ return config
+
+def config_from_key(config, key, section="nimbusweb"):
+ setting = config.get(section, key)
+ log.debug("%s: %s" % (key, setting))
+ return setting
+
+class ARGS:
+
+ """Class for command-line argument constants"""
+
+ BASEDIR_LONG="--basedir"
+ BASEDIR="-b"
+ BASEDIR_HELP="Path to base web directory (where bin, lib, etc. is)"
+
+ CHECKSSL_LONG="--checkssl"
+ CHECKSSL="-s"
+ CHECKSSL_HELP="Check on SSL setup for standalone server system"
+
+ CONFIGPATH_LONG="--conf"
+ CONFIGPATH="-c"
+ CONFIGPATH_HELP="Path to configuration file"
+
+ DEBUG_LONG="--debug"
+ DEBUG="-d"
+ DEBUG_HELP="Log debug messages"
+
+ NEWCONF_LONG="--newconf"
+ NEWCONF="-n"
+ NEWCONF_HELP="Make sure the internal webapp settings are in line with the standalone system's conf file and filesystem location"
+
+ FORCESSL_LONG="--forcessl"
+ FORCESSL="-f"
+ FORCESSL_HELP="Set up a CA and hostcert, useful outside webapp system. \
+It is not interactive."
+
+ FORCECAPATH_LONG="--force-ca-path"
+ FORCECAPATH="-p"
+ FORCECAPATH_HELP="Absolute path to non-existent CA directory for %s" % FORCESSL_LONG
+
+ FORCECERTPATH_LONG="--force-hostcert-path"
+ FORCECERTPATH="-e"
+ FORCECERTPATH_HELP="Absolute path to non-existent hostcert for %s" % FORCESSL_LONG
+
+ FORCEKEYPATH_LONG="--force-hostkey-path"
+ FORCEKEYPATH="-k"
+ FORCEKEYPATH_HELP="Absolute path to non-existent hostkey for %s" % FORCESSL_LONG
+
+ FORCEHOSTNAME_LONG="--force-hostname"
+ FORCEHOSTNAME="-m"
+ FORCEHOSTNAME_HELP="hostname to use for hostcert in %s" % FORCESSL_LONG
+
+ PRINTPORT_LONG="--printport"
+ PRINTPORT="-t"
+ PRINTPORT_HELP="Print configured port # to stdout"
+
+ PRINTHOST_LONG="--printhost"
+ PRINTHOST="-l"
+ PRINTHOST_HELP="Print configured host interface to stdout"
+
+ PRINTCERTPATH_LONG="--printcertpath"
+ PRINTCERTPATH="-i"
+ PRINTCERTPATH_HELP="Print configured cert path to stdout and exit"
+
+ PRINTKEYPATH_LONG="--printkeypath"
+ PRINTKEYPATH="-z"
+ PRINTKEYPATH_HELP="Print configured key path to stdout and exit"
+
+ # only used by "developer-server.sh"
+ INSECUREMODE_LONG="--insecuremode"
+ INSECUREMODE="-a"
+ INSECUREMODE_HELP="Alter configuration to allow for developer's insecure mode"
+
+def validateargs(opts):
+
+ actions = [opts.checkssl, opts.forcenewssl, opts.newconf,
+ opts.printport, opts.printcertpath, opts.printkeypath,
+ opts.printhost]
+
+ count = 0
+ for action in actions:
+ if action:
+ count += 1
+
+ seeh = "see help (-h)"
+
+ if not count:
+ raise InvalidInput("You must supply an action, %s." % seeh)
+
+ if count != 1:
+ raise InvalidInput("You may only supply one action, %s." % seeh)
+
+ if not opts.basedir:
+ raise InvalidInput("%s required, %s." % (ARGS.BASEDIR_LONG, seeh))
+
+ if opts.forcenewssl:
+ if not opts.forcecapath:
+ raise InvalidInput("%s required for %s, %s." % (ARGS.FORCECAPATH_LONG, ARGS.FORCESSL_LONG, seeh))
+ if not opts.forcecertpath: