diff --git a/.gitignore b/.gitignore index 66fd13c..cba6286 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ # Dependency directories (remove the comment below to include it) # vendor/ +*.log \ No newline at end of file diff --git a/README.md b/README.md index 830e9a1..155d74c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ # flotta-scale-tests The purpose of this project is to test the scalability and performance of [project-flotta](https://github.com/project-flotta/flotta-operator) using [JMeter](https://jmeter.apache.org). +## Install OCP SNO cluster +Clone https://github.com/openshift/assisted-test-infra and see https://github.com/openshift/assisted-test-infra#single-node---bootstrap-in-place-with-assisted-service for instructions +Set the KUBECONFIG variable with the path where the kube config file is located. + +Clone https://github.com/project-flotta/flotta-operator then generate and push docker image to your repository. +Run `TARGET=ocp IMG= make ` to deploy flotta operator to your cluster. + +Add entry to your /etc/hosts file with the IP address of the cluster (`oc get nodes -o wide`) with name project-flotta.io + ## Running the test plan Use [./scripts/run_test_plan.sh](./scripts/run_test_plan.sh) to run the test plan. The script will create the required resources on the cluster for running the test. @@ -26,4 +35,4 @@ The [basic test plan](./test_plans/flotta_test_plan.jmx) runs the following scen * In Loop: * Sends heartbeats to the server * Get updates from the server - \ No newline at end of file + diff --git a/generate_devices_and_workload.sh b/generate_devices_and_workload.sh new file mode 100755 index 0000000..62c8a81 --- /dev/null +++ b/generate_devices_and_workload.sh @@ -0,0 +1,187 @@ +#!/bin/bash +NB_DEVICES=$1 +SCRIPT=$(readlink -f "$0") +export SCRIPT_DIR=$(dirname "$SCRIPT") +export CERTS_FOLDER=${SCRIPT_DIR}/certs +export REGISTRATION_FOLDER=${SCRIPT_DIR}/logs/registration +export ENROL_FOLDER=${SCRIPT_DIR}/logs/enrol +rm -rf ${SCRIPT_DIR}/logs $CERTS_FOLDER +mkdir -p $REGISTRATION_FOLDER +mkdir -p $ENROL_FOLDER +mkdir -p $CERTS_FOLDER +export HTTP_SERVER=127.0.0.1 +export HTTP_SERVER_PORT=8043 +for p in $(kubectl -n flotta-test get edgedevices --no-headers | awk '{print $1}'); do kubectl -n flotta-test patch edgedevices $p -p '{"metadata":{"finalizers":null}}' --type=merge >/dev/null; done + +kubectl delete namespace flotta-test +kubectl create namespace flotta-test + +BASE_SERIAL=$(uuidgen) +for i in $(seq 1 $NB_DEVICES); do + DEVICE_ID=$(uuidgen) + PAYLOAD='{ + "content": { + "target_namespace": "flotta-test", + "features": { + "hardware": { + "cpu": { + "architecture": "x86_64", + "flags": [], + "model_name": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz" + }, + "hostname": "fedora", + "system_vendor": { + "manufacturer": "LENOVO", + "product_name": "azerty'$(expr $i % 2)'", + "serial_number": "'${BASE_SERIAL}_${i}'" + } + }, + "os_image_id": "unknown" + + } + }, + "directive": "enrolment", + "message_id": "${__UUID()}", + "sent": "2021-11-21T14:45:25.271+02:00", + "type": "data", + "version": 1 + + }' + DEVICE_ID=default CERTS_FOLDER=$CERTS_FOLDER sh scripts/generate_certs.sh >> $CERTS_FOLDER/logs.out 2>> $CERTS_FOLDER/logs.err + + DEVICE_ID=$DEVICE_ID PAYLOAD=$PAYLOAD sh scripts/enrol_device.sh >> $ENROL_FOLDER/logs.out 2>> $ENROL_FOLDER/logs.err + + + ## Registration + + PAYLOAD='{ + "content": { + "hardware": { + "cpu": { + "architecture": "x86_64", + "flags": [], + "model_name": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz" + }, + "hostname": "fedora", + "system_vendor": { + "manufacturer": "LENOVO", + "product_name": "azerty'$(expr $i % 2)'", + "serial_number": "'${BASE_SERIAL}_${i}'" + } + }, + "os_image_id": "unknown" + }, + "directive": "registration", + "message_id": "'$(uuidgen)'", + "sent": "2021-11-21T14:45:25.271+02:00", + "type": "data", + "version": 1 + + }' + + DEVICE_ID=$DEVICE_ID PAYLOAD=$PAYLOAD sh scripts/register_device.sh >> $REGISTRATION_FOLDER/logs.out 2>> $REGISTRATION_FOLDER/logs.err +done +SELECTOR_ALL="device.system-manufacturer: lenovo" +SELECTOR_ODD="device.system-product: azerty1" +SELECTOR_PAIR="device.system-product: azerty0" +SELECTOR_UNIQUE="device.system-serial: ${BASE_SERIAL}_1" + +# A pretend Python dictionary with bash 3 +WORKLOADS_SELECTOR=( "all:$SELECTOR_ALL" + "odd:$SELECTOR_ODD" + "pair:$SELECTOR_PAIR" + "unique:$SELECTOR_UNIQUE" ) + +for WORKLOAD_SELECTOR in "${WORKLOADS_SELECTOR[@]}" ; do + SELECTOR_NAME=${WORKLOAD_SELECTOR%%:*} + SELECTOR=${WORKLOAD_SELECTOR#*:} + printf "%s apply %s.\n" "$SELECTOR_NAME" "$SELECTOR" + WORKLOAD=" +apiVersion: management.project-flotta.io/v1alpha1 +kind: EdgeWorkload +metadata: + name: edgeworkload-sample-${SELECTOR_NAME} + namespace: flotta-test +spec: + deviceSelector: + matchLabels: + $SELECTOR + data: + paths: + - source: . + target: nginx + type: pod + pod: + spec: + containers: + - name: nginx + image: docker.io/nginx:1.14.2 + ports: + - containerPort: 80 + hostPort: 9090 +" + echo "$WORKLOAD" | kubectl apply -f - > /dev/null +done +echo "==================" +if [[ $NB_DEVICES -lt 2 ]]; then + echo "!!! Warn: Amount of device the create is $NB_DEVICES which is lower than 2, tests checking the expected amount of devices matching a workload will fail" +fi +echo -n "Checking if workloads are correctly depoloyed on devices..." + +NB_ODD_EXPTECTED=$(expr $NB_DEVICES / 2) +NB_PAIR_EXPTECTED=$(expr $NB_DEVICES - $NB_ODD_EXPTECTED) +NB_ALL_DEVICES=0 +NB_ODD_DEVICES=0 +NB_PAIR_DEVICES=0 +NB_UNIQUE_DEVICES=0 + +for DEVICE in $(kubectl -n flotta-test get edgedevice --no-headers | awk '{print $1}') +do + kubectl -n flotta-test get edgedevices $DEVICE -o yaml | grep "name: edgeworkload-sample-all" > /dev/null + if [[ $? -ne 0 ]]; then + echo $'\n'"Error: $DEVICE should have workload edgeworkload-sample-all but has not" + else + let "NB_ALL_DEVICES++" + fi +done +if [[ $NB_ALL_DEVICES -ne $NB_DEVICES ]]; then + echo $'\n'"Error: edgeworkload-sample-all is not apply to all devices created: should be $NB_DEVICES get $NB_ALL_DEVICES" +fi + +for ODD_DEVICE in $(kubectl -n flotta-test get edgedevice -l device.system-product=azerty1 --no-headers | awk '{print $1}'); do + kubectl -n flotta-test get edgedevices $ODD_DEVICE -o yaml | grep "name: edgeworkload-sample-odd" > /dev/null + if [[ $? -ne 0 ]]; then + echo $'\n'"Error: $ODD_DEVICE should have workload edgeworkload-sample-odd but has not" + else + let "NB_ODD_DEVICES++" + fi +done +if [[ $NB_ODD_DEVICES -ne $NB_ODD_EXPTECTED ]]; then + echo $'\n'"Error: edgeworkload-sample-odd is not apply to all devices created: should be $NB_ODD_EXPTECTED get $NB_ODD_DEVICES" +fi + +for PAIR_DEVICE in $(kubectl -n flotta-test get edgedevice -l device.system-product=azerty0 --no-headers | awk '{print $1}'); do + kubectl -n flotta-test get edgedevices $PAIR_DEVICE -o yaml | grep "name: edgeworkload-sample-pair" > /dev/null + if [[ $? -ne 0 ]]; then + echo $'\n'"Error: $PAIR_DEVICE should have workload edgeworkload-sample-pair but has not" + else + let "NB_PAIR_DEVICES++" + fi +done +if [[ $NB_PAIR_DEVICES -ne $NB_PAIR_EXPTECTED ]]; then + echo $'\n'"Error: edgeworkload-sample-pair is not apply to all devices created: should be $NB_PAIR_EXPTECTED get $NB_PAIR_DEVICES" +fi + +for UNIQUE_DEVICE in $(kubectl -n flotta-test get edgedevice -l device.system-serial=${BASE_SERIAL}_1 --no-headers | awk '{print $1}'); do + kubectl -n flotta-test get edgedevices $UNIQUE_DEVICE -o yaml | grep "name: edgeworkload-sample-unique" > /dev/null + if [[ $? -ne 0 ]]; then + echo $'\n'"Error: $UNIQUE_DEVICE should have workload edgeworkload-sample-unique but has not" + else + let "NB_UNIQUE_DEVICES++" + fi +done +if [[ $NB_UNIQUE_DEVICES -ne 1 ]]; then + echo "Error: edgeworkload-sample-unique is not apply to all devices created: should be 1 get $NB_UNIQUE_DEVICES" +fi + +echo "Done" \ No newline at end of file diff --git a/samples/edgedevice-registration-simple.json.in b/samples/edgedevice-registration-simple.json.in new file mode 100644 index 0000000..43b3061 --- /dev/null +++ b/samples/edgedevice-registration-simple.json.in @@ -0,0 +1,24 @@ +{ + "content": { + "certificate_request": "$CERTIFICATE_REQUEST", + "hardware": { + "cpu": { + "architecture": "x86_64", + "flags": [], + "model_name": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz" + }, + "hostname": "$HOSTNAME", + "system_vendor": { + "manufacturer": "LENOVO", + "product_name": "${PRODUCT_NAME}", + "serial_number": "${SERIAL_NAME}" + } + }, + "os_image_id": "unknown" + }, + "directive": "registration", + "message_id": "$UUID", + "sent": "2021-11-21T14:45:25.271+02:00", + "type": "data", + "version": 1 +} diff --git a/samples/edgedeployment.json.in b/samples/edgeworkload.json.in similarity index 97% rename from samples/edgedeployment.json.in rename to samples/edgeworkload.json.in index 19c9af8..ae7903a 100644 --- a/samples/edgedeployment.json.in +++ b/samples/edgeworkload.json.in @@ -1,6 +1,6 @@ { "apiVersion": "management.project-flotta.io/v1alpha1", - "kind": "EdgeDeployment", + "kind": "EdgeWorkload", "name": "${DEPLOYMENT_NAME}-${DEPLOYMENT_SUFFIX}", "namespace": "${NAMESPACE}", }, diff --git a/scripts/create_output_streams.sh b/scripts/create_output_streams.sh new file mode 100755 index 0000000..4d33b8c --- /dev/null +++ b/scripts/create_output_streams.sh @@ -0,0 +1,11 @@ +#!/bin/bash +mkdir -p ${REGISTRATION_FOLDER} +mkdir -p ${GET_UPDATES_FOLDER} +mkdir -p ${HEARTBEAT_FOLDER} + +touch ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.out +touch ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.err +touch ${GET_UPDATES_FOLDER}/${DEVICE_ID}_get_updates.err +touch ${GET_UPDATES_FOLDER}/${DEVICE_ID}_get_updates.out +touch ${HEARTBEAT_FOLDER}/${DEVICE_ID}_heartbeat.out +touch ${HEARTBEAT_FOLDER}/${DEVICE_ID}_heartbeat.err \ No newline at end of file diff --git a/scripts/enrol_device.sh b/scripts/enrol_device.sh new file mode 100644 index 0000000..62bb44d --- /dev/null +++ b/scripts/enrol_device.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +echo "${PAYLOAD}" | envsubst > ${ENROL_FOLDER}/${DEVICE_ID}_enrol_payload.json + +#Verify! +cat ${ENROL_FOLDER}/${DEVICE_ID}_enrol_payload.json | jq . + +if [ $? -ne 0 ]; then + echo "Error when checking ${ENROL_FOLDER}/${DEVICE_ID}_enrol_payload.json" + exit -1 +fi +echo "curl \ + --cacert ${CERTS_FOLDER}/default_ca.pem \\ + --cert ${CERTS_FOLDER}/default_cert.pem \\ + --key ${CERTS_FOLDER}/default_key.pem -v \\ + -d @${ENROL_FOLDER}/${DEVICE_ID}_enrol_payload.json \\ + -X POST \\ + -H \"Content-Type: application/json\" \ + -i \\ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT}/api/flotta-management/v1/data/${DEVICE_ID}/out > ${ENROL_FOLDER}/${DEVICE_ID}_enrol_response.json" + +curl \ + --cacert ${CERTS_FOLDER}/default_ca.pem \ + --cert ${CERTS_FOLDER}/default_cert.pem \ + --key ${CERTS_FOLDER}/default_key.pem -v \ + -d @${ENROL_FOLDER}/${DEVICE_ID}_enrol_payload.json \ + -X POST \ + -H "Content-Type: application/json" \ + -i \ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT}/api/flotta-management/v1/data/${DEVICE_ID}/out > ${ENROL_FOLDER}/${DEVICE_ID}_enrol_response.json + +if [ $? -ne 0 ]; then + echo "Error when sending enrol request, see ${ENROL_FOLDER}/${DEVICE_ID}_enrol.out" + exit -1 +fi + +cat ${ENROL_FOLDER}/${DEVICE_ID}_enrol_response.json | grep 208 > /dev/null +if [ $? -eq 0 ]; then + echo "Device ${DEVICE_ID} already enroled" + exit -1 +else + cat ${ENROL_FOLDER}/${DEVICE_ID}_enrol_response.json | grep 200 > /dev/null + if [ $? -ne 0 ]; then + echo "Error when sending enrol request, see ${ENROL_FOLDER}/${DEVICE_ID}_enrol_response.json" + exit -1 + fi +fi + +exit 0 \ No newline at end of file diff --git a/scripts/generate_certs.sh b/scripts/generate_certs.sh new file mode 100755 index 0000000..3ad62a7 --- /dev/null +++ b/scripts/generate_certs.sh @@ -0,0 +1,13 @@ +#!/bin/bash +if [[ -z "${CERTS_FOLDER}" ]]; then + export CERTS_FOLDER="${test_dir}/certs" + echo "CERTS_FOLDER no defined, setting it to ${CERTS_FOLDER}" +fi +mkdir -p $CERTS_FOLDER + +# make get-certs +kubectl -n flotta get secrets flotta-ca --template="{{index .data \"ca.crt\" | base64decode}}" > ${CERTS_FOLDER}/${DEVICE_ID}_ca.pem +export REG_SECRET_NAME=$(kubectl get secrets -n flotta -l reg-client-ca=true --sort-by=.metadata.creationTimestamp | tail -1 | awk '{print $1}') +kubectl -n flotta get secret ${REG_SECRET_NAME} --template="{{index .data \"client.crt\" | base64decode}}" > ${CERTS_FOLDER}/${DEVICE_ID}_cert.pem +kubectl -n flotta get secret ${REG_SECRET_NAME} --template="{{index .data \"client.key\" | base64decode}}" > ${CERTS_FOLDER}/${DEVICE_ID}_key.pem +# make get-certs END diff --git a/scripts/get_device_update.sh b/scripts/get_device_update.sh new file mode 100755 index 0000000..3a1bb01 --- /dev/null +++ b/scripts/get_device_update.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +echo "curl -XGET \\ + --cacert ${CERTS_FOLDER}/default_ca.pem \\ + --cert ${CERTS_FOLDER}/${DEVICE_ID}.pem \\ + --key ${CERTS_FOLDER}/${DEVICE_ID}.key -v \\ + -H \"Content-Type: application/json\" \\ + -H \"Cache-Control: no-cache\" \\ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT}/${REQUEST_PATH}" + +curl -XGET \ + --cacert ${CERTS_FOLDER}/default_ca.pem \ + --cert ${CERTS_FOLDER}/${DEVICE_ID}.pem \ + --key ${CERTS_FOLDER}/${DEVICE_ID}.key -v \ + -H "Content-Type: application/json" \ + -H "Cache-Control: no-cache" \ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT}/${REQUEST_PATH} + +if [ $? -ne 0 ]; then + echo "Error getting device updates" + exit -1 +fi; + +exit 0 diff --git a/scripts/register_device.sh b/scripts/register_device.sh new file mode 100755 index 0000000..109ab01 --- /dev/null +++ b/scripts/register_device.sh @@ -0,0 +1,51 @@ +#!/bin/bash +openssl ecparam -name prime256v1 -genkey -noout -out ${CERTS_FOLDER}/${DEVICE_ID}.key +openssl req -new -subj '/CN=${DEVICE_ID}' -key ${CERTS_FOLDER}/${DEVICE_ID}.key -out ${CERTS_FOLDER}/${DEVICE_ID}.csr +export CERTIFICATE_REQUEST=$(cat ${CERTS_FOLDER}/${DEVICE_ID}.csr | sed 's/$/\\n/' | tr -d '\n') +UUID=$(uuidgen) + +echo "${PAYLOAD}" | sed -e 's/"content": {/"content": {\n "certificate_request": "$CERTIFICATE_REQUEST",/g' | envsubst > ${REGISTRATION_FOLDER}/${DEVICE_ID}_payload.json + +#Verify! +cat ${REGISTRATION_FOLDER}/${DEVICE_ID}_payload.json | jq . + +if [ $? -ne 0 ]; then + echo "Error when checking ${REGISTRATION_FOLDER}/${DEVICE_ID}_payload.json" + exit -1 +fi +echo "curl \ + --cacert ${CERTS_FOLDER}/default_ca.pem \\ + --cert ${CERTS_FOLDER}/default_cert.pem \\ + --key ${CERTS_FOLDER}/default_key.pem -v \\ + -d @${REGISTRATION_FOLDER}/${DEVICE_ID}_payload.json \\ + -X POST \\ + -H \"Content-Type: application/json\" \ + -o ${REGISTRATION_FOLDER}/${DEVICE_ID}_response.json \\ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT}/api/flotta-management/v1/data/${DEVICE_ID}/out" + +curl \ + --cacert ${CERTS_FOLDER}/default_ca.pem \ + --cert ${CERTS_FOLDER}/default_cert.pem \ + --key ${CERTS_FOLDER}/default_key.pem -v \ + -d @${REGISTRATION_FOLDER}/${DEVICE_ID}_payload.json \ + -X POST \ + -H "Content-Type: application/json" \ + -o ${REGISTRATION_FOLDER}/${DEVICE_ID}_response.json \ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT}/api/flotta-management/v1/data/${DEVICE_ID}/out +if [ $? -ne 0 ]; then + echo "Error when sending registration request, see ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.out" + exit -1 +fi + +cat ${REGISTRATION_FOLDER}/${DEVICE_ID}_response.json | jq '.content.certificate' | sed -e 's/\\n/\n/g' | sed -e 's/"//g' > ${CERTS_FOLDER}/${DEVICE_ID}.pem + + +#openssl x509 -in ${CERTS_FOLDER}/${DEVICE_ID}.pem --text + +if [ $? -ne 0 ]; then + echo "Error when extracting ${REGISTRATION_FOLDER}/${DEVICE_ID}_response.json to ${CERTS_FOLDER}/${DEVICE_ID}.pem" + exit -1 +fi + +exit 0 + diff --git a/scripts/request_operator.sh b/scripts/request_operator.sh new file mode 100755 index 0000000..e264c4c --- /dev/null +++ b/scripts/request_operator.sh @@ -0,0 +1,26 @@ +#!/bin/bash +#echo "${POST_BODY}" | envsubst > ${ENROL_FOLDER}/${DEVICE_ID}_enrol_payload.json + + +echo "curl -XPOST \\ + --cacert ${CERTS_FOLDER}/default_ca.pem \\ + --cert ${CERTS_FOLDER}/${DEVICE_ID}.pem \\ + --key ${CERTS_FOLDER}/${DEVICE_ID}.key -v \\ + -H \"Content-Type: application/json\" \\ + --data \"${POST_BODY}\" \\ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT}/${REQUEST_PATH} | grep \"200 OK\"" + +curl -XPOST \ + --cacert ${CERTS_FOLDER}/default_ca.pem \ + --cert ${CERTS_FOLDER}/${DEVICE_ID}.pem \ + --key ${CERTS_FOLDER}/${DEVICE_ID}.key -v \ + -H "Content-Type: application/json" \ + --data "${POST_BODY}" -i \ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT}/${REQUEST_PATH} | grep "200 OK" + +if [ $? -ne 0 ]; then + echo "Error posting device" + exit -1 +fi; + +exit 0 diff --git a/scripts/run_test_plan.sh b/scripts/run_test_plan.sh index 59ebc1d..b28b198 100755 --- a/scripts/run_test_plan.sh +++ b/scripts/run_test_plan.sh @@ -20,7 +20,7 @@ OPTIONS: -m Run must-gather to collect logs (default: false) -n Test run ID -o Edge deployment updates concurrency (default: 5) - -p Total of edge deployments per device + -p Total of edge workloads per device -q Number of namespaces (default: 10). Requires hacked version of flotta-operator and specific test plan. -r Ramp-up time in seconds to create all edge devices -s Address of OCP API server @@ -57,7 +57,7 @@ while getopts "c:d:e:f:g:h:i:j:k:l:m:n:o:p:q:r:s:t:u:v" option; do l) LOG_LEVEL=${OPTARG};; m) MUST_GATHER=${OPTARG};; n) TEST_ID=${OPTARG};; - o) EDGEDEPLOYMENT_CONCURRENCY=${OPTARG};; + o) EDGEWORKLOAD_CONCURRENCY=${OPTARG};; p) EDGE_DEPLOYMENTS_PER_DEVICE=${OPTARG};; q) NAMESPACES_COUNT=${OPTARG};; r) RAMP_UP_TIME=${OPTARG};; @@ -86,9 +86,9 @@ if [[ -z $REPLICAS ]]; then echo "INFO: Number of replicas not specified. Using default value: $REPLICAS" fi -if [[ -z $EDGEDEPLOYMENT_CONCURRENCY ]]; then - EDGEDEPLOYMENT_CONCURRENCY=5 - echo "INFO: Edge deployment concurrency not specified. Using default value: $EDGEDEPLOYMENT_CONCURRENCY" +if [[ -z $EDGEWORKLOAD_CONCURRENCY ]]; then + EDGEWORKLOAD_CONCURRENCY=5 + echo "INFO: Edge deployment concurrency not specified. Using default value: $EDGEWORKLOAD_CONCURRENCY" fi if [[ -z $TEST_ID ]]; then @@ -104,7 +104,7 @@ if [[ -z $EDGE_DEVICES_COUNT ]]; then fi if [[ -z $EDGE_DEPLOYMENTS_PER_DEVICE ]]; then - echo "ERROR: Edge deployments per device is required" + echo "ERROR: edge workloads per device is required" usage exit 1 fi @@ -160,8 +160,13 @@ if [[ -z $HTTP_SERVER ]]; then fi if [[ -z $HTTP_SERVER_PORT ]]; then - echo "HTTP port is not specified. Using default value: 80" - HTTP_SERVER_PORT=80 + echo "HTTP port is not specified. Using default value: 3143" + HTTP_SERVER_PORT=3143 +fi + +if [[ $HTTP_SERVER_PORT -lt 30000 ]] || [[ $HTTP_SERVER_PORT -gt 32767 ]]; then + echo "HTTP_SERVER_PORT shall be between 30000 - 32767 to allow NodePort service, given: $HTTP_SERVER_PORT" + exit -1 fi if [[ -z $JMETER_HOME ]]; then @@ -189,7 +194,7 @@ if [[ -n $VERBOSE ]]; then set -xv fi -test_dir="./test-run-${TEST_ID}" +export test_dir="$(pwd)/test-run-${TEST_ID}" if [ -d "$test_dir" ]; then echo "ERROR: Test directory $test_dir already exists" exit 1 @@ -209,7 +214,7 @@ echo "Target folder: $test_dir" echo "Test ID: ${TEST_ID}" echo "Test plan: ${TEST_PLAN}" echo "Total of edge devices: ${EDGE_DEVICES_COUNT}" -echo "Edge deployments per device: ${EDGE_DEPLOYMENTS_PER_DEVICE}" +echo "edge workloads per device: ${EDGE_DEPLOYMENTS_PER_DEVICE}" echo "Ramp-up time: ${RAMP_UP_TIME}" echo "Iterations: ${ITERATIONS}" echo "OCP API server: ${OCP_API_SERVER}" @@ -223,13 +228,16 @@ echo "----------------------------------------------------" cp $TEST_PLAN $test_dir/ edgedevices=$(kubectl get edgedevices --all-namespaces | wc -l) -edgedeploy=$(kubectl get edgedeployments --all-namespaces | wc -l) -echo "Before test: There are $edgedevices edge devices and $edgedeploy edge deployments" >> $test_dir/summary.txt +edgeworkload=$(kubectl get edgeworkloads --all-namespaces | wc -l) +echo "Before test: There are $edgedevices edge devices and $edgeworkload edge workloads" >> $test_dir/summary.txt } run_test() { -echo "INFO: Running test" +SCRIPT=$(readlink -f "$0") +SCRIPT_DIR=$(dirname "$SCRIPT") + +echo "INFO: Running test located in ${SCRIPT_DIR}" JVM_ARGS="-Xms4g -Xmx64g -Xss250k -XX:MaxMetaspaceSize=1g" $JMETER_HOME/bin/jmeter.sh -n -l $test_dir/results.csv \ -f -e -o $test_dir/results/ -t $TEST_PLAN \ -JEDGE_DEVICES_COUNT=$EDGE_DEVICES_COUNT \ @@ -240,6 +248,13 @@ JVM_ARGS="-Xms4g -Xmx64g -Xss250k -XX:MaxMetaspaceSize=1g" $JMETER_HOME/bin/jmet -JK8S_BEARER_TOKEN=$K8S_BEARER_TOKEN \ -JHTTP_SERVER=$HTTP_SERVER \ -JHTTP_SERVER_PORT=$HTTP_SERVER_PORT \ + -JTEST_DIR=$test_dir \ + -JSCRIPTS_DIR=$SCRIPT_DIR \ + -JCERTS_FOLDER=$CERTS_FOLDER \ + -JREGISTRATION_FOLDER="${SCRIPT_DIR}/test-run-${TEST_ID}/logs/registration" \ + -JGET_UPDATES_FOLDER="${SCRIPT_DIR}/test-run-${TEST_ID}/logs/get_updates" \ + -JHEARTBEAT_FOLDER="${SCRIPT_DIR}/test-run-${TEST_ID}/logs/heartbeat" \ + -JENROL_FOLDER="${logs_dir}/enrol" \ -JNAMESPACES_COUNT=$NAMESPACES_COUNT|& tee -a $test_dir/summary.txt } @@ -253,13 +268,13 @@ echo "After test:" >> $test_dir/summary.txt if [[ -z $RUN_WITHOUT_NAMESPACES ]]; then edgedevices=$(kubectl get edgedevices --all-namespaces | wc -l) - edgedeploy=$(kubectl get edgedeployments --all-namespaces | wc -l) - echo "There are $edgedevices edge devices and $edgedeploy edge deployments" >> $test_dir/summary.txt + edgeworkload=$(kubectl get edgeworkloads --all-namespaces | wc -l) + echo "There are $edgedevices edge devices and $edgeworkload edge workloads" >> $test_dir/summary.txt else for i in $(seq 1 $NAMESPACES_COUNT); do edgedevices=$(kubectl get edgedevices -n $i | wc -l) - edgedeploy=$(kubectl get edgedeployments -n $i | wc -l) - echo "There are $edgedevices edge devices and $edgedeploy edge deployments in namespace $i" >> $test_dir/summary.txt + edgeworkload=$(kubectl get edgeworkloads -n $i | wc -l) + echo "There are $edgedevices edge devices and $edgeworkload edge workloads in namespace $i" >> $test_dir/summary.txt done fi @@ -297,7 +312,7 @@ kubectl patch cm -n flotta flotta-operator-manager-config --type merge --patch ' "LOG_LEVEL": "'$LOG_LEVEL'", "OBC_AUTO_CREATE": "false", "MAX_CONCURRENT_RECONCILES": "'$MAX_CONCURRENT_RECONCILES'", - "EDGEDEPLOYMENT_CONCURRENCY": "'$EDGEDEPLOYMENT_CONCURRENCY'", + "EDGEWORKLOAD_CONCURRENCY": "'$EDGEWORKLOAD_CONCURRENCY'", "NAMESPACES_COUNT": "'$NAMESPACES_COUNT'"} }' @@ -388,15 +403,24 @@ if [[ -n $EXPOSE_PPROF ]]; then }' fi +kubectl patch service flotta-operator-controller-manager -n flotta --type='json' -p "[{\"op\":\"replace\",\"path\":\"/spec/type\",\"value\":\"NodePort\"},{\"op\":\"replace\",\"path\":\"/spec/ports/0/nodePort\",\"value\":${HTTP_SERVER_PORT}}]" + kubectl scale --replicas=$REPLICAS deployment flotta-operator-controller-manager -n flotta kubectl wait --for=condition=available -n flotta deployment.apps/flotta-operator-controller-manager count=0 - +export CERTS_FOLDER="${test_dir}/certs" +DEVICE_ID='default' +DEVICE_ID=$DEVICE_ID sh generate_certs.sh echo "Waiting for HTTP server to be ready at $HTTP_SERVER" until [[ count -gt 100 ]] do - curl -m 5 -s -i "$HTTP_SERVER":"$HTTP_SERVER_PORT" | grep 404 > /dev/null + curl \ + --cacert ${CERTS_FOLDER}/${DEVICE_ID}_ca.pem \ + --cert ${CERTS_FOLDER}/${DEVICE_ID}_cert.pem \ + --key ${CERTS_FOLDER}/${DEVICE_ID}_key.pem -v \ + -m 5 -s -i \ + https://${HTTP_SERVER}:${HTTP_SERVER_PORT} | grep 404 > /dev/null if [ "$?" == "1" ]; then echo -n "." count=$((count+1)) @@ -422,8 +446,11 @@ kubectl top pods -n flotta --use-protocol-buffers } >> $test_dir/summary.txt } + + parse_args "$@" log_run_details +sh setup.sh patch_flotta_operator log_pods_details run_test diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..b8ce819 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,22 @@ +sysctl -w net.core.somaxconn=50000 +sysctl -w net.core.netdev_max_backlog=50000 +sysctl -w net.ipv4.tcp_max_syn_backlog=50000 +sysctl -w net.ipv4.ip_local_port_range="15000 65000" +sysctl -w net.ipv4.tcp_fin_timeout=10 +sysctl -w vm.max_map_count=999999 +sysctl -w kernel.threads-max=4113992 + +if [[ -z $(grep "* soft nofile 999999" "/etc/security/limits.conf") ]]; then + cat "* soft nofile 999999" >> /etc/security/limits.conf +fi + +if [[ -z $(grep "* hard nofile 999999" "/etc/security/limits.conf") ]]; then + cat "* hard nofile 999999" >> /etc/security/limits.conf +fi + + +ifconfig br-ex txqueuelen 5000 +ifconfig cni-podman0 txqueuelen 5000 +ifconfig ens3 txqueuelen 5000 +ifconfig ens4 txqueuelen 5000 +ifconfig ovn-k8s-mp0 txqueuelen 5000 diff --git a/scripts/teardown.sh b/scripts/teardown.sh index f10c7a6..bca618f 100755 --- a/scripts/teardown.sh +++ b/scripts/teardown.sh @@ -5,15 +5,15 @@ if [ $# -eq 1 ]; then do NS=$((i - 1)) kubectl get edgedevices -n $NS --no-headers | awk -v ns=$NS '{print $1 " --namespace=" ns}' | xargs -P 20 -n 2 kubectl patch edgedevice -p '{"metadata":{"finalizers":null}}' --type=merge - kubectl get edgedeployment -n $NS --no-headers | awk -v ns=$NS '{print $1 " --namespace=" ns}' | xargs -P 20 -n 2 kubectl patch edgedeployment -p '{"metadata":{"finalizers":null}}' --type=merge + kubectl get edgeworkload -n $NS --no-headers | awk -v ns=$NS '{print $1 " --namespace=" ns}' | xargs -P 20 -n 2 kubectl patch edgeworkload -p '{"metadata":{"finalizers":null}}' --type=merge kubectl delete edgedevice --all -n $NS - kubectl delete edgedeployments --all -n $NS + kubectl delete edgeworkloads --all -n $NS kubectl delete ns $NS done exit 0 fi kubectl get edgedevices --all-namespaces --no-headers | awk '{print $2 " --namespace=" $1}' | xargs -P 20 -n 2 kubectl patch edgedevice -p '{"metadata":{"finalizers":null}}' --type=merge -kubectl get edgedeployment --all-namespaces --no-headers | awk '{print $2 " --namespace=" $1}' | xargs -P 20 -n 2 kubectl patch edgedeployment -p '{"metadata":{"finalizers":null}}' --type=merge +kubectl get edgeworkload --all-namespaces --no-headers | awk '{print $2 " --namespace=" $1}' | xargs -P 20 -n 2 kubectl patch edgeworkload -p '{"metadata":{"finalizers":null}}' --type=merge kubectl delete edgedevice --all --all-namespaces -kubectl delete edgedeployments --all --all-namespaces +kubectl delete edgeworkloads --all --all-namespaces diff --git a/test_plans/flotta_test_plan.jmx b/test_plans/flotta_test_plan.jmx index 64b2f0a..2f6a175 100644 --- a/test_plans/flotta_test_plan.jmx +++ b/test_plans/flotta_test_plan.jmx @@ -1,5 +1,5 @@ - + @@ -10,7 +10,7 @@ HTTP_SERVER - localhost:8888 + localhost:8083 = @@ -28,17 +28,31 @@ LABEL_VALUE NAMESPACE DEPLOYMENTS_PER_DEVICE + TEST_DIR + SCRIPTS_DIR + REGISTRATION_FOLDER + GET_UPDATES_FOLDER + HEARTBEAT_FOLDER + CERTS_FOLDER + ENROL_FOLDER - - ${__P(HTTP_SERVER,flotta-operator-controller-manager-flotta-operator-system.apps.mycluster.redhat.com)} + + ${__P(HTTP_SERVER,flotta-operator-controller-manager-flotta-operator-system.apps.mycluster.redhat.com)} ${__P(HTTP_SERVER_PORT,80)} ${__P(OCP_API_SERVER,api.mycluster.redhat.com)} - ${__P(OCP_API_PORT,6443)} + ${__P(OCP_API_PORT,6443)} region emea default ${__P(DEPLOYMENTS_PER_DEVICE,5)} + ${__P(TEST_DIR,test_dir_delete_me)} + ${__P(SCRIPTS_DIR,.)} + ${__P(REGISTRATION_FOLDER,./registration)} + ${__P(GET_UPDATES_FOLDER,./get_updates)} + ${__P(HEARTBEAT_FOLDER,./heartbeat)} + ${__P(CERTS_FOLDER,./certs)} + ${__P(ENROL_FOLDER,./enrol)} false @@ -58,7 +72,7 @@ true - + @@ -83,7 +97,248 @@ The device ID to be used for the entire scenario of a specific device and additional device properties - + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/create_output_streams.sh + = + + + + + + + REGISTRATION_FOLDER + ${REGISTRATION_FOLDER} + = + + + GET_UPDATES_FOLDER + ${GET_UPDATES_FOLDER} + = + + + HEARTBEAT_FOLDER + ${HEARTBEAT_FOLDER} + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + ENROL_FOLDER + ${ENROL_FOLDER} + = + + + + + + + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/enrol_device.sh + = + + + + + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + PRODUCT_NAME + ${PRODUCT_NAME} + = + + + SERIAL_NAME + ${SERIAL_NAME} + = + + + PAYLOAD + { "content": { "target_namespace": "flotta", "features": { "hardware": { "cpu": { "architecture": "x86_64", "flags": [], "model_name": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz" }, "hostname": "fedora", "system_vendor": { "manufacturer": "LENOVO", "product_name": "${PRODUCT_NAME}", "serial_number": "${SERIAL_NAME}" } }, "os_image_id": "unknown" } }, "directive": "enrolment", "message_id": "${__UUID()}", "sent": "2021-11-21T14:45:25.271+02:00", "type": "data", "version": 1 } + = + + + ENROL_FOLDER + ${ENROL_FOLDER} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${ENROL_FOLDER}/${DEVICE_ID}_register.out + ${ENROL_FOLDER}/${DEVICE_ID}_register.err + + + + true + + + + false + { + "spec": { + "approved": true + } +} + = + + + + ${OCP_API_SERVER} + ${OCP_API_PORT} + https + UTF-8 + /apis/management.project-flotta.io/v1alpha1/namespaces/default/edgedevicesignedrequest/${DEVICE_ID} + PATCH + true + false + true + false + + HttpClient4 + + + Approve device enrolment + + + + + + Content-Type + application/merge-patch+json + + + Cache-Control + no-cache + + + Authorization + Bearer ${__P(K8S_BEARER_TOKEN)} + + + + + + false + true + true + false + + + + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/register_device.sh + = + + + + + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + PRODUCT_NAME + ${PRODUCT_NAME} + = + + + SERIAL_NAME + ${SERIAL_NAME} + = + + + PAYLOAD + { "content": { "hardware": { "cpu": { "architecture": "x86_64", "flags": [], "model_name": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz" }, "hostname": "${HOSTNAME}", "system_vendor": { "manufacturer": "LENOVO", "product_name": "${PRODUCT_NAME}", "serial_number": "${SERIAL_NAME}" } }, "os_image_id": "unknown" }, "directive": "registration", "message_id": "${__UUID()}", "sent": "2021-11-21T14:45:25.271+02:00", "type": "data", "version": 1 } + = + + + REGISTRATION_FOLDER + ${REGISTRATION_FOLDER} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.out + ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.err + + + true @@ -218,9 +473,9 @@ - + - + true ${DEPLOYMENTS_PER_DEVICE} @@ -235,7 +490,7 @@ true - + true @@ -243,7 +498,7 @@ false { "apiVersion": "management.project-flotta.io/v1alpha1", - "kind": "EdgeDeployment", + "kind": "EdgeWorkload", "metadata": { "name": "${DEVICE_ID}-${NameSuffix}", "namespace": "default" @@ -290,7 +545,7 @@ ${OCP_API_PORT} https UTF-8 - /apis/management.project-flotta.io/v1alpha1/namespaces/${NAMESPACE}/edgedeployments + /apis/management.project-flotta.io/v1alpha1/namespaces/${NAMESPACE}/edgeworkloads POST true false @@ -300,7 +555,7 @@ HttpClient4 - Create Edge Deployment with labels matching for device + Create Edge Workload with labels matching for device @@ -328,8 +583,8 @@ - - Add delays between edgedeployments creation of the same device + + Add delays between edgeworkloads creation of the same device 1000 @@ -340,7 +595,7 @@ 4 - + @@ -360,13 +615,122 @@ + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/get_device_update.sh + = + + + + + + + REQUEST_PATH + api/flotta-management/v1/data/${DEVICE_ID}/in + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${GET_UPDATES_FOLDER}/${DEVICE_ID}_get_updates.out + ${GET_UPDATES_FOLDER}/${DEVICE_ID}_get_updates.err + + Add delays between Get Updates requests 15000 - + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/request_operator.sh + = + + + + + + + REQUEST_PATH + api/flotta-management/v1/data/${DEVICE_ID}/out + = + + + POST_BODY + { "content": { "events": [ { "message": "error starting container f8433cc4b0c963ce95625ab3b1811382f852432f61a2d087422210e9d34bc2bc: cannot listen on the TCP port: listen tcp4 :11000: bind: address already in use,error starting container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50: a dependency of container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50 failed to start: container state improper", "reason": "Failed", "type": "warn" }, { "message": "error starting container f8433cc4b0c963ce95625ab3b1811382f852432f61a2d087422210e9d34bc2bc: cannot listen on the TCP port: listen tcp4 :11000: bind: address already in use,error starting container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50: a dependency of container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50 failed to start: container state improper", "reason": "Failed", "type": "warn" }, { "message": "error starting container f8433cc4b0c963ce95625ab3b1811382f852432f61a2d087422210e9d34bc2bc: cannot listen on the TCP port: listen tcp4 :11000: bind: address already in use,error starting container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50: a dependency of container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50 failed to start: container state improper", "reason": "Failed", "type": "warn" }, { "message": "error starting container f8433cc4b0c963ce95625ab3b1811382f852432f61a2d087422210e9d34bc2bc: cannot listen on the TCP port: listen tcp4 :11000: bind: address already in use,error starting container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50: a dependency of container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50 failed to start: container state improper", "reason": "Failed", "type": "warn" } ], "status": "up", "time": "${__time(yyyy-MM-dd'T'HH:mm:ss.SSS'Z')}", "version": "278650", "workloads": [ { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-1", "status": "Running" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-2", "status": "Created" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-3", "status": "Running" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-4", "status": "Created" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-5", "status": "Running" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-6", "status": "Created" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-7", "status": "Running" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-8", "status": "Created" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-9", "status": "Running" } ] }, "directive": "heartbeat", "message_id": "${__UUID()}", "type": "data", "version": 1 } + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${HEARTBEAT_FOLDER}/${DEVICE_ID}_heartbeat.out + ${HEARTBEAT_FOLDER}/${DEVICE_ID}_heartbeat.err + + + true diff --git a/test_plans/flotta_test_plan_edge_devices_only.jmx b/test_plans/flotta_test_plan_edge_devices_only.jmx index 3ddac93..3174388 100644 --- a/test_plans/flotta_test_plan_edge_devices_only.jmx +++ b/test_plans/flotta_test_plan_edge_devices_only.jmx @@ -1,5 +1,5 @@ - + The test plan will not include edge deployments creation @@ -10,7 +10,7 @@ HTTP_SERVER - localhost:8888 + localhost:8084 = @@ -28,17 +28,29 @@ LABEL_VALUE NAMESPACE DEPLOYMENTS_PER_DEVICE + TEST_DIR + SCRIPTS_DIR + REGISTRATION_FOLDER + GET_UPDATES_FOLDER + HEARTBEAT_FOLDER + CERTS_FOLDER - - flotta-operator-controller-manager-flotta-operator-system.apps.mycluster.redhat.com - + + ${__P(HTTP_SERVER,flotta-operator-controller-manager-flotta-operator-system.apps.mycluster.redhat.com)} + ${__P(HTTP_SERVER_PORT,80)} ${__P(OCP_API_SERVER,api.mycluster.redhat.com)} - 6443 + ${__P(OCP_API_PORT,6443)} region emea default - 10 + ${__P(DEPLOYMENTS_PER_DEVICE,10)} + ${__P(TEST_DIR,test_dir_delete_me)} + ${__P(SCRIPTS_DIR,.)} + ${__P(REGISTRATION_FOLDER,./registration)} + ${__P(GET_UPDATES_FOLDER,./get_updates)} + ${__P(HEARTBEAT_FOLDER,./heartbeat)} + ${__P(CERTS_FOLDER,./certs)} false @@ -58,6 +70,51 @@ true + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/create_output_streams.sh + = + + + + + + + REGISTRATION_FOLDER + ${REGISTRATION_FOLDER} + = + + + GET_UPDATES_FOLDER + ${GET_UPDATES_FOLDER} + = + + + HEARTBEAT_FOLDER + ${HEARTBEAT_FOLDER} + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + + + + @@ -70,7 +127,7 @@ MAC_ADDRESS2 - + ${__UUID()} ${__RandomString(10,abcdefg)} ${__RandomString(10,abcdefg)} @@ -83,7 +140,69 @@ The device ID to be used for the entire scenario of a specific device and additional device properties - + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/register_device.sh + = + + + + + + + REQUEST_PATH + api/flotta-management/v1/data/${DEVICE_ID}/in + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + PAYLOAD + { "content": { "hardware": { "boot": { "current_boot_mode": "bios" }, "cpu": { "architecture": "x86_64", "count": 8, "flags": [ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "clflush", "dts", "acpi", "mmx", "fxsr", "sse", "sse2", "ss", "ht", "tm", "pbe", "syscall", "nx", "pdpe1gb", "rdtscp", "lm", "constant_tsc", "art", "arch_perfmon", "pebs", "bts", "rep_good", "nopl", "xtopology", "nonstop_tsc", "cpuid", "aperfmperf", "pni", "pclmulqdq", "dtes64", "monitor", "ds_cpl", "vmx", "smx", "est", "tm2", "ssse3", "sdbg", "fma", "cx16", "xtpr", "pdcm", "pcid", "sse4_1", "sse4_2", "x2apic", "movbe", "popcnt", "tsc_deadline_timer", "aes", "xsave", "avx", "f16c", "rdrand", "lahf_lm", "abm", "3dnowprefetch", "cpuid_fault", "epb", "invpcid_single", "pti", "ssbd", "ibrs", "ibpb", "stibp", "tpr_shadow", "vnmi", "flexpriority", "ept", "vpid", "ept_ad", "fsgsbase", "tsc_adjust", "bmi1", "hle", "avx2", "smep", "bmi2", "erms", "invpcid", "rtm", "mpx", "rdseed", "adx", "smap", "clflushopt", "intel_pt", "xsaveopt", "xsavec", "xgetbv1", "xsaves", "dtherm", "ida", "arat", "pln", "pts", "hwp", "hwp_notify", "hwp_act_window", "hwp_epp", "md_clear", "flush_l1d" ], "frequency": 3600, "model_name": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz" }, "disks": [ { "drive_type": "SSD", "id": "/dev/dm-0", "name": "dm-0", "path": "/dev/dm-0", "size_bytes": 511032950784, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-0\"],\"messages\":[{\"string\":\"/dev/dm-0: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-1", "name": "dm-1", "path": "/dev/dm-1", "size_bytes": 117440512, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-1\"],\"messages\":[{\"string\":\"/dev/dm-1: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-10", "name": "dm-10", "path": "/dev/dm-10", "size_bytes": 6576668672, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-10\"],\"messages\":[{\"string\":\"/dev/dm-10: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-2", "name": "dm-2", "path": "/dev/dm-2", "size_bytes": 477232103424, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-2\"],\"messages\":[{\"string\":\"/dev/dm-2: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-3", "name": "dm-3", "path": "/dev/dm-3", "size_bytes": 477232103424, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-3\"],\"messages\":[{\"string\":\"/dev/dm-3: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-4", "name": "dm-4", "path": "/dev/dm-4", "size_bytes": 107374182400, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-4\"],\"messages\":[{\"string\":\"/dev/dm-4: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-5", "name": "dm-5", "path": "/dev/dm-5", "size_bytes": 16609443840, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-5\"],\"messages\":[{\"string\":\"/dev/dm-5: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-6", "name": "dm-6", "path": "/dev/dm-6", "size_bytes": 477232103424, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-6\"],\"messages\":[{\"string\":\"/dev/dm-6: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-7", "name": "dm-7", "path": "/dev/dm-7", "size_bytes": 369857921024, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-7\"],\"messages\":[{\"string\":\"/dev/dm-7: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-8", "name": "dm-8", "path": "/dev/dm-8", "size_bytes": 511705088, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-8\"],\"messages\":[{\"string\":\"/dev/dm-8: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "drive_type": "SSD", "id": "/dev/dm-9", "name": "dm-9", "path": "/dev/dm-9", "size_bytes": 6576668672, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/dm-9\"],\"messages\":[{\"string\":\"/dev/dm-9: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" }, { "bootable": true, "by_id": "/dev/disk/by-id/nvme-eui.002538c571b05d4b", "by_path": "/dev/disk/by-path/pci-0000:3e:00.0-nvme-1", "drive_type": "SSD", "id": "/dev/disk/by-id/nvme-eui.002538c571b05d4b", "model": "SAMSUNG MZVKW512HMJP-000L7", "name": "nvme0n1", "path": "/dev/nvme0n1", "serial": "S35BNX0J505918", "size_bytes": 512110190592, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/nvme0n1\"],\"exit_status\":0},\"device\":{\"name\":\"/dev/nvme0n1\",\"info_name\":\"/dev/nvme0n1\",\"type\":\"nvme\",\"protocol\":\"NVMe\"},\"model_name\":\"SAMSUNG MZVKW512HMJP-000L7\",\"serial_number\":\"S35BNX0J505918\",\"firmware_version\":\"7L6QCXA7\",\"nvme_pci_vendor\":{\"id\":5197,\"subsystem_id\":5197},\"nvme_ieee_oui_identifier\":9528,\"nvme_total_capacity\":512110190592,\"nvme_unallocated_capacity\":0,\"nvme_controller_id\":2,\"nvme_version\":{\"string\":\"1.2\",\"value\":66048},\"nvme_number_of_namespaces\":1,\"nvme_namespaces\":[{\"id\":1,\"size\":{\"blocks\":1000215216,\"bytes\":512110190592},\"capacity\":{\"blocks\":1000215216,\"bytes\":512110190592},\"utilization\":{\"blocks\":1000215216,\"bytes\":512110190592},\"formatted_lba_size\":512,\"eui64\":{\"oui\":9528,\"ext_id\":848015940939}}],\"user_capacity\":{\"blocks\":1000215216,\"bytes\":512110190592},\"logical_block_size\":512,\"local_time\":{\"time_t\":1637498725,\"asctime\":\"Sun Nov 21 14:45:25 2021 IST\"},\"smart_status\":{\"passed\":true,\"nvme\":{\"value\":0}},\"nvme_smart_health_information_log\":{\"critical_warning\":0,\"temperature\":27,\"available_spare\":100,\"available_spare_threshold\":10,\"percentage_used\":15,\"data_units_read\":17934599,\"data_units_written\":97148210,\"host_reads\":463356329,\"host_writes\":2453263768,\"controller_busy_time\":15671,\"power_cycles\":1517,\"power_on_hours\":11110,\"unsafe_shutdowns\":261,\"media_errors\":0,\"num_err_log_entries\":495,\"warning_temp_time\":0,\"critical_comp_time\":0,\"temperature_sensors\":[27,40]},\"temperature\":{\"current\":27},\"power_cycle_count\":1517,\"power_on_time\":{\"hours\":11110}}", "wwn": "eui.002538c571b05d4b" }, { "drive_type": "SSD", "id": "/dev/zram0", "name": "zram0", "path": "/dev/zram0", "size_bytes": 4294967296, "smart": "{\"json_format_version\":[1,0],\"smartctl\":{\"version\":[7,2],\"svn_revision\":\"5155\",\"platform_info\":\"x86_64-linux-5.13.14-100.fc33.x86_64\",\"build_info\":\"(local build)\",\"argv\":[\"smartctl\",\"--xall\",\"--json=c\",\"/dev/zram0\"],\"messages\":[{\"string\":\"/dev/zram0: Unable to detect device type\",\"severity\":\"error\"}],\"exit_status\":1}}" } ], "gpus": [ { "address": "0000:01:00.0", "device_id": "13b1", "name": "GM107GLM [Quadro M1000M]", "vendor": "NVIDIA Corporation", "vendor_id": "10de" } ], "hostname": "${HOSTNAME}", "interfaces": [ { "biosdevname": "em1", "flags": [ "up", "broadcast", "multicast" ], "has_carrier": true, "ipv4_addresses": [ "10.100.102.22/24" ], "ipv6_addresses": [], "mac_address": "${MAC_ADDRESS2}", "mtu": 1500, "name": "enp0s31f6", "product": "0x15b7", "speed_mbps": 1000, "vendor": "0x8086" }, { "biosdevname": "p2p1", "flags": [ "broadcast", "multicast" ], "ipv4_addresses": [], "ipv6_addresses": [], "mac_address": "${MAC_ADDRESS2}", "mtu": 1500, "name": "wlp4s0", "product": "0x24f3", "vendor": "0x8086" } ], "memory": { "physical_bytes": 34359738368, "usable_bytes": 33084645376 }, "system_vendor": { "manufacturer": "LENOVO", "product_name": "${PRODUCT_NAME}", "serial_number": "${SERIAL_NAME}" } }, "os_image_id": "unknown" }, "directive": "registration", "message_id": "${__UUID()}", "sent": "2021-11-21T14:45:25.271+02:00", "type": "data", "version": 1 } + = + + + REGISTRATION_FOLDER + ${REGISTRATION_FOLDER} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.out + ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.err + + + true @@ -507,7 +626,59 @@ 4 - + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/get_device_update.sh + = + + + + + + + REQUEST_PATH + api/flotta-management/v1/data/${DEVICE_ID}/in + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${GET_UPDATES_FOLDER}/${DEVICE_ID}_get_updates.out + ${GET_UPDATES_FOLDER}/${DEVICE_ID}_get_updates.err + + + @@ -532,7 +703,64 @@ - + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/request_operator.sh + = + + + + + + + REQUEST_PATH + api/flotta-management/v1/data/${DEVICE_ID}/out + = + + + POST_BODY + { "content": { "events": [], "status": "up", "time": "2021-11-23T02:16:37.697+02:00", "version": "278650", "workloads": [] }, "directive": "heartbeat", "message_id": "${__UUID()}", "type": "data", "version": 1 } + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${HEARTBEAT_FOLDER}/${DEVICE_ID}_heartbeat.out + ${HEARTBEAT_FOLDER}/${DEVICE_ID}_heartbeat.err + + + true diff --git a/test_plans/flotta_test_plan_multiple_namespaces.jmx b/test_plans/flotta_test_plan_multiple_namespaces.jmx index 2e8d8a0..07565ae 100644 --- a/test_plans/flotta_test_plan_multiple_namespaces.jmx +++ b/test_plans/flotta_test_plan_multiple_namespaces.jmx @@ -1,5 +1,5 @@ - + @@ -23,10 +23,15 @@ DEFAULT_NAMESPACE DEPLOYMENTS_PER_DEVICE NAMESPACES_COUNT - + TEST_DIR + SCRIPTS_DIR + REGISTRATION_FOLDER + GET_UPDATES_FOLDER + HEARTBEAT_FOLDER + CERTS_FOLDER - + ${__P(HTTP_SERVER,flotta-operator-controller-manager-flotta-operator-system.apps.mycluster.redhat.com)} ${__P(HTTP_SERVER_PORT,80)} ${__P(OCP_API_SERVER,api.mycluster.redhat.com)} @@ -36,7 +41,12 @@ default ${__P(DEPLOYMENTS_PER_DEVICE,5)} ${__P(NAMESPACES_COUNT,5)} - + ${__P(TEST_DIR,test_dir_delete_me)} + ${__P(SCRIPTS_DIR,.)} + ${__P(REGISTRATION_FOLDER,./registration)} + ${__P(GET_UPDATES_FOLDER,./get_updates)} + ${__P(HEARTBEAT_FOLDER,./heartbeat)} + ${__P(CERTS_FOLDER,./certs)} false @@ -90,7 +100,7 @@ HttpClient4 - Create Edge Deployment with labels matching for device + Create Edge Workload with labels matching for device @@ -133,6 +143,51 @@ true + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/create_output_streams.sh + = + + + + + + + REGISTRATION_FOLDER + ${REGISTRATION_FOLDER} + = + + + GET_UPDATES_FOLDER + ${GET_UPDATES_FOLDER} + = + + + HEARTBEAT_FOLDER + ${HEARTBEAT_FOLDER} + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + + + + @@ -182,7 +237,74 @@ vars.put("NAMESPACE", ns); The device ID to be used for the entire scenario of a specific device and additional device properties - + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/register_device.sh + = + + + + + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + PRODUCT_NAME + ${PRODUCT_NAME} + = + + + SERIAL_NAME + ${SERIAL_NAME} + = + + + PAYLOAD + { "content": { "hardware": { "cpu": { "architecture": "x86_64", "flags": [], "model_name": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz" }, "hostname": "${HOSTNAME}", "system_vendor": { "manufacturer": "LENOVO", "product_name": "${PRODUCT_NAME}", "serial_number": "${SERIAL_NAME}" } }, "os_image_id": "unknown" }, "directive": "registration", "message_id": "${__UUID()}", "sent": "2021-11-21T14:45:25.271+02:00", "type": "data", "version": 1 } + = + + + REGISTRATION_FOLDER + ${REGISTRATION_FOLDER} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.out + ${REGISTRATION_FOLDER}/${DEVICE_ID}_register.err + + + true @@ -327,9 +449,9 @@ vars.put("NAMESPACE", ns); - + - + true ${DEPLOYMENTS_PER_DEVICE} @@ -344,7 +466,7 @@ vars.put("NAMESPACE", ns); true - + true @@ -352,7 +474,7 @@ vars.put("NAMESPACE", ns); false { "apiVersion": "management.project-flotta.io/v1alpha1", - "kind": "EdgeDeployment", + "kind": "EdgeWorkload", "metadata": { "name": "${DEVICE_ID}-${NameSuffix}", "namespace": "${NAMESPACE}" @@ -399,7 +521,7 @@ vars.put("NAMESPACE", ns); ${OCP_API_PORT} https UTF-8 - /apis/management.project-flotta.io/v1alpha1/namespaces/${NAMESPACE}/edgedeployments + /apis/management.project-flotta.io/v1alpha1/namespaces/${NAMESPACE}/edgeworkloads POST true false @@ -409,7 +531,7 @@ vars.put("NAMESPACE", ns); HttpClient4 - Create Edge Deployment with labels matching for device + Create Edge Workload with labels matching for device @@ -437,8 +559,8 @@ vars.put("NAMESPACE", ns); - - Add delays between edgedeployments creation of the same device + + Add delays between edgeworkloads creation of the same device 1000 @@ -454,7 +576,59 @@ vars.put("NAMESPACE", ns); 4 - + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/get_device_update.sh + = + + + + + + + REQUEST_PATH + api/flotta-management/v1/data/${DEVICE_ID}/in + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${GET_UPDATES_FOLDER}/${DEVICE_ID}_get_updates.out + ${GET_UPDATES_FOLDER}/${DEVICE_ID}_get_updates.err + + + @@ -480,7 +654,64 @@ vars.put("NAMESPACE", ns); - + + true + 0 + /bin/bash + + + + + -c + = + + + + ${SCRIPTS_DIR}/request_operator.sh + = + + + + + + + REQUEST_PATH + api/flotta-management/v1/data/${DEVICE_ID}/out + = + + + POST_BODY + { "content": { "events": [ { "message": "error starting container f8433cc4b0c963ce95625ab3b1811382f852432f61a2d087422210e9d34bc2bc: cannot listen on the TCP port: listen tcp4 :11000: bind: address already in use,error starting container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50: a dependency of container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50 failed to start: container state improper", "reason": "Failed", "type": "warn" }, { "message": "error starting container f8433cc4b0c963ce95625ab3b1811382f852432f61a2d087422210e9d34bc2bc: cannot listen on the TCP port: listen tcp4 :11000: bind: address already in use,error starting container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50: a dependency of container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50 failed to start: container state improper", "reason": "Failed", "type": "warn" }, { "message": "error starting container f8433cc4b0c963ce95625ab3b1811382f852432f61a2d087422210e9d34bc2bc: cannot listen on the TCP port: listen tcp4 :11000: bind: address already in use,error starting container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50: a dependency of container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50 failed to start: container state improper", "reason": "Failed", "type": "warn" }, { "message": "error starting container f8433cc4b0c963ce95625ab3b1811382f852432f61a2d087422210e9d34bc2bc: cannot listen on the TCP port: listen tcp4 :11000: bind: address already in use,error starting container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50: a dependency of container 7cd64802bde9d6b9dd425d79ea68eb49546e5fc87d0dce474c7515e81f448d50 failed to start: container state improper", "reason": "Failed", "type": "warn" } ], "status": "up", "time": "${__time(yyyy-MM-dd'T'HH:mm:ss.SSS'Z')}", "version": "278650", "workloads": [ { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-1", "status": "Running" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-2", "status": "Created" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-3", "status": "Running" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-4", "status": "Created" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-5", "status": "Running" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-6", "status": "Created" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-7", "status": "Running" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-8", "status": "Created" }, { "last_data_upload": "0001-01-01T00:00:00.000Z", "name": "${DEVICE_ID}-9", "status": "Running" } ] }, "directive": "heartbeat", "message_id": "${__UUID()}", "type": "data", "version": 1 } + = + + + DEVICE_ID + ${DEVICE_ID} + = + + + HTTP_SERVER + ${HTTP_SERVER} + = + + + HTTP_SERVER_PORT + ${HTTP_SERVER_PORT} + = + + + CERTS_FOLDER + ${CERTS_FOLDER} + = + + + + + ${HEARTBEAT_FOLDER}/${DEVICE_ID}_heartbeat.out + ${HEARTBEAT_FOLDER}/${DEVICE_ID}_heartbeat.err + + + true