nfv/nfv/nfv-tests/nfv_scenario_tests/main.py

732 lines
28 KiB
Python
Executable File

#
# Copyright (c) 2015-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import argparse
import codecs
import datetime
import os
import shutil
import signal
import sys
import tarfile
import time
import traceback
import uuid
import yaml
from jinja2 import Environment
from jinja2 import FileSystemLoader
from nfv_common import debug
from nfv_common import forensic
from nfv_plugins.nfvi_plugins import config
import tests # pylint: disable=relative-import
DLOG = debug.debug_get_logger('nfv_tests')
def process_signal_handler(signum, frame):
"""
Test - Process Signal Handler
"""
if signal.SIGINT == signum:
raise KeyboardInterrupt
else:
print("Ignoring signal" % signum)
def process_initialize():
"""
Test - Process Initialize
"""
utf8_writer = codecs.getwriter('utf8')
sys.stdout = utf8_writer(sys.stdout)
debug.debug_initialize(config.CONF['debug'], 'NFV-TEST')
forensic.forensic_initialize()
def process_finalize():
"""
Test - Process Finalize
"""
forensic.forensic_finalize()
debug.debug_finalize()
def process_progress_marker_start(marker_name):
space_str = '.' * (60 - len(marker_name))
sys.stdout.write("%s %s %s "
% (str(datetime.datetime.now())[:-3], marker_name,
space_str))
sys.stdout.flush()
def process_progress_marker_end(marker_result):
sys.stdout.write("%s\n" % marker_result)
sys.stdout.flush()
def process_do_setup(loads_dir, setup_data):
"""
Test - Process Do Setup
"""
from nfv_plugins.nfvi_plugins.openstack import openstack
from nfv_plugins.nfvi_plugins.openstack import nova
from nfv_plugins.nfvi_plugins.openstack import cinder
from nfv_plugins.nfvi_plugins.openstack import glance
from nfv_plugins.nfvi_plugins.openstack import neutron
directory = openstack.get_directory(config,
openstack.SERVICE_CATEGORY.OPENSTACK)
token = openstack.get_token(directory)
result = nova.get_flavors(token)
flavors = result.result_data.get('flavors', list())
result = glance.get_images(token)
images = result.result_data.get('images', list())
result = cinder.get_volumes(token)
volumes = result.result_data.get('volumes', list())
result = neutron.get_networks(token)
networks = result.result_data.get('networks', list())
result = neutron.get_subnets(token)
subnets = result.result_data.get('subnets', list())
result = nova.get_servers(token)
servers = result.result_data.get('servers', list())
for resource in setup_data['resources']:
if 'flavor' == resource['type']:
process_progress_marker_start("Create flavor %s " % resource['name'])
flavor = next((x for x in flavors
if x['name'] == resource['name']), None)
if flavor is None:
nova.create_flavor(token, resource['id'], resource['name'],
resource['vcpus'], resource['ram_mb'],
resource['disk_gb'],
ephemeral_gb=resource['ephemeral_gb'],
swap_mb=resource['swap_mb'])
if 'extra_specs' in resource:
for extra_spec in resource['extra_specs']:
nova.set_flavor_extra_specs(
token, resource['id'],
{extra_spec['key']: str(extra_spec['value'])})
process_progress_marker_end("[OKAY]")
result = nova.get_flavors(token)
flavors = result.result_data.get('flavors', list())
for resource in setup_data['resources']:
if 'image' == resource['type']:
process_progress_marker_start("Create image %s " % resource['name'])
image = next((x for x in images if x['name'] == resource['name']), None)
if image is None:
image_file = resource['file']
if not os.path.isfile(image_file):
image_file = loads_dir + '/' + resource['file']
if not os.path.isfile(image_file):
process_progress_marker_end("[FAILED]")
print("Image file %s does not exist." % resource['file'])
return False
image_data = glance.create_image(token, resource['name'],
resource['description'],
resource['container_format'],
resource['disk_format'],
resource['min_disk_size_gb'],
resource['min_memory_size_mb'],
resource['visibility'],
resource['protected'],
resource['properties']).result_data
glance.upload_image_data_by_file(token, image_data['id'],
image_file)
process_progress_marker_end("[OKAY]")
result = glance.get_images(token)
images = result.result_data.get('images', list())
for resource in setup_data['resources']:
if 'volume' == resource['type']:
process_progress_marker_start("Create volume %s " % resource['name'])
volume = next((x for x in volumes
if x['name'] == resource['name']), None)
if volume is None:
if resource['image_name'] is not None:
image = next((x for x in images
if x['name'] == resource['image_name']), None)
if image is None:
process_progress_marker_end("[FAILED]")
print("Image %s for volume %s does not exist."
% (resource['image_name'], resource['name']))
return False
image_id = image['id']
else:
image_id = None
bootable = None
if resource['bootable'] in ['YES', 'Yes', 'yes']:
bootable = True
cinder.create_volume(token, resource['name'],
resource['description'],
resource['size_gb'],
image_id,
bootable=bootable)
for _ in range(10):
time.sleep(5)
volumes = cinder.get_volumes(token).result_data
if volumes is not None:
volumes = volumes.get('volumes', list())
volume = next((x for x in volumes
if x['name'] == resource['name']), None)
volume = cinder.get_volume(token, volume['id']).result_data
if 'available' == volume['volume']['status']:
break
else:
process_progress_marker_end("[FAILED]")
print("Volume %s not create properly." % resource['name'])
return False
process_progress_marker_end("[OKAY]")
result = cinder.get_volumes(token)
volumes = result.result_data.get('volumes', list())
for resource in setup_data['resources']:
if 'network' == resource['type']:
process_progress_marker_start("Create network %s " % resource['name'])
network = next((x for x in networks
if x['name'] == resource['name']), None)
if network is None:
neutron.create_network(token, resource['name'],
resource['network_type'],
resource['segmentation_id'],
resource['physical_network'],
resource['shared'])
process_progress_marker_end("[OKAY]")
result = neutron.get_networks(token)
networks = result.result_data.get('networks', list())
for resource in setup_data['resources']:
if 'subnet' == resource['type']:
process_progress_marker_start("Create subnet %s " % resource['name'])
subnet = next((x for x in subnets
if x['name'] == resource['name']), None)
if subnet is None:
network = next((x for x in networks
if x['name'] == resource['network_name']), None)
if network is None:
process_progress_marker_end("[FAILED]")
print("Network %s for subnet %s does not exist."
% (resource['network_name'], resource['name']))
return False
neutron.create_subnet(token, network['id'], resource['name'],
resource['ip_version'], resource['cidr'],
resource['gateway_ip'],
resource['dhcp_enabled'])
process_progress_marker_end("[OKAY]")
result = neutron.get_subnets(token)
subnets = result.result_data.get('subnets', list())
instance_created = False
for resource in setup_data['resources']:
if 'instance' == resource['type']:
process_progress_marker_start("Create instance %s " % resource['name'])
server = next((x for x in servers
if x['name'] == resource['name']), None)
if server is None:
flavor = next((x for x in flavors
if x['name'] == resource['flavor']), None)
if flavor is None:
process_progress_marker_end("[FAILED]")
print("Can't find flavor %s for instance %s"
% (resource['flavor'], resource['name']))
return False
if resource['image'] is not None:
image = next((x for x in images
if x['name'] == resource['image']), None)
if image is None:
process_progress_marker_end("[FAILED]")
print("Can't find image %s for instance %s"
% (resource['image'], resource['name']))
return False
image_id = image['id']
else:
image_id = None
block_devices = list()
for block_device in resource['block_devices']:
if 'volume' == block_device['type']:
volume = next((x for x in volumes
if x['name'] == block_device['volume_name']),
None)
if volume is None:
process_progress_marker_end("[FAILED]")
print("Can't find volume %s for instance %s"
% (block_device['volume_name'], resource['name']))
return False
block_devices.append(
{'uuid': volume['id'],
'device_name': block_device['device_name'],
'source_type': block_device['source_type'],
'destination_type': block_device['destination_type'],
'boot_index': block_device['boot_index']})
if 0 == len(block_devices):
block_devices = None
network_ids = list()
for network_name in resource['networks']:
network = next((x for x in networks
if x['name'] == network_name), None)
if network is None:
process_progress_marker_end("[FAILED]")
print("Can't find network %s for instance %s"
% (network_name, resource['name']))
return False
network_ids.append({'uuid': network['id']})
if 0 == len(network_ids):
network_ids = None
nova.create_server(token, resource['name'], flavor['id'],
image_id, block_devices, network_ids)
for _ in range(10):
time.sleep(5)
result = nova.get_servers(token)
servers = result.result_data.get('servers', list())
if servers:
server = next((x for x in servers
if x['name'] == resource['name']), None)
server = nova.get_server(token, server['id']).result_data
if 'ACTIVE' == server['server']['status']:
server_id = server['server']['id']
break
else:
process_progress_marker_end("[FAILED]")
print("Server %s not created properly." % resource['name'])
return False
for attached_volume in resource['attached_volumes']:
volume = next((x for x in volumes
if x['name'] == attached_volume['volume_name']),
None)
if volume is None:
process_progress_marker_end("[FAILED]")
print("Can't find volume %s for instance %s"
% (attached_volume['volume_name'], resource['name']))
return False
nova.attach_volume(token, server_id, volume['id'],
attached_volume['device_name'])
instance_created = True
process_progress_marker_end("[OKAY]")
if instance_created:
# Allow time for instances to boot and guest client to start up
# inside the each instance (in case it is being used). Timeout is long
# because we are usually testing in Virtual Box.
time.sleep(90)
return True
def process_do_tests(test_data):
"""
Test - Process Do Tests
"""
test_output_dir = config.CONF['test-output']['dir']
if os.path.exists(test_output_dir):
shutil.rmtree(test_output_dir)
os.makedirs(test_output_dir)
test_set = list()
for test in test_data['tests']:
if 'pause_instance' == test['type']:
test = tests.TestInstancePause(test['entity'], test['timeout'],
test['guest_hb'])
elif 'unpause_instance' == test['type']:
test = tests.TestInstanceUnpause(test['entity'], test['timeout'],
test['guest_hb'])
elif 'suspend_instance' == test['type']:
test = tests.TestInstanceSuspend(test['entity'], test['timeout'],
test['guest_hb'])
elif 'resume_instance' == test['type']:
test = tests.TestInstanceResume(test['entity'], test['timeout'],
test['guest_hb'])
elif 'reboot_instance' == test['type']:
test = tests.TestInstanceReboot(test['entity'], test['timeout'],
test['hard_reset'], test['guest_hb'])
elif 'rebuild_instance' == test['type']:
test = tests.TestInstanceRebuild(test['entity'], test['timeout'],
test['guest_hb'])
elif 'stop_instance' == test['type']:
test = tests.TestInstanceStop(test['entity'], test['timeout'],
test['guest_hb'])
elif 'start_instance' == test['type']:
test = tests.TestInstanceStart(test['entity'], test['timeout'],
test['guest_hb'])
elif 'live_migrate_instance' == test['type']:
test = tests.TestInstanceLiveMigrate(test['entity'], test['timeout'],
None, test['guest_hb'])
elif 'cold_migrate_instance' == test['type']:
test = tests.TestInstanceColdMigrate(test['entity'], test['timeout'],
None, test['guest_hb'])
elif 'cold_migrate_confirm_instance' == test['type']:
test = tests.TestInstanceColdMigrateConfirm(test['entity'],
test['timeout'],
test['guest_hb'])
elif 'cold_migrate_revert_instance' == test['type']:
test = tests.TestInstanceColdMigrateRevert(test['entity'],
test['timeout'],
test['guest_hb'])
elif 'resize_instance' == test['type']:
test = tests.TestInstanceResize(test['entity'], test['flavors'],
test['timeout'], test['guest_hb'])
elif 'resize_confirm_instance' == test['type']:
test = tests.TestInstanceResizeConfirm(test['entity'], test['flavors'],
test['timeout'],
test['guest_hb'])
elif 'resize_revert_instance' == test['type']:
test = tests.TestInstanceResizeRevert(test['entity'], test['flavors'],
test['timeout'], test['guest_hb'])
elif 'lock_host' == test['type']:
test = tests.TestHostLock(test['entity'], test['instances'],
test['timeout'])
elif 'unlock_host' == test['type']:
test = tests.TestHostUnlock(test['entity'], test['timeout'])
else:
test = None
if test is not None:
test_set.append(test)
result_file = config.CONF['test-output']['result_file']
start_datetime = datetime.datetime.now()
for test in test_set:
process_progress_marker_start("Test %s " % test.name)
if not test.setup():
process_progress_marker_end("[SETUP-FAILED] (%s %s=%s)"
% (str(test.end_datetime)[:-3], u"\u0394",
str(test.elapsed_datetime)[:-3]))
break
if not test.run():
process_progress_marker_end("[FAILED] (%s %s=%s)"
% (str(test.end_datetime)[:-3], u"\u0394",
str(test.elapsed_datetime)[:-3]))
break
process_progress_marker_end("[OKAY] (%s %s=%s)"
% (str(test.end_datetime)[:-3], u"\u0394",
str(test.elapsed_datetime)[:-3]))
with open(result_file, 'a') as f:
f.write("%s\n" % test.name.upper())
test.save_customer_alarms(result_file)
test.save_customer_alarm_history(result_file)
test.save_customer_logs(result_file)
time.sleep(1)
tar_file = config.CONF['test-output']['tar_file']
with tarfile.open(tar_file, "w:gz") as tar:
tar.add(test_output_dir, arcname=os.path.basename(test_output_dir))
elapsed_datetime = datetime.datetime.now() - start_datetime
sys.stdout.write("Total-Tests: %s Execution-Time: %s\n"
% (len(test_set), str(elapsed_datetime)[:-3]))
sys.stdout.flush()
def process_do_teardown(setup_data):
"""
Test - Process Do Teardown
"""
from nfv_plugins.nfvi_plugins.openstack import openstack
from nfv_plugins.nfvi_plugins.openstack import nova
from nfv_plugins.nfvi_plugins.openstack import cinder
from nfv_plugins.nfvi_plugins.openstack import glance
from nfv_plugins.nfvi_plugins.openstack import neutron
directory = openstack.get_directory(config,
openstack.SERVICE_CATEGORY.OPENSTACK)
token = openstack.get_token(directory)
result = nova.get_flavors(token)
flavors = result.result_data.get('flavors', list())
result = glance.get_images(token)
images = result.result_data.get('images', list())
result = cinder.get_volumes(token)
volumes = result.result_data.get('volumes', list())
result = neutron.get_networks(token)
networks = result.result_data.get('networks', list())
result = neutron.get_subnets(token)
subnets = result.result_data.get('subnets', list())
result = nova.get_servers(token)
servers = result.result_data.get('servers', list())
for resource in setup_data['resources']:
if 'instance' == resource['type']:
process_progress_marker_start("Delete instance %s " % resource['name'])
server = next((x for x in servers
if x['name'] == resource['name']), None)
if server is not None:
nova.delete_server(token, server['id'])
for _ in range(10):
time.sleep(5)
servers = nova.get_servers(token).result_data
if servers is not None:
servers = servers.get('servers', list())
server = next((x for x in servers
if x['name'] == resource['name']), None)
if server is None:
break
else:
process_progress_marker_end("[FAILED]")
print("Server %s not deleted." % resource['name'])
return False
process_progress_marker_end("[OKAY]")
for resource in setup_data['resources']:
if 'subnet' == resource['type']:
process_progress_marker_start("Delete subnet %s " % resource['name'])
subnet = next((x for x in subnets
if x['name'] == resource['name']), None)
if subnet is not None:
neutron.delete_subnet(token, subnet['id'])
process_progress_marker_end("[OKAY]")
for resource in setup_data['resources']:
if 'network' == resource['type']:
process_progress_marker_start("Delete network %s " % resource['name'])
network = next((x for x in networks
if x['name'] == resource['name']), None)
if network is not None:
neutron.delete_network(token, network['id'])
process_progress_marker_end("[OKAY]")
for resource in setup_data['resources']:
if 'volume' == resource['type']:
process_progress_marker_start("Delete volume %s " % resource['name'])
volume = next((x for x in volumes
if x['name'] == resource['name']), None)
if volume is not None:
cinder.delete_volume(token, volume['id'])
process_progress_marker_end("[OKAY]")
for resource in setup_data['resources']:
if 'image' == resource['type']:
process_progress_marker_start("Delete image %s " % resource['name'])
image = next((x for x in images if x['name'] == resource['name']), None)
if image is not None:
glance.delete_image(token, image['id'])
process_progress_marker_end("[OKAY]")
for resource in setup_data['resources']:
if 'flavor' == resource['type']:
process_progress_marker_start("Delete flavor %s " % resource['name'])
flavor = next((x for x in flavors
if x['name'] == resource['name']), None)
if flavor is not None:
nova.delete_flavor(token, flavor['id'])
process_progress_marker_end("[OKAY]")
return True
def process_main():
"""
Test - Process Main
"""
try:
want_teardown = False
root_dir = os.path.dirname(__file__)
data_dir = root_dir + '/data'
loads_dir = data_dir + '/loads'
setup_dir = data_dir + '/setup'
tests_dir = data_dir + '/tests'
j2_env = Environment(loader=FileSystemLoader([setup_dir, tests_dir]),
trim_blocks=True)
j2_env.globals['uuid4'] = uuid.uuid4
signal.signal(signal.SIGINT, process_signal_handler)
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('-c', '--config', help='configuration file')
arg_parser.add_argument('-d', '--data', help='data file')
arg_parser.add_argument('-s', '--setup', help='setup file')
arg_parser.add_argument('-t', '--tests', help='tests file')
arg_parser.add_argument('-r', '--repeat', help='repeat tests x times')
arg_parser.add_argument('-f', '--forever', help='loop forever doing tests',
action='store_true')
arg_parser.add_argument('-w', '--wipe', help='cleanup setup',
action='store_true')
args = arg_parser.parse_args()
if args.config:
config.load(args.config)
else:
print("No configuration given.")
sys.exit(1)
if args.data:
data_fill = yaml.load(open(data_dir + '/data/' + args.data + '.yaml'))
else:
print("No data file given.")
sys.exit(1)
if args.setup:
setup_template = j2_env.get_template(args.setup + '.template')
setup_yaml = setup_template.render(data_fill)
setup_data = yaml.load(setup_yaml)
else:
print("No setup file given.")
sys.exit(1)
if args.tests:
tests_template = j2_env.get_template(args.tests + '.template')
tests_yaml = tests_template.render(data_fill)
test_data = yaml.load(tests_yaml)
else:
print("No tests given.")
sys.exit(1)
if args.repeat:
repeat = int(args.repeat)
max_iteration_str = "max-iterations=%s" % repeat
else:
repeat = 0
max_iteration_str = "single-execution"
if args.forever:
forever = True
max_iteration_str = "forever"
else:
forever = False
if args.wipe:
want_teardown = True
process_initialize()
if want_teardown:
setup_str = "===== Cleanup Previous Configuration"
header_str = "%s %s" % (setup_str, '=' * (140 - len(setup_str)))
footer_str = "%s" % '=' * 141
sys.stdout.write("%s\n" % header_str)
if not process_do_teardown(setup_data):
print("Cleanup failed.")
sys.exit(1)
sys.stdout.write("%s\n" % footer_str)
want_teardown = True
time.sleep(60)
setup_str = "===== Setup"
header_str = "%s %s" % (setup_str, '=' * (140 - len(setup_str)))
footer_str = "%s" % '=' * 141
sys.stdout.write("%s\n" % header_str)
if not process_do_setup(loads_dir, setup_data):
print("Setup failed.")
sys.exit(1)
sys.stdout.write("%s\n" % footer_str)
loop_i = 0
while True:
iteration_str = "===== Test Iteration %s (%s)" % (loop_i,
max_iteration_str)
header_str = "%s %s" % (iteration_str, '=' * (140 - len(iteration_str)))
footer_str = "%s" % '=' * 141
sys.stdout.write("%s\n" % header_str)
process_do_tests(test_data)
sys.stdout.write("%s\n" % footer_str)
loop_i += 1
if not forever:
if loop_i >= repeat:
break
if want_teardown:
setup_str = "===== Teardown"
header_str = "%s %s" % (setup_str, '=' * (140 - len(setup_str)))
footer_str = "%s" % '=' * 141
sys.stdout.write("%s\n" % header_str)
if not process_do_teardown(setup_data):
print("Teardown failed.")
sys.exit(1)
sys.stdout.write("%s\n" % footer_str)
except KeyboardInterrupt:
print("Keyboard Interrupt received.")
except Exception as e:
print("Exception: %s" % e)
traceback.print_exc()
sys.exit(1)
finally:
process_finalize()
if __name__ == '__main__':
process_main()