Migrating trove to entry points

PBR/Distribute generates binscripts for us. By moving the
binscript code into the source tree, we can unit test it
as well. Run setup.py develop to generate the binscripts for
development use.

implements blueprint entrypoints-for-binscripts
Change-Id: I9ad4bb4ddc55f64bcd806c588a795cd6e0847aa9
This commit is contained in:
Michael Basnight 2014-02-01 00:24:57 +00:00
parent 67e3e7a76e
commit b06db4ab7f
14 changed files with 90 additions and 580 deletions

View File

@ -1,72 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Starter script for Nova OS API."""
import eventlet
eventlet.monkey_patch()
import os
import sys
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
sys.argv[0]), os.pardir, os.pardir))
if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")):
sys.path.insert(0, possible_topdir)
from nova import flags
from nova import log as logging
from nova import service
from nova import utils
from nova import wsgi
from nova.openstack.common import cfg
SERVICE_NAME = "troveapi_database"
trove_opts = [
cfg.StrOpt('trove_api_paste_config',
default='trove-api-paste.ini',
help='Trove API paste config'),
# port magic in service.WSGIService the name of the app has to be the same
# as the name of the service
cfg.IntOpt('%s_listen_port' % SERVICE_NAME,
default=8779,
help='Trove API default port'),
cfg.MultiStrOpt('trove_api_extension',
default=['trove.api.database.contrib.standard_extensions'],
help='osapi compute extension to load'), ]
FLAGS = flags.FLAGS
FLAGS.register_opts(trove_opts)
def main():
utils.default_flagfile()
flags.FLAGS(sys.argv)
logging.setup()
utils.monkey_patch()
loader = wsgi.Loader(config_path=FLAGS.trove_api_paste_config)
server = service.WSGIService(SERVICE_NAME, loader=loader)
service.serve(server)
service.wait()
if __name__ == '__main__':
main()

View File

@ -1,303 +0,0 @@
#!/usr/bin/env python
# Copyright 2011 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Trove Command line tool
"""
import json
import optparse
import os
import sys
# If ../trove/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'troveclient',
'__init__.py')):
sys.path.insert(0, possible_topdir)
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
sys.path.insert(0, possible_topdir)
from troveclient import common
oparser = None
def _pretty_print(info):
print(json.dumps(info, sort_keys=True, indent=4))
class InstanceCommands(object):
"""Commands to perform various instances operations and actions"""
def __init__(self):
pass
def create(self, name, volume_size,
flavorRef="http://localhost:8775/v1.0/flavors/1"):
"""Create a new instance"""
dbaas = common.get_client()
volume = {"size": volume_size}
try:
result = dbaas.instances.create(name, flavorRef, volume)
_pretty_print(result._info)
except Exception:
print(sys.exc_info()[1])
def delete(self, id):
"""Delete the specified instance"""
dbaas = common.get_client()
try:
result = dbaas.instances.delete(id)
if result:
print(result)
except Exception:
print(sys.exc_info()[1])
def get(self, id):
"""Get details for the specified instance"""
dbaas = common.get_client()
try:
_pretty_print(dbaas.instances.get(id)._info)
except Exception:
print(sys.exc_info()[1])
def list(self):
"""List all instances for account"""
dbaas = common.get_client()
try:
for instance in dbaas.instances.list():
_pretty_print(instance._info)
except Exception:
print(sys.exc_info()[1])
def resize(self, id, size):
"""Resize an instance volume"""
dbaas = common.get_client()
try:
result = dbaas.instances.resize(id, size)
if result:
print(result)
except Exception:
print(sys.exc_info()[1])
def restart(self, id):
"""Restart the database"""
dbaas = common.get_client()
try:
result = dbaas.instances.restart(id)
if result:
print(result)
except Exception:
print(sys.exc_info()[1])
class FlavorsCommands(object):
"""Commands for listing Flavors"""
def __init__(self):
pass
def list(self):
"""List the available flavors"""
dbaas = common.get_client()
try:
for flavor in dbaas.flavors.list():
_pretty_print(flavor._info)
except Exception:
print(sys.exc_info()[1])
class DatabaseCommands(object):
"""Database CRUD operations on an instance"""
def __init__(self):
pass
def create(self, id, dbname):
"""Create a database"""
dbaas = common.get_client()
try:
databases = [{'name': dbname}]
dbaas.databases.create(id, databases)
except Exception:
print(sys.exc_info()[1])
def delete(self, id, dbname):
"""Delete a database"""
dbaas = common.get_client()
try:
dbaas.databases.delete(id, dbname)
except Exception:
print(sys.exc_info()[1])
def list(self, id):
"""List the databases"""
dbaas = common.get_client()
try:
for database in dbaas.databases.list(id):
_pretty_print(database._info)
except Exception:
print(sys.exc_info()[1])
class UserCommands(object):
"""User CRUD operations on an instance"""
def __init__(self):
pass
def create(self, id, username, password, dbname, *args):
"""Create a user in instance, with access to one or more databases"""
dbaas = common.get_client()
try:
databases = [{'name': dbname}]
[databases.append({"name": db}) for db in args]
users = [{'name': username, 'password': password,
'databases': databases}]
dbaas.users.create(id, users)
except Exception:
print(sys.exc_info()[1])
def delete(self, id, user):
"""Delete the specified user"""
dbaas = common.get_client()
try:
dbaas.users.delete(id, user)
except Exception:
print(sys.exc_info()[1])
def list(self, id):
"""List all the users for an instance"""
dbaas = common.get_client()
try:
for user in dbaas.users.list(id):
_pretty_print(user._info)
except Exception:
print(sys.exc_info()[1])
class RootCommands(object):
"""Root user related operations on an instance"""
def __init__(self):
pass
def create(self, id):
"""Enable the instance's root user."""
dbaas = common.get_client()
try:
user, password = dbaas.root.create(id)
print("User:\t\t%s\nPassword:\t%s" % (user, password))
except Exception:
print(sys.exc_info()[1])
def enabled(self, id):
"""Check the instance for root access"""
dbaas = common.get_client()
try:
_pretty_print(dbaas.root.is_root_enabled(id))
except Exception:
print(sys.exc_info()[1])
class VersionCommands(object):
"""List available versions"""
def __init__(self):
pass
def list(self, url):
"""List all the supported versions"""
dbaas = common.get_client()
try:
versions = dbaas.versions.index(url)
for version in versions:
_pretty_print(version._info)
except Exception:
print(sys.exc_info()[1])
def config_options():
global oparser
oparser.add_option("-u", "--url", default="http://localhost:5000/v1.1",
help="Auth API endpoint URL with port and version. \
Default: http://localhost:5000/v1.1")
COMMANDS = {'auth': common.Auth,
'instance': InstanceCommands,
'flavor': FlavorsCommands,
'database': DatabaseCommands,
'user': UserCommands,
'root': RootCommands,
'version': VersionCommands}
def main():
# Parse arguments
global oparser
oparser = optparse.OptionParser("%prog [options] <cmd> <action> <args>",
version='1.0')
config_options()
(options, args) = oparser.parse_args()
if not args:
common.print_commands(COMMANDS)
# Pop the command and check if it's in the known commands
cmd = args.pop(0)
if cmd in COMMANDS:
fn = COMMANDS.get(cmd)
command_object = fn()
# Get a list of supported actions for the command
actions = common.methods_of(command_object)
if len(args) < 1:
common.print_actions(cmd, actions)
# Check for a valid action and perform that action
action = args.pop(0)
if action in actions:
fn = actions.get(action)
try:
fn(*args)
sys.exit(0)
except TypeError as err:
print("Possible wrong number of arguments supplied.")
print("%s %s: %s" % (cmd, action, fn.__doc__))
print("\t\t", [fn.func_code.co_varnames[i] for i in
range(fn.func_code.co_argcount)])
print("ERROR: %s" % err)
except Exception:
print("Command failed, please check the log for more info.")
raise
else:
common.print_actions(cmd, actions)
else:
common.print_commands(COMMANDS)
if __name__ == '__main__':
main()

