summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZiad Sawalha <github@highbridgellc.com>2011-12-04 03:03:22 -0600
committerDolph Mathews <dolph.mathews@gmail.com>2011-12-06 10:26:50 -0600
commit0d8bc572339bc8defe5ea5fba16eedcd79c5472b (patch)
tree7431f1b0db879acd53ae48270cb347f966f4215b
parent5d7b61b76fc0b05cc029177182e9e9607f210232 (diff)
downloadkeystone-0d8bc572339bc8defe5ea5fba16eedcd79c5472b.tar.gz
keystone-0d8bc572339bc8defe5ea5fba16eedcd79c5472b.tar.xz
keystone-0d8bc572339bc8defe5ea5fba16eedcd79c5472b.zip
Refactor: move initialization code to class
- Each script (keystone, keystone-admin, keystone-auth) had a copy of the initialization code that handled options, arguments, and starting the paste apps. The code was also duplicated in the test SetUp code. This code has now been consolidated in one class. - Created the keystone.Server class that has start/stop methods to manage keystone servers. It also handles initializing options and arguments. - This provides one point of entry into keystone where we can now start refactoring logging and backend code. Change-Id: Ie4e2a9aae9578c3657c0459381d1618d30b8ca32
-rwxr-xr-xbin/keystone81
-rwxr-xr-xbin/keystone-admin35
-rwxr-xr-xbin/keystone-auth35
-rw-r--r--keystone/__init__.py131
-rw-r--r--keystone/test/__init__.py75
5 files changed, 176 insertions, 181 deletions
diff --git a/bin/keystone b/bin/keystone
index db4d1dca..d79189db 100755
--- a/bin/keystone
+++ b/bin/keystone
@@ -36,16 +36,18 @@ if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
import keystone.tools.tracer # @UnusedImport # module runs on import
import keystone
-from keystone.common import config, wsgi
+from keystone.common import config
if __name__ == '__main__':
+
# Initialize a parser for our configuration paramaters
+ # since we have special handling for --admin-port argument
parser = optparse.OptionParser(version='%%prog %s' % keystone.version)
common_group = config.add_common_options(parser)
config.add_log_options(parser)
# Handle a special argument to support starting two endpoints
- common_group.add_option(
+ option = common_group.add_option(
'-a', '--admin-port', dest="admin_port", metavar="PORT",
help="specifies port for Admin API to listen on (default is 35357)")
@@ -54,67 +56,22 @@ if __name__ == '__main__':
# Start services
try:
- # Load Service API server
- conf, app = config.load_paste_app(
- 'keystone-legacy-auth', options, args)
- admin_conf, admin_app = config.load_paste_app(
- 'admin', options, args)
-
- debug = options.get('debug') or conf.get('debug', False)
- debug = debug in [True, "True", "1"]
- verbose = options.get('verbose') or conf.get('verbose', False)
- verbose = verbose in [True, "True", "1"]
-
- # Safely get SSL options
- service_ssl = conf.get('service_ssl', False)
- service_ssl = service_ssl in [True, "True", "1"]
- admin_ssl = conf.get('admin_ssl', False)
- admin_ssl = admin_ssl in [True, "True", "1"]
- cert_required = conf.get('cert_required', False)
- cert_required = cert_required in [True, "True", "1"]
- certfile = conf.get('certfile')
- keyfile = conf.get('keyfile')
- ca_certs = conf.get('ca_certs')
-
- if debug or verbose:
- config_file = config.find_config_file(options, args)
- print "Using config file:", config_file
-
- port = int(options.get('bind_port') or conf.get('service_port', 5000))
- host = options.get('bind_host', conf.get('service_host', '0.0.0.0'))
-
- # Load Service API server
- if service_ssl:
- server = wsgi.SslServer()
- server.start(app, port, host,
- certfile=certfile, keyfile=keyfile,
- ca_certs=ca_certs,
- cert_required=cert_required)
- else:
- server = wsgi.Server()
- server.start(app, port, host)
-
- print "Service API (ssl=%s) listening on %s:%s" % (
- service_ssl, host, port)
+ # Load Service API Server
+ service = keystone.Server(name="Service API",
+ config_name='keystone-legacy-auth',
+ options=options, args=args)
+ service.start(wait=False)
+ except RuntimeError, e:
+ sys.exit("ERROR: %s" % e)
+ try:
# Load Admin API server
- port = int(options.get('admin_port') or conf.get('admin_port', 35357))
- host = options.get('bind_host', conf.get('admin_host', '0.0.0.0'))
-
- if admin_ssl:
- admin_server = wsgi.SslServer()
- admin_server.start(admin_app, port, host,
- certfile=certfile, keyfile=keyfile,
- ca_certs=ca_certs,
- cert_required=cert_required)
- else:
- admin_server = wsgi.Server()
- admin_server.start(admin_app, port, host)
-
- print "Admin API (ssl=%s) listening on %s:%s" % (
- admin_ssl, host, port)
-
- # Wait until done
- server.wait()
+ port = options.get('admin_port', None)
+ host = options.get('bind_host', None)
+ admin = keystone.Server(name='Admin API', config_name='admin',
+ options=options, args=args)
+ admin.start(host=host, port=port, wait=True)
except RuntimeError, e:
sys.exit("ERROR: %s" % e)
+ finally:
+ service.stop()
diff --git a/bin/keystone-admin b/bin/keystone-admin
index fd5c6ef9..68549303 100755
--- a/bin/keystone-admin
+++ b/bin/keystone-admin
@@ -19,7 +19,7 @@
# under the License.
"""
-Keystone Identity Server - Admin API
+Keystone Identity Server - Admin API
"""
import optparse
@@ -36,40 +36,11 @@ if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
import keystone.tools.tracer # @UnusedImport # module runs on import
import keystone
-from keystone.common import config, wsgi
-
if __name__ == '__main__':
- # Initialize a parser for our configuration paramaters
- parser = optparse.OptionParser(version='%%prog %s' % keystone.version)
- common_group = config.add_common_options(parser)
- config.add_log_options(parser)
-
- # Parse arguments and load config
- (options, args) = config.parse_options(parser)
- config_file = config.find_config_file(options, args)
-
- # Start services
try:
# Load Admin API server
- conf, app = config.load_paste_app('admin', options, args)
-
- debug = options.get('debug') or conf.get('debug', False)
- debug = debug in [True, "True", "1"]
- verbose = options.get('verbose') or conf.get('verbose', False)
- verbose = verbose in [True, "True", "1"]
- if debug or verbose:
- print "Using config file:", config_file
-
- server = wsgi.Server()
-
- port = int(options['bind_port'] or conf['admin_port'] or 35357)
- host = options['bind_host'] or conf['admin_host']
-
- server.start(app, port, host)
-
- print "Admin API listening on %s:%s" % (host, port)
-
- server.wait()
+ admin = keystone.Server(name='Admin API', config_name='admin')
+ admin.start(wait=True)
except RuntimeError, e:
sys.exit("ERROR: %s" % e)
diff --git a/bin/keystone-auth b/bin/keystone-auth
index 73d43863..287482a0 100755
--- a/bin/keystone-auth
+++ b/bin/keystone-auth
@@ -36,41 +36,12 @@ if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
import keystone.tools.tracer # @UnusedImport # module runs on import
import keystone
-from keystone.common import config, wsgi
-
if __name__ == '__main__':
- # Initialize a parser for our configuration paramaters
- parser = optparse.OptionParser(version='%%prog %s' % keystone.version)
- common_group = config.add_common_options(parser)
- config.add_log_options(parser)
-
- # Parse arguments and load config
- (options, args) = config.parse_options(parser)
-
- # Start services
try:
# Load Service API server
- conf, app = config.load_paste_app('keystone-legacy-auth',
- options, args)
-
- debug = options.get('debug') or conf.get('debug', False)
- debug = debug in [True, "True", "1"]
- verbose = options.get('verbose') or conf.get('verbose', False)
- verbose = verbose in [True, "True", "1"]
- if debug or verbose:
- config_file = config.find_config_file(options, args)
- print "Using config file:", config_file
-
- server = wsgi.Server()
-
- port = int(options['bind_port'] or conf['service_port'] or 5000)
- host = options['bind_host'] or conf['service_host']
-
- server.start(app, port, host)
-
- print "Service API listening on %s:%s" % (host, port)
-
- server.wait()
+ admin = keystone.Server(name='Service API',
+ config_name='keystone-legacy-auth')
+ admin.start(wait=True)
except RuntimeError, e:
sys.exit("ERROR: %s" % e)
diff --git a/keystone/__init__.py b/keystone/__init__.py
index 226b09ae..30ee337f 100644
--- a/keystone/__init__.py
+++ b/keystone/__init__.py
@@ -13,6 +13,10 @@
# limitations under the License.
import gettext
+import optparse
+import sys
+
+from keystone.common import config, wsgi
API_VERSION = "2.0"
@@ -37,3 +41,130 @@ def version():
# This installs the _(...) function as a built-in so all other modules
# don't need to.
gettext.install('keystone')
+
+
+class Server():
+ """Used to start and stop Keystone servers
+
+ This class is called from shell and command-line scripts and is the
+ entry-point for starting and stopping Keystone servers.
+
+ The initializer can take option and argument overrides, but otherwise will
+ parse arguments and configuration files itself to determine how to start
+ the server.
+ """
+
+ def __init__(self, name='admin', config_name=None,
+ options=None, args=None):
+ """Initizalizer which takes the following paramaters:
+
+ :param name: A cosmetic name for the server (ex. Admin API)
+ :param config: the paste config name to look for when starting the
+ server
+ :param options: a mapping of option key/str(value) pairs passed to
+ config.load_paste_app
+ :param args: override for sys.argv (otherwise sys.argv is used)
+ """
+ self.options = options
+ if args:
+ self.args = args
+ else:
+ self.args = sys.argv
+
+ if options is None or args is None:
+ # Initialize a parser for our configuration paramaters
+ parser = optparse.OptionParser(version='%%prog %s' %
+ version)
+ common_group = config.add_common_options(parser)
+ config.add_log_options(parser)
+
+ # Parse arguments and load config
+ (poptions, pargs) = config.parse_options(parser)
+
+ if options is None:
+ self.options = poptions
+ else:
+ self.options = options
+
+ if args is None:
+ self.args = pargs
+ else:
+ self.args = args
+
+ self.name = name
+ self.config = config_name or self.name
+
+ def start(self, host=None, port=None, wait=True):
+ """Starts the Keystone server
+
+ :param host: the IP address to listen on
+ :param port: the TCP/IP port to listen on
+ :param wait: whether to wait (block) for the server to terminate or
+ return to the caller without waiting
+ """
+ # Load Service API server
+ conf, app = config.load_paste_app(
+ self.config, self.options, self.args)
+
+ debug = self.options.get('debug') or conf.get('debug', False)
+ debug = debug in [True, "True", "1"]
+ verbose = self.options.get('verbose') or conf.get('verbose', False)
+ verbose = verbose in [True, "True", "1"]
+
+ if debug or verbose:
+ config_file = config.find_config_file(self.options, self.args)
+ print "Starting '%s' with config: %s" % (self.config, config_file)
+
+ if port is None:
+ if self.config == 'admin':
+ # Legacy
+ port = int(self.options.get('bind_port') or
+ conf.get('admin_port', 35357))
+ else:
+ port = int(self.options.get('bind_port') or
+ conf.get('service_port', 5000))
+ if host is None:
+ host = self.options.get('bind_host',
+ conf.get('service_host', '0.0.0.0'))
+
+ self.key = "%s-%s:%s" % (self.name, host, port)
+
+ # Safely get SSL options
+ service_ssl = conf.get('service_ssl', False)
+ service_ssl = service_ssl in [True, "True", "1"]
+
+ # Load the server
+ if service_ssl:
+ cert_required = conf.get('cert_required', False)
+ cert_required = cert_required in [True, "True", "1"]
+ certfile = conf.get('certfile')
+ keyfile = conf.get('keyfile')
+ ca_certs = conf.get('ca_certs')
+
+ self.server = wsgi.SslServer()
+ self.server.start(app, port, host,
+ certfile=certfile, keyfile=keyfile,
+ ca_certs=ca_certs,
+ cert_required=cert_required,
+ key=self.key)
+ else:
+ self.server = wsgi.Server()
+ self.server.start(app, port, host,
+ key="%s-%s:%s" % (self.config, host, port))
+
+ print "%s listening on %s://%s:%s" % (
+ self.name, ['http', 'https'][service_ssl], host, port)
+
+ # Wait until done
+ if wait:
+ self.server.wait()
+
+ def stop(self):
+ """Stops the Keystone server
+
+ This should be called always to release the network socket
+ """
+ if self.server is not None:
+ if self.key in self.server.threads:
+ self.server.threads[self.key].kill()
+ self.server = None
diff --git a/keystone/test/__init__.py b/keystone/test/__init__.py
index 915eaf15..3765bfba 100644
--- a/keystone/test/__init__.py
+++ b/keystone/test/__init__.py
@@ -65,7 +65,7 @@ cgitb.enable(format="text")
from functional.common import HttpTestCase
import keystone
from keystone.common import config, wsgi
-from keystone import backends
+from keystone import backends, Server
TEST_DIR = os.path.abspath(os.path.dirname(__file__))
BASE_DIR = os.path.abspath(os.path.join(TEST_DIR, os.pardir, os.pardir))
@@ -399,61 +399,28 @@ class KeystoneTest(object):
(options, args) = config.parse_options(parser)
options['config_file'] = self.conf_fp.name
- # Start services
try:
- # Load Service API server
- conf, app = config.load_paste_app(
- 'keystone-legacy-auth', options, args)
- admin_conf, admin_app = config.load_paste_app(
- 'admin', options, args)
-
- port = int(options['bind_port'] or conf['service_port'] or 5000)
- host = options['bind_host'] or conf['service_host']
-
- if (self.isSsl == True):
- server = wsgi.SslServer()
- server.start(app, port, host,
- certfile=conf['certfile'],
- keyfile=conf['keyfile'],
- ca_certs=conf['ca_certs'],
- cert_required=conf['cert_required'])
- # Load Admin API server
- port = int(options['admin_port'] or conf['admin_port']
- or 35357)
- host = options['bind_host'] or conf['admin_host']
-
- admin_server = wsgi.SslServer()
- admin_server.start(admin_app,
- port, host,
- certfile=conf['certfile'],
- keyfile=conf['keyfile'],
- ca_certs=conf['ca_certs'],
- cert_required=conf['cert_required'])
-
- else:
- server = wsgi.Server()
- server.start(app, port, host, key="Test")
-
- print "Service API (ssl=%s) listening on %s:%s" % (
- conf['service_ssl'], host, port)
-
- # Load Admin API server
- port = int(options['admin_port'] or conf['admin_port']
- or 35357)
- host = options['bind_host'] or conf['admin_host']
-
- admin_server = wsgi.Server()
- admin_server.start(admin_app, port, host, key="Test")
-
- print "Admin API (ssl=%s) listening on %s:%s" % (
- conf['admin_ssl'], host, port)
+ # Load Service API Server
+ service = keystone.Server(name="Service API",
+ config_name='keystone-legacy-auth',
+ options=options, args=args)
+ service.start(wait=False)
+ except RuntimeError, e:
+ sys.exit("ERROR: %s" % e)
+ try:
+ # Load Admin API server
+ port = options.get('admin_port', None)
+ host = options.get('bind_host', None)
+ admin = keystone.Server(name='Admin API', config_name='admin',
+ options=options, args=args)
+ admin.start(host=host, port=port, wait=False)
except RuntimeError, e:
- print e
+ service.stop()
sys.exit("ERROR: %s" % e)
- self.server = server
- self.admin_server = admin_server
+ self.server = service
+ self.admin_server = admin
# Load sample data
from keystone.test import sampledata
@@ -465,12 +432,10 @@ class KeystoneTest(object):
print "Stopping the keystone server..."
try:
if self.server is not None:
- if 'Test' in self.server.threads:
- self.server.threads['Test'].kill()
+ self.server.stop()
self.server = None
if self.admin_server is not None:
- if 'Test' in self.admin_server.threads:
- self.admin_server.threads['Test'].kill()
+ self.admin_server.stop()
self.admin_server = None
self.conf_fp.close()
self.conf_fp = None