Rewrite kolla-ansible CLI to python
Moving the CLI to python allows for easier maintenance and larger feature-set. This patch introduces a few breaking changes! The changes stem the nature of the cliff package. - the order of parameters must be kolla-ansible <action> <arguments> - mariadb_backup and mariadb_recovery now are mariadb-backup and mariadb-recovery Closes-bug: #1589020 Signed-off-by: Roman Krček <roman.krcek@tietoevry.com> Change-Id: I9749b320d4f5eeec601a055b597dfa7d8fb97ce2
This commit is contained in:
parent
66a2f5830c
commit
9ea63dc300
@ -284,13 +284,15 @@ For development:
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
cd kolla-ansible
|
pip install -e ./kolla-ansible
|
||||||
tools/kolla-ansible deploy-bifrost
|
kolla-ansible deploy-bifrost
|
||||||
|
|
||||||
|
|
||||||
For Production:
|
For Production:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
pip install -U ./kolla-ansible
|
||||||
kolla-ansible deploy-bifrost
|
kolla-ansible deploy-bifrost
|
||||||
|
|
||||||
Deploy Bifrost manually
|
Deploy Bifrost manually
|
||||||
@ -376,12 +378,14 @@ For Development:
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
tools/kolla-ansible deploy-servers
|
pip install -e ./kolla-ansible
|
||||||
|
kolla-ansible deploy-servers
|
||||||
|
|
||||||
For Production:
|
For Production:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
pip install -U ./kolla-ansible
|
||||||
kolla-ansible deploy-servers
|
kolla-ansible deploy-servers
|
||||||
|
|
||||||
Manually
|
Manually
|
||||||
|
318
kolla_ansible/ansible.py
Normal file
318
kolla_ansible/ansible.py
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
# 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
|
||||||
|
import os
|
||||||
|
import subprocess # nosec
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from kolla_ansible import utils
|
||||||
|
from typing import List
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_CONFIG_PATH = "/etc/kolla"
|
||||||
|
|
||||||
|
CONFIG_PATH_ENV = "KOLLA_CONFIG_PATH"
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def add_ansible_args(parser):
|
||||||
|
"""Add arguments required for running Ansible playbooks to a parser."""
|
||||||
|
parser.add_argument(
|
||||||
|
"-b",
|
||||||
|
"--become",
|
||||||
|
action="store_true",
|
||||||
|
help="run operations with become (nopasswd implied)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-C",
|
||||||
|
"--check",
|
||||||
|
action="store_true",
|
||||||
|
help="don't make any changes; instead, try to predict "
|
||||||
|
"some of the changes that may occur",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-D",
|
||||||
|
"--diff",
|
||||||
|
action="store_true",
|
||||||
|
help="when changing (small) files and templates, show "
|
||||||
|
"the differences in those files; works great "
|
||||||
|
"with --check",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-e",
|
||||||
|
"--extra-vars",
|
||||||
|
metavar="EXTRA_VARS",
|
||||||
|
action="append",
|
||||||
|
help="set additional variables as key=value or "
|
||||||
|
"YAML/JSON",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-i",
|
||||||
|
"--inventory",
|
||||||
|
metavar="INVENTORY",
|
||||||
|
action="append",
|
||||||
|
help="specify inventory host path ",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-l",
|
||||||
|
"--limit",
|
||||||
|
metavar="SUBSET",
|
||||||
|
help="further limit selected hosts to an additional "
|
||||||
|
"pattern",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--skip-tags",
|
||||||
|
metavar="TAGS",
|
||||||
|
help="only run plays and tasks whose tags do not "
|
||||||
|
"match these values",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-t",
|
||||||
|
"--tags",
|
||||||
|
metavar="TAGS",
|
||||||
|
help="only run plays and tasks tagged with these "
|
||||||
|
"values",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-lt",
|
||||||
|
"--list-tasks",
|
||||||
|
action="store_true",
|
||||||
|
help="only print names of tasks, don't run them, "
|
||||||
|
"note this has no affect on kolla-ansible.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-p", "--playbook",
|
||||||
|
metavar="PLAYBOOKS",
|
||||||
|
action="append",
|
||||||
|
help="Specify custom playbooks for kolla ansible "
|
||||||
|
"to use"
|
||||||
|
),
|
||||||
|
parser.add_argument(
|
||||||
|
"--vault-id",
|
||||||
|
metavar="VAULT_IDS",
|
||||||
|
action="append",
|
||||||
|
help="the vault identity to use. "
|
||||||
|
"This argument may be specified multiple times.",
|
||||||
|
default=[]
|
||||||
|
),
|
||||||
|
parser.add_argument(
|
||||||
|
"--vault-password-file",
|
||||||
|
"--vault-pass-file",
|
||||||
|
metavar="VAULT_APSSWORD_FILES",
|
||||||
|
action="append",
|
||||||
|
help="vault password file",
|
||||||
|
default=[]
|
||||||
|
),
|
||||||
|
parser.add_argument(
|
||||||
|
"-J",
|
||||||
|
"--ask-vault-password",
|
||||||
|
"--ask-vault-pass",
|
||||||
|
action="store_true",
|
||||||
|
help="ask for vault password"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def add_kolla_ansible_args(parser):
|
||||||
|
"""Add arguments required for running Kolla Ansible to a parser."""
|
||||||
|
default_config_path = os.getenv(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH)
|
||||||
|
parser.add_argument(
|
||||||
|
"--configdir",
|
||||||
|
default=default_config_path,
|
||||||
|
dest="kolla_config_path",
|
||||||
|
help="path to Kolla configuration."
|
||||||
|
"(default=$%s or %s)" % (CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--passwords",
|
||||||
|
dest="kolla_passwords",
|
||||||
|
help="Path to the kolla ansible passwords file"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_inventory_paths(parsed_args) -> List[str]:
|
||||||
|
"""Return path to the Kolla Ansible inventory."""
|
||||||
|
if parsed_args.inventory:
|
||||||
|
return parsed_args.inventory
|
||||||
|
|
||||||
|
default_inventory = os.path.join(
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path),
|
||||||
|
"ansible", "inventory", "all-in-one")
|
||||||
|
return [default_inventory]
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_args(parsed_args, playbooks: list) -> None:
|
||||||
|
"""Validate Kolla Ansible arguments."""
|
||||||
|
result = utils.is_readable_dir(
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path))
|
||||||
|
if not result["result"]:
|
||||||
|
LOG.error(
|
||||||
|
"Kolla Ansible configuration path %s is invalid: %s",
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path),
|
||||||
|
result["message"],
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
inventories = _get_inventory_paths(parsed_args)
|
||||||
|
for inventory in inventories:
|
||||||
|
result = utils.is_readable_dir(inventory)
|
||||||
|
if not result["result"]:
|
||||||
|
# NOTE(mgoddard): Previously the inventory was a file, now it is a
|
||||||
|
# directory to allow us to support inventory host_vars. Support
|
||||||
|
# both formats for now.
|
||||||
|
result_f = utils.is_readable_file(inventory)
|
||||||
|
if not result_f["result"]:
|
||||||
|
LOG.error(
|
||||||
|
"Kolla inventory %s is invalid: %s",
|
||||||
|
inventory, result["message"]
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
for playbook in playbooks:
|
||||||
|
result = utils.is_readable_file(playbook)
|
||||||
|
if not result["result"]:
|
||||||
|
LOG.error(
|
||||||
|
"Kolla Ansible playbook %s is invalid: %s",
|
||||||
|
playbook, result["message"]
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if parsed_args.kolla_passwords:
|
||||||
|
passwd_file = parsed_args.kolla_passwords
|
||||||
|
else:
|
||||||
|
passwd_file = os.path.join(
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path), "passwords.yml")
|
||||||
|
result = utils.is_readable_file(passwd_file)
|
||||||
|
if not result["result"]:
|
||||||
|
LOG.error("Kolla Ansible passwords file %s is invalid: %s",
|
||||||
|
passwd_file, result["message"])
|
||||||
|
|
||||||
|
globals_file = os.path.join(os.path.abspath(
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path)), "globals.yml")
|
||||||
|
result = utils.is_readable_file(globals_file)
|
||||||
|
if not result["result"]:
|
||||||
|
LOG.error("Kolla ansible globals file %s is invalid %s",
|
||||||
|
globals_file, result["message"])
|
||||||
|
|
||||||
|
|
||||||
|
def _get_vars_files(config_path: os.path) -> List[str]:
|
||||||
|
"""Return a list of Kolla Ansible configuration variable files.
|
||||||
|
|
||||||
|
The globals.d directory in config path is searched to create the list of
|
||||||
|
variable files. The files will be sorted alphabetically by name for each
|
||||||
|
file, but ordering of file is kept to allow overrides.
|
||||||
|
"""
|
||||||
|
vars_path = os.path.join(config_path, "globals.d")
|
||||||
|
result = utils.is_readable_dir(vars_path)
|
||||||
|
if not result["result"]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
vars_files = []
|
||||||
|
for vars_file in os.listdir(vars_path):
|
||||||
|
abs_path = os.path.join(vars_path, vars_file)
|
||||||
|
if utils.is_readable_file(abs_path)["result"]:
|
||||||
|
root, ext = os.path.splitext(vars_file)
|
||||||
|
if ext in (".yml", ".yaml", ".json"):
|
||||||
|
vars_files.append(abs_path)
|
||||||
|
|
||||||
|
return sorted(vars_files)
|
||||||
|
|
||||||
|
|
||||||
|
def build_args(parsed_args,
|
||||||
|
playbooks: list,
|
||||||
|
extra_vars: dict = {},
|
||||||
|
verbose_level: int = None) -> Tuple[str, List[str]]:
|
||||||
|
"""Build arguments required for running Ansible playbooks."""
|
||||||
|
args = list()
|
||||||
|
if verbose_level:
|
||||||
|
args += ["-" + "v" * verbose_level]
|
||||||
|
if parsed_args.list_tasks:
|
||||||
|
args += ["--list-tasks"]
|
||||||
|
inventories = _get_inventory_paths(parsed_args)
|
||||||
|
for inventory in inventories:
|
||||||
|
args += ["--inventory", inventory]
|
||||||
|
args += ["-e", "@%s" % os.path.join(
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path),
|
||||||
|
"globals.yml")]
|
||||||
|
args += ["-e", "@%s" % os.path.join(
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path),
|
||||||
|
"passwords.yml")]
|
||||||
|
for vault_id in parsed_args.vault_id:
|
||||||
|
args += ["--vault-id", vault_id]
|
||||||
|
for vault_pass_file in parsed_args.vault_password_file:
|
||||||
|
args += ["--vault-password-file", vault_pass_file]
|
||||||
|
if parsed_args.ask_vault_password:
|
||||||
|
args += "--ask-vault-password"
|
||||||
|
vars_files = _get_vars_files(
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path))
|
||||||
|
for vars_file in vars_files:
|
||||||
|
args += ["-e", "@%s" % vars_file]
|
||||||
|
if parsed_args.extra_vars:
|
||||||
|
for extra_var in parsed_args.extra_vars:
|
||||||
|
args += ["-e", extra_var]
|
||||||
|
if extra_vars:
|
||||||
|
for extra_var_name, extra_var_value in extra_vars.items():
|
||||||
|
args += ["-e", "%s=%s" % (extra_var_name, extra_var_value)]
|
||||||
|
args += ["-e", "CONFIG_DIR=%s" %
|
||||||
|
os.path.abspath(parsed_args.kolla_config_path)]
|
||||||
|
if parsed_args.become:
|
||||||
|
args += ["--become"]
|
||||||
|
if parsed_args.check:
|
||||||
|
args += ["--check"]
|
||||||
|
if parsed_args.diff:
|
||||||
|
args += ["--diff"]
|
||||||
|
if parsed_args.limit:
|
||||||
|
args += ["--limit", parsed_args.limit]
|
||||||
|
if parsed_args.skip_tags:
|
||||||
|
args += ["--skip-tags", parsed_args.skip_tags]
|
||||||
|
if parsed_args.tags:
|
||||||
|
args += ["--tags", parsed_args.tags]
|
||||||
|
args += [" ".join(playbooks)]
|
||||||
|
return ("ansible-playbook", args)
|
||||||
|
|
||||||
|
|
||||||
|
def run_playbooks(parsed_args, playbooks: list, extra_vars: dict = {},
|
||||||
|
quiet: bool = False, verbose_level: int = 0) -> None:
|
||||||
|
"""Run a Kolla Ansible playbook."""
|
||||||
|
LOG.debug("Parsed arguments: %s" % parsed_args)
|
||||||
|
_validate_args(parsed_args, playbooks)
|
||||||
|
(executable, args) = build_args(
|
||||||
|
parsed_args,
|
||||||
|
playbooks,
|
||||||
|
extra_vars=extra_vars,
|
||||||
|
verbose_level=verbose_level,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
utils.run_command(executable, args, quiet=quiet)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
LOG.error(
|
||||||
|
"Kolla Ansible playbook(s) %s exited %d", ", ".join(
|
||||||
|
playbooks), e.returncode
|
||||||
|
)
|
||||||
|
sys.exit(e.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def install_galaxy_collections(force: bool = True) -> None:
|
||||||
|
"""Install Ansible Galaxy collection dependencies.
|
||||||
|
|
||||||
|
Installs collection dependencies specified in kolla-ansible,
|
||||||
|
and if present, in kolla-ansibnle configuration.
|
||||||
|
|
||||||
|
:param force: Whether to force reinstallation of roles.
|
||||||
|
"""
|
||||||
|
requirements = utils.get_data_files_path("requirements.yml")
|
||||||
|
requirements_core = utils.get_data_files_path("requirements-core.yml")
|
||||||
|
utils.galaxy_collection_install(requirements, force=force)
|
||||||
|
utils.galaxy_collection_install(requirements_core, force=force)
|
0
kolla_ansible/cli/__init__.py
Normal file
0
kolla_ansible/cli/__init__.py
Normal file
470
kolla_ansible/cli/commands.py
Normal file
470
kolla_ansible/cli/commands.py
Normal file
@ -0,0 +1,470 @@
|
|||||||
|
# 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 cliff.command import Command
|
||||||
|
|
||||||
|
from kolla_ansible import ansible
|
||||||
|
from kolla_ansible import utils
|
||||||
|
|
||||||
|
# Serial is not recommended and disabled by default.
|
||||||
|
# Users can enable it by configuring the variable.
|
||||||
|
ANSIBLE_SERIAL = 0
|
||||||
|
|
||||||
|
|
||||||
|
def _get_playbook_path(playbook):
|
||||||
|
"""Return the absolute path of Kolla Ansible playbook"""
|
||||||
|
return utils.get_data_files_path("ansible", "%s.yml" % playbook)
|
||||||
|
|
||||||
|
|
||||||
|
def _choose_playbooks(parsed_args, kolla_playbook="site"):
|
||||||
|
"""Return user defined playbook if set, otherwise return Kolla playbook"""
|
||||||
|
if parsed_args.playbook:
|
||||||
|
playbooks = parsed_args.playbook
|
||||||
|
else:
|
||||||
|
playbooks = [_get_playbook_path(kolla_playbook)]
|
||||||
|
return playbooks
|
||||||
|
|
||||||
|
|
||||||
|
class KollaAnsibleMixin:
|
||||||
|
"""Mixin class for commands running Kolla Ansible."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(KollaAnsibleMixin, self).get_parser(prog_name)
|
||||||
|
ansible_group = parser.add_argument_group("Ansible arguments")
|
||||||
|
ka_group = parser.add_argument_group("Kolla Ansible arguments")
|
||||||
|
self.add_ansible_args(ansible_group)
|
||||||
|
self.add_kolla_ansible_args(ka_group)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def add_kolla_ansible_args(self, group):
|
||||||
|
ansible.add_kolla_ansible_args(group)
|
||||||
|
|
||||||
|
def add_ansible_args(self, group):
|
||||||
|
ansible.add_ansible_args(group)
|
||||||
|
|
||||||
|
def _get_verbosity_args(self):
|
||||||
|
"""Add quietness and verbosity level arguments."""
|
||||||
|
# Cliff's default verbosity level is 1, 0 means quiet.
|
||||||
|
verbosity_args = {}
|
||||||
|
if self.app.options.verbose_level:
|
||||||
|
ansible_verbose_level = self.app.options.verbose_level - 1
|
||||||
|
verbosity_args["verbose_level"] = ansible_verbose_level
|
||||||
|
else:
|
||||||
|
verbosity_args["quiet"] = True
|
||||||
|
return verbosity_args
|
||||||
|
|
||||||
|
def run_playbooks(self, parsed_args, *args, **kwargs):
|
||||||
|
kwargs.update(self._get_verbosity_args())
|
||||||
|
return ansible.run_playbooks(parsed_args, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class GatherFacts(KollaAnsibleMixin, Command):
|
||||||
|
"""Gather Ansible facts on hosts"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Gathering Ansible facts")
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "gather-facts")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks)
|
||||||
|
|
||||||
|
|
||||||
|
class InstallDeps(KollaAnsibleMixin, Command):
|
||||||
|
"""Install Ansible Galaxy dependencies"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Installing Ansible Galaxy dependencies")
|
||||||
|
ansible.install_galaxy_collections()
|
||||||
|
|
||||||
|
|
||||||
|
class Prechecks(KollaAnsibleMixin, Command):
|
||||||
|
"""Do pre-deployment checks for hosts"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Pre-deployment checking")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "precheck"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args,)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class GenConfig(KollaAnsibleMixin, Command):
|
||||||
|
"""Generate configuration files for services. No container changes!"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info(
|
||||||
|
"Generate configuration files for enabled OpenStack services")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "config"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class Reconfigure(KollaAnsibleMixin, Command):
|
||||||
|
"""Reconfigure enabled OpenStack service"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Reconfigure OpenStack service")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "reconfigure"
|
||||||
|
extra_vars["kolla_serial"] = ANSIBLE_SERIAL
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateConfig(KollaAnsibleMixin, Command):
|
||||||
|
"""Validate configuration files for enabled OpenStack services"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Validate configuration files for enabled "
|
||||||
|
"OpenStack services")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "config_validate"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class BootstrapServers(KollaAnsibleMixin, Command):
|
||||||
|
"""Bootstrap servers with Kolla Ansible deploy dependencies"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Bootstrapping servers")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "bootstrap-servers"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "kolla-host")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class Pull(KollaAnsibleMixin, Command):
|
||||||
|
"""Pull all images for containers. Only pulls, no container changes."""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Pulling Docker images")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "pull"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class Certificates(KollaAnsibleMixin, Command):
|
||||||
|
"""Generate self-signed certificate for TLS *For Development Only*"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Generate TLS Certificates")
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "certificates")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks)
|
||||||
|
|
||||||
|
|
||||||
|
class OctaviaCertificates(KollaAnsibleMixin, Command):
|
||||||
|
"""Generate certificates for octavia deployment"""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
group = parser.add_argument_group("Octavia certificates action")
|
||||||
|
group.add_argument(
|
||||||
|
"--check-expiry",
|
||||||
|
type=int,
|
||||||
|
help="Check if the certificates will expire "
|
||||||
|
"within given number of days",
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
extra_vars = {}
|
||||||
|
|
||||||
|
if hasattr(parsed_args, "check_expiry"):
|
||||||
|
self.app.LOG.info("Checking if certificates expire "
|
||||||
|
"within given number of days.")
|
||||||
|
extra_vars["octavia_certs_check_expiry"] = "yes"
|
||||||
|
extra_vars["octavia_certs_expiry_limit"] = parsed_args.check_expiry
|
||||||
|
else:
|
||||||
|
self.app.LOG.info("Generate octavia Certificates")
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "octavia-certificates")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class Deploy(KollaAnsibleMixin, Command):
|
||||||
|
"""Generate config, bootstrap and start all Kolla Ansible containers"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Deploying Playbooks")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "deploy"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class DeployContainers(KollaAnsibleMixin, Command):
|
||||||
|
"""Only deploy and start containers (no config updates or bootstrapping)"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Deploying Containers")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "deploy-containers"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class Postdeploy(KollaAnsibleMixin, Command):
|
||||||
|
"""Do post deploy on deploy node"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Post-Deploying Playbooks")
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "post-deploy")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks)
|
||||||
|
|
||||||
|
|
||||||
|
class Upgrade(KollaAnsibleMixin, Command):
|
||||||
|
"""Upgrades existing OpenStack Environment"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Upgrading OpenStack Environment")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "upgrade"
|
||||||
|
extra_vars["kolla_serial"] = ANSIBLE_SERIAL
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class Stop(KollaAnsibleMixin, Command):
|
||||||
|
"""Stop Kolla Ansible containers"""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
group = parser.add_argument_group("Stop action")
|
||||||
|
group.add_argument(
|
||||||
|
"--yes-i-really-really-mean-it",
|
||||||
|
action="store_true",
|
||||||
|
required=True,
|
||||||
|
help="WARNING! This action will remove the Openstack deployment!",
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Stop Kolla containers")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "stop"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args)
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class Destroy(KollaAnsibleMixin, Command):
|
||||||
|
"""Destroy Kolla Ansible containers, volumes and host configuration!"""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
group = parser.add_argument_group("Destroy action")
|
||||||
|
group.add_argument(
|
||||||
|
"--yes-i-really-really-mean-it",
|
||||||
|
action="store_true",
|
||||||
|
required=True,
|
||||||
|
help="WARNING! This action will remove the Openstack deployment!",
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--include-dev",
|
||||||
|
action="store_true",
|
||||||
|
help="Remove devevelopment environment",
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--include-images",
|
||||||
|
action="store_true",
|
||||||
|
help="Remove leftover container images",
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.warning("WARNING: This will PERMANENTLY DESTROY "
|
||||||
|
"all deployed kolla containers, volumes "
|
||||||
|
"and host configuration. There is no way "
|
||||||
|
"to recover from this action!")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "destroy"
|
||||||
|
extra_vars["destroy_include_dev"] = (
|
||||||
|
"yes" if parsed_args.include_dev else "no"
|
||||||
|
)
|
||||||
|
extra_vars["destroy_include_images"] = (
|
||||||
|
"yes" if parsed_args.include_images else "no"
|
||||||
|
)
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "destroy")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class PruneImages(KollaAnsibleMixin, Command):
|
||||||
|
"""Prune orphaned Kolla Ansible docker images"""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
group = parser.add_argument_group("Prune images action")
|
||||||
|
group.add_argument(
|
||||||
|
"--yes-i-really-really-mean-it",
|
||||||
|
action="store_true",
|
||||||
|
required=True,
|
||||||
|
help="WARNING! This action will remove all orphaned images!",
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Prune orphaned Kolla images")
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "prune-images")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks)
|
||||||
|
|
||||||
|
|
||||||
|
class BifrostDeploy(KollaAnsibleMixin, Command):
|
||||||
|
"""Deploy and start bifrost container"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Deploying Bifrost")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "deploy"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "bifrost")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class BifrostDeployServers(KollaAnsibleMixin, Command):
|
||||||
|
"""Enroll and deploy servers with bifrost"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Deploying servers with bifrost")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "deploy-servers"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "bifrost")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class BifrostUpgrade(KollaAnsibleMixin, Command):
|
||||||
|
"""Upgrades an existing bifrost container"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Upgrading Bifrost")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "upgrade"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "bifrost")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class RabbitMQResetState(KollaAnsibleMixin, Command):
|
||||||
|
"""Force reset the state of RabbitMQ"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Force reset the state of RabbitMQ")
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "rabbitmq-reset-state")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks)
|
||||||
|
|
||||||
|
|
||||||
|
class MariaDBBackup(KollaAnsibleMixin, Command):
|
||||||
|
"""Take a backup of MariaDB databases. See help for options."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
group = parser.add_argument_group("MariaDB backup type")
|
||||||
|
group.add_argument(
|
||||||
|
"--full",
|
||||||
|
action="store_const",
|
||||||
|
const="full",
|
||||||
|
dest="mariadb_backup_type",
|
||||||
|
default="full"
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--incremental",
|
||||||
|
action="store_const",
|
||||||
|
const="incremental",
|
||||||
|
dest="mariadb_backup_type"
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Backup MariaDB databases")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "backup"
|
||||||
|
extra_vars["mariadb_backup_type"] = parsed_args.mariadb_backup_type
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "mariadb_backup")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class MariaDBRecovery(KollaAnsibleMixin, Command):
|
||||||
|
"""Recover a completely stopped MariaDB cluster"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Attempting to restart MariaDB cluster")
|
||||||
|
|
||||||
|
extra_vars = {}
|
||||||
|
extra_vars["kolla_action"] = "deploy"
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "mariadb_recovery")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class NovaLibvirtCleanup(KollaAnsibleMixin, Command):
|
||||||
|
"""Clean up disabled nova_libvirt containers"""
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.info("Cleanup disabled nova_libvirt containers")
|
||||||
|
|
||||||
|
playbooks = _choose_playbooks(parsed_args, "nova-libvirt-cleanup")
|
||||||
|
|
||||||
|
self.run_playbooks(parsed_args, playbooks)
|
50
kolla_ansible/cmd/kolla_ansible.py
Normal file
50
kolla_ansible/cmd/kolla_ansible.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# 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 sys
|
||||||
|
|
||||||
|
from cliff.app import App
|
||||||
|
from cliff.commandmanager import CommandManager
|
||||||
|
|
||||||
|
from kolla_ansible import version
|
||||||
|
|
||||||
|
|
||||||
|
class KollaAnsibleApp(App):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
release_version = version.version_info.release_string()
|
||||||
|
super().__init__(
|
||||||
|
description="Kolla Ansible Command Line Interface (CLI)",
|
||||||
|
version=release_version,
|
||||||
|
command_manager=CommandManager("kolla_ansible.cli"),
|
||||||
|
deferred_help=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def initialize_app(self, argv):
|
||||||
|
self.LOG.debug("initialize_app")
|
||||||
|
|
||||||
|
def prepare_to_run_command(self, cmd):
|
||||||
|
self.LOG.debug("prepare_to_run_command %s", cmd.__class__.__name__)
|
||||||
|
|
||||||
|
def clean_up(self, cmd, result, err):
|
||||||
|
self.LOG.debug("clean_up %s", cmd.__class__.__name__)
|
||||||
|
if err:
|
||||||
|
self.LOG.debug("got an error: %s", err)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv=sys.argv[1:]):
|
||||||
|
myapp = KollaAnsibleApp()
|
||||||
|
return myapp.run(argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
173
kolla_ansible/utils.py
Normal file
173
kolla_ansible/utils.py
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
# Copyright (c) 2017 StackHPC Ltd.
|
||||||
|
#
|
||||||
|
# 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 glob
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import subprocess # nosec
|
||||||
|
import sys
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from importlib.metadata import Distribution
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_files_path(*relative_path) -> os.path:
|
||||||
|
"""Given a relative path to a data file, return the absolute path"""
|
||||||
|
# Detect editable pip install / python setup.py develop and use a path
|
||||||
|
# relative to the source directory
|
||||||
|
return os.path.join(_get_base_path(), *relative_path)
|
||||||
|
|
||||||
|
|
||||||
|
def _detect_install_prefix(path: os.path) -> str:
|
||||||
|
script_path = os.path.realpath(path)
|
||||||
|
script_path = os.path.normpath(script_path)
|
||||||
|
components = script_path.split(os.sep)
|
||||||
|
# use heuristic: anything before the last 'lib' in path is the prefix
|
||||||
|
if 'lib' not in components:
|
||||||
|
return None
|
||||||
|
last_lib = len(components) - 1 - components[::-1].index('lib')
|
||||||
|
prefix = components[:last_lib]
|
||||||
|
prefix_path = os.sep.join(prefix)
|
||||||
|
return prefix_path
|
||||||
|
|
||||||
|
|
||||||
|
def _get_direct_url(dist: Distribution) -> str:
|
||||||
|
direct_url = os.path.join(dist._path, 'direct_url.json')
|
||||||
|
if os.path.isfile(direct_url):
|
||||||
|
with open(direct_url, 'r') as f:
|
||||||
|
direct_url_content = json.loads(f.readline().strip())
|
||||||
|
url = direct_url_content['url']
|
||||||
|
prefix = 'file://'
|
||||||
|
if url.startswith(prefix):
|
||||||
|
return url[len(prefix):]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _get_base_path() -> os.path:
|
||||||
|
"""Return location where kolla-ansible package is installed."""
|
||||||
|
override = os.environ.get("KOLLA_ANSIBLE_DATA_FILES_PATH")
|
||||||
|
if override:
|
||||||
|
return os.path.join(override)
|
||||||
|
|
||||||
|
kolla_ansible_dist = list(Distribution.discover(name="kolla_ansible"))
|
||||||
|
if kolla_ansible_dist:
|
||||||
|
direct_url = _get_direct_url(kolla_ansible_dist[0])
|
||||||
|
if direct_url:
|
||||||
|
return direct_url
|
||||||
|
|
||||||
|
egg_glob = os.path.join(
|
||||||
|
sys.prefix, 'lib*', 'python*', '*-packages', 'kolla-ansible.egg-link'
|
||||||
|
)
|
||||||
|
egg_link = glob.glob(egg_glob)
|
||||||
|
if egg_link:
|
||||||
|
with open(egg_link[0], "r") as f:
|
||||||
|
realpath = f.readline().strip()
|
||||||
|
return os.path.join(realpath)
|
||||||
|
|
||||||
|
prefix = _detect_install_prefix(__file__)
|
||||||
|
if prefix:
|
||||||
|
return os.path.join(prefix, "share", "kolla-ansible")
|
||||||
|
|
||||||
|
# Assume uninstalled
|
||||||
|
return os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")
|
||||||
|
|
||||||
|
|
||||||
|
def galaxy_collection_install(requirements_file: str,
|
||||||
|
collections_path: str = None,
|
||||||
|
force: bool = False) -> None:
|
||||||
|
"""Install ansible collections needed by kolla-ansible roles."""
|
||||||
|
requirements = read_yaml_file(requirements_file)
|
||||||
|
if not isinstance(requirements, dict):
|
||||||
|
# Handle legacy role list format, which causes the command to fail.
|
||||||
|
return
|
||||||
|
args = ["collection", "install"]
|
||||||
|
if collections_path:
|
||||||
|
args += ["--collections-path", collections_path]
|
||||||
|
args += ["--requirements-file", requirements_file]
|
||||||
|
if force:
|
||||||
|
args += ["--force"]
|
||||||
|
try:
|
||||||
|
run_command("ansible-galaxy", args)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
LOG.error("Failed to install Ansible collections from %s via Ansible "
|
||||||
|
"Galaxy: returncode %d", requirements_file, e.returncode)
|
||||||
|
sys.exit(e.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def read_file(path: os.path, mode: str = "r") -> str | bytes:
|
||||||
|
"""Read the content of a file."""
|
||||||
|
with open(path, mode) as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def read_yaml_file(path: os.path):
|
||||||
|
"""Read and decode a YAML file."""
|
||||||
|
try:
|
||||||
|
content = read_file(path)
|
||||||
|
except IOError as e:
|
||||||
|
print("Failed to open YAML file %s: %s" %
|
||||||
|
(path, repr(e)))
|
||||||
|
sys.exit(1)
|
||||||
|
try:
|
||||||
|
return yaml.safe_load(content)
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
print("Failed to decode YAML file %s: %s" %
|
||||||
|
(path, repr(e)))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def is_readable_dir(path: os.path) -> bool:
|
||||||
|
"""Check whether a path references a readable directory."""
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return {"result": False, "message": "Path does not exist"}
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
return {"result": False, "message": "Path is not a directory"}
|
||||||
|
if not os.access(path, os.R_OK):
|
||||||
|
return {"result": False, "message": "Directory is not readable"}
|
||||||
|
return {"result": True}
|
||||||
|
|
||||||
|
|
||||||
|
def is_readable_file(path: os.path) -> bool:
|
||||||
|
"""Check whether a path references a readable file."""
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return {"result": False, "message": "Path does not exist"}
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
return {"result": False, "message": "Path is not a file"}
|
||||||
|
if not os.access(path, os.R_OK):
|
||||||
|
return {"result": False, "message": "File is not readable"}
|
||||||
|
return {"result": True}
|
||||||
|
|
||||||
|
|
||||||
|
def run_command(executable: str,
|
||||||
|
args: list,
|
||||||
|
quiet: bool = False,
|
||||||
|
**kwargs) -> None:
|
||||||
|
"""Run a command, checking the output.
|
||||||
|
|
||||||
|
:param quiet: Redirect output to /dev/null
|
||||||
|
"""
|
||||||
|
full_cmd = [executable] + args
|
||||||
|
cmd_string = " ".join(full_cmd)
|
||||||
|
LOG.debug("Running command: %s", cmd_string)
|
||||||
|
|
||||||
|
if quiet:
|
||||||
|
kwargs["stdout"] = subprocess.DEVNULL
|
||||||
|
kwargs["stderr"] = subprocess.DEVNULL
|
||||||
|
subprocess.run(full_cmd, shell=False, **kwargs) # nosec
|
||||||
|
else:
|
||||||
|
subprocess.run(full_cmd, shell=False, **kwargs) # nosec
|
16
releasenotes/notes/python-cli-3e568065b8706e73.yaml
Normal file
16
releasenotes/notes/python-cli-3e568065b8706e73.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Rewrite kolla-ansible CLI to python
|
||||||
|
|
||||||
|
Moving the CLI to python allows for easier
|
||||||
|
maintenance and larger feature set.
|
||||||
|
The CLI was built using the cliff package
|
||||||
|
that is used in openstack-cli and kayobe-cli.
|
||||||
|
|
||||||
|
This patch introduces a few breaking changes.
|
||||||
|
The changes stem the nature of the cliff package.
|
||||||
|
1. the order of parameters must be
|
||||||
|
kolla-ansible <action> <arguments>
|
||||||
|
2. mariadb_backup and mariadb_recovery now are
|
||||||
|
mariadb-backup and mariadb-recovery
|
@ -23,7 +23,5 @@ oslo.utils>=3.33.0 # Apache-2.0
|
|||||||
# Password hashing
|
# Password hashing
|
||||||
passlib[bcrypt]>=1.0.0 # BSD
|
passlib[bcrypt]>=1.0.0 # BSD
|
||||||
|
|
||||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
# CLI
|
||||||
|
cliff>=4.7.0 # Apache-2.0
|
||||||
# YAML parsing
|
|
||||||
PyYAML>=3.12 # MIT
|
|
||||||
|
31
setup.cfg
31
setup.cfg
@ -38,12 +38,37 @@ data_files =
|
|||||||
share/kolla-ansible = requirements.yml
|
share/kolla-ansible = requirements.yml
|
||||||
share/kolla-ansible = requirements-core.yml
|
share/kolla-ansible = requirements-core.yml
|
||||||
|
|
||||||
scripts =
|
|
||||||
tools/kolla-ansible
|
|
||||||
|
|
||||||
[entry_points]
|
[entry_points]
|
||||||
console_scripts =
|
console_scripts =
|
||||||
kolla-genpwd = kolla_ansible.cmd.genpwd:main
|
kolla-genpwd = kolla_ansible.cmd.genpwd:main
|
||||||
kolla-mergepwd = kolla_ansible.cmd.mergepwd:main
|
kolla-mergepwd = kolla_ansible.cmd.mergepwd:main
|
||||||
kolla-writepwd = kolla_ansible.cmd.writepwd:main
|
kolla-writepwd = kolla_ansible.cmd.writepwd:main
|
||||||
kolla-readpwd = kolla_ansible.cmd.readpwd:main
|
kolla-readpwd = kolla_ansible.cmd.readpwd:main
|
||||||
|
kolla-ansible = kolla_ansible.cmd.kolla_ansible:main
|
||||||
|
|
||||||
|
kolla-ansible.cli =
|
||||||
|
gather-facts = kolla_ansible.cli.commands:GatherFacts
|
||||||
|
install-deps = kolla_ansible.cli.commands:InstallDeps
|
||||||
|
prechecks = kolla_ansible.cli.commands:Prechecks
|
||||||
|
genconfig = kolla_ansible.cli.commands:GenConfig
|
||||||
|
reconfigure = kolla_ansible.cli.commands:Reconfigure
|
||||||
|
validate-config = kolla_ansible.cli.commands:ValidateConfig
|
||||||
|
bootstrap-servers = kolla_ansible.cli.commands:BootstrapServers
|
||||||
|
pull = kolla_ansible.cli.commands:Pull
|
||||||
|
certificates = kolla_ansible.cli.commands:Certificates
|
||||||
|
octavia-certificates = kolla_ansible.cli.commands:OctaviaCertificates
|
||||||
|
deploy = kolla_ansible.cli.commands:Deploy
|
||||||
|
deploy-containers = kolla_ansible.cli.commands:DeployContainers
|
||||||
|
post-deploy = kolla_ansible.cli.commands:Postdeploy
|
||||||
|
upgrade = kolla_ansible.cli.commands:Upgrade
|
||||||
|
stop = kolla_ansible.cli.commands:Stop
|
||||||
|
destroy = kolla_ansible.cli.commands:Destroy
|
||||||
|
prune-images = kolla_ansible.cli.commands:PruneImages
|
||||||
|
deploy-bifrost = kolla_ansible.cli.commands:BifrostDeploy
|
||||||
|
deploy-servers = kolla_ansible.cli.commands:BifrostDeployServers
|
||||||
|
upgrade-bifrost = kolla_ansible.cli.commands:BifrostUpgrade
|
||||||
|
rabbitmq-reset-state = kolla_ansible.cli.commands:RabbitMQResetState
|
||||||
|
mariadb-backup = kolla_ansible.cli.commands:MariaDBBackup
|
||||||
|
mariadb-recovery = kolla_ansible.cli.commands:MariaDBRecovery
|
||||||
|
nova-libvirt-cleanup = kolla_ansible.cli.commands:NovaLibvirtCleanup
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ function deploy_bifrost {
|
|||||||
# Deploy the bifrost container.
|
# Deploy the bifrost container.
|
||||||
# TODO(mgoddard): add pull action when we have a local registry service in
|
# TODO(mgoddard): add pull action when we have a local registry service in
|
||||||
# CI.
|
# CI.
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv deploy-bifrost &> /tmp/logs/ansible/deploy-bifrost
|
kolla-ansible deploy-bifrost -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/deploy-bifrost
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ function certificates {
|
|||||||
|
|
||||||
# generate self-signed certificates for the optional internal TLS tests
|
# generate self-signed certificates for the optional internal TLS tests
|
||||||
if [[ "$TLS_ENABLED" = "True" ]]; then
|
if [[ "$TLS_ENABLED" = "True" ]]; then
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv certificates > /tmp/logs/ansible/certificates
|
kolla-ansible certificates -i ${RAW_INVENTORY} -vvv > /tmp/logs/ansible/certificates
|
||||||
fi
|
fi
|
||||||
if [[ "$LE_ENABLED" = "True" ]]; then
|
if [[ "$LE_ENABLED" = "True" ]]; then
|
||||||
init_pebble
|
init_pebble
|
||||||
@ -64,13 +64,13 @@ function deploy {
|
|||||||
certificates
|
certificates
|
||||||
|
|
||||||
# Actually do the deployment
|
# Actually do the deployment
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv prechecks &> /tmp/logs/ansible/deploy-prechecks
|
kolla-ansible prechecks -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/deploy-prechecks
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv pull &> /tmp/logs/ansible/pull
|
kolla-ansible pull -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/pull
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv deploy &> /tmp/logs/ansible/deploy
|
kolla-ansible deploy -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/deploy
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv post-deploy &> /tmp/logs/ansible/post-deploy
|
kolla-ansible post-deploy -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/post-deploy
|
||||||
|
|
||||||
if [[ $HAS_UPGRADE == 'no' ]]; then
|
if [[ $HAS_UPGRADE == 'no' ]]; then
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv validate-config &> /tmp/logs/ansible/validate-config
|
kolla-ansible validate-config -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/validate-config
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ function reconfigure {
|
|||||||
if [[ $SCENARIO == "ovn" ]]; then
|
if [[ $SCENARIO == "ovn" ]]; then
|
||||||
sudo ${CONTAINER_ENGINE} rm -f ovn_nb_db ovn_sb_db && sudo ${CONTAINER_ENGINE} volume rm ovn_nb_db ovn_sb_db
|
sudo ${CONTAINER_ENGINE} rm -f ovn_nb_db ovn_sb_db && sudo ${CONTAINER_ENGINE} volume rm ovn_nb_db ovn_sb_db
|
||||||
fi
|
fi
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv prechecks &> /tmp/logs/ansible/reconfigure-prechecks
|
kolla-ansible prechecks -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/reconfigure-prechecks
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv reconfigure &> /tmp/logs/ansible/reconfigure
|
kolla-ansible reconfigure -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/reconfigure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ EOF
|
|||||||
RAW_INVENTORY=/etc/kolla/inventory
|
RAW_INVENTORY=/etc/kolla/inventory
|
||||||
|
|
||||||
source $KOLLA_ANSIBLE_VENV_PATH/bin/activate
|
source $KOLLA_ANSIBLE_VENV_PATH/bin/activate
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv bootstrap-servers &> /tmp/logs/ansible/bootstrap-servers
|
kolla-ansible bootstrap-servers -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/bootstrap-servers
|
||||||
deactivate
|
deactivate
|
||||||
|
|
||||||
prepare_images
|
prepare_images
|
||||||
|
@ -125,7 +125,7 @@ EOF
|
|||||||
deactivate
|
deactivate
|
||||||
source $KOLLA_ANSIBLE_VENV_PATH/bin/activate
|
source $KOLLA_ANSIBLE_VENV_PATH/bin/activate
|
||||||
echo 'designate_enable_notifications_sink: "yes"' >> /etc/kolla/globals.yml
|
echo 'designate_enable_notifications_sink: "yes"' >> /etc/kolla/globals.yml
|
||||||
kolla-ansible -i ${RAW_INVENTORY} --tags designate,nova,nova-cell,neutron -vvv reconfigure &> /tmp/logs/ansible/reconfigure-designate
|
kolla-ansible reconfigure -i ${RAW_INVENTORY} --tags designate,nova,nova-cell,neutron -vvv &> /tmp/logs/ansible/reconfigure-designate
|
||||||
deactivate
|
deactivate
|
||||||
source ~/openstackclient-venv/bin/activate
|
source ~/openstackclient-venv/bin/activate
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ export PYTHONUNBUFFERED=1
|
|||||||
|
|
||||||
function mariadb_stop {
|
function mariadb_stop {
|
||||||
echo "Stopping the database cluster"
|
echo "Stopping the database cluster"
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv stop --yes-i-really-really-mean-it --tags mariadb --skip-tags common
|
kolla-ansible stop -i ${RAW_INVENTORY} -vvv --yes-i-really-really-mean-it --tags mariadb --skip-tags common
|
||||||
if [[ $(sudo ${container_engine} ps -q | grep mariadb | wc -l) -ne 0 ]]; then
|
if [[ $(sudo ${container_engine} ps -q | grep mariadb | wc -l) -ne 0 ]]; then
|
||||||
echo "Failed to stop MariaDB cluster"
|
echo "Failed to stop MariaDB cluster"
|
||||||
return 1
|
return 1
|
||||||
@ -21,7 +21,7 @@ function mariadb_stop {
|
|||||||
function mariadb_recovery {
|
function mariadb_recovery {
|
||||||
# Recover the database cluster.
|
# Recover the database cluster.
|
||||||
echo "Recovering the database cluster"
|
echo "Recovering the database cluster"
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv mariadb_recovery --tags mariadb --skip-tags common
|
kolla-ansible mariadb-recovery -i ${RAW_INVENTORY} -vvv --tags mariadb --skip-tags common
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_recovery {
|
function test_recovery {
|
||||||
@ -32,7 +32,7 @@ function test_recovery {
|
|||||||
|
|
||||||
function test_backup {
|
function test_backup {
|
||||||
echo "Performing full backup"
|
echo "Performing full backup"
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv mariadb_backup --full
|
kolla-ansible mariadb-backup -i ${RAW_INVENTORY} -vvv --full
|
||||||
# Sleep for 30 seconds, not because it's absolutely necessary.
|
# Sleep for 30 seconds, not because it's absolutely necessary.
|
||||||
# The full backup is already completed at this point, as the
|
# The full backup is already completed at this point, as the
|
||||||
# ansible job is waiting for the completion of the backup script
|
# ansible job is waiting for the completion of the backup script
|
||||||
@ -42,7 +42,7 @@ function test_backup {
|
|||||||
# data gets written within those 30 seconds.
|
# data gets written within those 30 seconds.
|
||||||
echo "Sleeping for 30 seconds"
|
echo "Sleeping for 30 seconds"
|
||||||
sleep 30
|
sleep 30
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv mariadb_backup --incremental
|
kolla-ansible mariadb-backup -i ${RAW_INVENTORY} -vvv --incremental
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_backup_with_retries {
|
function test_backup_with_retries {
|
||||||
|
@ -17,7 +17,7 @@ function upgrade_bifrost {
|
|||||||
# CI.
|
# CI.
|
||||||
# TODO(mgoddard): make some configuration file changes and trigger a real
|
# TODO(mgoddard): make some configuration file changes and trigger a real
|
||||||
# upgrade.
|
# upgrade.
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv deploy-bifrost &> /tmp/logs/ansible/upgrade-bifrost
|
kolla-ansible deploy-bifrost -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/upgrade-bifrost
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,14 +12,14 @@ function upgrade {
|
|||||||
|
|
||||||
source $KOLLA_ANSIBLE_VENV_PATH/bin/activate
|
source $KOLLA_ANSIBLE_VENV_PATH/bin/activate
|
||||||
|
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv certificates &> /tmp/logs/ansible/certificates
|
kolla-ansible certificates -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/certificates
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv prechecks &> /tmp/logs/ansible/upgrade-prechecks
|
kolla-ansible prechecks -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/upgrade-prechecks
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv pull &> /tmp/logs/ansible/pull-upgrade
|
kolla-ansible pull -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/pull-upgrade
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv upgrade &> /tmp/logs/ansible/upgrade
|
kolla-ansible upgrade -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/upgrade
|
||||||
|
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv post-deploy &> /tmp/logs/ansible/upgrade-post-deploy
|
kolla-ansible post-deploy -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/upgrade-post-deploy
|
||||||
|
|
||||||
kolla-ansible -i ${RAW_INVENTORY} -vvv validate-config &> /tmp/logs/ansible/validate-config
|
kolla-ansible validate-config -i ${RAW_INVENTORY} -vvv &> /tmp/logs/ansible/validate-config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,608 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# This script can be used to interact with kolla via ansible.
|
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
|
|
||||||
# do not use _PYTHON_BIN directly, use $(get_python_bin) instead
|
|
||||||
_PYTHON_BIN=""
|
|
||||||
|
|
||||||
ANSIBLE_VERSION_MIN=2.16
|
|
||||||
ANSIBLE_VERSION_MAX=2.17
|
|
||||||
|
|
||||||
function get_python_bin {
|
|
||||||
if [ -n "$_PYTHON_BIN" ]; then
|
|
||||||
echo -n "$_PYTHON_BIN"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
local ansible_path
|
|
||||||
ansible_path=$(which ansible)
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "ERROR: Ansible is not installed in the current (virtual) environment." >&2
|
|
||||||
echo "Ansible version should be between $ANSIBLE_VERSION_MIN and $ANSIBLE_VERSION_MAX." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local ansible_shebang_line
|
|
||||||
ansible_shebang_line=$(head -n1 "$ansible_path")
|
|
||||||
|
|
||||||
if ! echo "$ansible_shebang_line" | egrep "^#!" &>/dev/null; then
|
|
||||||
echo "ERROR: Ansible script is malformed (missing shebang line)." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# NOTE(yoctozepto): may have multiple parts
|
|
||||||
_PYTHON_BIN=${ansible_shebang_line#\#\!}
|
|
||||||
echo -n "$_PYTHON_BIN"
|
|
||||||
}
|
|
||||||
|
|
||||||
function check_environment_coherence {
|
|
||||||
local ansible_python_cmdline
|
|
||||||
ansible_python_cmdline=$(get_python_bin)
|
|
||||||
ansible_python_version=$($ansible_python_cmdline -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')
|
|
||||||
|
|
||||||
if ! $ansible_python_cmdline --version &>/dev/null; then
|
|
||||||
echo "ERROR: Ansible Python is not functional." >&2
|
|
||||||
echo "Tried '$ansible_python_cmdline'" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for existence of kolla_ansible module using Ansible's Python.
|
|
||||||
if ! $ansible_python_cmdline -c 'import kolla_ansible' &>/dev/null; then
|
|
||||||
echo "ERROR: kolla_ansible has to be available in the Ansible PYTHONPATH." >&2
|
|
||||||
echo "Please install both in the same (virtual) environment." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local ansible_full_version
|
|
||||||
ansible_full_version=$($ansible_python_cmdline -c 'import ansible; print(ansible.__version__)')
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "ERROR: Failed to obtain Ansible version:" >&2
|
|
||||||
echo "$ansible_full_version" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local ansible_version
|
|
||||||
ansible_version=$(echo "$ansible_full_version" | egrep -o '^[0-9]+\.[0-9]+')
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "ERROR: Failed to parse Ansible version:" >&2
|
|
||||||
echo "$ansible_full_version" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [[ $(printf "%s\n" "$ANSIBLE_VERSION_MIN" "$ANSIBLE_VERSION_MAX" "$ansible_version" | sort -V | head -n1) != "$ANSIBLE_VERSION_MIN" ]] ||
|
|
||||||
[[ $(printf "%s\n" "$ANSIBLE_VERSION_MIN" "$ANSIBLE_VERSION_MAX" "$ansible_version" | sort -V | tail -n1) != "$ANSIBLE_VERSION_MAX" ]]; then
|
|
||||||
echo "ERROR: Ansible version should be between $ANSIBLE_VERSION_MIN and $ANSIBLE_VERSION_MAX. Current version is $ansible_full_version which is not supported."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function find_base_dir {
|
|
||||||
local dir_name
|
|
||||||
local python_dir
|
|
||||||
dir_name=$(dirname "$0")
|
|
||||||
# NOTE(yoctozepto): Fix the case where dir_name is a symlink and VIRTUAL_ENV might not be. This
|
|
||||||
# happens with pyenv-virtualenv, see https://bugs.launchpad.net/kolla-ansible/+bug/1903887
|
|
||||||
dir_name=$(readlink -e "$dir_name")
|
|
||||||
python_dir="python${ansible_python_version}"
|
|
||||||
if [ -z "$SNAP" ]; then
|
|
||||||
if [[ ${dir_name} == "/usr/bin" ]]; then
|
|
||||||
if test -f /usr/lib/${python_dir}/*-packages/kolla-ansible.egg-link; then
|
|
||||||
# Editable install.
|
|
||||||
BASEDIR="$(head -n1 /usr/lib/${python_dir}/*-packages/kolla-ansible.egg-link)"
|
|
||||||
else
|
|
||||||
BASEDIR=/usr/share/kolla-ansible
|
|
||||||
fi
|
|
||||||
elif [[ ${dir_name} == "/usr/local/bin" ]]; then
|
|
||||||
if test -f /usr/local/lib/${python_dir}/*-packages/kolla-ansible.egg-link; then
|
|
||||||
# Editable install.
|
|
||||||
BASEDIR="$(head -n1 /usr/local/lib/${python_dir}/*-packages/kolla-ansible.egg-link)"
|
|
||||||
else
|
|
||||||
BASEDIR=/usr/local/share/kolla-ansible
|
|
||||||
fi
|
|
||||||
elif [[ ${dir_name} == ~/.local/bin ]]; then
|
|
||||||
if test -f ~/.local/lib/${python_dir}/*-packages/kolla-ansible.egg-link; then
|
|
||||||
# Editable install.
|
|
||||||
BASEDIR="$(head -n1 ~/.local/lib/${python_dir}/*-packages/kolla-ansible.egg-link)"
|
|
||||||
else
|
|
||||||
BASEDIR=~/.local/share/kolla-ansible
|
|
||||||
fi
|
|
||||||
elif [[ -n ${VIRTUAL_ENV} ]] && [[ ${dir_name} == "$(readlink -e "${VIRTUAL_ENV}/bin")" ]]; then
|
|
||||||
if test -f ${VIRTUAL_ENV}/lib/${python_dir}/site-packages/kolla-ansible.egg-link; then
|
|
||||||
# Editable install.
|
|
||||||
BASEDIR="$(head -n1 ${VIRTUAL_ENV}/lib/${python_dir}/*-packages/kolla-ansible.egg-link)"
|
|
||||||
else
|
|
||||||
BASEDIR="${VIRTUAL_ENV}/share/kolla-ansible"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Running from sources (repo).
|
|
||||||
BASEDIR="$(dirname ${dir_name})"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
BASEDIR="$SNAP/share/kolla-ansible"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function install_deps {
|
|
||||||
echo "Installing Ansible Galaxy dependencies"
|
|
||||||
if pip show ansible 2>/dev/null; then
|
|
||||||
ansible-galaxy collection install -r ${BASEDIR}/requirements.yml --force
|
|
||||||
else
|
|
||||||
ansible-galaxy collection install -r ${BASEDIR}/requirements.yml --force
|
|
||||||
ansible-galaxy collection install -r ${BASEDIR}/requirements-core.yml --force
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "ERROR: Failed to install Ansible Galaxy dependencies" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function process_cmd {
|
|
||||||
echo "$ACTION : $CMD"
|
|
||||||
$CMD
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "Command failed $CMD"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function usage {
|
|
||||||
cat <<EOF
|
|
||||||
Usage: $0 COMMAND [options]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--inventory, -i <inventory_path> Specify path to ansible inventory file. \
|
|
||||||
Can be specified multiple times to pass multiple inventories.
|
|
||||||
--playbook, -p <playbook_path> Specify path to ansible playbook file
|
|
||||||
--configdir <config_path> Specify path to directory with globals.yml
|
|
||||||
--key -k <key_path> Specify path to ansible vault keyfile
|
|
||||||
--help, -h Show this usage information
|
|
||||||
--tags, -t <tags> Only run plays and tasks tagged with these values
|
|
||||||
--skip-tags <tags> Only run plays and tasks whose tags do not match these values
|
|
||||||
--extra, -e <ansible variables> Set additional variables as key=value or YAML/JSON passed to ansible-playbook
|
|
||||||
--passwords <passwords_path> Specify path to the passwords file
|
|
||||||
--limit <host> Specify host to run plays
|
|
||||||
--forks <forks> Number of forks to run Ansible with
|
|
||||||
--vault-id <@prompt or path> Specify @prompt or password file (Ansible >= 2.4)
|
|
||||||
--ask-vault-pass Ask for vault password
|
|
||||||
--vault-password-file <path> Specify password file for vault decrypt
|
|
||||||
--check, -C Don't make any changes and try to predict some of the changes that may occur instead
|
|
||||||
--diff, -D Show differences in ansible-playbook changed tasks
|
|
||||||
--verbose, -v Increase verbosity of ansible-playbook
|
|
||||||
--version Show version
|
|
||||||
|
|
||||||
Environment variables:
|
|
||||||
EXTRA_OPTS Additional arguments to pass to ansible-playbook
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
install-deps Install Ansible Galaxy dependencies
|
|
||||||
prechecks Do pre-deployment checks for hosts
|
|
||||||
mariadb_recovery Recover a completely stopped mariadb cluster
|
|
||||||
mariadb_backup Take a backup of MariaDB databases
|
|
||||||
--full (default)
|
|
||||||
--incremental
|
|
||||||
bootstrap-servers Bootstrap servers with kolla deploy dependencies
|
|
||||||
destroy Destroy Kolla containers, volumes and host configuration
|
|
||||||
--include-images to also destroy Kolla images
|
|
||||||
--include-dev to also destroy dev mode repos
|
|
||||||
deploy Deploy and start all kolla containers
|
|
||||||
deploy-bifrost Deploy and start bifrost container
|
|
||||||
deploy-servers Enroll and deploy servers with bifrost
|
|
||||||
deploy-containers Only deploy and start containers (no config updates or bootstrapping)
|
|
||||||
gather-facts Gather Ansible facts
|
|
||||||
post-deploy Do post deploy on deploy node
|
|
||||||
pull Pull all images for containers (only pulls, no running container changes)
|
|
||||||
rabbitmq-reset-state Force reset the state of RabbitMQ
|
|
||||||
rabbitmq-upgrade <version> Upgrade to a specific version of RabbitMQ
|
|
||||||
reconfigure Reconfigure OpenStack service
|
|
||||||
stop Stop Kolla containers
|
|
||||||
certificates Generate self-signed certificate for TLS *For Development Only*
|
|
||||||
octavia-certificates Generate certificates for octavia deployment
|
|
||||||
--check-expiry <days> to check if certificates expire within that many days
|
|
||||||
upgrade Upgrades existing OpenStack Environment
|
|
||||||
upgrade-bifrost Upgrades an existing bifrost container
|
|
||||||
genconfig Generate configuration files for enabled OpenStack services
|
|
||||||
validate-config Validate configuration files for enabled OpenStack services
|
|
||||||
prune-images Prune orphaned Kolla images
|
|
||||||
nova-libvirt-cleanup Clean up disabled nova_libvirt containers
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
function bash_completion {
|
|
||||||
cat <<EOF
|
|
||||||
--inventory -i
|
|
||||||
--playbook -p
|
|
||||||
--configdir
|
|
||||||
--key -k
|
|
||||||
--help -h
|
|
||||||
--skip-tags
|
|
||||||
--tags -t
|
|
||||||
--extra -e
|
|
||||||
--passwords
|
|
||||||
--limit
|
|
||||||
--forks
|
|
||||||
--vault-id
|
|
||||||
--ask-vault-pass
|
|
||||||
--vault-password-file
|
|
||||||
--check -C
|
|
||||||
--diff -D
|
|
||||||
--verbose -v
|
|
||||||
--version
|
|
||||||
install-deps
|
|
||||||
prechecks
|
|
||||||
mariadb_recovery
|
|
||||||
mariadb_backup
|
|
||||||
bootstrap-servers
|
|
||||||
destroy
|
|
||||||
deploy
|
|
||||||
deploy-bifrost
|
|
||||||
deploy-containers
|
|
||||||
deploy-servers
|
|
||||||
gather-facts
|
|
||||||
post-deploy
|
|
||||||
pull
|
|
||||||
rabbitmq-reset-state
|
|
||||||
rabbitmq-upgrade
|
|
||||||
reconfigure
|
|
||||||
stop
|
|
||||||
certificates
|
|
||||||
octavia-certificates
|
|
||||||
upgrade
|
|
||||||
upgrade-bifrost
|
|
||||||
genconfig
|
|
||||||
validate-config
|
|
||||||
prune-images
|
|
||||||
nova-libvirt-cleanup
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
function version {
|
|
||||||
local python_bin
|
|
||||||
python_bin=$(get_python_bin)
|
|
||||||
|
|
||||||
$python_bin -c 'from kolla_ansible.version import version_info; print(version_info)'
|
|
||||||
}
|
|
||||||
|
|
||||||
check_environment_coherence
|
|
||||||
|
|
||||||
SHORT_OPTS="hi:p:t:k:e:CD:v"
|
|
||||||
LONG_OPTS="help,version,inventory:,playbook:,skip-tags:,tags:,key:,extra:,check,diff,verbose,configdir:,passwords:,limit:,forks:,vault-id:,ask-vault-pass,vault-password-file:,yes-i-really-really-mean-it,include-images,include-dev:,full,incremental,check-expiry:"
|
|
||||||
|
|
||||||
RAW_ARGS="$*"
|
|
||||||
ARGS=$(getopt -o "${SHORT_OPTS}" -l "${LONG_OPTS}" --name "$0" -- "$@") || { usage >&2; exit 2; }
|
|
||||||
|
|
||||||
eval set -- "$ARGS"
|
|
||||||
|
|
||||||
find_base_dir
|
|
||||||
|
|
||||||
INVENTORY="${BASEDIR}/ansible/inventory/all-in-one"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/site.yml"
|
|
||||||
VERBOSITY=
|
|
||||||
EXTRA_OPTS=${EXTRA_OPTS}
|
|
||||||
CONFIG_DIR="/etc/kolla"
|
|
||||||
DANGER_CONFIRM=
|
|
||||||
INCLUDE_IMAGES=
|
|
||||||
INCLUDE_DEV=
|
|
||||||
BACKUP_TYPE="full"
|
|
||||||
OCTAVIA_CERTS_EXPIRY=
|
|
||||||
# Serial is not recommended and disabled by default. Users can enable it by
|
|
||||||
# configuring ANSIBLE_SERIAL variable.
|
|
||||||
ANSIBLE_SERIAL=${ANSIBLE_SERIAL:-0}
|
|
||||||
INVENTORIES=()
|
|
||||||
|
|
||||||
while [ "$#" -gt 0 ]; do
|
|
||||||
case "$1" in
|
|
||||||
|
|
||||||
(--inventory|-i)
|
|
||||||
INVENTORIES+=("$2")
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--playbook|-p)
|
|
||||||
PLAYBOOK="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--skip-tags)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --skip-tags $2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--tags|-t)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --tags $2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--check|-C)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --check"
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--diff|-D)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --diff"
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--verbose|-v)
|
|
||||||
VERBOSITY="$VERBOSITY --verbose"
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--configdir)
|
|
||||||
CONFIG_DIR="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--yes-i-really-really-mean-it)
|
|
||||||
if [[ ${RAW_ARGS} =~ "$1" ]]
|
|
||||||
then
|
|
||||||
DANGER_CONFIRM="$1"
|
|
||||||
fi
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--include-images)
|
|
||||||
INCLUDE_IMAGES="$1"
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--include-dev)
|
|
||||||
INCLUDE_DEV="$1"
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--key|-k)
|
|
||||||
VAULT_PASS_FILE="$2"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --vault-password-file=$VAULT_PASS_FILE"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--extra|-e)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e $2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--passwords)
|
|
||||||
PASSWORDS_FILE="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--limit)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --limit $2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--forks)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --forks $2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--vault-id)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --vault-id $2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--ask-vault-pass)
|
|
||||||
VERBOSITY="$EXTRA_OPTS --ask-vault-pass"
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--vault-password-file)
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS --vault-password-file $2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--full)
|
|
||||||
BACKUP_TYPE="full"
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--incremental)
|
|
||||||
BACKUP_TYPE="incremental"
|
|
||||||
shift 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--check-expiry)
|
|
||||||
OCTAVIA_CERTS_EXPIRY="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--version)
|
|
||||||
version
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--help|-h)
|
|
||||||
usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
|
|
||||||
(--)
|
|
||||||
shift
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
|
|
||||||
(*)
|
|
||||||
echo "error"
|
|
||||||
exit 3
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
|
|
||||||
(install-deps)
|
|
||||||
install_deps
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
(prechecks)
|
|
||||||
ACTION="Pre-deployment checking"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=precheck"
|
|
||||||
;;
|
|
||||||
(mariadb_recovery)
|
|
||||||
ACTION="Attempting to restart mariadb cluster"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/mariadb_recovery.yml"
|
|
||||||
;;
|
|
||||||
(mariadb_backup)
|
|
||||||
ACTION="Backup MariaDB databases"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=backup -e mariadb_backup_type=${BACKUP_TYPE}"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/mariadb_backup.yml"
|
|
||||||
;;
|
|
||||||
(destroy)
|
|
||||||
ACTION="Destroy Kolla containers, volumes and host configuration"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/destroy.yml"
|
|
||||||
|
|
||||||
INVENTORIES_COMMA_SEPARATED=""
|
|
||||||
for INVENTORY in ${INVENTORIES[@]}; do
|
|
||||||
INVENTORIES_COMMA_SEPARATED="${INVENTORIES_COMMA_SEPARATED},${INVENTORY}"
|
|
||||||
done
|
|
||||||
INVENTORIES_COMMA_SEPARATED=$(echo "${INVENTORIES_COMMA_SEPARATED}" | sed -e 's/^,//g')
|
|
||||||
|
|
||||||
if [[ "${INCLUDE_IMAGES}" == "--include-images" ]]; then
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e destroy_include_images=yes"
|
|
||||||
fi
|
|
||||||
if [[ "${INCLUDE_DEV}" == "--include-dev" ]]; then
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e destroy_include_dev=yes"
|
|
||||||
fi
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e inventories_comma_separated=${INVENTORIES_COMMA_SEPARATED}"
|
|
||||||
if [[ "${DANGER_CONFIRM}" != "--yes-i-really-really-mean-it" ]]; then
|
|
||||||
cat << EOF
|
|
||||||
WARNING:
|
|
||||||
This will PERMANENTLY DESTROY all deployed kolla containers, volumes and host configuration.
|
|
||||||
There is no way to recover from this action. To confirm, please add the following option:
|
|
||||||
--yes-i-really-really-mean-it
|
|
||||||
EOF
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
(bootstrap-servers)
|
|
||||||
ACTION="Bootstrapping servers"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/kolla-host.yml"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=bootstrap-servers"
|
|
||||||
;;
|
|
||||||
(deploy)
|
|
||||||
ACTION="Deploying Playbooks"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
|
|
||||||
;;
|
|
||||||
(deploy-bifrost)
|
|
||||||
ACTION="Deploying Bifrost"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/bifrost.yml"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
|
|
||||||
;;
|
|
||||||
(deploy-containers)
|
|
||||||
ACTION="Deploying Containers"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy-containers"
|
|
||||||
;;
|
|
||||||
(deploy-servers)
|
|
||||||
ACTION="Deploying servers with bifrost"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/bifrost.yml"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy-servers"
|
|
||||||
;;
|
|
||||||
(gather-facts)
|
|
||||||
ACTION="Gathering Ansible facts"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/gather-facts.yml"
|
|
||||||
;;
|
|
||||||
(post-deploy)
|
|
||||||
ACTION="Post-Deploying Playbooks"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/post-deploy.yml"
|
|
||||||
;;
|
|
||||||
(pull)
|
|
||||||
ACTION="Pulling Docker images"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=pull"
|
|
||||||
;;
|
|
||||||
(upgrade)
|
|
||||||
ACTION="Upgrading OpenStack Environment"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=upgrade -e kolla_serial=${ANSIBLE_SERIAL}"
|
|
||||||
;;
|
|
||||||
(upgrade-bifrost)
|
|
||||||
ACTION="Upgrading Bifrost"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/bifrost.yml"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=upgrade"
|
|
||||||
;;
|
|
||||||
(reconfigure)
|
|
||||||
ACTION="Reconfigure OpenStack service"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=reconfigure -e kolla_serial=${ANSIBLE_SERIAL}"
|
|
||||||
;;
|
|
||||||
(stop)
|
|
||||||
ACTION="Stop Kolla containers"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=stop"
|
|
||||||
if [[ "${DANGER_CONFIRM}" != "--yes-i-really-really-mean-it" ]]; then
|
|
||||||
cat << EOF
|
|
||||||
WARNING:
|
|
||||||
This will stop all deployed kolla containers, limit with tags is possible and also with
|
|
||||||
skip_stop_containers variable. To confirm, please add the following option:
|
|
||||||
--yes-i-really-really-mean-it
|
|
||||||
EOF
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
(certificates)
|
|
||||||
ACTION="Generate TLS Certificates"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/certificates.yml"
|
|
||||||
;;
|
|
||||||
(octavia-certificates)
|
|
||||||
ACTION="Generate octavia Certificates"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/octavia-certificates.yml"
|
|
||||||
if [[ ! -z "${OCTAVIA_CERTS_EXPIRY}" ]]; then
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e octavia_certs_check_expiry=yes -e octavia_certs_expiry_limit=${OCTAVIA_CERTS_EXPIRY}"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
(genconfig)
|
|
||||||
ACTION="Generate configuration files for enabled OpenStack services"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=config"
|
|
||||||
;;
|
|
||||||
(validate-config)
|
|
||||||
ACTION="Validate configuration files for enabled OpenStack services"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=config_validate"
|
|
||||||
;;
|
|
||||||
(prune-images)
|
|
||||||
ACTION="Prune orphaned Kolla images"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/prune-images.yml"
|
|
||||||
if [[ "${DANGER_CONFIRM}" != "--yes-i-really-really-mean-it" ]]; then
|
|
||||||
cat << EOF
|
|
||||||
WARNING:
|
|
||||||
This will PERMANENTLY DELETE all orphaned kolla images. To confirm, please add the following option:
|
|
||||||
--yes-i-really-really-mean-it
|
|
||||||
EOF
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
(nova-libvirt-cleanup)
|
|
||||||
ACTION="Cleanup disabled nova_libvirt containers"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/nova-libvirt-cleanup.yml"
|
|
||||||
;;
|
|
||||||
(rabbitmq-reset-state)
|
|
||||||
ACTION="Force reset the state of RabbitMQ"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/rabbitmq-reset-state.yml"
|
|
||||||
;;
|
|
||||||
(rabbitmq-upgrade)
|
|
||||||
RMQ_VERSION="$2"
|
|
||||||
ACTION="Upgrade to a specific version of RabbitMQ"
|
|
||||||
PLAYBOOK="${BASEDIR}/ansible/rabbitmq-upgrade.yml"
|
|
||||||
EXTRA_OPTS="$EXTRA_OPTS -e rabbitmq_version_suffix=${RMQ_VERSION}"
|
|
||||||
;;
|
|
||||||
(bash-completion)
|
|
||||||
bash_completion
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
(*) usage
|
|
||||||
exit 3
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
GLOBALS_DIR="${CONFIG_DIR}/globals.d"
|
|
||||||
EXTRA_GLOBALS=$([ -d "${GLOBALS_DIR}" ] && find ${GLOBALS_DIR} -maxdepth 1 -type f -name '*.yml' -printf ' -e @%p' || true 2>/dev/null)
|
|
||||||
PASSWORDS_FILE="${PASSWORDS_FILE:-${CONFIG_DIR}/passwords.yml}"
|
|
||||||
CONFIG_OPTS="-e @${CONFIG_DIR}/globals.yml ${EXTRA_GLOBALS} -e @${PASSWORDS_FILE} -e CONFIG_DIR=${CONFIG_DIR}"
|
|
||||||
CMD="ansible-playbook $CONFIG_OPTS $EXTRA_OPTS $PLAYBOOK $VERBOSITY"
|
|
||||||
for INVENTORY in ${INVENTORIES[@]}; do
|
|
||||||
CMD="${CMD} --inventory $INVENTORY"
|
|
||||||
done
|
|
||||||
process_cmd
|
|
Loading…
Reference in New Issue
Block a user