View File

@ -1,66 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import eventlet
eventlet.monkey_patch()
import gettext
import os
import sys
gettext.install('trove', unicode=1)
# If ../trove/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'trove', '__init__.py')):
sys.path.insert(0, possible_topdir)
from trove.common import cfg
from trove.common.rpc import service as rpc_service
from oslo.config import cfg as openstack_cfg
from trove.openstack.common import log as logging
from trove.openstack.common import service as openstack_service
from trove.db import get_db_api
CONF = cfg.CONF
CONF.register_opts([openstack_cfg.StrOpt('taskmanager_manager')])
def main():
cfg.parse_args(sys.argv)
logging.setup(None)
try:
get_db_api().configure_db(CONF)
server = rpc_service.RpcService(manager=CONF.taskmanager_manager,
topic="mgmt-taskmanager")
launcher = openstack_service.launch(server)
launcher.wait()
except RuntimeError as error:
import traceback
print(traceback.format_exc())
sys.exit("ERROR: %s" % error)
if __name__ == '__main__':
main()

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python #!/usr/bin/python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack Foundation # Copyright 2011 OpenStack Foundation
# All Rights Reserved. # All Rights Reserved.
@ -16,46 +15,20 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import gettext """This is necessary currently because the guest needs a init script.
import os When the guest is moved out of the application, this will no longer
be needed in the project."""
import sys import sys
import os
gettext.install('trove', unicode=1)
# If ../trove/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir, os.pardir,
os.pardir)) os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'trove', '__init__.py')): if os.path.exists(os.path.join(possible_topdir, 'trove', '__init__.py')):
sys.path.insert(0, possible_topdir) sys.path.insert(0, possible_topdir)
from trove.common import cfg from trove.cmd.guest import main
from trove.openstack.common import log as logging
from trove.common import wsgi
from trove.db import get_db_api
if __name__ == "__main__":
CONF = cfg.CONF sys.exit(main())
def main():
cfg.parse_args(sys.argv)
logging.setup(None)
try:
get_db_api().configure_db(CONF)
conf_file = CONF.find_file(CONF.api_paste_config)
launcher = wsgi.launch('trove', CONF.bind_port or 8779, conf_file,
workers=CONF.trove_api_workers)
launcher.wait()
except RuntimeError as error:
import traceback
print(traceback.format_exc())
sys.exit("ERROR: %s" % error)
if __name__ == '__main__':
main()

