2015-01-05 13:09:32 +08:00
|
|
|
# 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 logging
|
|
|
|
|
2015-01-16 15:53:16 +08:00
|
|
|
from oslo_serialization import jsonutils
|
2015-01-05 19:46:22 +08:00
|
|
|
|
|
|
|
from senlinclient.common import exc
|
2015-01-05 13:09:32 +08:00
|
|
|
from senlinclient.common.i18n import _
|
|
|
|
from senlinclient.common import utils
|
2015-01-16 15:53:16 +08:00
|
|
|
from senlinclient.v1 import models
|
2015-01-05 13:09:32 +08:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2015-01-05 19:46:22 +08:00
|
|
|
def do_build_info(sc, args):
|
|
|
|
'''Retrieve build information.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
result = sc.get(models.BuildInfo)
|
2015-01-05 19:46:22 +08:00
|
|
|
formatters = {
|
|
|
|
'api': utils.json_formatter,
|
|
|
|
'engine': utils.json_formatter,
|
|
|
|
}
|
|
|
|
utils.print_dict(result, formatters=formatters)
|
|
|
|
|
|
|
|
|
|
|
|
#### PROFILE TYPES
|
|
|
|
|
|
|
|
|
|
|
|
def do_profile_type_list(sc, args):
|
|
|
|
'''List the available profile types.'''
|
2015-01-20 23:34:45 +08:00
|
|
|
types = sc.list_short(models.ProfileType, {})
|
2015-01-16 15:53:16 +08:00
|
|
|
utils.print_list(types, ['name'], sortby_index=0)
|
2015-01-05 19:46:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('profile_type', metavar='<PROFILE_TYPE>',
|
|
|
|
help=_('Profile type to get the details for.'))
|
|
|
|
def do_profile_type_show(sc, args):
|
|
|
|
'''Show the profile type.'''
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {'profile_type': args.profile_type}
|
|
|
|
profile_type = sc.get(models.ProfileTypeSchema, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
except exc.HTTPNotFound:
|
|
|
|
raise exc.CommandError(
|
|
|
|
_('Profile Type not found: %s') % args.profile_type)
|
|
|
|
else:
|
|
|
|
print(jsonutils.dumps(profile_type, indent=2))
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('profile_type', metavar='<PROFILE_TYPE>',
|
|
|
|
help=_('Profile type to generate a template for.'))
|
|
|
|
@utils.arg('-F', '--format', metavar='<FORMAT>',
|
|
|
|
help=_("The template output format, one of: %s.")
|
|
|
|
% ', '.join(utils.supported_formats.keys()))
|
|
|
|
def do_profile_type_template(sc, args):
|
|
|
|
'''Generate a template based on a profile type.'''
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {'profile_type': args.profile_type}
|
|
|
|
template = sc.get(models.ProfileTypeTemplate, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
except exc.HTTPNotFound:
|
|
|
|
raise exc.CommandError(
|
|
|
|
_('Profile Type %s not found.') % args.profile_type)
|
|
|
|
|
|
|
|
if args.format:
|
|
|
|
print(utils.format_output(template, format=args.format))
|
|
|
|
else:
|
|
|
|
print(utils.format_output(template))
|
|
|
|
|
|
|
|
|
|
|
|
#### PROFILES
|
|
|
|
|
|
|
|
|
2015-01-26 22:45:16 +08:00
|
|
|
@utils.arg('-d', '--show-deleted', default=False, action="store_true",
|
2015-01-19 21:37:50 +08:00
|
|
|
help=_('Include soft-deleted profiles if any.'))
|
|
|
|
@utils.arg('-l', '--limit', metavar='<LIMIT>',
|
2015-01-25 19:28:29 +08:00
|
|
|
help=_('Limit the number of profiles returned.'))
|
2015-01-19 21:37:50 +08:00
|
|
|
@utils.arg('-m', '--marker', metavar='<ID>',
|
|
|
|
help=_('Only return profiles that appear after the given ID.'))
|
|
|
|
def do_profile_list(sc, args=None):
|
|
|
|
'''List profiles that meet the criteria.'''
|
|
|
|
fields = ['id', 'name', 'type', 'permission', 'created_time']
|
2015-01-26 22:45:16 +08:00
|
|
|
queries = {
|
|
|
|
'show_deleted': args.show_deleted,
|
|
|
|
'limit': args.limit,
|
|
|
|
'marker': args.marker,
|
|
|
|
}
|
|
|
|
|
|
|
|
profiles = sc.list(models.Profile, **queries)
|
2015-01-25 19:28:29 +08:00
|
|
|
utils.print_list(profiles, fields, sortby_index=1)
|
2015-01-19 21:37:50 +08:00
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('-t', '--profile-type', metavar='<TYPE NAME>',
|
|
|
|
help=_('Profile type used for this profile.'))
|
|
|
|
@utils.arg('-s', '--spec-file', metavar='<SPEC FILE>',
|
|
|
|
help=_('The spec file used to create the profile.'))
|
|
|
|
@utils.arg('-p', '--permission', metavar='<PERMISSION>', default='',
|
|
|
|
help=_('A string format permission for this profile.'))
|
|
|
|
@utils.arg('-g', '--tags', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Tag values to be attached to the profile. '
|
|
|
|
'This can be specified multiple times, or once with tags'
|
|
|
|
'separated by a semicolon.'),
|
|
|
|
action='append')
|
|
|
|
@utils.arg('name', metavar='<PROFILE_NAME>',
|
|
|
|
help=_('Name of the profile to create.'))
|
|
|
|
def do_profile_create(sc, args):
|
|
|
|
'''Create a profile.'''
|
|
|
|
spec = utils.get_spec_content(args.spec_file)
|
|
|
|
if args.profile_type == 'os.heat.stack':
|
|
|
|
spec = utils.process_stack_spec(spec)
|
|
|
|
params = {
|
|
|
|
'name': args.name,
|
|
|
|
'type': args.profile_type,
|
|
|
|
'spec': spec,
|
|
|
|
'permission': args.permission,
|
|
|
|
'tags': utils.format_parameters(args.tags),
|
|
|
|
}
|
|
|
|
|
2015-02-03 22:52:13 +08:00
|
|
|
profile = sc.create(models.Profile, params)
|
2015-01-20 21:45:14 +08:00
|
|
|
if profile:
|
2015-01-20 23:34:45 +08:00
|
|
|
print("Profile created: %s" % profile.id)
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of profile to show.'))
|
|
|
|
def do_profile_show(sc, args):
|
|
|
|
'''Show the profile details.'''
|
|
|
|
try:
|
|
|
|
params = {'id': args.id}
|
|
|
|
profile = sc.get(models.Profile, params)
|
|
|
|
except exc.HTTPNotFound:
|
|
|
|
raise exc.CommandError(_('Profile not found: %s') % args.id)
|
|
|
|
|
|
|
|
formatters = {
|
|
|
|
'tags': utils.json_formatter,
|
|
|
|
'spec': utils.nested_dict_formatter(
|
|
|
|
['name', 'rollback', 'parameters', 'environment', 'template'],
|
|
|
|
['property', 'value']),
|
|
|
|
}
|
2015-02-03 22:17:52 +08:00
|
|
|
print(profile.to_dict())
|
2015-01-20 23:34:45 +08:00
|
|
|
utils.print_dict(profile.to_dict(), formatters=formatters)
|
2015-01-20 21:45:14 +08:00
|
|
|
|
|
|
|
|
2015-02-03 22:17:52 +08:00
|
|
|
@utils.arg('-f', '--force', default=False, action="store_true",
|
|
|
|
help=_('Delete the profile completely from database.'))
|
2015-01-20 21:45:14 +08:00
|
|
|
@utils.arg('id', metavar='<NAME or ID>', nargs='+',
|
|
|
|
help=_('Name or ID of profile(s) to delete.'))
|
|
|
|
def do_profile_delete(sc, args):
|
|
|
|
'''Delete profile(s).'''
|
|
|
|
failure_count = 0
|
|
|
|
|
|
|
|
for cid in args.id:
|
|
|
|
try:
|
2015-02-03 22:17:52 +08:00
|
|
|
query = {
|
|
|
|
'id': cid,
|
|
|
|
'force': args.force
|
|
|
|
}
|
2015-01-20 21:45:14 +08:00
|
|
|
sc.delete(models.Profile, query)
|
|
|
|
except exc.HTTPNotFound as ex:
|
|
|
|
failure_count += 1
|
|
|
|
print(ex)
|
|
|
|
if failure_count == len(args.id):
|
|
|
|
msg = _('Failed to delete any of the specified profile(s).')
|
|
|
|
raise exc.CommandError(msg)
|
|
|
|
print('Profile deleted: %s' % args.id)
|
2015-01-19 21:37:50 +08:00
|
|
|
|
|
|
|
|
2015-01-05 19:46:22 +08:00
|
|
|
#### POLICY TYPES
|
|
|
|
|
|
|
|
|
|
|
|
def do_policy_type_list(sc, args):
|
|
|
|
'''List the available policy types.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
types = sc.list_short(models.PolicyType)
|
|
|
|
utils.print_list(types, ['name'], sortby_index=0)
|
2015-01-05 19:46:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('policy_type', metavar='<POLICY_TYPE>',
|
|
|
|
help=_('Policy type to get the details for.'))
|
|
|
|
def do_policy_type_show(sc, args):
|
|
|
|
'''Show the policy type.'''
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {'policy_type': args.policy_type}
|
|
|
|
policy_type = sc.get(models.PolicyTypeSchema, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
except exc.HTTPNotFound:
|
|
|
|
raise exc.CommandError(
|
|
|
|
_('Policy Type not found: %s') % args.policy_type)
|
|
|
|
else:
|
|
|
|
print(jsonutils.dumps(policy_type, indent=2))
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('policy_type', metavar='<POLICY_TYPE>',
|
|
|
|
help=_('Policy type to generate a template for.'))
|
|
|
|
@utils.arg('-F', '--format', metavar='<FORMAT>',
|
|
|
|
help=_("The template output format, one of: %s.")
|
|
|
|
% ', '.join(utils.supported_formats.keys()))
|
|
|
|
def do_policy_type_template(sc, args):
|
|
|
|
'''Generate a template based on a policy type.'''
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {'policy_type': args.policy_type}
|
|
|
|
template = sc.get(models.PolicyTypeTemplate, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
except exc.HTTPNotFound:
|
|
|
|
raise exc.CommandError(
|
|
|
|
_('Policy Type %s not found.') % args.policy_type)
|
|
|
|
|
|
|
|
if args.format:
|
|
|
|
print(utils.format_output(template, format=args.format))
|
|
|
|
else:
|
|
|
|
print(utils.format_output(template))
|
|
|
|
|
|
|
|
|
|
|
|
#### POLICIES
|
|
|
|
|
|
|
|
|
|
|
|
#### CLUSTERS
|
|
|
|
|
|
|
|
|
2015-01-07 13:04:22 +08:00
|
|
|
@utils.arg('-s', '--show-deleted', default=False, action="store_true",
|
|
|
|
help=_('Include soft-deleted clusters if any.'))
|
|
|
|
@utils.arg('-n', '--show-nested', default=False, action="store_true",
|
|
|
|
help=_('Include nested clusters if any.'))
|
|
|
|
@utils.arg('-f', '--filters', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Filter parameters to apply on returned clusters. '
|
|
|
|
'This can be specified multiple times, or once with '
|
|
|
|
'parameters separated by a semicolon.'),
|
|
|
|
action='append')
|
2015-01-23 16:38:10 +08:00
|
|
|
@utils.arg('-k', '--sort-keys', metavar='<KEYS>',
|
|
|
|
help=_('Name of keys used for sorting the returned events.'))
|
|
|
|
@utils.arg('-d', '--sort-dir', metavar='<DIR>',
|
|
|
|
help=_('Direction for sorting, where DIR can be "asc" or "desc".'))
|
2015-01-07 13:04:22 +08:00
|
|
|
@utils.arg('-l', '--limit', metavar='<LIMIT>',
|
|
|
|
help=_('Limit the number of clusters returned.'))
|
|
|
|
@utils.arg('-m', '--marker', metavar='<ID>',
|
|
|
|
help=_('Only return clusters that appear after the given cluster '
|
|
|
|
'ID.'))
|
|
|
|
def do_cluster_list(sc, args=None):
|
|
|
|
'''List the user's clusters.'''
|
2015-01-26 22:49:25 +08:00
|
|
|
fields = ['id', 'name', 'status', 'created_time']
|
2015-01-26 22:45:16 +08:00
|
|
|
queries = {
|
|
|
|
'limit': args.limit,
|
|
|
|
'marker': args.marker,
|
|
|
|
'filters': utils.format_parameters(args.filters),
|
|
|
|
'show_deleted': args.show_deleted,
|
|
|
|
'show_nested': args.show_nested
|
|
|
|
}
|
|
|
|
if args.show_nested:
|
|
|
|
fields.append('parent')
|
2015-01-07 13:04:22 +08:00
|
|
|
|
2015-01-26 22:45:16 +08:00
|
|
|
clusters = sc.list(models.Cluster, **queries)
|
2015-01-07 13:04:22 +08:00
|
|
|
utils.print_list(clusters, fields, sortby_index=3)
|
|
|
|
|
|
|
|
|
2015-02-04 10:35:08 +08:00
|
|
|
def _show_cluster(sc, cluster_id):
|
|
|
|
try:
|
|
|
|
query = {'id': cluster_id}
|
|
|
|
cluster = sc.get(models.Cluster, query)
|
|
|
|
except exc.HTTPNotFound:
|
|
|
|
raise exc.CommandError(_('Cluster %s is not found') % args.id)
|
|
|
|
|
|
|
|
formatters = {
|
|
|
|
'tags': utils.json_formatter,
|
|
|
|
'nodes': utils.list_formatter,
|
|
|
|
}
|
|
|
|
utils.print_dict(cluster.to_dict(), formatters=formatters)
|
|
|
|
|
|
|
|
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-p', '--profile', metavar='<PROFILE ID>',
|
|
|
|
help=_('Profile Id used for this cluster.'))
|
|
|
|
@utils.arg('-n', '--size', metavar='<NUMBER>',
|
|
|
|
help=_('Initial size of the cluster.'))
|
2015-01-26 13:33:55 +08:00
|
|
|
@utils.arg('-o', '--parent', metavar='<PARENT_ID>',
|
|
|
|
help=_('ID of the parent cluster, if exists.'))
|
|
|
|
@utils.arg('-t', '--timeout', metavar='<TIMEOUT>', type=int,
|
2015-01-05 19:46:22 +08:00
|
|
|
help=_('Cluster creation timeout in minutes.'))
|
|
|
|
@utils.arg('-g', '--tags', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Tag values to be attached to the cluster. '
|
|
|
|
'This can be specified multiple times, or once with tags'
|
|
|
|
'separated by a semicolon.'),
|
|
|
|
action='append')
|
|
|
|
@utils.arg('name', metavar='<CLUSTER_NAME>',
|
|
|
|
help=_('Name of the cluster to create.'))
|
|
|
|
def do_cluster_create(sc, args):
|
|
|
|
'''Create the cluster.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {
|
2015-01-05 19:46:22 +08:00
|
|
|
'name': args.name,
|
|
|
|
'profile_id': args.profile,
|
|
|
|
'size': args.size,
|
2015-01-26 13:33:55 +08:00
|
|
|
'parent': args.parent,
|
|
|
|
'tags': utils.format_parameters(args.tags),
|
2015-01-05 19:46:22 +08:00
|
|
|
'timeout': args.timeout
|
|
|
|
}
|
|
|
|
|
2015-02-04 10:35:08 +08:00
|
|
|
cluster = sc.create(models.Cluster, params)
|
|
|
|
_show_cluster(sc, cluster.id)
|
2015-01-05 19:46:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>', nargs='+',
|
|
|
|
help=_('Name or ID of cluster(s) to delete.'))
|
|
|
|
def do_cluster_delete(sc, args):
|
|
|
|
'''Delete the cluster(s).'''
|
|
|
|
failure_count = 0
|
|
|
|
|
|
|
|
for cid in args.id:
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
query = {'id': cid}
|
|
|
|
sc.delete(models.Cluster, query)
|
2015-01-05 19:46:22 +08:00
|
|
|
except exc.HTTPNotFound as ex:
|
|
|
|
failure_count += 1
|
|
|
|
print(ex)
|
|
|
|
if failure_count == len(args.id):
|
|
|
|
msg = _('Failed to delete any of the specified clusters.')
|
|
|
|
raise exc.CommandError(msg)
|
2015-01-28 23:06:51 +08:00
|
|
|
|
|
|
|
print('Request accepted')
|
2015-01-05 19:46:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('-p', '--profile', metavar='<PROFILE ID>',
|
|
|
|
help=_('ID of new profile to use.'))
|
2015-01-07 13:04:22 +08:00
|
|
|
@utils.arg('-n', '--size', metavar='<NUMBER>',
|
|
|
|
help=_('Initial size of the cluster.'))
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-t', '--timeout', metavar='<TIMEOUT>',
|
|
|
|
type=int,
|
|
|
|
help=_('Cluster update timeout in minutes.'))
|
|
|
|
@utils.arg('-g', '--tags', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Tag values to be attached to the cluster. '
|
|
|
|
'This can be specified multiple times, or once with tags'
|
|
|
|
'separated by a semicolon.'),
|
|
|
|
action='append')
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of cluster to update.'))
|
|
|
|
def do_cluster_update(sc, args):
|
|
|
|
'''Update the cluster.'''
|
|
|
|
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {
|
2015-01-05 19:46:22 +08:00
|
|
|
'profile_id': args.profile,
|
2015-01-07 13:04:22 +08:00
|
|
|
'size': args.size,
|
2015-01-05 19:46:22 +08:00
|
|
|
'tags': utils.format_parameters(args.tags),
|
|
|
|
}
|
|
|
|
|
|
|
|
if args.timeout:
|
2015-01-16 15:53:16 +08:00
|
|
|
params['timeout'] = args.timeout
|
2015-01-05 19:46:22 +08:00
|
|
|
|
2015-01-16 15:53:16 +08:00
|
|
|
sc.update(models.Cluster, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
do_cluster_list(sc)
|
|
|
|
|
|
|
|
|
2015-01-07 13:04:22 +08:00
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of cluster to show.'))
|
|
|
|
def do_cluster_show(sc, args):
|
|
|
|
'''Show details of the cluster.'''
|
2015-02-04 10:35:08 +08:00
|
|
|
_show_cluster(sc, args.id)
|
2015-01-07 13:04:22 +08:00
|
|
|
|
2015-01-07 14:43:23 +08:00
|
|
|
|
2015-01-07 14:38:32 +08:00
|
|
|
@utils.arg('-s', '--show-deleted', default=False, action="store_true",
|
|
|
|
help=_('Include soft-deleted nodes if any.'))
|
|
|
|
@utils.arg('-f', '--filters', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Filter parameters to apply on returned nodes. '
|
|
|
|
'This can be specified multiple times, or once with '
|
|
|
|
'parameters separated by a semicolon.'),
|
|
|
|
action='append')
|
|
|
|
@utils.arg('-l', '--limit', metavar='<LIMIT>',
|
|
|
|
help=_('Limit the number of nodes returned.'))
|
|
|
|
@utils.arg('-m', '--marker', metavar='<ID>',
|
|
|
|
help=_('Only return nodes that appear after the given node ID.'))
|
2015-02-01 22:33:20 +08:00
|
|
|
@utils.arg('-F', '--full-id', default=False, action="store_true",
|
|
|
|
help=_('Print full IDs in list.'))
|
2015-01-07 13:04:22 +08:00
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of cluster to nodes from.'))
|
|
|
|
def do_cluster_node_list(sc, args):
|
|
|
|
'''List nodes from cluster.'''
|
2015-02-01 22:33:20 +08:00
|
|
|
def _short_id(obj):
|
|
|
|
return obj.id[:8] + ' ...'
|
|
|
|
|
|
|
|
def _short_physical_id(obj):
|
|
|
|
return obj.physical_id[:8] + ' ...'
|
|
|
|
|
2015-01-07 14:38:32 +08:00
|
|
|
fields = ['id', 'name', 'index', 'status', 'physical_id', 'created_time']
|
|
|
|
|
2015-01-16 15:53:16 +08:00
|
|
|
query = {
|
2015-01-07 14:38:32 +08:00
|
|
|
'cluster_id': args.id,
|
|
|
|
'show_deleted': args.show_deleted,
|
|
|
|
'filters': utils.format_parameters(args.filters),
|
|
|
|
'limit': args.limit,
|
|
|
|
'marker': args.marker,
|
|
|
|
}
|
|
|
|
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
nodes = sc.list(models.ClusterNode, query)
|
2015-01-07 14:38:32 +08:00
|
|
|
except exc.HTTPNotFound:
|
|
|
|
msg = _('No node matching criteria is found')
|
|
|
|
raise exc.CommandError(msg)
|
|
|
|
|
2015-02-01 22:33:20 +08:00
|
|
|
if not args.full_id:
|
|
|
|
formatters = {
|
|
|
|
'id': _short_id,
|
|
|
|
'physical_id': _short_physical_id,
|
|
|
|
}
|
|
|
|
else:
|
|
|
|
formatters = {}
|
|
|
|
|
|
|
|
utils.print_list(nodes, fields, formatters=formatters, sortby_index=5)
|
2015-01-07 13:04:22 +08:00
|
|
|
|
|
|
|
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-n', '--nodes', metavar='<NODE_IDs>',
|
|
|
|
help=_('ID of nodes to be added.'))
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of cluster to operate on.'))
|
|
|
|
def do_cluster_node_add(sc, args):
|
|
|
|
'''Add specified nodes to cluster.'''
|
|
|
|
failure_count = 0
|
|
|
|
for nid in args.nodes:
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {'cluster_id': args.id, 'id': nid}
|
|
|
|
sc.create(models.ClusterNode, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
except Exception as ex:
|
|
|
|
failure_count += 1
|
|
|
|
print(ex)
|
|
|
|
if failure_count == len(args.nodes):
|
|
|
|
msg = _('Failed to add any of the specified nodes.')
|
|
|
|
raise exc.CommandError(msg)
|
|
|
|
|
|
|
|
do_cluster_node_list(sc, id=args.id)
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('-n', '--nodes', metavar='<NODE_IDs>',
|
|
|
|
help=_('ID of nodes to be deleted.'))
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of cluster to operate on.'))
|
|
|
|
def do_cluster_node_del(sc, args):
|
|
|
|
'''Delete specified nodes from cluster.'''
|
|
|
|
failure_count = 0
|
|
|
|
for nid in args.nodes:
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
query = {'cluster_id': args.id, 'id': nid}
|
|
|
|
sc.delete(models.ClusterNode, query)
|
2015-01-05 19:46:22 +08:00
|
|
|
except Exception as ex:
|
|
|
|
failure_count += 1
|
|
|
|
print(ex)
|
|
|
|
if failure_count == len(args.nodes):
|
|
|
|
msg = _('Failed to delete any of the specified nodes.')
|
|
|
|
raise exc.CommandError(msg)
|
|
|
|
|
|
|
|
do_cluster_node_list(sc, id=args.id)
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
2015-01-07 13:04:22 +08:00
|
|
|
help=_('Name or ID of cluster to operate on.'))
|
|
|
|
def do_cluster_policy_list(sc, args):
|
|
|
|
'''List policies from cluster.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
query = {'id': args.id}
|
|
|
|
policies = sc.list(models.ClusterPolicy, query)
|
2015-01-07 13:04:22 +08:00
|
|
|
fields = ['id', 'name', 'enabled', 'level']
|
|
|
|
utils.print_list(policies, fields, sortby_index=1)
|
2015-01-05 19:46:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('-p', '--policy', metavar='<POLICY_ID>',
|
|
|
|
help=_('ID of policy to be attached.'))
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of cluster to operate on.'))
|
|
|
|
def do_cluster_policy_attach(sc, args):
|
|
|
|
'''Attach policy to cluster.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {'cluster_id': args.id, 'policy_id': args.policy}
|
|
|
|
sc.create(models.ClusterPolicy, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
do_cluster_policy_list(sc, args.id)
|
|
|
|
|
|
|
|
|
2015-01-07 14:43:23 +08:00
|
|
|
@utils.arg('-p', '--policy', metavar='<POLICY_ID>',
|
|
|
|
help=_('ID of policy to be detached.'))
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of cluster to operate on.'))
|
|
|
|
def do_cluster_policy_detach(sc, args):
|
|
|
|
'''Detach policy from cluster.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {'cluster_id': args.id, 'policy_id': args.policy}
|
|
|
|
sc.delete(models.ClusterPolicy, params)
|
2015-01-07 14:43:23 +08:00
|
|
|
do_cluster_policy_list(sc, args.id)
|
|
|
|
|
|
|
|
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-p', '--policy', metavar='<POLICY_ID>',
|
|
|
|
help=_('ID of policy to be enabled.'))
|
2015-01-07 13:04:22 +08:00
|
|
|
@utils.arg('-c', '--cooldown', metavar='<COOLDOWN>',
|
|
|
|
help=_('Cooldown interval in seconds.'))
|
|
|
|
@utils.arg('-l', '--level', metavar='<LEVEL>',
|
|
|
|
help=_('Enforcement level.'))
|
2015-01-07 14:43:23 +08:00
|
|
|
@utils.arg('-e', '--enabled', metavar='<BOOLEAN>',
|
|
|
|
help=_('Specify whether to enable policy.'))
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of cluster to operate on.'))
|
2015-01-07 13:04:22 +08:00
|
|
|
def do_cluster_policy_update(sc, args):
|
2015-01-05 19:46:22 +08:00
|
|
|
'''Enable policy on cluster.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {
|
|
|
|
'cluster_id': args.id,
|
2015-01-07 13:04:22 +08:00
|
|
|
'policy_id': args.policy,
|
|
|
|
'cooldown': args.cooldown,
|
2015-01-07 14:43:23 +08:00
|
|
|
'enabled': args.enabled,
|
2015-01-07 13:04:22 +08:00
|
|
|
'level': args.level,
|
|
|
|
}
|
2015-01-16 15:53:16 +08:00
|
|
|
sc.update(models.ClusterPolicy, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
do_cluster_policy_list(sc, args.id)
|
|
|
|
|
|
|
|
|
|
|
|
#### NODES
|
|
|
|
|
|
|
|
|
2015-01-23 16:38:10 +08:00
|
|
|
@utils.arg('-c', '--cluster', default=None,
|
|
|
|
help=_('ID or name of cluster for nodes to list.'))
|
|
|
|
@utils.arg('-s', '--show-deleted', default=False, action="store_true",
|
|
|
|
help=_('Include soft-deleted nodes if any.'))
|
|
|
|
@utils.arg('-f', '--filters', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Filter parameters to apply on returned nodes. '
|
|
|
|
'This can be specified multiple times, or once with '
|
|
|
|
'parameters separated by a semicolon.'),
|
|
|
|
action='append')
|
|
|
|
@utils.arg('-k', '--sort-keys', metavar='<KEYS>',
|
|
|
|
help=_('Name of keys used for sorting the returned events.'))
|
|
|
|
@utils.arg('-d', '--sort-dir', metavar='<DIR>',
|
|
|
|
help=_('Direction for sorting, where DIR can be "asc" or "desc".'))
|
|
|
|
@utils.arg('-l', '--limit', metavar='<LIMIT>',
|
|
|
|
help=_('Limit the number of nodes returned.'))
|
|
|
|
@utils.arg('-m', '--marker', metavar='<ID>',
|
|
|
|
help=_('Only return nodes that appear after the given node ID.'))
|
2015-02-01 22:33:20 +08:00
|
|
|
@utils.arg('-F', '--full-id', default=False, action="store_true",
|
|
|
|
help=_('Print full IDs in list.'))
|
2015-01-23 16:38:10 +08:00
|
|
|
def do_node_list(sc, args):
|
|
|
|
'''Show list of nodes.'''
|
2015-02-01 22:33:20 +08:00
|
|
|
def _short_id(obj):
|
|
|
|
return obj.id[:8] + ' ...'
|
|
|
|
|
|
|
|
def _short_cluster_id(obj):
|
|
|
|
return obj.cluster_id[:8] + ' ...' if obj.cluster_id else ''
|
|
|
|
|
|
|
|
def _short_physical_id(obj):
|
|
|
|
return obj.physical_id[:8] + ' ...' if obj.physical_id else ''
|
2015-01-23 16:38:10 +08:00
|
|
|
|
|
|
|
fields = ['id', 'name', 'status', 'cluster_id', 'physical_id',
|
2015-01-30 15:07:50 +08:00
|
|
|
'profile_name', 'created_time', 'updated_time']
|
2015-01-26 22:45:16 +08:00
|
|
|
|
|
|
|
queries = {
|
|
|
|
'show_deleted': args.show_deleted,
|
|
|
|
'cluster_id': args.cluster,
|
|
|
|
'filters': utils.format_parameters(args.filters),
|
|
|
|
'sort_keys': args.sort_keys,
|
|
|
|
'sort_dir': args.sort_dir,
|
|
|
|
'limit': args.limit,
|
|
|
|
'marker': args.marker,
|
|
|
|
}
|
|
|
|
|
2015-01-30 15:07:50 +08:00
|
|
|
if args.show_deleted:
|
|
|
|
fields.append('deleted_time')
|
|
|
|
|
2015-01-26 22:45:16 +08:00
|
|
|
nodes = sc.list(models.Node, **queries)
|
2015-02-01 22:33:20 +08:00
|
|
|
|
|
|
|
if not args.full_id:
|
|
|
|
formatters = {
|
|
|
|
'id': _short_id,
|
|
|
|
'cluster_id': _short_cluster_id,
|
|
|
|
'physical_id': _short_physical_id,
|
|
|
|
}
|
|
|
|
else:
|
|
|
|
formatters = {}
|
|
|
|
|
|
|
|
utils.print_list(nodes, fields, formatters=formatters, sortby_index=5)
|
2015-01-23 16:38:10 +08:00
|
|
|
|
|
|
|
|
2015-02-04 13:46:41 +08:00
|
|
|
def _show_node(sc, id):
|
|
|
|
'''Show detailed info about the specified node.'''
|
|
|
|
try:
|
|
|
|
query = {'id': id}
|
|
|
|
node = sc.get(models.Node, query)
|
|
|
|
except exc.HTTPNotFound:
|
|
|
|
msg = _('Node %(id)s is not found') % args.id
|
|
|
|
raise exc.CommandError(msg)
|
|
|
|
|
|
|
|
formatters = {
|
|
|
|
'tags': utils.json_formatter,
|
|
|
|
'data': utils.json_formatter,
|
|
|
|
}
|
|
|
|
|
|
|
|
utils.print_dict(node.to_dict(), formatters=formatters)
|
|
|
|
|
|
|
|
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-c', '--cluster', metavar='<CLUSTER_ID>',
|
|
|
|
help=_('Cluster Id for this node.'))
|
|
|
|
@utils.arg('-p', '--profile', metavar='<PROFILE_ID>',
|
|
|
|
help=_('Profile Id used for this node.'))
|
|
|
|
@utils.arg('-r', '--role', metavar='<ROLE>',
|
|
|
|
help=_('Role for this node in the specific cluster.'))
|
|
|
|
@utils.arg('-g', '--tags', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Tag values to be attached to the cluster. '
|
|
|
|
'This can be specified multiple times, or once with tags'
|
|
|
|
'separated by a semicolon.'),
|
|
|
|
action='append')
|
|
|
|
@utils.arg('name', metavar='<NODE_NAME>',
|
|
|
|
help=_('Name of the node to create.'))
|
|
|
|
def do_node_create(sc, args):
|
|
|
|
'''Create the node.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {
|
2015-01-05 19:46:22 +08:00
|
|
|
'name': args.name,
|
|
|
|
'cluster_id': args.cluster,
|
|
|
|
'profile_id': args.profile,
|
|
|
|
'role': args.role,
|
|
|
|
'tags': utils.format_parameters(args.tags),
|
|
|
|
}
|
|
|
|
|
2015-02-04 13:46:41 +08:00
|
|
|
node = sc.create(models.Node, params)
|
|
|
|
_show_node(sc, node.id)
|
2015-01-05 19:46:22 +08:00
|
|
|
|
|
|
|
|
2015-01-23 16:58:41 +08:00
|
|
|
@utils.arg('id', metavar='<NODE ID>',
|
|
|
|
help=_('Name or ID of the node to show the details for.'))
|
|
|
|
def do_node_show(sc, args):
|
|
|
|
'''Show detailed info about the specified node.'''
|
2015-02-04 13:46:41 +08:00
|
|
|
_show_node(sc, args.id)
|
2015-01-23 16:58:41 +08:00
|
|
|
|
|
|
|
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('id', metavar='<NAME or ID>', nargs='+',
|
|
|
|
help=_('Name or ID of node(s) to delete.'))
|
|
|
|
def do_node_delete(sc, args):
|
|
|
|
'''Delete the node(s).'''
|
|
|
|
failure_count = 0
|
|
|
|
|
|
|
|
for nid in args.id:
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
query = {'id': nid}
|
|
|
|
sc.delete(models.Node, query)
|
2015-01-25 19:50:02 +08:00
|
|
|
except exc.HTTPNotFound:
|
2015-01-05 19:46:22 +08:00
|
|
|
failure_count += 1
|
2015-01-25 19:28:29 +08:00
|
|
|
print('Node id "%s" not found' % nid)
|
2015-01-05 19:46:22 +08:00
|
|
|
if failure_count == len(args.id):
|
|
|
|
msg = _('Failed to delete any of the specified nodes.')
|
|
|
|
raise exc.CommandError(msg)
|
2015-01-23 16:38:10 +08:00
|
|
|
print('Request accepted')
|
2015-01-05 19:46:22 +08:00
|
|
|
|
|
|
|
|
2015-01-07 15:13:51 +08:00
|
|
|
@utils.arg('-n', '--name', metavar='<NAME>',
|
|
|
|
help=_('New name for the node.'))
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-p', '--profile', metavar='<PROFILE ID>',
|
|
|
|
help=_('ID of new profile to use.'))
|
2015-01-07 15:13:51 +08:00
|
|
|
@utils.arg('-r', '--role', metavar='<ROLE>',
|
|
|
|
help=_('Role for this node in the specific cluster.'))
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-g', '--tags', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Tag values to be attached to the node. '
|
|
|
|
'This can be specified multiple times, or once with tags'
|
|
|
|
'separated by a semicolon.'),
|
|
|
|
action='append')
|
2015-01-07 15:13:51 +08:00
|
|
|
@utils.arg('id', metavar='<ID>',
|
|
|
|
help=_('ID of node to update.'))
|
2015-01-05 19:46:22 +08:00
|
|
|
def do_node_update(sc, args):
|
|
|
|
'''Update the node.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {
|
|
|
|
'id': args.id,
|
2015-01-07 15:13:51 +08:00
|
|
|
'name': args.name,
|
|
|
|
'role': args.role,
|
2015-01-05 19:46:22 +08:00
|
|
|
'profile': args.profile,
|
|
|
|
'tags': utils.format_parameters(args.tags),
|
|
|
|
}
|
|
|
|
|
2015-01-16 15:53:16 +08:00
|
|
|
sc.update(models.Node, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
do_node_list(sc)
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of node to operate on.'))
|
|
|
|
def do_node_leave(sc, args):
|
|
|
|
'''Make node leave its current cluster.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {
|
|
|
|
'id': args.id,
|
2015-01-07 15:13:51 +08:00
|
|
|
'cluster_id': '',
|
|
|
|
}
|
2015-01-16 15:53:16 +08:00
|
|
|
|
|
|
|
sc.update(models.Node, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
do_node_list(sc)
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('-c', '--cluster',
|
|
|
|
help=_('ID or name of cluster for node to join.'))
|
|
|
|
@utils.arg('id', metavar='<NAME or ID>',
|
|
|
|
help=_('Name or ID of node to operate on.'))
|
|
|
|
def do_node_join(sc, args):
|
|
|
|
'''Make node join the specified cluster.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
params = {
|
|
|
|
'id': args.id,
|
2015-01-07 15:13:51 +08:00
|
|
|
'cluster_id': args.cluster,
|
|
|
|
}
|
2015-01-16 15:53:16 +08:00
|
|
|
|
|
|
|
sc.update(models.Node, params)
|
2015-01-05 19:46:22 +08:00
|
|
|
do_node_list(sc)
|
|
|
|
|
|
|
|
|
|
|
|
##### EVENTS
|
|
|
|
|
|
|
|
|
2015-01-13 15:21:25 +08:00
|
|
|
@utils.arg('-i', '--id', metavar='<ID>',
|
|
|
|
help=_('ID of objects to show the events for.'))
|
|
|
|
@utils.arg('-n', '--name', metavar='<NAME>',
|
|
|
|
help=_('Name of objects to show the events for.'))
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-t', '--type', metavar='<OBJECT TYPE>',
|
|
|
|
help=_('Types of the objects to filter events by.'
|
|
|
|
'The types can be CLUSTER, NODE, PROFILE, POLICY.'))
|
|
|
|
@utils.arg('-f', '--filters', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Filter parameters to apply on returned events. '
|
|
|
|
'This can be specified multiple times, or once with '
|
|
|
|
'parameters separated by a semicolon.'),
|
|
|
|
action='append')
|
|
|
|
@utils.arg('-l', '--limit', metavar='<LIMIT>',
|
|
|
|
help=_('Limit the number of events returned.'))
|
|
|
|
@utils.arg('-m', '--marker', metavar='<ID>',
|
|
|
|
help=_('Only return events that appear after the given event ID.'))
|
2015-01-13 15:21:25 +08:00
|
|
|
@utils.arg('-k', '--sort-keys', metavar='<KEYS>',
|
|
|
|
help=_('Name of keys used for sorting the returned events.'))
|
|
|
|
@utils.arg('-d', '--sort-dir', metavar='<DIR>',
|
|
|
|
help=_('Direction for sorting, where DIR can be "asc" or "desc".'))
|
2015-01-05 19:46:22 +08:00
|
|
|
def do_event_list(sc, args):
|
|
|
|
'''List events.'''
|
2015-01-16 15:53:16 +08:00
|
|
|
queries = {
|
2015-01-13 15:21:25 +08:00
|
|
|
'obj_id': args.id,
|
|
|
|
'obj_name': args.name,
|
|
|
|
'obj_type': args.type,
|
|
|
|
'filters': utils.format_parameters(args.filters),
|
|
|
|
'sort_keys': args.sort_keys,
|
|
|
|
'sort_dir': args.sort_dir,
|
|
|
|
'limit': args.limit,
|
|
|
|
'marker': args.marker,
|
|
|
|
}
|
|
|
|
|
2015-01-05 19:46:22 +08:00
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
events = sc.list(models.Event, queries)
|
2015-01-05 19:46:22 +08:00
|
|
|
except exc.HTTPNotFound as ex:
|
|
|
|
raise exc.CommandError(str(ex))
|
|
|
|
|
|
|
|
fields = ['timestamp', 'obj_type', 'obj_id', 'action', 'status',
|
|
|
|
'status_reason']
|
|
|
|
utils.print_list(events, fields, sortby_index=0)
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('event', metavar='<EVENT>',
|
|
|
|
help=_('ID of event to display details for.'))
|
|
|
|
def do_event_show(sc, args):
|
|
|
|
'''Describe the event.'''
|
|
|
|
try:
|
2015-01-16 15:53:16 +08:00
|
|
|
query = {'id': args.event}
|
|
|
|
event = sc.get(models.Event, query)
|
2015-01-05 19:46:22 +08:00
|
|
|
except exc.HTTPNotFound as ex:
|
|
|
|
raise exc.CommandError(str(ex))
|
|
|
|
|
|
|
|
utils.print_dict(event.to_dict())
|
|
|
|
|
|
|
|
|
|
|
|
#### EVENTS
|
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('-f', '--filters', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
|
|
|
help=_('Filter parameters to apply on returned actions. '
|
|
|
|
'This can be specified multiple times, or once with '
|
|
|
|
'parameters separated by a semicolon.'),
|
|
|
|
action='append')
|
2015-01-23 21:50:00 +08:00
|
|
|
@utils.arg('-k', '--sort-keys', metavar='<KEYS>',
|
|
|
|
help=_('Name of keys used for sorting the returned events.'))
|
|
|
|
@utils.arg('-d', '--sort-dir', metavar='<DIR>',
|
|
|
|
help=_('Direction for sorting, where DIR can be "asc" or "desc".'))
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-l', '--limit', metavar='<LIMIT>',
|
2015-01-23 21:50:00 +08:00
|
|
|
help=_('Limit the number of nodes returned.'))
|
2015-01-05 19:46:22 +08:00
|
|
|
@utils.arg('-m', '--marker', metavar='<ID>',
|
2015-01-23 21:50:00 +08:00
|
|
|
help=_('Only return nodes that appear after the given node ID.'))
|
|
|
|
@utils.arg('-s', '--show-deleted', default=False, action="store_true",
|
|
|
|
help=_('Include soft-deleted nodes if any.'))
|
2015-01-26 14:07:14 +08:00
|
|
|
@utils.arg('-F', '--full-id', default=False, action="store_true",
|
|
|
|
help=_('Print full IDs in list.'))
|
2015-01-05 19:46:22 +08:00
|
|
|
def do_action_list(sc, args):
|
|
|
|
'''List actions.'''
|
2015-01-26 14:07:14 +08:00
|
|
|
def _short_id(obj):
|
|
|
|
return obj.id[:8] + ' ...'
|
2015-01-26 22:55:00 +08:00
|
|
|
|
2015-01-26 14:07:14 +08:00
|
|
|
def _short_target(obj):
|
|
|
|
return obj.target[:8] + ' ...'
|
|
|
|
|
2015-01-26 22:45:16 +08:00
|
|
|
queries = {
|
|
|
|
'show_deleted': args.show_deleted,
|
|
|
|
'filters': utils.format_parameters(args.filters),
|
|
|
|
'sort_keys': args.sort_keys,
|
|
|
|
'sort_dir': args.sort_dir,
|
|
|
|
'limit': args.limit,
|
|
|
|
'marker': args.marker,
|
|
|
|
}
|
2015-01-05 19:46:22 +08:00
|
|
|
|
2015-01-26 22:45:16 +08:00
|
|
|
actions = sc.list(models.Action, **queries)
|
2015-01-05 19:46:22 +08:00
|
|
|
|
2015-01-23 21:50:00 +08:00
|
|
|
fields = ['id', 'name', 'action', 'status', 'target', 'depends_on',
|
2015-01-05 19:46:22 +08:00
|
|
|
'depended_by']
|
|
|
|
|
2015-01-26 14:07:14 +08:00
|
|
|
if not args.full_id:
|
|
|
|
formatters = {
|
|
|
|
'id': _short_id,
|
|
|
|
'target': _short_target,
|
|
|
|
}
|
|
|
|
else:
|
|
|
|
formatters = {}
|
|
|
|
|
|
|
|
utils.print_list(actions, fields, formatters=formatters, sortby_index=0)
|
2015-01-23 21:50:00 +08:00
|
|
|
|
|
|
|
|
|
|
|
@utils.arg('id', metavar='<ACTION ID>',
|
|
|
|
help=_('Name or ID of the action to show the details for.'))
|
|
|
|
def do_action_show(sc, args):
|
|
|
|
'''Show detailed info about the specified action.'''
|
|
|
|
try:
|
|
|
|
query = {'id': args.id}
|
|
|
|
action = sc.get(models.Action, query)
|
|
|
|
except exc.HTTPNotFound:
|
|
|
|
msg = _('Action %(id)s is not found') % args.id
|
|
|
|
raise exc.CommandError(msg)
|
|
|
|
|
|
|
|
formatters = {
|
|
|
|
'inputs': utils.json_formatter,
|
|
|
|
'outputs': utils.json_formatter,
|
|
|
|
'tags': utils.json_formatter,
|
|
|
|
'data': utils.json_formatter,
|
|
|
|
}
|
|
|
|
|
|
|
|
utils.print_dict(action.to_dict(), formatters=formatters)
|