From 1c1d92b4dbe07c605a5261ad5f09c735280b9b5d Mon Sep 17 00:00:00 2001
From: Mark Goddard <mark@stackhpc.com>
Date: Tue, 22 Aug 2017 18:24:29 +0000
Subject: [PATCH] Add command to save overcloud introspection data

The CLI command is:

kayobe overcloud introspection data save [--output-dir <dir>] [--output-format <format>]

This command will save introspection data collected by the seed host's ironic
inspector service to the control host for analysis.
---
 ansible/overcloud-introspection-data-save.yml | 64 +++++++++++++++++++
 doc/source/deployment.rst                     | 13 ++++
 kayobe/cli/commands.py                        | 33 ++++++++++
 setup.py                                      |  1 +
 4 files changed, 111 insertions(+)
 create mode 100644 ansible/overcloud-introspection-data-save.yml

diff --git a/ansible/overcloud-introspection-data-save.yml b/ansible/overcloud-introspection-data-save.yml
new file mode 100644
index 00000000..3b00a079
--- /dev/null
+++ b/ansible/overcloud-introspection-data-save.yml
@@ -0,0 +1,64 @@
+---
+- name: Ensure the overcloud nodes' hardware introspection data is saved
+  hosts: overcloud
+  vars:
+    seed_host: "{{ groups['seed'][0] }}"
+    # Override this to save results to another location.
+    output_dir: "{{ lookup('env', 'PWD') }}/overcloud-introspection-data"
+    # Override this to set the output data format. One of json, yaml.
+    output_format: json
+  gather_facts: no
+  tasks:
+    - name: Query overcloud nodes' hardware introspection data
+      command: >
+        docker exec bifrost_deploy
+        bash -c '. env-vars &&
+        export OS_URL=$IRONIC_URL
+        export OS_TOKEN=$OS_AUTH_TOKEN &&
+        export BIFROST_INVENTORY_SOURCE=ironic &&
+        ansible baremetal
+        --connection local
+        --inventory /etc/bifrost/inventory/
+        -e @/etc/bifrost/bifrost.yml
+        -e @/etc/bifrost/dib.yml
+        --limit {{ inventory_hostname }}
+        -m shell
+        -a "env OS_URL=http://localhost:5050 openstack baremetal introspection data save {% raw %}{{ inventory_hostname }}{% endraw %}"'
+      register: save_result
+      changed_when: False
+      # Ignore errors, log a message later.
+      failed_when: False
+      delegate_to: "{{ seed_host }}"
+      vars:
+        # NOTE: Without this, the seed's ansible_host variable will not be
+        # respected when using delegate_to.
+        ansible_host: "{{ hostvars[seed_host].ansible_host | default(seed_host) }}"
+
+    - name: Ensure introspection data output directory exists
+      local_action:
+        module: file
+        path: "{{ output_dir }}"
+        state: directory
+
+    - name: Ensure introspection data is saved locally
+      local_action:
+        module: copy
+        content: "{{ introspection_data_map[output_format | lower] }}"
+        dest: "{{ output_dir }}/{{ inventory_hostname }}.{{ output_format | lower }}"
+      when: save_result.rc == 0
+      vars:
+        introspection_data: "{{ save_result.stdout_lines[1:] | join('\n') | from_json }}"
+        introspection_data_json: "{{ introspection_data | to_nice_json(indent=4) }}"
+        introspection_data_yaml: "{{ introspection_data | to_nice_yaml }}"
+        introspection_data_map:
+          json: "{{ introspection_data_json }}"
+          yaml: "{{ introspection_data_yaml }}"
+
+    - name: Log when introspection data could not be queried
+      debug:
+        msg: >
+          Could not query hardware introspection data for
+          {{ inventory_hostname }}.
+          Stdout: {{ save_result.stdout }}.
+          Stderr: {{ save_result.stderr }}.
+      when: save_result.rc != 0
diff --git a/doc/source/deployment.rst b/doc/source/deployment.rst
index 65c8e43c..b0235a81 100644
--- a/doc/source/deployment.rst
+++ b/doc/source/deployment.rst
@@ -207,6 +207,19 @@ to add them to the Kayobe and bifrost Ansible inventories::
 
     (kayobe-venv) $ kayobe overcloud inventory discover
 
+Saving Hardware Introspection Data
+----------------------------------
+
+If ironic inspector is in use on the seed host, introspection data will be
+stored in the local nginx service.  This data may be saved to the control
+host::
+
+    (kayobe-venv) $ kayobe overcloud introspection data save
+
+``--output-dir`` may be used to specify the directory in which introspection
+data files will be saved. ``--output-format`` may be used to set the format of
+the files.
+
 BIOS and RAID Configuration
 ---------------------------
 
diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py
index c6ea1b13..52d5fbce 100644
--- a/kayobe/cli/commands.py
+++ b/kayobe/cli/commands.py
@@ -369,6 +369,39 @@ class OvercloudInventoryDiscover(KayobeAnsibleMixin, VaultMixin, Command):
                                  tags="config")
 
 
+class OvercloudIntrospectionDataSave(KayobeAnsibleMixin, VaultMixin, Command):
+    """Save hardware introspection data for the overcloud.
+
+    Save hardware introspection data from the seed's ironic inspector service
+    to the control host.
+    """
+
+    def get_parser(self, prog_name):
+        parser = super(OvercloudIntrospectionDataSave, self).get_parser(
+            prog_name)
+        group = parser.add_argument_group("Introspection data")
+        # Defaults for these are applied in the playbook.
+        group.add_argument("--output-dir", type=str,
+                           help="Path to directory in which to save "
+                               "introspection data. Default: "
+                               "$PWD/overcloud-introspection-data")
+        group.add_argument("--output-format", type=str,
+                           help="Format in which to save output data. One of "
+                                "JSON or YAML. Default: JSON",
+                           choices=["JSON", "YAML"])
+        return parser
+
+    def take_action(self, parsed_args):
+        self.app.LOG.debug("Saving introspection data")
+        extra_vars = {}
+        if parsed_args.output_dir:
+            extra_vars['output_dir'] = parsed_args.output_dir
+        if parsed_args.output_format:
+            extra_vars['output_format'] = parsed_args.output_format
+        playbooks = _build_playbook_list("overcloud-introspection-data-save")
+        self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars)
+
+
 class OvercloudBIOSRAIDConfigure(KayobeAnsibleMixin, VaultMixin, Command):
     """Configure BIOS and RAID for the overcloud hosts."""
 
diff --git a/setup.py b/setup.py
index 524c721c..c21e4d0e 100644
--- a/setup.py
+++ b/setup.py
@@ -62,6 +62,7 @@ setup(
             'overcloud_deprovision = kayobe.cli.commands:OvercloudDeprovision',
             'overcloud_hardware_inspect = kayobe.cli.commands:OvercloudHardwareInspect',
             'overcloud_host_configure = kayobe.cli.commands:OvercloudHostConfigure',
+            'overcloud_introspection_data_save = kayobe.cli.commands:OvercloudIntrospectionDataSave',
             'overcloud_inventory_discover = kayobe.cli.commands:OvercloudInventoryDiscover',
             'overcloud_post_configure = kayobe.cli.commands:OvercloudPostConfigure',
             'overcloud_provision = kayobe.cli.commands:OvercloudProvision',
-- 
GitLab