Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 3 additions & 132 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,136 +1,7 @@
# Runtime folder
runtime/
venv/
.vscode/

error
pylint.out
local/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/
__pycache__/
49 changes: 25 additions & 24 deletions framework/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,46 @@
import os

LOGGERS = {}
_LOG_FORMAT = "%(asctime)s %(name)-8s %(levelname)-7s %(message)s"
_LOG_FORMAT = '%(asctime)s %(name)-8s %(levelname)-7s %(message)s'
_DATE_FORMAT = '%b %02d %H:%M:%S'
_DEFAULT_LOG_LEVEL = logging.INFO
_LOG_LEVEL = logging.INFO
_CONF_DIR = "conf"
_CONF_FILE_NAME = "system.json"
_LOG_DIR = "runtime/testing/"
_CONF_DIR = 'conf'
_CONF_FILE_NAME = 'system.json'
_LOG_DIR = 'runtime/testing/'

# Set log level
with open(os.path.join(_CONF_DIR, _CONF_FILE_NAME), encoding='utf-8') as system_conf_file:
system_conf_json = json.load(system_conf_file)
with open(os.path.join(_CONF_DIR, _CONF_FILE_NAME),
encoding='utf-8') as system_conf_file:
system_conf_json = json.load(system_conf_file)
log_level_str = system_conf_json['log_level']

temp_log = logging.getLogger('temp')
try:
temp_log.setLevel(logging.getLevelName(log_level_str))
_LOG_LEVEL = logging.getLevelName(log_level_str)
temp_log.setLevel(logging.getLevelName(log_level_str))
_LOG_LEVEL = logging.getLevelName(log_level_str)
except ValueError:
print('Invalid log level set in ' + _CONF_DIR + '/' + _CONF_FILE_NAME +
'. Using INFO as log level')
_LOG_LEVEL = _DEFAULT_LOG_LEVEL
print('Invalid log level set in ' + _CONF_DIR + '/' + _CONF_FILE_NAME +
'. Using INFO as log level')
_LOG_LEVEL = _DEFAULT_LOG_LEVEL

log_format = logging.Formatter(fmt=_LOG_FORMAT, datefmt=_DATE_FORMAT)

def add_file_handler(log, log_file):
handler = logging.FileHandler(_LOG_DIR + log_file + ".log")
handler.setFormatter(log_format)
log.addHandler(handler)
handler = logging.FileHandler(_LOG_DIR + log_file + '.log')
handler.setFormatter(log_format)
log.addHandler(handler)

def add_stream_handler(log):
handler = logging.StreamHandler()
handler.setFormatter(log_format)
log.addHandler(handler)
handler = logging.StreamHandler()
handler.setFormatter(log_format)
log.addHandler(handler)

def get_logger(name, log_file=None):
if name not in LOGGERS:
LOGGERS[name] = logging.getLogger(name)
LOGGERS[name].setLevel(_LOG_LEVEL)
add_stream_handler(LOGGERS[name])
if log_file is not None:
add_file_handler(LOGGERS[name], log_file)
return LOGGERS[name]
if name not in LOGGERS:
LOGGERS[name] = logging.getLogger(name)
LOGGERS[name].setLevel(_LOG_LEVEL)
add_stream_handler(LOGGERS[name])
if log_file is not None:
add_file_handler(LOGGERS[name], log_file)
return LOGGERS[name]
93 changes: 46 additions & 47 deletions framework/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,61 +14,60 @@
import logger
import signal

LOGGER = logger.get_logger('runner')

LOGGER = logger.get_logger("runner")

class TestRunner:
"""Controls and starts the Test Run application."""

def __init__(self, config_file=None, validate=True, net_only=False, single_intf=False):
self._register_exits()
self.test_run = TestRun(config_file=config_file,
validate=validate,
net_only=net_only,
single_intf=single_intf)

def _register_exits(self):
signal.signal(signal.SIGINT, self._exit_handler)
signal.signal(signal.SIGTERM, self._exit_handler)
signal.signal(signal.SIGABRT, self._exit_handler)
signal.signal(signal.SIGQUIT, self._exit_handler)
def __init__(self, config_file=None, validate=True,
net_only=False, single_intf=False):
self._register_exits()
self.test_run = TestRun(config_file=config_file,
validate=validate,
net_only=net_only,
single_intf=single_intf)

