From 382fa452e0c9a8189911f615416e1b24badaf5e4 Mon Sep 17 00:00:00 2001 From: Tim Rozet Date: Mon, 27 Nov 2017 15:22:25 -0500 Subject: Adds the ability to fetch logs from deployment Usage: opnfv-pyutil --fetch-logs python3 utils.py --fetch-logs --lib-dir ../lib Eventually all utils.sh functions will be migrated here. Note there is no support here for containers. Will be added later. Change-Id: I223b8592ad09e0370e287ee2801072db31f9aa12 Signed-off-by: Tim Rozet --- apex/common/constants.py | 2 +- apex/deploy.py | 13 +++-- apex/undercloud/undercloud.py | 19 ++++++-- apex/utils.py | 107 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 apex/utils.py (limited to 'apex') diff --git a/apex/common/constants.py b/apex/common/constants.py index 0aa6a6ca..4f72b082 100644 --- a/apex/common/constants.py +++ b/apex/common/constants.py @@ -16,7 +16,7 @@ STORAGE_NETWORK = 'storage' API_NETWORK = 'api' CONTROLLER = 'controller' COMPUTE = 'compute' - +ANSIBLE_PATH = 'ansible/playbooks' OPNFV_NETWORK_TYPES = [ADMIN_NETWORK, TENANT_NETWORK, EXTERNAL_NETWORK, STORAGE_NETWORK, API_NETWORK] DNS_SERVERS = ["8.8.8.8", "8.8.4.4"] diff --git a/apex/deploy.py b/apex/deploy.py index 7bc5568f..4facadef 100644 --- a/apex/deploy.py +++ b/apex/deploy.py @@ -39,7 +39,6 @@ from apex.overcloud import config as oc_cfg from apex.overcloud import deploy as oc_deploy APEX_TEMP_DIR = tempfile.mkdtemp(prefix='apex_tmp') -ANSIBLE_PATH = 'ansible/playbooks' SDN_IMAGE = 'overcloud-full-opendaylight.qcow2' @@ -309,7 +308,7 @@ def main(): 'virsh_enabled_networks': net_settings.enabled_network_list } utils.run_ansible(ansible_args, - os.path.join(args.lib_dir, ANSIBLE_PATH, + os.path.join(args.lib_dir, constants.ANSIBLE_PATH, 'deploy_dependencies.yml')) uc_external = False if 'external' in net_settings.enabled_network_list: @@ -397,7 +396,7 @@ def main(): args.deploy_dir, APEX_TEMP_DIR) # Install Undercloud undercloud.configure(net_settings, deploy_settings, - os.path.join(args.lib_dir, ANSIBLE_PATH, + os.path.join(args.lib_dir, constants.ANSIBLE_PATH, 'configure_undercloud.yml'), APEX_TEMP_DIR, virtual_oc=args.virtual) @@ -433,7 +432,7 @@ def main(): os.path.basename(opnfv_env), net_data=net_data) # Prepare undercloud with containers - docker_playbook = os.path.join(args.lib_dir, ANSIBLE_PATH, + docker_playbook = os.path.join(args.lib_dir, constants.ANSIBLE_PATH, 'prepare_overcloud_containers.yml') if ds_opts['containers']: ceph_version = constants.CEPH_VERSION_MAP[ds_opts['os_version']] @@ -466,7 +465,7 @@ def main(): os.remove(os.path.join(APEX_TEMP_DIR, 'overcloud-full.qcow2')) raise - deploy_playbook = os.path.join(args.lib_dir, ANSIBLE_PATH, + deploy_playbook = os.path.join(args.lib_dir, constants.ANSIBLE_PATH, 'deploy_overcloud.yml') virt_env = 'virtual-environment.yaml' bm_env = 'baremetal-environment.yaml' @@ -542,7 +541,7 @@ def main(): else: deploy_vars['overcloudrc_files'] = ['overcloudrc'] - post_undercloud = os.path.join(args.lib_dir, ANSIBLE_PATH, + post_undercloud = os.path.join(args.lib_dir, constants.ANSIBLE_PATH, 'post_deploy_undercloud.yml') logging.info("Executing post deploy configuration undercloud playbook") try: @@ -561,7 +560,7 @@ def main(): deploy_vars['sriov'] = ds_opts.get('sriov') # TODO(trozet): pull all logs and store in tmp dir in overcloud # playbook - post_overcloud = os.path.join(args.lib_dir, ANSIBLE_PATH, + post_overcloud = os.path.join(args.lib_dir, constants.ANSIBLE_PATH, 'post_deploy_overcloud.yml') # Run per overcloud node for node, ip in deploy_vars['overcloud_nodes'].items(): diff --git a/apex/undercloud/undercloud.py b/apex/undercloud/undercloud.py index e799d371..2972351c 100644 --- a/apex/undercloud/undercloud.py +++ b/apex/undercloud/undercloud.py @@ -77,15 +77,26 @@ class Undercloud: self.inject_auth() self._update_delorean_repo() - def _set_ip(self): - ip_out = self.vm.interfaceAddresses( + @staticmethod + def _get_ip(vm): + ip_out = vm.interfaceAddresses( libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE, 0) if ip_out: for (name, val) in ip_out.items(): for ipaddr in val['addrs']: if ipaddr['type'] == libvirt.VIR_IP_ADDR_TYPE_IPV4: - self.ip = ipaddr['addr'] - return True + return ipaddr['addr'] + + def _set_ip(self): + ip = self._get_ip(self.vm) + if ip: + self.ip = ip + return True + + @staticmethod + def get_ip(): + vm = Undercloud._get_vm() + return Undercloud._get_ip(vm) def start(self): """ diff --git a/apex/utils.py b/apex/utils.py new file mode 100644 index 00000000..cea25fe9 --- /dev/null +++ b/apex/utils.py @@ -0,0 +1,107 @@ +############################################################################## +# Copyright (c) 2017 Tim Rozet (trozet@redhat.com) and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +# TODO(trozet) migrate rest of utils.sh here + +import argparse +import datetime +import logging +import os +import sys +import tempfile + +from apex.common import constants +from apex.common import parsers +from apex.undercloud import undercloud as uc_lib +from apex.common import utils + +VALID_UTILS = ['fetch_logs'] +START_TIME = datetime.datetime.now().strftime("%Y-%m-%d-%H:%M") +APEX_TEMP_DIR = tempfile.mkdtemp(prefix="apex-logs-{}-".format(START_TIME)) + + +def fetch_logs(args): + uc_ip = uc_lib.Undercloud.get_ip() + if not uc_ip: + raise Exception('No Undercloud IP found') + logging.info("Undercloud IP is: {}".format(uc_ip)) + fetch_vars = dict() + fetch_vars['stackrc'] = 'source /home/stack/stackrc' + fetch_vars['apex_temp_dir'] = APEX_TEMP_DIR + fetch_playbook = os.path.join(args.lib_dir, constants.ANSIBLE_PATH, + 'fetch_overcloud_nodes.yml') + try: + utils.run_ansible(fetch_vars, fetch_playbook, host=uc_ip, + user='stack', tmp_dir=APEX_TEMP_DIR) + logging.info("Retrieved overcloud nodes info") + except Exception: + logging.error("Failed to retrieve overcloud nodes. Please check log") + raise + nova_output = os.path.join(APEX_TEMP_DIR, 'nova_output') + fetch_vars['overcloud_nodes'] = parsers.parse_nova_output(nova_output) + fetch_vars['SSH_OPTIONS'] = '-o StrictHostKeyChecking=no -o ' \ + 'GlobalKnownHostsFile=/dev/null -o ' \ + 'UserKnownHostsFile=/dev/null -o ' \ + 'LogLevel=error' + fetch_playbook = os.path.join(args.lib_dir, constants.ANSIBLE_PATH, + 'fetch_overcloud_logs.yml') + # Run per overcloud node + for node, ip in fetch_vars['overcloud_nodes'].items(): + logging.info("Executing fetch logs overcloud playbook on " + "node {}".format(node)) + try: + utils.run_ansible(fetch_vars, fetch_playbook, host=ip, + user='heat-admin', tmp_dir=APEX_TEMP_DIR) + logging.info("Logs retrieved for node {}".format(node)) + except Exception: + logging.error("Log retrieval failed " + "for node {}. Please check log".format(node)) + raise + logging.info("Log retrieval complete and stored in {}".format( + APEX_TEMP_DIR)) + + +def execute_actions(args): + for action in VALID_UTILS: + if hasattr(args, action) and getattr(args, action): + util_module = __import__('utils') + func = getattr(util_module, action) + logging.info("Executing action: {}".format(action)) + func(args) + + +def main(): + util_parser = argparse.ArgumentParser() + util_parser.add_argument('-f', '--fetch-logs', + dest='fetch_logs', + required=False, + default=False, + action='store_true', + help='Fetch all overcloud logs') + util_parser.add_argument('--lib-dir', + default='/usr/share/opnfv-apex', + help='Directory path for apex ansible ' + 'and third party libs') + args = util_parser.parse_args(sys.argv[1:]) + os.makedirs(os.path.dirname('./apex_util.log'), exist_ok=True) + formatter = '%(asctime)s %(levelname)s: %(message)s' + logging.basicConfig(filename='./apex_clean.log', + format=formatter, + datefmt='%m/%d/%Y %I:%M:%S %p', + level=logging.DEBUG) + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + console.setFormatter(logging.Formatter(formatter)) + logging.getLogger('').addHandler(console) + + execute_actions(args) + + +if __name__ == '__main__': + main() -- cgit 1.2.3-korg