Commit 50506c28 authored by Roque's avatar Roque

erp5-util-benchmark/scalability

First commit with all my changes in webrunner-testnode in order to run the benchmark suites using performance tester and runScalabilityTestSuite.
Full of logs, comments and hard-codes.
Cleanup code needed.
parent f9aaa614
# Specify user login/password used to run the tests. Note that there must be # Specify user login/password used to run the tests. Note that there must be
# the same number of users specified here *and* on the script command-line. # the same number of users specified here *and* on the script command-line.
user_tuple = tuple([('scalability_user_%i' % x, 'insecure') for x in range(0, 1000)])
#user_tuple = tuple([('scalability_user_%i' % x, 'insecure') for x in range(0, 1000)])
user_tuple = tuple([('zope', 'yiujrsvp') for x in range(0, 1)])
\ No newline at end of file
...@@ -82,7 +82,8 @@ def fillRelatedObjects(browser, result, name, maximum=1, actionName="", TMIN_SLE ...@@ -82,7 +82,8 @@ def fillRelatedObjects(browser, result, name, maximum=1, actionName="", TMIN_SLE
for i in range(0, iteration): for i in range(0, iteration):
line_number = random.randint(1,num_line) + 2 line_number = random.randint(1,num_line) + 2
# Check the box corresponding to line_number if not already checked # Check the box corresponding to line_number if not already checked
if browser.mainForm.getListboxControl(line_number=line_number, column_number=1).selected == False: #if browser.mainForm.getListboxControl(line_number=line_number, column_number=1).selected == False:
if browser.mainForm.getListboxControl(line_number=line_number, column_number=1).value == False:
browser.mainForm.getListboxControl(line_number=line_number, column_number=1).click() browser.mainForm.getListboxControl(line_number=line_number, column_number=1).click()
result('Submit '+actionName+' Relations', result('Submit '+actionName+' Relations',
browser.mainForm.submit(name='Base_callDialogMethod:method', browser.mainForm.submit(name='Base_callDialogMethod:method',
...@@ -124,4 +125,4 @@ def fillOneRelatedObjectSimplified(browser, name): ...@@ -124,4 +125,4 @@ def fillOneRelatedObjectSimplified(browser, name):
browser.mainForm.submit(name='Base_callDialogMethod:method') browser.mainForm.submit(name='Base_callDialogMethod:method')
# Check whether the changes have been successfully updated # Check whether the changes have been successfully updated
assert browser.getTransitionMessage() == 'Data updated.' assert browser.getTransitionMessage() == 'Data updated.'
\ No newline at end of file
...@@ -45,8 +45,10 @@ class PerformanceTester(object): ...@@ -45,8 +45,10 @@ class PerformanceTester(object):
if not namespace: if not namespace:
self._argument_namespace = self._parse_arguments(argparse.ArgumentParser( self._argument_namespace = self._parse_arguments(argparse.ArgumentParser(
description='Run ERP5 benchmarking suites.')) description='Run ERP5 benchmarking suites.'))
#print "INIT method. Arguments: " + str(self._argument_namespace)
else: else:
self._argument_namespace = namespace self._argument_namespace = namespace
#print "INIT method. Arguments: " + str(self._argument_namespace)
@staticmethod @staticmethod
def _add_parser_arguments(parser): def _add_parser_arguments(parser):
...@@ -166,15 +168,14 @@ class PerformanceTester(object): ...@@ -166,15 +168,14 @@ class PerformanceTester(object):
namespace.user_tuple = ArgumentType.objectFromModule(namespace.user_info_filename, namespace.user_tuple = ArgumentType.objectFromModule(namespace.user_info_filename,
object_name='user_tuple', object_name='user_tuple',
searchable_path_list=users_file_path_list) searchable_path_list=users_file_path_list)
print "USER TUPLE: " + str(namespace.user_tuple)
namespace.benchmark_suite_list = namespace.benchmark_suite_list[0].split(" ") namespace.benchmark_suite_list = namespace.benchmark_suite_list[0].split(" ")
object_benchmark_suite_list = [] object_benchmark_suite_list = []
for benchmark_suite in namespace.benchmark_suite_list: for benchmark_suite in namespace.benchmark_suite_list:
object_benchmark_suite_list.append(ArgumentType.objectFromModule(benchmark_suite, object_benchmark_suite_list.append(ArgumentType.objectFromModule(benchmark_suite,
callable_object=True, callable_object=True,
searchable_path_list=namespace.benchmark_path_list)) searchable_path_list=namespace.benchmark_path_list))
if namespace.repeat > 0: if namespace.repeat > 0:
namespace.max_error_number = \ namespace.max_error_number = \
min(len(namespace.benchmark_suite_list) * namespace.repeat, min(len(namespace.benchmark_suite_list) * namespace.repeat,
...@@ -238,6 +239,7 @@ class PerformanceTester(object): ...@@ -238,6 +239,7 @@ class PerformanceTester(object):
result_class = self.getResultClass() result_class = self.getResultClass()
for user_index in range(nb_users): for user_index in range(nb_users):
print "[PERFORMANCE TESTER] Creating benchmark process for user: " + str(user_index)
process = BenchmarkProcess(exit_msg_queue, result_class, process = BenchmarkProcess(exit_msg_queue, result_class,
self._argument_namespace, nb_users, self._argument_namespace, nb_users,
user_index, user_index,
...@@ -289,9 +291,10 @@ class PerformanceTester(object): ...@@ -289,9 +291,10 @@ class PerformanceTester(object):
return (error_message_set, exit_status) return (error_message_set, exit_status)
def run(self): def run(self):
print "[PERFORMANCE TESTER] run method"
error_message_set, exit_status = set(), 0 error_message_set, exit_status = set(), 0
self.preRun() self.preRun()
if isinstance(self._argument_namespace.users, tuple): if isinstance(self._argument_namespace.users, tuple):
min_user_number, max_user_number = self._argument_namespace.users min_user_number, max_user_number = self._argument_namespace.users
repeat_counter = 0 repeat_counter = 0
......
...@@ -79,6 +79,7 @@ class BenchmarkProcess(multiprocessing.Process): ...@@ -79,6 +79,7 @@ class BenchmarkProcess(multiprocessing.Process):
def runBenchmarkSuiteList(self, result): def runBenchmarkSuiteList(self, result):
for target_idx, target in enumerate(self._argument_namespace.benchmark_suite_list): for target_idx, target in enumerate(self._argument_namespace.benchmark_suite_list):
self._logger.debug("EXECUTE: %s" % target) self._logger.debug("EXECUTE: %s" % target)
print "[PROCESS] EXECUTE: %s" % target
result.enterSuite(target.__name__) result.enterSuite(target.__name__)
with_error = False with_error = False
...@@ -115,7 +116,9 @@ class BenchmarkProcess(multiprocessing.Process): ...@@ -115,7 +116,9 @@ class BenchmarkProcess(multiprocessing.Process):
# Clear the Browser history (which keeps (request, response)) # Clear the Browser history (which keeps (request, response))
# otherwise it will consume a lot of memory after some time. Also it # otherwise it will consume a lot of memory after some time. Also it
# does make sense to keep it as suites are independent of each other # does make sense to keep it as suites are independent of each other
self._browser.mech_browser.clear_history() #self._browser.mech_browser.clear_history()
self._browser._history.clear()
print "Browser memory cleaned"
result.exitSuite(with_error) result.exitSuite(with_error)
...@@ -127,6 +130,7 @@ class BenchmarkProcess(multiprocessing.Process): ...@@ -127,6 +130,7 @@ class BenchmarkProcess(multiprocessing.Process):
result.iterationFinished() result.iterationFinished()
def run(self): def run(self):
print "[PROCESS] run method"
result_instance = self._result_klass(self._argument_namespace, result_instance = self._result_klass(self._argument_namespace,
self._nb_users, self._nb_users,
self._user_index, self._user_index,
...@@ -147,10 +151,13 @@ class BenchmarkProcess(multiprocessing.Process): ...@@ -147,10 +151,13 @@ class BenchmarkProcess(multiprocessing.Process):
socket.socket = _patched_socket socket.socket = _patched_socket
print "[PROCESS] (signal.SIGTERM, self.stopGracefully)"
# Ensure the data are flushed before exiting, handled by Result class # Ensure the data are flushed before exiting, handled by Result class
# __exit__ block # __exit__ block
signal.signal(signal.SIGTERM, self.stopGracefully) signal.signal(signal.SIGTERM, self.stopGracefully)
print "[PROCESS] Ignore KeyboardInterrupt"
# Ignore KeyboardInterrupt as it is handled by the parent process # Ignore KeyboardInterrupt as it is handled by the parent process
signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_IGN)
......
File mode changed from 100755 to 100644
...@@ -80,10 +80,14 @@ class BenchmarkResultStatistic(object): ...@@ -80,10 +80,14 @@ class BenchmarkResultStatistic(object):
@property @property
def mean(self): def mean(self):
if self.n == 0:
self.n = 1
return self._value_sum / self.n return self._value_sum / self.n
@property @property
def standard_deviation(self): def standard_deviation(self):
if self.n == 0:
self.n = 1
return math.sqrt(self._variance_sum / self.n) return math.sqrt(self._variance_sum / self.n)
class NothingFlushedException(Exception): class NothingFlushedException(Exception):
......
...@@ -124,12 +124,16 @@ def getCreatedDocumentNumberFromERP5(erp5_url, log): ...@@ -124,12 +124,16 @@ def getCreatedDocumentNumberFromERP5(erp5_url, log):
# XXX: This import is required, just to populate sys.modules['test_suite']. # XXX: This import is required, just to populate sys.modules['test_suite'].
# Even if it's not used in this file. Yuck. # Even if it's not used in this file. Yuck.
import product.ERP5Type.tests.ERP5TypeTestSuite # ROQUE: can't find this module. If I add an egg 'product', it also fails
#import product.ERP5Type.tests.ERP5TypeTestSuite
# XXX: dirty hack until product is property imported
import sys
sys.path.append('/opt/slapgrid/7031c818b335cf4caf0052ae845689d0/parts/erp5/product/ERP5Type/tests/')
import ERP5TypeTestSuite
from subprocess import call from subprocess import call
LOG_FILE_PREFIX = "performance_tester_erp5" LOG_FILE_PREFIX = "scalability_tester_erp5"
# Duration of a test case # Duration of a test case
TEST_CASE_DURATION = 60 TEST_CASE_DURATION = 60
# Maximum limit of documents to create during a test case # Maximum limit of documents to create during a test case
...@@ -145,6 +149,14 @@ def doNothing(**kwargs): ...@@ -145,6 +149,14 @@ def doNothing(**kwargs):
pass pass
def makeSuite(test_suite=None, log=doNothing, **kwargs): def makeSuite(test_suite=None, log=doNothing, **kwargs):
### ROQUE hardcoded test suite for debug
import imp
module = imp.load_source('tests', '/opt/slapgrid/7031c818b335cf4caf0052ae845689d0/parts/erp5/tests/__init__.py')
suite = module.ERP5_scalability(max_instance_count=1, **kwargs)
return suite
# BBB tests (plural form) is only checked for backward compatibility # BBB tests (plural form) is only checked for backward compatibility
for k in sys.modules.keys(): for k in sys.modules.keys():
if k in ('tests', 'test',) or k.startswith('tests.') or k.startswith('test.'): if k in ('tests', 'test',) or k.startswith('tests.') or k.startswith('test.'):
...@@ -153,6 +165,9 @@ def makeSuite(test_suite=None, log=doNothing, **kwargs): ...@@ -153,6 +165,9 @@ def makeSuite(test_suite=None, log=doNothing, **kwargs):
while True: while True:
module_name, class_name = ('%s.%s' % (singular_succeed and 'test' or 'tests', module_name, class_name = ('%s.%s' % (singular_succeed and 'test' or 'tests',
test_suite)).rsplit('.', 1) test_suite)).rsplit('.', 1)
print "module name and class name:"
print module_name
print class_name
try: try:
suite_class = getattr(__import__(module_name, None, None, [class_name]), suite_class = getattr(__import__(module_name, None, None, [class_name]),
class_name) class_name)
...@@ -165,7 +180,6 @@ def makeSuite(test_suite=None, log=doNothing, **kwargs): ...@@ -165,7 +180,6 @@ def makeSuite(test_suite=None, log=doNothing, **kwargs):
suite = suite_class(max_instance_count=1, **kwargs) suite = suite_class(max_instance_count=1, **kwargs)
return suite return suite
class ScalabilityLauncher(object): class ScalabilityLauncher(object):
def __init__(self): def __init__(self):
# Parse arguments # Parse arguments
...@@ -187,9 +201,16 @@ class ScalabilityLauncher(object): ...@@ -187,9 +201,16 @@ class ScalabilityLauncher(object):
logger.addHandler(file_handler) logger.addHandler(file_handler)
self.log = logger.info self.log = logger.info
# ROQUE testing if this proxy works
proxy = taskdistribution.ServerProxy(
self.__argumentNamespace.test_suite_master_url,
allow_none=True
).portal_task_distribution
# Proxy to with erp5 master test_result # Proxy to with erp5 master test_result
self.test_result = taskdistribution.TestResultProxy( self.test_result = taskdistribution.TestResultProxy(
self.__argumentNamespace.test_suite_master_url, proxy, #self.__argumentNamespace.test_suite_master_url,
1.0, DummyLogger(self.log), 1.0, DummyLogger(self.log),
self.__argumentNamespace.test_result_path, self.__argumentNamespace.test_result_path,
self.__argumentNamespace.node_title, self.__argumentNamespace.node_title,
...@@ -265,7 +286,10 @@ class ScalabilityLauncher(object): ...@@ -265,7 +286,10 @@ class ScalabilityLauncher(object):
Return a ScalabilityTest with current running test case informations, Return a ScalabilityTest with current running test case informations,
or None if no test_case ready or None if no test_case ready
""" """
data = self.test_result.getRunningTestCase() # ROQUE hardcoded due to error: test_result is not referencing master test_result module
#data = self.test_result.getRunningTestCase() # this runs in master
data = json.dumps({"relative_path": "test_result_module/9667/2",
"title": "0", "count" : 1, })
if not data: if not data:
return None return None
decoded_data = Utils.deunicodeData(json.loads(data)) decoded_data = Utils.deunicodeData(json.loads(data))
...@@ -285,7 +309,8 @@ class ScalabilityLauncher(object): ...@@ -285,7 +309,8 @@ class ScalabilityLauncher(object):
# Get suite informations # Get suite informations
suite = makeSuite(self.__argumentNamespace.test_suite, self.log) suite = makeSuite(self.__argumentNamespace.test_suite, self.log)
test_suite_list = suite.getTestList() test_suite_list = suite.getTestList()
test_suite_list = ['createPerson']
# Main loop # Main loop
while True: while True:
...@@ -297,6 +322,7 @@ class ScalabilityLauncher(object): ...@@ -297,6 +322,7 @@ class ScalabilityLauncher(object):
self.log("Test Case %s going to be run." %(current_test.title)) self.log("Test Case %s going to be run." %(current_test.title))
# Prepare configuration # Prepare configuration
### ROQUE hardcoded test suite for debug
current_test_number = int(current_test.title) current_test_number = int(current_test.title)
test_duration = suite.getTestDuration(current_test_number) test_duration = suite.getTestDuration(current_test_number)
benchmarks_path = os.path.join(self.__argumentNamespace.erp5_location, suite.getTestPath()) benchmarks_path = os.path.join(self.__argumentNamespace.erp5_location, suite.getTestPath())
...@@ -304,8 +330,8 @@ class ScalabilityLauncher(object): ...@@ -304,8 +330,8 @@ class ScalabilityLauncher(object):
user_file_path = os.path.split(user_file_full_path)[0] user_file_path = os.path.split(user_file_full_path)[0]
user_file = os.path.split(user_file_full_path)[1] user_file = os.path.split(user_file_full_path)[1]
tester_path = self.__argumentNamespace.runner_path tester_path = self.__argumentNamespace.runner_path
user_number = suite.getUserNumber(current_test_number) user_number = 1 #suite.getUserNumber(current_test_number)
repetition = suite.getTestRepetition(current_test_number) repetition = 1 #suite.getTestRepetition(current_test_number)
self.log("user_number: %s" %str(user_number)) self.log("user_number: %s" %str(user_number))
self.log("test_duration: %s seconds" %str(test_duration)) self.log("test_duration: %s seconds" %str(test_duration))
...@@ -319,9 +345,10 @@ class ScalabilityLauncher(object): ...@@ -319,9 +345,10 @@ class ScalabilityLauncher(object):
# Get the number of documents present before running the test. # Get the number of documents present before running the test.
waitFor0PendingActivities(self.__argumentNamespace.erp5_url, self.log) waitFor0PendingActivities(self.__argumentNamespace.erp5_url, self.log)
previous_document_number = getCreatedDocumentNumberFromERP5(self.__argumentNamespace.erp5_url, self.log) # ROQUE hardcoded. Don't know what is this method. /erp5/count_docs_scalability ????
self.log("previous_document_number: %d" %previous_document_number) #previous_document_number = getCreatedDocumentNumberFromERP5(self.__argumentNamespace.erp5_url, self.log)
#self.log("previous_document_number: %d" %previous_document_number)
self.log("previous_document_number:---")
# Generate commands to run # Generate commands to run
command_list = [] command_list = []
user_index = 0 user_index = 0
...@@ -333,21 +360,22 @@ class ScalabilityLauncher(object): ...@@ -333,21 +360,22 @@ class ScalabilityLauncher(object):
'--benchmark-path-list', benchmarks_path, '--benchmark-path-list', benchmarks_path,
'--users-file-path', user_file_path, '--users-file-path', user_file_path,
'--users-file', user_file, '--users-file', user_file,
'--filename-prefix', "%s_%s_repetition%d" %(LOG_FILE_PREFIX, current_test.title, i), #'--filename-prefix', "%s_%s_repetition%d" %(LOG_FILE_PREFIX, current_test.title, i),
'--report-directory', self.__argumentNamespace.log_path, '--report-directory', self.__argumentNamespace.log_path,
'--repeat', "%s" %str(MAX_DOCUMENTS), '--repeat', "%s" %str(1), #(MAX_DOCUMENTS),
'--max-errors', str(1000000), '--max-errors', str(1000000),
'--user-index', str(user_index), #'--user-index', str(user_index),
]) ])
user_index += user_number/len(test_suite_list) user_index += user_number/len(test_suite_list)
# Launch commands # Launch commands
tester_process_list = [] tester_process_list = []
for command in command_list: for command in command_list:
self.log("command: %s" %str(command)) self.log("command: %s" %str(command))
tester_process_list.append(subprocess.Popen(command)) tester_process_list.append(subprocess.Popen(command))
# Sleep # Sleep
#test_duration = 5
time.sleep(test_duration) time.sleep(test_duration)
# Stop # Stop
...@@ -358,15 +386,17 @@ class ScalabilityLauncher(object): ...@@ -358,15 +386,17 @@ class ScalabilityLauncher(object):
# Count created documents # Count created documents
# Wait for 0 pending activities before counting # Wait for 0 pending activities before counting
waitFor0PendingActivities(self.__argumentNamespace.erp5_url, self.log) waitFor0PendingActivities(self.__argumentNamespace.erp5_url, self.log)
current_document_number = getCreatedDocumentNumberFromERP5(self.__argumentNamespace.erp5_url, self.log) # ROQUE hardcoded. Dont know what is this method. /erp5/count_docs_scalability ????
created_document_number = current_document_number - previous_document_number #current_document_number = getCreatedDocumentNumberFromERP5(self.__argumentNamespace.erp5_url, self.log)
self.log("previous_document_number: %d" %previous_document_number) #created_document_number = current_document_number - previous_document_number
self.log("current_document_number: %d" %current_document_number) #self.log("previous_document_number: %d" %previous_document_number)
self.log("created_document_number: %d" %created_document_number) #self.log("current_document_number: %d" %current_document_number)
document_number.append(created_document_number) #self.log("created_document_number: %d" %created_document_number)
self.log("commented lines of document number 'count_docs_scalability'")
#document_number.append(created_document_number)
# Move csv/logs # Move csv/logs
self.moveLogs(current_test.title) #self.moveLogs(current_test.title)
self.log("Test Case %s is finish" %(current_test.title)) self.log("Test Case %s is finish" %(current_test.title))
# Get the maximum as choice # Get the maximum as choice
...@@ -399,10 +429,13 @@ class ScalabilityLauncher(object): ...@@ -399,10 +429,13 @@ class ScalabilityLauncher(object):
'_'.join(test_suite_list) '_'.join(test_suite_list)
) )
self.log("Results: %s" %results) self.log("Results: %s" %results)
test_result_line_test.stop(stdout=results, #test_result_line_test.stop(stdout=results,
test_count=len(test_suite_list), # test_count=len(test_suite_list),
duration=test_duration) # duration=test_duration)
# ROQUE commented because it tries to do "_logger.warning" and self.log is already a function
self.log("Test Case Stopped") self.log("Test Case Stopped")
print "SLEEPING FOR 100 (in while TRUE)"
time.sleep(100)
# #
error_message_set = None error_message_set = None
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
# #
# WARNING: This program as such is intended to be used by professional # WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential # programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs # consequences resulting from its eventual inadequacies and bugsc
# End users who are looking for a ready-to-use solution with commercial # End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software # garantees and support are strongly adviced to contract a Free Software
# Service Company # Service Company
...@@ -36,7 +36,7 @@ import urllib ...@@ -36,7 +36,7 @@ import urllib
from urlparse import urljoin from urlparse import urljoin
from z3c.etestbrowser.browser import ExtendedTestBrowser from z3c.etestbrowser.browser import ExtendedTestBrowser
from zope.testbrowser.browser import onlyOne, fix_exception_name from zope.testbrowser.browser import onlyOne #, fix_exception_name
def measurementMetaClass(prefix): def measurementMetaClass(prefix):
""" """
...@@ -234,7 +234,7 @@ class Browser(ExtendedTestBrowser): ...@@ -234,7 +234,7 @@ class Browser(ExtendedTestBrowser):
try: try:
response = self.mech_browser.open_novisit(url_or_path, data) response = self.mech_browser.open_novisit(url_or_path, data)
except Exception, e: except Exception, e:
fix_exception_name(e) #fix_exception_name(e)
raise raise
except mechanize.HTTPError, e: except mechanize.HTTPError, e:
if e.code >= 200 and e.code <= 299: if e.code >= 200 and e.code <= 299:
...@@ -313,21 +313,22 @@ class Browser(ExtendedTestBrowser): ...@@ -313,21 +313,22 @@ class Browser(ExtendedTestBrowser):
@todo: Patch zope.testbrowser to allow the class to be given @todo: Patch zope.testbrowser to allow the class to be given
rather than duplicating the code rather than duplicating the code
""" """
print "MAINFORM PROPERTY ASKED"
# If the page has not changed, no need to re-create a class, so # If the page has not changed, no need to re-create a class, so
# just return the main_form instance # just return the main_form instance
if self._main_form and self._counter == self._main_form._browser_counter: if self._main_form and self._counter == self._main_form._browser_counter:
print "return last MAINFORM"
return self._main_form return self._main_form
main_form = None main_form = None
for form in self.mech_browser.forms(): #for form in self.mech_browser.forms():
if form.attrs.get('id') == 'main_form': # if form.attrs.get('id') == 'main_form':
main_form = form # main_form = form
main_form = self.getForm(id='main_form')._form
if not main_form: if not main_form:
raise LookupError("Could not get 'main_form'") raise LookupError("Could not get 'main_form'")
#self.mech_browser.form = form
self.mech_browser.form = form self._main_form = ContextMainForm(self, main_form)
self._main_form = ContextMainForm(self, form) print "return new ContextMainForm"
return self._main_form return self._main_form
def getLink(self, text=None, url=None, id=None, index=0, def getLink(self, text=None, url=None, id=None, index=0,
...@@ -682,6 +683,8 @@ class MainForm(Form): ...@@ -682,6 +683,8 @@ class MainForm(Form):
class attribute name, if class_attribute class attribute name, if class_attribute
parameter is given. parameter is given.
""" """
print "SUBMIT METHOD"
print "Submitting (name='%s', label='%s', class='%s')" % (name, label, class_attribute)
self._logger.debug( self._logger.debug(
"Submitting (name='%s', label='%s', class='%s')" % (name, label, "Submitting (name='%s', label='%s', class='%s')" % (name, label,
class_attribute)) class_attribute))
...@@ -700,13 +703,33 @@ class MainForm(Form): ...@@ -700,13 +703,33 @@ class MainForm(Form):
class_attribute) class_attribute)
if label is None and name is None: if label is None and name is None:
#self._form.submit(label=label, name=name, *args, **kwargs)
super(MainForm, self).submit(label=label, name=name, *args, **kwargs) super(MainForm, self).submit(label=label, name=name, *args, **kwargs)
else: else:
if index is None: if index is None:
index = 0 index = 0
super(MainForm, self).submit(label=label, name=name, index=index, super(MainForm, self).submit(label=label, name=name, index=index,
*args, **kwargs) *args, **kwargs)
print "Browser.url"
print str(self.browser.url)
print "Browser.title"
print str(self.browser.title)
#print "Browser.contents"
#print str(self.browser.contents)
print "Browser.headers"
print str(self.browser.headers)
print "Browser.cookies"
print str(self.browser.cookies)
print "len(browser.cookies)"
print len(self.browser.cookies)
print "Browser.cookies.url"
print str(self.browser.cookies.url)
print "Browser..cookies.keys()"
print str(self.browser.cookies.keys())
def submitSelect(self, select_name, submit_name, label=None, value=None, def submitSelect(self, select_name, submit_name, label=None, value=None,
select_index=None, control_index=None): select_index=None, control_index=None):
...@@ -747,8 +770,15 @@ class MainForm(Form): ...@@ -747,8 +770,15 @@ class MainForm(Form):
@raise LookupError: The select, option or submit control could not @raise LookupError: The select, option or submit control could not
be found be found
""" """
print "SUBMIT SELECT ASKED"
print "select_name: %s " % select_name
print "submit_name: %s " % submit_name
print "label: %s " % label
print "value: %s " % value
#form = self.mainForm._form
#form = self._form
#select_control = form.getControl(name=select_name, index=select_index)
select_control = self.getControl(name=select_name, index=select_index) select_control = self.getControl(name=select_name, index=select_index)
# zope.testbrowser checks for a whole word but it is also useful # zope.testbrowser checks for a whole word but it is also useful
# to match the end of the option control value string because in # to match the end of the option control value string because in
# ERP5, the value could be URL (such as 'http://foo:81/erp5/logout') # ERP5, the value could be URL (such as 'http://foo:81/erp5/logout')
...@@ -760,13 +790,15 @@ class MainForm(Form): ...@@ -760,13 +790,15 @@ class MainForm(Form):
if item.endswith(value): if item.endswith(value):
value = item value = item
break break
print "select_id='%s', label='%s', value='%s'" % \
(select_name, label, value)
self._logger.debug("select_id='%s', label='%s', value='%s'" % \ self._logger.debug("select_id='%s', label='%s', value='%s'" % \
(select_name, label, value)) (select_name, label, value))
control = select_control.getControl(label=label, value=value,
index=control_index)
select_control.getControl(label=label, value=value, select_control.getControl(label=label, value=value,
index=control_index).selected = True index=control_index).selected = True
print "CONTROL %s FOUND AND SELECTED" % (control.value)
self.submit(name=submit_name) self.submit(name=submit_name)
def submitLogin(self): def submitLogin(self):
...@@ -783,13 +815,18 @@ class MainForm(Form): ...@@ -783,13 +815,18 @@ class MainForm(Form):
@todo: Use information sent back as headers rather than looking @todo: Use information sent back as headers rather than looking
into the page content? into the page content?
""" """
print "SUBMIT LOGIN ASKED"
check_logged_in_xpath = '//div[@id="logged_in_as"]/*' check_logged_in_xpath = '//div[@id="logged_in_as"]/*'
if self.etree.xpath(check_logged_in_xpath): if self.etree.xpath(check_logged_in_xpath):
print "LOGIN: Already logged in"
self._logger.debug("Already logged in") self._logger.debug("Already logged in")
# TODO: Perhaps zope.testbrowser should be patched instead? # TODO: Perhaps zope.testbrowser should be patched instead?
self.browser.timer.start_time = self.browser.timer.end_time = 0 self.browser.timer.start_time = self.browser.timer.end_time = 0
return return
print "Logging in: username='%s', password='%s'" % \
(self.browser._username, self.browser._password)
self._logger.debug("Logging in: username='%s', password='%s'" % \ self._logger.debug("Logging in: username='%s', password='%s'" % \
(self.browser._username, self.browser._password)) (self.browser._username, self.browser._password))
...@@ -797,6 +834,7 @@ class MainForm(Form): ...@@ -797,6 +834,7 @@ class MainForm(Form):
form.getControl(name='__ac_name').value = self.browser._username form.getControl(name='__ac_name').value = self.browser._username
form.getControl(name='__ac_password').value = self.browser._password form.getControl(name='__ac_password').value = self.browser._password
form.submit() form.submit()
print "LOGGED IN "
try: try:
login(self) login(self)
...@@ -809,6 +847,15 @@ class MainForm(Form): ...@@ -809,6 +847,15 @@ class MainForm(Form):
(self.browser._erp5_base_url, (self.browser._erp5_base_url,
self.browser._username, self.browser._username,
self.browser._password)) self.browser._password))
print "SETTING COOKIES AFTER LOGIN"
import Cookie
cookie = Cookie.SimpleCookie()
cookie.load(self.browser.headers['set-cookie'])
ac_value = cookie['__ac'].value
self.browser.cookies["__ac"] = ac_value
print "BROWSER COOKIES:"
print self.browser.cookies
def submitSelectFavourite(self, label=None, value=None, **kw): def submitSelectFavourite(self, label=None, value=None, **kw):
""" """
...@@ -949,6 +996,9 @@ class ContextMainForm(MainForm): ...@@ -949,6 +996,9 @@ class ContextMainForm(MainForm):
""" """
Create a new object. Create a new object.
""" """
print "SUBMIT NEW ASKED"
#self._form.submit(name='Folder_create:method')
#self.mainForm._form.submit(name='Folder_create:method')
self.submit(name='Folder_create:method') self.submit(name='Folder_create:method')
def submitClone(self): def submitClone(self):
...@@ -1187,7 +1237,8 @@ class ContextMainForm(MainForm): ...@@ -1187,7 +1237,8 @@ class ContextMainForm(MainForm):
# control), then get the item from its value # control), then get the item from its value
if isinstance(control, ListControl): if isinstance(control, ListControl):
control = control.getControl(value=input_element.get('value')) control = control.getControl(value=input_element.get('value'))
print "CONTROL TYPE: "
print str(type(control))
return control return control
from zope.testbrowser.browser import SubmitControl from zope.testbrowser.browser import SubmitControl
......
...@@ -85,7 +85,7 @@ class ScalabilityTestRunner(): ...@@ -85,7 +85,7 @@ class ScalabilityTestRunner():
self.log("SlapOS Master hateoas url is: %s" %self.slapos_api_rest_url) self.log("SlapOS Master hateoas url is: %s" %self.slapos_api_rest_url)
self.key_path, self.cert_path, config_path = self.slapos_controler.createSlaposConfigurationFileAccount( self.key_path, self.cert_path, config_path = self.slapos_controler.createSlaposConfigurationFileAccount(
key, certificate, self.slapos_url, self.testnode.config, self.slapos_api_rest_url) key, certificate, self.slapos_url, self.testnode.config)
self.slapos_communicator = None self.slapos_communicator = None
# Dict containing used to store which SR is not yet correctly installed. # Dict containing used to store which SR is not yet correctly installed.
# looks like: {'comp_id1':'SR_urlA', 'comp_id2':'SR_urlA',..} # looks like: {'comp_id1':'SR_urlA', 'comp_id2':'SR_urlA',..}
...@@ -150,7 +150,6 @@ class ScalabilityTestRunner(): ...@@ -150,7 +150,6 @@ class ScalabilityTestRunner():
config = self._generateInstanceXML(software_configuration, config = self._generateInstanceXML(software_configuration,
test_result, test_suite) test_result, test_suite)
request_kw = {"partition_parameter_kw": {"_" : json.dumps(config)} } request_kw = {"partition_parameter_kw": {"_" : json.dumps(config)} }
#self.log("request_kw: " + str(request_kw)) # kept for DEBUG
self.slapos_communicator._request(SlapOSMasterCommunicator.INSTANCE_STATE_STARTED, instance_title, request_kw) self.slapos_communicator._request(SlapOSMasterCommunicator.INSTANCE_STATE_STARTED, instance_title, request_kw)
self.authorize_request = False self.authorize_request = False
return {'status_code' : 0} return {'status_code' : 0}
...@@ -235,13 +234,13 @@ late a SlapOS (positive) answer." %(str(os.getpid()),str(os.getpid()),)) ...@@ -235,13 +234,13 @@ late a SlapOS (positive) answer." %(str(os.getpid()),str(os.getpid()),))
raise ValueError(error_message) raise ValueError(error_message)
self.log("Instance correctly '%s' after %s seconds." %(state, str(time.time()-start_time))) self.log("Instance correctly '%s' after %s seconds." %(state, str(time.time()-start_time)))
def _waitInstanceCreation(self, instance_title, hateoas, max_time=MAX_CREATION_INSTANCE_TIME): def _waitInstanceCreation(self, instance_title, max_time=MAX_CREATION_INSTANCE_TIME):
""" """
Wait for 'max_time' the instance creation Wait for 'max_time' the instance creation
""" """
self.log("Waiting for instance creation...") self.log("Waiting for instance creation...")
start_time = time.time() start_time = time.time()
while (not instance_title in hateoas.getHostingSubscriptionDict() \ while (not self.slapos_communicator.isInstanceRequested(instance_title) \
and (max_time > (time.time()-start_time)) ): and (max_time > (time.time()-start_time)) ):
self.log("Instance not ready yet. Sleeping 5 sec.") self.log("Instance not ready yet. Sleeping 5 sec.")
time.sleep(5) time.sleep(5)
...@@ -390,7 +389,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),str(os.getpid()),)) ...@@ -390,7 +389,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),str(os.getpid()),))
except: except:
self.log("Unable to launch instance") self.log("Unable to launch instance")
raise ValueError("Unable to launch instance") raise ValueError("Unable to launch instance")
self._waitInstanceCreation(self.instance_title, hateoas) self._waitInstanceCreation(self.instance_title)
return {'status_code' : 0} return {'status_code' : 0}
return {'status_code' : 1} return {'status_code' : 1}
...@@ -540,4 +539,4 @@ late a SlapOS (positive) answer." %(str(os.getpid()),str(os.getpid()),)) ...@@ -540,4 +539,4 @@ late a SlapOS (positive) answer." %(str(os.getpid()),str(os.getpid()),))
Used by the method testnode.constructProfile() to know Used by the method testnode.constructProfile() to know
if the software.cfg have to use relative path or not. if the software.cfg have to use relative path or not.
""" """
return True return True
\ No newline at end of file
...@@ -78,7 +78,7 @@ class SlapOSControler(object): ...@@ -78,7 +78,7 @@ class SlapOSControler(object):
#TODO: implement a method to get all instance related the slapOS account #TODO: implement a method to get all instance related the slapOS account
# and deleting all old instances (based on creation date or name etc...) # and deleting all old instances (based on creation date or name etc...)
def createSlaposConfigurationFileAccount(self, key, certificate, slapos_url, config, slapos_rest_url): def createSlaposConfigurationFileAccount(self, key, certificate, slapos_url, config):
# Create "slapos_account" directory in the "slapos_directory" # Create "slapos_account" directory in the "slapos_directory"
slapos_account_directory = os.path.join(config['slapos_directory'], "slapos_account") slapos_account_directory = os.path.join(config['slapos_directory'], "slapos_account")
createFolder(slapos_account_directory) createFolder(slapos_account_directory)
...@@ -86,10 +86,9 @@ class SlapOSControler(object): ...@@ -86,10 +86,9 @@ class SlapOSControler(object):
slapos_account_key_path = os.path.join(slapos_account_directory, "key") slapos_account_key_path = os.path.join(slapos_account_directory, "key")
slapos_account_certificate_path = os.path.join(slapos_account_directory, "certificate") slapos_account_certificate_path = os.path.join(slapos_account_directory, "certificate")
configuration_file_path = os.path.join(slapos_account_directory, "slapos.cfg") configuration_file_path = os.path.join(slapos_account_directory, "slapos.cfg")
configuration_file_value = "[slapos]\nmaster_url = %s\nmaster_rest_url = %s\n\ configuration_file_value = "[slapos]\nmaster_url = %s\n\
[slapconsole]\ncert_file = %s\nkey_file = %s" %( [slapconsole]\ncert_file = %s\nkey_file = %s" %(
slapos_url, slapos_url,
slapos_rest_url,
slapos_account_certificate_path, slapos_account_certificate_path,
slapos_account_key_path) slapos_account_key_path)
createFile(slapos_account_key_path, "w", key) createFile(slapos_account_key_path, "w", key)
......
...@@ -114,6 +114,10 @@ class SlapOSMasterCommunicator(object): ...@@ -114,6 +114,10 @@ class SlapOSMasterCommunicator(object):
state=state, state=state,
**self.request_kw) **self.request_kw)
def isInstanceRequested(self, instance_title):
hateoas = getattr(self.slap, '_hateoas_navigator', None)
return instance_title in hateoas.getHostingSubscriptionDict()
@retryOnNetworkFailure @retryOnNetworkFailure
def _hateoas_getComputer(self, reference): def _hateoas_getComputer(self, reference):
...@@ -512,5 +516,4 @@ class SoftwareReleaseTester(SlapOSMasterCommunicator): ...@@ -512,5 +516,4 @@ class SoftwareReleaseTester(SlapOSMasterCommunicator):
stepfunc, delay, _, _, _ = self.transition_dict[next_state] stepfunc, delay, _, _, _ = self.transition_dict[next_state]
self.deadline = now + delay self.deadline = now + delay
stepfunc(self) stepfunc(self)
return self.deadline return self.deadline
\ No newline at end of file
...@@ -404,14 +404,11 @@ shared = true ...@@ -404,14 +404,11 @@ shared = true
node_test_suite.edit(test_result=test_result) node_test_suite.edit(test_result=test_result)
# get cluster configuration for this test suite, this is needed to # get cluster configuration for this test suite, this is needed to
# know slapos parameters to user for creating instances # know slapos parameters to user for creating instances
log("Getting configuration from test suite " + str(node_test_suite.test_suite_title))
log("Getting configuration from test suite " + str(node_test_suite.test_suite_title))
generated_config = self.test_suite_portal.generateConfiguration(node_test_suite.test_suite_title) generated_config = self.test_suite_portal.generateConfiguration(node_test_suite.test_suite_title)
#log("Generated configuration: " + str(generated_config)) # kept for debug
jsonData = json.loads(generated_config) jsonData = json.loads(generated_config)
cluster_configuration = Utils.deunicodeData(jsonData['configuration_list'][0]) cluster_configuration = Utils.deunicodeData(jsonData['configuration_list'][0])
node_test_suite.edit(cluster_configuration=cluster_configuration) node_test_suite.edit(cluster_configuration=cluster_configuration)
# Now prepare the installation of SlapOS and create instance # Now prepare the installation of SlapOS and create instance
status_dict = runner.prepareSlapOSForTestSuite(node_test_suite) status_dict = runner.prepareSlapOSForTestSuite(node_test_suite)
# Give some time so computer partitions may start # Give some time so computer partitions may start
...@@ -486,4 +483,4 @@ shared = true ...@@ -486,4 +483,4 @@ shared = true
# Exceptions are swallowed during cleanup phase # Exceptions are swallowed during cleanup phase
log("GENERAL EXCEPTION, QUITING") log("GENERAL EXCEPTION, QUITING")
self.cleanUp(test_result) self.cleanUp(test_result)
log("GENERAL EXCEPTION, QUITING, cleanup finished") log("GENERAL EXCEPTION, QUITING, cleanup finished")
\ No newline at end of file
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
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