174 lines
7.3 KiB
Python
174 lines
7.3 KiB
Python
# 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 logging
|
|
import os
|
|
import os.path
|
|
import subprocess
|
|
import sys
|
|
|
|
from kayobe import utils
|
|
from kayobe import vault
|
|
|
|
|
|
DEFAULT_CONFIG_PATH = "/etc/kolla"
|
|
|
|
CONFIG_PATH_ENV = "KOLLA_CONFIG_PATH"
|
|
|
|
DEFAULT_VENV_PATH = "venvs/kolla-ansible"
|
|
|
|
VENV_PATH_ENV = "KOLLA_VENV_PATH"
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def add_args(parser):
|
|
"""Add arguments required for running Kolla Ansible to a parser."""
|
|
# $KOLLA_CONFIG_PATH or /etc/kolla.
|
|
default_config_path = os.getenv(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH)
|
|
# $KOLLA_VENV_PATH or $PWD/venvs/kolla-ansible
|
|
default_venv = os.getenv(VENV_PATH_ENV,
|
|
os.path.join(os.getcwd(), DEFAULT_VENV_PATH))
|
|
parser.add_argument("--kolla-config-path", default=default_config_path,
|
|
help="path to Kolla configuration. "
|
|
"(default=$%s or %s)" %
|
|
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
|
|
parser.add_argument("-ke", "--kolla-extra-vars", metavar="EXTRA_VARS",
|
|
action="append",
|
|
help="set additional variables as key=value or "
|
|
"YAML/JSON for Kolla Ansible")
|
|
parser.add_argument("-ki", "--kolla-inventory", metavar="INVENTORY",
|
|
help="specify inventory host path "
|
|
"(default=$%s/inventory or %s/inventory) or "
|
|
"comma-separated host list for Kolla Ansible" %
|
|
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
|
|
parser.add_argument("-kl", "--kolla-limit", metavar="SUBSET",
|
|
help="further limit selected hosts to an additional "
|
|
"pattern")
|
|
parser.add_argument("--kolla-skip-tags", metavar="TAGS",
|
|
help="only run plays and tasks whose tags do not "
|
|
"match these values in Kolla Ansible")
|
|
parser.add_argument("-kt", "--kolla-tags", metavar="TAGS",
|
|
help="only run plays and tasks tagged with these "
|
|
"values in Kolla Ansible")
|
|
parser.add_argument("--kolla-venv", metavar="VENV", default=default_venv,
|
|
help="path to virtualenv where Kolla Ansible is "
|
|
"installed (default=$%s or $PWD/%s)" %
|
|
(VENV_PATH_ENV, DEFAULT_VENV_PATH))
|
|
|
|
|
|
def _get_inventory_path(parsed_args, inventory_filename):
|
|
"""Return the path to the Kolla inventory."""
|
|
if parsed_args.kolla_inventory:
|
|
return parsed_args.kolla_inventory
|
|
else:
|
|
return os.path.join(parsed_args.kolla_config_path, "inventory",
|
|
inventory_filename)
|
|
|
|
|
|
def _validate_args(parsed_args, inventory_filename):
|
|
"""Validate Kayobe Ansible arguments."""
|
|
vault.validate_args(parsed_args)
|
|
result = utils.is_readable_dir(parsed_args.kolla_config_path)
|
|
if not result["result"]:
|
|
LOG.error("Kolla configuration path %s is invalid: %s",
|
|
parsed_args.kolla_config_path, result["message"])
|
|
sys.exit(1)
|
|
|
|
inventory = _get_inventory_path(parsed_args, inventory_filename)
|
|
result = utils.is_readable_dir(parsed_args.kolla_venv)
|
|
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)
|
|
|
|
result = utils.is_readable_dir(parsed_args.kolla_venv)
|
|
if not result["result"]:
|
|
LOG.error("Kolla virtualenv %s is invalid: %s",
|
|
parsed_args.kolla_venv, result["message"])
|
|
sys.exit(1)
|
|
|
|
|
|
def build_args(parsed_args, command, inventory_filename, extra_vars=None,
|
|
tags=None, verbose_level=None, extra_args=None, limit=None):
|
|
"""Build arguments required for running Kolla Ansible."""
|
|
venv_activate = os.path.join(parsed_args.kolla_venv, "bin", "activate")
|
|
cmd = [".", venv_activate, "&&"]
|
|
cmd += ["kolla-ansible", command]
|
|
if verbose_level:
|
|
cmd += ["-" + "v" * verbose_level]
|
|
cmd += vault.build_args(parsed_args, "--key")
|
|
inventory = _get_inventory_path(parsed_args, inventory_filename)
|
|
cmd += ["--inventory", inventory]
|
|
if parsed_args.kolla_config_path != DEFAULT_CONFIG_PATH:
|
|
cmd += ["--configdir", parsed_args.kolla_config_path]
|
|
cmd += ["--passwords",
|
|
os.path.join(parsed_args.kolla_config_path, "passwords.yml")]
|
|
if parsed_args.kolla_extra_vars:
|
|
for extra_var in parsed_args.kolla_extra_vars:
|
|
# Don't quote or escape variables passed via the kayobe -e CLI
|
|
# argument, to match Ansible's behaviour.
|
|
cmd += ["-e", extra_var]
|
|
if extra_vars:
|
|
for extra_var_name, extra_var_value in extra_vars.items():
|
|
# Quote and escape variables originating within the python CLI.
|
|
extra_var_value = utils.quote_and_escape(extra_var_value)
|
|
cmd += ["-e", "%s=%s" % (extra_var_name, extra_var_value)]
|
|
if parsed_args.kolla_limit or limit:
|
|
limits = [l for l in [parsed_args.kolla_limit, limit] if l]
|
|
cmd += ["--limit", ":&".join(limits)]
|
|
if parsed_args.kolla_skip_tags:
|
|
cmd += ["--skip-tags", parsed_args.kolla_skip_tags]
|
|
if parsed_args.kolla_tags or tags:
|
|
all_tags = [t for t in [parsed_args.kolla_tags, tags] if t]
|
|
cmd += ["--tags", ",".join(all_tags)]
|
|
if extra_args:
|
|
cmd += extra_args
|
|
return cmd
|
|
|
|
|
|
def run(parsed_args, command, inventory_filename, extra_vars=None,
|
|
tags=None, quiet=False, verbose_level=None, extra_args=None,
|
|
limit=None):
|
|
"""Run a Kolla Ansible command."""
|
|
_validate_args(parsed_args, inventory_filename)
|
|
cmd = build_args(parsed_args, command,
|
|
inventory_filename=inventory_filename,
|
|
extra_vars=extra_vars, tags=tags,
|
|
verbose_level=verbose_level,
|
|
extra_args=extra_args,
|
|
limit=limit)
|
|
env = os.environ.copy()
|
|
vault.update_environment(parsed_args, env)
|
|
try:
|
|
utils.run_command(" ".join(cmd), quiet=quiet, shell=True, env=env)
|
|
except subprocess.CalledProcessError as e:
|
|
LOG.error("kolla-ansible %s exited %d", command, e.returncode)
|
|
sys.exit(e.returncode)
|
|
|
|
|
|
def run_seed(*args, **kwargs):
|
|
"""Run a Kolla Ansible command using the seed inventory."""
|
|
return run(*args, inventory_filename="seed", **kwargs)
|
|
|
|
|
|
def run_overcloud(*args, **kwargs):
|
|
"""Run a Kolla Ansible command using the overcloud inventory."""
|
|
return run(*args, inventory_filename="overcloud", **kwargs)
|