View File

@ -21,14 +21,16 @@ classifier =
[files] [files]
packages = packages =
trove trove
scripts =
bin/trove-api [entry_points]
bin/trove-fake-mode console_scripts =
bin/trove-conductor trove-api = trove.cmd.api:main
bin/trove-manage trove-taskmanager = trove.cmd.taskmanager:main
bin/trove-mgmt-taskmanager trove-mgmt-taskmanager = trove.cmd.taskmanager:mgmt_main
bin/trove-taskmanager trove-conductor = trove.cmd.conductor:main
bin/trove-guestagent trove-manage = trove.cmd.manage:main
trove-guestagent = trove.cmd.guest:main
trove-fake-mode = trove.cmd.fakemode:main
[global] [global]
setup-hooks = setup-hooks =

0
trove/cmd/__init__.py Normal file
View File

42
trove/cmd/api.py Executable file
View File

@ -0,0 +1,42 @@
#!/usr/bin/env python
# Copyright 2011 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import gettext
import sys
gettext.install('trove', unicode=1)
from trove.common import cfg
from trove.openstack.common import log as logging
from trove.common import wsgi
from trove.db import get_db_api
CONF = cfg.CONF
def main():
cfg.parse_args(sys.argv)
logging.setup(None)
get_db_api().configure_db(CONF)
conf_file = CONF.find_file(CONF.api_paste_config)
launcher = wsgi.launch('trove', CONF.bind_port or 8779, conf_file,
workers=CONF.trove_api_workers)
launcher.wait()

View File

@ -20,7 +20,6 @@ import eventlet
eventlet.monkey_patch(all=True, thread=False) eventlet.monkey_patch(all=True, thread=False)
import gettext import gettext
import traceback
import sys import sys
@ -55,12 +54,5 @@ def main():
if not debug_utils.enabled(): if not debug_utils.enabled():
eventlet.monkey_patch(thread=True) eventlet.monkey_patch(thread=True)
try:
launch_services()
except RuntimeError as error:
print(traceback.format_exc())
sys.exit("ERROR: %s" % error)
launch_services()
if __name__ == '__main__':
main()

View File

@ -17,21 +17,12 @@
# under the License. # under the License.
import gettext import gettext
import os
import sys import sys
gettext.install('trove', unicode=1) gettext.install('trove', unicode=1)
# If ../trove/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'trove', '__init__.py')):
sys.path.insert(0, possible_topdir)
from trove.common import cfg from trove.common import cfg
from oslo.config import cfg as openstack_cfg from oslo.config import cfg as openstack_cfg
from trove.openstack.common import log as logging from trove.openstack.common import log as logging
@ -64,17 +55,12 @@ def start_fake_taskmanager():
def run_server(): def run_server():
try: get_db_api().configure_db(CONF)
get_db_api().configure_db(CONF) conf_file = CONF.find_file(CONF.api_paste_config)
conf_file = CONF.find_file(CONF.api_paste_config) launcher = wsgi.launch('trove', CONF.bind_port or 8779, conf_file,
launcher = wsgi.launch('trove', CONF.bind_port or 8779, conf_file, workers=CONF.trove_api_workers)
workers=CONF.trove_api_workers) start_fake_taskmanager()
start_fake_taskmanager() launcher.wait()
launcher.wait()
except Exception:
import traceback
print(traceback.format_exc())
sys.exit("ERROR Starting up")
def main(): def main():
@ -96,7 +82,3 @@ def main():
f.write(str(pid)) f.write(str(pid))
else: else:
run_server() run_server()
if __name__ == '__main__':
main()

