diff options
author | Jakub Dudycz <jakub.dudycz@nokia.com> | 2019-06-21 17:19:49 +0200 |
---|---|---|
committer | Jakub Dudycz <jakub.dudycz@nokia.com> | 2019-07-03 11:49:14 +0200 |
commit | 83a1d39bca162e8fdabfb3ad9189c5e4f94a44df (patch) | |
tree | c0ee3c382cb9072c0fdd21f46649ada824852c5c /tools | |
parent | 3449b38b23fe1952a534ab35c5a23105c13e8262 (diff) |
Create script to run performance test locally
Change-Id: I6bbf0e9b029aef1558008286f0fbec83b76be44c
Signed-off-by: Jakub Dudycz <jakub.dudycz@nokia.com>
Issue-ID: DCAEGEN2-1641
Diffstat (limited to 'tools')
28 files changed, 3133 insertions, 0 deletions
diff --git a/tools/development/bin/constants.sh b/tools/development/bin/constants.sh new file mode 100755 index 00000000..f0df9b00 --- /dev/null +++ b/tools/development/bin/constants.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# dcaegen2-collectors-veshv +# ================================================================================ +# Copyright (C) 2019 NOKIA +# ================================================================================ +# 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========================================================= + +DCAE_APP_HOSTNAME=localhost +DCAE_APP_PORT=6064 +DCAE_APP_ADDRESS=${DCAE_APP_HOSTNAME}:${DCAE_APP_PORT}
\ No newline at end of file diff --git a/tools/development/bin/consul.sh b/tools/development/bin/consul.sh new file mode 100755 index 00000000..5f9271f2 --- /dev/null +++ b/tools/development/bin/consul.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# dcaegen2-collectors-veshv +# ================================================================================ +# Copyright (C) 2018 NOKIA +# ================================================================================ +# 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========================================================= + +set -euo pipefail + +usage() { + echo "Put HV-VES configuration into Consul key-value store" + echo "Usage: $0 [-h|--help] [-v|--verbose] [domain [topic]]" + exit 1 +} + +optspec=":vh-:" # catch v, h and - +while getopts "$optspec" arg; do + case "${arg}" in + -) # handle longopts + case "${OPTARG}" in + verbose) + VERBOSE=True + ;; + help) + usage + ;; + *) + echo "Unknown option --${OPTARG}" >&2 + usage + ;; + esac + ;; + v) + VERBOSE=True + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" >&2 + usage + ;; + esac +done +shift $((OPTIND-1)) + +DOMAIN=${1:-perf3gpp} +TOPIC=${2:-HV_VES_PERF3GPP} + +CONFIGURATION="{ + \"streams_publishes\": { + \"${DOMAIN}\": { + \"type\": \"kafka\", + \"kafka_info\": { + \"bootstrap_servers\": \"message-router-kafka:9092\", + \"topic_name\": \"${TOPIC}\" + } + } + } +}" +CONFIGURATION_ENDPOINT=localhost:8500/v1/kv/dcae-hv-ves-collector + + +if [ -n "${VERBOSE+x}" ]; then + echo "Configuration: ${CONFIGURATION}" + echo "Putting configuration under ${CONFIGURATION_ENDPOINT}" +fi +curl --request PUT ${CONFIGURATION_ENDPOINT} -d "${CONFIGURATION}" +echo diff --git a/tools/development/bin/dcae-msgs.sh b/tools/development/bin/dcae-msgs.sh new file mode 100755 index 00000000..84cef972 --- /dev/null +++ b/tools/development/bin/dcae-msgs.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# dcaegen2-collectors-veshv +# ================================================================================ +# Copyright (C) 2018 NOKIA +# ================================================================================ +# 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========================================================= + +set -euo pipefail + +usage() { + echo "Return current amount of consumed messages by dcae-app-simulator on given topic" + echo "Usage: $0 [-h|--help] [-v|--verbose] <topic>" + echo "" + echo " - topic : kafka topic to retrieve messages from, default `HV_VES_PERF3GPP`" + exit 1 +} + +optspec=":vh-:" # catch v, h and - +while getopts "$optspec" arg; do + case "${arg}" in + -) # handle longopts + case "${OPTARG}" in + verbose) + VERBOSE=True + ;; + help) + usage + ;; + *) + echo "Unknown option --${OPTARG}" >&2 + usage + ;; + esac + ;; + v) + VERBOSE=True + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" >&2 + usage + ;; + esac +done +shift $((OPTIND-1)) + +TOPIC=${1:-HV_VES_PERF3GPP} + +DEVELOPMENT_BIN_DIRECTORY=$(realpath $(dirname "$0")) +source ${DEVELOPMENT_BIN_DIRECTORY}/constants.sh + +if [ -n "${VERBOSE+x}" ]; then + echo "All messages count currently consumed by dcae app simulator on topic ${TOPIC}: " +fi + +curl --request GET ${DCAE_APP_ADDRESS}/messages/${TOPIC}/count +echo diff --git a/tools/development/bin/dcae-reset.sh b/tools/development/bin/dcae-reset.sh new file mode 100755 index 00000000..d2d8ebd0 --- /dev/null +++ b/tools/development/bin/dcae-reset.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# dcaegen2-collectors-veshv +# ================================================================================ +# Copyright (C) 2018 NOKIA +# ================================================================================ +# 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========================================================= + +set -euo pipefail + + +usage() { + echo "Resets dcae-app-simulator consumed messages count on given topic" + echo "Usage: $0 [-h|--help] [-v|--verbose] <topic>" + echo "" + echo " - topic : kafka topic to reset consumer for, default 'HV_VES_PERF3GPP'" + exit 1 +} + +optspec=":vh-:" # catch v, h and - +while getopts "$optspec" arg; do + case "${arg}" in + -) # handle longopts + case "${OPTARG}" in + verbose) + VERBOSE=True + ;; + help) + usage + ;; + *) + echo "Unknown option --${OPTARG}" >&2 + usage + ;; + esac + ;; + v) + VERBOSE=True + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" >&2 + usage + ;; + esac +done +shift $((OPTIND-1)) + +TOPIC=${1:-HV_VES_PERF3GPP} + +DEVELOPMENT_BIN_DIRECTORY=$(realpath $(dirname "$0")) +source ${DEVELOPMENT_BIN_DIRECTORY}/constants.sh + +if [ -n "${VERBOSE+x}" ]; then + echo "Requesting DCAE app running on port ${DCAE_APP_PORT} to reset messages count" +fi + +curl --request DELETE ${DCAE_APP_ADDRESS}/messages/${TOPIC} +echo diff --git a/tools/development/bin/dcae-topic.sh b/tools/development/bin/dcae-topic.sh new file mode 100755 index 00000000..b4c2638d --- /dev/null +++ b/tools/development/bin/dcae-topic.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# dcaegen2-collectors-veshv +# ================================================================================ +# Copyright (C) 2018 NOKIA +# ================================================================================ +# 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========================================================= + +set -euo pipefail + +usage() { + echo "Set dcae-app-simulator to start consuming messages from given comma-separated topics (HV_VES_PERF3GPP by default)" + echo "Usage: $0 [-h|--help] [-v|--verbose] [topics]" + echo "" + echo "Example invocations:" + echo "./dcae-topic.sh FAULT_TOPIC,HEARTBEAT_TOPIC,HV_VES_PERF3GPP" + exit 1 +} + +optspec=":vh-:" # catch v, h and - +while getopts "$optspec" arg; do + case "${arg}" in + -) # handle longopts + case "${OPTARG}" in + verbose) + VERBOSE=True + ;; + help) + usage + ;; + *) + echo "Unknown option --${OPTARG}" >&2 + usage + ;; + esac + ;; + v) + VERBOSE=True + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" >&2 + usage + ;; + esac +done +shift $((OPTIND-1)) + +DEVELOPMENT_BIN_DIRECTORY=$(realpath $(dirname "$0")) +source ${DEVELOPMENT_BIN_DIRECTORY}/constants.sh + +TOPIC=${1:-HV_VES_PERF3GPP} + +if [ -n "${VERBOSE+x}" ]; then + echo "Requesting DCAE app running on ${DCAE_APP_ADDRESS} to consume messages from topics: ${TOPIC}" +fi + +curl --request PUT ${DCAE_APP_ADDRESS}/configuration/topics -d ${TOPIC} +echo
\ No newline at end of file diff --git a/tools/development/bin/run-xnf-simulator.sh b/tools/development/bin/run-xnf-simulator.sh new file mode 100755 index 00000000..e4d8d94a --- /dev/null +++ b/tools/development/bin/run-xnf-simulator.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# dcaegen2-collectors-veshv +# ================================================================================ +# Copyright (C) 2018 NOKIA +# ================================================================================ +# 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========================================================= + +set -euo pipefail + +usage() { + echo "Start xnf-simulator container on given port and inside of given docker-network" + echo "Usage: $0 [-h|--help] [-v|--verbose] [--ssl-disable] <xnf listen port> [<hv ves hostname> <hv ves port> <hv ves docker network>]" + echo "" + echo "Optional parameters:" + echo " - ssl-disable : Should xNF simulator be configured without using SSL/TLS connections" + echo "Default values:" + echo " - hv ves hostname: ves-hv-collector" + echo " - hv ves port: 6061" + exit 1 +} + +optspec=":vh-:" # catch v, h and - +while getopts "$optspec" arg; do + case "${arg}" in + -) # handle longopts + case "${OPTARG}" in + verbose) + VERBOSE=True ;; + ssl-disable) + SSL_DISABLE=True ;; + help) + usage ;; + *) + echo "Unknown option --${OPTARG}" >&2 + usage ;; + esac ;; + v) + VERBOSE=True ;; + h) + usage ;; + *) + echo "Unknown option -${OPTARG}" >&2 + usage ;; + esac +done +shift $((OPTIND-1)) + +[ $# -eq 0 ] && usage + + +LISTEN_PORT=$1 +HV_VES_HOSTNAME=${2:-ves-hv-collector} +HV_VES_PORT=${3:-6061} +if [ $# -gt 3 ]; then + HV_VES_NETWORK=${4} +fi + +PORTS="${LISTEN_PORT}:${LISTEN_PORT}/tcp" +HV_VES_REPO_HOME=$(realpath $(dirname "$0"))/.. + +if [ -n "${SSL_DISABLE+x}" ]; then + SSL_CONFIGURATION="--ssl-disable" +else + SSL_CONFIGURATION="--key-store-password onaponap --trust-store-password onaponap" +fi + +if [ -n "${VERBOSE+x}" ]; then + echo "Starting xnf-simulator with " + echo " - ports configuration: ${PORTS}" + echo " - SSL configuration: ${SSL_CONFIGURATION}" + echo "Container id:" +fi + + +XNF_CONTAINER_ID=$(docker run -d \ + -v ${HV_VES_REPO_HOME}/ssl/:/etc/ves-hv/ \ + --health-cmd='curl -s -f http://localhost:6063/health/ready || exit 1' \ + --health-interval=5s \ + --health-retries=3 \ + --health-start-period='10s' \ + -p ${PORTS} \ + onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-xnf-simulator \ + --listen-port ${LISTEN_PORT} \ + --health-check-api-port 6063 \ + --ves-host ${HV_VES_HOSTNAME} \ + --ves-port ${HV_VES_PORT} \ + ${SSL_CONFIGURATION}) + +echo $XNF_CONTAINER_ID + +if [ -n "${HV_VES_NETWORK+x}" ]; then + if [ -n "${VERBOSE+x}" ]; then + echo "Adding container to network: ${HV_VES_NETWORK}" + fi + docker network connect ${HV_VES_NETWORK} ${XNF_CONTAINER_ID} +fi diff --git a/tools/development/bin/start-simulation.sh b/tools/development/bin/start-simulation.sh new file mode 100755 index 00000000..8c63ddbb --- /dev/null +++ b/tools/development/bin/start-simulation.sh @@ -0,0 +1,289 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# dcaegen2-collectors-veshv +# ================================================================================ +# Copyright (C) 2018 NOKIA +# ================================================================================ +# 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========================================================= + +set -euo pipefail + + +function usage() { + echo "" + echo "Send messages to hv-ves from multiple xNF simulators" + echo "Usage: $0 [-h|--help] [-v|--verbose] [--ssl-disable]" + echo " [--messages-in-batch=ARG] [--docker-network=ARG] [--xnf-logs-directory=ARG]" + echo " <hv ves hostname> <hv ves port> <simulators amount> <messages batches amount per simulator> <messages sending interval>" + echo "" + echo " - hv ves hostname : HighVolume VES Collector network hostname" + echo " - hv ves port : HighVolume VES Collector network port" + echo " - simulators amount : Amount of xNF simulators to be launched" + echo " - messages batches amount per simulator : Amount of batches of messages to be sent from each xNF simulator to HV-VES" + echo " - messages sending interval : interval in seconds between sending batches of messages from xNFs" + echo "Optional parameters:" + echo " - ssl-disable : Should xNF simulator be configured without using SSL/TLS connections" + echo " - messages-in-batch : Amount of messages sent on each request" + echo " - docker-network : Docker network to which xNF simulators should be added" + echo " - xnf-logs-directory : Path to directory where logs from all xNF simulators should be stored" + echo "Example invocations:" + echo "./start-simulation.sh --messages-in-batch=5 --docker-network=development_default ves-hv-collector 6061 10 20 0.5" + echo "./start-simulation.sh --messages-in-batch=5 --xnf-logs-directory=/tmp/xnf-simulation localhost 6061 10 20 0.5" + echo "Invocation with remote HV-VES host (Kubernetes slave IP given with default K8S NodePort for HV-VES service):" + echo "./start-simulation.sh --ssl-disable --xnf-logs-directory=/tmp/xnf-simulation 10.183.36.78 30222 5 100 5" + exit 1 +} + +function verbose_log() { + if [ -n "${VERBOSE+x}" ]; then + echo $@ + fi +} + +function create_logs_dir() { + if [ -n "${XNF_LOGS_DIRECTORY+x}" ]; then + if [ ! -d "${XNF_LOGS_DIRECTORY}" ]; then + mkdir ${XNF_LOGS_DIRECTORY} + fi + fi +} + +function create_xNFs_simulators() { + echo "Creating ${XNFS_AMOUNT} xNFs simulators" + [ -n "${SSL_DISABLE+x}" ] && verbose_log "--ssl-disable flag will be set inside containers." + for i in $(seq 1 ${XNFS_AMOUNT}); do + local XNF_PORT=$(get_unoccupied_port 32000 65000) + verbose_log "Starting xNF simulator container on port ${XNF_PORT} using run-xnf-simulator script" + XNF_CONTAINER_ID=$(${DEVELOPMENT_BIN_DIRECTORY}/run-xnf-simulator.sh ${SSL_DISABLE} $XNF_PORT ${HV_VES_HOSTNAME} ${HV_VES_PORT} ${DOCKER_NETWORK:-}) + CREATED_XNF_SIMULATORS_PORTS+=(${XNF_PORT}) + verbose_log "Container id: ${XNF_CONTAINER_ID}" + CREATED_XNF_SIMULATORS_IDS+=(${XNF_CONTAINER_ID}) + done +} + +function get_unoccupied_port() { + local LPORT=$1 + local UPORT=$2 + while true; do + local MPORT=$[$LPORT + ($RANDOM % $UPORT)]; + local LISTENING_PORTS=$(osqueryi --header=false --list "select port from listening_ports order by port"); + if (echo "${LISTENING_PORTS[@]}" | grep -xqv $MPORT); then + echo $MPORT; + break; + fi + done +} + +function wait_for_containers_startup_or_fail() { + local intervals_amount=30 + local wait_interval=5 + local all_containers_healthy=1 + + verbose_log "Waiting up to ${intervals_amount} times with interval of ${wait_interval}s for containers startup" + set +e + for i in $(seq 1 ${intervals_amount}); do + verbose_log "Try no. ${i}" + all_containers_healthy=1 + for id in ${CREATED_XNF_SIMULATORS_IDS[@]}; do + verbose_log "Checking container with id ${id}" + health=$(docker inspect --format='{{json .State.Health.Status}}' ${id}) + if [ ${health} != "\"healthy\"" ]; then + verbose_log "Container ${id} is not in healthy state. Actual status: ${health}" + all_containers_healthy=0 + break + fi + done + if [ $all_containers_healthy -eq 1 ]; then + break + fi + verbose_log "Sleeping for ${wait_interval}s" + sleep $wait_interval + done + set -e + + if [ $all_containers_healthy -ne 1 ]; then + echo "Some xNFs simulators failed at startup. Trying to cleanup..." + cleanup + echo "Exitting..." + exit 2 + fi +} + +function start_simulation() { + verbose_log "Simulation: every xNF will send ${MESSAGES_IN_BATCH} messages to hv-ves ( running on + ${HV_VES_HOSTNAME}:${HV_VES_PORT} ) ${MESSAGE_BATCHES_AMOUNT} times, once every ${MESSAGES_SENDING_INTERVAL}s" + for port in ${CREATED_XNF_SIMULATORS_PORTS[@]}; do + start_single_simulation $port $MESSAGES_IN_BATCH & + done +} + +function start_single_simulation() { + local port=$1 + local messages_to_be_sent=$2 + local message_type="VALID" + for i in $(seq 1 ${MESSAGE_BATCHES_AMOUNT}); do + ${DEVELOPMENT_BIN_DIRECTORY}/xnf-simulation.sh $port $messages_to_be_sent $message_type > /dev/null & + sleep $MESSAGES_SENDING_INTERVAL + done +} + +function assure_all_xNFs_requests_were_sent { + WAIT_TIME_FOR_REQUESTS_TO_BE_SENT=$(echo ";1 + $MESSAGES_SENDING_INTERVAL * $MESSAGE_BATCHES_AMOUNT" | bc) + echo "Waiting ${WAIT_TIME_FOR_REQUESTS_TO_BE_SENT}s for all xNF requests to be sent" + sleep $WAIT_TIME_FOR_REQUESTS_TO_BE_SENT +} + +function wait_for_simulators_to_finish_sending_messages() { + local seconds_to_wait=$1 + local all_containers_finished=1 + + echo "Waiting up to ${seconds_to_wait}s for xNFs simulators to finish sending messages" + for i in $(seq 1 ${seconds_to_wait}); do + verbose_log "Wait no. ${i}" + all_containers_finished=1 + for id in ${CREATED_XNF_SIMULATORS_IDS[@]}; do + verbose_log "Checking container ${id}" + local container_status=$(docker inspect --format='{{json .State.Health.Log }}' ${id} | jq '.[-1] | .Output') + + verbose_log "Container ${id} status: ${container_status}" + if [ "${container_status}" != "\"UP\\nNo simulation is in progress at the moment\"" ]; then + all_containers_finished=0 + break + fi + done + if [ $all_containers_finished -eq 1 ]; then + echo "All containers finished sending messages" + break + fi + verbose_log "Sleeping for 1s" + sleep 1 + done + + + if [ $all_containers_finished -ne 1 ]; then + echo "[ERROR] Some xNFs simulators failed to finish sending messages - simulation probably failed" + echo "For debug output rerun simulation with -v and --xnf-logs-directory command line options" + cleanup + echo "Exitting..." + exit 3 + fi +} + +function cleanup() { + echo "Cleaning up" + set +e + for container_id in ${CREATED_XNF_SIMULATORS_IDS[@]}; do + verbose_log "Stopping container: ${container_id}" + docker stop $container_id > /dev/null + if [ -n "${XNF_LOGS_DIRECTORY+x}" ]; then + local log_file=${XNF_LOGS_DIRECTORY}/${container_id}.log + verbose_log "Writing container logs to: ${log_file}" + docker logs ${container_id} &> $log_file + fi + verbose_log "Removing container: ${container_id}" + docker rm $container_id > /dev/null + done + set -e +} + + +function parse_long_opts_with_arguments() { + if [[ ${OPTARG} =~ .*=.* ]] # is option in --key=value format + then + OPT=${OPTARG/=*/} + ((${#OPT} <= 1)) && { + echo "Invalid option '$OPT'" >&2 + exit 2 + } + OPTARG=${OPTARG#*=} + else + echo -e "No value provided for ${OPTARG}. Please use \"--${OPTARG}=VALUE\" format." >&2 + usage + fi +} + +# parse command line +optspec=":vh-:" # catch v, h and - +while getopts "$optspec" arg; do + case "${arg}" in + -) # handle longopts + case "${OPTARG}" in + verbose) + VERBOSE=True ;; + ssl-disable) + SSL_DISABLE="--ssl-disable" ;; + help) + usage ;; + *) + parse_long_opts_with_arguments + case "${OPT}" in + messages-in-batch) + MESSAGES_IN_BATCH=$OPTARG ;; + docker-network) + DOCKER_NETWORK=$OPTARG ;; + xnf-logs-directory) + XNF_LOGS_DIRECTORY=$OPTARG ;; + *) + usage ;; + esac ;; + esac ;; + v) + VERBOSE=True ;; + h) + usage ;; + *) + echo "Unknown option -${OPTARG}" >&2 + usage ;; + esac +done +shift $((OPTIND-1)) + +[ $# -le 4 ] && (echo -e "Unsufficient arguments"; usage) + + +DEVELOPMENT_BIN_DIRECTORY=$(realpath $(dirname "$0")) +HV_VES_HOSTNAME=${1} +HV_VES_PORT=${2} +XNFS_AMOUNT=${3} +MESSAGE_BATCHES_AMOUNT=${4} +MESSAGES_SENDING_INTERVAL=${5} + +# set defaults if absent +[ -z "${MESSAGES_IN_BATCH+x}" ] && MESSAGES_IN_BATCH=1 +[ -z "${SSL_DISABLE+x}" ] && SSL_DISABLE="" + +create_logs_dir + + +CREATED_XNF_SIMULATORS_PORTS=() +CREATED_XNF_SIMULATORS_IDS=() +trap cleanup SIGINT SIGTERM +create_xNFs_simulators + +wait_for_containers_startup_or_fail + +echo "All xNFs containers are healthy, starting simulation" +start_simulation + +assure_all_xNFs_requests_were_sent + +assumed_message_sending_time=$(echo ";0.00025 * $XNFS_AMOUNT" | bc) +seconds_to_wait=$(echo ";$assumed_message_sending_time * $MESSAGE_BATCHES_AMOUNT * $MESSAGES_IN_BATCH" | bc) +seconds_to_wait=$(echo ";if($seconds_to_wait > 2) $seconds_to_wait else 2" | bc) +wait_for_simulators_to_finish_sending_messages $seconds_to_wait +# there might be network lag between moment when xNF finished sending messages and they actually are received by hv-ves +# thus we cannot start removing xNFs immediately to prevent closing socket channels +sleep 5 + +cleanup
\ No newline at end of file diff --git a/tools/development/bin/xnf-simulation.sh b/tools/development/bin/xnf-simulation.sh new file mode 100755 index 00000000..ade0e426 --- /dev/null +++ b/tools/development/bin/xnf-simulation.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# dcaegen2-collectors-veshv +# ================================================================================ +# Copyright (C) 2018 NOKIA +# ================================================================================ +# 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========================================================= + +set -euo pipefail + +usage() { + echo "Send request to xnf-simulator" + echo "Usage: $0 [-h|--help] [-v|--verbose] [<xnf listen port> [<messages amount> [<messages type> [<xnf endpoint>]]]]" + echo "" + echo "Default values:" + echo " - xnf listen port : 6062" + echo " - messages amount : 1" + echo " - messages type : VALID" + echo " - xnf endpoint : simulator/async" + echo "Example invocations:" + echo "./xnf-simulation.sh -v 6062 1000 VALID" + exit 1 +} + +optspec=":vh-:" # catch v, h and - +while getopts "$optspec" arg; do + case "${arg}" in + -) # handle longopts + case "${OPTARG}" in + verbose) + VERBOSE=True + ;; + help) + usage + ;; + *) + echo "Unknown option --${OPTARG}" >&2 + usage + ;; + esac + ;; + v) + VERBOSE=True + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" >&2 + usage + ;; + esac +done +shift $((OPTIND-1)) + +XNF_PORT=${1:-6062} +MESSAGES_AMOUNT=${2:-1} +MESSAGES_TYPE=${3:-VALID} +XNF_ENDPOINT=simulator/async + +if [ -n "${VERBOSE+x}" ]; then + echo "Requesting xnf-simulator on port ${XNF_PORT} to send ${MESSAGES_AMOUNT} messages of type ${MESSAGES_TYPE}" +fi + +currentTimeMicros=$((`date +%s%N`/1000)) +REQUEST_ID=$(curl --request POST -s --header 'Content-Type: application/json' localhost:${XNF_PORT}/${XNF_ENDPOINT} -d " +[ + { + \"commonEventHeader\": { + \"version\": \"sample-version\", + \"domain\": \"perf3gpp\", + \"sequence\": 1, + \"priority\": 1, + \"eventId\": \"sample-event-id\", + \"eventName\": \"sample-event-name\", + \"eventType\": \"sample-event-type\", + \"startEpochMicrosec\": 120034455, + \"lastEpochMicrosec\": $currentTimeMicros, + \"nfNamingCode\": \"sample-nf-naming-code\", + \"nfcNamingCode\": \"sample-nfc-naming-code\", + \"reportingEntityId\": \"sample-reporting-entity-id\", + \"reportingEntityName\": \"sample-reporting-entity-name\", + \"sourceId\": \"sample-source-id\", + \"sourceName\": \"sample-source-name\", + \"vesEventListenerVersion\": \"7.2.0\" + }, + \"messageType\": \"${MESSAGES_TYPE}\", + \"messagesAmount\": ${MESSAGES_AMOUNT} + } +]") + +if [ -n "${VERBOSE+x}" ]; then + echo -e "Request id: ${REQUEST_ID}\n" + + echo "To check request status execute:" + echo "curl --request GET localhost:${XNF_PORT}/simulator/${REQUEST_ID}" + echo "To further debug you can try something similiar to:" + echo "docker ps -a | grep ${XNF_PORT} | awk '{ print \$1 }' | xargs docker logs" +else + echo "${REQUEST_ID}" +fi
\ No newline at end of file diff --git a/tools/development/configuration/base.json b/tools/development/configuration/base.json new file mode 100644 index 00000000..2a806adb --- /dev/null +++ b/tools/development/configuration/base.json @@ -0,0 +1,11 @@ +{ + "logLevel": "DEBUG", + "server.listenPort": 6061, + "server.idleTimeoutSec": 60, + "cbs.firstRequestDelaySec": 5, + "cbs.requestIntervalSec": 5, + "security.keys.keyStoreFile": "/etc/ves-hv/ssl/server.p12", + "security.keys.keyStorePasswordFile": "/etc/ves-hv/ssl/server.pass", + "security.keys.trustStoreFile": "/etc/ves-hv/ssl/trust.p12", + "security.keys.trustStorePasswordFile": "/etc/ves-hv/ssl/trust.pass" +}
\ No newline at end of file diff --git a/tools/development/configuration/local.json b/tools/development/configuration/local.json new file mode 100644 index 00000000..cfaaaa40 --- /dev/null +++ b/tools/development/configuration/local.json @@ -0,0 +1,11 @@ +{ + "logLevel": "DEBUG", + "server.listenPort": 8061, + "server.idleTimeoutSec": 60, + "cbs.firstRequestDelaySec": 10, + "cbs.requestIntervalSec": 5, + "security.keys.keyStoreFile": "development/ssl/server.p12", + "security.keys.keyStorePasswordFile": "development/ssl/server.pass", + "security.keys.trustStoreFile": "development/ssl/trust.p12", + "security.keys.trustStorePasswordFile": "development/ssl/server.pass" +} diff --git a/tools/development/consul/configuration.hcl b/tools/development/consul/configuration.hcl new file mode 100644 index 00000000..f975955e --- /dev/null +++ b/tools/development/consul/configuration.hcl @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * csit-dcaegen2-collectors-hv-ves + * ================================================================================ + * Copyright (C) 2019 NOKIA + * ================================================================================ + * 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========================================================= + */ + +server = true +bootstrap = true +ui = true +client_addr = "0.0.0.0" + +service { + # name under which hv-ves collector should seek cbs + # usually set as CONFIG_BINDING_SERVICE environment variable + Name = "CBS" + # address of CBS as seen by hv-ves collector + Address = "config-binding-service" + Port = 10000 +} + diff --git a/tools/development/docker-compose.yml b/tools/development/docker-compose.yml new file mode 100644 index 00000000..fbc38920 --- /dev/null +++ b/tools/development/docker-compose.yml @@ -0,0 +1,181 @@ +version: "3.5" +services: + + # + # DMaaP Message Router + # + + message-router-zookeeper: + image: nexus3.onap.org:10001/onap/dmaap/zookeeper:4.0.0 + ports: + - "2181:2181" + + message-router-kafka-0: + image: nexus3.onap.org:10001/onap/dmaap/kafka111:0.0.6 + ports: + - "9092:9092" + - "9093:9093" +# command: "start-kafka.sh" + environment: + HOST_IP: 127.0.0.1 + KAFKA_BROKER_ID: 0 + ENDPOINT_PORT: 30490 + KAFKA_ZOOKEEPER_CONNECT: "message-router-zookeeper:2181" + KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" + KAFKA_DELETE_TOPIC_ENABLE: "true" + + KAFKA_LISTENERS: "INTERNAL_SASL_PLAINTEXT://0.0.0.0:9092,EXTERNAL_SASL_PLAINTEXT://0.0.0.0:9093" + KAFKA_ADVERTISED_LISTENERS: "INTERNAL_SASL_PLAINTEXT://message-router-kafka-0:9092,EXTERNAL_SASL_PLAINTEXT://message-router-kafka-0:9093" + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL_SASL_PLAINTEXT:SASL_PLAINTEXT,EXTERNAL_SASL_PLAINTEXT:SASL_PLAINTEXT" + KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL_SASL_PLAINTEXT" + KAFKA_SASL_ENABLED_MECHANISMS: "PLAIN" + KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: "PLAIN" + KAFKA_AUTHORIZER_CLASS_NAME: "org.onap.dmaap.kafkaAuthorize.KafkaCustomAuthorizer" + + aaf_locate_url: https://aaf-locate:8095 + KAFKA_LOG_DIRS: /opt/kafka/data + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_DEFAULT_REPLICATION_FACTOR: 1 + KAFKA_NUM_PARTITIONS: 1 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + depends_on: + - message-router-zookeeper + + # + # Consul / CBS + # + + consul-server: + image: docker.io/consul:1.0.6 + ports: + - "8500:8500" + volumes: + - ./consul/:/consul/config + + consul-config: + image: docker.io/consul:1.0.6 + restart: on-failure + command: ["kv", "put", "-http-addr=http://consul-server:8500", "dcae-hv-ves-collector", '{ + "streams_publishes": { + "perf3gpp": { + "type": "kafka", + "aaf_credentials": { + "username": "admin", + "password": "admin_secret" + }, + "kafka_info": { + "bootstrap_servers": "message-router-kafka-0:9093", + "topic_name": "HV_VES_PERF3GPP" + } + } + } + }' + ] + depends_on: + - consul-server + + config-binding-service: + image: nexus3.onap.org:10001/onap/org.onap.dcaegen2.platform.configbinding.app-app:2.2.4 + ports: + - "10000:10000" + environment: + CONSUL_HOST: "consul-server" + depends_on: + - consul-config + + # + # DCAE HV VES Collector + # + + ves-hv-collector: + image: onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-main:latest + ports: + - "6060:6060" + - "6061:6061/tcp" + environment: + JAVA_OPTS: "-Dio.netty.leakDetection.level=paranoid -Dlogback.configurationFile=/etc/ONAP/dcae-hv-ves-collector/logback.xml" + VESHV_CONFIGURATION_FILE: "/etc/ves-hv/configuration/base.json" + CONSUL_HOST: "consul-server" + CONFIG_BINDING_SERVICE: "CBS" + HOSTNAME: "dcae-hv-ves-collector" + healthcheck: + test: ./healthcheck.sh || exit 1 + interval: 10s + timeout: 3s + retries: 3 + start_period: 15s + depends_on: + - message-router-kafka-0 + - config-binding-service + volumes: + - ./configuration/:/etc/ves-hv/configuration/ + - ../ssl/:/etc/ves-hv/ssl/ + - ./logs:/var/log/ONAP/dcae-hv-ves-collector + + + # + # Simulators + # + + xnf-simulator: + image: onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-xnf-simulator + ports: + - "6062:6062/tcp" + - "6063:6063" + command: ["--listen-port", "6062", + "--health-check-api-port", "6063", + "--ves-host", "ves-hv-collector", + "--ves-port", "6061", + "--key-store", "/etc/ves-hv/client.p12", + "--key-store-password-file", "/etc/ves-hv/client.pass", + "--trust-store", "/etc/ves-hv/trust.p12", + "--trust-store-password-file", "/etc/ves-hv/trust.pass"] + healthcheck: + test: curl -f http://localhost:6063/health/ready || exit 1 + interval: 10s + timeout: 3s + retries: 3 + start_period: 10s + depends_on: + - ves-hv-collector + volumes: + - ./ssl/:/etc/ves-hv/ + + dcae-app-simulator: + image: onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-dcae-app-simulator + ports: + - "6064:6064/tcp" + command: ["--listen-port", "6064", + "--kafka-bootstrap-servers", "message-router-kafka-0:9092", + "--kafka-topics", "HV_VES_PERF3GPP"] + depends_on: + - message-router-kafka-0 + + # + # Monitoring + # + + prometheus: + image: prom/prometheus + ports: + - "9090:9090" + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + + grafana: + image: grafana/grafana + ports: + - "3000:3000" + environment: + GF_AUTH_DISABLE_LOGIN_FORM: "true" + GF_AUTH_DISABLE_SIGNOUT_MENU: "true" + GF_AUTH_ANONYMOUS_ENABLED: "true" + GF_AUTH_ANONYMOUS_ORG_ROLE: "Admin" + volumes: + - ./grafana/datasources:/etc/grafana/provisioning/datasources + - ./grafana/dashboards-providers:/etc/grafana/provisioning/dashboards + # defined in ./grafana/dashboards-providers/dasboard-providers.yaml + - ./grafana/dashboards:/var/lib/grafana/dashboards/hv-ves + + diff --git a/tools/development/grafana/dashboards-providers/dashboard-providers.yaml b/tools/development/grafana/dashboards-providers/dashboard-providers.yaml new file mode 100644 index 00000000..78da55c9 --- /dev/null +++ b/tools/development/grafana/dashboards-providers/dashboard-providers.yaml @@ -0,0 +1,10 @@ +apiVersion: 1 + +providers: +- name: 'hv-ves-dashboards' + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + options: + path: /var/lib/grafana/dashboards/hv-ves
\ No newline at end of file diff --git a/tools/development/grafana/dashboards/connections.json b/tools/development/grafana/dashboards/connections.json new file mode 100644 index 00000000..2d0182c9 --- /dev/null +++ b/tools/development/grafana/dashboards/connections.json @@ -0,0 +1,573 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "Prometheus", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 1, + "links": [], + "panels": [ + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "Prometheus", + "format": "none", + "gauge": { + "maxValue": 10000, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(hvves_connections_active) by (value)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "7000,9000", + "title": "Currently active connections", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "columns": [ + { + "text": "Current", + "value": "current" + } + ], + "datasource": "Prometheus", + "fontSize": "100%", + "gridPos": { + "h": 9, + "w": 6, + "x": 6, + "y": 0 + }, + "id": 2, + "links": [], + "pageSize": 10, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(hvves_connections_active) by (kubernetes_pod_name, value)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "B" + } + ], + "timeFrom": "1h", + "title": "Active connections per pod", + "transform": "timeseries_aggregations", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(hvves_connections_active)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Active connections total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": "45 m", + "timeRegions": [], + "timeShift": null, + "title": "Active connections over time", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 9 + }, + "id": 8, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(hvves_connections_total)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "title": "Total connections", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "Prometheus", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 9 + }, + "id": 10, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(hvves_clients_rejected_total)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Clients rejected", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "0", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "columns": [ + { + "text": "Current", + "value": "current" + } + ], + "datasource": "Prometheus", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 12 + }, + "id": 11, + "links": [], + "pageSize": 10, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(hvves_connections_total) by (kubernetes_pod_name, value)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "B" + } + ], + "timeFrom": "1h", + "title": "Total connections per pod", + "transform": "timeseries_aggregations", + "type": "table" + }, + { + "columns": [ + { + "text": "Current", + "value": "current" + } + ], + "datasource": "Prometheus", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 12 + }, + "id": 12, + "links": [], + "pageSize": 10, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(hvves_clients_rejected_total) by (kubernetes_pod_name, value)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "B" + } + ], + "timeFrom": "1h", + "title": "Rejected connections per pod", + "transform": "timeseries_aggregations", + "type": "table" + } + ], + "refresh": "1s", + "schemaVersion": 16, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "1s", + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "HV-VES connections", + "uid": "bAy7xlwmk", + "version": 1 +}
\ No newline at end of file diff --git a/tools/development/grafana/dashboards/processing.json b/tools/development/grafana/dashboards/processing.json new file mode 100644 index 00000000..d74968cb --- /dev/null +++ b/tools/development/grafana/dashboards/processing.json @@ -0,0 +1,926 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "Prometheus", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 2, + "links": [], + "panels": [ + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "Prometheus", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 0 + }, + "id": 2, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(hvves_messages_received_total) by (value)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Messages received", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 3, + "y": 0 + }, + "id": 4, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(hvves_messages_dropped_total)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Messages dropped", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 6, + "y": 0 + }, + "id": 6, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(hvves_messages_sent_total)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Messages Sent", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "fill": 0, + "gridPos": { + "h": 12, + "w": 15, + "x": 9, + "y": 0 + }, + "id": 9, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 350, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.90, sum( rate(hvves_messages_processing_time_seconds_bucket[15m]) )by(le) )", + "format": "time_series", + "hide": false, + "instant": false, + "intervalFactor": 1, + "legendFormat": "90th percentile of processing time on pods", + "refId": "B" + }, + { + "expr": "rate(hvves_messages_processing_time_seconds_sum[15m])/rate(hvves_messages_processing_time_seconds_count[15m])", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ kubernetes_pod_name }}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Single message processing time average", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "fill": 0, + "gridPos": { + "h": 9, + "w": 9, + "x": 0, + "y": 3 + }, + "id": 8, + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(hvves_messages_latency_seconds_sum[1h])/rate(hvves_messages_latency_seconds_count[1h])", + "format": "time_series", + "hide": false, + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{ kubernetes_pod_name }}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [ + { + "text": "Current", + "value": "current" + } + ], + "fontSize": "100%", + "gridPos": { + "h": 9, + "w": 5, + "x": 0, + "y": 12 + }, + "id": 11, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(hvves_messages_received_total) by (kubernetes_pod_name, value)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Messages processed per pod", + "transform": "timeseries_aggregations", + "type": "table" + }, + { + "columns": [ + { + "text": "Current", + "value": "current" + } + ], + "fontSize": "100%", + "gridPos": { + "h": 5, + "w": 4, + "x": 5, + "y": 12 + }, + "id": 12, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(hvves_messages_sent_topic_total) by (topic, value)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{topic}}", + "refId": "A" + } + ], + "title": "Messages sent per topic", + "transform": "timeseries_aggregations", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fill": 0, + "gridPos": { + "h": 9, + "w": 9, + "x": 9, + "y": 12 + }, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(system_cpu_usage) by (kubernetes_pod_name)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": "20 m", + "timeRegions": [], + "timeShift": null, + "title": "System cpu usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": false, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [ + { + "text": "Current", + "value": "current" + }, + { + "text": "Avg", + "value": "avg" + } + ], + "datasource": "Prometheus", + "fontSize": "100%", + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 12 + }, + "id": 22, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "(sum(container_memory_usage_bytes{pod_name=~\"dep-dcae-hv-ves-collector.*\"}) by (pod_name)) / 1024 / 1024 / 1024", + "format": "time_series", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "{{ pod_name }}", + "refId": "A" + } + ], + "title": "Memory usage per pod [GB]", + "transform": "timeseries_aggregations", + "transparent": false, + "type": "table" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "format": "decbytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 5, + "y": 17 + }, + "id": 20, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(hvves_messages_received_payload_bytes_total)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Total received payload bytes", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "Prometheus", + "format": "decbytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 5, + "y": 19 + }, + "id": 18, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(hvves_messages_received_payload_bytes_total)/sum(hvves_messages_received_total)", + "format": "time_series", + "hide": false, + "instant": false, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Average received payload bytes", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "0", + "value": "null" + } + ], + "valueName": "current" + } + ], + "refresh": "1s", + "schemaVersion": 16, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "1s", + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "HV-VES processing", + "uid": "V94Kjlwmz", + "version": 1 +}
\ No newline at end of file diff --git a/tools/development/grafana/datasources/prometheus.yaml b/tools/development/grafana/datasources/prometheus.yaml new file mode 100644 index 00000000..80717b08 --- /dev/null +++ b/tools/development/grafana/datasources/prometheus.yaml @@ -0,0 +1,11 @@ +apiVersion: 1 + +datasources: +- name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: true + jsonData: + timeInterval: '5s' diff --git a/tools/development/logs/.gitignore b/tools/development/logs/.gitignore new file mode 100644 index 00000000..1287e9bd --- /dev/null +++ b/tools/development/logs/.gitignore @@ -0,0 +1,2 @@ +** +!.gitignore diff --git a/tools/development/prometheus.yml b/tools/development/prometheus.yml new file mode 100644 index 00000000..201c8f96 --- /dev/null +++ b/tools/development/prometheus.yml @@ -0,0 +1,14 @@ +global: + scrape_interval: 5s + external_labels: + monitor: 'my-monitor' + +scrape_configs: + - job_name: 'prometheus' + static_configs: + - targets: ['localhost:9090'] + + - job_name: 'ves-hv-collector' + metrics_path: '/monitoring/prometheus' + static_configs: + - targets: ['ves-hv-collector:6060'] diff --git a/tools/performance/configuration/base.json b/tools/performance/configuration/base.json new file mode 100644 index 00000000..2a806adb --- /dev/null +++ b/tools/performance/configuration/base.json @@ -0,0 +1,11 @@ +{ + "logLevel": "DEBUG", + "server.listenPort": 6061, + "server.idleTimeoutSec": 60, + "cbs.firstRequestDelaySec": 5, + "cbs.requestIntervalSec": 5, + "security.keys.keyStoreFile": "/etc/ves-hv/ssl/server.p12", + "security.keys.keyStorePasswordFile": "/etc/ves-hv/ssl/server.pass", + "security.keys.trustStoreFile": "/etc/ves-hv/ssl/trust.p12", + "security.keys.trustStorePasswordFile": "/etc/ves-hv/ssl/trust.pass" +}
\ No newline at end of file diff --git a/tools/performance/consul/configuration.hcl b/tools/performance/consul/configuration.hcl new file mode 100644 index 00000000..f975955e --- /dev/null +++ b/tools/performance/consul/configuration.hcl @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * csit-dcaegen2-collectors-hv-ves + * ================================================================================ + * Copyright (C) 2019 NOKIA + * ================================================================================ + * 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========================================================= + */ + +server = true +bootstrap = true +ui = true +client_addr = "0.0.0.0" + +service { + # name under which hv-ves collector should seek cbs + # usually set as CONFIG_BINDING_SERVICE environment variable + Name = "CBS" + # address of CBS as seen by hv-ves collector + Address = "config-binding-service" + Port = 10000 +} + diff --git a/tools/performance/docker-compose.yml b/tools/performance/docker-compose.yml new file mode 100644 index 00000000..82143235 --- /dev/null +++ b/tools/performance/docker-compose.yml @@ -0,0 +1,116 @@ +version: "3.5" +services: + + message-router-zookeeper: + image: nexus3.onap.org:10001/onap/dmaap/zookeeper:4.0.0 + ports: + - "2181:2181" + + message-router-kafka-0: + image: nexus3.onap.org:10001/onap/dmaap/kafka111:0.0.6 + ports: + - "9092:9092" + - "9093:9093" + environment: + HOST_IP: 127.0.0.1 + KAFKA_BROKER_ID: 0 + ENDPOINT_PORT: 30490 + KAFKA_ZOOKEEPER_CONNECT: "message-router-zookeeper:2181" + KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" + KAFKA_DELETE_TOPIC_ENABLE: "true" + + KAFKA_LISTENERS: "INTERNAL_SASL_PLAINTEXT://0.0.0.0:9092,EXTERNAL_SASL_PLAINTEXT://0.0.0.0:9093" + KAFKA_ADVERTISED_LISTENERS: "INTERNAL_SASL_PLAINTEXT://message-router-kafka-0:9092,EXTERNAL_SASL_PLAINTEXT://message-router-kafka-0:9093" + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL_SASL_PLAINTEXT:SASL_PLAINTEXT,EXTERNAL_SASL_PLAINTEXT:SASL_PLAINTEXT" + KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL_SASL_PLAINTEXT" + KAFKA_SASL_ENABLED_MECHANISMS: "PLAIN" + KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: "PLAIN" + KAFKA_AUTHORIZER_CLASS_NAME: "org.onap.dmaap.kafkaAuthorize.KafkaCustomAuthorizer" + + aaf_locate_url: https://aaf-locate:8095 + KAFKA_LOG_DIRS: /opt/kafka/data + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_DEFAULT_REPLICATION_FACTOR: 1 + KAFKA_NUM_PARTITIONS: 1 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + depends_on: + - message-router-zookeeper + + consul-server: + image: docker.io/consul:1.0.6 + ports: + - "8500:8500" + volumes: + - ./consul/:/consul/config + + consul-bootstrap: + image: docker.io/consul:1.0.6 + restart: on-failure + command: ["kv", "put", "-http-addr=http://consul-server:8500", "dcae-hv-ves-collector", '{ + "streams_publishes": { + "perf3gpp": { + "type": "kafka", + "aaf_credentials": { + "username": "admin", + "password": "admin_secret" + }, + "kafka_info": { + "bootstrap_servers": "message-router-kafka-0:9093", + "topic_name": "HV_VES_PERF3GPP" + } + } + } + }' + ] + depends_on: + - consul-server + + config-binding-service: + image: nexus3.onap.org:10001/onap/org.onap.dcaegen2.platform.configbinding.app-app:2.2.4 + ports: + - "10000:10000" + environment: + CONSUL_HOST: "consul-server" + depends_on: + - consul-bootstrap + + ves-hv-collector: + image: onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-main:latest + ports: + - "6060:6060" + - "6061:6061/tcp" + environment: + JAVA_OPTS: "-Dio.netty.leakDetection.level=paranoid -Dlogback.configurationFile=/etc/ONAP/dcae-hv-ves-collector/logback.xml" + VESHV_CONFIGURATION_FILE: "/etc/ves-hv/configuration/base.json" + CONSUL_HOST: "consul-server" + CONFIG_BINDING_SERVICE: "CBS" + HOSTNAME: "dcae-hv-ves-collector" + healthcheck: + test: ./healthcheck.sh || exit 1 + interval: 10s + timeout: 3s + retries: 3 + start_period: 15s + depends_on: + - message-router-kafka-0 + - config-binding-service + volumes: + - ./configuration/:/etc/ves-hv/configuration/ + - ./logs:/var/log/ONAP/dcae-hv-ves-collector + - ../ssl/:/etc/ves-hv/ssl/ + + kafka-consumer: + image: onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-kafka-consumer + ports: + - "6064:6064/tcp" + command: ["--listen-port", "6062"] + depends_on: + - message-router-kafka-0 + + prometheus: + image: prom/prometheus + ports: + - "9090:9090" + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml diff --git a/tools/performance/local-performance-test.sh b/tools/performance/local-performance-test.sh new file mode 100755 index 00000000..cad21ef8 --- /dev/null +++ b/tools/performance/local-performance-test.sh @@ -0,0 +1,176 @@ +#!/usr/bin/env bash + +cd "$(dirname "$0")" + +CERT_FILE=${CERT_FILE:-/ssl/client.p12} +CERT_PASS_FILE=${CERT_PASS_FILE:-/ssl/client.pass} +HV_VES_NETWORK=${HV_VES_NETWORK:-performance_default} +VOLUME_MAPPING=${VOLUME_MAPPING:-$PWD/../ssl/:/ssl} +PRODUCER_IMAGE_NAME=${PRODUCER_IMAGE_NAME:-the-a-team-registry-local.esisoj70.emea.nsn-net.net/onap/org.onap.dcaegen2.collectors.hv-ves.hv-collector-rust-client:latest} + +PRODUCER_APP_NAME=hv-ves-producer +HV_VES_ADDRESS=ves-hv-collector:6061 +CONTAINERS_COUNT=1 +CLIENTS_PER_CONTAINER=1 +MSG_SIZE=16384 +MSG_COUNT=1000 +INTERVAL_MS=0 + + +function usage() { + echo "" + echo "Run HV-VES performance test locally" + echo "Usage $0 setup|start|clean|help" + echo " setup : generate certs and set up docker components" + echo " start : run the performance test" + echo " Optional parameters:" + echo " --address : HV-VES address in host:port format (ves-hv-collector:6061)" + echo " --containers : number of docker containers to create (1)" + echo " --clients : number of clients in single container (1)" + echo " --msg-size : size in bytes of a single message (16384)" + echo " --msg-count : amount of messages to sent by one client in single container (1000)" + echo " --interval : interval between messages (0)" + echo " clean : remove generated certs, HV-VES components and producers" + echo " help : print usage" + echo "Example invocations:" + echo "./local-performance-test.sh setup" + echo "./local-performance-test.sh start --containers 10 --clients 100 --msg-count 10000" + echo "./local-performance-test.sh clean" + exit 1 +} + +function setup_environment(){ + echo "Setting up" + cd ../ssl + ./gen-certs.sh + cd ../performance + docker-compose up -d + + echo "Waiting for components to be healthy.." + while [[ $(docker-compose ps | grep -c "unhealthy\|starting") -ne 0 ]] ; do + sleep 1 + done + + echo "All components ready" + exit 0 +} + +function start_performance_test(){ + + TEST_ID=$(date +%s) + create_containers ${CONTAINERS_COUNT} ${TEST_ID} & + + while :; do + ACTIVE_PRODUCERS=$(docker ps --format "table {{.ID}}\t{{.Status}}" -f "label=id=$TEST_ID") + ACTIVE_PRODUCERS_COUNT=$(echo "$ACTIVE_PRODUCERS" | grep -c "Up") + + clear + print_test_configuration + echo "Active producers ($ACTIVE_PRODUCERS_COUNT/$CONTAINERS_COUNT):" + echo "$ACTIVE_PRODUCERS" + + EXITED_CONTAINERS=$(docker ps -aq -f "label=id=$TEST_ID" -f status=exited | wc -l) + [[ ${EXITED_CONTAINERS} -eq ${CONTAINERS_COUNT} ]] && break + + sleep 1 + done + + clear + print_test_configuration + echo "Test finished" + # TODO put test result here + exit 0 +} + +function print_test_configuration(){ + echo "PERFORMANCE TEST IN PROGRESS" + echo "" + echo "Test configuration:" + echo "Containers count: $CONTAINERS_COUNT" + echo "Clients per container: $CLIENTS_PER_CONTAINER" + echo "Message size: $MSG_SIZE" + echo "Messages per client: $MSG_COUNT" + echo "Interval: $INTERVAL_MS" + echo "" +} + +function create_containers(){ + + for i in $(seq 1 ${1}); do + docker run -d -l id="$2" -l app="$PRODUCER_APP_NAME" -v "$VOLUME_MAPPING" --network="$HV_VES_NETWORK" "$PRODUCER_IMAGE_NAME" \ + --address "$HV_VES_ADDRESS" \ + --certfile "$CERT_FILE" \ + --certpass "$CERT_PASS_FILE" \ + --containers "$CONTAINERS_COUNT" \ + --clients "$CLIENTS_PER_CONTAINER" \ + --msgsize "$MSG_SIZE" \ + --msgcount "$MSG_COUNT" \ + --intervalms "$INTERVAL_MS" > /dev/null + done +} + +function clean(){ + echo "Cleaning up" + + echo "Removing active producers" + docker rm --force $(docker ps -aqf "label=app=$PRODUCER_APP_NAME") + + echo "Clearing generated certs" + cd ../ssl + ./gen-certs.sh clean + cd ../performance + + echo "Removing HV-VES components" + docker-compose down + exit 0 +} + +if [[ $# -eq 0 ]]; then + usage +else + for arg in ${@} + do + case ${arg} in + setup) + setup_environment + ;; + start) + shift 1 + while [[ $(($#)) -gt 0 ]]; do + case "${1}" in + --address) + HV_VES_ADDRESS=${2} + ;; + --containers) + CONTAINERS_COUNT=${2} + ;; + --clients) + CLIENTS_PER_CONTAINER=${2} + ;; + --msg-size) + MSG_SIZE=${2} + ;; + --msg-count) + MSG_COUNT=${2} + ;; + --interval) + INTERVAL_MS=${2} + ;; + esac + shift 2 + done + start_performance_test + ;; + clean) + clean + ;; + help) + usage + ;; + *) + echo "Unknown action: ${arg}" >&2 + usage + ;; + esac + done +fi
\ No newline at end of file diff --git a/tools/performance/logs/.gitignore b/tools/performance/logs/.gitignore new file mode 100644 index 00000000..1287e9bd --- /dev/null +++ b/tools/performance/logs/.gitignore @@ -0,0 +1,2 @@ +** +!.gitignore diff --git a/tools/performance/prometheus.yml b/tools/performance/prometheus.yml new file mode 100644 index 00000000..b9a937c2 --- /dev/null +++ b/tools/performance/prometheus.yml @@ -0,0 +1,14 @@ +global: + scrape_interval: 5s + external_labels: + monitor: 'my-monitor' + +scrape_configs: + - job_name: 'prometheus' + static_configs: + - targets: ['localhost:9090'] + + - job_name: 'kafka-consumer' + metrics_path: '/monitoring/prometheus' + static_configs: + - targets: ['kafka-consumer:6062'] diff --git a/tools/ssl/.gitignore b/tools/ssl/.gitignore new file mode 100644 index 00000000..955c17d1 --- /dev/null +++ b/tools/ssl/.gitignore @@ -0,0 +1,7 @@ +*.crt +*.key +*.srl +*.csr +*.pkcs12 +*.p12 +*.pass diff --git a/tools/ssl/Makefile-openssl b/tools/ssl/Makefile-openssl new file mode 100644 index 00000000..09802ce4 --- /dev/null +++ b/tools/ssl/Makefile-openssl @@ -0,0 +1,41 @@ +FILE=sample +PASSWD=onaponap +CA_PASSWD=onaponap +SUBJ=/C=PL/ST=DL/L=Wroclaw/O=Nokia/OU=MANO +CA=trust + +sign: $(FILE).crt + +clean: + rm -f *.crt *.key *.srl *.csr *.pkcs12 + +generate-ca-certificate: $(CA).crt + +generate-private-key: $(FILE).key + +create-public-key: $(FILE).pub + +create-sign-request: $(FILE).csr + +create-key-store: $(FILE).ks.pkcs12 + +create-trust-store: $(CA).crt + openssl pkcs12 -export -in $(CA).crt -CAfile $(CA).crt -out $(CA).pkcs12 -nokeys -noiter -nomaciter -passout pass:$(PASSWD) + +$(CA).crt: + openssl req -new -x509 -keyout $(CA).key -out $(CA).crt -days 365 -passout pass:$(CA_PASSWD) -subj "$(SUBJ)" + +$(FILE).key: + openssl genpkey -algorithm RSA -out $(FILE).key -pkeyopt rsa_keygen_bits:2048 + +$(FILE).pub: $(FILE).key + openssl x509 -req -days 360 -in client.csr -CA $(CA).crt -CAkey $(CA).key -CAcreateserial -out client.crt + +$(FILE).csr: $(FILE).key + openssl req -new -sha256 -key $(FILE).key -out $(FILE).csr -subj "$(SUBJ)" + +$(FILE).crt: $(CA).crt $(FILE).csr + openssl x509 -req -days 360 -in $(FILE).csr -CA $(CA).crt -CAkey $(CA).key -out $(FILE).crt -CAcreateserial -passin pass:$(CA_PASSWD) + +$(FILE).ks.pkcs12: $(FILE).key $(FILE).crt $(CA).crt + openssl pkcs12 -export -in $(FILE).crt -inkey $(FILE).key -CAfile $(CA).crt -out $(FILE).ks.pkcs12 -noiter -nomaciter -passout pass:$(PASSWD) diff --git a/tools/ssl/README.md b/tools/ssl/README.md new file mode 100644 index 00000000..c2819d24 --- /dev/null +++ b/tools/ssl/README.md @@ -0,0 +1,54 @@ +# Generating SSL certificates + +## Java keytool way (recommended) + +To generate: + +```shell +./gen-certs.sh +``` + +To clean (remove generated files): + +```shell +./gen-certs.sh clean +``` + +## OpenSSL way (currently might not work) + +> Add `-f Makefile-openssl` to each command + +Typical usage: + +```shell +make FILE=client +make FILE=server +``` + +or (to generate PKCS12 key and trust stores): + +```shell +make create-key-store FILE=client +make create-key-store FILE=server +make create-trust-store +``` + +Will generate CA certificate and signed client and server certificates. + +More "low-level" usage: + +```shell +make generate-ca-certificate +make generate-private-key FILE=client +make sign FILE=client +``` + +# Connecting to a server + +First generate *client* and *server* certificates. Then start a server with it's cert and make ca.crt a trusted certification authority. + +After that you can: + +```shell +./connect.sh client localhost:8600 < file_with_a_data_to_be_sent.dat +``` diff --git a/tools/ssl/gen-certs.sh b/tools/ssl/gen-certs.sh new file mode 100755 index 00000000..bf28ca02 --- /dev/null +++ b/tools/ssl/gen-certs.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# ============LICENSE_START======================================================= +# csit-dcaegen2-collectors-hv-ves +# ================================================================================ +# Copyright (C) 2018-2019 NOKIA +# ================================================================================ +# 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========================================================= + +set -eu -o pipefail -o xtrace + +STORE_PASS=onaponap +CN_PREFIX=dcaegen2-hvves +DNAME_PREFIX="C=PL,ST=DL,L=Wroclaw,O=Nokia,OU=MANO,CN=${CN_PREFIX}" +TRUST=trust + +store_opts="-storetype PKCS12 -storepass ${STORE_PASS} -noprompt" + +function gen_key() { + local key_name="$1" + local ca="$2" + local keystore="-keystore ${key_name}.p12 ${store_opts}" + keytool -genkey -alias ${key_name} \ + ${keystore} \ + -keyalg RSA \ + -validity 730 \ + -keysize 2048 \ + -dname "${DNAME_PREFIX}-${key_name}" + keytool -import -trustcacerts -alias ${ca} -file ${ca}.crt ${keystore} + + keytool -certreq -alias ${key_name} -keyalg RSA ${keystore} | \ + keytool -alias ${ca} -gencert -ext "san=dns:${CN_PREFIX}-${ca}" ${store_opts} -keystore ${ca}.p12 | \ + keytool -alias ${key_name} -importcert ${keystore} + + printf ${STORE_PASS} > ${key_name}.pass +} + + +function gen_ca() { + local ca="$1" + keytool -genkeypair ${store_opts} -alias ${ca} -dname "${DNAME_PREFIX}-${ca}" -keystore ${ca}.p12 + keytool -export -alias ${ca} -file ${ca}.crt ${store_opts} -keystore ${ca}.p12 +} + +function gen_truststore() { + local trusted_ca="$1" + keytool -import -trustcacerts -alias ca -file ${trusted_ca}.crt ${store_opts} -keystore ${TRUST}.p12 + printf ${STORE_PASS} > ${TRUST}.pass +} + +function clean() { + rm -f *.crt *.p12 *.pass +} + +if [[ $# -eq 0 ]]; then + gen_ca ca + gen_ca untrustedca + gen_truststore ca + gen_key client ca + gen_key server ca + gen_key untrustedclient untrustedca +elif [[ $1 == "clean" ]]; then + clean +else + echo "usage: $0 [clean]" + exit 1 +fi + |