def _exit_handler(self, signum, arg): # pylint: disable=unused-argument
LOGGER.debug("Exit signal received: " + str(signum))
if signum in (2, signal.SIGTERM):
LOGGER.info("Exit signal received.")
# Kill all container services quickly
# If we're here, we want everything to stop immediately
# and don't care about a gracefully shutdown
self._stop(True)
sys.exit(1)
def _register_exits(self):
signal.signal(signal.SIGINT, self._exit_handler)
signal.signal(signal.SIGTERM, self._exit_handler)
signal.signal(signal.SIGABRT, self._exit_handler)
signal.signal(signal.SIGQUIT, self._exit_handler)

def stop(self, kill=False):
self.test_run.stop(kill)
def _exit_handler(self, signum, arg): # pylint: disable=unused-argument
LOGGER.debug("Exit signal received: " + str(signum))
if signum in (2, signal.SIGTERM):
LOGGER.info("Exit signal received.")
# Kill all container services quickly
# If we're here, we want everything to stop immediately
# and don't care about a gracefully shutdown
self._stop(True)
sys.exit(1)

def start(self):
self.test_run.start()
LOGGER.info("Test Run has finished")
def stop(self, kill=False):
self.test_run.stop(kill)

def start(self):
self.test_run.start()
LOGGER.info("Test Run has finished")

def parse_args(argv):
parser = argparse.ArgumentParser(description="Test Run",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-f", "--config-file", default=None,
help="Define the configuration file for Test Run and Network Orchestrator")
parser.add_argument("--no-validate", action="store_true",
help="Turn off the validation of the network after network boot")
parser.add_argument("-net", "--net-only", action="store_true",
help="Run the network only, do not run tests")
parser.add_argument("--single-intf", action="store_true",
help="Single interface mode (experimental)")
args, unknown = parser.parse_known_args()
return args

parser = argparse.ArgumentParser(description="Test Run",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-f", "--config-file", default=None,
help="Define the configuration file for Test Run and Network Orchestrator")
parser.add_argument("--no-validate", action="store_true",
help="Turn off the validation of the network after network boot")
parser.add_argument("-net", "--net-only", action="store_true",
help="Run the network only, do not run tests")
parser.add_argument("--single-intf", action="store_true",
help="Single interface mode (experimental)")
parsed_args = parser.parse_known_args()[0]
return parsed_args

if __name__ == "__main__":
args = parse_args(sys.argv)
runner = TestRunner(config_file=args.config_file,
validate=not args.no_validate,
net_only=args.net_only,
single_intf=args.single_intf)
runner.start()
args = parse_args(sys.argv)
runner = TestRunner(config_file=args.config_file,
validate=not args.no_validate,
net_only=args.net_only,
single_intf=args.single_intf)
runner.start()
10 changes: 5 additions & 5 deletions framework/testrun.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class TestRun: # pylint: disable=too-few-public-methods
orchestrator and user interface.
"""

def __init__(self,
def __init__(self,
config_file=CONFIG_FILE,
validate=True,
net_only=False,
Expand Down Expand Up @@ -97,7 +97,7 @@ def start(self):

LOGGER.info('Waiting for devices on the network...')

# Check timeout and whether testing is currently
# Check timeout and whether testing is currently
# in progress before stopping
time.sleep(RUNTIME)

Expand Down Expand Up @@ -138,7 +138,7 @@ def _run_tests(self, device):
# To Do: Make this configurable
time.sleep(60) # Let device bootup

self._test_orc._run_test_modules(device)
self._test_orc.run_test_modules(device)

def _stop_network(self, kill=False):
self._net_orc.stop(kill=kill)
Expand All @@ -165,9 +165,9 @@ def _load_devices(self, device_dir):
mac_addr = device_config_json.get(DEVICE_MAC_ADDR)
test_modules = device_config_json.get(DEVICE_TEST_MODULES)

device = Device(make=device_make,
device = Device(make=device_make,
model=device_model,
mac_addr=mac_addr,
mac_addr=mac_addr,
test_modules=json.dumps(test_modules))
self._devices.append(device)

Expand Down
Loading