View File

@ -20,18 +20,11 @@ import eventlet
eventlet.monkey_patch() eventlet.monkey_patch()
import gettext import gettext
import os
import sys import sys
gettext.install('trove', unicode=1) gettext.install('trove', unicode=1)
# If ../trove/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'trove', '__init__.py')):
sys.path.insert(0, possible_topdir)
from trove.common import cfg from trove.common import cfg
from trove.common.rpc import service as rpc_service from trove.common.rpc import service as rpc_service
@ -39,6 +32,7 @@ from oslo.config import cfg as openstack_cfg
from trove.openstack.common import log as logging from trove.openstack.common import log as logging
from trove.openstack.common import service as openstack_service from trove.openstack.common import service as openstack_service
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts([openstack_cfg.StrOpt('guest_id')]) CONF.register_opts([openstack_cfg.StrOpt('guest_id')])
@ -48,20 +42,11 @@ def main():
from trove.guestagent import dbaas from trove.guestagent import dbaas
logging.setup(None) logging.setup(None)
try: manager = dbaas.datastore_registry().get(CONF.datastore_manager)
manager = dbaas.datastore_registry().get(CONF.datastore_manager) if not manager:
if not manager: msg = ("Manager class not registered for datastore manager %s" %
msg = ("Manager class not registered for datastore manager %s" % CONF.datastore_manager)
CONF.datastore_manager) raise RuntimeError(msg)
raise RuntimeError(msg) server = rpc_service.RpcService(manager=manager, host=CONF.guest_id)
server = rpc_service.RpcService(manager=manager, host=CONF.guest_id) launcher = openstack_service.launch(server)
launcher = openstack_service.launch(server) launcher.wait()
launcher.wait()
except RuntimeError as error:
import traceback
print(traceback.format_exc())
sys.exit("ERROR: %s" % error)
if __name__ == '__main__':
main()

View File

@ -18,21 +18,12 @@
import gettext import gettext
import inspect import inspect
import os
import sys import sys
gettext.install('trove', unicode=1) gettext.install('trove', unicode=1)
# If ../trove/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'trove', '__init__.py')):
sys.path.insert(0, possible_topdir)
from trove.common import cfg from trove.common import cfg
from trove.common import exception from trove.common import exception
from trove.common import utils from trove.common import utils
@ -140,7 +131,3 @@ def main():
except Exception: except Exception:
print(_("Command failed, please check log for more info")) print(_("Command failed, please check log for more info"))
raise raise
if __name__ == '__main__':
main()

View File

@ -16,8 +16,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import gettext
import os
import sys import sys
import eventlet import eventlet
@ -32,21 +30,11 @@ from trove.common import debug_utils
# after debug_utils setting up # after debug_utils setting up
eventlet.monkey_patch(all=True, thread=False) eventlet.monkey_patch(all=True, thread=False)
gettext.install('trove', unicode=1)
# If ../trove/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'trove', '__init__.py')):
sys.path.insert(0, possible_topdir)
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts([openstack_cfg.StrOpt('taskmanager_manager')]) CONF.register_opts([openstack_cfg.StrOpt('taskmanager_manager')])
def main(): def startup(topic):
cfg.parse_args(sys.argv) cfg.parse_args(sys.argv)
logging.setup(None) logging.setup(None)
@ -60,16 +48,16 @@ def main():
from trove.openstack.common import service as openstack_service from trove.openstack.common import service as openstack_service
from trove.db import get_db_api from trove.db import get_db_api
try: get_db_api().configure_db(CONF)
get_db_api().configure_db(CONF) server = rpc_service.RpcService(manager=CONF.taskmanager_manager,
server = rpc_service.RpcService(manager=CONF.taskmanager_manager) topic=topic)
launcher = openstack_service.launch(server) launcher = openstack_service.launch(server)
launcher.wait() launcher.wait()
except RuntimeError as error:
import traceback
print(traceback.format_exc())
sys.exit("ERROR: %s" % error)
if __name__ == '__main__': def main():
main() startup(None)
def mgmt_main():
startup("mgmt-taskmanager")