From d170a37e980660f2f3ceaa4ed35f5ed2e4fe1f53 Mon Sep 17 00:00:00 2001 From: Morgan Richomme Date: Thu, 3 Sep 2015 10:07:38 +0200 Subject: change vPing to push results in Test DB JIRA: FUNCTEST-36 Change-Id: I2b1fd1f633bc44971e63ab5344076934c144c115 Signed-off-by: Morgan Richomme --- testcases/vPing/CI/libraries/vPing.py | 318 +++++++++++++++++++++++----------- 1 file changed, 219 insertions(+), 99 deletions(-) (limited to 'testcases/vPing/CI/libraries/vPing.py') diff --git a/testcases/vPing/CI/libraries/vPing.py b/testcases/vPing/CI/libraries/vPing.py index 1cc73922c..56f4fc538 100644 --- a/testcases/vPing/CI/libraries/vPing.py +++ b/testcases/vPing/CI/libraries/vPing.py @@ -1,49 +1,69 @@ #!/usr/bin/python # -# Copyright (c) 2015 All rights reserved. This program and the accompanying materials +# Copyright (c) 2015 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 +# http://www.apache.org/licenses/LICENSE-2.0 # -# This script boots the VM1 and allocates IP address from Nova +# 0.1: This script boots the VM1 and allocates IP address from Nova # Later, the VM2 boots then execute cloud-init to ping VM1. # After successful ping, both the VMs are deleted. +# 0.2: measure test duration and publish results under json format # -# Note: this is script works only with Ubuntu image, not with Cirros image # -import os, time, subprocess, logging, argparse, yaml, pprint, sys +import os +import time +import argparse +import pprint +import sys +import json +import logging +import yaml +import datetime +import requests import novaclient.v2.client as novaclient from neutronclient.v2_0 import client as neutronclient pp = pprint.PrettyPrinter(indent=4) - parser = argparse.ArgumentParser() + parser.add_argument("repo_path", help="Path to the repository") -parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") +parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") +parser.add_argument("-r", "--report", + help="Create json result file", + action="store_true") + args = parser.parse_args() sys.path.append(args.repo_path + "testcases/") + import functest_utils """ logging configuration """ + logger = logging.getLogger('vPing') logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() + if args.debug: ch.setLevel(logging.DEBUG) else: ch.setLevel(logging.INFO) -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + +formatter = logging.Formatter('%(asctime)s - %(name)s' + '- %(levelname)s - %(message)s') + ch.setFormatter(formatter) logger.addHandler(ch) +HOME = os.environ['HOME'] + "/" -HOME = os.environ['HOME']+"/" -with open(args.repo_path+"testcases/config_functest.yaml") as f: +with open(args.repo_path + "testcases/config_functest.yaml") as f: functest_yaml = yaml.safe_load(f) f.close() @@ -51,151 +71,203 @@ f.close() VM_BOOT_TIMEOUT = 180 VM_DELETE_TIMEOUT = 100 PING_TIMEOUT = functest_yaml.get("vping").get("ping_timeout") +TEST_DB = functest_yaml.get("results").get("test_db_url") NAME_VM_1 = functest_yaml.get("vping").get("vm_name_1") NAME_VM_2 = functest_yaml.get("vping").get("vm_name_2") IP_1 = functest_yaml.get("vping").get("ip_1") IP_2 = functest_yaml.get("vping").get("ip_2") -GLANCE_IMAGE_NAME = functest_yaml.get("general").get("openstack").get("image_name") +GLANCE_IMAGE_NAME = functest_yaml.get("general"). \ + get("openstack").get("image_name") FLAVOR = functest_yaml.get("vping").get("vm_flavor") # NEUTRON Private Network parameters -NEUTRON_PRIVATE_NET_NAME = functest_yaml.get("general").get("openstack").get("neutron_private_net_name") -NEUTRON_PRIVATE_SUBNET_NAME = functest_yaml.get("general").get("openstack").get("neutron_private_subnet_name") -NEUTRON_PRIVATE_SUBNET_CIDR = functest_yaml.get("general").get("openstack").get("neutron_private_subnet_cidr") -NEUTRON_ROUTER_NAME = functest_yaml.get("general").get("openstack").get("neutron_router_name") + +NEUTRON_PRIVATE_NET_NAME = functest_yaml.get("general"). \ + get("openstack").get("neutron_private_net_name") + +NEUTRON_PRIVATE_SUBNET_NAME = functest_yaml.get("general"). \ + get("openstack").get("neutron_private_subnet_name") + +NEUTRON_PRIVATE_SUBNET_CIDR = functest_yaml.get("general"). \ + get("openstack").get("neutron_private_subnet_cidr") + +NEUTRON_ROUTER_NAME = functest_yaml.get("general"). \ + get("openstack").get("neutron_router_name") def pMsg(value): + """pretty printing""" pp.pprint(value) -def waitVmActive(nova,vm): +def waitVmActive(nova, vm): + # sleep and wait for VM status change sleep_time = 3 count = VM_BOOT_TIMEOUT / sleep_time while True: - status = functest_utils.get_instance_status(nova,vm) + status = functest_utils.get_instance_status(nova, vm) logger.debug("Status: %s" % status) if status == "ACTIVE": return True if status == "ERROR" or count == 0: return False - count-=1 + count -= 1 time.sleep(sleep_time) return False -def waitVmDeleted(nova,vm): + +def waitVmDeleted(nova, vm): + # sleep and wait for VM status change sleep_time = 3 count = VM_DELETE_TIMEOUT / sleep_time while True: - status = functest_utils.get_instance_status(nova,vm) + status = functest_utils.get_instance_status(nova, vm) if not status: return True elif count == 0: logger.debug("Timeout") return False else: - #return False - count-=1 + # return False + count -= 1 time.sleep(sleep_time) return False def create_private_neutron_net(neutron): + neutron.format = 'json' logger.info('Creating neutron network %s...' % NEUTRON_PRIVATE_NET_NAME) - network_id = functest_utils.create_neutron_net(neutron, NEUTRON_PRIVATE_NET_NAME) + network_id = functest_utils. \ + create_neutron_net(neutron, NEUTRON_PRIVATE_NET_NAME) + if not network_id: return False logger.debug("Network '%s' created successfully" % network_id) - logger.debug('Creating Subnet....') - subnet_id = functest_utils.create_neutron_subnet(neutron, NEUTRON_PRIVATE_SUBNET_NAME, NEUTRON_PRIVATE_SUBNET_CIDR, network_id) + subnet_id = functest_utils. \ + create_neutron_subnet(neutron, + NEUTRON_PRIVATE_SUBNET_NAME, + NEUTRON_PRIVATE_SUBNET_CIDR, + network_id) if not subnet_id: return False logger.debug("Subnet '%s' created successfully" % subnet_id) - logger.debug('Creating Router...') - router_id = functest_utils.create_neutron_router(neutron, NEUTRON_ROUTER_NAME) + router_id = functest_utils. \ + create_neutron_router(neutron, NEUTRON_ROUTER_NAME) + if not router_id: return False - logger.debug("Router '%s' created successfully" % router_id) + logger.debug("Router '%s' created successfully" % router_id) logger.debug('Adding router to subnet...') + result = functest_utils.add_interface_router(neutron, router_id, subnet_id) + if not result: return False - logger.debug("Interface added successfully.") - network_dic = {'net_id' : network_id, - 'subnet_id' : subnet_id, - 'router_id' : router_id} + logger.debug("Interface added successfully.") + network_dic = {'net_id': network_id, + 'subnet_id': subnet_id, + 'router_id': router_id} return network_dic -def cleanup(nova,neutron,network_dic): +def cleanup(nova, neutron, network_dic): + # delete both VMs logger.info("Cleaning up...") vm1 = functest_utils.get_instance_by_name(nova, NAME_VM_1) if vm1: - logger.debug("Deleting '%s'..." %NAME_VM_1) + logger.debug("Deleting '%s'..." % NAME_VM_1) nova.servers.delete(vm1) - #wait until VMs are deleted - if not waitVmDeleted(nova,vm1): - logger.error("Instance '%s' with cannot be deleted. Status is '%s'" % (NAME_VM_1,functest_utils.get_instance_status(nova_client,vm1))) + # wait until VMs are deleted + if not waitVmDeleted(nova, vm1): + logger.error( + "Instance '%s' with cannot be deleted. Status is '%s'" % ( + NAME_VM_1, functest_utils.get_instance_status(nova, vm1))) else: logger.debug("Instance %s terminated." % NAME_VM_1) vm2 = functest_utils.get_instance_by_name(nova, NAME_VM_2) + if vm2: - logger.debug("Deleting '%s'..." %NAME_VM_2) + logger.debug("Deleting '%s'..." % NAME_VM_2) vm2 = nova.servers.find(name=NAME_VM_2) nova.servers.delete(vm2) - if not waitVmDeleted(nova,vm2): - logger.error("Instance '%s' with cannot be deleted. Status is '%s'" % (NAME_VM_2,functest_utils.get_instance_status(nova_client,vm2))) + + if not waitVmDeleted(nova, vm2): + logger.error( + "Instance '%s' with cannot be deleted. Status is '%s'" % ( + NAME_VM_2, functest_utils.get_instance_status(nova, vm2))) else: logger.debug("Instance %s terminated." % NAME_VM_2) # delete created network logger.info("Deleting network '%s'..." % NEUTRON_PRIVATE_NET_NAME) - net_id=network_dic["net_id"] - subnet_id=network_dic["subnet_id"] - router_id=network_dic["router_id"] - if not functest_utils.remove_interface_router(neutron, router_id, subnet_id): - logger.error("Unable to remove subnet '%s' from router '%s'" %(subnet_id,router_id)) - return False + net_id = network_dic["net_id"] + subnet_id = network_dic["subnet_id"] + router_id = network_dic["router_id"] + + if not functest_utils.remove_interface_router(neutron, router_id, + subnet_id): + logger.error("Unable to remove subnet '%s' from router '%s'" % ( + subnet_id, router_id)) + return False + logger.debug("Interface removed successfully") if not functest_utils.delete_neutron_router(neutron, router_id): - logger.error("Unable to delete router '%s'" %router_id) + logger.error("Unable to delete router '%s'" % router_id) return False + logger.debug("Router deleted successfully") + if not functest_utils.delete_neutron_subnet(neutron, subnet_id): - logger.error("Unable to delete subnet '%s'" %subnet_id) + logger.error("Unable to delete subnet '%s'" % subnet_id) return False - logger.debug("Subnet '%s' deleted successfully" %NEUTRON_PRIVATE_SUBNET_NAME) + + logger.debug( + "Subnet '%s' deleted successfully" % NEUTRON_PRIVATE_SUBNET_NAME) + if not functest_utils.delete_neutron_net(neutron, net_id): - logger.error("Unable to delete network '%s'" %net_id) + logger.error("Unable to delete network '%s'" % net_id) return False - logger.debug("Network '%s' deleted successfully" %NEUTRON_PRIVATE_NET_NAME) + + logger.debug( + "Network '%s' deleted successfully" % NEUTRON_PRIVATE_NET_NAME) return True +def push_results_to_db(payload): + + # TODO move DB creds into config file + url = TEST_DB + params = {"project_name": "functest", "case_name": "vPing", "pod_id": 1, + "details": payload} + headers = {'Content-Type': 'application/json'} + r = requests.post(url, data=json.dumps(params), headers=headers) + logger.debug(r) + def main(): + creds_nova = functest_utils.get_credentials("nova") nova_client = novaclient.Client(**creds_nova) creds_neutron = functest_utils.get_credentials("neutron") neutron_client = neutronclient.Client(**creds_neutron) EXIT_CODE = -1 + image = None - network = None flavor = None # Check if the given image exists try: - image = nova_client.images.find(name = GLANCE_IMAGE_NAME) + image = nova_client.images.find(name=GLANCE_IMAGE_NAME) logger.info("Glance image found '%s'" % GLANCE_IMAGE_NAME) except: logger.error("ERROR: Glance image '%s' not found." % GLANCE_IMAGE_NAME) @@ -204,15 +276,18 @@ def main(): exit(-1) network_dic = create_private_neutron_net(neutron_client) + if not network_dic: - logger.error("There has been a problem when creating the neutron network") + logger.error( + "There has been a problem when creating the neutron network") exit(-1) network_id = network_dic["net_id"] # Check if the given flavor exists + try: - flavor = nova_client.flavors.find(name = FLAVOR) + flavor = nova_client.flavors.find(name=FLAVOR) logger.info("Flavor found '%s'" % FLAVOR) except: logger.error("Flavor '%s' not found." % FLAVOR) @@ -220,77 +295,102 @@ def main(): pMsg(nova_client.flavor.list()) exit(-1) - # Deleting instances if they exist - servers=nova_client.servers.list() + + servers = nova_client.servers.list() for server in servers: if server.name == NAME_VM_1 or server.name == NAME_VM_2: - logger.info("Instance %s found. Deleting..." %server.name) + logger.info("Instance %s found. Deleting..." % server.name) server.delete() - # boot VM 1 # basic boot - # tune (e.g. flavor, images, network) to your specific openstack configuration here + # tune (e.g. flavor, images, network) to your specific + # openstack configuration here + # we consider start time at VM1 booting + start_time_ts = time.time() + end_time_ts = start_time_ts + logger.info("vPing Start Time:'%s'" % ( + datetime.datetime.fromtimestamp(start_time_ts).strftime( + '%Y-%m-%d %H:%M:%S'))) # create VM - logger.debug("Creating port 'vping-port-1' with IP %s..." %IP_1) - port_id=functest_utils.create_neutron_port(neutron_client, "vping-port-1", network_id, IP_1) + logger.debug("Creating port 'vping-port-1' with IP %s..." % IP_1) + port_id = functest_utils.create_neutron_port(neutron_client, + "vping-port-1", network_id, + IP_1) if not port_id: logger.error("Unable to create port.") exit(-1) - logger.info("Creating instance '%s' with IP %s..." %(NAME_VM_1,IP_1)) - logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n" %(NAME_VM_1,flavor,image,network_id)) + + logger.info("Creating instance '%s' with IP %s..." % (NAME_VM_1, IP_1)) + logger.debug( + "Configuration:\n name=%s \n flavor=%s \n image=%s \n " + "network=%s \n" % (NAME_VM_1, flavor, image, network_id)) vm1 = nova_client.servers.create( - name = NAME_VM_1, - flavor = flavor, - image = image, - #nics = [{"net-id": network_id, "v4-fixed-ip": IP_1}] - nics = [{"port-id": port_id}] + name=NAME_VM_1, + flavor=flavor, + image=image, + # nics = [{"net-id": network_id, "v4-fixed-ip": IP_1}] + nics=[{"port-id": port_id}] ) - #wait until VM status is active - if not waitVmActive(nova_client,vm1): - logger.error("Instance '%s' cannot be booted. Status is '%s'" % (NAME_VM_1,functest_utils.get_instance_status(nova_client,vm1))) - cleanup(nova_client,neutron_client,network_dic) + + # wait until VM status is active + if not waitVmActive(nova_client, vm1): + + logger.error("Instance '%s' cannot be booted. Status is '%s'" % ( + NAME_VM_1, functest_utils.get_instance_status(nova_client, vm1))) + cleanup(nova_client, neutron_client, network_dic) return (EXIT_CODE) else: logger.info("Instance '%s' is ACTIVE." % NAME_VM_1) - #retrieve IP of first VM - #logger.debug("Fetching IP...") - #server = functest_utils.get_instance_by_name(nova_client, NAME_VM_1) - # theoretically there is only one IP address so we take the first element of the table + # Retrieve IP of first VM + # logger.debug("Fetching IP...") + # server = functest_utils.get_instance_by_name(nova_client, NAME_VM_1) + # theoretically there is only one IP address so we take the + # first element of the table # Dangerous! To be improved! - #test_ip = server.networks.get(NEUTRON_PRIVATE_NET_NAME)[0] - test_ip=IP_1 - logger.debug("Instance '%s' got %s" %(NAME_VM_1,test_ip)) + # test_ip = server.networks.get(NEUTRON_PRIVATE_NET_NAME)[0] + test_ip = IP_1 + logger.debug("Instance '%s' got %s" % (NAME_VM_1, test_ip)) # boot VM 2 # we will boot then execute a ping script with cloud-init # the long chain corresponds to the ping procedure converted with base 64 - # tune (e.g. flavor, images, network) to your specific openstack configuration here - u = "#!/bin/sh\n\nwhile true; do\n ping -c 1 %s 2>&1 >/dev/null\n RES=$?\n if [ \"Z$RES\" = \"Z0\" ] ; then\n echo 'vPing OK'\n break\n else\n echo 'vPing KO'\n fi\n sleep 1\ndone\n"%test_ip + # tune (e.g. flavor, images, network) to your specific openstack + # configuration here + u = "#!/bin/sh\n\nwhile true; do\n ping -c 1 %s 2>&1 >/dev/null\n " \ + "RES=$?\n if [ \"Z$RES\" = \"Z0\" ] ; then\n echo 'vPing OK'\n " \ + "break\n else\n echo 'vPing KO'\n fi\n sleep 1\ndone\n" % test_ip + # create VM + logger.debug("Creating port 'vping-port-2' with IP %s..." % IP_2) + port_id = functest_utils.create_neutron_port(neutron_client, + "vping-port-2", network_id, + IP_2) - logger.debug("Creating port 'vping-port-2' with IP %s..." %IP_2) - port_id=functest_utils.create_neutron_port(neutron_client, "vping-port-2", network_id, IP_2) if not port_id: logger.error("Unable to create port.") exit(-1) - logger.info("Creating instance '%s' with IP %s..." %(NAME_VM_2,IP_2)) - logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n userdata= \n%s" %(NAME_VM_2,flavor,image,network_id,u)) + logger.info("Creating instance '%s' with IP %s..." % (NAME_VM_2, IP_2)) + logger.debug( + "Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s " + "\n userdata= \n%s" % ( + NAME_VM_2, flavor, image, network_id, u)) vm2 = nova_client.servers.create( - name = NAME_VM_2, - flavor = flavor, - image = image, - #nics = [{"net-id": network_id, "v4-fixed-ip": IP_2}], - nics = [{"port-id": port_id}], - userdata = u + name=NAME_VM_2, + flavor=flavor, + image=image, + # nics = [{"net-id": network_id, "v4-fixed-ip": IP_2}], + nics=[{"port-id": port_id}], + userdata=u ) - if not waitVmActive(nova_client,vm2): - logger.error("Instance '%s' cannot be booted. Status is '%s'" % (NAME_VM_2,functest_utils.get_instance_status(nova_client,vm2))) - cleanup(nova_client,neutron_client,network_dic) + if not waitVmActive(nova_client, vm2): + logger.error("Instance '%s' cannot be booted. Status is '%s'" % ( + NAME_VM_2, functest_utils.get_instance_status(nova_client, vm2))) + cleanup(nova_client, neutron_client, network_dic) return (EXIT_CODE) else: logger.info("Instance '%s' is ACTIVE." % NAME_VM_2) @@ -298,13 +398,19 @@ def main(): logger.info("Waiting for ping...") sec = 0 console_log = vm2.get_console_output() + while True: time.sleep(1) console_log = vm2.get_console_output() - #print "--"+console_log + # print "--"+console_log # report if the test is failed if "vPing OK" in console_log: logger.info("vPing detected!") + + # we consider start time at VM1 booting + end_time_ts = time.time() + duration = round(end_time_ts - start_time_ts, 1) + logger.info("vPing duration:'%s'" % duration) EXIT_CODE = 0 break elif sec == PING_TIMEOUT: @@ -312,17 +418,31 @@ def main(): break else: logger.debug("No vPing detected...") - sec+=1 + sec += 1 - cleanup(nova_client,neutron_client,network_dic) + cleanup(nova_client, neutron_client, network_dic) + test_status = "NOK" if EXIT_CODE == 0: logger.info("vPing OK") + test_status = "OK" else: logger.error("vPing FAILED") - exit(EXIT_CODE) + try: + if args.report: + logger.debug("Push result into DB") + # TODO check path result for the file + push_results_to_db( + {'timestart': start_time_ts, 'duration': duration, + 'status': test_status}) + # with open("vPing-result.json", "w") as outfile: + # json.dump({'timestart': start_time_ts, 'duration': duration, + # 'status': test_status}, outfile, indent=4) + except: + logger.error("Error pushing results into Database") + exit(EXIT_CODE) if __name__ == '__main__': main() -- cgit 1.2.3-korg From 7d4d546a0be38dcd49a2fc6e0a13fdc1ab9fd311 Mon Sep 17 00:00:00 2001 From: Morgan Richomme Date: Thu, 17 Sep 2015 18:31:08 +0200 Subject: creation of scripts to generate Dashboard compatible json result files JIRA: FUNCTEST-45 Change-Id: I2336b830d3b5079f45c96bbb69061c8020ea637a Signed-off-by: Morgan Richomme --- testcases/Dashboard/dashboard_utils.py | 251 ++++++++++++++++++++++++++++++ testcases/Dashboard/functest2Dashboard.py | 81 ++++++++++ testcases/Dashboard/odl2Dashboard.py | 52 +++++++ testcases/Dashboard/rally2Dashboard.py | 52 +++++++ testcases/Dashboard/tempest2Dashboard.py | 52 +++++++ testcases/Dashboard/vPing2Dashboard.py | 91 ++++------- testcases/config_functest.yaml | 2 +- testcases/vPing/CI/libraries/vPing.py | 2 +- 8 files changed, 519 insertions(+), 64 deletions(-) create mode 100644 testcases/Dashboard/dashboard_utils.py create mode 100644 testcases/Dashboard/functest2Dashboard.py create mode 100644 testcases/Dashboard/odl2Dashboard.py create mode 100644 testcases/Dashboard/rally2Dashboard.py create mode 100644 testcases/Dashboard/tempest2Dashboard.py (limited to 'testcases/vPing/CI/libraries/vPing.py') diff --git a/testcases/Dashboard/dashboard_utils.py b/testcases/Dashboard/dashboard_utils.py new file mode 100644 index 000000000..90562855a --- /dev/null +++ b/testcases/Dashboard/dashboard_utils.py @@ -0,0 +1,251 @@ +#!/usr/bin/python +# +# Copyright (c) 2015 Orange +# morgan.richomme@orange.com +# +# 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 +# +# This script is used to get data from test DB +# and format them into a json format adapted for a dashboard +# +# v0.1: basic example +# +import json +import requests +from vPing2Dashboard import format_vPing_for_dashboard + + +class TestCriteria: + + """ describes the test criteria platform """ + def __init__(self): + self.project = '' + self.testcase = '' + self.pod_id = -1 + self.duration = 'all' + self.version = 'all' + self.installer = 'all' + + def setCriteria(self, project, testcase, pod_id, + duration, version, installer): + self.project = project + self.testcase = testcase + self.pod_id = pod_id + self.duration = duration + self.version = version + self.installer = installer + + def format_criteria(self, name): + if(name == 'all' or name == 0): + return "" + else: + if(type(name) == int): + return "-" + str(name) + else: + return "-" + name + + def format(self): + pod_name = self.format_criteria(self.pod_id) + version_name = self.format_criteria(self.version) + installer_name = self.format_criteria(self.installer) + duration_name = self.format_criteria(self.duration) + try: + fileName = "result-" + self.project + "-" + self.testcase + \ + pod_name + version_name + installer_name + \ + duration_name + ".json" + except: + print "Impossible to format json file name" + return fileName + + +def get_pods(db_url): + # retrieve the list of pods + url = db_url + "/pods" + # Build headers + headers = {'Content-Type': 'application/json'} + + try: + db_data = requests.get(url, headers=headers) + # Get result as a json object + pods_data = json.loads(db_data.text) + # Get results + pods = pods_data['pods'] + pods_table = [] + for pod in pods: + # cast int becase otherwise API retrieve 1.0 + # TODO check format with API + pods_table.append(int(pod['_id'])) + + pods_table.append(0) # 0 means all the pods here + return pods_table + except: + print "Error retrieving the list of PODs" + return None + + +def get_versions(db_url): + # retrieve the list of versions + # TODO not supported in API yet + url = db_url + "/versions" + # Build headers + headers = {'Content-Type': 'application/json'} + + try: + db_data = requests.get(url, headers=headers) + # Get result as a json object + versions_data = json.loads(db_data.text) + # Get results + versions = versions_data['versions'] + + versions_table = [] + for version in versions: + versions_table.append(version['version']) + + versions_table.append('all') + + return versions_table + except: + print "Error retrieving the list of OPNFV versions" + return None + + +def get_installers(db_url): + # retrieve the list of installers + # TODO not supported in API yet + url = db_url + "/installers" + # Build headers + headers = {'Content-Type': 'application/json'} + + try: + db_data = requests.get(url, headers=headers) + # Get result as a json object + installers_data = json.loads(db_data.text) + # Get results + installers = installers_data['installers'] + + installers_table = [] + for installer in installers: + installers_table.append(installer['installer']) + + installers_table.append('all') + + return installers + except: + print "Error retrieving the list of OPNFV installers" + return None + + +def get_testcases(db_url, project): + # retrieve the list of pods + url = db_url + "/test_projects/" + project + "/cases" + # Build headers + headers = {'Content-Type': 'application/json'} + + try: + db_data = requests.get(url, headers=headers) + # Get result as a json object + testcases_data = json.loads(db_data.text) + # Get results + testcases = testcases_data['test_cases'] + testcases_table = [] + for testcase in testcases: + testcases_table.append(testcase['name']) + + testcases_table.append('all') + + return testcases_table + except: + print "Error retrieving the list of testcases" + return None + + +def get_results(db_url, test_criteria): + + # use param to filter request to result DB + # if not precised => no filter + # filter criteria: + # - POD + # - versions + # - installers + # - testcase + # - test projects + # - timeframe (last 30 days, 365 days, since beginning of the project) + # e.g. + # - vPing tests since 2 months + # - Tempest tests on LF POD2 fuel based / Arno stable since the beginning + # - yardstick tests on any POD since 30 days + # - Qtip tests on dell-test1 POD + # + # params = {"pod_id":pod_id, "testcase":testcase} + # filter_date = days # data from now - days + + # test_project = test_criteria.project + testcase = test_criteria.testcase + # duration_frame = test_criteria.duration + # version = test_criteria.version + # installer_type = test_criteria.installer + pod_id = test_criteria.pod_id + + pod_criteria = "" + if (pod_id > 0): + pod_criteria = "&pod=" + str(pod_id) + + # TODO complete params (installer type, testcase, version ) + # need API to be up to date + # we assume that criteria could be used at the API level + # no need to processing on date for instance + params = {"pod_id": pod_id} + + # Build headers + headers = {'Content-Type': 'application/json'} + + url = db_url + "/results?case=" + testcase + pod_criteria + + # Send Request to Test DB + myData = requests.get(url, data=json.dumps(params), headers=headers) + # Get result as a json object + myNewData = json.loads(myData.text) + + # Get results + myDataResults = myNewData['test_results'] + + return myDataResults + + +def generateJson(test_name, test_case, db_url): + # pod_id = 1 + # test_version = 'Arno master' + # test_installer = 'fuel' + # test_retention = 30 + + pods = get_pods(db_url) + versions = ['ArnoR1', 'ArnoSR1', 'all'] # not available in the API yet + installers = ['fuel', 'foreman', 'all'] # not available in the API yet + test_durations = [90, 365, 'all'] # not available through the API yet + + # For all the PoDs + for pod in pods: + # all the versions + for version in versions: + # all the installers + for installer in installers: + # all the retention time + for test_duration in test_durations: + + criteria = TestCriteria() + criteria.setCriteria(test_name, test_case, pod, + test_duration, version, installer) + format_data_for_dashboard(criteria) + + +def format_data_for_dashboard(criteria): + + # Depending on the use case, json for dashboarding is customized + # depending on the graph you want to show + + if (criteria.testcase == "vPing"): + format_vPing_for_dashboard(criteria) diff --git a/testcases/Dashboard/functest2Dashboard.py b/testcases/Dashboard/functest2Dashboard.py new file mode 100644 index 000000000..c03ddbd14 --- /dev/null +++ b/testcases/Dashboard/functest2Dashboard.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +# +# Copyright (c) 2015 Orange +# morgan.richomme@orange.com +# +# 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 +# +# This script is used to get data from test DB +# and format them into a json format adapted for a dashboard +# +# v0.1: basic example +# +import logging +import argparse +import pprint +import dashboard_utils +import os +import yaml + +pp = pprint.PrettyPrinter(indent=4) + +parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") +parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") +args = parser.parse_args() + +""" logging configuration """ +logger = logging.getLogger('config_functest') +logger.setLevel(logging.DEBUG) + +ch = logging.StreamHandler() +if args.debug: + ch.setLevel(logging.DEBUG) +else: + ch.setLevel(logging.INFO) + +formatter = logging.Formatter('%(asctime)s - %(name)s -\ + %(levelname)s - %(message)s') +ch.setFormatter(formatter) +logger.addHandler(ch) + +if not os.path.exists(args.repo_path): + logger.error("Repo directory not found '%s'" % args.repo_path) + exit(-1) + +with open(args.repo_path+"testcases/config_functest.yaml") as f: + functest_yaml = yaml.safe_load(f) +f.close() + +""" global variables """ +# Directories +HOME = os.environ['HOME']+"/" +REPO_PATH = args.repo_path +TEST_DB = functest_yaml.get("results").get("test_db_url") + + +def main(): + try: + logger.info("Functest test result generation for dashboard") + + # TODO create the loop to provide all the json files + logger.debug("Retrieve all the testcases from DB") + test_cases = dashboard_utils.get_testcases(TEST_DB, "functest") + + # TODO to be refactor once graph for Tempest, rally and ODL ready + # Do it only for vPing in first stage + for case in test_cases: + logger.debug("Generate " + case + " json files") + dashboard_utils.generateJson('functest', case, TEST_DB) + + logger.info("Functest json files for dashboard successfully generated") + except: + logger.error("Impossible to generate json files for dashboard") + + +if __name__ == '__main__': + main() diff --git a/testcases/Dashboard/odl2Dashboard.py b/testcases/Dashboard/odl2Dashboard.py new file mode 100644 index 000000000..12247663e --- /dev/null +++ b/testcases/Dashboard/odl2Dashboard.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# +# Copyright (c) 2015 Orange +# morgan.richomme@orange.com +# +# 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 +# +# This script is used to build json files for the dashboard +# for the ODL test case +# +# v0.1: basic example +# +import logging +import argparse +import pprint +# import json +# import dashboard_utils +import os +import yaml + +pp = pprint.PrettyPrinter(indent=4) + +parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") +parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") +args = parser.parse_args() + +""" logging configuration """ +logger = logging.getLogger('config_functest') +logger.setLevel(logging.DEBUG) + +if not os.path.exists(args.repo_path): + logger.error("Repo directory not found '%s'" % args.repo_path) + exit(-1) + +with open(args.repo_path+"testcases/config_functest.yaml") as f: + functest_yaml = yaml.safe_load(f) +f.close() + +""" global variables """ +# Directories +HOME = os.environ['HOME']+"/" +REPO_PATH = args.repo_path +TEST_DB = functest_yaml.get("results").get("test_db_url") + + +def format_tempest_for_dashboard(criteria): + logger.debug("generate dashboard json files for ODL suite") diff --git a/testcases/Dashboard/rally2Dashboard.py b/testcases/Dashboard/rally2Dashboard.py new file mode 100644 index 000000000..20e597468 --- /dev/null +++ b/testcases/Dashboard/rally2Dashboard.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# +# Copyright (c) 2015 Orange +# morgan.richomme@orange.com +# +# 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 +# +# This script is used to build json files for the dashboard +# for the rally test case +# +# v0.1: basic example +# +import logging +import argparse +import pprint +# import json +# import dashboard_utils +import os +import yaml + +pp = pprint.PrettyPrinter(indent=4) + +parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") +parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") +args = parser.parse_args() + +""" logging configuration """ +logger = logging.getLogger('config_functest') +logger.setLevel(logging.DEBUG) + +if not os.path.exists(args.repo_path): + logger.error("Repo directory not found '%s'" % args.repo_path) + exit(-1) + +with open(args.repo_path+"testcases/config_functest.yaml") as f: + functest_yaml = yaml.safe_load(f) +f.close() + +""" global variables """ +# Directories +HOME = os.environ['HOME']+"/" +REPO_PATH = args.repo_path +TEST_DB = functest_yaml.get("results").get("test_db_url") + + +def format_tempest_for_dashboard(criteria): + logger.debug("generate dashboard json files for rally") diff --git a/testcases/Dashboard/tempest2Dashboard.py b/testcases/Dashboard/tempest2Dashboard.py new file mode 100644 index 000000000..8cbecbbc8 --- /dev/null +++ b/testcases/Dashboard/tempest2Dashboard.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# +# Copyright (c) 2015 Orange +# morgan.richomme@orange.com +# +# 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 +# +# This script is used to build json files for the dashboard +# for the tempest test case +# +# v0.1: basic example +# +import logging +import argparse +import pprint +# import json +# import dashboard_utils +import os +import yaml + +pp = pprint.PrettyPrinter(indent=4) + +parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") +parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") +args = parser.parse_args() + +""" logging configuration """ +logger = logging.getLogger('config_functest') +logger.setLevel(logging.DEBUG) + +if not os.path.exists(args.repo_path): + logger.error("Repo directory not found '%s'" % args.repo_path) + exit(-1) + +with open(args.repo_path+"testcases/config_functest.yaml") as f: + functest_yaml = yaml.safe_load(f) +f.close() + +""" global variables """ +# Directories +HOME = os.environ['HOME']+"/" +REPO_PATH = args.repo_path +TEST_DB = functest_yaml.get("results").get("test_db_url") + + +def format_tempest_for_dashboard(criteria): + logger.debug("generate dashboard json files for Tempest") diff --git a/testcases/Dashboard/vPing2Dashboard.py b/testcases/Dashboard/vPing2Dashboard.py index d32187afd..f799e280f 100644 --- a/testcases/Dashboard/vPing2Dashboard.py +++ b/testcases/Dashboard/vPing2Dashboard.py @@ -9,8 +9,8 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -# This script is used to get data from test DB -# and format them into a json format adapted for a dashboard +# This script is used to build json files for the dashboard +# for the vPing test case # # v0.1: basic example # @@ -18,65 +18,40 @@ import logging import argparse import pprint import json -import requests +import dashboard_utils +import os +import yaml pp = pprint.PrettyPrinter(indent=4) parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") args = parser.parse_args() """ logging configuration """ -logger = logging.getLogger('vPing2DashBoard') +logger = logging.getLogger('config_functest') logger.setLevel(logging.DEBUG) -ch = logging.StreamHandler() -if args.debug: - ch.setLevel(logging.DEBUG) -else: - ch.setLevel(logging.INFO) - -formatter = logging.Formatter # retrieve info from DB -('%(asctime)s - %(name)s - %(levelname)s - %(message)s') -ch.setFormatter(formatter) -logger.addHandler(ch) - - -def get_data(test_project, testcase, pod_id, days, version, installerType): - # ugly hard coding => TODO use yaml config file - url = "http://213.77.62.197:80/results" - - # use param to filter request to result DB - # if not precised => no filter - # filter criteria: - # - POD - # - versions - # - installers - # - testcase - # - test projects - # - timeframe (last 30 days, 365 days, since beginning of the project) - # e.g. - # - vPing tests since 2 months - # - Tempest tests on LF POD2 fuel based / Arno stable since the beginning - # - yardstick tests on any POD since 30 days - # - Qtip tests on dell-test1 POD - # - # params = {"pod_id":pod_id, "testcase":testcase} - # filter_date = days # data from now - days - - # TODO complete params (installer type, testcase, version ) - params = {"pod_id": 1} - - # Build headers - headers = {'Content-Type': 'application/json'} - - # Send Request to Test DB - myData = requests.get(url, data=json.dumps(params), headers=headers) - # Get result as a json object - myNewData = json.loads(myData.text) +if not os.path.exists(args.repo_path): + logger.error("Repo directory not found '%s'" % args.repo_path) + exit(-1) + +with open(args.repo_path+"testcases/config_functest.yaml") as f: + functest_yaml = yaml.safe_load(f) +f.close() + +""" global variables """ +# Directories +HOME = os.environ['HOME']+"/" +REPO_PATH = args.repo_path +TEST_DB = functest_yaml.get("results").get("test_db_url") + + +def format_vPing_for_dashboard(criteria): # Get results - myDataResults = myNewData['test_results'] + myDataResults = dashboard_utils.get_results(TEST_DB, criteria) # Depending on the use case, json for dashboarding is customized # depending on the graph you want to show @@ -84,6 +59,7 @@ def get_data(test_project, testcase, pod_id, days, version, installerType): test_data = [{'description': 'vPing results for Dashboard'}] # Graph 1: Duration = f(time) + # *************************** new_element = [] for data in myDataResults: new_element.append({'x': data['creation_date'], @@ -96,6 +72,7 @@ def get_data(test_project, testcase, pod_id, days, version, installerType): 'data_set': new_element}) # Graph 2: bar + # ************ nbTest = 0 nbTestOk = 0 @@ -104,24 +81,14 @@ def get_data(test_project, testcase, pod_id, days, version, installerType): if data['details']['status'] == "OK": nbTestOk += 1 - # Generate json file - # TODO complete with other criteria - fileName = "result-" + test_project + "-" + testcase + "-" + str(days) + "-" + str(pod_id) + "-status.json" - test_data.append({'name': "vPing status", 'info': {"type": "bar"}, 'data_set': [{'Nb tests': nbTest, 'Nb Success': nbTestOk}]}) - fileName = "result-" + test_project + "-" + testcase + ".json" + # Generate json file + fileName = criteria.format() + logger.debug("Generate json file:" + fileName) with open(fileName, "w") as outfile: json.dump(test_data, outfile, indent=4) - - -def main(): - get_data('functest', 'vPing', 1, 30, 'Arno master', 'fuel') - - -if __name__ == '__main__': - main() diff --git a/testcases/config_functest.yaml b/testcases/config_functest.yaml index 484d66eb6..c38b46066 100644 --- a/testcases/config_functest.yaml +++ b/testcases/config_functest.yaml @@ -39,4 +39,4 @@ vping: ip_2: 192.168.120.40 results: - test_db_url: http://213.77.62.197:80/results + test_db_url: http://213.77.62.197 diff --git a/testcases/vPing/CI/libraries/vPing.py b/testcases/vPing/CI/libraries/vPing.py index 56f4fc538..5d68f2229 100644 --- a/testcases/vPing/CI/libraries/vPing.py +++ b/testcases/vPing/CI/libraries/vPing.py @@ -246,7 +246,7 @@ def cleanup(nova, neutron, network_dic): def push_results_to_db(payload): # TODO move DB creds into config file - url = TEST_DB + url = TEST_DB + "/results" params = {"project_name": "functest", "case_name": "vPing", "pod_id": 1, "details": payload} headers = {'Content-Type': 'application/json'} -- cgit 1.2.3-korg