update host api & cli
- update host add, remove api - new apis for host setup, ssh_check, get_hosts, get_groups - new exception classes - update host cli commands to use new apis Jira-Issue: OSTACKDEV-16
This commit is contained in:
parent
5a1596f051
commit
b883423d67
@ -13,8 +13,13 @@
|
||||
# under the License.
|
||||
import logging
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.exceptions import InvalidArgument
|
||||
from kollacli.api.job import Job
|
||||
from kollacli.common.ansible import actions
|
||||
from kollacli.common.inventory import Inventory
|
||||
from kollacli.common.utils import safe_decode
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -49,6 +54,15 @@ class AsyncApi(object):
|
||||
Stops and removes all kolla related docker containers on the
|
||||
specified hosts.
|
||||
"""
|
||||
if destroy_type not in ['stop', 'kill']:
|
||||
raise InvalidArgument(
|
||||
u._('Invalid destroy type ({type}). Must be either '
|
||||
'"stop" or "kill".').format(type=destroy_type))
|
||||
|
||||
hostnames = safe_decode(hostnames)
|
||||
inventory = Inventory.load()
|
||||
inventory.validate_hostnames(hostnames)
|
||||
|
||||
ansible_job = actions.destroy_hosts(hostnames, destroy_type,
|
||||
verbose_level, include_data)
|
||||
return Job(ansible_job)
|
||||
@ -60,5 +74,9 @@ class AsyncApi(object):
|
||||
any of the hosts are not configured correctly or if they have
|
||||
already been deployed to.
|
||||
"""
|
||||
hostnames = safe_decode(hostnames)
|
||||
inventory = Inventory.load()
|
||||
inventory.validate_hostnames(hostnames)
|
||||
|
||||
ansible_job = actions.precheck(hostnames, verbose_level)
|
||||
return Job(ansible_job)
|
||||
|
79
kollacli/api/exceptions.py
Normal file
79
kollacli/api/exceptions.py
Normal file
@ -0,0 +1,79 @@
|
||||
# Copyright(c) 2016, Oracle and/or its affiliates. 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.
|
||||
"""Exception definitions."""
|
||||
import kollacli.i18n as u
|
||||
|
||||
|
||||
class ClientException(Exception):
|
||||
"""KollaClient Base Class Exception"""
|
||||
def __init__(self, message, *args):
|
||||
if not message:
|
||||
message = u._('An unknown exception occurred.')
|
||||
super(ClientException, self).__init__(message, *args)
|
||||
|
||||
|
||||
class NotInInventory(ClientException):
|
||||
"""Not in inventory exception"""
|
||||
def __init__(self, obj_type, obj_names, *args):
|
||||
if isinstance(obj_names, list):
|
||||
# list of names
|
||||
invalid_objs = ''
|
||||
comma = ''
|
||||
for obj_name in obj_names:
|
||||
invalid_objs = ''.join([invalid_objs, comma, obj_name])
|
||||
comma = ','
|
||||
else:
|
||||
# single object name
|
||||
invalid_objs = obj_names
|
||||
message = (u._('{type} ({objs}) does not exist.')
|
||||
.format(type=obj_type, objs=invalid_objs))
|
||||
super(NotInInventory, self).__init__(message, *args)
|
||||
|
||||
|
||||
class HostError(ClientException):
|
||||
pass
|
||||
|
||||
|
||||
class HostsSshCheckError(ClientException):
|
||||
def __init__(self, hostnames, *args):
|
||||
failed_hosts = ''
|
||||
comma = ''
|
||||
for hostname in hostnames:
|
||||
failed_hosts = ''.join([failed_hosts, comma, hostname])
|
||||
comma = ','
|
||||
message = (u._('host(s) ssh check failed: {hosts}')
|
||||
.format(hosts=failed_hosts))
|
||||
super(HostsSshCheckError, self).__init__(message, *args)
|
||||
|
||||
|
||||
class InvalidArgument(ClientException):
|
||||
"""Invalid argument"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidConfiguration(ClientException):
|
||||
"""Invalid configuration"""
|
||||
pass
|
||||
|
||||
|
||||
class FailedOperation(ClientException):
|
||||
pass
|
||||
|
||||
|
||||
class MissingArgument(ClientException):
|
||||
"""Missing argument"""
|
||||
def __init__(self, argname, *args):
|
||||
message = (u._('argument is missing: {name}')
|
||||
.format(name=argname))
|
||||
super(InvalidArgument, self).__init__(message, *args)
|
@ -13,26 +13,92 @@
|
||||
# under the License.
|
||||
import logging
|
||||
|
||||
from kollacli.api.exceptions import MissingArgument
|
||||
from kollacli.common.inventory import Inventory
|
||||
from kollacli.common.utils import safe_decode
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HostApi(object):
|
||||
|
||||
def host_add(self, hostname):
|
||||
def host_add(self, hostnames):
|
||||
"""add hosts to the inventory"""
|
||||
if not hostnames:
|
||||
raise MissingArgument('host names')
|
||||
hostnames = safe_decode(hostnames)
|
||||
|
||||
inventory = Inventory.load()
|
||||
inventory.add_host(hostname)
|
||||
for hostname in hostnames:
|
||||
inventory.add_host(hostname)
|
||||
Inventory.save(inventory)
|
||||
|
||||
def host_remove(self, hostname):
|
||||
# TODO(bmace) - need to do a lot of validity
|
||||
# / null checking in these api calls
|
||||
def host_remove(self, hostnames):
|
||||
"""remove hosts from the inventory"""
|
||||
inventory = Inventory.load()
|
||||
|
||||
if hostname.lower() == 'all':
|
||||
inventory.remove_all_hosts()
|
||||
else:
|
||||
if not hostnames:
|
||||
raise MissingArgument('host name')
|
||||
|
||||
hostnames = safe_decode(hostnames)
|
||||
for hostname in hostnames:
|
||||
inventory.remove_host(hostname)
|
||||
|
||||
Inventory.save(inventory)
|
||||
|
||||
def host_get_all(self):
|
||||
"""get all hosts in the inventory"""
|
||||
# TODO(snoyes) - need to make a host object
|
||||
inventory = Inventory.load()
|
||||
hostnames = inventory.get_hostnames()
|
||||
return hostnames
|
||||
|
||||
def host_get_groups(self, hostname=None):
|
||||
"""get groups for hosts
|
||||
|
||||
Return:
|
||||
- if hostname, {hostname: [groups]}
|
||||
- else, {hostname: [groups], hostname: [groups]...}
|
||||
"""
|
||||
inventory = Inventory.load()
|
||||
host_groups = inventory.get_host_groups()
|
||||
if hostname:
|
||||
hostname = safe_decode(hostname)
|
||||
inventory.validate_hostnames([hostname])
|
||||
groupnames = host_groups[hostname]
|
||||
host_groups = {hostname: groupnames}
|
||||
return host_groups
|
||||
|
||||
def host_check_ssh(self, hostnames):
|
||||
"""ssh check for hosts
|
||||
|
||||
return {hostname: {'success': True|False,
|
||||
'msg': message}}
|
||||
"""
|
||||
inventory = Inventory.load()
|
||||
hostnames = safe_decode(hostnames)
|
||||
inventory.validate_hostnames(hostnames)
|
||||
summary = inventory.ssh_check_hosts(hostnames)
|
||||
return summary
|
||||
|
||||
def host_setup_hosts(self, hosts_info):
|
||||
"""setup multiple hosts
|
||||
|
||||
hosts_info is a dict of format:
|
||||
{'hostname1': {
|
||||
'password': password
|
||||
'uname': user_name
|
||||
}
|
||||
}
|
||||
The uname entry is optional.
|
||||
"""
|
||||
inventory = Inventory.load()
|
||||
inventory.validate_hostnames(hosts_info.keys())
|
||||
inventory.setup_hosts(hosts_info)
|
||||
|
||||
def host_setup(self, hostname, password):
|
||||
# TODO(snoyes) move to host object
|
||||
inventory = Inventory.load()
|
||||
hostname = safe_decode(hostname)
|
||||
inventory.validate_hostnames([hostname])
|
||||
inventory.setup_host(hostname, password)
|
||||
|
@ -17,8 +17,8 @@ import traceback
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.client import ClientApi
|
||||
from kollacli.commands.exceptions import CommandError
|
||||
from kollacli.common.utils import convert_to_unicode
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
from cliff.command import Command
|
||||
|
||||
|
@ -16,6 +16,9 @@ import kollacli.i18n as u
|
||||
|
||||
|
||||
class CommandError(Exception):
|
||||
"""CLI command error"""
|
||||
def __init__(self, message, *args):
|
||||
message = u._('ERROR: {message}').format(message=message)
|
||||
prefix = u._('ERROR: ')
|
||||
if not message.startswith(prefix):
|
||||
message = prefix + message
|
||||
super(CommandError, self).__init__(message, *args)
|
@ -15,9 +15,9 @@ import traceback
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.commands.exceptions import CommandError
|
||||
from kollacli.common.inventory import Inventory
|
||||
from kollacli.common.utils import convert_to_unicode
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
from cliff.command import Command
|
||||
from cliff.lister import Lister
|
||||
|
@ -21,11 +21,8 @@ import yaml
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.client import ClientApi
|
||||
# TODO(snoyes): remove inventory reference from CLI
|
||||
from kollacli.common.inventory import Inventory
|
||||
from kollacli.common.utils import convert_to_unicode
|
||||
from kollacli.common.utils import get_setup_user
|
||||
from kollacli.exceptions import CommandError
|
||||
from kollacli.api.exceptions import ClientException
|
||||
from kollacli.commands.exceptions import CommandError
|
||||
|
||||
from cliff.command import Command
|
||||
from cliff.lister import Lister
|
||||
@ -34,12 +31,6 @@ LOG = logging.getLogger(__name__)
|
||||
CLIENT = ClientApi()
|
||||
|
||||
|
||||
def _host_not_found(hostname):
|
||||
raise CommandError(
|
||||
u._('Host ({host}) not found. Please add it with "host add".')
|
||||
.format(host=hostname))
|
||||
|
||||
|
||||
class HostAdd(Command):
|
||||
"""Add host to openstack-kolla."""
|
||||
|
||||
@ -52,17 +43,10 @@ class HostAdd(Command):
|
||||
def take_action(self, parsed_args):
|
||||
try:
|
||||
hostname = parsed_args.hostname.strip()
|
||||
hostname = convert_to_unicode(hostname)
|
||||
CLIENT.host_add([hostname])
|
||||
|
||||
if hostname.lower() == 'all':
|
||||
raise CommandError(
|
||||
u._('Special host name "all" cannot be added as an '
|
||||
'individual host.'))
|
||||
|
||||
CLIENT.host_add(hostname)
|
||||
|
||||
except CommandError as e:
|
||||
raise e
|
||||
except ClientException as e:
|
||||
raise CommandError(str(e))
|
||||
except Exception as e:
|
||||
raise Exception(traceback.format_exc())
|
||||
|
||||
@ -86,17 +70,11 @@ class HostDestroy(Command):
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
try:
|
||||
hostname = ''
|
||||
hostname = parsed_args.hostname.strip()
|
||||
hostname = convert_to_unicode(hostname)
|
||||
|
||||
inventory = Inventory.load()
|
||||
hostnames = [hostname]
|
||||
if hostname == 'all':
|
||||
hostnames = inventory.get_hostnames()
|
||||
else:
|
||||
if not inventory.get_host(hostname):
|
||||
_host_not_found(hostname)
|
||||
hostnames = CLIENT.host_get_all()
|
||||
|
||||
destroy_type = 'kill'
|
||||
if parsed_args.stop:
|
||||
@ -118,8 +96,8 @@ class HostDestroy(Command):
|
||||
raise CommandError(u._('Job failed:\n{msg}')
|
||||
.format(msg=job.get_error_message()))
|
||||
|
||||
except CommandError as e:
|
||||
raise e
|
||||
except ClientException as e:
|
||||
raise CommandError(str(e))
|
||||
except Exception as e:
|
||||
raise Exception(traceback.format_exc())
|
||||
|
||||
@ -129,19 +107,20 @@ class HostRemove(Command):
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(HostRemove, self).get_parser(prog_name)
|
||||
parser.add_argument('hostname', metavar='<hostname>',
|
||||
help=u._('Host name'))
|
||||
parser.add_argument('hostname', metavar='<hostname | all>',
|
||||
help=u._('Host name or "all"'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
try:
|
||||
hostname = parsed_args.hostname.strip()
|
||||
hostname = convert_to_unicode(hostname)
|
||||
hostnames = [hostname]
|
||||
if hostname == 'all':
|
||||
hostnames = CLIENT.host_get_all()
|
||||
CLIENT.host_remove(hostnames)
|
||||
|
||||
CLIENT.host_remove(hostname)
|
||||
|
||||
except CommandError as e:
|
||||
raise e
|
||||
except ClientException as e:
|
||||
raise CommandError(str(e))
|
||||
except Exception as e:
|
||||
raise Exception(traceback.format_exc())
|
||||
|
||||
@ -163,28 +142,19 @@ class HostList(Lister):
|
||||
hostname = None
|
||||
if parsed_args.hostname:
|
||||
hostname = parsed_args.hostname.strip()
|
||||
hostname = convert_to_unicode(hostname)
|
||||
|
||||
inventory = Inventory.load()
|
||||
|
||||
if hostname:
|
||||
host = inventory.get_host(hostname)
|
||||
if not host:
|
||||
_host_not_found(hostname)
|
||||
|
||||
host_groups = CLIENT.host_get_groups(hostname)
|
||||
data = []
|
||||
host_groups = inventory.get_host_groups()
|
||||
if host_groups:
|
||||
if hostname:
|
||||
data.append((hostname, host_groups[hostname]))
|
||||
else:
|
||||
for (hostname, groupnames) in host_groups.items():
|
||||
data.append((hostname, groupnames))
|
||||
for (hostname, groupnames) in host_groups.items():
|
||||
data.append((hostname, groupnames))
|
||||
else:
|
||||
data.append(('', ''))
|
||||
|
||||
return ((u._('Host'), u._('Groups')), sorted(data))
|
||||
except CommandError as e:
|
||||
raise e
|
||||
|
||||
except ClientException as e:
|
||||
raise CommandError(str(e))
|
||||
except Exception as e:
|
||||
raise Exception(traceback.format_exc())
|
||||
|
||||
@ -194,7 +164,7 @@ class HostCheck(Command):
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(HostCheck, self).get_parser(prog_name)
|
||||
parser.add_argument('hostname', metavar='<hostname>',
|
||||
parser.add_argument('hostname', metavar='<hostname | all>',
|
||||
help=u._('Host name or "all"'))
|
||||
parser.add_argument('--predeploy', action='store_true',
|
||||
help=u._('Run pre-deploy host checks.'))
|
||||
@ -203,14 +173,9 @@ class HostCheck(Command):
|
||||
def take_action(self, parsed_args):
|
||||
try:
|
||||
hostname = parsed_args.hostname.strip()
|
||||
hostname = convert_to_unicode(hostname)
|
||||
inventory = Inventory.load()
|
||||
hostnames = [hostname]
|
||||
if hostname == 'all':
|
||||
hostnames = inventory.get_hostnames()
|
||||
else:
|
||||
if not inventory.get_host(hostname):
|
||||
_host_not_found(hostname)
|
||||
hostnames = CLIENT.host_get_all()
|
||||
|
||||
if parsed_args.predeploy:
|
||||
# run pre-deploy checks
|
||||
@ -224,24 +189,23 @@ class HostCheck(Command):
|
||||
if status != 0:
|
||||
raise CommandError(u._('Job failed:\n{msg}')
|
||||
.format(msg=job.get_error_message()))
|
||||
|
||||
else:
|
||||
# run ssh checks
|
||||
summary = CLIENT.host_check_ssh(hostnames)
|
||||
all_ok = True
|
||||
summary = inventory.ssh_check_hosts(hostnames)
|
||||
for hostname, info in summary.items():
|
||||
status = 'success'
|
||||
status = u._('success')
|
||||
msg = ''
|
||||
if not info['success']:
|
||||
status = 'failed- '
|
||||
status = u._('failed- ')
|
||||
msg = info['msg']
|
||||
all_ok = False
|
||||
LOG.info('Host (%s): %s %s' % (hostname, status, msg))
|
||||
LOG.info(u._('Host {host}: {sts} {msg}')
|
||||
.format(host=hostname, sts=status, msg=msg))
|
||||
|
||||
if not all_ok:
|
||||
raise CommandError('Host check failed.')
|
||||
except CommandError as e:
|
||||
raise e
|
||||
raise CommandError(u._('Host check failed.'))
|
||||
except ClientException as e:
|
||||
raise CommandError(str(e))
|
||||
except Exception as e:
|
||||
raise Exception(traceback.format_exc())
|
||||
|
||||
@ -268,21 +232,16 @@ class HostSetup(Command):
|
||||
raise CommandError(
|
||||
u._('Host name and hosts info file path '
|
||||
'cannot both be present.'))
|
||||
inventory = Inventory.load()
|
||||
|
||||
if parsed_args.file:
|
||||
# multi-host setup via xml file
|
||||
hosts_data = self.get_yml_data(parsed_args.file.strip())
|
||||
inventory.setup_hosts(hosts_data)
|
||||
CLIENT.host_setup_hosts(hosts_data)
|
||||
else:
|
||||
# single host setup
|
||||
hostname = parsed_args.hostname.strip()
|
||||
hostname = convert_to_unicode(hostname)
|
||||
if not inventory.get_host(hostname):
|
||||
_host_not_found(hostname)
|
||||
|
||||
check_ok, _ = inventory.ssh_check_host(hostname)
|
||||
if check_ok:
|
||||
summary = CLIENT.host_check_ssh([hostname])
|
||||
if summary[hostname]['success']:
|
||||
LOG.info(
|
||||
u._LI('Skipping setup of host ({host}) as '
|
||||
'ssh check is ok.').format(host=hostname))
|
||||
@ -291,15 +250,13 @@ class HostSetup(Command):
|
||||
if parsed_args.insecure:
|
||||
password = parsed_args.insecure.strip()
|
||||
else:
|
||||
setup_user = get_setup_user()
|
||||
password = getpass.getpass(
|
||||
u._('{user} password for {host}: ')
|
||||
.format(user=setup_user, host=hostname))
|
||||
password = convert_to_unicode(password)
|
||||
inventory.setup_host(hostname, password)
|
||||
u._('kolla password for {host}: ')
|
||||
.format(host=hostname))
|
||||
CLIENT.host_setup(hostname, password)
|
||||
|
||||
except CommandError as e:
|
||||
raise e
|
||||
except ClientException as e:
|
||||
raise CommandError(str(e))
|
||||
except Exception as e:
|
||||
raise Exception(traceback.format_exc())
|
||||
|
||||
|
@ -20,10 +20,10 @@ import kollacli.i18n as u
|
||||
from cliff.command import Command
|
||||
from cliff.lister import Lister
|
||||
|
||||
from kollacli.commands.exceptions import CommandError
|
||||
from kollacli.common.passwords import clear_password
|
||||
from kollacli.common.passwords import get_password_names
|
||||
from kollacli.common.passwords import set_password
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
|
||||
class PasswordSet(Command):
|
||||
|
@ -15,9 +15,9 @@ import traceback
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.commands.exceptions import CommandError
|
||||
from kollacli.common import properties
|
||||
from kollacli.common import utils
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
from cliff.command import Command
|
||||
from cliff.lister import Lister
|
||||
|
@ -15,9 +15,9 @@ import traceback
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.commands.exceptions import CommandError
|
||||
from kollacli.common.inventory import Inventory
|
||||
from kollacli.common.utils import convert_to_unicode
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
from cliff.command import Command
|
||||
from cliff.lister import Lister
|
||||
|
@ -19,7 +19,7 @@ from cliff.command import Command
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.client import ClientApi
|
||||
from kollacli.exceptions import CommandError
|
||||
from kollacli.commands.exceptions import CommandError
|
||||
|
||||
|
||||
CLIENT = ClientApi()
|
||||
|
@ -16,6 +16,9 @@ import os
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.exceptions import InvalidArgument
|
||||
from kollacli.api.exceptions import InvalidConfiguration
|
||||
from kollacli.api.exceptions import NotInInventory
|
||||
from kollacli.common.ansible.playbook import AnsiblePlaybook
|
||||
from kollacli.common.inventory import Inventory
|
||||
from kollacli.common import properties
|
||||
@ -24,7 +27,6 @@ from kollacli.common.utils import get_kolla_etc
|
||||
from kollacli.common.utils import get_kolla_home
|
||||
from kollacli.common.utils import get_kollacli_home
|
||||
from kollacli.common.utils import is_string_true
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -37,11 +39,6 @@ def destroy_hosts(hostnames, destroy_type,
|
||||
or killed. That will be determined by the destroy_type,
|
||||
which can either be 'stop' or 'kill'.
|
||||
'''
|
||||
if destroy_type not in ['stop', 'kill']:
|
||||
raise CommandError(
|
||||
u._('Invalid destroy type ({type}). Must be either '
|
||||
'"stop" or "kill".').format(type=destroy_type))
|
||||
|
||||
playbook_name = 'host_destroy_no_data.yml'
|
||||
if include_data:
|
||||
playbook_name = 'host_destroy.yml'
|
||||
@ -125,7 +122,7 @@ def _run_deploy_rules(playbook):
|
||||
|
||||
# cannot have both groups and hosts
|
||||
if playbook.hosts and playbook.groups:
|
||||
raise CommandError(
|
||||
raise InvalidArgument(
|
||||
u._('Hosts and Groups arguments cannot '
|
||||
'both be present at the same time.'))
|
||||
|
||||
@ -134,8 +131,7 @@ def _run_deploy_rules(playbook):
|
||||
for service in playbook.services:
|
||||
valid_service = inventory.get_service(service)
|
||||
if not valid_service:
|
||||
raise CommandError(u._('Service ({srvc}) not found.')
|
||||
.format(srvc=service))
|
||||
raise NotInInventory(u._('Service'), service)
|
||||
|
||||
# check that every group with enabled services
|
||||
# has hosts associated to it
|
||||
@ -160,7 +156,7 @@ def _run_deploy_rules(playbook):
|
||||
failed_groups.append(groupname)
|
||||
|
||||
if len(failed_groups) > 0:
|
||||
raise CommandError(
|
||||
raise InvalidConfiguration(
|
||||
u._('Deploy failed. '
|
||||
'Groups: {groups} with enabled '
|
||||
'services : {services} '
|
||||
@ -184,4 +180,4 @@ def _run_deploy_rules(playbook):
|
||||
'not yet been set up. Please see the '
|
||||
'documentation for swift configuration '
|
||||
'instructions.')
|
||||
raise CommandError(msg)
|
||||
raise InvalidConfiguration(msg)
|
||||
|
@ -18,11 +18,11 @@ import traceback
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.exceptions import NotInInventory
|
||||
from kollacli.common.ansible.job import AnsibleJob
|
||||
from kollacli.common.utils import get_admin_user
|
||||
from kollacli.common.utils import get_ansible_command
|
||||
from kollacli.common.utils import get_kolla_etc
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
from kollacli.common.inventory import Inventory
|
||||
|
||||
@ -114,15 +114,13 @@ class AnsiblePlaybook(object):
|
||||
for hostname in self.hosts:
|
||||
host = self.inventory.get_host(hostname)
|
||||
if not host:
|
||||
raise CommandError(u._('Host ({host}) not found.')
|
||||
.format(host=hostname))
|
||||
raise NotInInventory(u._('Host'), hostname)
|
||||
inventory_filter['deploy_hosts'] = self.hosts
|
||||
elif self.groups:
|
||||
for groupname in self.groups:
|
||||
group = self.inventory.get_group(groupname)
|
||||
if not group:
|
||||
raise CommandError(u._('Group ({group}) not found.')
|
||||
.format(group=groupname))
|
||||
raise NotInInventory(u._('Group'), groupname)
|
||||
inventory_filter['deploy_groups'] = self.groups
|
||||
inventory_path = \
|
||||
self.inventory.create_json_gen_file(inventory_filter)
|
||||
|
@ -21,6 +21,12 @@ import uuid
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.exceptions import FailedOperation
|
||||
from kollacli.api.exceptions import HostError
|
||||
from kollacli.api.exceptions import InvalidArgument
|
||||
from kollacli.api.exceptions import InvalidConfiguration
|
||||
from kollacli.api.exceptions import MissingArgument
|
||||
from kollacli.api.exceptions import NotInInventory
|
||||
from kollacli.common.sshutils import ssh_setup_host
|
||||
from kollacli.common.utils import get_admin_user
|
||||
from kollacli.common.utils import get_ansible_command
|
||||
@ -31,8 +37,6 @@ from kollacli.common.utils import run_cmd
|
||||
from kollacli.common.utils import sync_read_file
|
||||
from kollacli.common.utils import sync_write_file
|
||||
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
ANSIBLE_SSH_USER = 'ansible_ssh_user'
|
||||
ANSIBLE_CONNECTION = 'ansible_connection'
|
||||
ANSIBLE_BECOME = 'ansible_become'
|
||||
@ -336,7 +340,7 @@ class Inventory(object):
|
||||
else:
|
||||
inventory = Inventory()
|
||||
except Exception:
|
||||
raise CommandError(
|
||||
raise FailedOperation(
|
||||
u._('Loading inventory failed. : {error}')
|
||||
.format(error=traceback.format_exc()))
|
||||
return inventory
|
||||
@ -353,7 +357,7 @@ class Inventory(object):
|
||||
sync_write_file(inventory_path, pretty_data)
|
||||
|
||||
except Exception as e:
|
||||
raise CommandError(
|
||||
raise FailedOperation(
|
||||
u._('Saving inventory failed. : {error}')
|
||||
.format(error=str(e)))
|
||||
|
||||
@ -397,17 +401,14 @@ class Inventory(object):
|
||||
if group name is not none, add host to group
|
||||
"""
|
||||
if groupname and groupname not in self._groups:
|
||||
raise CommandError(
|
||||
u._('Group name ({group}) does not exist.')
|
||||
.format(group=groupname))
|
||||
raise NotInInventory(u._('Group'), groupname)
|
||||
|
||||
if groupname and hostname not in self._hosts:
|
||||
raise CommandError(
|
||||
u._('Host name ({host}) does not exist.')
|
||||
.format(host=hostname))
|
||||
# if a groupname is specified, the host must already exist
|
||||
raise NotInInventory(u._('Host'), hostname)
|
||||
|
||||
if not groupname and not self.remote_mode and len(self._hosts) >= 1:
|
||||
raise CommandError(
|
||||
raise InvalidConfiguration(
|
||||
u._('Cannot have more than one host when in local deploy '
|
||||
'mode.'))
|
||||
|
||||
@ -436,9 +437,7 @@ class Inventory(object):
|
||||
if group name is not none, remove host from group
|
||||
"""
|
||||
if groupname and groupname not in self._groups:
|
||||
raise CommandError(
|
||||
u._('Group name ({group}) does not exist.')
|
||||
.format(group=groupname))
|
||||
raise NotInInventory(u._('Group'), groupname)
|
||||
|
||||
if hostname not in self._hosts:
|
||||
return
|
||||
@ -488,7 +487,7 @@ class Inventory(object):
|
||||
summary = '\n'
|
||||
for hostname, err in failed_hosts.items():
|
||||
summary = summary + '- %s: %s\n' % (hostname, err)
|
||||
raise CommandError(
|
||||
raise HostError(
|
||||
u._('Not all hosts were set up. : {reasons}')
|
||||
.format(reasons=summary))
|
||||
else:
|
||||
@ -507,7 +506,7 @@ class Inventory(object):
|
||||
LOG.info(u._LI('Host ({host}) setup succeeded.')
|
||||
.format(host=hostname))
|
||||
except Exception as e:
|
||||
raise CommandError(
|
||||
raise HostError(
|
||||
u._('Host ({host}) setup failed : {error}')
|
||||
.format(host=hostname, error=str(e)))
|
||||
return True
|
||||
@ -559,7 +558,7 @@ class Inventory(object):
|
||||
|
||||
# Group names cannot overlap with service names:
|
||||
if groupname in self._services or groupname in self._sub_services:
|
||||
raise CommandError(
|
||||
raise InvalidArgument(
|
||||
u._('Invalid group name. A service name '
|
||||
'cannot be used for a group name.'))
|
||||
|
||||
@ -574,7 +573,7 @@ class Inventory(object):
|
||||
|
||||
def remove_group(self, groupname):
|
||||
if groupname in PROTECTED_GROUPS:
|
||||
raise CommandError(
|
||||
raise InvalidArgument(
|
||||
u._('Cannot remove {group} group. It is required by kolla.')
|
||||
.format(group=groupname))
|
||||
|
||||
@ -617,7 +616,7 @@ class Inventory(object):
|
||||
return groups
|
||||
|
||||
def get_host_groups(self):
|
||||
"""return { hostname : groupnames }"""
|
||||
"""return { hostname : [groupnames] }"""
|
||||
|
||||
host_groups = {}
|
||||
for host in self._hosts.values():
|
||||
@ -676,8 +675,7 @@ class Inventory(object):
|
||||
|
||||
def add_group_to_service(self, groupname, servicename):
|
||||
if groupname not in self._groups:
|
||||
raise CommandError(u._('Group ({group}) not found.')
|
||||
.format(group=groupname))
|
||||
raise NotInInventory(u._('Group'), groupname)
|
||||
if servicename in self._services:
|
||||
service = self.get_service(servicename)
|
||||
service.add_groupname(groupname)
|
||||
@ -685,13 +683,11 @@ class Inventory(object):
|
||||
sub_service = self.get_sub_service(servicename)
|
||||
sub_service.add_groupname(groupname)
|
||||
else:
|
||||
raise CommandError(u._('Service ({service})) not found.')
|
||||
.format(service=servicename))
|
||||
raise NotInInventory(u._('Service'), servicename)
|
||||
|
||||
def remove_group_from_service(self, groupname, servicename):
|
||||
if groupname not in self._groups:
|
||||
raise CommandError(u._('Group ({group}) not found.')
|
||||
.format(group=groupname))
|
||||
raise NotInInventory(u._('Group'), groupname)
|
||||
if servicename in self._services:
|
||||
service = self.get_service(servicename)
|
||||
service.remove_groupname(groupname)
|
||||
@ -699,8 +695,7 @@ class Inventory(object):
|
||||
sub_service = self.get_sub_service(servicename)
|
||||
sub_service.remove_groupname(groupname)
|
||||
else:
|
||||
raise CommandError(u._('Service ({service})) not found.')
|
||||
.format(service=servicename))
|
||||
raise NotInInventory(u._('Service'), servicename)
|
||||
|
||||
def create_sub_service(self, sub_servicename):
|
||||
if sub_servicename not in self._sub_services:
|
||||
@ -750,7 +745,7 @@ class Inventory(object):
|
||||
|
||||
def set_deploy_mode(self, remote_flag):
|
||||
if not remote_flag and len(self._hosts) > 1:
|
||||
raise CommandError(
|
||||
raise InvalidConfiguration(
|
||||
u._('Cannot set local deploy mode when multiple hosts exist.'))
|
||||
self.remote_mode = remote_flag
|
||||
|
||||
@ -887,3 +882,13 @@ class Inventory(object):
|
||||
|
||||
def remove_json_gen_file(self, path):
|
||||
remove_temp_inventory(path)
|
||||
|
||||
def validate_hostnames(self, hostnames):
|
||||
if not hostnames:
|
||||
raise MissingArgument(u._('host name(s)'))
|
||||
invalid_hosts = []
|
||||
for hostname in hostnames:
|
||||
if hostname not in self._hosts:
|
||||
invalid_hosts.append(hostname)
|
||||
if invalid_hosts:
|
||||
raise NotInInventory(u._('Host'), invalid_hosts)
|
||||
|
@ -15,8 +15,8 @@ import os
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.exceptions import FailedOperation
|
||||
from kollacli.common import utils
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
PWDS_FILENAME = 'passwords.yml'
|
||||
PWD_EDITOR_FILENAME = 'passwd_editor.py'
|
||||
@ -31,7 +31,7 @@ def set_password(pwd_key, pwd_value):
|
||||
cmd = '%s -k %s -v %s' % (_get_cmd_prefix(), pwd_key, pwd_value)
|
||||
err_msg, output = utils.run_cmd(cmd, print_output=False)
|
||||
if err_msg:
|
||||
raise CommandError(
|
||||
raise FailedOperation(
|
||||
u._('Password set failed. {error} {message}')
|
||||
.format(error=err_msg, message=output))
|
||||
|
||||
@ -44,7 +44,7 @@ def clear_password(pwd_key):
|
||||
cmd = '%s -k %s -c' % (_get_cmd_prefix(), pwd_key)
|
||||
err_msg, output = utils.run_cmd(cmd, print_output=False)
|
||||
if err_msg:
|
||||
raise CommandError('%s %s' % (err_msg, output))
|
||||
raise FailedOperation('%s %s' % (err_msg, output))
|
||||
|
||||
|
||||
def get_password_names():
|
||||
@ -52,7 +52,7 @@ def get_password_names():
|
||||
cmd = '%s -l' % (_get_cmd_prefix())
|
||||
err_msg, output = utils.run_cmd(cmd, print_output=False)
|
||||
if err_msg:
|
||||
raise CommandError('%s %s' % (err_msg, output))
|
||||
raise FailedOperation('%s %s' % (err_msg, output))
|
||||
|
||||
pwd_names = []
|
||||
if output and ',' in output:
|
||||
|
@ -18,13 +18,13 @@ import yaml
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.api.exceptions import NotInInventory
|
||||
from kollacli.common.inventory import Inventory
|
||||
from kollacli.common.utils import change_property
|
||||
from kollacli.common.utils import get_group_vars_dir
|
||||
from kollacli.common.utils import get_host_vars_dir
|
||||
from kollacli.common.utils import get_kolla_home
|
||||
from kollacli.common.utils import sync_read_file
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -185,9 +185,7 @@ class AnsibleProperties(object):
|
||||
for host_name in host_list:
|
||||
host = inventory.get_host(host_name)
|
||||
if host is None:
|
||||
raise CommandError(
|
||||
u._('Host {host} does not exist.')
|
||||
.format(host=host_name))
|
||||
raise NotInInventory(u._('Host'), host_name)
|
||||
if host_name in self.host_props:
|
||||
prop_list += self.host_props[host_name]
|
||||
else:
|
||||
@ -204,9 +202,7 @@ class AnsibleProperties(object):
|
||||
for group_name in group_list:
|
||||
group = inventory.get_group(group_name)
|
||||
if group is None:
|
||||
raise CommandError(
|
||||
u._('Group {group} does not exist.')
|
||||
.format(group=group_name))
|
||||
raise NotInInventory(u._('Group'), group_name)
|
||||
if group_name in self.group_props:
|
||||
prop_list += self.group_props[group_name]
|
||||
else:
|
||||
@ -264,9 +260,7 @@ class AnsibleProperties(object):
|
||||
for host_name in hosts:
|
||||
host = inventory.get_host(host_name)
|
||||
if host is None:
|
||||
raise CommandError(
|
||||
u._('Host {host} does not exist.')
|
||||
.format(host=host_name))
|
||||
raise NotInInventory(u._('Host'), host_name)
|
||||
host_list.append(host)
|
||||
try:
|
||||
for host in host_list:
|
||||
@ -286,9 +280,7 @@ class AnsibleProperties(object):
|
||||
for group_name in groups:
|
||||
group = inventory.get_group(group_name)
|
||||
if group is None:
|
||||
raise CommandError(
|
||||
u._('Group {group} does not exist.')
|
||||
.format(group=group_name))
|
||||
raise NotInInventory(u._('Group'), group_name)
|
||||
group_list.append(group)
|
||||
try:
|
||||
for group in group_list:
|
||||
@ -315,9 +307,7 @@ class AnsibleProperties(object):
|
||||
for host_name in hosts:
|
||||
host = inventory.get_host(host_name)
|
||||
if host is None:
|
||||
raise CommandError(
|
||||
u._('Host {host} does not exist.')
|
||||
.format(host=host_name))
|
||||
raise NotInInventory(u._('Host'), host_name)
|
||||
host_list.append(host)
|
||||
try:
|
||||
for host in host_list:
|
||||
@ -337,9 +327,7 @@ class AnsibleProperties(object):
|
||||
for group_name in groups:
|
||||
group = inventory.get_group(group_name)
|
||||
if group is None:
|
||||
raise CommandError(
|
||||
u._('Group {group} does not exist.')
|
||||
.format(group=group_name))
|
||||
raise NotInInventory(u._('Group'), group_name)
|
||||
group_list.append(group)
|
||||
try:
|
||||
for group in group_list:
|
||||
|
@ -22,7 +22,7 @@ import sys
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.exceptions import CommandError
|
||||
from kollacli.api.exceptions import InvalidArgument
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -69,7 +69,7 @@ def get_kolla_log_file_size():
|
||||
try:
|
||||
size = int(size_str)
|
||||
except Exception:
|
||||
raise CommandError(
|
||||
raise InvalidArgument(
|
||||
u._('Environmental variable ({env_var}) is not an '
|
||||
'integer ({log_size}).')
|
||||
.format(env_var=envvar, log_size=size_str))
|
||||
@ -82,7 +82,7 @@ def get_property_list_length():
|
||||
try:
|
||||
length = int(length_str)
|
||||
except Exception:
|
||||
raise CommandError(
|
||||
raise InvalidArgument(
|
||||
u._('Environmental variable ({env_var}) is not an '
|
||||
'integer ({prop_length}).')
|
||||
.format(env_var=envvar, prop_length=length_str))
|
||||
@ -133,6 +133,8 @@ def convert_to_unicode(the_string):
|
||||
This is used to fixup extended ascii chars in strings. these chars cause
|
||||
errors in json pickle/unpickle.
|
||||
"""
|
||||
if the_string is None:
|
||||
return the_string
|
||||
return six.u(the_string)
|
||||
|
||||
|
||||
@ -265,15 +267,32 @@ def sync_write_file(path, data, mode='w'):
|
||||
raise e
|
||||
|
||||
|
||||
def safe_decode(text):
|
||||
"""Convert bytes or string to unicode string"""
|
||||
if text is not None:
|
||||
def safe_decode(obj_to_decode):
|
||||
"""Convert bytes or string to unicode string
|
||||
|
||||
Convert either a string or list of strings to
|
||||
unicode.
|
||||
"""
|
||||
if obj_to_decode is None:
|
||||
return None
|
||||
|
||||
new_obj = None
|
||||
if isinstance(obj_to_decode, list):
|
||||
new_obj = []
|
||||
for text in obj_to_decode:
|
||||
try:
|
||||
text = text.decode('utf-8')
|
||||
except AttributeError: # nosec
|
||||
# py3 will raise if text is already a string
|
||||
pass
|
||||
new_obj.append(text)
|
||||
else:
|
||||
try:
|
||||
text = text.decode('utf-8')
|
||||
new_obj = obj_to_decode.decode('utf-8')
|
||||
except AttributeError: # nosec
|
||||
# py3 will raise if text is already a string
|
||||
pass
|
||||
return text
|
||||
new_obj = obj_to_decode
|
||||
return new_obj
|
||||
|
||||
|
||||
def is_string_true(string):
|
||||
|
@ -21,11 +21,11 @@ from cliff.commandmanager import CommandManager
|
||||
|
||||
import kollacli.i18n as u
|
||||
|
||||
from kollacli.commands.exceptions import CommandError
|
||||
from kollacli.common.inventory import INVENTORY_PATH
|
||||
from kollacli.common.utils import get_kolla_log_dir
|
||||
from kollacli.common.utils import get_kolla_log_file_size
|
||||
from kollacli.common.utils import get_kollacli_etc
|
||||
from kollacli.exceptions import CommandError
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -159,7 +159,8 @@ class TestFunctional(KollaCliTest):
|
||||
|
||||
# no hostname and no file spec
|
||||
msg = self.run_cli_cmd('host setup', True)
|
||||
self.assertIn('ERROR', msg, 'No command params did not error')
|
||||
self.assertIn('ERROR', msg,
|
||||
'Setup with no command params did not error')
|
||||
|
||||
# hostname and file spec both present
|
||||
msg = self.run_cli_cmd('host setup -f zzzzz hostname', True)
|
||||
|
Loading…
Reference in New Issue
Block a user