X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=openvimd.py;h=b9d9d826af1e2fd5290e320f65bf2a32260d93e7;hb=refs%2Fchanges%2F17%2F1317%2F3;hp=cc2ae590b4b9c09c6a0cc8fe70789c6886ceb4d7;hpb=9a61c6b761065160d0889e7bd1e0f9fc37de5310;p=osm%2Fopenvim.git diff --git a/openvimd.py b/openvimd.py index cc2ae59..b9d9d82 100755 --- a/openvimd.py +++ b/openvimd.py @@ -28,33 +28,31 @@ and launches the rest of threads: http clients, openflow controller and host controllers ''' -__author__="Alfonso Tierno" -__date__ ="$10-jul-2014 12:07:15$" -__version__="0.4.7-r494" -version_date="Sep 2016" -database_version="0.7" #expected database schema version +__author__ = "Alfonso Tierno" +__date__ = "$10-jul-2014 12:07:15$" + import httpserver import auxiliary_functions as af import sys import getopt import time -import vim_db import yaml import os from jsonschema import validate as js_v, exceptions as js_e -import host_thread as ht -import dhcp_thread as dt -import openflow_thread as oft -import threading from vim_schema import config_schema import logging -import imp +import logging.handlers as log_handlers +import socket +import ovim global config_dic global logger logger = logging.getLogger('vim') +class LoadConfigurationException(Exception): + pass + def load_configuration(configuration_file): default_tokens ={'http_port':9080, 'http_host':'localhost', 'of_controller_nets_with_same_vlan':True, @@ -64,6 +62,10 @@ def load_configuration(configuration_file): 'log_level': "DEBUG", 'log_level_db': "ERROR", 'log_level_of': 'ERROR', + 'bridge_ifaces': {}, + 'network_type': 'ovs', + 'ovs_controller_user': 'osm_dhcp', + 'ovs_controller_file_path': '/var/lib/', } try: #First load configuration from configuration file @@ -104,30 +106,34 @@ def load_configuration(configuration_file): return (False, "Error loading configuration file '"+configuration_file+"': "+str(e)) return (True, config) -def create_database_connection(config_dic): - db = vim_db.vim_db( (config_dic["network_vlan_range_start"],config_dic["network_vlan_range_end"]), config_dic['log_level_db'] ); - if db.connect(config_dic['db_host'], config_dic['db_user'], config_dic['db_passwd'], config_dic['db_name']) == -1: - logger.error("Cannot connect to database %s at %s@%s", config_dic['db_name'], config_dic['db_user'], config_dic['db_host']) - exit(-1) - return db - def usage(): print "Usage: ", sys.argv[0], "[options]" print " -v|--version: prints current version" - print " -c|--config [configuration_file]: loads the configuration file (default: openvimd.cfg)" + print " -c|--config FILE: loads the configuration file (default: openvimd.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 " -p|--port PORT: changes port number and overrides the port number in the configuration file (default: 908)" + print " -P|--adminport PORT: changes admin port number and overrides the port number in the configuration file (default: not listen)" + print " --dbname NAME: changes db_name and overrides the db_name 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") return if __name__=="__main__": + hostname = socket.gethostname() #streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s" - streamformat = "%(asctime)s %(name)s %(levelname)s: %(message)s" - logging.basicConfig(format=streamformat, level= logging.DEBUG) + 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('openvim') logger.setLevel(logging.DEBUG) try: - opts, args = getopt.getopt(sys.argv[1:], "hvc:p:P:", ["config", "help", "version", "port", "adminport"]) + opts, args = getopt.getopt(sys.argv[1:], "hvc:p:P:", ["config=", "help", "version", "port=", "adminport=", "log-file=", "dbname="]) except getopt.GetoptError, err: # print help information and exit: logger.error("%s. Type -h for help", err) # will print something like "option -a not recognized" @@ -137,10 +143,12 @@ if __name__=="__main__": port=None port_admin = None config_file = 'openvimd.cfg' + log_file = None + db_name = None for o, a in opts: if o in ("-v", "--version"): - print "openvimd version", __version__, version_date + print "openvimd version", ovim.ovim.get_version(), ovim.ovim.get_version_date() print "(c) Copyright Telefonica" sys.exit(0) elif o in ("-h", "--help"): @@ -152,10 +160,18 @@ if __name__=="__main__": port = a elif o in ("-P", "--adminport"): port_admin = a + elif o in ("-P", "--dbname"): + db_name = a + elif o == "--log-file": + log_file = a else: assert False, "Unhandled option" + engine = None + http_thread = None + http_thread_admin = None + try: #Load configuration file r, config_dic = load_configuration(config_file) @@ -164,11 +180,27 @@ if __name__=="__main__": logger.error(config_dic) config_dic={} exit(-1) - logging.basicConfig(level = getattr(logging, config_dic['log_level'])) + if 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, str(e)) ) + logger.setLevel(getattr(logging, config_dic['log_level'])) + logger.critical("Starting openvim server command: '%s'", sys.argv[0]) #override parameters obtained by command line - if port is not None: config_dic['http_port'] = port - if port_admin is not None: config_dic['http_admin_port'] = port_admin + if port: + config_dic['http_port'] = port + if port_admin: + config_dic['http_admin_port'] = port_admin + if db_name: + config_dic['db_name'] = db_name #check mode if 'mode' not in config_dic: @@ -176,146 +208,29 @@ if __name__=="__main__": #allow backward compatibility of test_mode option if 'test_mode' in config_dic and config_dic['test_mode']==True: config_dic['mode'] = 'test' - if config_dic['mode'] == 'development' and ( 'development_bridge' not in config_dic or config_dic['development_bridge'] not in config_dic.get("bridge_ifaces",None) ): + if config_dic['mode'] == 'development' and config_dic['network_type'] == 'bridge' and \ + ( 'development_bridge' not in config_dic or config_dic['development_bridge'] not in config_dic.get("bridge_ifaces",None) ): logger.error("'%s' is not a valid 'development_bridge', not one of the 'bridge_ifaces'", config_file) exit(-1) - + if config_dic['mode'] != 'normal': print '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' print "!! Warning, openvimd in TEST mode '%s'" % config_dic['mode'] print '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' - config_dic['version'] = __version__ - - #Connect to database - db_http = create_database_connection(config_dic) - r = db_http.get_db_version() - if r[0]<0: - logger.error("DATABASE is not a VIM one or it is a '0.0' version. Try to upgrade to version '%s' with './database_utils/migrate_vim_db.sh'", database_version) - exit(-1) - elif r[1]!=database_version: - logger.error("DATABASE wrong version '%s'. Try to upgrade/downgrade to version '%s' with './database_utils/migrate_vim_db.sh'", r[1], database_version) - exit(-1) - db_of = create_database_connection(config_dic) - db_lock= threading.Lock() - config_dic['db'] = db_of - config_dic['db_lock'] = db_lock + config_dic['version'] = ovim.ovim.get_version() + config_dic["logger_name"] = "openvim" - #precreate interfaces; [bridge:, VLAN used at Host, uuid of network camping in this bridge, speed in Gbit/s - config_dic['dhcp_nets']=[] - config_dic['bridge_nets']=[] - for bridge,vlan_speed in config_dic["bridge_ifaces"].items(): - #skip 'development_bridge' - if config_dic['mode'] == 'development' and config_dic['development_bridge'] == bridge: - continue - config_dic['bridge_nets'].append( [bridge, vlan_speed[0], vlan_speed[1], None] ) - del config_dic["bridge_ifaces"] + engine = ovim.ovim(config_dic) + engine.start_service() - #check if this bridge is already used (present at database) for a network) - used_bridge_nets=[] - for brnet in config_dic['bridge_nets']: - r,nets = db_of.get_table(SELECT=('uuid',), FROM='nets',WHERE={'provider': "bridge:"+brnet[0]}) - if r>0: - brnet[3] = nets[0]['uuid'] - used_bridge_nets.append(brnet[0]) - if config_dic.get("dhcp_server"): - if brnet[0] in config_dic["dhcp_server"]["bridge_ifaces"]: - config_dic['dhcp_nets'].append(nets[0]['uuid']) - if len(used_bridge_nets) > 0 : - logger.info("found used bridge nets: " + ",".join(used_bridge_nets)) - #get nets used by dhcp - if config_dic.get("dhcp_server"): - for net in config_dic["dhcp_server"].get("nets", () ): - r,nets = db_of.get_table(SELECT=('uuid',), FROM='nets',WHERE={'name': net}) - if r>0: - config_dic['dhcp_nets'].append(nets[0]['uuid']) - - # get host list from data base before starting threads - r,hosts = db_of.get_table(SELECT=('name','ip_name','user','uuid'), FROM='hosts', WHERE={'status':'ok'}) - if r<0: - logger.error("Cannot get hosts from database %s", hosts) - exit(-1) - # create connector to the openflow controller - of_test_mode = False if config_dic['mode']=='normal' or config_dic['mode']=="OF only" else True - - if of_test_mode: - OF_conn = oft.of_test_connector({"of_debug": config_dic['log_level_of']} ) - else: - #load other parameters starting by of_ from config dict in a temporal dict - temp_dict={ "of_ip": config_dic['of_controller_ip'], - "of_port": config_dic['of_controller_port'], - "of_dpid": config_dic['of_controller_dpid'], - "of_debug": config_dic['log_level_of'] - } - for k,v in config_dic.iteritems(): - if type(k) is str and k[0:3]=="of_" and k[0:13] != "of_controller": - temp_dict[k]=v - if config_dic['of_controller']=='opendaylight': - module = "ODL" - elif "of_controller_module" in config_dic: - module = config_dic["of_controller_module"] - else: - module = config_dic['of_controller'] - module_info=None - try: - module_info = imp.find_module(module) - - OF_conn = imp.load_module("OF_conn", *module_info) - try: - OF_conn = OF_conn.OF_conn(temp_dict) - except Exception as e: - logger.error("Cannot open the Openflow controller '%s': %s", type(e).__name__, str(e)) - if module_info and module_info[0]: - file.close(module_info[0]) - exit(-1) - except (IOError, ImportError) as e: - if module_info and module_info[0]: - file.close(module_info[0]) - logger.error("Cannot open openflow controller module '%s'; %s: %s; revise 'of_controller' field of configuration file.", module, type(e).__name__, str(e)) - exit(-1) - - - #create openflow thread - thread = oft.openflow_thread(OF_conn, of_test=of_test_mode, db=db_of, db_lock=db_lock, - pmp_with_same_vlan=config_dic['of_controller_nets_with_same_vlan'], - debug=config_dic['log_level_of']) - r,c = thread.OF_connector.obtain_port_correspondence() - if r<0: - logger.error("Cannot get openflow information %s", c) - exit() - thread.start() - config_dic['of_thread'] = thread - - #create dhcp_server thread - host_test_mode = True if config_dic['mode']=='test' or config_dic['mode']=="OF only" else False - dhcp_params = config_dic.get("dhcp_server") - if dhcp_params: - thread = dt.dhcp_thread(dhcp_params=dhcp_params, test=host_test_mode, dhcp_nets=config_dic["dhcp_nets"], db=db_of, db_lock=db_lock, debug=config_dic['log_level_of']) - thread.start() - config_dic['dhcp_thread'] = thread - - - #Create one thread for each host - host_test_mode = True if config_dic['mode']=='test' or config_dic['mode']=="OF only" else False - host_develop_mode = True if config_dic['mode']=='development' else False - host_develop_bridge_iface = config_dic.get('development_bridge', None) - config_dic['host_threads'] = {} - for host in hosts: - host['image_path'] = '/opt/VNF/images/openvim' - thread = ht.host_thread(name=host['name'], user=host['user'], host=host['ip_name'], db=db_of, db_lock=db_lock, - test=host_test_mode, image_path=config_dic['image_path'], version=config_dic['version'], - host_id=host['uuid'], develop_mode=host_develop_mode, develop_bridge_iface=host_develop_bridge_iface ) - thread.start() - config_dic['host_threads'][ host['uuid'] ] = thread - - #Create thread to listen to web requests - http_thread = httpserver.httpserver(db_http, 'http', config_dic['http_host'], config_dic['http_port'], False, config_dic) + http_thread = httpserver.httpserver(engine, 'http', config_dic['http_host'], config_dic['http_port'], False, config_dic) http_thread.start() - if 'http_admin_port' in config_dic: - db_http = create_database_connection(config_dic) - http_thread_admin = httpserver.httpserver(db_http, 'http-admin', config_dic['http_host'], config_dic['http_admin_port'], True) + if 'http_admin_port' in config_dic: + engine2 = ovim.ovim(config_dic) + http_thread_admin = httpserver.httpserver(engine2, 'http-admin', config_dic['http_host'], config_dic['http_admin_port'], True) http_thread_admin.start() else: http_thread_admin = None @@ -337,21 +252,27 @@ if __name__=="__main__": except (KeyboardInterrupt, SystemExit): pass + except SystemExit: + pass + except getopt.GetoptError as e: + logger.critical(str(e)) # will print something like "option -a not recognized" + #usage() + exit(-1) + except LoadConfigurationException as e: + logger.critical(str(e)) + exit(-1) + except ovim.ovimException as e: + logger.critical(str(e)) + exit(-1) logger.info('Exiting openvimd') - threads = config_dic.get('host_threads', {}) - if 'of_thread' in config_dic: - threads['of'] = (config_dic['of_thread']) - if 'dhcp_thread' in config_dic: - threads['dhcp'] = (config_dic['dhcp_thread']) - - for thread in threads.values(): - thread.insert_task("exit") - for thread in threads.values(): - thread.join() - #http_thread.join() - #if http_thread_admin is not None: - #http_thread_admin.join() + if engine: + engine.stop_service() + if http_thread: + http_thread.join(1) + if http_thread_admin: + http_thread_admin.join(1) + logger.debug( "bye!") exit()