Adding resources creation and other helper scripts

 - prepare.sh
   Create all manner of resources needed for testing
   Also, creating manifest with all names and IDs for future use
   Automated detect, download and create of images
   cirros35, cirros40, ubuntu16

 - add_user_to_image.sh
   Semi-manual script to add user to ubuntu image
 - entropy_bench.pl
   Benchmark entropy levels on host
 - poke.sh
   direct curl to project resource using token
 - profiled_run.sh
   Execute any command several time or one and calculate avg time
 - simple_profile.sh
   Execute resource listings and calculate avg time

Fixes for cleanup.sh
 - container deletion
 - cleaning flavors
 - mask now cleans all with 'cvp' too

Change-Id: I073857abc2fbee730b983b1d8655e0fa16fee3fc
Related-PROD: PROD-30951
diff --git a/cleanup.sh b/cleanup.sh
index 6b295a0..897cee3 100644
--- a/cleanup.sh
+++ b/cleanup.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 export OS_INTERFACE='admin'
-mask='s_rally\|rally_\|tempest_\|tempest-'
+mask='cvp\|s_rally\|rally_\|tempest_\|tempest-'
 stack_alt=false
 stack_regex='api-[0-9]+-[a-z]+'
 dry_run=false
@@ -282,12 +282,19 @@
 
 ### Containers
 function _clean_containers {
-    containers=( $(openstack container list --all -c ID -c Name -f value | grep ${mask}) )
+    containers=( $(openstack container list --all -c ID -c Name -f value | grep ${mask} | cut -d' ' -f1) )
     echo "-> ${#containers[@]} containers containing '${mask}' found"
     printf "%s\n" ${containers[@]} | xargs -I{} echo container delete {} >>${cmds}
     _clean_and_flush
 }
 
+function _clean_flavors {
+    flavors=( $(openstack flavor list --all -c ID -c Name -f value | grep ${mask} | cut -d' ' -f1) )
+    echo "-> ${#flavors[@]} flavors containing '${mask}' found"
+    printf "%s\n" ${flavors[@]} | xargs -I{} echo flavor delete {} >>${cmds}
+    _clean_and_flush
+}
+
 ###################
 ### Main
 ###################
