Commit fdc33575 authored by Giorgos Korfiatis's avatar Giorgos Korfiatis Committed by Georgios D. Tsoukalas
Browse files

Automate the stress test for projects

parent 2cc68a6c
......@@ -414,6 +414,14 @@ def get_related_project_id(application_id):
except:
return None
def get_chain_of_application_id(application_id):
try:
app = ProjectApplication.objects.get(id=application_id)
chain = app.chain
return chain.chain
except:
return None
def get_project_by_id(project_id):
try:
return Project.objects.get(id=project_id)
......
......@@ -6,11 +6,5 @@ GRANT ALL PRIVILEGES ON DATABASE astakos_test TO tester;
Setup the database:
./setup.sh
Launch server:
./launch.sh
Initialize (the first time you set up the database):
./init.sh
In terminal 1: ./submit-and-approve.py 1 dummy
In terminal 2: ./join-and-leave.py 1 dummy
Run test:
./stress.py
#!/bin/sh
d=`dirname $0`
export SYNNEFO_SETTINGS_DIR=$d/settings
snf-manage astakos-load-service-resources
snf-manage user-add --active test@synnefo.org Tester Tester
snf-manage user-add --active test2@synnefo.org Tester2 Tester2
#!/usr/bin/env python
# Copyright 2013 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
import os
import sys
path = os.path.dirname(os.path.realpath(__file__))
os.environ['SYNNEFO_SETTINGS_DIR'] = path + '/settings'
os.environ['DJANGO_SETTINGS_MODULE'] = 'synnefo.settings'
from astakos.im.functions import get_project_by_name, get_project_by_id
from views import join, leave
USAGE = "usage: join-and-leave <user_id> <project_id or name>"
def main():
argv = sys.argv
argc = len(sys.argv)
if argc < 3:
raise AttributeError(USAGE)
try:
user_id = int(argv[1])
proj = argv[2]
except ValueError:
raise AttributeError(USAGE)
proj_id = resolve(proj)
join_and_leave(proj_id, user_id)
def resolve(proj):
if proj.isdigit():
return proj
else:
try:
return get_project_by_name(proj).id
except:
AttributeError(USAGE)
def join_and_leave(proj_id, user_id, times=20):
for i in range(times):
try:
print '%s: joining project %s' % (i, proj_id)
join(proj_id, user_id)
except Exception as e:
print e
try:
print '%s: leaving project %s' % (i, proj_id)
leave(proj_id, user_id)
except Exception as e:
print e
if __name__ == "__main__":
main()
#!/bin/bash
cwd=`dirname $0`
cd "$cwd"
export SYNNEFO_SETTINGS_DIR=./settings
HOST=127.0.0.1
pkill -f "runserver $HOST:8000"
pkill -f "runserver $HOST:8008"
snf-manage runserver $HOST:8000 &
snf-manage runserver $HOST:8008 &
#!/bin/sh
#!/bin/bash
d=`dirname $0`
export SYNNEFO_SETTINGS_DIR=$d/settings
snf-manage syncdb --noinput
snf-manage migrate
snf-manage flush --noinput
HOST=127.0.0.1
P1=8000
P2=8008
pkill -f "runserver $HOST:$P1"
pkill -f "runserver $HOST:$P2"
snf-manage runserver $HOST:$P1 &
snf-manage runserver $HOST:$P2 &
while true; do
nc -z -w 4 $HOST $P1
OUT=$?
if [ $OUT -eq 0 ]
then
nc -z -w 4 $HOST $P2
OUT=$?
if [ $OUT -eq 0 ]
then break
else sleep 0.1
fi
else sleep 0.1
fi
done
snf-manage astakos-load-service-resources
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2013 GRNET S.A. All rights reserved.
#
......@@ -35,80 +36,171 @@
import os
import sys
import random
import string
from optparse import OptionParser
from time import sleep
import threading
import datetime
from random import choice, randint
import logging
path = os.path.dirname(os.path.realpath(__file__))
os.environ['SYNNEFO_SETTINGS_DIR'] = path + '/settings'
os.environ['DJANGO_SETTINGS_MODULE'] = 'synnefo.settings'
from astakos.im.models import Chain, ProjectApplication, Project
from views import submit, approve
USAGE = "usage: submit-and-approve <user_id> <precursor id or name>"
from astakos.im.api.callpoint import AstakosCallpoint
from astakos.im.functions import get_chain_of_application_id
from views import submit, approve, join, leave
def main():
argv = sys.argv
argc = len(sys.argv)
if argc < 3:
raise AttributeError(USAGE)
try:
user_id = int(argv[1])
chain = argv[2]
except ValueError:
raise AttributeError(USAGE)
prec, name = resolve(chain)
submit_and_approve(name, user_id, prec)
def rand_name():
char_set = string.ascii_letters + string.digits
return ''.join(random.sample(char_set, 6))
def resolve_chain(chain):
state, project, app = chain.full_state()
if state not in Chain.PENDING_STATES and project is not None:
app = project.application
return app.id, app.name
else:
return app.id, app.name
def resolve(chain):
if chain is None:
return None, rand_name()
if chain.isdigit():
try:
chain = Chain.objects.get(chain=chain)
return resolve_chain(chain)
except:
raise AttributeError('there is no chain %s' % (chain,))
else:
try:
project = Project.objects.get(name=chain)
return resolve_chain(project.id)
except Project.DoesNotExist:
try:
apps = ProjectApplication.objects.filter(name=chain)
last = apps.order_by('-id')[0]
return last.id, chain
except:
return None, chain
def submit_and_approve(name, user_id, prec, times=20):
for i in range(times):
USERS = {}
PROJECTS = {}
def random_name():
alphabet = u'abcdef_123490αβγδεζ'
length = randint(1, 15)
return ''.join(choice(alphabet) for _ in xrange(length))
def random_email():
alphabet = u'abcdef_123490'
length = randint(1, 10)
first = ''.join(choice(alphabet) for _ in xrange(length))
alphabet = u'abcdef'
length = randint(2,4)
last = ''.join(choice(alphabet) for _ in xrange(length))
return first + '@' + last
def new_user():
email = random_email()
u = {'email': email,
'first_name': random_name(),
'last_name': random_name(),
'active': True,
}
c = AstakosCallpoint()
r = c.create_users((u,)).next()
return r.data['id'], email
def new_users(count):
for i in range(count):
uid, email = new_user()
USERS[uid] = email
class SubmitApproveT(threading.Thread):
def __init__(self, *args, **kwargs):
self.repeat = kwargs.pop('repeat', 1)
threading.Thread.__init__(self, *args, **kwargs)
def run(self):
owner = choice(USERS.keys())
p_name = random_name()
submit_and_approve(p_name, owner, None, self.repeat,
prefix=self.getName())
def submit_and_approve(name, user_id, prec, repeat, prefix=""):
if prefix:
prefix += ' '
for i in range(repeat):
try:
print '%s: submitting with precursor %s' % (i, prec)
now = datetime.datetime.now()
print '%s%s: submitting with precursor %s' % (prefix, now, prec)
app_id = submit(name, user_id, prec)
prec = app_id
except Exception as e:
raise e
print e
try:
print '%s: approving application %s' % (i, app_id)
now = datetime.datetime.now()
pid = get_chain_of_application_id(app_id)
print '%s%s: approving application %s of project %s' % (
prefix, now, app_id, pid)
approve(app_id)
PROJECTS[pid] = True
except Exception as e:
print e
class JoinLeaveT(threading.Thread):
def __init__(self, *args, **kwargs):
self.repeat = kwargs.pop('repeat', 1)
threading.Thread.__init__(self, *args, **kwargs)
def run(self):
owner = choice(USERS.keys())
while True:
projects = PROJECTS.keys()
if projects:
pid = choice(projects)
break
sleep(0.1)
join_and_leave(pid, owner, self.repeat, prefix=self.getName())
def join_and_leave(proj_id, user_id, repeat, prefix=""):
if prefix:
prefix += ' '
for i in range(repeat):
try:
now = datetime.datetime.now()
print '%s%s: user %s joining project %s' % (
prefix, now, user_id, proj_id)
join(proj_id, user_id)
except Exception as e:
print e
try:
now = datetime.datetime.now()
print '%s%s: user %s leaving project %s' % (
prefix, now, user_id, proj_id)
leave(proj_id, user_id)
except Exception as e:
raise e
print e
def test(users, projects, memb, repeat):
logging.basicConfig()
new_users(users)
for i in range(projects):
SubmitApproveT(repeat=repeat).start()
for i in range(memb):
JoinLeaveT(repeat=repeat).start()
def main():
parser = OptionParser()
parser.add_option('--users',
dest='users',
default=2,
help="Number of users (default=2)")
parser.add_option('--projects',
dest='projects',
default=2,
help="Number of projects (default=2)")
parser.add_option('--memb',
dest='memb',
default=2,
help="Number of membership requests (default=2)")
parser.add_option('--repeat',
dest='repeat',
default=20,
help="Number of iterations (default=20)")
(options, args) = parser.parse_args()
users = int(options.users)
projects = int(options.projects)
memb = int(options.memb)
repeat = int(options.repeat)
test(users, projects, memb, repeat)
if __name__ == "__main__":
main()
......@@ -36,14 +36,14 @@ from datetime import datetime, timedelta
from astakos.im.models import AstakosUser, PendingMembershipError
from astakos.im.functions import (join_project, leave_project,
submit_application, approve_application)
from astakos.im.project_xctx import project_transaction_context
from astakos.im.project_xctx import cmd_project_transaction_context
from astakos.im.retry_xctx import RetryException
@project_transaction_context(sync=True)
@cmd_project_transaction_context(sync=True)
def join(proj_id, user_id, ctx=None):
join_project(proj_id, user_id)
@project_transaction_context(sync=True)
@cmd_project_transaction_context(sync=True)
def leave(proj_id, user_id, ctx=None):
try:
leave_project(proj_id, user_id)
......@@ -51,7 +51,7 @@ def leave(proj_id, user_id, ctx=None):
print e
raise RetryException()
@project_transaction_context(sync=True)
@cmd_project_transaction_context(sync=True)
def submit(name, user_id, prec, ctx=None):
try:
owner = AstakosUser.objects.get(id=user_id)
......@@ -73,6 +73,6 @@ def submit(name, user_id, prec, ctx=None):
app = submit_application(data, request_user=owner)
return app.id
@project_transaction_context(sync=True)
@cmd_project_transaction_context(sync=True)
def approve(app_id, ctx=None):
approve_application(app_id)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment