blob: c302d8cac1dee88a9fd8a23f70b7afe55ac5cde5 [file] [log] [blame]
#
# Copyright 2016-present Ciena Corporation
#
# 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.
#
from CordContainer import Container, Onos, OnosStopWrapper, OnosCord, OnosCordStopWrapper, Quagga, QuaggaStopWrapper, Radius, reinitContainerClients
from nose.tools import nottest
from SimpleXMLRPCServer import SimpleXMLRPCServer
from resource import getrlimit, RLIMIT_NOFILE
import daemon
import xmlrpclib
import os
import signal
import json
import time
import threading
##Server to handle container restart/stop requests from test container.
##Used now to restart ONOS from vrouter test container
CORD_TEST_HOST = '172.17.0.1'
CORD_TEST_PORT = 25000
class CordTestServer(object):
onos_cord = None
def __restart_onos(self, node = None, config = None, timeout = 10):
if self.onos_cord:
onos_config = '{}/network-cfg.json'.format(self.onos_cord.onos_config_dir)
else:
onos_config = '{}/network-cfg.json'.format(Onos.host_config_dir)
if config is None:
try:
os.unlink(onos_config)
except:
pass
print('Restarting ONOS')
if self.onos_cord:
self.onos_cord.start(restart = True, network_cfg = config)
else:
Onos.restart_node(node = node, network_cfg = config, timeout = timeout)
return 'DONE'
def restart_onos(self, kwargs):
return self.__restart_onos(**kwargs)
def __shutdown_onos(self, node = None):
if node is None:
node = Onos.NAME
OnosStopWrapper(node)
return 'DONE'
def shutdown_onos(self, kwargs):
return self.__shutdown_onos(**kwargs)
def __restart_cluster(self, config = None, timeout = 10, setup = False):
Onos.restart_cluster(network_cfg = config, timeout = timeout, setup = setup)
return 'DONE'
def restart_cluster(self, kwargs):
return self.__restart_cluster(**kwargs)
def __add_cluster_onos(self, count = 1, config = None):
Onos.add_cluster(count = count, network_cfg = config)
return 'DONE'
def add_cluster_onos(self, kwargs):
return self.__add_cluster_onos(**kwargs)
def __restart_quagga(self, config = None, boot_delay = 30 ):
config_file = Quagga.quagga_config_file
if config is not None:
quagga_config = '{}/testrib_gen.conf'.format(Quagga.host_quagga_config)
config_file = '{}/testrib_gen.conf'.format(Quagga.guest_quagga_config)
with open(quagga_config, 'w+') as fd:
fd.write(str(config))
print('Restarting QUAGGA with config file %s, delay %d' %(config_file, boot_delay))
Quagga(prefix = Container.IMAGE_PREFIX, restart = True, config_file = config_file, boot_delay = boot_delay)
return 'DONE'
def restart_quagga(self, kwargs):
return self.__restart_quagga(**kwargs)
def stop_quagga(self):
quaggaStop = QuaggaStopWrapper()
time.sleep(5)
try:
quagga_config_gen = '{}/testrib_gen.conf'.format(Quagga.host_quagga_config)
os.unlink(quagga_config_gen)
except: pass
return 'DONE'
def __run_shell_quagga(self, cmd = None):
ret = 0
if cmd is not None:
exec_cmd = 'docker exec {} {}'.format(Quagga.NAME, cmd)
ret = os.system(exec_cmd)
return ret
def __run_shell(self, cmd = None):
ret = 0
if cmd is not None:
ret = os.system(cmd)
return ret
def run_shell_quagga(self, kwargs):
return self.__run_shell_quagga(**kwargs)
def run_shell(self, kwargs):
return self.__run_shell(**kwargs)
def restart_radius(self):
print('Restarting RADIUS Server')
Radius(prefix = Container.IMAGE_PREFIX, restart = True)
return 'DONE'
def shutdown(self):
print('Shutting down cord test server')
os.kill(0, signal.SIGKILL)
return 'DONE'
def find_files_by_path(*paths):
wanted = []
for p in paths:
try:
fd = os.open(p, os.O_RDONLY)
wanted.append(os.fstat(fd)[1:3])
finally:
os.close(fd)
def fd_wanted(fd):
try:
return os.fstat(fd)[1:3] in wanted
except OSError:
return False
max_fd = getrlimit(RLIMIT_NOFILE)[1]
return [ fd for fd in xrange(max_fd) if fd_wanted(fd) ]
@nottest
def cord_test_server_start(daemonize = True,
cord_test_host = CORD_TEST_HOST,
cord_test_port = CORD_TEST_PORT,
onos_cord = None,
foreground=False):
server = SimpleXMLRPCServer( (cord_test_host, cord_test_port) )
server.register_instance(CordTestServer())
CordTestServer.onos_cord = onos_cord
if daemonize is True:
##before daemonizing, preserve urandom needed by paramiko
preserve_list = find_files_by_path('/dev/urandom')
preserve_list.append(server)
d = daemon.DaemonContext(files_preserve = preserve_list,
detach_process = True)
with d:
reinitContainerClients()
server.serve_forever()
else:
if foreground:
try:
server.serve_forever()
except KeyboardInterrupt:
return server
else:
task = threading.Thread(target = server.serve_forever)
##terminate when main thread exits
task.daemon = True
task.start()
return server
@nottest
def cord_test_server_stop(server):
server.shutdown()
server.server_close()
@nottest
def get_cord_test_loc():
host = os.getenv('CORD_TEST_HOST', CORD_TEST_HOST)
port = int(os.getenv('CORD_TEST_PORT', CORD_TEST_PORT))
return host, port
def rpc_server_instance():
'''Stateless'''
host, port = get_cord_test_loc()
rpc_server = 'http://{}:{}'.format(host, port)
return xmlrpclib.Server(rpc_server, allow_none = True)
@nottest
def __cord_test_onos_restart(**kwargs):
return rpc_server_instance().restart_onos(kwargs)
@nottest
def cord_test_onos_restart(node = None, config = None, timeout = 10):
'''Send ONOS restart to server'''
for i in range(3):
try:
data = __cord_test_onos_restart(node = node, config = config, timeout = timeout)
if data == 'DONE':
return True
except:
time.sleep(2)
return False
@nottest
def __cord_test_onos_shutdown(**kwargs):
return rpc_server_instance().shutdown_onos(kwargs)
@nottest
def cord_test_onos_shutdown(node = None):
data = __cord_test_onos_shutdown(node = node)
if data == 'DONE':
return True
return False
@nottest
def __cord_test_restart_cluster(**kwargs):
return rpc_server_instance().restart_cluster(kwargs)
@nottest
def cord_test_restart_cluster(config = None, timeout = 10, setup = False):
for i in range(3):
try:
data = __cord_test_restart_cluster(config = config, timeout = timeout, setup = setup)
if data == 'DONE':
return True
except:
time.sleep(2)
return False
@nottest
def __cord_test_onos_add_cluster(**kwargs):
return rpc_server_instance().add_cluster_onos(kwargs)
@nottest
def cord_test_onos_add_cluster(count = 1, config = None):
data = __cord_test_onos_add_cluster(count = count, config = config)
if data == 'DONE':
return True
return False
@nottest
def __cord_test_quagga_restart(**kwargs):
return rpc_server_instance().restart_quagga(kwargs)
@nottest
def cord_test_quagga_restart(config = None, boot_delay = 30):
'''Send QUAGGA restart to server'''
data = __cord_test_quagga_restart(config = config, boot_delay = boot_delay)
if data == 'DONE':
return True
return False
@nottest
def __cord_test_quagga_shell(**kwargs):
return rpc_server_instance().run_shell_quagga(kwargs)
@nottest
def cord_test_quagga_shell(cmd = None):
'''Send QUAGGA shell cmd to server'''
return __cord_test_quagga_shell(cmd = cmd)
@nottest
def __cord_test_shell(**kwargs):
return rpc_server_instance().run_shell(kwargs)
@nottest
def cord_test_shell(cmd = None):
'''Send shell cmd to run remotely'''
return __cord_test_shell(cmd = cmd)
@nottest
def cord_test_quagga_stop():
data = rpc_server_instance().stop_quagga()
if data == 'DONE':
return True
return False
@nottest
def cord_test_radius_restart():
'''Send Radius server restart to server'''
data = rpc_server_instance().restart_radius()
if data == 'DONE':
return True
return False
@nottest
def cord_test_server_shutdown(host, port):
'''Shutdown the cord test server'''
rpc_server = 'http://{}:{}'.format(host, port)
try:
xmlrpclib.Server(rpc_server, allow_none = True).shutdown()
except: pass
return True