diff --git a/scripts/add_user_to_image.sh b/scripts/add_user_to_image.sh
new file mode 100644
index 0000000..cf72d2c
--- /dev/null
+++ b/scripts/add_user_to_image.sh
@@ -0,0 +1,31 @@
+# package
+apt-get install qemu-utils
+
+#image
+wget https://cloud-images.ubuntu.com/releases/14.04.1/release/ubuntu-14.04-server-cloudimg-amd64-disk1.img
+
+# adding module
+modprobe nbd
+dmesg | grep nbd
+
+# mapping it
+qemu-nbd --connect=/dev/nbd0 /home/osavatieiev/ubuntu-14.04-server-cloudimg-amd64-disk1.img
+blockdev --rereadpt /dev/nbd0
+mkdir /mnt/target_vm
+mount /dev/nbd0p1 /mnt/target_vm
+
+# download iperf just in case
+wget http://archive.ubuntu.com/ubuntu/pool/universe/i/iperf/iperf_2.0.5-3_amd64.deb
+cp iperf_2.0.5-3_amd64.deb /mnt/vm/tmp/
+
+chroot /mnt/target_vm/
+
+# add user
+adduser spt
+usermod -aG sudo spt
+dpkg -i /tmp/iperf_2.0.5-3_amd64.deb
+
+# ctrl + D
+# disconect
+umount /mnt/target_vm
+qemu-nbd --disconnect /dev/nbd0
\ No newline at end of file
diff --git a/cleanup_old.sh b/scripts/cleanup_old.sh
similarity index 100%
rename from cleanup_old.sh
rename to scripts/cleanup_old.sh
diff --git a/scripts/entropy_bench.pl b/scripts/entropy_bench.pl
new file mode 100755
index 0000000..a8f6bd0
--- /dev/null
+++ b/scripts/entropy_bench.pl
@@ -0,0 +1,152 @@
+#!/usr/bin/perl
+
+eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
+    if 0; # not running under some shell
+# $Id: entropy-random-bench,v 1.7 2014/11/27 21:58:22 dpchrist Exp $
+#######################################################################
+# Argument defaults -- edit to suit:
+
+my $entropy             = '/proc/sys/kernel/random/entropy_avail';
+my $random              = '/dev/urandom';
+my $duration            =   60.0;       # seconds
+my $entropy_upper       = 4095;         # bits
+my $entropy_lower       =    0;         # bits
+my $nap_upper           =   10.0;       # seconds
+my $nap_lower           =    1.0E-06;   # seconds
+my $gain                =   10.0;       # seconds / bit
+
+#######################################################################
+# The rest of the script should not be edited:
+
+use strict;
+use warnings;
+
+use Getopt::Long                qw(
+                                    :config
+                                    auto_help
+                                    auto_version
+                                );
+use Pod::Usage;
+use Time::HiRes         qw( sleep time );
+
+$| = 1;
+
+our $VERSION    = sprintf("%d.%03d", q$Revision: 1.7 $ =~ /(\d+)/g);
+my $man;
+
+GetOptions(
+    "entropy=s"         => \$entropy,
+    "random=s"          => \$random,
+    "duration=f"        => \$duration,
+    "entropy-upper=f"   => \$entropy_upper,
+    "entropy-lower=f"   => \$entropy_lower,
+    "nap-upper=f"       => \$nap_upper,
+    "nap-lower=f"       => \$nap_lower,
+    "gain=f"            => \$gain,
+    "man"               => \$man,
+) or pod2usage(2);
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+my $entropy_span        = $entropy_upper - $entropy_lower;
+my $entropy_setpoint    = $entropy_upper / 2;
+my $nap_span            = $nap_upper - $nap_lower;
+my $nap_offset          = $nap_upper / 2;
+
+my $err;
+my $buf;
+my $e1;
+my $e2;
+my $t1;
+my $t2;
+my $rate;
+my $dt;
+my $signal;
+my $nap                 = $nap_lower;
+my $lastprint;
+
+open(my $random_fh, $random) or die "error opening $random: $!";
+$err = sysread($random_fh, $buf, 1);
+die "error reading $random: $!" unless defined $err && $err;
+
+### /proc/sys/kernel/random/entropy_avail is not world-readable, but
+### 'cat' can read it (?)
+$e1 = `cat $entropy`;
+chomp $e1;
+
+print "time (seconds)  entropy (bits)  random (bytes/second)\n",
+      "==============  ==============  ======================\n";
+my $begin = $lastprint = $t1 = time();
+my $end = $begin + $duration;
+do {
+    sleep($nap);
+
+    $err = sysread($random_fh, $buf, 1);
+    die "error reading $random: $!" unless defined $err;
+
+    $e2 = `cat $entropy`;
+    chomp $e2;
+
+    $t2 = time();
+    $dt = $t2 - $t1;
+    $rate = 1.0 / $dt;
+    if ($dt && ($lastprint + 1 < $t2)) {
+        $lastprint = $t2;
+        printf "%14.06f  %14i  %22.6f\n",
+            $t2 - $begin,
+            $e2,
+            $rate;
+    }
+    $signal = ($e2 - $entropy_setpoint) / $entropy_span;
+    $nap = -1.0 * $gain * $signal * $nap_span + $nap_offset;
+    $nap = $nap_lower if $nap       < $nap_lower;
+    $nap = $nap_upper if $nap_upper < $nap;
+    $e1 = $e2;
+    $t1 = $t2;
+} while ($t2 < $end);
+DONE:
+
+__END__
+
+=head1 NAME
+
+entropy-random-bench - Linux entropy pool / random number benchmark
+
+=head1 SYNOPSIS
+
+ entropy-random-bench.pl [options]
+
+  Options:
+   --entropy                    path to entropy availble file
+   --random                     path to random number file
+   --duration                   duration of benchmark
+   --entropy-upper              upper range value of entropy available
+   --entropy-lower              lower range value of entropy available
+   --nap-upper                  upper range value for sleep() calls
+   --nap-lower                  upper range value for sleep() calls
+   --gain                       timing loop proportional gain
+   --man                        print manual page and exit
+   --help, -?                   print usage message and exit
+
+=head1 DESCRIPTION
+
+Interactive benchmark for Linux entropy pool
+and random number generator.
+
+$Revision: 1.7 $
+
+=head1 SEE ALSO
+
+=head1 AUTHOR
+
+David Paul Christensen, E<lt>dpchrist@holgerdanske.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2014 by David Paul Christensen
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.14.2 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut
+
diff --git a/scripts/poke.sh b/scripts/poke.sh
new file mode 100755
index 0000000..70920b9
--- /dev/null
+++ b/scripts/poke.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+if [[ -z ${token+x} ]]; then
+    export token=$(openstack token issue -c id -f value)
+    echo "# Exported token: ${token}"
+fi
+if [[ -z ${project_id+x} ]]; then
+    export project_id=$(openstack project list -c ID -c Name -f value | grep ${OS_PROJECT_NAME} | cut -d' ' -f1)
+    echo "# Exported project_id: ${project_id}"
+fi
+poke_uri=$(echo ${1/project_id/$project_id})
+echo "# Input uri is ${1}"
+echo "[$(date +'%H:%M:%S')] -> '${poke_uri}'"
+curl -sH "X-Auth-Token: ${token}" ${poke_uri} | python -m json.tool
diff --git a/scripts/prepare.sh b/scripts/prepare.sh
new file mode 100644
index 0000000..aba32f8
--- /dev/null
+++ b/scripts/prepare.sh
@@ -0,0 +1,336 @@
+#!/bin/bash
+export OS_INTERFACE='admin'
+
+# local vars
+name_prefix=cvp
+filename=${name_prefix}.manifest
+huge_pages=false
+
+# Project, User, Roles
+project=${name_prefix}.project
+user=${name_prefix}.user
+admin=${name_prefix}.admin
+password=mcp1234
+
+# Security group
+sg_all=${name_prefix}.sg.all
+sg_icmp=${name_prefix}.sg.icmp
+sg_ssh=${name_prefix}.sg.ssh
+sg_iperf=${name_prefix}.sg.perf
+
+# Testkey
+key=${name_prefix}_testkey
+
+# Flavors: tiny, small (cirrus and migration), medium (ubuntu and volume/stress activities)
+flavor_t=${name_prefix}.tiny
+flavor_s=${name_prefix}.small
+flavor_m=${name_prefix}.medium
+
+# Fixed Networks (2, for testing router interconnection)
+net_left=${name_prefix}.net.1
+net_right=${name_prefix}.net.2
+subnet1=${name_prefix}.subnet.1
+subnet2=${name_prefix}.subnet.2
+
+# Router
+router=${name_prefix}.router
+
+# Images: cirros (3.5, 4.0), ubuntu (16.04)
+cirros3=${name_prefix}.cirros.35
+cirros4=${name_prefix}.cirros.40
+ubuntu16=${name_prefix}.ubuntu.1604
+
+cirros3_link=http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img
+cirros4_link=http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-aarch64-disk.img
+ubuntu16_link=https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img
+
+# Volume (2GB)
+volume=${name_prefix}.volume
+
+function show_help {
+    printf "CVP Pipeline: Resource creation script\n\t-h, -?\t\tShow this help\n"
+    printf "\t-H\t\tAdds '--property hw:mem_page_size=large' to flavors, i.e. huge_pages for DPDK\n"
+    printf "\t-w <path>\tSets working folder"
+}
+
+OPTIND=1 # Reset in case getopts has been used previously in the shell.
+while getopts "h?:Hw:" opt; do
+    case "$opt" in
+    h|\?)
+        show_help
+        exit 0
+        ;;
+    w)  working_folder=${OPTARG}
+        printf "# Working folder is ${working_folder}\n"
+        ;;
+    h)  huge_pages=true
+        printf "# Using 'huge_pages' property in flavors\n"
+        ;;
+    esac
+done
+
+shift $((OPTIND-1))
+[ "${1:-}" = "--" ] && shift
+
+function put() {
+    echo "$1=$2" | tee -a ${filename}
+}
+
+# now, some hard to understand stuff...
+# f1 $(<command with output to cut>)
+function f1() { echo $1 | cut -d' ' -f1; };
+# <commands with output to cut> | p1
+function p1() { while read input; do echo ${input} | cut -d' ' -f1; done; };
+# ol1 is short for openstack list with 1 param. Also grep and cut
+# "ol1 network public" will list all networks, grep by name public and return IDs
+function ol1() { echo $(openstack $1 list -c ID -c Name -f value | grep $2 | cut -d' ' -f1); }
+# same as ol1 but with 2 initial commands before list
+function ol2() { echo $(openstack $1 $2 list -c ID -c Name -f value | grep $3 | cut -d' ' -f1); }
+
+function print_manifest() {
+    touch ./${filename}
+    truncate -s 0 ${filename}
+    printf "\n# Checking and filling manifest: $(pwd)/${filename}\n"
+    put project_id $(ol1 project ${project})
+    put user_name ${user}
+    put user_id $(ol1 user ${user})
+    put admin_name ${admin}
+    put admin_id $(ol1 user ${admin})
+    # sg
+    put secgroup_all_name ${sg_all}
+    put secgroup_all_id $(ol2 security group ${sg_all})
+    put secgroup_icmp_name ${sg_icmp}
+    put secgroup_icmp_id $(ol2 security group ${sg_icmp})
+    put secgroup_ssh_name ${sg_ssh}
+    put secgroup_ssh_id $(ol2 security group ${sg_ssh})
+    put secgroup_iperf_name ${sg_iperf}
+    put secgroup_iperf_id $(ol2 security group ${sg_iperf})
+
+    # keypair
+    put keypair_name ${key}
+    put keypair_id $(ol1 keypair ${key})
+
+    # flavors
+    put flavor_tiny_name ${flavor_t}
+    put flavor_tiny_id $(ol1 flavor ${flavor_t})
+    put flavor_small_name ${flavor_s}
+    put flavor_small_id $(ol1 flavor ${flavor_s})
+    put flavor_medium_name ${flavor_m}
+    put flavor_medium_id $(ol1 flavor ${flavor_m})
+
+    # fixed nets
+    put fixed_net_left_name ${net_left}
+    put fixed_net_left_id $(ol1 network ${net_left})
+    put fixed_net_right_name ${net_right}
+    put fixed_net_right_id $(ol1 network ${net_right})
+    put fixed_net_left_subnet_name ${subnet1}
+    put fixed_net_left_subnet_id $(openstack subnet list --network ${net_left} -c ID -f value | p1)
+    put fixed_net_right_subnet_name ${subnet2}
+    put fixed_net_right_subnet_id $(openstack subnet list --network ${net_right} -c ID -f value | p1)
+
+    # router
+    put router_name ${router}
+    put router_id $(ol1 router ${router})
+
+    # volumes
+    put volume_name ${volume}
+    put volume_id $(ol1 volume ${volume})
+
+    # images
+    put cirros35_name ${cirros3}
+    put cirros35_id $(ol1 image ${cirros3})
+    put cirros40_name ${cirros4}
+    put cirros40_id $(ol1 image ${cirros4})
+    put ubuntu16_name ${cirros3}
+    put ubuntu16_id $(ol1 image ${ubuntu16})
+}
+
+function process_cmds() {
+    if [ -s ${cmds} ]; then
+        cat ${cmds} | tr '\n' '\0' | xargs -P 1 -n 1 -0 echo | tee /dev/tty | openstack >/dev/nul
+        truncate -s 0 ${cmds}
+    fi
+}
+
+function _project() {
+    echo project create --description \"CVP Pipeline project\" ${project} >>${cmds}
+    echo role add --user admin --project ${project} admin >>${cmds}
+}
+
+function _users() {
+    echo user create --project ${project} --password ${password} ${user} >>${cmds}
+    echo user create --project ${project} --password ${password} ${admin} >>${cmds}
+    echo role add --user ${admin} --project ${project} admin >>${cmds}
+}
+
+function _sg_all() {
+    echo security group create --project ${project} --description \"ICMP, SSH, iPerf, HTTP\" ${sg_all} >>${cmds}
+    # icmp
+    echo security group rule create --protocol icmp ${sg_all} >>${cmds}
+    # ssh
+    echo security group rule create --protocol tcp --dst-port 22 ${sg_all} >>${cmds}
+    # iperf
+    echo security group rule create --protocol tcp --dst-port 5001 ${sg_all} >>${cmds}
+    # iperf3
+    echo security group rule create --protocol tcp --dst-port 5201 ${sg_all} >>${cmds}
+    # nc connectivity
+    echo security group rule create --protocol tcp --dst-port 3000 ${sg_all} >>${cmds}
+    # http
+    echo security group rule create --protocol tcp --dst-port 80 ${sg_all} >>${cmds}
+}
+
+function _sg_icmp() {
+    echo security group create --project ${project} --description \"ICMP\" ${sg_icmp} >>${cmds}
+    echo security group rule create --protocol icmp ${sg_icmp} >>${cmds}
+}
+
+function _sg_ssh() {
+    echo security group create --project ${project} --description \"ICMP, SSH\" ${sg_ssh} >>${cmds}
+    # icmp
+    echo security group rule create --protocol icmp ${sg_ssh} >>${cmds}
+    # ssh
+    echo security group rule create --protocol tcp --dst-port 22 ${sg_ssh} >>${cmds}
+}
+
+function _sg_iperf() {
+    echo security group create --project ${project} --description \"ICMP, iPerf\" ${sg_iperf} >>${cmds}
+    # icmp
+    echo security group rule create --protocol icmp ${sg_iperf} >>${cmds}
+    # iperf
+    echo security group rule create --protocol tcp --dst-port 5001 ${sg_iperf} >>${cmds}
+    # iperf3
+    echo security group rule create --protocol tcp --dst-port 5201 ${sg_iperf} >>${cmds}
+}
+
+function create_keypair() {
+    echo "# Creating keypair"
+    openstack keypair create ${key} >${key}
+    chmod 600 ${key}
+    echo "-> created keyfile: $(pwd)/${key}"
+}
+
+function _flavors() {
+    # huge paged flavors
+    if [ "$huge_pages" = true ]; then
+        echo flavor create --id 1 --ram 64 --disk 1 --vcpus 1 ${flavor_t} --property hw:mem_page_size=large >>${cmds}
+        echo flavor create --id 1 --ram 256 --disk 2 --vcpus 1 ${flavor_s} --property hw:mem_page_size=large >>${cmds}
+        echo flavor create --id 1 --ram 2048 --disk 5 --vcpus 2 ${flavor_m} --property hw:mem_page_size=large >>${cmds}
+    else
+        echo flavor create --ram 64 --disk 1 --vcpus 1 ${flavor_t} >>${cmds}
+        echo flavor create --ram 256 --disk 2 --vcpus 1 ${flavor_s} >>${cmds}
+        echo flavor create --ram 2048 --disk 5 --vcpus 2 ${flavor_m} >>${cmds}
+    fi
+}
+
+function _volumes() {
+    echo volume create --size 2 ${volume} >>${cmds}
+}
+
+function create_fixed_nets() {
+    echo "# Creating fixed networks"
+    echo network create --project ${project} ${net_left} >>${cmds}
+    echo subnet create ${subnet1} --network ${net_left} --subnet-range 10.10.11.0/24 >>${cmds}
+    echo network set --share ${net_left} >>${cmds}
+    echo network create --project ${project} ${net_right} >>${cmds}
+    echo subnet create ${subnet2} --network ${net_right} --subnet-range 10.10.12.0/24 >>${cmds}
+    echo network set --share ${net_right} >>${cmds}
+    process_cmds
+
+    # get subnet ids
+    subnet1_id=$(openstack subnet list --network ${net_left} -c ID -f value)
+    subnet2_id=$(openstack subnet list --network ${net_right} -c ID -f value)
+
+    echo router create --project ${project} ${router} >>${cmds}
+    process_cmds
+
+    router_id=$(openstack router list -c ID -c Name -f value | grep ${router} | cut -d' ' -f1)
+    echo router add subnet ${router_id} ${subnet1_id} >>${cmds}
+    echo router add subnet ${router_id} ${subnet2_id} >>${cmds}
+    process_cmds
+
+    # TODO: Search for external net
+    external=ext-net
+    echo router set ${router} --external-gateway ${external} >>${cmds}
+    process_cmds
+}
+
+function _get_image() {
+    # build vars for name and link
+    name="${1}"
+    link="${1}_link"
+    which wget >/dev/nul
+    if [ $? -ne 0 ]; then
+        printf "\nERROR: 'wget' not detected. Download skipped: ${!name}\n"
+    else
+        # no redownloads, quet, save named and show progress
+        r=$(wget --no-check-certificate -nc -q -O ./${!name} --show-progress ${!link})
+        if [ $? -ne 0 ]; then
+            # non-empty output on error
+            echo ${r}
+        fi
+    fi
+}
+
+function create_image() {
+    name="${1}"
+    # Check if image is in the cloud
+    echo "# Checking image '${!name}'"
+    ids=( $(ol1 image ${!name}) )
+    # if array is not empty, download and upload it
+    if [ ${#ids[@]} -eq 0 ]; then
+        # check and download
+        if [ ! -f ${!name} ]; then
+            r=$(_get_image ${1})
+        else
+            r=""
+        fi
+        # check if output is not empty
+        if [ ${#r} -eq 0 ]; then
+            image_id=$(openstack image create --public --disk-format qcow2 --container-format bare --file ${!name} ${!name} -c id -f value)
+            echo "-> created ${!name} (${image_id})"
+        else
+            printf "\n-> Error detected, creation skipped\n"
+        fi
+    else
+        # image(s) already there, list them
+        for id in ${ids[@]}; do
+            echo "-> found ${!name} with ID of '${id}'"
+        done
+    fi
+}
+
+###################
+### Main
+###################
+if [[ -z ${working_folder+x} ]]; then
+    # cwd into working dir
+    cd ${working_folder}
+fi
+
+cmds=$(mktemp)
+trap "rm -f ${cmds}" EXIT
+echo "Using tempfile: '${cmds}'"
+
+# not dependent stuff
+echo "# Creating basic resources"
+_project
+_users
+_sg_all
+_sg_icmp
+_sg_ssh
+_sg_iperf
+_flavors
+_volumes
+process_cmds
+
+# sphisticated, step dependent stuff
+create_keypair
+create_fixed_nets
+
+# images
+create_image cirros3
+create_image cirros4
+create_image ubuntu16
+
+### Manifest
+print_manifest
diff --git a/scripts/profiled_run.sh b/scripts/profiled_run.sh
new file mode 100755
index 0000000..f88362c
--- /dev/null
+++ b/scripts/profiled_run.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+function help_and_exit {
+    echo "profiled_run.sh <command>"
+    exit 1
+}
+
+#if [ -z ${1+x} ]; then echo "First parameter should be command to run"; help_and_exit; fi
+#if [ -z ${2+x} ]; then echo "Second parameter should be count of time to run"; help_and_exit; fi
+total=${2}
+count=1
+cmd="${1}"
+
+declare all_req=()
+declare errors=()
+tmp_time=$(mktemp)
+tmp_out=$(mktemp)
+
+function timed_run {
+        if [ -z ${2+x} ]; then
+                echo "--> '${1}'"
+                /usr/bin/time --quiet -f'%e %x' -o ${tmp_time} /bin/bash -c "${1}" 1>/dev/null 2>${tmp_out}
+                real=$(cat ${tmp_time} | awk '{print $1}')
+                errlevel=$(cat ${tmp_time} | awk '{print $2}')
+                if [ 0 -eq ${errlevel} ]; then
+                        echo "#${count}(${real}s), '${1:0:12}...'";
+                        all_req+=("#${count}, ${real}, '${1}'");
+                else
+                        echo "#${count}, ERROR(${errlevel}): '${1}'"
+                        errors+=("#${count}: $(cat ${tmp_out})")
+                fi
+                ((count++))
+        else
+                echo "### Running '${1:0:12}...' ${2} times"
+                for (( idx=1; idx<=${2}; idx++ ))
+                do
+                        /usr/bin/time --quiet -f'%e %x' -o ${tmp_time} /bin/bash -c "${1}" 1>/dev/null 2>${tmp_out}
+                        real=$(cat ${tmp_time} | awk '{print $1}')
+                        errlevel=$(cat ${tmp_time} | awk '{print $2}')
+                        if [ 0 -eq ${errlevel} ]; then
+                                echo "#${count}/${total}, ${real}s";
+                                all_req+=("#${count}/${idx}, ${real}, '${1}'");
+                        else
+                                echo "#${count}/${total}, ERROR(${errlevel}): '${1}'"
+                                errors+=("#${count}: $(cat ${tmp_out})")
+                        fi
+                        ((count++))
+                done
+        fi
+}
+
+function errors {
+        echo "==== Errors"
+        for i in "${!errors[@]}"; do
+                printf "#%s\n\n" "${errors[$i]}"
+        done
+}
+
+function stats {
+        echo "==== Stats"
+        printf '%s\n' "${all_req[@]}" | awk 'BEGIN{min=999;avg=0}
+        {if($2<min){min=$2;}if($2>max){max=$2;}avg+=$2;}
+        END { print "Total requests: "NR", Timings: "min" <-- "avg/NR" --> "max;}'
+}
+
+function clean {
+        rm ${tmp_time}
+        rm ${tmp_out}
+}
+
+timed_run "${cmd}" ${total}
+stats
+errors
+clean
\ No newline at end of file
diff --git a/scripts/simple_profile.sh b/scripts/simple_profile.sh
new file mode 100755
index 0000000..c097ae9
--- /dev/null
+++ b/scripts/simple_profile.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+
+function help_and_exit {
+    echo "simple_profile.sh <repeat_count>"
+    exit 1
+}
+
+#if [ -z ${1+x} ]; then echo "First parameter should be total count of the requests"; help_and_exit; fi
+count=1
+declare all_req=()
+declare errors=()
+tmp_time=$(mktemp)
+tmp_out=$(mktemp)
+
+function profiled_run {
+        if [ -z ${2+x} ]; then
+                /usr/bin/time --quiet -f'%e %x' -o ${tmp_time} ${1} 1>/dev/null 2>${tmp_out}
+                real=$(cat ${tmp_time} | awk '{print $1}')
+                errlevel=$(cat ${tmp_time} | awk '{print $2}')
+                if [ 0 -eq ${errlevel} ]; then
+                        echo "#${count}(${real}s), '${1}'";
+                        all_req+=("#${count}, ${real}, '${1}'");
+                else
+                        echo "#${count}, ERROR(${errlevel}): '${1}'"
+                        errors+=("#${count}: $(cat ${tmp_out})")
+                fi
+                ((count++))
+        else
+                echo "### Running '${1}' ${2} times"
+                for (( idx=1; idx<=${2}; idx++ ))
+                do
+                        /usr/bin/time --quiet -f'%e %x' -o ${tmp_time} ${1} 1>/dev/null 2>${tmp_out}
+                        real=$(cat ${tmp_time} | awk '{print $1}')
+                        errlevel=$(cat ${tmp_time} | awk '{print $2}')
+                        if [ 0 -eq ${errlevel} ]; then
+                                echo "#${count}/${idx}, ${real}s";
+                                all_req+=("#${count}/${idx}, ${real}, '${1}'");
+                        else
+                                echo "#${count}/${idx}, ERROR(${errlevel}): '${1}'"
+                                errors+=("#${count}: $(cat ${tmp_out})")
+                        fi
+                        ((count++))
+                done
+        fi
+}
+
+function errors {
+        echo "==== Errors"
+        for i in "${!errors[@]}"; do
+                printf "#%s\n\n" "${errors[$i]}"
+        done
+}
+
+function stats {
+        echo "==== Stats"
+        printf '%s\n' "${all_req[@]}" | awk 'BEGIN{min=999;avg=0}
+        {if($2<min){min=$2;}if($2>max){max=$2;}avg+=$2;}
+        END { print "Total requests: "NR", Timings: "min" <-- "avg/NR" --> "max;}'
+}
+
+function clean {
+        rm ${tmp_time}
+        rm ${tmp_out}
+}
+
+echo "===== Totals"
+echo "Total projects = $(openstack project list -f value -c ID | wc -l)"
+echo "Total networks = $(openstack network list -f value -c ID | wc -l)"
+echo "Total subnets = $(openstack subnet list -f value -c ID | wc -l)"
+echo "Total ports = $(openstack port list -f value -c ID | wc -l)"
+echo "Total servers = $(openstack server list --all-projects --limit -1 -f value -c ID | wc -l)"
+echo "Total images = $(openstack image list -f value -c ID | wc -l)"
+echo "===== Timings"
+openstack --timing project list
+openstack --timing network list
+openstack --timing subnet list
+openstack --timing port list
+openstack --timing server list
+openstack --timing image list
+
+echo "********"
+profiled_run "openstack network list" 10
+stats
+declare all_req=()
+echo "********"
+profiled_run "openstack project list" 10
+stats
+declare all_req=()
+echo "********"
+profiled_run "openstack server list --limit -1" 10
+stats
+declare all_req=()
+profiled_run "heat stack-list" 10
+stats
+declare all_req=()
+echo "********"
+profiled_run "heat resource-type-list" 10
+stats
+declare all_req=()
+echo "********"
+profiled_run "nova list --limit -1" 10
+stats
+declare all_req=()
+echo "********"
+profiled_run "glance image-list" 10
+echo "===================================="
+errors
+clean
\ No newline at end of file