sahara/sahara/db/templates/cli.py

209 lines
8.1 KiB
Python

# Copyright 2015 Red Hat, Inc.
#
# 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.
from __future__ import print_function
import sys
from oslo_config import cfg
from oslo_log import log
import pkg_resources as pkg
from sahara.db.templates import api
from sahara import version
LOG = log.getLogger(__name__)
CONF = cfg.CONF
def extra_option_checks():
if not CONF.database.connection:
print("No database connection string was specified in configuration",
file=sys.stderr)
sys.exit(1)
if CONF.command.name in ['update', 'delete']:
if CONF.command.plugin_version and not CONF.command.plugin_name:
print("The --plugin-version option is not valid "
"without --plugin-name", file=sys.stderr)
sys.exit(-1)
if CONF.command.name == "update":
# Options handling probably needs some refactoring in the future.
# For now, though, we touch the conductor which ultimately touches
# the plugins.base. Use the "plugins" option there as a default
# list of plugins to process, since those are the plugins that
# will be loaded by Sahara
if not CONF.command.plugin_name:
if "plugins" in CONF and CONF.plugins:
LOG.info("Using plugin list {plugins} from config".format(
plugins=CONF.plugins))
else:
print("No plugins specified with --plugin-name "
"or config", file=sys.stderr)
sys.exit(-1)
def add_command_parsers(subparsers):
# Note, there is no 'list' command here because the client
# or REST can be used for list operations. Default templates
# will display, and templates will show the 'is_default' field.
def add_id(parser):
parser.add_argument('--id', required=True,
help='The id of the default '
'template to delete')
def add_tenant_id(parser):
parser.add_argument('-t', '--tenant_id', required=True,
help='Tenant ID for database operations.')
def add_name_and_tenant_id(parser):
parser.add_argument('--name', dest='template_name', required=True,
help='Name of the default template')
add_tenant_id(parser)
def add_plugin_name_and_version(parser, require_plugin_name=False):
plugin_name_help = ('Only process templates containing '
'a "plugin_name" field matching '
'one of these values.')
if not require_plugin_name:
extra = (' The default list of plugin names '
'is taken from the "plugins" parameter in '
'the [DEFAULT] config section.')
plugin_name_help += extra
parser.add_argument('-p', '--plugin-name', nargs="*",
required=require_plugin_name,
help=plugin_name_help)
parser.add_argument('-pv', '--plugin-version', nargs="*",
help='Only process templates containing a '
'"hadoop_version" field matching one of '
'these values. This option is '
'only valid if --plugin-name is specified '
'as well. A version specified '
'here may optionally be prefixed with a '
'plugin name and a dot, for exmaple '
'"vanilla.1.2.1". Dotted versions only '
'apply to the plugin named in the '
'prefix. Versions without a prefix apply to '
'all plugins.')
fname = pkg.resource_filename(version.version_info.package,
"plugins/default_templates")
# update command
parser = subparsers.add_parser('update',
help='Update the default template set')
parser.add_argument('-d', '--directory',
default=fname,
help='Template directory. Default is %s' % fname)
parser.add_argument('-n', '--norecurse', action='store_true',
help='Do not descend into subdirectories')
add_plugin_name_and_version(parser)
add_tenant_id(parser)
parser.set_defaults(func=api.do_update)
# delete command
parser = subparsers.add_parser('delete',
help='Delete default templates '
'by plugin and version')
add_plugin_name_and_version(parser, require_plugin_name=True)
add_tenant_id(parser)
parser.set_defaults(func=api.do_delete)
# node-group-template-delete command
parser = subparsers.add_parser('node-group-template-delete',
help='Delete a default '
'node group template by name')
add_name_and_tenant_id(parser)
parser.set_defaults(func=api.do_node_group_template_delete)
# cluster-template-delete command
parser = subparsers.add_parser('cluster-template-delete',
help='Delete a default '
'cluster template by name')
add_name_and_tenant_id(parser)
parser.set_defaults(func=api.do_cluster_template_delete)
# node-group-template-delete-id command
parser = subparsers.add_parser('node-group-template-delete-id',
help='Delete a default '
'node group template by id')
add_id(parser)
parser.set_defaults(func=api.do_node_group_template_delete_by_id)
# cluster-template-delete-id command
parser = subparsers.add_parser('cluster-template-delete-id',
help='Delete a default '
'cluster template by id')
add_id(parser)
parser.set_defaults(func=api.do_cluster_template_delete_by_id)
command_opt = cfg.SubCommandOpt('command',
title='Command',
help='Available commands',
handler=add_command_parsers)
CONF.register_cli_opt(command_opt)
def unregister_extra_cli_opt(name):
try:
for cli in CONF._cli_opts:
if cli['opt'].name == name:
CONF.unregister_opt(cli['opt'])
except Exception:
pass
# Remove a few extra CLI opts that we picked up via imports
# Do this early so that they do not appear in the help
for extra_opt in ["log-exchange", "host", "port"]:
unregister_extra_cli_opt(extra_opt)
def main():
# TODO(tmckay): Work on restricting the options
# pulled in by imports which show up in the help.
# If we find a nice way to do this the calls to
# unregister_extra_cli_opt() can be removed
CONF(project='sahara')
# For some reason, this is necessary to clear cached values
# and re-read configs. For instance, if this is not done
# here the 'plugins' value will not reflect the value from
# the config file on the command line
CONF.reload_config_files()
log.setup(CONF, "sahara")
# If we have to enforce extra option checks, like one option
# requires another, do it here
extra_option_checks()
# Since this may be scripted, record the command in the log
# so a user can know exactly what was done
LOG.info("Command: {command}".format(command=' '.join(sys.argv)))
api.set_logger(LOG)
api.set_conf(CONF)
CONF.command.func()
LOG.info("Finished {command}".format(command=CONF.command.name))