5ffec0c85b
1. Change the sequence how progression runs; 2. Refine the progression header formater function; 3. Format adjustments and typo fixes on force_cleanup document; Change-Id: I09a6290a583f8a0698075b2980563e343efb4a15
165 lines
7.4 KiB
Python
165 lines
7.4 KiB
Python
# Copyright 2015 Cisco Systems, Inc. All rights reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from __future__ import division
|
|
|
|
from kb_runner_base import KBException
|
|
from kb_runner_base import KBRunner
|
|
import log as logging
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
class KBSetStaticRouteException(KBException):
|
|
pass
|
|
|
|
class KBHTTPServerUpException(KBException):
|
|
pass
|
|
|
|
class KBHTTPBenchException(KBException):
|
|
pass
|
|
|
|
class KBRunner_HTTP(KBRunner):
|
|
"""
|
|
Control the testing VMs on the testing cloud
|
|
"""
|
|
|
|
def __init__(self, client_list, config, expected_agent_version, single_cloud=True):
|
|
KBRunner.__init__(self, client_list, config, expected_agent_version, single_cloud)
|
|
|
|
def header_formatter(self, stage, vm_count):
|
|
conns = vm_count * self.config.http_tool_configs.connections
|
|
rate_limit = vm_count * self.config.http_tool_configs.rate_limit
|
|
msg = "Stage %d: %d VM(s), %d Connections, %d Expected RPS" %\
|
|
(stage, vm_count, conns, rate_limit)
|
|
return msg
|
|
|
|
def setup_static_route(self, active_range, timeout=30):
|
|
func = {'cmd': 'setup_static_route', 'active_range': active_range}
|
|
self.send_cmd('EXEC', 'http', func)
|
|
cnt_succ = self.polling_vms(timeout)[0]
|
|
if cnt_succ != len(self.client_dict):
|
|
raise KBSetStaticRouteException()
|
|
|
|
def check_http_service(self, active_range, timeout=30):
|
|
func = {'cmd': 'check_http_service', 'active_range': active_range}
|
|
self.send_cmd('EXEC', 'http', func)
|
|
cnt_succ = self.polling_vms(timeout)[0]
|
|
if cnt_succ != len(self.client_dict):
|
|
raise KBHTTPServerUpException()
|
|
|
|
def run_http_test(self, active_range):
|
|
func = {'cmd': 'run_http_test', 'active_range': active_range,
|
|
'parameter': dict(self.config.http_tool_configs)}
|
|
self.send_cmd('EXEC', 'http', func)
|
|
# Give additional 30 seconds for everybody to report results
|
|
timeout = self.config.http_tool_configs.duration + 30
|
|
cnt_pending = self.polling_vms(timeout)[2]
|
|
if cnt_pending != 0:
|
|
LOG.warning("Testing VMs are not returning results within grace period, "
|
|
"summary shown below may not be accurate!")
|
|
|
|
# Parse the results from HTTP benchmarking tool
|
|
for key, instance in self.client_dict.items():
|
|
self.result[key] = instance.perf_client_parser(**self.result[key])
|
|
|
|
def single_run(self, active_range=None, http_test_only=False):
|
|
try:
|
|
if not http_test_only:
|
|
if self.single_cloud:
|
|
LOG.info("Setting up static route to reach tested cloud...")
|
|
self.setup_static_route(active_range)
|
|
|
|
LOG.info("Waiting for HTTP service to come up...")
|
|
self.check_http_service(active_range)
|
|
|
|
if self.config.prompt_before_run:
|
|
print "Press enter to start running benchmarking tools..."
|
|
raw_input()
|
|
|
|
LOG.info("Running HTTP Benchmarking...")
|
|
self.report = {'seq': 0, 'report': None}
|
|
self.result = {}
|
|
self.run_http_test(active_range)
|
|
|
|
# Call the method in corresponding tools to consolidate results
|
|
perf_tool = self.client_dict.values()[0].perf_tool
|
|
LOG.kbdebug(self.result.values())
|
|
self.tool_result = perf_tool.consolidate_results(self.result.values())
|
|
self.tool_result['http_rate_limit'] =\
|
|
len(self.client_dict) * self.config.http_tool_configs.rate_limit
|
|
self.tool_result['total_connections'] =\
|
|
len(self.client_dict) * self.config.http_tool_configs.connections
|
|
vm_count = active_range[1] - active_range[0] + 1\
|
|
if active_range else len(self.full_client_dict)
|
|
self.tool_result['total_client_vms'] = vm_count
|
|
self.tool_result['total_server_vms'] = self.tool_result['total_client_vms']
|
|
# self.tool_result['host_stats'] = self.gen_host_stats()
|
|
except KBSetStaticRouteException:
|
|
raise KBException("Could not set static route.")
|
|
except KBHTTPServerUpException:
|
|
raise KBException("HTTP service is not up in testing cloud.")
|
|
except KBHTTPBenchException:
|
|
raise KBException("Error while running HTTP benchmarking tool.")
|
|
|
|
def run(self, test_only=False):
|
|
if not test_only:
|
|
# Resources are already staged, just re-run the HTTP benchmarking tool
|
|
self.wait_for_vm_up()
|
|
|
|
if self.config.progression.enabled:
|
|
self.tool_result = {}
|
|
start = self.config.progression.vm_start
|
|
multiple = self.config.progression.vm_multiple
|
|
limit = self.config.progression.http_stop_limit
|
|
timeout = self.config.http_tool_configs.timeout
|
|
vm_list = self.full_client_dict.keys()
|
|
vm_list.sort(cmp=lambda x, y: cmp(int(x[x.rfind('I') + 1:]), int(y[y.rfind('I') + 1:])))
|
|
self.client_dict = {}
|
|
cur_stage = 1
|
|
|
|
while True:
|
|
cur_vm_count = len(self.client_dict)
|
|
if start == 1:
|
|
target_vm_count = 1 if cur_stage == 1 else (cur_stage - 1) * multiple
|
|
else:
|
|
target_vm_count = cur_stage * multiple
|
|
timeout_at_percentile = 0
|
|
if target_vm_count > len(self.full_client_dict):
|
|
break
|
|
if self.tool_result and 'latency_stats' in self.tool_result:
|
|
err = self.tool_result['http_sock_err'] + self.tool_result['http_sock_timeout']
|
|
pert_dict = dict(self.tool_result['latency_stats'])
|
|
if limit[1] in pert_dict.keys():
|
|
timeout_at_percentile = pert_dict[limit[1]] // 1000000
|
|
elif limit[1] != 0:
|
|
LOG.warning('Percentile %s%% is not a standard statistic point.' % limit[1])
|
|
if err > limit[0] or timeout_at_percentile > timeout:
|
|
LOG.warning('KloudBuster is stopping the iteration because the result '
|
|
'reaches the stop limit.')
|
|
break
|
|
|
|
for idx in xrange(cur_vm_count, target_vm_count):
|
|
self.client_dict[vm_list[idx]] = self.full_client_dict[vm_list[idx]]
|
|
description = "-- %s --" % self.header_formatter(cur_stage, len(self.client_dict))
|
|
LOG.info(description)
|
|
self.single_run(active_range=[0, target_vm_count - 1],
|
|
http_test_only=test_only)
|
|
LOG.info('-- Stage %s: %s --' % (cur_stage, str(self.tool_result)))
|
|
self.tool_result['description'] = description
|
|
cur_stage += 1
|
|
yield self.tool_result
|
|
else:
|
|
self.single_run(http_test_only=test_only)
|
|
yield self.tool_result
|