Add support of Session Manager for Rest API
1. Add support of Session Manager for Rest API; 2. Add Rest API for getting periodical report; 3. Add Rest API for getting console logs; 4. Fix KB-PROXY placement bug when topology file is provided; 5. Fix the logic for consolidating samples; 6. Refine Swagger definition files for Rest API; 7. Set the -c parameter in kb_gen_chart.py to required; Known Issue / TODO: 1. The Pecan server logs will be dumped to clients; 2. The RestAPI "log" need remember the offset and only gets the incremental Change-Id: If912fbfcabc73a04caa0122ffe942405a667608d
This commit is contained in:
parent
8aaa12d2b0
commit
0d30c860fc
1
.gitignore
vendored
1
.gitignore
vendored
@ -60,5 +60,4 @@ kb*.log
|
|||||||
*.html
|
*.html
|
||||||
*.qcow2
|
*.qcow2
|
||||||
scale/dib/kloudbuster.d/
|
scale/dib/kloudbuster.d/
|
||||||
|
|
||||||
.vagrant/
|
.vagrant/
|
||||||
|
@ -87,9 +87,7 @@ class BaseCompute(object):
|
|||||||
return instance
|
return instance
|
||||||
if instance.status == 'ERROR':
|
if instance.status == 'ERROR':
|
||||||
LOG.error('Instance creation error:' + instance.fault['message'])
|
LOG.error('Instance creation error:' + instance.fault['message'])
|
||||||
break
|
return None
|
||||||
# print "[%s] VM status=%s, retrying %s of %s..." \
|
|
||||||
# % (vmname, instance.status, (retry_attempt + 1), retry_count)
|
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
def get_server_list(self):
|
def get_server_list(self):
|
||||||
|
@ -20,6 +20,7 @@ import log as logging
|
|||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
import credentials
|
import credentials
|
||||||
|
import kb_vm_agent
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -109,6 +110,13 @@ class KBConfig(object):
|
|||||||
self.client_cfg['vms_per_network'] =\
|
self.client_cfg['vms_per_network'] =\
|
||||||
self.get_total_vm_count(self.server_cfg) + 1
|
self.get_total_vm_count(self.server_cfg) + 1
|
||||||
|
|
||||||
|
# Use the default image name for Glance
|
||||||
|
# defaults to something like "kloudbuster_v3"
|
||||||
|
if not self.server_cfg['image_name']:
|
||||||
|
self.server_cfg['image_name'] = kb_vm_agent.get_image_name()
|
||||||
|
if not self.client_cfg['image_name']:
|
||||||
|
self.client_cfg['image_name'] = kb_vm_agent.get_image_name()
|
||||||
|
|
||||||
def init_with_cli(self):
|
def init_with_cli(self):
|
||||||
self.get_credentials()
|
self.get_credentials()
|
||||||
self.get_configs()
|
self.get_configs()
|
||||||
|
@ -183,7 +183,7 @@ def main():
|
|||||||
parser = argparse.ArgumentParser(description='KloudBuster Chart Generator V' + __version__)
|
parser = argparse.ArgumentParser(description='KloudBuster Chart Generator V' + __version__)
|
||||||
|
|
||||||
parser.add_argument('-c', '--chart', dest='chart',
|
parser.add_argument('-c', '--chart', dest='chart',
|
||||||
action='store',
|
action='store', required=True,
|
||||||
help='create and save chart in html file',
|
help='create and save chart in html file',
|
||||||
metavar='<file>')
|
metavar='<file>')
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
from sets import Set
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ import log as logging
|
|||||||
import redis
|
import redis
|
||||||
|
|
||||||
# A set of warned VM version mismatches
|
# A set of warned VM version mismatches
|
||||||
vm_version_mismatches = Set()
|
vm_version_mismatches = set()
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -55,6 +54,7 @@ class KBRunner(object):
|
|||||||
self.tool_result = {}
|
self.tool_result = {}
|
||||||
self.expected_agent_version = expected_agent_version
|
self.expected_agent_version = expected_agent_version
|
||||||
self.agent_version = None
|
self.agent_version = None
|
||||||
|
self.report = {'seq': 0, 'report': None}
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
self.redis_obj = None
|
self.redis_obj = None
|
||||||
@ -180,7 +180,10 @@ class KBRunner(object):
|
|||||||
LOG.info(log_msg)
|
LOG.info(log_msg)
|
||||||
|
|
||||||
if sample_count != 0:
|
if sample_count != 0:
|
||||||
print http_tool.consolidate_samples(samples, len(self.client_dict))
|
report = http_tool.consolidate_samples(samples, len(self.client_dict))
|
||||||
|
self.report['seq'] = self.report['seq'] + 1
|
||||||
|
self.report['report'] = report
|
||||||
|
LOG.info('Periodical report: %s.' % str(self.report))
|
||||||
samples = []
|
samples = []
|
||||||
retry = retry + 1
|
retry = retry + 1
|
||||||
|
|
||||||
|
@ -25,10 +25,10 @@ app = {
|
|||||||
'static_root': '%(confdir)s/public',
|
'static_root': '%(confdir)s/public',
|
||||||
'template_path': '%(confdir)s/kb_server/templates',
|
'template_path': '%(confdir)s/kb_server/templates',
|
||||||
'debug': True,
|
'debug': True,
|
||||||
'errors': {
|
# 'errors': {
|
||||||
404: '/error/404',
|
# 404: '/error/404',
|
||||||
'__force_dict__': True
|
# '__force_dict__': True
|
||||||
}
|
# }
|
||||||
}
|
}
|
||||||
|
|
||||||
logging = {
|
logging = {
|
||||||
|
@ -12,36 +12,57 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import traceback
|
||||||
kb_main_path = os.path.split(os.path.abspath(__file__))[0] + "/../../.."
|
kb_main_path = os.path.split(os.path.abspath(__file__))[0] + "/../../.."
|
||||||
sys.path.append(kb_main_path)
|
sys.path.append(kb_main_path)
|
||||||
|
|
||||||
from credentials import Credentials
|
from credentials import Credentials
|
||||||
|
from kb_session import KBSession
|
||||||
|
from kb_session import KBSessionManager
|
||||||
|
import log as logging
|
||||||
|
|
||||||
from configure import Configuration
|
from configure import Configuration
|
||||||
from kb_config import KBConfig
|
from kb_config import KBConfig
|
||||||
from pecan import expose
|
from pecan import expose
|
||||||
from pecan import response
|
from pecan import response
|
||||||
|
|
||||||
lock = threading.Lock()
|
|
||||||
kb_config = KBConfig()
|
|
||||||
|
|
||||||
class ConfigController(object):
|
class ConfigController(object):
|
||||||
|
|
||||||
@expose(generic=True)
|
@expose(generic=True)
|
||||||
def running_config(self):
|
def default_config(self):
|
||||||
|
kb_config = KBConfig()
|
||||||
|
# @TODO(Bug in Python???)
|
||||||
|
# return json.dumps(dict(kb_config.config_scale))
|
||||||
return str(kb_config.config_scale)
|
return str(kb_config.config_scale)
|
||||||
|
|
||||||
|
@expose(generic=True)
|
||||||
|
def running_config(self, *args):
|
||||||
|
if len(args):
|
||||||
|
session_id = args[0]
|
||||||
|
else:
|
||||||
|
response.status = 400
|
||||||
|
response.text = u"Please specify the session_id."
|
||||||
|
return response.text
|
||||||
|
if KBSessionManager.has(session_id):
|
||||||
|
kb_config_obj = KBSessionManager.get(session_id).kb_config
|
||||||
|
config_scale = kb_config_obj.config_scale
|
||||||
|
config_scale['server'] = kb_config_obj.server_cfg
|
||||||
|
config_scale['client'] = kb_config_obj.client_cfg
|
||||||
|
config_scale = dict(config_scale)
|
||||||
|
# @TODO(Bug in Python???)
|
||||||
|
# return json.dumps(config_scale)
|
||||||
|
return str(config_scale)
|
||||||
|
else:
|
||||||
|
response.status = 404
|
||||||
|
response.text = u"Session ID is not found or invalid."
|
||||||
|
return response.text
|
||||||
|
|
||||||
@running_config.when(method='POST')
|
@running_config.when(method='POST')
|
||||||
def running_config_POST(self, arg):
|
def running_config_POST(self, arg):
|
||||||
if not lock.acquire(False):
|
|
||||||
response.status = 403
|
|
||||||
response.text = u"An instance of KloudBuster is running, you cannot change"\
|
|
||||||
"the config until the run is finished!"
|
|
||||||
return response.text
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Expectation:
|
# Expectation:
|
||||||
# {
|
# {
|
||||||
@ -51,7 +72,7 @@ class ConfigController(object):
|
|||||||
# 'topo_cfg': {<TOPOLOGY_CONFIGS>}
|
# 'topo_cfg': {<TOPOLOGY_CONFIGS>}
|
||||||
# 'tenants_cfg': {<TENANT_AND_USER_LISTS_FOR_REUSING>}
|
# 'tenants_cfg': {<TENANT_AND_USER_LISTS_FOR_REUSING>}
|
||||||
# }
|
# }
|
||||||
user_config = eval(arg)
|
user_config = json.loads(arg)
|
||||||
|
|
||||||
# Parsing credentials from application input
|
# Parsing credentials from application input
|
||||||
cred_config = user_config['credentials']
|
cred_config = user_config['credentials']
|
||||||
@ -65,6 +86,13 @@ class ConfigController(object):
|
|||||||
# Use the same openrc file for both cases
|
# Use the same openrc file for both cases
|
||||||
cred_testing = cred_tested
|
cred_testing = cred_tested
|
||||||
|
|
||||||
|
session_id = hashlib.md5(str(cred_config)).hexdigest()
|
||||||
|
kb_config = KBConfig()
|
||||||
|
if KBSessionManager.has(session_id):
|
||||||
|
response.status = 403
|
||||||
|
response.text = u"Session is already existed."
|
||||||
|
return response.text
|
||||||
|
|
||||||
# Parsing server and client configs from application input
|
# Parsing server and client configs from application input
|
||||||
# Save the public key into a temporary file
|
# Save the public key into a temporary file
|
||||||
if 'public_key' in user_config['kb_cfg']:
|
if 'public_key' in user_config['kb_cfg']:
|
||||||
@ -74,6 +102,9 @@ class ConfigController(object):
|
|||||||
f.close()
|
f.close()
|
||||||
kb_config.config_scale['public_key_file'] = pubkey_filename
|
kb_config.config_scale['public_key_file'] = pubkey_filename
|
||||||
|
|
||||||
|
if 'prompt_before_run' in user_config['kb_cfg']:
|
||||||
|
kb_config.config_scale['prompt_before_run'] = False
|
||||||
|
|
||||||
if user_config['kb_cfg']:
|
if user_config['kb_cfg']:
|
||||||
alt_config = Configuration.from_string(user_config['kb_cfg']).configure()
|
alt_config = Configuration.from_string(user_config['kb_cfg']).configure()
|
||||||
kb_config.config_scale = kb_config.config_scale.merge(alt_config)
|
kb_config.config_scale = kb_config.config_scale.merge(alt_config)
|
||||||
@ -89,16 +120,58 @@ class ConfigController(object):
|
|||||||
tenants_list = Configuration.from_string(user_config['tenants_list']).configure()
|
tenants_list = Configuration.from_string(user_config['tenants_list']).configure()
|
||||||
else:
|
else:
|
||||||
tenants_list = None
|
tenants_list = None
|
||||||
except Exception as e:
|
except Exception:
|
||||||
response.status = 403
|
response.status = 400
|
||||||
response.text = u"Error while parsing configurations: %s" % (e.message)
|
response.text = u"Error while parsing configurations: \n%s" % (traceback.format_exc)
|
||||||
lock.release()
|
|
||||||
return response.text
|
return response.text
|
||||||
|
|
||||||
|
logging.setup("kloudbuster", logfile="/tmp/kb_log_%s" % session_id)
|
||||||
kb_config.init_with_rest_api(cred_tested=cred_tested,
|
kb_config.init_with_rest_api(cred_tested=cred_tested,
|
||||||
cred_testing=cred_testing,
|
cred_testing=cred_testing,
|
||||||
topo_cfg=topo_cfg,
|
topo_cfg=topo_cfg,
|
||||||
tenants_list=tenants_list)
|
tenants_list=tenants_list)
|
||||||
lock.release()
|
|
||||||
|
|
||||||
return "OK!"
|
kb_session = KBSession()
|
||||||
|
kb_session.kb_config = kb_config
|
||||||
|
KBSessionManager.add(session_id, kb_session)
|
||||||
|
|
||||||
|
return str(session_id)
|
||||||
|
|
||||||
|
@running_config.when(method='PUT')
|
||||||
|
def running_config_PUT(self, *args):
|
||||||
|
# @TODO(Not completed! ENOTSUP)
|
||||||
|
if len(args):
|
||||||
|
session_id = args[0]
|
||||||
|
else:
|
||||||
|
response.status = 400
|
||||||
|
response.text = u"Please specify the session_id."
|
||||||
|
return response.text
|
||||||
|
if KBSessionManager.has(session_id):
|
||||||
|
# kb_session = KBSessionManager.get(session_id)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
return "OK!"
|
||||||
|
else:
|
||||||
|
response.status = 404
|
||||||
|
response.text = u"Session ID is not found or invalid."
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
@running_config.when(method='DELETE')
|
||||||
|
def running_config_DELETE(self, *args):
|
||||||
|
if len(args):
|
||||||
|
session_id = args[0]
|
||||||
|
else:
|
||||||
|
response.status = 400
|
||||||
|
response.text = u"Please specify the session_id."
|
||||||
|
return response.text
|
||||||
|
if KBSessionManager.has(session_id):
|
||||||
|
kb_session = KBSessionManager.get(session_id)
|
||||||
|
if kb_session.kloudbuster:
|
||||||
|
kb_session.kloudbuster.dispose()
|
||||||
|
KBSessionManager.delete(session_id)
|
||||||
|
return "OK!"
|
||||||
|
else:
|
||||||
|
response.status = 404
|
||||||
|
response.text = u"Session ID is not found or invalid."
|
||||||
|
return response.text
|
||||||
|
@ -12,14 +12,15 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import threading
|
||||||
kb_main_path = os.path.split(os.path.abspath(__file__))[0] + "/../../.."
|
kb_main_path = os.path.split(os.path.abspath(__file__))[0] + "/../../.."
|
||||||
sys.path.append(kb_main_path)
|
sys.path.append(kb_main_path)
|
||||||
|
|
||||||
from api_cfg import kb_config as kb_config
|
from kb_session import KBSessionManager
|
||||||
from api_cfg import lock as kb_config_lock
|
from kloudbuster import __version__ as kb_version
|
||||||
from kloudbuster import KloudBuster
|
from kloudbuster import KloudBuster
|
||||||
|
|
||||||
from pecan import expose
|
from pecan import expose
|
||||||
@ -28,37 +29,109 @@ from pecan import response
|
|||||||
class KBController(object):
|
class KBController(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.kb_status = 'READY'
|
self.kb_thread = None
|
||||||
|
|
||||||
@expose(generic=True)
|
|
||||||
def status(self):
|
|
||||||
return self.kb_status
|
|
||||||
|
|
||||||
@expose(generic=True)
|
|
||||||
def run(self):
|
|
||||||
if (not kb_config.cred_tested) or (not kb_config.cred_testing):
|
|
||||||
response.status = 403
|
|
||||||
response.text = u"Credentials to the cloud are missing."\
|
|
||||||
"(Forgot to provide the config?)"
|
|
||||||
return response.text
|
|
||||||
if not kb_config_lock.acquire(False):
|
|
||||||
response.status = 403
|
|
||||||
response.text = u"An instance of KloudBuster is running, you cannot "\
|
|
||||||
"change the config until the run is finished!"
|
|
||||||
return response.text
|
|
||||||
|
|
||||||
|
def kb_thread_handler(self, session_id):
|
||||||
|
kb_session = KBSessionManager.get(session_id)
|
||||||
|
kb_session.kb_status = 'RUNNING'
|
||||||
|
kb_config = kb_session.kb_config
|
||||||
try:
|
try:
|
||||||
kloudbuster = KloudBuster(
|
kloudbuster = KloudBuster(
|
||||||
kb_config.cred_tested, kb_config.cred_testing,
|
kb_config.cred_tested, kb_config.cred_testing,
|
||||||
kb_config.server_cfg, kb_config.client_cfg,
|
kb_config.server_cfg, kb_config.client_cfg,
|
||||||
kb_config.topo_cfg, kb_config.tenants_list)
|
kb_config.topo_cfg, kb_config.tenants_list)
|
||||||
|
kb_session.kloudbuster = kloudbuster
|
||||||
|
|
||||||
if kloudbuster.check_and_upload_images():
|
if kloudbuster.check_and_upload_images():
|
||||||
kloudbuster.run()
|
kloudbuster.run()
|
||||||
|
kb_session.kb_status = 'READY'
|
||||||
except Exception:
|
except Exception:
|
||||||
response.status = 403
|
kb_session.kb_status = 'ERROR'
|
||||||
response.text = u"Error while running KloudBuster:\n%s" % traceback.format_exc()
|
|
||||||
kb_config_lock.release()
|
@expose(generic=True)
|
||||||
|
def status(self, *args):
|
||||||
|
if len(args):
|
||||||
|
session_id = args[0]
|
||||||
|
else:
|
||||||
|
response.status = 400
|
||||||
|
response.text = u"Please specify the session_id."
|
||||||
return response.text
|
return response.text
|
||||||
|
|
||||||
kb_config_lock.release()
|
if KBSessionManager.has(session_id):
|
||||||
|
status = KBSessionManager.get(session_id).kb_status
|
||||||
|
return status
|
||||||
|
else:
|
||||||
|
response.status = 404
|
||||||
|
response.text = u"Session ID is not found or invalid."
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
@expose(generic=True)
|
||||||
|
def log(self, *args):
|
||||||
|
if len(args):
|
||||||
|
session_id = args[0]
|
||||||
|
else:
|
||||||
|
response.status = 400
|
||||||
|
response.text = u"Please specify the session_id."
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
if KBSessionManager.has(session_id):
|
||||||
|
kb_session = KBSessionManager.get(session_id)
|
||||||
|
plog = kb_session.kloudbuster.dump_logs(offset=0)\
|
||||||
|
if kb_session.kloudbuster else ""
|
||||||
|
return json.dumps(plog)
|
||||||
|
else:
|
||||||
|
response.status = 404
|
||||||
|
response.text = u"Session ID is not found or invalid."
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
@expose(generic=True)
|
||||||
|
def report(self, *args):
|
||||||
|
if len(args):
|
||||||
|
session_id = args[0]
|
||||||
|
else:
|
||||||
|
response.status = 400
|
||||||
|
response.text = u"Please specify the session_id."
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
if KBSessionManager.has(session_id):
|
||||||
|
kb_session = KBSessionManager.get(session_id)
|
||||||
|
preport = kb_session.kloudbuster.kb_runner.report\
|
||||||
|
if kb_session.kloudbuster and kb_session.kloudbuster.kb_runner else ""
|
||||||
|
return json.dumps(preport)
|
||||||
|
else:
|
||||||
|
response.status = 404
|
||||||
|
response.text = u"Session ID is not found or invalid."
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
@expose(generic=True)
|
||||||
|
def version(self):
|
||||||
|
return kb_version
|
||||||
|
|
||||||
|
@expose(generic=True)
|
||||||
|
def run(self, *args):
|
||||||
|
response.status = 400
|
||||||
|
response.text = u"Please POST to this resource."
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
@run.when(method='POST')
|
||||||
|
def run_POST(self, *args):
|
||||||
|
if len(args):
|
||||||
|
session_id = args[0]
|
||||||
|
else:
|
||||||
|
response.status = 400
|
||||||
|
response.text = u"Please specify the session_id."
|
||||||
|
return response.text
|
||||||
|
if not KBSessionManager.has(session_id):
|
||||||
|
response.status = 404
|
||||||
|
response.text = u"Session ID is not found or invalid."
|
||||||
|
return response.text
|
||||||
|
if KBSessionManager.get(session_id).kb_status == 'RUNNING':
|
||||||
|
response.status = 403
|
||||||
|
response.text = u"An instance of KloudBuster is already running."
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
self.kb_thread = threading.Thread(target=self.kb_thread_handler, args=[session_id])
|
||||||
|
self.kb_thread.daemon = True
|
||||||
|
self.kb_thread.start()
|
||||||
|
|
||||||
return "OK!"
|
return "OK!"
|
||||||
|
53
kloudbuster/kb_server/kb_server/controllers/kb_session.py
Normal file
53
kloudbuster/kb_server/kb_server/controllers/kb_session.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import threading
|
||||||
|
|
||||||
|
KB_SESSIONS = {}
|
||||||
|
KB_SESSIONS_LOCK = threading.Lock()
|
||||||
|
|
||||||
|
class KBSessionManager(object):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def has(session_id):
|
||||||
|
global KB_SESSIONS
|
||||||
|
return True if session_id in KB_SESSIONS else False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get(session_id):
|
||||||
|
global KB_SESSIONS
|
||||||
|
return KB_SESSIONS[session_id] if KBSessionManager.has(session_id) else None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add(session_id, new_session):
|
||||||
|
global KB_SESSIONS
|
||||||
|
global KB_SESSIONS_LOCK
|
||||||
|
KB_SESSIONS_LOCK.acquire()
|
||||||
|
KB_SESSIONS[session_id] = new_session
|
||||||
|
KB_SESSIONS_LOCK.release()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def delete(session_id):
|
||||||
|
global KB_SESSIONS
|
||||||
|
global KB_SESSIONS_LOCK
|
||||||
|
KB_SESSIONS_LOCK.acquire()
|
||||||
|
KB_SESSIONS.pop(session_id)
|
||||||
|
KB_SESSIONS_LOCK.release()
|
||||||
|
|
||||||
|
|
||||||
|
class KBSession(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.kb_status = 'READY'
|
||||||
|
self.kb_config = None
|
||||||
|
self.kloudbuster = None
|
@ -6,7 +6,7 @@ info:
|
|||||||
data plane.
|
data plane.
|
||||||
version: "0.1.0"
|
version: "0.1.0"
|
||||||
host: 127.0.0.1:8080
|
host: 127.0.0.1:8080
|
||||||
basePath: /api/v1
|
basePath: /api
|
||||||
schemes:
|
schemes:
|
||||||
- http
|
- http
|
||||||
- https
|
- https
|
||||||
@ -15,6 +15,19 @@ consumes:
|
|||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
paths:
|
paths:
|
||||||
|
/config/default_config:
|
||||||
|
get:
|
||||||
|
description: |
|
||||||
|
Get the default KloudBuster configuration from server
|
||||||
|
tags:
|
||||||
|
- config
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: The default configuration
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: json
|
||||||
|
|
||||||
/config/running_config:
|
/config/running_config:
|
||||||
post:
|
post:
|
||||||
description: |
|
description: |
|
||||||
@ -40,6 +53,8 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Errors in details
|
description: Errors in details
|
||||||
|
403:
|
||||||
|
description: Session is already existed
|
||||||
|
|
||||||
/config/running_config/{session_id}:
|
/config/running_config/{session_id}:
|
||||||
get:
|
get:
|
||||||
@ -65,6 +80,7 @@ paths:
|
|||||||
|
|
||||||
put:
|
put:
|
||||||
description: |
|
description: |
|
||||||
|
(NOT IMPLEMENTED)
|
||||||
Update KloudBuster configuration for an existing session
|
Update KloudBuster configuration for an existing session
|
||||||
parameters:
|
parameters:
|
||||||
- name: session_id
|
- name: session_id
|
||||||
@ -108,6 +124,18 @@ paths:
|
|||||||
404:
|
404:
|
||||||
description: The session_id is not found or invalid
|
description: The session_id is not found or invalid
|
||||||
|
|
||||||
|
/kloudbuster/version:
|
||||||
|
get:
|
||||||
|
description: Get KloudBuster server version
|
||||||
|
tags:
|
||||||
|
- kloudbuster
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The version of the KloudBuster server
|
||||||
|
|
||||||
/kloudbuster/status/{session_id}:
|
/kloudbuster/status/{session_id}:
|
||||||
get:
|
get:
|
||||||
description: |
|
description: |
|
||||||
@ -130,9 +158,17 @@ paths:
|
|||||||
404:
|
404:
|
||||||
description: The session_id is not found or invalid
|
description: The session_id is not found or invalid
|
||||||
|
|
||||||
/kloudbuster/version:
|
/kloudbuster/console_log/{session_id}:
|
||||||
get:
|
get:
|
||||||
description: Get KloudBuster server version
|
description: |
|
||||||
|
Get KloudBuster console log for a given session
|
||||||
|
parameters:
|
||||||
|
- name: session_id
|
||||||
|
type: string
|
||||||
|
format: md5sum
|
||||||
|
in: path
|
||||||
|
description: The session to be queried
|
||||||
|
required: true
|
||||||
tags:
|
tags:
|
||||||
- kloudbuster
|
- kloudbuster
|
||||||
responses:
|
responses:
|
||||||
@ -140,7 +176,32 @@ paths:
|
|||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: The version of the KloudBuster server
|
description: The console log of the given session
|
||||||
|
404:
|
||||||
|
description: The session_id is not found or invalid
|
||||||
|
|
||||||
|
/kloudbuster/report/{session_id}:
|
||||||
|
get:
|
||||||
|
description: |
|
||||||
|
Get KloudBuster periodical report for a given session. Only
|
||||||
|
last report will be returned.
|
||||||
|
parameters:
|
||||||
|
- name: session_id
|
||||||
|
type: string
|
||||||
|
format: md5sum
|
||||||
|
in: path
|
||||||
|
description: The session to be queried
|
||||||
|
required: true
|
||||||
|
tags:
|
||||||
|
- kloudbuster
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The periodical report of the given session
|
||||||
|
404:
|
||||||
|
description: The session_id is not found or invalid
|
||||||
|
|
||||||
/kloudbuster/run/{session_id}:
|
/kloudbuster/run/{session_id}:
|
||||||
post:
|
post:
|
||||||
@ -162,6 +223,8 @@ paths:
|
|||||||
403:
|
403:
|
||||||
description: |
|
description: |
|
||||||
KloudBuster is already running on the given session
|
KloudBuster is already running on the given session
|
||||||
|
404:
|
||||||
|
description: The session_id is not found or invalid
|
||||||
|
|
||||||
definitions:
|
definitions:
|
||||||
Configuration_New:
|
Configuration_New:
|
@ -232,6 +232,8 @@ class KloudBuster(object):
|
|||||||
self.final_result = None
|
self.final_result = None
|
||||||
self.server_vm_create_thread = None
|
self.server_vm_create_thread = None
|
||||||
self.client_vm_create_thread = None
|
self.client_vm_create_thread = None
|
||||||
|
self.kb_runner = None
|
||||||
|
self.fp_logfile = None
|
||||||
|
|
||||||
def check_and_upload_images(self):
|
def check_and_upload_images(self):
|
||||||
keystone_list = [create_keystone_client(self.server_cred)[0],
|
keystone_list = [create_keystone_client(self.server_cred)[0],
|
||||||
@ -256,8 +258,8 @@ class KloudBuster(object):
|
|||||||
kb_image_name = 'dib/' + kb_vm_agent.get_image_name() + '.qcow2'
|
kb_image_name = 'dib/' + kb_vm_agent.get_image_name() + '.qcow2'
|
||||||
if not os.path.exists(kb_image_name):
|
if not os.path.exists(kb_image_name):
|
||||||
LOG.error("VM Image not in Glance and could not find " + kb_image_name +
|
LOG.error("VM Image not in Glance and could not find " + kb_image_name +
|
||||||
" to upload, please refer "
|
" to upload, please refer to dib/README.rst for how to build"
|
||||||
"to dib/README.rst for how to build image for KloudBuster.")
|
" image for KloudBuster.")
|
||||||
return False
|
return False
|
||||||
LOG.info("Image is not found in %s, uploading %s..." % (kloud, kb_image_name))
|
LOG.info("Image is not found in %s, uploading %s..." % (kloud, kb_image_name))
|
||||||
with open(kb_image_name) as fimage:
|
with open(kb_image_name) as fimage:
|
||||||
@ -330,7 +332,6 @@ class KloudBuster(object):
|
|||||||
"""
|
"""
|
||||||
The runner for KloudBuster Tests
|
The runner for KloudBuster Tests
|
||||||
"""
|
"""
|
||||||
kbrunner = None
|
|
||||||
vm_creation_concurrency = self.client_cfg.vm_creation_concurrency
|
vm_creation_concurrency = self.client_cfg.vm_creation_concurrency
|
||||||
try:
|
try:
|
||||||
tenant_quota = self.calc_tenant_quota()
|
tenant_quota = self.calc_tenant_quota()
|
||||||
@ -349,16 +350,19 @@ class KloudBuster(object):
|
|||||||
self.kb_proxy.user_data['role'] = 'KB-PROXY'
|
self.kb_proxy.user_data['role'] = 'KB-PROXY'
|
||||||
self.kb_proxy.boot_info['flavor_type'] = 'kb.proxy' if \
|
self.kb_proxy.boot_info['flavor_type'] = 'kb.proxy' if \
|
||||||
not self.tenants_list['client'] else self.testing_kloud.flavor_to_use
|
not self.tenants_list['client'] else self.testing_kloud.flavor_to_use
|
||||||
if self.testing_kloud.placement_az:
|
if self.topology:
|
||||||
self.kb_proxy.boot_info['avail_zone'] = "%s:%s" %\
|
proxy_hyper = self.topology.clients_rack.split()[0]
|
||||||
(self.testing_kloud.placement_az, self.topology.clients_rack.split()[0])
|
self.kb_proxy.boot_info['avail_zone'] =\
|
||||||
|
"%s:%s" % (self.testing_kloud.placement_az, proxy_hyper)\
|
||||||
|
if self.testing_kloud.placement_az else "nova:%s" % (proxy_hyper)
|
||||||
|
|
||||||
self.kb_proxy.boot_info['user_data'] = str(self.kb_proxy.user_data)
|
self.kb_proxy.boot_info['user_data'] = str(self.kb_proxy.user_data)
|
||||||
self.testing_kloud.create_vm(self.kb_proxy)
|
self.testing_kloud.create_vm(self.kb_proxy)
|
||||||
|
|
||||||
kbrunner = KBRunner(client_list, self.client_cfg,
|
self.kb_runner = KBRunner(client_list, self.client_cfg,
|
||||||
kb_vm_agent.get_image_version(),
|
kb_vm_agent.get_image_version(),
|
||||||
self.single_cloud)
|
self.single_cloud)
|
||||||
kbrunner.setup_redis(self.kb_proxy.fip_ip)
|
self.kb_runner.setup_redis(self.kb_proxy.fip_ip)
|
||||||
|
|
||||||
if self.single_cloud:
|
if self.single_cloud:
|
||||||
# Find the shared network if the cloud used to testing is same
|
# Find the shared network if the cloud used to testing is same
|
||||||
@ -392,11 +396,11 @@ class KloudBuster(object):
|
|||||||
self.print_provision_info()
|
self.print_provision_info()
|
||||||
|
|
||||||
# Run the runner to perform benchmarkings
|
# Run the runner to perform benchmarkings
|
||||||
kbrunner.run()
|
self.kb_runner.run()
|
||||||
self.final_result = kbrunner.tool_result
|
self.final_result = self.kb_runner.tool_result
|
||||||
self.final_result['total_server_vms'] = len(server_list)
|
self.final_result['total_server_vms'] = len(server_list)
|
||||||
self.final_result['total_client_vms'] = len(client_list)
|
self.final_result['total_client_vms'] = len(client_list)
|
||||||
# self.final_result['host_stats'] = kbrunner.host_stats
|
# self.final_result['host_stats'] = self.kb_runner.host_stats
|
||||||
LOG.info(self.final_result)
|
LOG.info(self.final_result)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
traceback.format_exc()
|
traceback.format_exc()
|
||||||
@ -418,6 +422,17 @@ class KloudBuster(object):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
KBResLogger.dump_and_save('clt', self.testing_kloud.res_logger.resource_list)
|
KBResLogger.dump_and_save('clt', self.testing_kloud.res_logger.resource_list)
|
||||||
|
|
||||||
|
def dump_logs(self, offset=0):
|
||||||
|
if not self.fp_logfile:
|
||||||
|
self.fp_logfile = open(CONF.log_file)
|
||||||
|
|
||||||
|
self.fp_logfile.seek(offset)
|
||||||
|
return self.fp_logfile.read()
|
||||||
|
|
||||||
|
def dispose(self):
|
||||||
|
self.fp_logfile.close()
|
||||||
|
logging.delete_logfile('kloudbuster')
|
||||||
|
|
||||||
def get_tenant_vm_count(self, config):
|
def get_tenant_vm_count(self, config):
|
||||||
return (config['users_per_tenant'] * config['routers_per_user'] *
|
return (config['users_per_tenant'] * config['routers_per_user'] *
|
||||||
config['networks_per_router'] * config['vms_per_network'])
|
config['networks_per_router'] * config['vms_per_network'])
|
||||||
@ -563,13 +578,6 @@ def main():
|
|||||||
LOG.error('Error parsing the configuration file')
|
LOG.error('Error parsing the configuration file')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Use the default image name for Glance
|
|
||||||
# defaults to something like "kloudbuster_v3"
|
|
||||||
if not kb_config.server_cfg['image_name']:
|
|
||||||
kb_config.server_cfg['image_name'] = kb_vm_agent.get_image_name()
|
|
||||||
if not kb_config.client_cfg['image_name']:
|
|
||||||
kb_config.client_cfg['image_name'] = kb_vm_agent.get_image_name()
|
|
||||||
|
|
||||||
# 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 deletion
|
# levarages tenant and user class for resource creations and deletion
|
||||||
kloudbuster = KloudBuster(
|
kloudbuster = KloudBuster(
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import handlers
|
from oslo_log import handlers
|
||||||
@ -41,11 +42,15 @@ KBDEBUG = logging.KBDEBUG
|
|||||||
WARN = logging.WARN
|
WARN = logging.WARN
|
||||||
WARNING = logging.WARNING
|
WARNING = logging.WARNING
|
||||||
|
|
||||||
def setup(product_name, version="unknown"):
|
def setup(product_name, logfile=None):
|
||||||
dbg_color = handlers.ColorHandler.LEVEL_COLORS[logging.DEBUG]
|
dbg_color = handlers.ColorHandler.LEVEL_COLORS[logging.DEBUG]
|
||||||
handlers.ColorHandler.LEVEL_COLORS[logging.KBDEBUG] = dbg_color
|
handlers.ColorHandler.LEVEL_COLORS[logging.KBDEBUG] = dbg_color
|
||||||
|
|
||||||
oslogging.setup(CONF, product_name, version)
|
if logfile:
|
||||||
|
if os.path.exists(logfile):
|
||||||
|
os.remove(logfile)
|
||||||
|
CONF.log_file = logfile
|
||||||
|
oslogging.setup(CONF, product_name)
|
||||||
|
|
||||||
if CONF.kb_debug:
|
if CONF.kb_debug:
|
||||||
oslogging.getLogger(
|
oslogging.getLogger(
|
||||||
@ -59,6 +64,14 @@ def getLogger(name="unknown", version="unknown"):
|
|||||||
"version": version})
|
"version": version})
|
||||||
return oslogging._loggers[name]
|
return oslogging._loggers[name]
|
||||||
|
|
||||||
|
def delete_logfile(product_name):
|
||||||
|
if CONF.log_file and os.path.exists(CONF.log_file):
|
||||||
|
os.remove(CONF.log_file)
|
||||||
|
# Reset the logging to default (stdout)
|
||||||
|
CONF.log_file = None
|
||||||
|
oslogging.setup(CONF, product_name)
|
||||||
|
|
||||||
|
|
||||||
class KloudBusterContextAdapter(oslogging.KeywordArgumentAdapter):
|
class KloudBusterContextAdapter(oslogging.KeywordArgumentAdapter):
|
||||||
|
|
||||||
def kbdebug(self, msg, *args, **kwargs):
|
def kbdebug(self, msg, *args, **kwargs):
|
||||||
|
@ -129,10 +129,10 @@ class WrkTool(PerfTool):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def consolidate_samples(results, vm_count):
|
def consolidate_samples(results, vm_count):
|
||||||
all_res = WrkTool.consolidate_results(results)
|
all_res = WrkTool.consolidate_results(results)
|
||||||
total_count = len(results) / vm_count
|
total_count = float(len(results)) / vm_count
|
||||||
if not total_count:
|
if not total_count:
|
||||||
return all_res
|
return all_res
|
||||||
|
|
||||||
all_res['http_rps'] = all_res['http_rps'] / total_count
|
all_res['http_rps'] = int(all_res['http_rps'] / total_count)
|
||||||
all_res['http_throughput_kbytes'] = all_res['http_throughput_kbytes'] / total_count
|
all_res['http_throughput_kbytes'] = int(all_res['http_throughput_kbytes'] / total_count)
|
||||||
return all_res
|
return all_res
|
||||||
|
Loading…
x
Reference in New Issue
Block a user