From d2891a02092c60024d5e7c684e365a4ae206d809 Mon Sep 17 00:00:00 2001 From: Yichen Wang Date: Mon, 13 Jul 2015 16:46:39 -0700 Subject: [PATCH] Add the RestAPI suppor to upload config 1. Add the RestAPI suppor to upload config; 2. Support multiple routers per tenant; 3. Enhance the cleanup logic; Change-Id: Id209765a138686db7a767b4ab65c833ab6f78522 --- scale/base_network.py | 2 +- scale/cfg.scale.yaml | 1 - scale/credentials.py | 61 ++++++++-------- scale/kb_config.py | 69 ++++++++++--------- .../kb_server/kb_server/controllers/config.py | 65 +++++++++++++++-- scale/kloudbuster.py | 10 ++- 6 files changed, 139 insertions(+), 69 deletions(-) diff --git a/scale/base_network.py b/scale/base_network.py index 0cc5164..4365ee3 100644 --- a/scale/base_network.py +++ b/scale/base_network.py @@ -234,7 +234,7 @@ class Router(object): network_instance = BaseNetwork(self) self.network_list.append(network_instance) # Create the network and subnet - network_name = self.user.user_name + "-N" + str(network_count) + network_name = self.router['router']['name'] + "-N" + str(network_count) network_instance.create_network_and_subnet(network_name) # Attach the created network to router interface self.attach_router_interface(network_instance) diff --git a/scale/cfg.scale.yaml b/scale/cfg.scale.yaml index 0bd75c7..ea2a3d8 100644 --- a/scale/cfg.scale.yaml +++ b/scale/cfg.scale.yaml @@ -45,7 +45,6 @@ server: users_per_tenant: 1 # Number of routers to be created within the context of each User - # For now support only 1 router per user routers_per_user: 1 # Number of networks to be created within the context of each Router diff --git a/scale/credentials.py b/scale/credentials.py index 4941c82..1dff9aa 100644 --- a/scale/credentials.py +++ b/scale/credentials.py @@ -46,46 +46,53 @@ class Credentials(object): dct['version'] = 2 return dct - # + def _init_with_openrc_(self, openrc_contents): + export_re = re.compile('export OS_([A-Z_]*)="?(.*)') + for line in openrc_contents: + line = line.strip() + mstr = export_re.match(line) + if mstr: + # get rif of posible trailing double quote + # the first one was removed by the re + name = mstr.group(1) + value = mstr.group(2) + if value.endswith('"'): + value = value[:-1] + # get rid of password assignment + # echo "Please enter your OpenStack Password: " + # read -sr OS_PASSWORD_INPUT + # export OS_PASSWORD=$OS_PASSWORD_INPUT + if value.startswith('$'): + continue + # now match against wanted variable names + if name == 'USERNAME': + self.rc_username = value + elif name == 'AUTH_URL': + self.rc_auth_url = value + elif name == 'TENANT_NAME': + self.rc_tenant_name = value + # Read a openrc file and take care of the password # The 2 args are passed from the command line and can be None - # - def __init__(self, openrc_file, pwd, no_env): + def __init__(self, openrc_file=None, openrc_contents=None, pwd=None, no_env=False): self.rc_password = None self.rc_username = None self.rc_tenant_name = None self.rc_auth_url = None + self.openrc_contents = openrc_contents success = True if openrc_file: if os.path.exists(openrc_file): - export_re = re.compile('export OS_([A-Z_]*)="?(.*)') - for line in open(openrc_file): - line = line.strip() - mstr = export_re.match(line) - if mstr: - # get rif of posible trailing double quote - # the first one was removed by the re - name = mstr.group(1) - value = mstr.group(2) - if value.endswith('"'): - value = value[:-1] - # get rid of password assignment - # echo "Please enter your OpenStack Password: " - # read -sr OS_PASSWORD_INPUT - # export OS_PASSWORD=$OS_PASSWORD_INPUT - if value.startswith('$'): - continue - # now match against wanted variable names - if name == 'USERNAME': - self.rc_username = value - elif name == 'AUTH_URL': - self.rc_auth_url = value - elif name == 'TENANT_NAME': - self.rc_tenant_name = value + self.openrc_contents = open(openrc_file).read() + self._init_with_openrc_(self.openrc_contents) else: LOG.error("rc file does not exist %s" % openrc_file) success = False + return + + if self.openrc_contents: + self._init_with_openrc_(self.openrc_contents) elif not no_env: # no openrc file passed - we assume the variables have been # sourced by the calling shell diff --git a/scale/kb_config.py b/scale/kb_config.py index 6bbb7a8..a5e91db 100644 --- a/scale/kb_config.py +++ b/scale/kb_config.py @@ -75,39 +75,7 @@ class KBConfig(object): self.client_cfg = None self.topo_cfg = None - def init_with_cli(self): - self.get_credentials() - self.get_configs() - self.get_topo_cfg() - - def init_with_rest_api(self, **kwargs): - self.cred_tested = kwargs['cred_tested'] - self.cred_testing = kwargs['cred_testing'] - self.server_cfg = kwargs['server_cfg'] - self.client_cfg = kwargs['client_cfg'] - self.topo_cfg = kwargs['topo_cfg'] - - def get_total_vm_count(self, config): - return (config['number_tenants'] * config['users_per_tenant'] * - config['routers_per_user'] * config['networks_per_router'] * - config['vms_per_network']) - - def get_credentials(self): - # Retrieve the credentials - self.cred_tested = credentials.Credentials(CONF.tested_rc, CONF.passwd_tested, CONF.no_env) - if CONF.testing_rc and CONF.testing_rc != CONF.tested_rc: - self.cred_testing = credentials.Credentials(CONF.testing_rc, - CONF.passwd_testing, - CONF.no_env) - else: - # Use the same openrc file for both cases - self.cred_testing = self.cred_tested - - def get_configs(self): - if CONF.config: - alt_config = configure.Configuration.from_file(CONF.config).configure() - self.config_scale = self.config_scale.merge(alt_config) - + def update_configs(self): # Initialize the key pair name if self.config_scale['public_key_file']: # verify the public key file exists @@ -137,6 +105,41 @@ class KBConfig(object): self.client_cfg['vms_per_network'] =\ self.get_total_vm_count(self.server_cfg) + 1 + def init_with_cli(self): + self.get_credentials() + self.get_configs() + self.get_topo_cfg() + self.update_configs() + + def init_with_rest_api(self, **kwargs): + self.cred_tested = kwargs['cred_tested'] + self.cred_testing = kwargs['cred_testing'] + self.topo_cfg = kwargs['topo_cfg'] + self.update_configs() + + def get_total_vm_count(self, config): + return (config['number_tenants'] * config['users_per_tenant'] * + config['routers_per_user'] * config['networks_per_router'] * + config['vms_per_network']) + + def get_credentials(self): + # Retrieve the credentials + self.cred_tested = credentials.Credentials(openrc_file=CONF.tested_rc, + pwd=CONF.passwd_tested, + no_env=CONF.no_env) + if CONF.testing_rc and CONF.testing_rc != CONF.tested_rc: + self.cred_testing = credentials.Credentials(openrc_file=CONF.testing_rc, + pwd=CONF.passwd_testing, + no_env=CONF.no_env) + else: + # Use the same openrc file for both cases + self.cred_testing = self.cred_tested + + def get_configs(self): + if CONF.config: + alt_config = configure.Configuration.from_file(CONF.config).configure() + self.config_scale = self.config_scale.merge(alt_config) + def get_topo_cfg(self): if CONF.topology: self.topo_cfg = configure.Configuration.from_file(CONF.topology).configure() diff --git a/scale/kb_server/kb_server/controllers/config.py b/scale/kb_server/kb_server/controllers/config.py index a3c559a..1bd44b1 100644 --- a/scale/kb_server/kb_server/controllers/config.py +++ b/scale/kb_server/kb_server/controllers/config.py @@ -17,23 +17,78 @@ import sys kb_main_path = os.path.split(os.path.abspath(__file__))[0] + "/../../.." sys.path.append(kb_main_path) +from credentials import Credentials + +from configure import Configuration from kb_config import KBConfig from pecan import expose +from pecan import response class ConfigController(object): def __init__(self): self.kb_config = KBConfig() - self.cur_config = None + self.status = 'READY' + self.def_config = self.kb_config.config_scale @expose(generic=True) def default_config(self): - def_config = self.kb_config.config_scale - return str(def_config) + return str(self.def_config) @expose(generic=True) - def current_config(self): - return str(self.cur_config) + def running_config(self): + return str(self.kb_config.config_scale) + + @running_config.when(method='POST') + def running_config_POST(self, args): + try: + user_config = eval(args) + except Exception: + response.status = 403 + response.text = "Error while parsing configurations!" + return response.text + + # Expectation: + # { + # 'credentials': {'tested_rc': '', 'passwd_tested': '', + # 'testing_rc': '', 'passwd_testing': ''}, + # 'kb_cfg': {}, + # 'topo_cfg': {} + # } + + # Parsing credentials from application input + cred_config = user_config['credentials'] + cred_tested = Credentials(openrc_contents=cred_config['tested_rc'], + pwd=cred_config['passwd_tested']) + if ('testing_rc' in cred_config and cred_config['testing_rc'] != cred_config['tested_rc']): + cred_testing = Credentials(openrc_contents=cred_config['testing_rc'], + pwd=cred_config['passwd_testing']) + else: + # Use the same openrc file for both cases + cred_testing = cred_tested + + # Parsing server and client configs from application input + # Save the public key into a temporary file + if 'public_key' in user_config['kb_cfg']: + pubkey_filename = '/tmp/kb_public_key.pub' + f = open(pubkey_filename, 'w') + f.write(user_config['kb_cfg']['public_key_file']) + f.close() + self.kb_config.config_scale['public_key_file'] = pubkey_filename + + alt_config = Configuration.from_string(user_config['kb_cfg']).configure() + self.kb_config.config_scale = self.kb_config.config_scale.merge(alt_config) + + # Parsing topology configs from application input + if 'topo_cfg' in user_config: + topo_cfg = Configuration.from_string(user_config['topo_cfg']).configure() + else: + topo_cfg = None + + self.kb_config.init_with_rest_api(cred_tested=cred_tested, + cred_testing=cred_testing, + topo_cfg=topo_cfg) + return str(self.kb_config.config_scale) @expose(generic=True) def status(self): diff --git a/scale/kloudbuster.py b/scale/kloudbuster.py index 9a055f9..5c7ff8c 100644 --- a/scale/kloudbuster.py +++ b/scale/kloudbuster.py @@ -120,7 +120,12 @@ class Kloud(object): def delete_resources(self): # Deleting flavors created by KloudBuster - nova_client = self.tenant_list[0].user_list[0].nova_client + try: + nova_client = self.tenant_list[0].user_list[0].nova_client + except Exception: + # NOVA Client is not yet initialized, so skip cleaning up... + return + flavor_manager = base_compute.Flavor(nova_client) if self.testing_side: flavor_manager.delete_flavor('kb.client') @@ -370,7 +375,8 @@ class KloudBuster(object): total_vm = self.get_tenant_vm_count(self.server_cfg) server_quota = {} - server_quota['network'] = self.server_cfg['networks_per_router'] + server_quota['network'] = self.server_cfg['routers_per_user'] *\ + self.server_cfg['networks_per_router'] server_quota['subnet'] = server_quota['network'] server_quota['router'] = self.server_cfg['routers_per_user'] if (self.server_cfg['use_floatingip']):