aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qtip/ansible_library/modules/apex.py133
-rwxr-xr-xtests/data/external/apex/baremetal_info.json57
-rwxr-xr-xtests/data/external/apex/server_info.json37
-rw-r--r--tests/unit/ansible_library/modules/apex_test.py30
4 files changed, 257 insertions, 0 deletions
diff --git a/qtip/ansible_library/modules/apex.py b/qtip/ansible_library/modules/apex.py
new file mode 100644
index 00000000..218440b2
--- /dev/null
+++ b/qtip/ansible_library/modules/apex.py
@@ -0,0 +1,133 @@
+#!/usr/bin/python
+
+###############################################################
+# Copyright (c) 2017 ZTE Corporation
+#
+# 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
+##############################################################################
+
+from collections import defaultdict
+import json
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.0',
+ 'status': ['preview'],
+ 'supported_by': 'community'}
+
+DOCUMENTATION = '''
+---
+module: apex
+short_description: collecting facts from apex environments
+description:
+ - Use this module to create a dynamic inventory from apex undercloud.
+version_added: "2.2"
+author: "Zhihui Wu"
+options:
+notes:
+requirements:
+ - Host 'apex-undercloud' is in ~/.ssh/config
+'''
+
+RETURN = '''
+ansible_facts:
+ description: facts collected for ansible
+ returned: success
+ type: dictionary
+ contains:
+ hosts:
+ description: host grouped by hostname, cluster, role and manufacture
+ type: dict
+ hosts_meta:
+ description: hosts meta data indexed by hostname
+ type: dict
+'''
+
+EXAMPLES = '''
+---
+- hosts: apex-undercloud
+ tasks:
+ - name: collect facts of apex hosts
+ apex:
+ - debug: var=hostvarsi
+ - name: add compute node to ansible inventory
+ add_host:
+ name: "{{ hosts_meta[item]['ip'] }}"
+ groups: compute
+ ansible_user: root
+ ansible_ssh_common_args: '-o StrictHostKeyChecking=No -o ProxyJump=apex-master'
+ with_items: "{{ hosts.compute }}"
+- hosts: compute
+ tasks:
+ - name: check ssh connection
+ ping:
+'''
+
+
+def generate_inventory(baremetal_info, server_info):
+ """Generate ansible inventory from node list in json format
+
+ Modified from https://github.com/martineg/ansible-apex-inventory/blob/master/apex.py
+ """
+
+ hosts = defaultdict(list)
+ hosts_meta = {}
+
+ for node in baremetal_info:
+ if node['Provisioning State'].lower() == 'active':
+ role = re.findall('.+profile:(\w+)$', node['Properties']['capabilities'])[0]
+ for server in server_info:
+ if server['ID'] == node['Instance UUID']:
+ node_ip = re.findall('.+=(\d+.\d+.\d+.\d+)$', server['Networks'])[0]
+ hosts[role].append(node_ip)
+ # To match ssh.cfg.j2 template
+ hosts_meta[node_ip] = {'ansible_ssh_host': node_ip}
+
+ for host in hosts:
+ hosts[host].sort()
+
+ return {'hosts': hosts, 'hosts_meta': hosts_meta}
+
+
+def main():
+ module = AnsibleModule(argument_spec=dict())
+
+ (rc, out, err) = module.run_command(['source ~/stackrc'])
+
+ if rc is not None and rc != 0:
+ return module.fail_json(msg=err)
+
+ cmd = [module.get_bin_path('openstack', True),
+ 'baremetal',
+ 'list',
+ '--fields instance_uuid properties provision_state',
+ '--format json']
+ (rc, out, err) = module.run_command(cmd)
+
+ if rc is not None and rc != 0:
+ return module.fail_json(msg=err)
+
+ baremetal_info = json.loads(out)
+
+ cmd = [module.get_bin_path('openstack', True),
+ 'server',
+ 'list',
+ '--format json']
+ (rc, out, err) = module.run_command(cmd)
+
+ if rc is not None and rc != 0:
+ return module.fail_json(msg=err)
+
+ server_info = json.loads(out)
+
+ module.exit_json(changed=False,
+ ansible_facts=generate_inventory(baremetal_info, server_info))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/data/external/apex/baremetal_info.json b/tests/data/external/apex/baremetal_info.json
new file mode 100755
index 00000000..8efe4e71
--- /dev/null
+++ b/tests/data/external/apex/baremetal_info.json
@@ -0,0 +1,57 @@
+[
+ {
+ "Properties": {
+ "memory_mb": "8192",
+ "cpu_arch": "x86_64",
+ "local_gb": "41",
+ "cpus": "4",
+ "capabilities": "boot_option:local,profile:compute"
+ },
+ "Provisioning State": "active",
+ "Instance UUID": "367827af-966c-4c91-bad4-d8dc12750eac"
+ },
+ {
+ "Properties": {
+ "memory_mb": "8192",
+ "cpu_arch": "x86_64",
+ "local_gb": "41",
+ "cpus": "4",
+ "capabilities": "boot_option:local,profile:compute"
+ },
+ "Provisioning State": "active",
+ "Instance UUID": "f214f844-ec4d-4f33-9d16-9aa21ade3cb4"
+ },
+ {
+ "Properties": {
+ "memory_mb": "8192",
+ "cpu_arch": "x86_64",
+ "local_gb": "41",
+ "cpus": "4",
+ "capabilities": "boot_option:local,profile:control"
+ },
+ "Provisioning State": "active",
+ "Instance UUID": "06234a4d-45fb-4930-bf8a-9b1627b1621f"
+ },
+ {
+ "Properties": {
+ "memory_mb": "8192",
+ "cpu_arch": "x86_64",
+ "local_gb": "41",
+ "cpus": "4",
+ "capabilities": "boot_option:local,profile:control"
+ },
+ "Provisioning State": "active",
+ "Instance UUID": "6dfd4c85-8a05-49ea-bd73-15dbaf84fa9b"
+ },
+ {
+ "Properties": {
+ "memory_mb": "8192",
+ "cpu_arch": "x86_64",
+ "local_gb": "41",
+ "cpus": "4",
+ "capabilities": "boot_option:local,profile:control"
+ },
+ "Provisioning State": "active",
+ "Instance UUID": "25b73b47-7c22-4f58-8ff3-ba5d714baa7c"
+ }
+]
diff --git a/tests/data/external/apex/server_info.json b/tests/data/external/apex/server_info.json
new file mode 100755
index 00000000..71bc40c5
--- /dev/null
+++ b/tests/data/external/apex/server_info.json
@@ -0,0 +1,37 @@
+[
+ {
+ "Status": "ACTIVE",
+ "Networks": "ctlplane=192.0.2.9",
+ "ID": "06234a4d-45fb-4930-bf8a-9b1627b1621f",
+ "Image Name": "overcloud-full",
+ "Name": "overcloud-controller-2"
+ },
+ {
+ "Status": "ACTIVE",
+ "Networks": "ctlplane=192.0.2.7",
+ "ID": "6dfd4c85-8a05-49ea-bd73-15dbaf84fa9b",
+ "Image Name": "overcloud-full",
+ "Name": "overcloud-controller-0"
+ },
+ {
+ "Status": "ACTIVE",
+ "Networks": "ctlplane=192.0.2.8",
+ "ID": "25b73b47-7c22-4f58-8ff3-ba5d714baa7c",
+ "Image Name": "overcloud-full",
+ "Name": "overcloud-controller-1"
+ },
+ {
+ "Status": "ACTIVE",
+ "Networks": "ctlplane=192.0.2.6",
+ "ID": "f214f844-ec4d-4f33-9d16-9aa21ade3cb4",
+ "Image Name": "overcloud-full",
+ "Name": "overcloud-novacompute-0"
+ },
+ {
+ "Status": "ACTIVE",
+ "Networks": "ctlplane=192.0.2.5",
+ "ID": "367827af-966c-4c91-bad4-d8dc12750eac",
+ "Image Name": "overcloud-full",
+ "Name": "overcloud-novacompute-1"
+ }
+] \ No newline at end of file
diff --git a/tests/unit/ansible_library/modules/apex_test.py b/tests/unit/ansible_library/modules/apex_test.py
new file mode 100644
index 00000000..8a1d0673
--- /dev/null
+++ b/tests/unit/ansible_library/modules/apex_test.py
@@ -0,0 +1,30 @@
+###############################################################
+# Copyright (c) 2017 ZTE Corporation
+#
+# 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
+##############################################################################
+
+import json
+import os
+
+from qtip.ansible_library.modules import apex
+
+
+def test_generate_inventory(data_root):
+ baremetal_info = json.load(open(os.path.join(data_root, 'external',
+ 'apex', 'baremetal_info.json')))
+ server_info = json.load(open(os.path.join(data_root, 'external',
+ 'apex', 'server_info.json')))
+ inventory = apex.generate_inventory(baremetal_info, server_info)
+ assert dict(inventory['hosts']) == {
+ u'compute': [u'192.0.2.5', u'192.0.2.6'],
+ u'control': [u'192.0.2.7', u'192.0.2.8', u'192.0.2.9']}
+ assert dict(inventory['hosts_meta']) == {
+ u'192.0.2.5': {'ansible_ssh_host': u'192.0.2.5'},
+ u'192.0.2.6': {'ansible_ssh_host': u'192.0.2.6'},
+ u'192.0.2.7': {'ansible_ssh_host': u'192.0.2.7'},
+ u'192.0.2.8': {'ansible_ssh_host': u'192.0.2.8'},
+ u'192.0.2.9': {'ansible_ssh_host': u'192.0.2.9'}}