From 4fc3562b400a0dbbd64df7a09dccca8fe79ec3c3 Mon Sep 17 00:00:00 2001 From: Lianhao Lu Date: Wed, 7 Nov 2018 17:59:37 +0800 Subject: Added JMeter scripts for perf test Change-Id: I4286c6defdef331ee5c40399d17381d3c8b8a544 Issue-ID: POLICY-836 Signed-off-by: Lianhao Lu (cherry picked from commit c1647ba56080a79d149b2e9fd647bda4da39997e) --- s3p/README.perf.md | 55 +++++++ s3p/generate_perf.py | 40 +++++ s3p/generate_perf.sh | 28 ++++ s3p/perf.jmx | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 530 insertions(+) create mode 100644 s3p/README.perf.md create mode 100644 s3p/generate_perf.py create mode 100755 s3p/generate_perf.sh create mode 100644 s3p/perf.jmx diff --git a/s3p/README.perf.md b/s3p/README.perf.md new file mode 100644 index 00000000..aaa9d47d --- /dev/null +++ b/s3p/README.perf.md @@ -0,0 +1,55 @@ +# Performance Test for Policy Distribution +## Steps to Run performance test +1. Download Apache JMeter +Download JMeter 5.0 from https://jmeter.apache.org/download_jmeter.cgi, and extracted it locally. + +2. Launch the policy distribution service +Launch the policy distribution service with the configuration from s3pConfig.json, you need to make sure when the service is being launched, the directory configured in s3pConfig.json by receptionHandlerConfigurationParameters.fileConfiguration.parameters.watchPath is a valid local directory(Default directory is /tmp/policy_distribution/csar/). +The policy distribution service will use the FileSystemReceptionHandler plugin to monitor the local directory specified by the 'watchPath' parameter for newly added csar files, parse them to generate policies and forward it to PDP. +``` +java -cp "" org.onap.policy.distribution.main.startstop.Main -c s3pConfig.json +``` + Or if you want to launch it from docker, please do the followings: +``` +mkdir -p /tmp/policy_distribution/csar/ +docker run -d -e "CONFIG_FILE=/opt/app/policy/distribution/etc/s3pConfig.json" \ + -v /tmp/policy_distribution/csar/:/tmp/policy_distribution/csar/ \ + -p 6969:6969 \ + --name policy-distribution policy-distribution +``` +Here we use -e option to "docker run" to pass the config file which the policy distribution service will be launched upon and use -v option to map the local host /tmp/policy_distribution/csar/ directory as the directory of /tmp/policy_distribution/csar/ within the policy-distribution docker. + +**NOTED:** +Please make sure when you launch the policy distribution service, the following requirements are met: +a. The policy PDP service is active, and can be reached using the parameters configured by policyForwarderConfigurationParameters.xacmlPdpConfiguration.parameters in the s3pConfig.json file. + +b. Make sure you have installed the AAF root CA either in local host or in the docker image(running as root): +``` +curl -s https://git.onap.org/dmaap/buscontroller/plain/misc/cert-client-init.sh | bash -- +``` + +3. Get the Jmeter configuration ans scripts +Git clone the policy distribution code, and goto the s3p directory: +``` +git clone https://git.onap.org/policy/distribution policy-distribution +cd policy-distribution/s3p +``` + +4. Run the JMeter stability test +``` +rm -f perf.log; /bin/jmeter.sh -t perf.jmx -n -Jhost= -Jtotal=5 -l perf.log +``` +In the meantime, you can run various system tools i.e. top, atop, etc. to monitor the cpu/memory usage of the policy-distribution service. + +After jmeter finished, search for 'Fail at idx' in the perf.log file to see if there is any errors found during the stability test. + +## JMeter properties +We can configure the following properties when running the JMeter stability test for policy distribution +| Property Name | Default Value | Description | +|---------------|-------------|---------------| +| host | pdp | PDP service host name or ip | +| csardir | /tmp/policy_distribution/csar | Directory where to store the generated csar files | +| total | 5 | Total number of csar files to be generated in bulk to test performance +| retry | 100 | Number of retry to retrieve the policy of each csar + + diff --git a/s3p/generate_perf.py b/s3p/generate_perf.py new file mode 100644 index 00000000..dfd62fc8 --- /dev/null +++ b/s3p/generate_perf.py @@ -0,0 +1,40 @@ +import argparse +import csv +import os +import shutil +import sys +import subprocess + + +def parse_args(): + parser = argparse.ArgumentParser(description='Prepare CSAR for policy distrition performance test') + parser.add_argument('--total', required=True, type=int, help='total number of CSAR to be generated') + parser.add_argument('--dest', required=True, help='dest directory where the CSAR files will be stored') + parser.add_argument('--out', default='perf_data.csv', help='list of generated CSAR identifier') + return parser.parse_args(sys.argv[1:]) + + +def main(): + args = parse_args() + + # create dest dir + shutil.rmtree(args.dest, ignore_errors=True) + os.makedirs(args.dest) + + # prepartion + count = 0 + maxwidth = len(str(args.total)) + scripts = os.path.dirname(os.path.abspath(__file__)) + scripts = os.path.join(scripts, 'generate.sh') + + with open(args.out, 'w') as out_file: + out_writer = csv.writer(out_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) + while (count < args.total): + seed = str(count).zfill(maxwidth) + subprocess.check_call([scripts, args.dest, seed]) + out_writer.writerow(["s3p_" + seed]) + count += 1 + return 0 + +if __name__ == '__main__': + main() diff --git a/s3p/generate_perf.sh b/s3p/generate_perf.sh new file mode 100755 index 00000000..beabb783 --- /dev/null +++ b/s3p/generate_perf.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +function print_usage_and_exit { + [ -z "$1" ] || echo "Error: $1" + echo "Usage: $0 " + echo " - : directory where the generated csar file will be put into" + echo " - : total number of csar files to be generated" + exit 1 +} + +[ "$#" -ne 2 ] && print_usage_and_exit +OUTPUT=$1 +TOTAL=$2 + +[ -d $OUTPUT ] || mkdir -p $OUTPUT +[ -d $OUTPUT ] || print_usage_and_exit "$OUTPUT is not a valid directory" +[[ $TOTAL =~ ^[0-9]+$ ]] || print_usage_and_exit "$SEED is not a integer" + + +ROOT_DIR=`dirname $(readlink -f $0)` +TMP_DIR=$ROOT_DIR/perf_tmp + +python $ROOT_DIR/generate_perf.py --dest $TMP_DIR --total $TOTAL --out $ROOT_DIR/perf_data.csv + +rm -f $OUTPUT/*.csar +cp -fr $TMP_DIR/*.csar $OUTPUT/ + +rm -rf $TMP_DIR diff --git a/s3p/perf.jmx b/s3p/perf.jmx new file mode 100644 index 00000000..ac934776 --- /dev/null +++ b/s3p/perf.jmx @@ -0,0 +1,407 @@ + + + + + + false + true + false + + + + PDP_HOST + ${__P(host,pdp)} + = + + + RETRY + ${__P(retry, 100)} + = + + + PERF_DATA + ${__P(perf_data, perf_data.csv)} + = + + + BASE_DIR + ${__BeanShell(import org.apache.jmeter.services.FileServer; FileServer.getFileServer().getBaseDir();)}${__BeanShell(File.separator,)} + = + + + CSAR_DIR + ${__P(csardir, /tmp/policy_distribution/csar)} + = + + + TOTAL + ${__P(total, 5)} + = + + + + + + + + continue + + false + 1 + + 1 + 1 + false + ${DURATION} + 1 + + + + + + Content-Type + application/json + + + Accept + application/json + + + ClientAuth + cHl0aG9uOnRlc3Q= + + + Authorization + Basic dGVzdHBkcDphbHBoYTEyMw== + + + Environment + TEST + + + + + + + + true + + + + false + {"policyName": "oofCasablanca.*s3p.*"} + = + + + + ${PDP_HOST} + 8081 + https + + /pdp/api/listConfig + POST + true + false + true + false + + + + + + + groovy + + + true + import groovy.json.JsonSlurper; + +def to_delete = []; +if (prev.getResponseCode() == '200') { + def jsonSlurper = new JsonSlurper(); + to_delete = jsonSlurper.parseText(prev.getResponseDataAsString()); +} +vars.putObject('to_delete', to_delete); + + + + + + ${__groovy(vars.getObject('to_delete').size() > 0)} + + + + true + + + + false + { + "pdpGroup": "default", + "policyComponent": "PDP", + "policyType": "Optimization", + "policyName": "${policyname}" +} + = + + + + ${PDP_HOST} + 8081 + https + + /pdp/api/deletePolicy + DELETE + true + false + true + false + + + + + + + groovy + + + true + def to_delete = vars.getObject('to_delete'); +def policyname = to_delete.pop() +vars.put('policyname', policyname.toString()); +vars.putObject('to_delete', to_delete); + + + + + + true + + + + false + { + "deleteCondition":"ALL", + "policyComponent": "PAP", + "policyType": "Optimization", + "policyName": "${policyname}" +} + = + + + + ${PDP_HOST} + 8081 + https + + /pdp/api/deletePolicy + DELETE + true + false + true + false + + + + + + + + + + + false + 0 + ${BASE_DIR}generate_perf.sh + + + + + ${CSAR_DIR} + = + + + + ${TOTAL} + = + + + + + + + + + + + true + + + def data_file=new File(vars.get('BASE_DIR') + vars.get('PERF_DATA')); +def data=data_file.readLines(); +def total=data.size(); + +vars.putObject('data', data); +vars.putObject('total', total); +vars.putObject('idx', 0); +vars.putObject('total_counter', vars.get('RETRY').toInteger() * total); + +SampleResult.setIgnore(); + groovy + + + + + false + true + + + + + + innter_counter + 1 + = + + + rescode + + = + + + counter + 1 + = + + + + + + ${__javaScript(${counter} < ${total_counter} && ${idx} < ${total})} + + + + groovy + + + true + //log.info("idx: " + vars.getObject('idx')); +//log.info("counter: " + vars.get('counter')); +//log.info("total_counter: " + vars.get('total_counter')); + +vars.putObject('inner_counter', 0); +vars.put('rescode', ""); + +SampleResult.setIgnore(); + + + + ${__javaScript(${inner_counter} < ${RETRY} && "${rescode}" != '200')} + + + + true + + + + false + {"policyName": "oofCasablanca.*${resid}.*"} + = + + + + ${PDP_HOST} + 8081 + https + + /pdp/api/getConfig + POST + true + false + true + false + + + + + + + groovy + + + true + def idx=vars.getObject('idx'); +def data=vars.getObject('data'); + +vars.put('resid', data[idx]); +//log.error(data[idx]); + + + + + true + + + def rescode = prev.getResponseCode(); +def idx=vars.getObject('idx'); +def total=vars.getObject('total'); +def inner_counter=vars.getObject('inner_counter'); + +vars.put('rescode', rescode); +//log.info('inner_counter: ' + inner_counter); +//log.info('idx: '+ idx); + +inner_counter += 1; +vars.putObject('inner_counter', inner_counter); + +if (rescode == '200'){ + idx += 1; + vars.putObject('idx', idx); +}else { + +} + + groovy + + + + + 1 + + 1 + counter + + true + true + + + + + + + + + groovy + + + true + def idx=vars.getObject('idx'); +def total=vars.getObject('total'); + +if (idx<total) { + SampleResult.setSuccessful(false); + SampleResult.setResponseCode("410"); + SampleResult.setResponseMessage("Fail at idx " + idx); +}else { + SampleResult.setSuccessful(true); + SampleResult.setResponseCode("200"); + SampleResult.setResponseMessage("Success"); +} + + + + + + + + -- cgit 1.2.3-korg