X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=openmanod;h=5a1701d5fe87e31cb14d303644a0790c0bb9af42;hb=6082b7d161e7ccfbb38c1b7938c88c2619b8f690;hp=190f7e3bc4121e5b60d22f1f85eb708070048b3e;hpb=ee272b991909be75507ed9b3fd2bd9db499e1bce;p=osm%2FRO.git diff --git a/openmanod b/openmanod index 190f7e3b..5a1701d5 100755 --- a/openmanod +++ b/openmanod @@ -22,7 +22,7 @@ # contact with: nfvlabs@tid.es ## -''' +""" openmano server. Main program that implements a reference NFVO (Network Functions Virtualisation Orchestrator). It interfaces with an NFV VIM through its API and offers a northbound interface, based on REST (openmano API), @@ -30,17 +30,13 @@ where NFV services are offered including the creation and deletion of VNF templa network service templates and network service instances. It loads the configuration file and launches the http_server thread that will listen requests using openmano API. -''' -__author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes" -__date__ ="$26-aug-2014 11:09:29$" -__version__="0.5.10-r520" -version_date="Apr 2017" -database_version="0.20" #expected database schema version +""" import time import sys import getopt import yaml +from os import getenv as os_getenv, path as os_path from jsonschema import validate as js_v, exceptions as js_e import logging import logging.handlers as log_handlers @@ -50,15 +46,24 @@ from osm_ro.openmano_schemas import config_schema from osm_ro.db_base import db_base_Exception import osm_ro +__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes" +__date__ = "$26-aug-2014 11:09:29$" +__version__ = "0.5.76-r586" +version_date = "Ago 2018" +database_version = 32 # expected database schema version + + global global_config global logger + class LoadConfigurationException(Exception): pass + def load_configuration(configuration_file): - default_tokens = {'http_port':9090, - 'http_host':'localhost', + default_tokens = {'http_port': 9090, + 'http_host': 'localhost', 'http_console_proxy': True, 'http_console_host': None, 'log_level': 'DEBUG', @@ -75,27 +80,30 @@ def load_configuration(configuration_file): config = yaml.load(config_str) #Validate configuration file with the config_schema js_v(config, config_schema) - + #Add default values tokens for k,v in default_tokens.items(): if k not in config: config[k]=v return config - + except yaml.YAMLError as e: error_pos = "" if hasattr(e, 'problem_mark'): mark = e.problem_mark error_pos = " at line:{} column:{}".format(mark.line+1, mark.column+1) - raise LoadConfigurationException("Bad YAML format at configuration file '{file}'{pos}".format(file=configuration_file, pos=error_pos) ) + raise LoadConfigurationException("Bad YAML format at configuration file '{file}'{pos}: {message}".format( + file=configuration_file, pos=error_pos, message=e)) except js_e.ValidationError as e: error_pos = "" if e.path: error_pos=" at '" + ":".join(map(str, e.path))+"'" - raise LoadConfigurationException("Invalid field at configuration file '{file}'{pos} {message}".format(file=configuration_file, pos=error_pos, message=str(e)) ) + raise LoadConfigurationException("Invalid field at configuration file '{file}'{pos} {message}".format( + file=configuration_file, pos=error_pos, message=e)) except Exception as e: - raise LoadConfigurationException("Cannot load configuration file '{file}' {message}".format(file=configuration_file, message=str(e) ) ) - + raise LoadConfigurationException("Cannot load configuration file '{file}' {message}".format( + file=configuration_file, message=e)) + def console_port_iterator(): '''this iterator deals with the http_console_ports @@ -115,42 +123,71 @@ def console_port_iterator(): yield port2 port2 += 1 index += 1 - - + + def usage(): print("Usage: ", sys.argv[0], "[options]") - print( " -v|--version: prints current version") - print( " -c|--config [configuration_file]: loads the configuration file (default: openmanod.cfg)") - print( " -h|--help: shows this help") - print( " -p|--port [port_number]: changes port number and overrides the port number in the configuration file (default: 9090)") - print( " -P|--adminport [port_number]: changes admin port number and overrides the port number in the configuration file (default: 9095)") - #print( " -V|--vnf-repository: changes the path of the vnf-repository and overrides the path in the configuration file") - print( " --log-socket-host HOST: send logs to this host") - print( " --log-socket-port PORT: send logs using this port (default: 9022)") - print( " --log-file FILE: send logs to this file") + print(" -v|--version: prints current version") + print(" -c|--config [configuration_file]: loads the configuration file (default: openmanod.cfg)") + print(" -h|--help: shows this help") + print(" -p|--port [port_number]: changes port number and overrides the port number in the configuration file (default: 9090)") + print(" -P|--adminport [port_number]: changes admin port number and overrides the port number in the configuration file (default: 9095)") + # print( " -V|--vnf-repository: changes the path of the vnf-repository and overrides the path in the configuration file") + print(" --log-socket-host HOST: send logs to this host") + print(" --log-socket-port PORT: send logs using this port (default: 9022)") + print(" --log-file FILE: send logs to this file") + print(" --create-tenant NAME: Try to creates this tenant name before starting, ignoring any errors as e.g. conflict") return - + + +def set_logging_file(log_file): + try: + file_handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=100e6, backupCount=9, delay=0) + file_handler.setFormatter(log_formatter_simple) + logger.addHandler(file_handler) + # logger.debug("moving logs to '%s'", global_config["log_file"]) + # remove initial stream handler + logging.root.removeHandler(logging.root.handlers[0]) + print ("logging on '{}'".format(log_file)) + except IOError as e: + raise LoadConfigurationException( + "Cannot open logging file '{}': {}. Check folder exist and permissions".format(log_file, e)) + + if __name__=="__main__": - #Configure logging step 1 + env_config = { + 'db_host': 'RO_DB_HOST', + 'db_name': 'RO_DB_NAME', + 'db_user': 'RO_DB_USER', + 'db_passwd': 'RO_DB_PASSWORD', + 'db_ovim_host': 'RO_DB_OVIM_HOST', + 'db_ovim_name': 'RO_DB_OVIM_NAME', + 'db_ovim_user': 'RO_DB_OVIM_USER', + 'db_ovim_passwd': 'RO_DB_OVIM_PASSWORD', + 'db_port': 'RO_DB_PORT', + 'db_port': 'RO_DB_PORT', + } + # Configure logging step 1 hostname = socket.gethostname() - #streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s" + # streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s" # "%(asctime)s %(name)s %(levelname)s %(filename)s:%(lineno)d %(funcName)s %(process)d: %(message)s" - log_formatter_complete = logging.Formatter( - '%(asctime)s.%(msecs)03d00Z[{host}@openmanod] %(filename)s:%(lineno)s severity:%(levelname)s logger:%(name)s log:%(message)s'.format(host=hostname), - datefmt='%Y-%m-%dT%H:%M:%S', - ) + log_formatter_complete = logging.Formatter('%(asctime)s.%(msecs)03d00Z[{host}@openmanod] %(filename)s:%(lineno)s ' + 'severity:%(levelname)s logger:%(name)s log:%(message)s'.format( + host=hostname), + datefmt='%Y-%m-%dT%H:%M:%S') log_format_simple = "%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)s %(message)s" log_formatter_simple = logging.Formatter(log_format_simple, datefmt='%Y-%m-%dT%H:%M:%S') logging.basicConfig(format=log_format_simple, level= logging.DEBUG) logger = logging.getLogger('openmano') logger.setLevel(logging.DEBUG) socket_handler = None - file_handler = None # Read parameters and configuration file httpthread = None try: - #load parameters and configuration - opts, args = getopt.getopt(sys.argv[1:], "hvc:V:p:P:", ["config=", "help", "version", "port=", "vnf-repository=", "adminport=", "log-socket-host=", "log-socket-port=", "log-file="]) + # load parameters and configuration + opts, args = getopt.getopt(sys.argv[1:], "hvc:V:p:P:", + ["config=", "help", "version", "port=", "vnf-repository=", "adminport=", + "log-socket-host=", "log-socket-port=", "log-file=", "create-tenant="]) port=None port_admin = None config_file = 'osm_ro/openmanod.cfg' @@ -158,7 +195,8 @@ if __name__=="__main__": log_file = None log_socket_host = None log_socket_port = None - + create_tenant = None + for o, a in opts: if o in ("-v", "--version"): print ("openmanod version " + __version__ + ' ' + version_date) @@ -181,11 +219,17 @@ if __name__=="__main__": log_socket_host = a elif o == "--log-file": log_file = a + elif o == "--create-tenant": + create_tenant = a else: assert False, "Unhandled option" + if log_file: + set_logging_file(log_file) global_config = load_configuration(config_file) + global_config["version"] = __version__ + global_config["version_date"] = version_date #print global_config - # Override parameters obtained by command line + # Override parameters obtained by command line on ENV if port: global_config['http_port'] = port if port_admin: @@ -194,12 +238,17 @@ if __name__=="__main__": global_config['log_socket_host'] = log_socket_host if log_socket_port: global_config['log_socket_port'] = log_socket_port - if log_file: - global_config['log_file'] = log_file + + # override with ENV + for config_key, env_var in env_config.items(): + if os_getenv(env_var): + global_config[config_key] = os_getenv(env_var) + + # if vnf_repository is not None: # global_config['vnf_repository'] = vnf_repository # else: -# if not 'vnf_repository' in global_config: +# if not 'vnf_repository' in global_config: # logger.error( os.getcwd() ) # global_config['vnf_repository'] = os.getcwd()+'/vnfrepo' # #print global_config @@ -210,7 +259,7 @@ if __name__=="__main__": # except Exception as e: # logger.error( "Error '%s'. Ensure the path 'vnf_repository' is properly set at %s",e.args[1], config_file) # exit(-1) - + global_config["console_port_iterator"] = console_port_iterator global_config["console_thread"]={} global_config["console_ports"]={} @@ -218,31 +267,26 @@ if __name__=="__main__": global_config["http_console_host"] = global_config["http_host"] if global_config["http_host"]=="0.0.0.0": global_config["http_console_host"] = socket.gethostname() - - #Configure logging STEP 2 + + # Configure logging STEP 2 if "log_host" in global_config: socket_handler= log_handlers.SocketHandler(global_config["log_socket_host"], global_config["log_socket_port"]) socket_handler.setFormatter(log_formatter_complete) - if global_config.get("log_socket_level") and global_config["log_socket_level"] != global_config["log_level"]: + if global_config.get("log_socket_level") and global_config["log_socket_level"] != global_config["log_level"]: socket_handler.setLevel(global_config["log_socket_level"]) logger.addHandler(socket_handler) - #logger.addHandler(log_handlers.SysLogHandler()) - if "log_file" in global_config: - try: - file_handler= logging.handlers.RotatingFileHandler(global_config["log_file"], maxBytes=100e6, backupCount=9, delay=0) - file_handler.setFormatter(log_formatter_simple) - logger.addHandler(file_handler) - #logger.debug("moving logs to '%s'", global_config["log_file"]) - #remove initial stream handler - logging.root.removeHandler(logging.root.handlers[0]) - print ("logging on '{}'".format(global_config["log_file"])) - except IOError as e: - raise LoadConfigurationException("Cannot open logging file '{}': {}. Check folder exist and permissions".format(global_config["log_file"], str(e)) ) - #logging.basicConfig(level = getattr(logging, global_config.get('log_level',"debug"))) + + # logger.addHandler(log_handlers.SysLogHandler()) + if log_file: + global_config['log_file'] = log_file + elif global_config.get('log_file'): + set_logging_file(global_config['log_file']) + + # logging.basicConfig(level = getattr(logging, global_config.get('log_level',"debug"))) logger.setLevel(getattr(logging, global_config['log_level'])) - logger.critical("Starting openmano server version: '%s %s' command: '%s'", + logger.critical("Starting openmano server version: '%s %s' command: '%s'", __version__, version_date, " ".join(sys.argv)) - + for log_module in ("nfvo", "http", "vim", "db", "console", "ovim"): log_level_module = "log_level_" + log_module log_file_module = "log_file_" + log_module @@ -251,40 +295,54 @@ if __name__=="__main__": logger_module.setLevel(global_config[log_level_module]) if log_file_module in global_config: try: - file_handler= logging.handlers.RotatingFileHandler(global_config[log_file_module], maxBytes=100e6, backupCount=9, delay=0) + file_handler = logging.handlers.RotatingFileHandler(global_config[log_file_module], + maxBytes=100e6, backupCount=9, delay=0) file_handler.setFormatter(log_formatter_simple) logger_module.addHandler(file_handler) except IOError as e: - raise LoadConfigurationException("Cannot open logging file '{}': {}. Check folder exist and permissions".format(global_config[log_file_module], str(e)) ) + raise LoadConfigurationException( + "Cannot open logging file '{}': {}. Check folder exist and permissions".format( + global_config[log_file_module], str(e)) ) global_config["logger_"+log_module] = logger_module #httpserver.logger = global_config["logger_http"] #nfvo.logger = global_config["logger_nfvo"] - + # Initialize DB connection mydb = nfvo_db.nfvo_db(); mydb.connect(global_config['db_host'], global_config['db_user'], global_config['db_passwd'], global_config['db_name']) + db_path = osm_ro.__path__[0] + "/database_utils" + if not os_path.exists(db_path + "/migrate_mano_db.sh"): + db_path = osm_ro.__path__[0] + "/../database_utils" try: r = mydb.get_db_version() - if r[1] != database_version: - logger.critical("DATABASE wrong version '%s'. \ - Try to upgrade/downgrade to version '%s' with '%s/database_utils/migrate_mano_db.sh'", - r[1], database_version, osm_ro.__path__[0]) + if r[0] != database_version: + logger.critical("DATABASE wrong version '{current}'. Try to upgrade/downgrade to version '{target}'" + " with '{db_path}/migrate_mano_db.sh {target}'".format( + current=r[0], target=database_version, db_path=db_path)) exit(-1) except db_base_Exception as e: - logger.critical("DATABASE is not a MANO one or it is a '0.0' version. Try to upgrade to version '%s' with \ - './database_utils/migrate_mano_db.sh'", database_version) + logger.critical("DATABASE is not valid. If you think it is corrupted, you can init it with" + " '{db_path}/init_mano_db.sh' script".format(db_path=db_path)) exit(-1) nfvo.global_config=global_config + if create_tenant: + try: + nfvo.new_tenant(mydb, {"name": create_tenant}) + except Exception as e: + if isinstance(e, nfvo.NfvoException) and e.http_code == 409: + pass # if tenant exist (NfvoException error 409), ignore + else: # otherwise print and error and continue + logger.error("Cannot create tenant '{}': {}".format(create_tenant, e)) nfvo.start_service(mydb) - + httpthread = httpserver.httpserver(mydb, False, global_config['http_host'], global_config['http_port']) - + httpthread.start() - if 'http_admin_port' in global_config: + if 'http_admin_port' in global_config: httpthreadadmin = httpserver.httpserver(mydb, True, global_config['http_host'], global_config['http_admin_port']) httpthreadadmin.start() - time.sleep(1) + time.sleep(1) logger.info('Waiting for http clients') print('Waiting for http clients') print('openmanod ready') @@ -314,6 +372,9 @@ if __name__=="__main__": except db_base_Exception as e: logger.critical(str(e)) exit(-1) + except nfvo.NfvoException as e: + logger.critical(str(e), exc_info=True) + exit(-1) nfvo.stop_service() if httpthread: httpthread.join(1)