2016-11-03 12:12:14 +00:00
|
|
|
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
2016-11-08 10:10:19 +00:00
|
|
|
import os
|
|
|
|
import prettytable
|
|
|
|
import textwrap
|
|
|
|
|
|
|
|
from oslo_serialization import jsonutils
|
|
|
|
from oslo_utils import encodeutils
|
|
|
|
from oslo_utils import importutils
|
2017-01-25 18:48:51 +09:00
|
|
|
from oslo_utils import uuidutils
|
2016-11-08 10:10:19 +00:00
|
|
|
|
2016-11-03 12:12:14 +00:00
|
|
|
from masakariclient.common import exception as exc
|
|
|
|
from masakariclient.common.i18n import _
|
|
|
|
|
|
|
|
|
|
|
|
def format_parameters(params, parse_semicolon=True):
|
|
|
|
"""Reformat parameters into dict of format expected by the API."""
|
|
|
|
if not params:
|
|
|
|
return {}
|
|
|
|
|
|
|
|
if parse_semicolon:
|
|
|
|
# expect multiple invocations of --parameters but fall back to ';'
|
|
|
|
# delimited if only one --parameters is specified
|
|
|
|
if len(params) == 1:
|
|
|
|
params = params[0].split(';')
|
|
|
|
|
|
|
|
parameters = {}
|
|
|
|
for p in params:
|
|
|
|
try:
|
|
|
|
(n, v) = p.split(('='), 1)
|
|
|
|
except ValueError:
|
|
|
|
msg = _('Malformed parameter(%s). Use the key=value format.') % p
|
|
|
|
raise exc.CommandError(msg)
|
|
|
|
|
|
|
|
if n not in parameters:
|
|
|
|
parameters[n] = v
|
|
|
|
else:
|
|
|
|
if not isinstance(parameters[n], list):
|
|
|
|
parameters[n] = [parameters[n]]
|
|
|
|
parameters[n].append(v)
|
|
|
|
|
|
|
|
return parameters
|
2016-11-05 17:07:41 +09:00
|
|
|
|
|
|
|
|
|
|
|
def remove_unspecified_items(attrs):
|
|
|
|
"""Remove the items that don't have any values."""
|
2017-03-07 15:20:26 +05:30
|
|
|
for key, value in list(attrs.items()):
|
2016-11-05 17:07:41 +09:00
|
|
|
if not value:
|
|
|
|
del attrs[key]
|
|
|
|
return attrs
|
2016-11-08 10:10:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
def import_versioned_module(version, submodule=None):
|
|
|
|
module = 'masakariclient.v%s' % version
|
|
|
|
if submodule:
|
|
|
|
module = '.'.join((module, submodule))
|
|
|
|
return importutils.import_module(module)
|
|
|
|
|
|
|
|
|
|
|
|
def arg(*args, **kwargs):
|
|
|
|
"""Decorator for CLI args."""
|
|
|
|
|
|
|
|
def _decorator(func):
|
|
|
|
if not hasattr(func, 'arguments'):
|
|
|
|
func.arguments = []
|
|
|
|
|
|
|
|
if (args, kwargs) not in func.arguments:
|
|
|
|
func.arguments.insert(0, (args, kwargs))
|
|
|
|
|
|
|
|
return func
|
|
|
|
|
|
|
|
return _decorator
|
|
|
|
|
|
|
|
|
|
|
|
def env(*args, **kwargs):
|
|
|
|
"""Returns the first environment variable set.
|
|
|
|
|
|
|
|
If all are empty, defaults to '' or keyword arg `default`.
|
|
|
|
"""
|
|
|
|
for arg in args:
|
|
|
|
value = os.environ.get(arg)
|
|
|
|
if value:
|
|
|
|
return value
|
|
|
|
return kwargs.get('default', '')
|
|
|
|
|
|
|
|
|
|
|
|
def print_list(objs, fields, formatters={}, sortby_index=None):
|
|
|
|
"""Print list data by PrettyTable."""
|
|
|
|
|
|
|
|
if sortby_index is None:
|
|
|
|
sortby = None
|
|
|
|
else:
|
|
|
|
sortby = fields[sortby_index]
|
|
|
|
mixed_case_fields = ['serverId']
|
|
|
|
pt = prettytable.PrettyTable([f for f in fields], caching=False)
|
|
|
|
pt.align = 'l'
|
|
|
|
|
|
|
|
for o in objs:
|
|
|
|
row = []
|
|
|
|
for field in fields:
|
|
|
|
if field in formatters:
|
|
|
|
row.append(formatters[field](o))
|
|
|
|
else:
|
|
|
|
if field in mixed_case_fields:
|
|
|
|
field_name = field.replace(' ', '_')
|
|
|
|
else:
|
|
|
|
field_name = field.lower().replace(' ', '_')
|
|
|
|
data = getattr(o, field_name, '')
|
|
|
|
if data is None:
|
|
|
|
data = '-'
|
|
|
|
# '\r' would break the table, so remove it.
|
2020-10-12 14:58:41 +08:00
|
|
|
data = str(data).replace("\r", "")
|
2016-11-08 10:10:19 +00:00
|
|
|
row.append(data)
|
|
|
|
pt.add_row(row)
|
|
|
|
|
|
|
|
if sortby is not None:
|
|
|
|
result = encodeutils.safe_encode(pt.get_string(sortby=sortby))
|
|
|
|
else:
|
|
|
|
result = encodeutils.safe_encode(pt.get_string())
|
|
|
|
|
2020-10-12 14:58:41 +08:00
|
|
|
result = result.decode()
|
2016-11-08 10:10:19 +00:00
|
|
|
|
|
|
|
print(result)
|
|
|
|
|
|
|
|
|
|
|
|
def print_dict(d, dict_property="Property", dict_value="Value", wrap=0):
|
|
|
|
"""Print dictionary data (eg. show) by PrettyTable."""
|
|
|
|
|
|
|
|
pt = prettytable.PrettyTable([dict_property, dict_value], caching=False)
|
|
|
|
pt.align = 'l'
|
|
|
|
for k, v in sorted(d.items()):
|
|
|
|
# convert dict to str to check length
|
|
|
|
if isinstance(v, (dict, list)):
|
|
|
|
v = jsonutils.dumps(v)
|
|
|
|
if wrap > 0:
|
2020-10-12 14:58:41 +08:00
|
|
|
v = textwrap.fill(str(v), wrap)
|
2016-11-08 10:10:19 +00:00
|
|
|
# if value has a newline, add in multiple rows
|
|
|
|
# e.g. fault with stacktrace
|
2020-10-12 14:58:41 +08:00
|
|
|
if v and isinstance(v, str) and (r'\n' in v or '\r' in v):
|
2016-11-08 10:10:19 +00:00
|
|
|
# '\r' would break the table, so remove it.
|
|
|
|
if '\r' in v:
|
|
|
|
v = v.replace('\r', '')
|
|
|
|
lines = v.strip().split(r'\n')
|
|
|
|
col1 = k
|
|
|
|
for line in lines:
|
|
|
|
pt.add_row([col1, line])
|
|
|
|
col1 = ''
|
|
|
|
else:
|
|
|
|
if v is None:
|
|
|
|
v = '-'
|
|
|
|
pt.add_row([k, v])
|
|
|
|
|
|
|
|
result = encodeutils.safe_encode(pt.get_string())
|
|
|
|
|
2020-10-12 14:58:41 +08:00
|
|
|
result = result.decode()
|
2016-11-08 10:10:19 +00:00
|
|
|
|
|
|
|
print(result)
|
2017-01-02 19:17:16 +05:30
|
|
|
|
|
|
|
|
|
|
|
def format_sort_filter_params(parsed_args):
|
|
|
|
queries = {}
|
|
|
|
limit = parsed_args.limit
|
|
|
|
marker = parsed_args.marker
|
|
|
|
sort = parsed_args.sort
|
|
|
|
if limit:
|
|
|
|
queries['limit'] = limit
|
|
|
|
if marker:
|
|
|
|
queries['marker'] = marker
|
|
|
|
|
|
|
|
sort_keys = []
|
|
|
|
sort_dirs = []
|
|
|
|
if sort:
|
|
|
|
for sort_param in sort.split(','):
|
|
|
|
sort_key, _sep, sort_dir = sort_param.partition(':')
|
|
|
|
if not sort_dir:
|
|
|
|
sort_dir = 'desc'
|
|
|
|
elif sort_dir not in ('asc', 'desc'):
|
|
|
|
raise exc.CommandError(_(
|
|
|
|
'Unknown sort direction: %s') % sort_dir)
|
|
|
|
sort_keys.append(sort_key)
|
|
|
|
sort_dirs.append(sort_dir)
|
|
|
|
|
|
|
|
queries['sort_key'] = sort_keys
|
|
|
|
queries['sort_dir'] = sort_dirs
|
|
|
|
|
|
|
|
if parsed_args.filters:
|
|
|
|
queries.update(format_parameters(parsed_args.filters))
|
|
|
|
|
|
|
|
return queries
|
2017-01-25 18:48:51 +09:00
|
|
|
|
|
|
|
|
|
|
|
def get_uuid_by_name(manager, name, segment=None):
|
|
|
|
"""Helper methods for getting uuid of segment or host by name.
|
|
|
|
|
|
|
|
:param manager: A client manager class
|
|
|
|
:param name: The resource we are trying to find a uuid
|
|
|
|
:param segment: segment id, default None
|
|
|
|
:return: The uuid of found resource
|
|
|
|
"""
|
|
|
|
|
|
|
|
# If it cannot be found return the name.
|
|
|
|
uuid = name
|
|
|
|
if not uuidutils.is_uuid_like(name):
|
|
|
|
if segment:
|
|
|
|
items = manager.hosts(segment)
|
|
|
|
else:
|
|
|
|
items = manager.segments()
|
|
|
|
|
|
|
|
for item in items:
|
|
|
|
item_name = getattr(item, 'name')
|
|
|
|
if item_name == name:
|
|
|
|
uuid = getattr(item, 'uuid')
|
|
|
|
break
|
|
|
|
return uuid
|