summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xci/create_stack.sh1
-rwxr-xr-xci/daily.sh9
-rwxr-xr-xci/launch_docker_container.sh45
-rwxr-xr-xci/remove_docker_container.sh30
-rwxr-xr-xci/start_job.sh4
-rw-r--r--docker-compose/docker-compose.yaml25
-rw-r--r--docker-compose/nginx.conf39
-rw-r--r--docs/release/release-notes/index.rst10
-rw-r--r--docs/release/release-notes/release-notes.rst40
-rwxr-xr-xdocs/testing/user/installation.rst228
-rw-r--r--docs/testing/user/introduction.rst153
-rw-r--r--docs/testing/user/test-usage.rst2
-rw-r--r--rest_server.py31
-rw-r--r--storperf/resources/hot/agent-group.yaml4
-rw-r--r--storperf/storperf_master.py18
-rw-r--r--tests/db_tests/configuration_db_test.py9
-rw-r--r--tests/storperf_master_test.py18
17 files changed, 437 insertions, 229 deletions
diff --git a/ci/create_stack.sh b/ci/create_stack.sh
index 68c4874..a0be65c 100755
--- a/ci/create_stack.sh
+++ b/ci/create_stack.sh
@@ -21,3 +21,4 @@ curl -X POST --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d @body.json \
'http://127.0.0.1:5000/api/v1.0/configurations'
+rm body.json \ No newline at end of file
diff --git a/ci/daily.sh b/ci/daily.sh
index c42fe64..26d5fea 100755
--- a/ci/daily.sh
+++ b/ci/daily.sh
@@ -27,8 +27,6 @@ pip install osc_lib==1.3.0
pip install python-openstackclient==3.7.0
pip install python-heatclient==1.7.0
-sudo find $WORKSPACE/ -name '*.db' -exec rm -fv {} \;
-
$WORKSPACE/ci/generate-admin-rc.sh
echo "TEST_DB_URL=http://testresults.opnfv.org/test/api/v1" >> $WORKSPACE/ci/job/admin.rc
$WORKSPACE/ci/generate-environment.sh
@@ -42,12 +40,12 @@ done < $WORKSPACE/ci/job/admin.rc
export AGENT_COUNT=${AGENT_COUNT:-$CINDER_NODES}
export BLOCK_SIZES=${BLOCK_SIZES:-1024,16384}
+export STEADY_STATE_SAMPLES=${STEADY_STATE_SAMPLES:-10}
export DEADLINE=${DEADLINE:-`expr $STEADY_STATE_SAMPLES \* 3`}
export DISK_TYPE=${DISK_TYPE:-unspecified}
export QUEUE_DEPTHS=${QUEUE_DEPTHS:-1,4}
export POD_NAME=${NODE_NAME:-`hostname`}
export SCENARIO_NAME=${DEPLOY_SCENARIO:-none}
-export STEADY_STATE_SAMPLES=${STEADY_STATE_SAMPLES:-10}
export TEST_CASE=${TEST_CASE:-snia_steady_state}
export VERSION=`echo ${BUILD_TAG#*daily-} | cut -d- -f1`
export VOLUME_SIZE=${VOLUME_SIZE:-2}
@@ -58,13 +56,13 @@ echo Environment
env | sort
echo ==========================================================================
+$WORKSPACE/ci/remove_docker_container.sh
$WORKSPACE/ci/delete_stack.sh
$WORKSPACE/ci/create_glance_image.sh
$WORKSPACE/ci/create_storperf_flavor.sh
$WORKSPACE/ci/launch_docker_container.sh
$WORKSPACE/ci/create_stack.sh $AGENT_COUNT $VOLUME_SIZE "Ubuntu 16.04 x86_64" $NETWORK
-
export WORKLOAD=_warm_up,$WORKLOADS
export BLOCK_SIZE=$BLOCK_SIZES
export QUEUE_DEPTH=$QUEUE_DEPTHS
@@ -99,7 +97,8 @@ curl -s -X DELETE --header 'Accept: application/json' 'http://127.0.0.1:5000/api
curl -s -X GET "http://127.0.0.1:5000/api/v1.0/jobs?id=$JOB&type=metadata" \
-o $WORKSPACE/ci/job/report.json
-docker rm -f storperf
+$WORKSPACE/ci/remove_docker_container.sh
+
sudo rm -rf $WORKSPACE/ci/job/carbon
echo ==========================================================================
diff --git a/ci/launch_docker_container.sh b/ci/launch_docker_container.sh
index ec9c4d8..4f4e38b 100755
--- a/ci/launch_docker_container.sh
+++ b/ci/launch_docker_container.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/bash -x
##############################################################################
# Copyright (c) 2016 EMC and others.
#
@@ -9,42 +9,29 @@
##############################################################################
cd `dirname $0`
+ci=`pwd`
-storperf_container=`docker ps -a -q -f name=storperf`
+cd ${ci}/../docker-compose
-if [ ! -z $storperf_container ]
-then
- echo "Stopping any existing StorPerf container"
- docker rm -fv $storperf_container
-fi
-
-if [ ! -f job/admin.rc ]
-then
- ./generate-admin-rc.sh
-fi
+export TAG=${DOCKER_TAG:-latest}
+export ENV_FILE=${ci}/job/admin.rc
+export CARBON_DIR=${ci}/job/carbon/
-if [ ! -d job/carbon ]
+if [ ! -d ${ci}/job/carbon ]
then
- mkdir job/carbon
- sudo chown 33:33 job/carbon
+ mkdir ${ci}/job/carbon
+ sudo chown 33:33 ${ci}/job/carbon
fi
-if [ -z $DOCKER_TAG ]
-then
- DOCKER_TAG=latest
-fi
-
-docker pull opnfv/storperf:$DOCKER_TAG
-
-docker run -d --env-file `pwd`/job/admin.rc \
- -p 5000:5000 \
- -p 8000:8000 \
- -v `pwd`/job/carbon:/opt/graphite/storage/whisper \
- --name storperf opnfv/storperf
-# -v `pwd`/../../storperf:/home/opnfv/repos/storperf \
+docker-compose pull
+docker-compose up -d
echo "Waiting for StorPerf to become active"
-while [ $(curl -X GET 'http://127.0.0.1:5000/api/v1.0/configurations' > /dev/null 2>&1;echo $?) -ne 0 ]
+curl -X GET 'http://127.0.0.1:5000/api/v1.0/configurations' > test.html 2>&1
+while [ `grep 'agent_count' test.html | wc -l` == "0" ]
do
sleep 1
+ curl -X GET 'http://127.0.0.1:5000/api/v1.0/configurations' > test.html 2>&1
done
+
+rm -f test.html
diff --git a/ci/remove_docker_container.sh b/ci/remove_docker_container.sh
new file mode 100755
index 0000000..f424110
--- /dev/null
+++ b/ci/remove_docker_container.sh
@@ -0,0 +1,30 @@
+#!/bin/bash -x
+##############################################################################
+# Copyright (c) 2016 EMC and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+cd `dirname $0`
+ci=`pwd`
+
+cd ${ci}/../docker-compose
+
+export TAG=${DOCKER_TAG:-latest}
+export ENV_FILE=${ci}/job/admin.rc
+export CARBON_DIR=${ci}/job/carbon/
+
+docker-compose down
+
+for container_name in storperf swagger-ui http-front-end
+do
+ container=`docker ps -a -q -f name=$container_name`
+ if [ ! -z $container ]
+ then
+ echo "Stopping any existing $container_name container"
+ docker rm -fv $container
+ fi
+done
diff --git a/ci/start_job.sh b/ci/start_job.sh
index 0a149fd..dde3dca 100755
--- a/ci/start_job.sh
+++ b/ci/start_job.sh
@@ -15,7 +15,7 @@ cat << EOF > body.json
"steady_state_samples": ${STEADY_STATE_SAMPLES},
"queue_depths": "${QUEUE_DEPTH}",
"workload": "${WORKLOAD}",
- "metadata": {
+ "metadata": {
"disk_type": "${DISK_TYPE}",
"pod_name": "${POD_NAME}",
"scenario_name": "${SCENARIO_NAME}",
@@ -32,3 +32,5 @@ cat body.json 1>&2
curl -s -X POST --header 'Content-Type: application/json' \
--header 'Accept: application/json' \
-d @body.json http://127.0.0.1:5000/api/v1.0/jobs
+
+rm body.json \ No newline at end of file
diff --git a/docker-compose/docker-compose.yaml b/docker-compose/docker-compose.yaml
new file mode 100644
index 0000000..dbba825
--- /dev/null
+++ b/docker-compose/docker-compose.yaml
@@ -0,0 +1,25 @@
+version: '2'
+services:
+ storperf:
+ container_name: "storperf"
+ image: "opnfv/storperf:${TAG}"
+ ports:
+ - "8000:8000"
+ env_file: ${ENV_FILE}
+ volumes:
+ - ${CARBON_DIR}:/opt/graphite/storage/whisper
+
+ swagger-ui:
+ container_name: "swagger-ui"
+ image: "schickling/swagger-ui"
+
+ http-front-end:
+ container_name: "http-front-end"
+ image: nginx:stable-alpine
+ ports:
+ - "5000:5000"
+ volumes:
+ - ./nginx.conf:/etc/nginx/nginx.conf:ro
+ links:
+ - storperf
+ - swagger-ui \ No newline at end of file
diff --git a/docker-compose/nginx.conf b/docker-compose/nginx.conf
new file mode 100644
index 0000000..6771358
--- /dev/null
+++ b/docker-compose/nginx.conf
@@ -0,0 +1,39 @@
+http {
+ include mime.types;
+ default_type application/octet-stream;
+ sendfile on;
+ keepalive_timeout 65;
+ proxy_send_timeout 600;
+ proxy_read_timeout 600;
+ send_timeout 600;
+
+ map $args $containsurl {
+ default 0;
+ "~(^|&)url=[^&]+($|&)" 1;
+ }
+
+ server {
+ listen 5000;
+
+ location /api/ {
+ proxy_pass http://storperf:5000;
+ proxy_set_header Host $host:$proxy_port;
+ }
+
+ location /graphite/ {
+ proxy_pass http://storperf:8000;
+ proxy_set_header Host $host:$proxy_port;
+ }
+
+ location /swagger/ {
+ if ($containsurl = 0) {
+ return 302 $scheme://$host:$server_port$uri?url=http://$host:$server_port/api/spec.json$args;
+ }
+ proxy_pass http://swagger-ui:80/;
+ }
+ }
+}
+
+events {
+ worker_connections 1024;
+}
diff --git a/docs/release/release-notes/index.rst b/docs/release/release-notes/index.rst
index 206e941..bf71c6c 100644
--- a/docs/release/release-notes/index.rst
+++ b/docs/release/release-notes/index.rst
@@ -1,13 +1,9 @@
-.. _storperf-releasenotes:
-
-.. This work is licensed under a Creative Commons Attribution 4.0 International
-.. License.
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0
-.. (c) OPNFV, Ericsson AB and others.
-======================
+****************************
StorPerf Release Notes
-======================
+****************************
.. toctree::
:maxdepth: 2
diff --git a/docs/release/release-notes/release-notes.rst b/docs/release/release-notes/release-notes.rst
index 0ec3cfb..7d66fc9 100644
--- a/docs/release/release-notes/release-notes.rst
+++ b/docs/release/release-notes/release-notes.rst
@@ -1,23 +1,24 @@
.. This work is licensed under a Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0
-******
-Danube
-******
-This document provides the release notes for Danube of StorPerf.
+This document provides the release notes for Danube 3.0 of StorPerf.
.. contents::
:depth: 3
:local:
+
Version history
-===============
+---------------
+--------------------+--------------------+--------------------+--------------------+
| **Date** | **Ver.** | **Author** | **Comment** |
| | | | |
+--------------------+--------------------+--------------------+--------------------+
+| 2017-07-14 | Danube 3.0 | Mark Beierl | |
+| | | | |
++--------------------+--------------------+--------------------+--------------------+
| 2017-05-04 | Danube 2.0 | Mark Beierl | |
| | | | |
+--------------------+--------------------+--------------------+--------------------+
@@ -26,6 +27,11 @@ Version history
+--------------------+--------------------+--------------------+--------------------+
+Important notes
+===============
+This is the last release where StorPerf is delivered as a single container. Moving
+forward, StorPerf must be run using docker-compose.
+
Summary
=======
@@ -33,6 +39,8 @@ StorPerf is a standalone framework that uses OpenStack to measure Cinder volume
performance. If desired, it can push results to the OPNFV Test Results DB, or
the embedded Graphite web interface can be used to perform ad hoc queries.
+This release supports Keystone v3 authentication
+
Release Data
============
@@ -40,16 +48,16 @@ Release Data
| **Project** | StorPerf |
| | |
+--------------------------------------+--------------------------------------+
-| **Repo/commit-ID** | storperf/danube.2.0 |
+| **Repo/commit-ID** | storperf/danube.3.0 |
| | |
+--------------------------------------+--------------------------------------+
| **Release designation** | Danube base release |
| | |
+--------------------------------------+--------------------------------------+
-| **Release date** | 2017-05-04 |
+| **Release date** | 2017-07-14 |
| | |
+--------------------------------------+--------------------------------------+
-| **Purpose of the delivery** | OPNFV Danube release 2.0 |
+| **Purpose of the delivery** | OPNFV Danube release 3.0 |
| | |
+--------------------------------------+--------------------------------------+
@@ -67,18 +75,19 @@ Reason for version
Features additions
^^^^^^^^^^^^^^^^^^
-None
+* STORPERF-139 - Expose maximum number of steady state samples as a parameter
Bug Fixes
^^^^^^^^^
The following minor bugs have been fixed
-* STORPERF-111
-* STORPERF-123
-* STORPERF-124
+* STORPERF-127 - Unable to communicate using v3 authentication due to missing domain.
+* STORPERF-128 - Daily Danube job uses latest tag from docker
+* STORPERF-153 - Profiling a file does not work
+* STORPERF-154 - PROJECT_DOMAIN_ID not recognized
-See JIRA for full `change log <https://jira.opnfv.org/jira/secure/ReleaseNote.jspa?projectId=11002&version=10713>`_
+See JIRA for full `change log <https://jira.opnfv.org/jira/secure/ReleaseNote.jspa?projectId=11002&version=10714>`_
Deliverables
------------
@@ -86,7 +95,7 @@ Deliverables
Software
^^^^^^^^
-- `StorPerf Docker image <https://hub.docker.com/r/opnfv/storperf/tags>`_ (tag: danube.2.0)
+- `StorPerf Docker image <https://hub.docker.com/r/opnfv/storperf/tags>`_ (tag: danube.3.0)
Documentation
^^^^^^^^^^^^^
@@ -102,7 +111,8 @@ Limitations
Known issues
------------
-* STORPERF-56 Cannot delete stack if create failed
+* STORPERF-56 - Cannot delete stack if create failed
+* STORPERF-180 - No details if stack create failed
Test Result
===========
diff --git a/docs/testing/user/installation.rst b/docs/testing/user/installation.rst
index 0effb2f..6098360 100755
--- a/docs/testing/user/installation.rst
+++ b/docs/testing/user/installation.rst
@@ -9,6 +9,11 @@ StorPerf Installation Guide
OpenStack Prerequisites
===========================
If you do not have an Ubuntu 16.04 image in Glance, you will need to add one.
+You also need to create the StorPerf flavor, or choose one that closely
+matches. For Ubuntu 16.04, it must have a minimum of a 4 GB disk. It should
+also have about 8 GB RAM to support FIO's memory mapping of written data blocks
+to ensure 100% coverage of the volume under test.
+
There are scripts in storperf/ci directory to assist, or you can use the follow
code snippets:
@@ -26,78 +31,214 @@ code snippets:
--disk 4 \
--vcpus 2
+OpenStack Credentials
+~~~~~~~~~~~~~~~~~~~~~
+
+You must have your OpenStack Controller environment variables defined and passed to
+the StorPerf container. The easiest way to do this is to put the rc file contents
+into a clean file called admin.rc that looks similar to this for V2 authentication:
+
+.. code-block:: console
+
+ cat << 'EOF' > admin.rc
+ OS_AUTH_URL=http://10.13.182.243:5000/v2.0
+ OS_TENANT_ID=e8e64985506a4a508957f931d1800aa9
+ OS_TENANT_NAME=admin
+ OS_PROJECT_NAME=admin
+ OS_USERNAME=admin
+ OS_PASSWORD=admin
+ OS_REGION_NAME=RegionOne
+ EOF
+
+For V3 authentication, at a minimum, use the following:
+
+.. code-block:: console
+
+ cat << 'EOF' > admin.rc
+ OS_AUTH_URL=http://10.10.243.14:5000/v3
+ OS_USERNAME=admin
+ OS_PASSWORD=admin
+ OS_PROJECT_DOMAIN_NAME=Default
+ OS_PROJECT_NAME=admin
+ OS_USER_DOMAIN_NAME=Default
+ EOF
+
+
+Additionally, if you want your results published to the common OPNFV Test Results
+DB, add the following:
+
+.. code-block:: console
+
+ TEST_DB_URL=http://testresults.opnfv.org/testapi
+
Planning
===========================
-StorPerf is delivered as a `Docker container
-<https://hub.docker.com/r/opnfv/storperf/tags/>`__. There are two possible
-methods for installation in your environment:
- 1. Run container on Jump Host
- 2. Run container in a VM
+StorPerf is delivered as a series of Docker containers managed by
+docker-compose. There are two possible methods for installation:
-
-Running StorPerf on Jump Host
-=============================
+#. Run container on bare metal
+#. Run container in a VM
Requirements:
- * Docker must be installed
- * Jump Host must have access to the OpenStack Controller API
- * Jump Host must have internet connectivity for downloading docker image
- * Enough floating IPs must be available to match your agent count
+* Docker and docker-compose must be installed
+ * (note: sudo_ may be required if user is not part of docker group)
+* OpenStack Controller credentials are available
+* Host has access to the OpenStack Controller API
+* Host must have internet connectivity for downloading docker image
+* Enough OpenStack floating IPs must be available to match your agent count
-Running StorPerf in a VM
-========================
+.. _sudo: https://docs.docker.com/engine/reference/run/#general-form
-Requirements:
+Ports
+=====
- * VM has docker installed
- * VM has OpenStack Controller credentials and can communicate with the Controller API
- * VM has internet connectivity for downloading the docker image
- * Enough floating IPs must be available to match your agent count
+The following ports are exposed if you use the supplied docker-compose.yaml
+file:
-VM Creation
-~~~~~~~~~~~
+* 5000 for StorPerf ReST API and Swagger UI
+* 8000 for StorPerf's Graphite Web Server
-The following procedure will create the VM in your environment
-.. code-block:: console
+Running StorPerf Container
+==========================
+
+**As of Euphrates (development) release (June 2017), StorPerf has
+changed to use docker-compose in order to start its services.**
- # Create the StorPerf VM itself. Here we use the network ID generated by OPNFV FUEL.
- ADMIN_NET_ID=`neutron net-list | grep 'admin_internal_net ' | awk '{print $2}'`
+Two files are needed in order
+to start StorPerf:
- nova boot --nic net-id=$ADMIN_NET_ID --flavor m1.small --key-name=StorPerf --image 'Ubuntu 14.04' 'StorPerf Master'
+#. docker-compose.yaml
+#. nginx.conf
-At this point, you may associate a floating IP with the StorPerf master VM.
+Copy and paste the following into a terminal to create the docker-compose.yaml
-VM Docker Installation
-~~~~~~~~~~~~~~~~~~~~~~
+.. code-block:: console
-The following procedure will install Docker on Ubuntu 14.04.
+ cat << 'EOF' > docker-compose.yaml
+ version: '2'
+ services:
+ storperf:
+ container_name: "storperf"
+ image: "opnfv/storperf:${TAG}"
+ ports:
+ - "8000:8000"
+ env_file: ${ENV_FILE}
+ volumes:
+ - ${CARBON_DIR}:/opt/graphite/storage/whisper
+ swagger-ui:
+ container_name: "swagger-ui"
+ image: "schickling/swagger-ui"
+ http-front-end:
+ container_name: "http-front-end"
+ image: nginx:stable-alpine
+ ports:
+ - "5000:5000"
+ volumes:
+ - ./nginx.conf:/etc/nginx/nginx.conf:ro
+ links:
+ - storperf
+ - swagger-ui
+ EOF
+
+Copy and paste the following into a terminal to create the nginx.conf
.. code-block:: console
- sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
- cat << EOF | sudo tee /etc/apt/sources.list.d/docker.list
- deb https://apt.dockerproject.org/repo ubuntu-trusty main
+ cat << 'EOF' > nginx.conf
+ http {
+ include mime.types;
+ default_type application/octet-stream;
+ sendfile on;
+ keepalive_timeout 65;
+ proxy_send_timeout 600;
+ proxy_read_timeout 600;
+ send_timeout 600;
+ map $args $containsurl {
+ default 0;
+ "~(^|&)url=[^&]+($|&)" 1;
+ }
+ server {
+ listen 5000;
+ location /api/ {
+ proxy_pass http://storperf:5000;
+ proxy_set_header Host $host:$proxy_port;
+ }
+ location /swagger/ {
+ if ($containsurl = 0) {
+ return 302 $scheme://$host:$server_port$uri?url=http://$host:$server_port/api/spec.json$args;
+ }
+ proxy_pass http://swagger-ui:80/;
+ }
+ }
+ }
+ events {
+ worker_connections 1024;
+ }
EOF
- sudo apt-get update
- sudo apt-get install -y docker-engine
- sudo usermod -aG docker ubuntu
+Local disk used for the Carbon DB storage as the default size of the docker
+container is only 10g. Here is an example of how to create a local storage
+directory and set its permissions so that StorPerf can write to it:
+
+.. code-block:: console
+
+ mkdir -p ./carbon
+ sudo chown 33:33 ./carbon
+
+
+The following command will start all the StorPerf services:
+
+.. code-block:: console
+
+ TAG=latest ENV_FILE=./admin.rc CARBON_DIR=./carbon/ docker-compose pull
+ TAG=latest ENV_FILE=./admin.rc CARBON_DIR=./carbon/ docker-compose up -d
+
+You can now view the StorPerf SwaggerUI at:
+
+``http://127.0.0.1:5000/swagger``
+
+
+Docker Exec
+~~~~~~~~~~~
+
+If needed, the container can be entered with docker exec. This is not normally
+required.
+
+.. code-block:: console
+
+ docker exec -it storperf bash
+
+
Pulling StorPerf Container
==========================
+Master (Euphrates)
+~~~~~~~~~~~~~~~~~~
+
+StorPerf has switched to docker-compose in the latest version. The tag for
+pulling the latest master Euphrates container is:
+
+.. code-block:: bash
+
+ docker pull opnfv/storperf:master
+
+However, by itself, this will no longer provide full functionality. Full
+instructions are provided in the Introduction document.
+
+
Danube
~~~~~~
-The tag for the latest stable Danube will be:
+The tag for the latest stable Danube is be:
.. code-block:: bash
- docker pull opnfv/storperf:danube.1.0
+ docker pull opnfv/storperf:danube.2.0
Colorado
~~~~~~~~
@@ -116,14 +257,3 @@ The tag for the latest stable Brahmaputra release is:
.. code-block:: bash
docker pull opnfv/storperf:brahmaputra.1.2
-
-Development
-~~~~~~~~~~~
-
-The tag for the latest development version is:
-
-.. code-block:: bash
-
- docker pull opnfv/storperf:master
-
-
diff --git a/docs/testing/user/introduction.rst b/docs/testing/user/introduction.rst
index a40750f..49e3220 100644
--- a/docs/testing/user/introduction.rst
+++ b/docs/testing/user/introduction.rst
@@ -2,100 +2,59 @@
.. http://creativecommons.org/licenses/by/4.0
.. (c) OPNFV, Dell EMC and others.
-==================================
-StorPerf Container Execution Guide
-==================================
-
-Planning
-========
-
-There are some ports that the container can expose:
-
- * 22 for SSHD. Username and password are root/storperf. This is used for CLI access only
- * 5000 for StorPerf ReST API.
- * 8000 for StorPerf's Graphite Web Server
-
-OpenStack Credentials
-~~~~~~~~~~~~~~~~~~~~~
-
-You must have your OpenStack Controller environment variables defined and passed to
-the StorPerf container. The easiest way to do this is to put the rc file contents
-into a clean file the looks similar to this for V2 authentication:
-
-.. code-block:: console
-
- OS_AUTH_URL=http://10.13.182.243:5000/v2.0
- OS_TENANT_ID=e8e64985506a4a508957f931d1800aa9
- OS_TENANT_NAME=admin
- OS_PROJECT_NAME=admin
- OS_USERNAME=admin
- OS_PASSWORD=admin
- OS_REGION_NAME=RegionOne
-
-For V3 authentication, use the following:
-
-.. code-block:: console
-
- OS_AUTH_URL=http://10.13.182.243:5000/v3
- OS_PROJECT_ID=32ae78a844bc4f108b359dd7320463e5
- OS_PROJECT_NAME=admin
- OS_USER_DOMAIN_NAME=Default
- OS_USERNAME=admin
- OS_PASSWORD=admin
- OS_REGION_NAME=RegionOne
- OS_INTERFACE=public
- OS_IDENTITY_API_VERSION=3
-
-Additionally, if you want your results published to the common OPNFV Test Results
- DB, add the following:
-
-.. code-block:: console
-
- TEST_DB_URL=http://testresults.opnfv.org/testapi
-
-Running StorPerf Container
-==========================
-
-You might want to have the local disk used for storage as the default size of the docker
-container is only 10g. This is done with the -v option, mounting under
-/opt/graphite/storage/whisper
-
-.. code-block:: console
-
- mkdir -p ~/carbon
- sudo chown 33:33 ~/carbon
-
-The recommended method of running StorPerf is to expose only the ReST and Graphite
-ports. The command line below shows how to run the container with local disk for
-the carbon database.
-
-.. code-block:: console
-
- docker run -t --env-file admin-rc -p 5000:5000 -p 8000:8000 -v ~/carbon:/opt/graphite/storage/whisper --name storperf opnfv/storperf
-
-
-Docker Exec
-~~~~~~~~~~~
-
-Instead of exposing port 5022 externally, you can use the exec method in docker. This
-provides a slightly more secure method of running StorPerf container without having to
-expose port 22.
-
-If needed, the container can be entered with docker exec. This is not normally required.
-
-.. code-block:: console
-
- docker exec -it storperf bash
-
-Container with SSH
-~~~~~~~~~~~~~~~~~~
-
-Running the StorPerf Container with all ports open and a local disk for the result
-storage. This is not recommended as the SSH port is open.
-
-.. code-block:: console
-
- docker run -t --env-file admin-rc -p 5022:22 -p 5000:5000 -p 8000:8000 -v ~/carbon:/opt/graphite/storage/whisper --name storperf opnfv/storperf
-
-This will then permit ssh to localhost port 5022 for CLI access.
-
+=====================
+StorPerf Introduction
+=====================
+
+The purpose of StorPerf is to provide a tool to measure ephemeral and block
+storage performance of OpenStack.
+
+A key challenge to measuring disk performance is to know when the disk (or,
+for OpenStack, the virtual disk or volume) is performing at a consistent and
+repeatable level of performance. Initial writes to a volume can perform
+poorly due to block allocation, and reads can appear instantaneous when
+reading empty blocks. How do we know when the data reported is valid? The
+Storage Network Industry Association (SNIA_) has developed methods which enable
+manufacturers to set, and customers to compare, the performance specifications
+of Solid State Storage devices. StorPerf applies this methodology to OpenStack
+Cinder and Glance services to provide a high level of confidence in the
+performance metrics in the shortest reasonable time.
+
+.. _SNIA: http://www.snia.org/sites/default/files/HoEasen_SNIA_Solid_State_Storage_Per_Test_1_0.pdf
+
+How Does StorPerf Work?
+=======================
+
+Once launched, StorPerf presents you with a ReST interface, along with a
+`Swagger UI <https://swagger.io/swagger-ui/>`_ that makes it easier to
+form HTTP ReST requests. Issuing an HTTP POST to the configurations API
+causes StorPerf to talk to your OpenStack's heat service to create a new stack
+with as many agent VMs and attached Cinder volumes as you specify.
+
+After the stack is created, you can issue one or more jobs by issuing a POST
+to the jobs ReST API. The job is the smallest unit of work that StorPerf
+can use to measure the disk's performance.
+
+While the job is running, StorPerf collects the performance metrics from each
+of the disks under test every minute. Once the trend of metrics match the
+criteria specified in the SNIA methodology, the job automatically terminates
+and the valid set of metrics are available for querying.
+
+What is the criteria? Simply put, it specifies that when the metrics
+measured start to "flat line" and stay within that range for the specified
+amount of time, then the metrics are considered to be indicative of a
+repeatable level of performance.
+
+What Data Can I Get?
+====================
+
+StorPerf provides the following metrics:
+
+* IOPS
+* Bandwidth (number of kilobytes read or written per second)
+* Latency
+
+These metrics are available for every job, and for the specific workloads,
+I/O loads and I/O types (read, write) associated with the job.
+
+As of this time, StorPerf only provides textual reports of the metrics.
diff --git a/docs/testing/user/test-usage.rst b/docs/testing/user/test-usage.rst
index 2beae69..91733cf 100644
--- a/docs/testing/user/test-usage.rst
+++ b/docs/testing/user/test-usage.rst
@@ -39,6 +39,7 @@ The following pieces of information are required to prepare the environment:
- The number of VMs/Cinder volumes to create
- The Glance image that holds the VM operating system to use. StorPerf has
only been tested with Ubuntu 16.04
+- The OpenStack flavor to use when creating the VMs
- The name of the public network that agents will use
- The size, in gigabytes, of the Cinder volumes to create
@@ -49,6 +50,7 @@ takes a JSON payload as follows.
{
"agent_count": int,
+ "agent_flavor": string
"agent_image": string,
"public_network": string,
"volume_size": int
diff --git a/rest_server.py b/rest_server.py
index 67d71a5..f2ee815 100644
--- a/rest_server.py
+++ b/rest_server.py
@@ -12,14 +12,13 @@ import logging.config
import os
import sys
-from flask import abort, Flask, request, jsonify, send_from_directory
+from flask import abort, Flask, request, jsonify
from flask_restful import Resource, Api, fields
from flask_restful_swagger import swagger
from flask_cors import CORS
from storperf.storperf_master import StorPerfMaster
-
app = Flask(__name__, static_url_path="")
CORS(app)
api = swagger.docs(Api(app), apiVersion='1.0')
@@ -31,6 +30,7 @@ storperf = StorPerfMaster()
class ConfigurationRequestModel:
resource_fields = {
'agent_count': fields.Integer,
+ 'agent_flavor': fields.String,
'agent_image': fields.String,
'public_network': fields.String,
'volume_size': fields.Integer
@@ -41,6 +41,7 @@ class ConfigurationRequestModel:
class ConfigurationResponseModel:
resource_fields = {
'agent_count': fields.Integer,
+ 'agent_flavor': fields.String,
'agent_image': fields.String,
'public_network': fields.String,
'stack_created': fields.Boolean,
@@ -62,6 +63,7 @@ class Configure(Resource):
)
def get(self):
return jsonify({'agent_count': storperf.agent_count,
+ 'agent_flavor': storperf.agent_flavor,
'agent_image': storperf.agent_image,
'public_network': storperf.public_network,
'volume_size': storperf.volume_size,
@@ -70,7 +72,7 @@ class Configure(Resource):
@swagger.operation(
notes='''Set the current agent configuration and create a stack in
- the controller. Returns once the stack request is submitted.''',
+ the controller. Returns once the stack create is completed.''',
parameters=[
{
"name": "configuration",
@@ -92,6 +94,8 @@ class Configure(Resource):
try:
if ('agent_count' in request.json):
storperf.agent_count = request.json['agent_count']
+ if ('agent_flavor' in request.json):
+ storperf.agent_flavor = request.json['agent_flavor']
if ('agent_image' in request.json):
storperf.agent_image = request.json['agent_image']
if ('public_network' in request.json):
@@ -100,8 +104,11 @@ class Configure(Resource):
storperf.volume_size = request.json['volume_size']
storperf.create_stack()
+ if storperf.stack_id is None:
+ abort(400, "Stack creation failed")
return jsonify({'agent_count': storperf.agent_count,
+ 'agent_flavor': storperf.agent_flavor,
'agent_image': storperf.agent_image,
'public_network': storperf.public_network,
'volume_size': storperf.volume_size,
@@ -159,11 +166,11 @@ class Job(Resource):
"paramType": "query"
},
{
- "name": "type",
- "description": "The type of metrics to report. May be "
+ "name": "metrics_type",
+ "description": "The metrics_type of metrics to report. May be "
"metrics (default), or metadata",
"required": False,
- "type": "string",
+ "metrics_type": "string",
"allowMultiple": False,
"paramType": "query"
}
@@ -181,19 +188,19 @@ class Job(Resource):
)
def get(self):
- type = "metrics"
+ metrics_type = "metrics"
if request.args.get('type'):
- type = request.args.get('type')
+ metrics_type = request.args.get('type')
workload_id = request.args.get('id')
- if type == "metrics":
+ if metrics_type == "metrics":
return jsonify(storperf.fetch_results(workload_id))
- if type == "metadata":
+ if metrics_type == "metadata":
return jsonify(storperf.fetch_metadata(workload_id))
- if type == "status":
+ if metrics_type == "status":
return jsonify(storperf.fetch_job_status(workload_id))
@swagger.operation(
@@ -332,4 +339,4 @@ if __name__ == "__main__":
setup_logging()
logging.getLogger("storperf").setLevel(logging.DEBUG)
- app.run(host='0.0.0.0', debug=True)
+ app.run(host='0.0.0.0', debug=True, threaded=True)
diff --git a/storperf/resources/hot/agent-group.yaml b/storperf/resources/hot/agent-group.yaml
index a06c847..c758ecd 100644
--- a/storperf/resources/hot/agent-group.yaml
+++ b/storperf/resources/hot/agent-group.yaml
@@ -14,7 +14,7 @@ parameters:
type: string
constraints:
- custom_constraint: neutron.network
- flavor:
+ agent_flavor:
type: string
default: "storperf"
agent_image:
@@ -47,7 +47,7 @@ resources:
properties: {
public_network: {get_param: public_network},
agent_network: {get_resource: storperf_network},
- flavor: {get_param: flavor},
+ flavor: {get_param: agent_flavor},
image: {get_param: agent_image},
storperf_open_security_group: {get_resource: storperf_open_security_group},
key_name: {get_resource: storperf_key_pair},
diff --git a/storperf/storperf_master.py b/storperf/storperf_master.py
index 5432ece..fb3e269 100644
--- a/storperf/storperf_master.py
+++ b/storperf/storperf_master.py
@@ -138,6 +138,23 @@ class StorPerfMaster(object):
value)
@property
+ def agent_flavor(self):
+ return self.configuration_db.get_configuration_value(
+ 'stack',
+ 'agent_flavor')
+
+ @agent_flavor.setter
+ def agent_flavor(self, value):
+ if (self.stack_id is not None):
+ raise ParameterError(
+ "ERROR: Cannot change flavor after stack is created")
+
+ self.configuration_db.set_configuration_value(
+ 'stack',
+ 'agent_flavor',
+ value)
+
+ @property
def stack_id(self):
return self.configuration_db.get_configuration_value(
'stack',
@@ -380,6 +397,7 @@ class StorPerfMaster(object):
heat_parameters['agent_count'] = self.agent_count
heat_parameters['volume_size'] = self.volume_size
heat_parameters['agent_image'] = self.agent_image
+ heat_parameters['agent_flavor'] = self.agent_flavor
return heat_parameters
def _attach_to_openstack(self):
diff --git a/tests/db_tests/configuration_db_test.py b/tests/db_tests/configuration_db_test.py
index e8b7188..dda616b 100644
--- a/tests/db_tests/configuration_db_test.py
+++ b/tests/db_tests/configuration_db_test.py
@@ -10,17 +10,14 @@
from storperf.db.configuration_db import ConfigurationDB
import os
import unittest
+import sqlite3
class ConfigurationDBTest(unittest.TestCase):
def setUp(self):
- ConfigurationDB.db_name = __name__ + ".db"
- try:
- os.remove(ConfigurationDB.db_name)
- except OSError:
- pass
-
+ ConfigurationDB.db_name = "file::memory:?cache=shared"
+ db = sqlite3.connect(ConfigurationDB.db_name)
self.config_db = ConfigurationDB()
def test_create_key(self):
diff --git a/tests/storperf_master_test.py b/tests/storperf_master_test.py
index 2dc810d..c67e3c4 100644
--- a/tests/storperf_master_test.py
+++ b/tests/storperf_master_test.py
@@ -9,18 +9,15 @@
from storperf.db.configuration_db import ConfigurationDB
from storperf.storperf_master import StorPerfMaster
-import os
import unittest
+import sqlite3
class StorPerfMasterTest(unittest.TestCase):
def setUp(self):
- ConfigurationDB.db_name = __name__ + ".db"
- try:
- os.remove(ConfigurationDB.db_name)
- except OSError:
- pass
+ ConfigurationDB.db_name = "file::memory:?cache=shared"
+ db = sqlite3.connect(ConfigurationDB.db_name)
self.storperf = StorPerfMaster()
def test_agent_count(self):
@@ -67,3 +64,12 @@ class StorPerfMasterTest(unittest.TestCase):
self.assertEqual(
expected, actual, "Did not expect: " + str(actual))
+
+ def test_agent_flavor(self):
+ expected = "m1.small"
+
+ self.storperf.agent_flavor = expected
+ actual = self.storperf.agent_flavor
+
+ self.assertEqual(
+ expected, actual, "Did not expect: " + str(actual))