Multiple enhancements and bugfixes
1. Add to return the counters of socket timeout; 2. Bugfixes on kb_gen_chart.py; 3. Create testing and tested kloud parallelly; Change-Id: Ie67bcc3c7a4375a885a478352b0c04731b2aca75
This commit is contained in:
parent
c2bd299caf
commit
e8b378bd7b
1
.gitignore
vendored
1
.gitignore
vendored
@ -57,3 +57,4 @@ ChangeLog
|
|||||||
# vmtp
|
# vmtp
|
||||||
*.local*
|
*.local*
|
||||||
*.json
|
*.json
|
||||||
|
*.html
|
||||||
|
@ -105,7 +105,7 @@ class BaseNetwork(object):
|
|||||||
secgroup_name = network_prefix + "-SG" + str(secgroup_count)
|
secgroup_name = network_prefix + "-SG" + str(secgroup_count)
|
||||||
secgroup_instance.create_secgroup_with_rules(secgroup_name)
|
secgroup_instance.create_secgroup_with_rules(secgroup_name)
|
||||||
|
|
||||||
LOG.info("Scheduled to create virtual machines...")
|
LOG.info("Scheduled to create virtual machines for network %s..." % network_prefix)
|
||||||
if config_scale['use_floatingip']:
|
if config_scale['use_floatingip']:
|
||||||
external_network = find_external_network(self.neutron_client)
|
external_network = find_external_network(self.neutron_client)
|
||||||
# Schedule to create the required number of VMs
|
# Schedule to create the required number of VMs
|
||||||
|
@ -14,6 +14,9 @@ keystone_admin_role: "admin"
|
|||||||
# Cleanup all kloudbuster resources upon exit
|
# Cleanup all kloudbuster resources upon exit
|
||||||
cleanup_resources: True
|
cleanup_resources: True
|
||||||
|
|
||||||
|
# VM creation concurrency
|
||||||
|
vm_creation_concurrency: 5
|
||||||
|
|
||||||
#
|
#
|
||||||
# ssh access to the test VMs launched by kloudbuster is not required
|
# ssh access to the test VMs launched by kloudbuster is not required
|
||||||
# but can be handy if the user wants to ssh manually to any of them (for example
|
# but can be handy if the user wants to ssh manually to any of them (for example
|
||||||
@ -50,13 +53,13 @@ server:
|
|||||||
|
|
||||||
# Assign floating IP for every VM
|
# Assign floating IP for every VM
|
||||||
use_floatingip: True
|
use_floatingip: True
|
||||||
|
|
||||||
# Placement hint
|
# Placement hint
|
||||||
# Availability zone to use for servers in the server cloud
|
# Availability zone to use for servers in the server cloud
|
||||||
# Leave empty if you prefer to have the Nova scheduler place the server VMs
|
# Leave empty if you prefer to have the Nova scheduler place the server VMs
|
||||||
# If you want to pick a particular AZ, put that AZ name (e.g. nova)
|
# If you want to pick a particular AZ, put that AZ name (e.g. nova)
|
||||||
# If you want a paticular compute host, put the AZ and compute host names s
|
# If you want a paticular compute host, put the AZ and compute host names s
|
||||||
# eparated by ':' (e.g. nova:tme100)
|
# eparated by ':' (e.g. nova:tme100)
|
||||||
availability_zone:
|
availability_zone:
|
||||||
|
|
||||||
|
|
||||||
@ -70,7 +73,7 @@ client:
|
|||||||
# Leave empty if you prefer to have the Nova scheduler place the server VMs
|
# Leave empty if you prefer to have the Nova scheduler place the server VMs
|
||||||
# If you want to pick a particular AZ, put that AZ name (e.g. nova)
|
# If you want to pick a particular AZ, put that AZ name (e.g. nova)
|
||||||
# If you want a paticular compute host, put the AZ and compute host names s
|
# If you want a paticular compute host, put the AZ and compute host names s
|
||||||
# eparated by ':' (e.g. nova:tme100)
|
# eparated by ':' (e.g. nova:tme100)
|
||||||
availability_zone:
|
availability_zone:
|
||||||
|
|
||||||
# (TEMP) Redis server configuration
|
# (TEMP) Redis server configuration
|
||||||
@ -104,4 +107,3 @@ client:
|
|||||||
|
|
||||||
# Prompt before running benchmarking tools
|
# Prompt before running benchmarking tools
|
||||||
prompt_before_run: False
|
prompt_before_run: False
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import locale
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
@ -33,7 +32,7 @@ __version__ = '0.0.1'
|
|||||||
kb_html_tpl = "./kb_tpl.jinja"
|
kb_html_tpl = "./kb_tpl.jinja"
|
||||||
|
|
||||||
def get_formatted_num(value):
|
def get_formatted_num(value):
|
||||||
return locale.format("%d", value, grouping=True)
|
return '{:,}'.format(value)
|
||||||
|
|
||||||
# List of fields to format with thousands separators
|
# List of fields to format with thousands separators
|
||||||
fields_to_format = ['rps_max', 'rps', 'http_sock_err', 'total_server_vm',
|
fields_to_format = ['rps_max', 'rps', 'http_sock_err', 'total_server_vm',
|
||||||
@ -142,5 +141,4 @@ if __name__ == '__main__':
|
|||||||
print('Version ' + __version__)
|
print('Version ' + __version__)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
locale.setlocale(locale.LC_ALL, 'en_US')
|
|
||||||
gen_chart(opts.file, opts.chart, opts.browser)
|
gen_chart(opts.file, opts.chart, opts.browser)
|
||||||
|
@ -113,7 +113,7 @@
|
|||||||
</div><!-- ROW1 -->
|
</div><!-- ROW1 -->
|
||||||
|
|
||||||
<div class="row" align="center"><!-- ROW2 -->
|
<div class="row" align="center"><!-- ROW2 -->
|
||||||
<div id="curve_chart" style="width: 800px; height: 500px"></div>
|
<div id="curve_chart" style="width: 1200px; height: 500px"></div>
|
||||||
</div><!-- ROW2 -->
|
</div><!-- ROW2 -->
|
||||||
</div><!--/panel-body-->
|
</div><!--/panel-body-->
|
||||||
</div><!--/panel-->
|
</div><!--/panel-->
|
||||||
|
@ -16,6 +16,7 @@ import json
|
|||||||
from multiprocessing.pool import ThreadPool
|
from multiprocessing.pool import ThreadPool
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import configure
|
import configure
|
||||||
@ -137,8 +138,8 @@ class Kloud(object):
|
|||||||
# Store the fixed ip as ssh ip since there is no floating ip
|
# Store the fixed ip as ssh ip since there is no floating ip
|
||||||
instance.ssh_ip = instance.fixed_ip
|
instance.ssh_ip = instance.fixed_ip
|
||||||
|
|
||||||
def create_vms(self):
|
def create_vms(self, vm_creation_concurrency):
|
||||||
tpool = ThreadPool(processes=5)
|
tpool = ThreadPool(processes=vm_creation_concurrency)
|
||||||
tpool.map(self.create_vm, self.get_all_instances())
|
tpool.map(self.create_vm, self.get_all_instances())
|
||||||
|
|
||||||
|
|
||||||
@ -167,6 +168,8 @@ class KloudBuster(object):
|
|||||||
self.kloud = Kloud(server_cfg, server_cred)
|
self.kloud = Kloud(server_cfg, server_cred)
|
||||||
self.testing_kloud = Kloud(client_cfg, client_cred, testing_side=True)
|
self.testing_kloud = Kloud(client_cfg, client_cred, testing_side=True)
|
||||||
self.final_result = None
|
self.final_result = None
|
||||||
|
self.server_vm_create_thread = None
|
||||||
|
self.client_vm_create_thread = None
|
||||||
|
|
||||||
def print_provision_info(self):
|
def print_provision_info(self):
|
||||||
"""
|
"""
|
||||||
@ -218,9 +221,9 @@ class KloudBuster(object):
|
|||||||
Support concurrency in fututure
|
Support concurrency in fututure
|
||||||
"""
|
"""
|
||||||
kbscheduler = None
|
kbscheduler = None
|
||||||
|
vm_creation_concurrency = self.client_cfg.vm_creation_concurrency
|
||||||
try:
|
try:
|
||||||
self.kloud.create_resources()
|
self.kloud.create_resources()
|
||||||
self.kloud.create_vms()
|
|
||||||
self.testing_kloud.create_resources()
|
self.testing_kloud.create_resources()
|
||||||
|
|
||||||
# Start the scheduler and ready for the incoming redis messages
|
# Start the scheduler and ready for the incoming redis messages
|
||||||
@ -235,7 +238,24 @@ class KloudBuster(object):
|
|||||||
shared_net = self.testing_kloud.get_first_network()
|
shared_net = self.testing_kloud.get_first_network()
|
||||||
self.kloud.attach_to_shared_net(shared_net)
|
self.kloud.attach_to_shared_net(shared_net)
|
||||||
self.gen_user_data()
|
self.gen_user_data()
|
||||||
self.testing_kloud.create_vms()
|
|
||||||
|
# Create VMs in both tested and testing kloud concurrently
|
||||||
|
self.client_vm_create_thread = threading.Thread(target=self.testing_kloud.create_vms,
|
||||||
|
args=[vm_creation_concurrency])
|
||||||
|
self.server_vm_create_thread = threading.Thread(target=self.kloud.create_vms,
|
||||||
|
args=[vm_creation_concurrency])
|
||||||
|
self.client_vm_create_thread.daemon = True
|
||||||
|
self.server_vm_create_thread.daemon = True
|
||||||
|
if self.single_cloud:
|
||||||
|
self.client_vm_create_thread.start()
|
||||||
|
self.client_vm_create_thread.join()
|
||||||
|
self.server_vm_create_thread.start()
|
||||||
|
self.server_vm_create_thread.join()
|
||||||
|
else:
|
||||||
|
self.client_vm_create_thread.start()
|
||||||
|
self.server_vm_create_thread.start()
|
||||||
|
self.client_vm_create_thread.join()
|
||||||
|
self.server_vm_create_thread.join()
|
||||||
|
|
||||||
# Function that print all the provisioning info
|
# Function that print all the provisioning info
|
||||||
self.print_provision_info()
|
self.print_provision_info()
|
||||||
@ -334,6 +354,18 @@ if __name__ == '__main__':
|
|||||||
alt_config = configure.Configuration.from_file(CONF.config).configure()
|
alt_config = configure.Configuration.from_file(CONF.config).configure()
|
||||||
config_scale = config_scale.merge(alt_config)
|
config_scale = config_scale.merge(alt_config)
|
||||||
|
|
||||||
|
# Retrieve the credentials
|
||||||
|
cred = credentials.Credentials(CONF.tested_rc, CONF.passwd_tested, CONF.no_env)
|
||||||
|
if CONF.testing_rc and CONF.testing_rc != CONF.tested_rc:
|
||||||
|
cred_testing = credentials.Credentials(CONF.testing_rc,
|
||||||
|
CONF.passwd_testing,
|
||||||
|
CONF.no_env)
|
||||||
|
single_cloud = False
|
||||||
|
else:
|
||||||
|
# Use the same openrc file for both cases
|
||||||
|
cred_testing = cred
|
||||||
|
single_cloud = True
|
||||||
|
|
||||||
# Initialize the key pair name
|
# Initialize the key pair name
|
||||||
if config_scale['public_key_file']:
|
if config_scale['public_key_file']:
|
||||||
# verify the public key file exists
|
# verify the public key file exists
|
||||||
@ -361,18 +393,6 @@ if __name__ == '__main__':
|
|||||||
# VMs on the server side (1:1)
|
# VMs on the server side (1:1)
|
||||||
client_side_cfg['vms_per_network'] = get_total_vm_count(server_side_cfg)
|
client_side_cfg['vms_per_network'] = get_total_vm_count(server_side_cfg)
|
||||||
|
|
||||||
# Retrieve the credentials
|
|
||||||
cred = credentials.Credentials(CONF.tested_rc, CONF.passwd_tested, CONF.no_env)
|
|
||||||
if CONF.testing_rc and CONF.testing_rc != CONF.tested_rc:
|
|
||||||
cred_testing = credentials.Credentials(CONF.testing_rc,
|
|
||||||
CONF.passwd_testing,
|
|
||||||
CONF.no_env)
|
|
||||||
single_cloud = False
|
|
||||||
else:
|
|
||||||
# Use the same openrc file for both cases
|
|
||||||
cred_testing = cred
|
|
||||||
single_cloud = True
|
|
||||||
|
|
||||||
# The KloudBuster class is just a wrapper class
|
# The KloudBuster class is just a wrapper class
|
||||||
# levarages tenant and user class for resource creations and
|
# levarages tenant and user class for resource creations and
|
||||||
# deletion
|
# deletion
|
||||||
|
@ -45,7 +45,8 @@ class PerfTool(object):
|
|||||||
def parse_results(self, protocol=None, throughput=None, lossrate=None, retrans=None,
|
def parse_results(self, protocol=None, throughput=None, lossrate=None, retrans=None,
|
||||||
rtt_ms=None, reverse_dir=False, msg_size=None, cpu_load=None,
|
rtt_ms=None, reverse_dir=False, msg_size=None, cpu_load=None,
|
||||||
http_total_req=None, http_rps=None, http_tp_kbytes=None,
|
http_total_req=None, http_rps=None, http_tp_kbytes=None,
|
||||||
http_sock_err=None, http_err=None, latency_stats=None):
|
http_sock_err=None, http_sock_timeout=None, http_err=None,
|
||||||
|
latency_stats=None):
|
||||||
res = {'tool': self.name}
|
res = {'tool': self.name}
|
||||||
if throughput is not None:
|
if throughput is not None:
|
||||||
res['throughput_kbps'] = throughput
|
res['throughput_kbps'] = throughput
|
||||||
@ -73,6 +74,8 @@ class PerfTool(object):
|
|||||||
res['http_throughput_kbytes'] = http_tp_kbytes
|
res['http_throughput_kbytes'] = http_tp_kbytes
|
||||||
if http_sock_err:
|
if http_sock_err:
|
||||||
res['http_sock_err'] = http_sock_err
|
res['http_sock_err'] = http_sock_err
|
||||||
|
if http_sock_timeout:
|
||||||
|
res['http_sock_timeout'] = http_sock_timeout
|
||||||
if http_err:
|
if http_err:
|
||||||
res['http_err'] = http_err
|
res['http_err'] = http_err
|
||||||
if latency_stats:
|
if latency_stats:
|
||||||
|
@ -84,9 +84,11 @@ class WrkTool(PerfTool):
|
|||||||
v2 = int(http_sock_err.group(2))
|
v2 = int(http_sock_err.group(2))
|
||||||
v3 = int(http_sock_err.group(3))
|
v3 = int(http_sock_err.group(3))
|
||||||
v4 = int(http_sock_err.group(4))
|
v4 = int(http_sock_err.group(4))
|
||||||
http_sock_err = v1 + v2 + v3 + v4
|
http_sock_err = v1 + v2 + v3
|
||||||
|
http_sock_timeout = v4
|
||||||
else:
|
else:
|
||||||
http_sock_err = 0
|
http_sock_err = 0
|
||||||
|
http_sock_timeout = 0
|
||||||
|
|
||||||
re_str = r'Non-2xx or 3xx responses: (\d+)'
|
re_str = r'Non-2xx or 3xx responses: (\d+)'
|
||||||
http_err = re.search(re_str, stdout)
|
http_err = re.search(re_str, stdout)
|
||||||
@ -97,7 +99,7 @@ class WrkTool(PerfTool):
|
|||||||
|
|
||||||
re_str = r'__START_KLOUDBUSTER_DATA__\n(((.*)\n)*)__END_KLOUDBUSTER_DATA__'
|
re_str = r'__START_KLOUDBUSTER_DATA__\n(((.*)\n)*)__END_KLOUDBUSTER_DATA__'
|
||||||
latency_stats = re.search(re_str, stdout).group(1).split()
|
latency_stats = re.search(re_str, stdout).group(1).split()
|
||||||
latency_stats = [(float(x.split(',')[0]), int(x.split(',')[1])) for x in latency_stats]
|
latency_stats = [[float(x.split(',')[0]), int(x.split(',')[1])] for x in latency_stats]
|
||||||
except Exception:
|
except Exception:
|
||||||
return self.parse_error('Could not parse: %s' % (stdout))
|
return self.parse_error('Could not parse: %s' % (stdout))
|
||||||
|
|
||||||
@ -105,6 +107,7 @@ class WrkTool(PerfTool):
|
|||||||
http_rps=http_rps,
|
http_rps=http_rps,
|
||||||
http_tp_kbytes=http_tp_kbytes,
|
http_tp_kbytes=http_tp_kbytes,
|
||||||
http_sock_err=http_sock_err,
|
http_sock_err=http_sock_err,
|
||||||
|
http_sock_timeout=http_sock_timeout,
|
||||||
http_err=http_err,
|
http_err=http_err,
|
||||||
latency_stats=latency_stats)
|
latency_stats=latency_stats)
|
||||||
|
|
||||||
@ -115,7 +118,8 @@ class WrkTool(PerfTool):
|
|||||||
if not total_count:
|
if not total_count:
|
||||||
return all_res
|
return all_res
|
||||||
|
|
||||||
for key in ['http_rps', 'http_total_req', 'http_sock_err', 'http_throughput_kbytes']:
|
for key in ['http_rps', 'http_total_req', 'http_sock_err',
|
||||||
|
'http_sock_timeout', 'http_throughput_kbytes']:
|
||||||
all_res[key] = 0
|
all_res[key] = 0
|
||||||
for item in results:
|
for item in results:
|
||||||
if (key in item['results']):
|
if (key in item['results']):
|
||||||
@ -127,12 +131,15 @@ class WrkTool(PerfTool):
|
|||||||
first_result = results[0]['results']['latency_stats']
|
first_result = results[0]['results']['latency_stats']
|
||||||
latency_counts = len(first_result)
|
latency_counts = len(first_result)
|
||||||
|
|
||||||
|
# for item in results:
|
||||||
|
# print item['results']['latency_stats']
|
||||||
|
|
||||||
for i in range(latency_counts):
|
for i in range(latency_counts):
|
||||||
latency_avg = 0
|
latency_avg = 0
|
||||||
for item in results:
|
for item in results:
|
||||||
latency_avg += item['results']['latency_stats'][i][1]
|
latency_avg += item['results']['latency_stats'][i][1]
|
||||||
latency_avg = int(latency_avg / total_count)
|
latency_avg = int(latency_avg / total_count)
|
||||||
latency_tup = (first_result[i][0], latency_avg)
|
latency_tup = [first_result[i][0], latency_avg]
|
||||||
all_res['latency_stats'].append(latency_tup)
|
all_res['latency_stats'].append(latency_tup)
|
||||||
|
|
||||||
return all_res
|
return all_res
|
||||||
|
Loading…
x
Reference in New Issue
Block a user