summaryrefslogtreecommitdiffstats
path: root/qtip
diff options
context:
space:
mode:
Diffstat (limited to 'qtip')
-rw-r--r--qtip/ansible_library/modules/apex.py133
-rw-r--r--qtip/ansible_library/plugins/action/aggregate.py36
-rw-r--r--qtip/ansible_library/plugins/action/calculate.py9
-rw-r--r--qtip/reporter/testapi.py22
4 files changed, 193 insertions, 7 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/qtip/ansible_library/plugins/action/aggregate.py b/qtip/ansible_library/plugins/action/aggregate.py
new file mode 100644
index 00000000..6e280419
--- /dev/null
+++ b/qtip/ansible_library/plugins/action/aggregate.py
@@ -0,0 +1,36 @@
+#!/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 numpy import mean
+
+from ansible.plugins.action import ActionBase
+
+
+class ActionModule(ActionBase):
+ def run(self, tmp=None, task_vars=None):
+
+ if task_vars is None:
+ task_vars = dict()
+
+ result = super(ActionModule, self).run(tmp, task_vars)
+
+ if result.get('skipped', False):
+ return result
+
+ return aggregate(self._task.args.get('group'), task_vars)
+
+
+# aggregate QPI results
+def aggregate(group, task_vars):
+ qpi_results = [task_vars['hostvars'][host]['qpi_result'] for host in task_vars['groups'][group]]
+ return {
+ 'score': int(mean([r['score'] for r in qpi_results]))
+ }
diff --git a/qtip/ansible_library/plugins/action/calculate.py b/qtip/ansible_library/plugins/action/calculate.py
index f88729b7..fade367f 100644
--- a/qtip/ansible_library/plugins/action/calculate.py
+++ b/qtip/ansible_library/plugins/action/calculate.py
@@ -10,6 +10,7 @@
##############################################################################
from numpy import mean
+import yaml
from ansible.plugins.action import ActionBase
from ansible.utils.display import Display
@@ -28,7 +29,9 @@ class ActionModule(ActionBase):
if result.get('skipped', False):
return result
- spec = self._task.args.get('spec')
+ with open(self._task.args.get('spec')) as stream:
+ spec = yaml.safe_load(stream)
+
metrics = self._task.args.get('metrics')
return calc_qpi(spec, metrics)
@@ -42,8 +45,10 @@ def calc_qpi(qpi_spec, metrics):
section_results = [{'name': s['name'], 'result': calc_section(s, metrics)}
for s in qpi_spec['sections']]
+
# TODO(yujunz): use formula in spec
- qpi_score = mean([r['result']['score'] for r in section_results])
+ standard_score = 2048
+ qpi_score = int(mean([r['result']['score'] for r in section_results]) * standard_score)
return {
'spec': qpi_spec,
'score': qpi_score,
diff --git a/qtip/reporter/testapi.py b/qtip/reporter/testapi.py
index a0be5379..2e4205ea 100644
--- a/qtip/reporter/testapi.py
+++ b/qtip/reporter/testapi.py
@@ -7,8 +7,18 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-import requests
+# OPNFV Testapi Client
+#
+# API url: http://testresults.opnfv.org/test/api/v1
+# API spec:
+# - http://testresults.opnfv.org/test/swagger/spec.html#!/spec/queryTestResults
+# - http://testresults.opnfv.org/test/swagger/spec.html#!/spec/createTestResult
+# Login:
+# username: opnfv
+# password: contact admin
+# Self host: https://github.com/opnfv/releng/tree/master/utils/test/testapi/deployment
+import requests
payload_template = {'project_name',
'case_name',
@@ -29,19 +39,21 @@ def validate_payload():
if set(payload.keys()) != payload_template:
missing_parameters = list(payload_template -
set(payload.keys()))
- print "Missing Parameters -- {}".\
- format(",".join(missing_parameters))
+ print("Missing Parameters -- {}".
+ format(",".join(missing_parameters)))
raise MissingParamsError("push_results", missing_parameters)
invalid_params = []
for key in payload:
if (payload[key] == "") or (payload[key] is None):
invalid_params.append(key)
if len(invalid_params) > 0:
- print "Invalid or missing values of parameters -- `{}`".\
- format(",".join(invalid_params))
+ print ("Invalid or missing values of parameters -- `{}`".
+ format(",".join(invalid_params)))
raise InvalidParamsError("push_results", invalid_params)
return func(testapi_url, payload)
+
return _execute
+
return _decorator