##
# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
-# This file is part of openmano
+# This file is part of openvim
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
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,
'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
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"
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"):
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)
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:
#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:<host_bridge_name>, 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
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()