diff options
Diffstat (limited to 'lib/auto/testcase')
-rw-r--r-- | lib/auto/testcase/EdgeCloud/AutoOSPlatCheck.py | 164 | ||||
-rw-r--r-- | lib/auto/testcase/EdgeCloud/AutoOSPlatTest.py | 80 | ||||
-rw-r--r-- | lib/auto/testcase/EdgeCloud/__init__.py | 0 | ||||
-rw-r--r-- | lib/auto/testcase/resiliency/AutoResilIftCloud.py | 46 | ||||
-rw-r--r-- | lib/auto/testcase/resiliency/AutoResilItfCloud.py | 227 | ||||
-rw-r--r-- | lib/auto/testcase/resiliency/AutoResilMain.py | 7 | ||||
-rw-r--r-- | lib/auto/testcase/resiliency/AutoResilMgTestDef.py | 276 | ||||
-rw-r--r-- | lib/auto/testcase/resiliency/clouds.yaml | 91 |
8 files changed, 824 insertions, 67 deletions
diff --git a/lib/auto/testcase/EdgeCloud/AutoOSPlatCheck.py b/lib/auto/testcase/EdgeCloud/AutoOSPlatCheck.py new file mode 100644 index 0000000..5a19109 --- /dev/null +++ b/lib/auto/testcase/EdgeCloud/AutoOSPlatCheck.py @@ -0,0 +1,164 @@ +# !/usr/bin/python +# +# Copyright (c) 2018 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 os +import re + +import logging +import json +import requests + +logger = logging.getLogger(__name__) + +class OS_env_check: + """Edge Clould Basic Env Function definition""" + + + def __init__(self): + """Variable Intitialization""" + self.osver = "v2.0" + self.imagever = "v2" + self.keystone_ver = 'v3' + self.tacker_ver = 'v1.0' + + def ping_os_endpoints(self): + "Simple ping check to OpenStack endpoint" + + os_auth_url = os.environ.get('OS_AUTH_URL', None) + password = os.environ.get('OS_PASSWORD', None) + if os_auth_url is None: + logger.error("Source the OpenStack credentials first") + exit(0) + try: + if os_auth_url: + endpoint_ip = re.search(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', os_auth_url).group() + response = os.system("ping -c 1 " + endpoint_ip + ">/dev/null") + if response == 0: + return 0 + else: + logger.error("Cannot talk to the OpenStack endpoint %s\n" % endpoint_ip) + exit(0) + except Exception: + logger.exception('Errors when verifying connectivity to %s', endpoint_ip) + return False + + def fetch_token(self): + "Fetch OS_AUTH_TOKEN from OpenStack Service" + + #(e.g.)url = 'http://10.164.16.100:5000/identity/v3/auth/tokens' + url = 'http://'+self.endpoint_ip+':5000/'+self.keystone_ver+'/auth/tokens' + data = '{"auth":{"identity":{"methods":["password"],"password":{"user":' \ + '{"domain":{"name":"default"},"name":"admin",' \ + '"password":"admin"}}},"scope":{"project":' \ + '{"domain":{"name":"default"},"name":"admin"}}}}' + headers = {"Accept": "application/json"} + try: + response = requests.post(url, headers=headers, data=data) + header_data = (response.headers) + token = header_data['X-Subject-Token'] + response_body = response.content + except Exception: + logger.error(" Failure: Not able to send API request for creating token") + if (response.status_code == 201): + response_body = response.content.decode('utf-8') + res = json.loads(response_body) + admin_user_id= res['token']['user']['id'] + return response.status_code,token + + def check_os_running_services(self): + "Get active/running OpenStack Services" + + url = 'http://' + self.endpoint_ip + ':5000/' + self.keystone_ver + '/auth/tokens' + data = '{"auth": {"identity": {"methods": ["password"],"password": \ + {"user": {"domain": {"name": "default"},"name": "admin",\ + "password": "admin"}}},\ + "scope": {"project": {"domain": {"name": "default"},"name": "admin"}}}}' + headers = {"Accept": "application/json"} + response = requests.post(url, headers=headers, data=data) + service = [] + url_ep = [] + if (response.status_code == 201): + response_body = response.content.decode('utf-8') + res = json.loads(response_body) + catalogs = res['token']['catalog'] + for x in catalogs: + services = x['name'] + if x['name'] is not None: + service.append(x['name']) + endpoints = x['endpoints'] + for y in endpoints: + url = y['url'] + if y['url'] not in url_ep: + url_ep.append(url) + return response.status_code,service,url_ep + + def check_nova_service(self, endpoints, token): + """ checks that a simple nova operation works """ + + try: + nova_url = endpoints.get('nova') + url = nova_url+ '/servers/detail' + headers = {"Content-Type": "application/json", "X-Auth-Token": token} + response = requests.get(url, headers=headers) + if (response.status_code == 200): + logger.info("Nova service is Active") + except Exception as error: + logger.error("Nova service is FAILED") + raise error + return response.status_code + + def check_neutron_service (self, endpoints, token): + """ checks that a simple neutron operation works """ + + try: + neutron_url = endpoints.get('neutron') + url = neutron_url +self.osver+'/networks' + headers = {"Content-Type": "application/json", "X-Auth-Token": token} + response = requests.get(url, headers=headers) + if (response.status_code == 200): + logger.info("Neutron service is Active") + except Exception as error: + logger.error("Neutron service is FAILED") + raise error + return response.status_code + + def check_glance_service(self, endpoints, token): + """ checks that a simple glance operation works """ + + try: + glance_url = endpoints.get('glance') + url = glance_url + '/' + self.imagever + '/images' + headers = {"Content-Type": "application/json", "X-Auth-Token": token} + response = requests.get(url, headers=headers) + if (response.status_code == 200): + logger.info("Glance:Image service is Active") + except Exception as error: + logger.error("Glance:Image service is FAILED") + raise error + return response.status_code + + def check_tacker_service(self, endpoints, token): + """ checks that a simple tacker operation works """ + + try: + if 'tacker' in endpoints.keys(): + logger.info("Tacker VNF Manager service is running") + else: + logger.error("No Tacker VNF Manager service is running") + return (0) + tacker_url = endpoints.get('tacker') + url = tacker_url + '/' + self.tacker_ver + '/vnf.json' + headers = {"Content-Type": "application/json", "X-Auth-Token": token} + response = requests.get(url, headers=headers) + if (response.status_code == 200): + logger.info("Tacker:VNF Manager has active VNFs") + except Exception as error: + logger.error("Tacker:No Active VNFs") + raise error + return response.status_code diff --git a/lib/auto/testcase/EdgeCloud/AutoOSPlatTest.py b/lib/auto/testcase/EdgeCloud/AutoOSPlatTest.py new file mode 100644 index 0000000..ef99ce5 --- /dev/null +++ b/lib/auto/testcase/EdgeCloud/AutoOSPlatTest.py @@ -0,0 +1,80 @@ +"""Script to Test the AUTO Edge Cloud OpenStack Services.""" +# !/usr/bin/python +# +# Copyright (c) 2018 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 +#fetch_token +# http://www.apache.org/licenses/LICENSE-2.0 +# +# ########################################################################### +# OPNFV AUTO Edge Cloud Script +# **** Scripted by Mohankumar Navaneethan - mnavaneethan@mvista.com ****** +# ########################################################################### + +# Testcase 1 : Ping OpenStack Endpoints +# Testcase 2 : Creation of Auth-Token +# TestCase 3 : Check OpenStack Active Services +# TestCase 4 : Check OpenStack Nova Service +# TestCase 5 : Check OpenStack Neutron Service +# TestCase 6 : Check OpenStack Glance Service +# TestCase 7 : Check OpenStack Tacker Service. +# ########################################################################### +# +import logging +from AutoOSPlatCheck import OS_env_check + + +class Env_check: + """Script to Test AUTO Edge Cloud OpenStack Services.""" + logger = logging.getLogger(__name__) + Env_obj = OS_env_check() + print("################################################################") + print(" OPNFV AUTO Script ") + print("################################################################") + logger.info("Prerequisites OpenStack configuration for AUTO") + ######################################################################### + logger.info("\t1. Ping OpenStack Endpoints") + if (Env_obj.ping_endpoints == 0): + logger.info("\t\tPing to OpenStack Endpoint is successfull") + else: + logger.error("\t\tPing to OpenStack Endpoint is NOT successfull") + + logger.info("\t2. Creation of Auth-Token") + response_code , token = Env_obj.fetch_token() + if (response_code == 201): + logger.info("\t\tCreation of Token is successfull") + else: + logger.error("\t\t : Creation of Token is NOT successfull") + logger.info("\t3. Check OpenStack Active Services") + status, services, endpoint = Env_obj.check_os_running_services() + endpoints = dict(zip(services, endpoint)) + if (status == 201): + logger.info("\t\tCheck OpenStack Active Services is successfull") + else: + logger.error("\t\tCheck OpenStack Active Services is NOT successfull") + + logger.info("\t4. Check OpenStack Nova Service") + if (Env_obj.check_nova_service(endpoints, token) == 200): + logger.info("\t\tNova service is responsive") + else: + logger.error("\t\tNova service is NOT responsive") + + logger.info("\t5. Check OpenStack Neutron Service") + if (Env_obj.check_neutron_service(endpoints, token) == 200): + logger.info("\t\tNeutron service is responsive") + else: + logger.error("\t\tNeutron service is NOT responsive") + + logger.info("\t6. Check OpenStack Glance Service") + if (Env_obj.check_glance_service(endpoints, token) == 200): + logger.info("\t\tGlance service is responsive") + else: + logger.error("\t\tGlance service is NOT responsive") + + logger.info("\t7. Check OpenStack Tacker Service") + if (Env_obj.check_glance_service(endpoints, token) == 200): + logger.info("\t\tTacker VNF Manager service is responsive") + else: + logger.error("\t\tTacker VNF Manager is NOT responsive") diff --git a/lib/auto/testcase/EdgeCloud/__init__.py b/lib/auto/testcase/EdgeCloud/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/auto/testcase/EdgeCloud/__init__.py diff --git a/lib/auto/testcase/resiliency/AutoResilIftCloud.py b/lib/auto/testcase/resiliency/AutoResilIftCloud.py deleted file mode 100644 index 01e948b..0000000 --- a/lib/auto/testcase/resiliency/AutoResilIftCloud.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 - -# ===============LICENSE_START======================================================= -# Apache-2.0 -# =================================================================================== -# Copyright (C) 2018 Wipro. All rights reserved. -# =================================================================================== -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ===============LICENSE_END========================================================= - - -# OPNFV Auto project -# https://wiki.opnfv.org/pages/viewpage.action?pageId=12389095 - -# Use case 02: Resilience Improvements -# Use Case description: https://wiki.opnfv.org/display/AUTO/Auto+Use+Cases -# Test case design: https://wiki.opnfv.org/display/AUTO/Use+case+2+%28Resilience+Improvements+through+ONAP%29+analysis - -# This module: interfaces with cloud managers (OpenStack, Kubernetes, AWS, ...) - - -###################################################################### -# import statements -import AutoResilGlobal - - -def f1(): - return 0 - -# OpenStack HTTP API: https://developer.openstack.org/api-ref/compute/ -#{your_compute_service_url}/servers/{server_id}/action -#GET -#http://mycompute.pvt/compute/v2.1/servers/{server_id}/suspend -#http://mycompute.pvt/compute/v2.1/servers/{server_id}/resume - diff --git a/lib/auto/testcase/resiliency/AutoResilItfCloud.py b/lib/auto/testcase/resiliency/AutoResilItfCloud.py new file mode 100644 index 0000000..69c5327 --- /dev/null +++ b/lib/auto/testcase/resiliency/AutoResilItfCloud.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 + +# ===============LICENSE_START======================================================= +# Apache-2.0 +# =================================================================================== +# Copyright (C) 2018 Wipro. All rights reserved. +# =================================================================================== +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ===============LICENSE_END========================================================= + + +# OPNFV Auto project +# https://wiki.opnfv.org/pages/viewpage.action?pageId=12389095 + +# Use case 02: Resilience Improvements +# Use Case description: https://wiki.opnfv.org/display/AUTO/Auto+Use+Cases +# Test case design: https://wiki.opnfv.org/display/AUTO/Use+case+2+%28Resilience+Improvements+through+ONAP%29+analysis + +# This module: interfaces with cloud managers (OpenStack, Kubernetes, AWS, ...) + + +###################################################################### +# import statements +import AutoResilGlobal + +# for method 1 and 2 +#import openstack + +#for method 3 +from openstack import connection + +def os_list_servers(conn): + """List OpenStack servers.""" + # see https://docs.openstack.org/python-openstacksdk/latest/user/proxies/compute.html + if conn != None: + print("\nList Servers:") + + try: + i=1 + for server in conn.compute.servers(): + print('Server',str(i),'\n',server,'n') + i+=1 + except Exception as e: + print("Exception:",type(e), e) + print("No Servers\n") + + +def os_list_networks(conn): + """List OpenStack networks.""" + # see https://docs.openstack.org/python-openstacksdk/latest/user/proxies/network.html + if conn != None: + print("\nList Networks:") + + try: + i=1 + for network in conn.network.networks(): + print('Network',str(i),'\n',network,'n') + i+=1 + except Exception as e: + print("Exception:",type(e), e) + print("No Networks\n") + + +def os_list_volumes(conn): + """List OpenStack volumes.""" + # see https://docs.openstack.org/python-openstacksdk/latest/user/proxies/block_storage.html + # note: The block_storage member will only be added if the service is detected. + if conn != None: + print("\nList Volumes:") + + try: + i=1 + for volume in conn.block_storage.volumes(): + print('Volume',str(i),'\n',volume,'n') + i+=1 + except Exception as e: + print("Exception:",type(e), e) + print("No Volumes\n") + + +def os_list_users(conn): + """List OpenStack users.""" + # see https://docs.openstack.org/python-openstacksdk/latest/user/guides/identity.html + if conn != None: + print("\nList Users:") + + try: + i=1 + for user in conn.identity.users(): + print('User',str(i),'\n',user,'n') + i+=1 + except Exception as e: + print("Exception:",type(e), e) + print("No Users\n") + +def os_list_projects(conn): + """List OpenStack projects.""" + # see https://docs.openstack.org/python-openstacksdk/latest/user/guides/identity.html + if conn != None: + print("\nList Projects:") + + try: + i=1 + for project in conn.identity.projects(): + print('Project',str(i),'\n',project,'n') + i+=1 + except Exception as e: + print("Exception:",type(e), e) + print("No Projects\n") + + +def os_list_domains(conn): + """List OpenStack domains.""" + # see https://docs.openstack.org/python-openstacksdk/latest/user/guides/identity.html + if conn != None: + print("\nList Domains:") + + try: + i=1 + for domain in conn.identity.domains(): + print('Domain',str(i),'\n',domain,'n') + i+=1 + except Exception as e: + print("Exception:",type(e), e) + print("No Domains\n") + + + + + + + +def gdtest_openstack(): + # Method 1: assume there is a clouds.yaml file in PATH, starting path search with local directory + #conn = openstack.connect(cloud='armopenstack', region_name='RegionOne') + #conn = openstack.connect(cloud='hpe16openstack', region_name='RegionOne') + # getting error: AttributeError: module 'openstack' has no attribute 'connect' + + # Method 2: pass arguments directly, all as strings + # see details at https://docs.openstack.org/python-openstacksdk/latest/user/connection.html + # conn = openstack.connect( + # auth_url='https://10.10.50.103:5000/v2.0', + # project_name='admin', + # username='admin', + # password='opnfv_secret', + # region_name='RegionOne', + # ) + # conn = openstack.connect( + # auth_url='http://10.16.0.101:5000/v2.0', + # project_name='admin', + # username='admin', + # password='opnfv_secret', + # region_name='RegionOne', + # ) + # getting error: AttributeError: module 'openstack' has no attribute 'connect' + + # Method 3: create Connection object directly + auth_args = { + #'auth_url': 'https://10.10.50.103:5000/v2.0', # Arm + #'auth_url': 'http://10.16.0.101:5000/v2.0', # hpe16, Euphrates + 'auth_url': 'http://10.16.0.107:5000/v3', # hpe16, Fraser + 'project_name': 'admin', + 'username': 'admin', + 'password': 'opnfv_secret', + 'region_name': 'RegionOne', + 'domain': 'Default'} + conn = connection.Connection(**auth_args) + + #conn = connection.Connection( + #auth_url='http://10.16.0.107:5000/v3', + #project_name='admin', + #username='admin', + #password='opnfv_secret') + + + os_list_servers(conn) + os_list_networks(conn) + os_list_volumes(conn) + os_list_users(conn) + os_list_projects(conn) + os_list_domains(conn) + + + # get_server(server): Get a single Server + # Parameters: server – The value can be the ID of a server or a Server instance. + # conn.compute.get_server(server) + + # suspend_server(server): Suspends a server and changes its status to SUSPENDED. + # Parameters: server – Either the ID of a server or a Server instance. + # conn.compute.suspend_server(server) + + # resume_server(server): Resumes a suspended server and changes its status to ACTIVE. + # Parameters: server – Either the ID of a server or a Server instance. + # conn.compute.resume_server(server) + + +def main(): + + print("\nTest Auto Cloud Interface") + + gdtest_openstack() + + print("Ciao\n") + +if __name__ == "__main__": + main() + + +# OpenStack HTTP API: https://developer.openstack.org/api-ref/compute/ +#{your_compute_service_url}/servers/{server_id}/action +#GET +#http://mycompute.pvt/compute/v2.1/servers/{server_id}/suspend +#http://mycompute.pvt/compute/v2.1/servers/{server_id}/resume +# but better use the python unified client + + diff --git a/lib/auto/testcase/resiliency/AutoResilMain.py b/lib/auto/testcase/resiliency/AutoResilMain.py index 03e7151..2f67bdf 100644 --- a/lib/auto/testcase/resiliency/AutoResilMain.py +++ b/lib/auto/testcase/resiliency/AutoResilMain.py @@ -164,8 +164,11 @@ def main(): print("Problem with test definition: empty") sys.exit() # stop entire program, because test definition MUST be correct else: - # TODO run test: method of TestDefinition, or function ? - pass + # TODO run test: call selected test definition run_test_code() method + test_def = get_indexed_item_from_list(selected_test_def_ID, AutoResilGlobal.test_definition_list) + if test_def != None: + test_def.run_test_code() + else: print("No current selection of Test Definition. Try again.") continue diff --git a/lib/auto/testcase/resiliency/AutoResilMgTestDef.py b/lib/auto/testcase/resiliency/AutoResilMgTestDef.py index 757d1e5..9667f93 100644 --- a/lib/auto/testcase/resiliency/AutoResilMgTestDef.py +++ b/lib/auto/testcase/resiliency/AutoResilMgTestDef.py @@ -54,6 +54,7 @@ import sys from enum import Enum from datetime import datetime, timedelta import AutoResilGlobal +#import openstack # Constants with definition file names FILE_PHYSICAL_RESOURCES = "ResourcesPhysical.bin" @@ -152,8 +153,6 @@ def get_indexed_item_from_file(index, file_name): - - ###################################################################### class TestCase(AutoBaseObject): @@ -269,7 +268,8 @@ class TestDefinition(AutoBaseObject): test_def_associatedMetricsIDs, test_def_recipientIDs, test_def_testCLICommandSent, - test_def_testAPICommandSent): + test_def_testAPICommandSent, + test_def_codeID): # superclass constructor AutoBaseObject.__init__(self, test_def_ID, test_def_name) @@ -291,6 +291,93 @@ class TestDefinition(AutoBaseObject): # associated test API commands to Recipients (list of data objects) self.test_API_command_sent_list = test_def_testAPICommandSent + # constant for total number of test codes (one of them is used per TestDefinition instance); would be 1 per test case + self.TOTAL_NUMBER_OF_TEST_CODES = 10 + # chosen test code ID (the ID is an index in a list of method names) for this instance; convention: [1;N]; in list, index is [0;N-1] + # a test code could use for instance Python clients (for OpenStack, Kubernetes, etc.), or HTTP APIs, or some of the CLI/API commands + try: + if 1 <= test_def_codeID <= self.TOTAL_NUMBER_OF_TEST_CODES: + self.test_code_ID = test_def_codeID + else: + print("TestDefinition constructor: incorrect test_def_codeID=",test_def_codeID) + sys.exit() # stop entire program, because code ID MUST be correct + except Exception as e: + print(type(e), e) + sys.exit() # stop entire program, because code ID MUST be correct + + self.test_code_list = [] # list of method names; leave as per-object method (i.e. not as class methods or as static methods) + # add one by one, for easier later additions of new methods + self.test_code_list.append(self.test_code001) + self.test_code_list.append(self.test_code002) + self.test_code_list.append(self.test_code003) + self.test_code_list.append(self.test_code004) + self.test_code_list.append(self.test_code005) + self.test_code_list.append(self.test_code006) + self.test_code_list.append(self.test_code007) + self.test_code_list.append(self.test_code008) + self.test_code_list.append(self.test_code009) + self.test_code_list.append(self.test_code010) + + + def run_test_code(self): + """Run currently selected test code.""" + try: + test_code_index = self.test_code_ID - 1 # lists are indexed from 0 to N-1 + self.test_code_list[test_code_index]() # invoke corresponding method, via index + except Exception as e: + print(type(e), e) + sys.exit() + + + # library of test codes, probably 1 per test case, so test_case_ID would be the same as test_code_ID + def test_code001(self): + """Test case code number 001.""" + print("This is test_code001 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + def test_code002(self): + """Test case code number 002.""" + print("This is test_code002 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + def test_code003(self): + """Test case code number 003.""" + print("This is test_code003 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + def test_code004(self): + """Test case code number 004.""" + print("This is test_code004 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + def test_code005(self): + """Test case code number 005.""" + print("This is test_code005 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + # here, trigger start code from challenge def (to simulate VM failure), manage Recovery time measurement, + # monitoring of VNF, trigger stop code from challenge def, perform restoration of VNF + challenge_def = get_indexed_item_from_list(self.challenge_def_ID, AutoResilGlobal.challenge_definition_list) + if challenge_def != None: + challenge_def.run_start_challenge_code() + challenge_def.run_stop_challenge_code() + + + def test_code006(self): + """Test case code number 006.""" + print("This is test_code006 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + def test_code007(self): + """Test case code number 007.""" + print("This is test_code007 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + def test_code008(self): + """Test case code number 008.""" + print("This is test_code008 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + def test_code009(self): + """Test case code number 009.""" + print("This is test_code009 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + + def test_code010(self): + """Test case code number 010.""" + print("This is test_code010 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='') + def printout_all(self, indent_level): """Print out all attributes, with an indentation level.""" @@ -304,6 +391,8 @@ class TestDefinition(AutoBaseObject): if test_case != None: test_case.printout_all(indent_level+1) + print(indent, "|-test code ID:", self.test_code_ID, sep='') + print(indent, "|-associated challenge def ID:", self.challenge_def_ID, sep='') challenge_def = get_indexed_item_from_list(self.challenge_def_ID, AutoResilGlobal.challenge_definition_list) if challenge_def != None: @@ -357,6 +446,7 @@ def init_test_definitions(): test_def_recipientIDs = [2] test_def_testCLICommandSent = ["pwd","kubectl describe pods --include-uninitialized=false"] test_def_testAPICommandSent = ["data1","data2"] + test_def_testCodeID = 5 test_definitions.append(TestDefinition(test_def_ID, test_def_name, test_def_challengeDefID, test_def_testCaseID, @@ -364,7 +454,8 @@ def init_test_definitions(): test_def_associatedMetricsIDs, test_def_recipientIDs, test_def_testCLICommandSent, - test_def_testAPICommandSent)) + test_def_testAPICommandSent, + test_def_testCodeID)) # write list to binary file write_list_bin(test_definitions, FILE_TEST_DEFINITIONS) @@ -400,7 +491,8 @@ class ChallengeDefinition(AutoBaseObject): chall_def_startChallengeCLICommandSent, chall_def_stopChallengeCLICommandSent, chall_def_startChallengeAPICommandSent, - chall_def_stopChallengeAPICommandSent): + chall_def_stopChallengeAPICommandSent, + chall_def_codeID): # superclass constructor AutoBaseObject.__init__(self, chall_def_ID, chall_def_name) @@ -431,6 +523,142 @@ class ChallengeDefinition(AutoBaseObject): # if API; to restore to normal self.stop_challenge_API_command_sent = chall_def_stopChallengeAPICommandSent + # constant for total number of challenge codes (one of them is used per ChallengeDefinition instance); + # may be 1 per test case, maybe not (common challenges, could be re-used across test definitions and test cases) + # start and stop challenges are strictly linked: exactly 1 Stop challenge for each Start challenge, so same ID for Start and for Stop + self.TOTAL_NUMBER_OF_CHALLENGE_CODES = 10 + + # chosen start/stop challenge code ID (the ID is an index in a list of method names) for this instance; + # convention: [1;N]; in list, index is [0;N-1] + # a challenge code could use for instance Python clients (for OpenStack, Kubernetes, etc.), or HTTP APIs, or some of the CLI/API commands + try: + if 1 <= chall_def_codeID <= self.TOTAL_NUMBER_OF_CHALLENGE_CODES: + self.challenge_code_ID = chall_def_codeID + else: + print("ChallengeDefinition constructor: incorrect chall_def_codeID=",chall_def_codeID) + sys.exit() # stop entire program, because code ID MUST be correct + except Exception as e: + print(type(e), e) + sys.exit() # stop entire program, because code ID MUST be correct + + # list of method names; leave as per-object method (i.e. not as class methods or as static methods) + self.start_challenge_code_list = [] + self.stop_challenge_code_list = [] + # add one by one, for easier later additions of new methods; MUST be same index for Start and for Stop + self.start_challenge_code_list.append(self.start_challenge_code001) + self.stop_challenge_code_list.append(self.stop_challenge_code001) + self.start_challenge_code_list.append(self.start_challenge_code002) + self.stop_challenge_code_list.append(self.stop_challenge_code002) + self.start_challenge_code_list.append(self.start_challenge_code003) + self.stop_challenge_code_list.append(self.stop_challenge_code003) + self.start_challenge_code_list.append(self.start_challenge_code004) + self.stop_challenge_code_list.append(self.stop_challenge_code004) + self.start_challenge_code_list.append(self.start_challenge_code005) + self.stop_challenge_code_list.append(self.stop_challenge_code005) + self.start_challenge_code_list.append(self.start_challenge_code006) + self.stop_challenge_code_list.append(self.stop_challenge_code006) + self.start_challenge_code_list.append(self.start_challenge_code007) + self.stop_challenge_code_list.append(self.stop_challenge_code007) + self.start_challenge_code_list.append(self.start_challenge_code008) + self.stop_challenge_code_list.append(self.stop_challenge_code008) + self.start_challenge_code_list.append(self.start_challenge_code009) + self.stop_challenge_code_list.append(self.stop_challenge_code009) + self.start_challenge_code_list.append(self.start_challenge_code010) + self.stop_challenge_code_list.append(self.stop_challenge_code010) + + + def run_start_challenge_code(self): + """Run currently selected challenge code, start portion.""" + try: + code_index = self.challenge_code_ID - 1 # lists are indexed from 0 to N-1 + self.start_challenge_code_list[code_index]() # invoke corresponding start method, via index + except Exception as e: + print(type(e), e) + sys.exit() + + def run_stop_challenge_code(self): + """Run currently selected challenge code, stop portion.""" + try: + code_index = self.challenge_code_ID - 1 # lists are indexed from 0 to N-1 + self.stop_challenge_code_list[code_index]() # invoke corresponding stop method, via index + except Exception as e: + print(type(e), e) + sys.exit() + + + + # library of challenge codes + def start_challenge_code001(self): + """Start Challenge code number 001.""" + print("This is start_challenge_code001 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code001(self): + """Stop Challenge code number 001.""" + print("This is stop_challenge_code001 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code002(self): + """Start Challenge code number 002.""" + print("This is start_challenge_code002 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code002(self): + """Stop Challenge code number 002.""" + print("This is stop_challenge_code002 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code003(self): + """Start Challenge code number 003.""" + print("This is start_challenge_code003 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code003(self): + """Stop Challenge code number 003.""" + print("This is stop_challenge_code003 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code004(self): + """Start Challenge code number 004.""" + print("This is start_challenge_code004 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code004(self): + """Stop Challenge code number 004.""" + print("This is stop_challenge_code004 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code005(self): + """Start Challenge code number 005.""" + print("This is start_challenge_code005 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code005(self): + """Stop Challenge code number 005.""" + print("This is stop_challenge_code005 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code006(self): + """Start Challenge code number 006.""" + print("This is start_challenge_code006 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code006(self): + """Stop Challenge code number 006.""" + print("This is stop_challenge_code006 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code007(self): + """Start Challenge code number 007.""" + print("This is start_challenge_code007 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code007(self): + """Stop Challenge code number 007.""" + print("This is stop_challenge_code007 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code008(self): + """Start Challenge code number 008.""" + print("This is start_challenge_code008 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code008(self): + """Stop Challenge code number 008.""" + print("This is stop_challenge_code008 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code009(self): + """Start Challenge code number 009.""" + print("This is start_challenge_code009 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code009(self): + """Stop Challenge code number 009.""" + print("This is stop_challenge_code009 from ChallengeDefinition #",self.ID, sep='') + + def start_challenge_code010(self): + """Start Challenge code number 010.""" + print("This is start_challenge_code010 from ChallengeDefinition #",self.ID, sep='') + def stop_challenge_code010(self): + """Stop Challenge code number 010.""" + print("This is stop_challenge_code010 from ChallengeDefinition #",self.ID, sep='') + + def printout_all(self, indent_level): """Print out all attributes, with an indentation level.""" @@ -441,6 +669,8 @@ class ChallengeDefinition(AutoBaseObject): print(indent, "|-challenge type:", self.challenge_type, sep='') + print(indent, "|-challenge code ID:", self.challenge_code_ID, sep='') + print(indent, "|-associated recipient ID:", self.recipient_ID, sep='') recipient = get_indexed_item_from_list(self.recipient_ID, AutoResilGlobal.recipient_list) if recipient != None: @@ -498,6 +728,8 @@ def init_challenge_definitions(): chall_def_startChallengeAPICommandSent = [] chall_def_stopChallengeAPICommandSent = [] + chall_def_codeID = 5 + challenge_defs.append(ChallengeDefinition(chall_def_ID, chall_def_name, chall_def_challengeType, chall_def_recipientID, @@ -508,7 +740,8 @@ def init_challenge_definitions(): chall_def_startChallengeCLICommandSent, chall_def_stopChallengeCLICommandSent, chall_def_startChallengeAPICommandSent, - chall_def_stopChallengeAPICommandSent)) + chall_def_stopChallengeAPICommandSent, + chall_def_codeID)) # write list to binary file write_list_bin(challenge_defs, FILE_CHALLENGE_DEFINITIONS) @@ -687,7 +920,7 @@ class RecoveryTimeDef(MetricDefinition): if time_challenge_started > time_restoration_detected: print("time_challenge_started should be <= time_restoration_detected") print("time_challenge_started=",time_challenge_started," time_restoration_detected=",time_restoration_detected) - sys.exit() # stop entire program, because fomulas MUST be correct + sys.exit() # stop entire program, because formulas MUST be correct measured_metric_value = time_restoration_detected - time_challenge_started #difference between 2 datetime is a timedelta timestamp = datetime.now() @@ -712,27 +945,27 @@ class UptimePercentageDef(MetricDefinition): if measured_uptime < 0.0: print("measured_uptime should be >= 0.0") print("meas=",measured_uptime," ref=",reference_time," pla=",planned_downtime) - sys.exit() # stop entire program, because fomulas MUST be correct + sys.exit() # stop entire program, because formulas MUST be correct if reference_time <= 0.0: print("reference_time should be > 0.0") print("meas=",measured_uptime," ref=",reference_time," pla=",planned_downtime) - sys.exit() # stop entire program, because fomulas MUST be correct + sys.exit() # stop entire program, because formulas MUST be correct if planned_downtime < 0.0: print("planned_downtime should be >= 0.0") print("meas=",measured_uptime," ref=",reference_time," pla=",planned_downtime) - sys.exit() # stop entire program, because fomulas MUST be correct + sys.exit() # stop entire program, because formulas MUST be correct if reference_time < planned_downtime: print("reference_time should be >= planned_downtime") print("meas=",measured_uptime," ref=",reference_time," pla=",planned_downtime) - sys.exit() # stop entire program, because fomulas MUST be correct + sys.exit() # stop entire program, because formulas MUST be correct if measured_uptime > reference_time: print("measured_uptime should be <= reference_time") print("meas=",measured_uptime," ref=",reference_time," pla=",planned_downtime) - sys.exit() # stop entire program, because fomulas MUST be correct + sys.exit() # stop entire program, because formulas MUST be correct if measured_uptime > (reference_time - planned_downtime): print("measured_uptime should be <= (reference_time - planned_downtime)") print("meas=",measured_uptime," ref=",reference_time," pla=",planned_downtime) - sys.exit() # stop entire program, because fomulas MUST be correct + sys.exit() # stop entire program, because formulas MUST be correct measured_metric_value = 100 * measured_uptime / (reference_time - planned_downtime) timestamp = datetime.now() @@ -1340,10 +1573,21 @@ def main(): print() + challgs = init_challenge_definitions() + print(challgs) + chall = get_indexed_item_from_file(1,FILE_CHALLENGE_DEFINITIONS) + print(chall) + chall.run_start_challenge_code() + chall.run_stop_challenge_code() + + print() + tds = init_test_definitions() print(tds) td = get_indexed_item_from_file(1,FILE_TEST_DEFINITIONS) print(td) + #td.printout_all(0) + #td.run_test_code() print() @@ -1354,12 +1598,6 @@ def main(): print() - challgs = init_challenge_definitions() - print(challgs) - chall = get_indexed_item_from_file(1,FILE_CHALLENGE_DEFINITIONS) - print(chall) - - print() metricdefs = init_metric_definitions() print(metricdefs) diff --git a/lib/auto/testcase/resiliency/clouds.yaml b/lib/auto/testcase/resiliency/clouds.yaml new file mode 100644 index 0000000..593a07c --- /dev/null +++ b/lib/auto/testcase/resiliency/clouds.yaml @@ -0,0 +1,91 @@ +clouds: + + # Openstack instance on Arm pod, controller IP@ 172.16.10.10 + # Horizon: https://10.10.50.103/project/ + # Identity API according to Horizon dashboard: https://10.10.50.103:5000/v2.0 + # other potential auth_url: http://172.16.10.10:35357/v3 + # (OS_AUTH_URL=http://controller:35357/v3) + # 2 project names: admin, service (project = tenant) + # project ID: 122caf64b3df4818bf2ce5ba793226b2 + # EC2 URL: https://10.10.50.103:8773/services/Cloud + # EC2 access key: bcf3c69a7d1c405e9757f87f26faf19f + # 10.10.50.0/8: floating IP@ + # 10.10.10.0/8: fixed IP@ + armopenstack: + auth: + auth_url: https://10.10.50.103:5000/v2.0 + username: admin + password: opnfv_secret + project_name: admin + region_name: RegionOne + + # Openstack instance on LaaS hpe16, from OPNFV Euphrates, controller IP@ (mgt: 172.16.10.101; public: 10.16.0.101) + # keystone endpoints (openstack endpoint list --service keystone) + # admin: http://172.16.10.101:35357/v2.0 + # internal: http://172.16.10.101:5000/v2.0 + # public: http://10.16.0.101:5000/v2.0 : works on LaaS hpe16, from hpe16 + hpe16openstackEuphrates: + auth: + auth_url: http://10.16.0.101:5000/v2.0 + username: admin + password: opnfv_secret + project_name: admin + region_name: RegionOne + + # Openstack instance on LaaS hpe16, from OPNFV Fraser, controller IP@ (mgt: 172.16.10.36; public: 10.16.0.107) + # keystone endpoints (openstack endpoint list --service keystone) + # admin: http://172.16.10.36:35357/v3 + # internal: http://172.16.10.36:5000/v3 + # public: http://10.16.0.107:5000/v3 + hpe16openstackFraser: + auth: + auth_url: http://10.16.0.107:5000/v3 + username: admin + password: opnfv_secret + project_name: admin + region_name: RegionOne + +# ubuntu@ctl01:~$ openstack project show admin +# +-------------+----------------------------------+ +# | Field | Value | +# +-------------+----------------------------------+ +# | description | OpenStack Admin tenant | +# | domain_id | default | +# | enabled | True | +# | id | 04fcfe7aa83f4df79ae39ca748aa8637 | +# | is_domain | False | +# | name | admin | +# | parent_id | default | +# +-------------+----------------------------------+ + +# (openstack) domain show default +# +-------------+----------------------------------------------------------+ +# | Field | Value | +# +-------------+----------------------------------------------------------+ +# | description | Domain created automatically to support V2.0 operations. | +# | enabled | True | +# | id | default | +# | name | Default | +# +-------------+----------------------------------------------------------+ + +# (openstack) domain show heat_user_domain +# +-------------+---------------------------------------------+ +# | Field | Value | +# +-------------+---------------------------------------------+ +# | description | Contains users and projects created by heat | +# | enabled | True | +# | id | d9c29adac0fe4816922d783b257879d6 | +# | name | heat_user_domain | +# +-------------+---------------------------------------------+ + +export OS_AUTH_URL=http://10.16.0.107:5000/v3 +export OS_PROJECT_ID=04fcfe7aa83f4df79ae39ca748aa8637 +export OS_PROJECT_NAME="admin" +export OS_USER_DOMAIN_NAME="Default" +export OS_USERNAME="admin" +export OS_PASSWORD="opnfv_secret" +export OS_REGION_NAME="RegionOne" +export OS_INTERFACE=public +export OS_IDENTITY_API_VERSION=3 + + |