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
42 changes: 41 additions & 1 deletion net_orc/python/src/network_orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,14 +469,54 @@ def _start_network_service(self, net_module):
privileged=True,
detach=True,
mounts=net_module.mounts,
environment={'HOST_USER': getpass.getuser()})
environment={'HOST_USER': self._get_host_user()})
except docker.errors.ContainerError as error:
LOGGER.error('Container run error')
LOGGER.error(error)

if network != 'host':
self._attach_service_to_network(net_module)

def _get_host_user(self):
user = self._get_os_user()

# If primary method failed, try secondary
if user is None:
user = self._get_user()

LOGGER.debug("Network orchestrator host user: " + user)
return user

def _get_os_user(self):
user = None
try:
user = os.getlogin()
except OSError as e:
# Handle the OSError exception
LOGGER.error("An OS error occurred while retrieving the login name.")
except Exception as e:
# Catch any other unexpected exceptions
LOGGER.error("An exception occurred:", e)
return user

def _get_user(self):
user = None
try:
user = getpass.getuser()
except (KeyError, ImportError, ModuleNotFoundError, OSError) as e:
# Handle specific exceptions individually
if isinstance(e, KeyError):
LOGGER.error("USER environment variable not set or unavailable.")
elif isinstance(e, ImportError):
LOGGER.error("Unable to import the getpass module.")
elif isinstance(e, ModuleNotFoundError):
LOGGER.error("The getpass module was not found.")
elif isinstance(e, OSError):
LOGGER.error("An OS error occurred while retrieving the username.")
else:
LOGGER.error("An exception occurred:", e)
return user

def _stop_service_module(self, net_module, kill=False):
LOGGER.debug('Stopping Service container ' + net_module.container_name)
try:
Expand Down
42 changes: 41 additions & 1 deletion net_orc/python/src/network_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def _start_network_device(self, device):
privileged=True,
detach=True,
mounts=device.mounts,
environment={'HOST_USER': getpass.getuser()})
environment={'HOST_USER': self._get_host_user()})
except docker.errors.ContainerError as error:
LOGGER.error('Container run error')
LOGGER.error(error)
Expand All @@ -167,6 +167,46 @@ def _start_network_device(self, device):

LOGGER.info('Validation device ' + device.name + ' has finished')

def _get_host_user(self):
user = self._get_os_user()

# If primary method failed, try secondary
if user is None:
user = self._get_user()

LOGGER.debug("Network validator host user: " + user)
return user

def _get_os_user(self):
user = None
try:
user = os.getlogin()
except OSError as e:
# Handle the OSError exception
LOGGER.error("An OS error occurred while retrieving the login name.")
except Exception as e:
# Catch any other unexpected exceptions
LOGGER.error("An exception occurred:", e)
return user

def _get_user(self):
user = None
try:
user = getpass.getuser()
except (KeyError, ImportError, ModuleNotFoundError, OSError) as e:
# Handle specific exceptions individually
if isinstance(e, KeyError):
LOGGER.error("USER environment variable not set or unavailable.")
elif isinstance(e, ImportError):
LOGGER.error("Unable to import the getpass module.")
elif isinstance(e, ModuleNotFoundError):
LOGGER.error("The getpass module was not found.")
elif isinstance(e, OSError):
LOGGER.error("An OS error occurred while retrieving the username.")
else:
LOGGER.error("An exception occurred:", e)
return user

def _get_device_status(self, module):
container = self._get_device_container(module)
if container is not None:
Expand Down
39 changes: 39 additions & 0 deletions test_orc/modules/conn/bin/start_test_module
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

# Setup and start the connection test module

# Define where the python source files are located
PYTHON_SRC_DIR=/testrun/python/src

# Fetch module name
MODULE_NAME=$1

# Default interface should be veth0 for all containers
DEFAULT_IFACE=veth0

# Allow a user to define an interface by passing it into this script
DEFINED_IFACE=$2

# Select which interace to use
if [[ -z $DEFINED_IFACE || "$DEFINED_IFACE" == "null" ]]
then
echo "No interface defined, defaulting to veth0"
INTF=$DEFAULT_IFACE
else
INTF=$DEFINED_IFACE
fi

# Create and set permissions on the log files
LOG_FILE=/runtime/output/$MODULE_NAME.log
RESULT_FILE=/runtime/output/$MODULE_NAME-result.json
touch $LOG_FILE
touch $RESULT_FILE
chown $HOST_USER:$HOST_USER $LOG_FILE
chown $HOST_USER:$HOST_USER $RESULT_FILE

# Run the python scrip that will execute the tests for this module
# -u flag allows python print statements
# to be logged by docker by running unbuffered
python3 -u $PYTHON_SRC_DIR/run.py "-m $MODULE_NAME"

echo Module has finished
22 changes: 22 additions & 0 deletions test_orc/modules/conn/conf/module_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"config": {
"meta": {
"name": "connection",
"display_name": "Connection",
"description": "Connection tests"
},
"network": true,
"docker": {
"depends_on": "base",
"enable_container": true,
"timeout": 30
},
"tests":[
{
"name": "connection.target_ping",
"description": "The device under test responds to an ICMP echo (ping) request.",
"expected_behavior": "The device under test responds to an ICMP echo (ping) request."
}
]
}
}
11 changes: 11 additions & 0 deletions test_orc/modules/conn/conn.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Image name: test-run/conn-test
FROM test-run/base-test:latest

# Copy over all configuration files
COPY modules/conn/conf /testrun/conf

# Load device binary files
COPY modules/conn/bin /testrun/bin

# Copy over all python files
COPY modules/conn/python /testrun/python
49 changes: 49 additions & 0 deletions test_orc/modules/conn/python/src/connection_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright 2023 Google LLC
#
# 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
#
# https://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.

"""Connection test module"""
import util
import sys
from test_module import TestModule

LOG_NAME = "test_connection"
LOGGER = None


class ConnectionModule(TestModule):
"""Connection Test module"""

def __init__(self, module):
super().__init__(module_name=module, log_name=LOG_NAME)
global LOGGER
LOGGER = self._get_logger()

def _connection_target_ping(self):
LOGGER.info("Running connection.target_ping")

# If the ipv4 address wasn't resolved yet, try again
if self._device_ipv4_addr is None:
self._device_ipv4_addr = self._get_device_ipv4(self)

if self._device_ipv4_addr is None:
LOGGER.error("No device IP could be resolved")
sys.exit(1)
else:
return self._ping(self._device_ipv4_addr)


def _ping(self, host):
cmd = 'ping -c 1 ' + str(host)
success = util.run_command(cmd, output=False)
return success
68 changes: 68 additions & 0 deletions test_orc/modules/conn/python/src/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright 2023 Google LLC
#
# 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
#
# https://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.

"""Run NMAP test module"""
import argparse
import signal
import sys
import logger

from connection_module import ConnectionModule

LOGGER = logger.get_logger('connection_module')


class ConnectionModuleRunner:
"""Run the Connection module tests."""

def __init__(self, module):

signal.signal(signal.SIGINT, self._handler)
signal.signal(signal.SIGTERM, self._handler)
signal.signal(signal.SIGABRT, self._handler)
signal.signal(signal.SIGQUIT, self._handler)

LOGGER.info('Starting connection module')

self._test_module = ConnectionModule(module)
self._test_module.run_tests()

def _handler(self, signum):
LOGGER.debug('SigtermEnum: ' + str(signal.SIGTERM))
LOGGER.debug('Exit signal received: ' + str(signum))
if signum in (2, signal.SIGTERM):
LOGGER.info('Exit signal received. Stopping connection test module...')
LOGGER.info('Test module stopped')
sys.exit(1)


def run():
parser = argparse.ArgumentParser(
description='Connection Module Help',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)

parser.add_argument(
'-m',
'--module',
help='Define the module name to be used to create the log file')

args = parser.parse_args()

# For some reason passing in the args from bash adds an extra
# space before the argument so we'll just strip out extra space
ConnectionModuleRunner(args.module.strip())


if __name__ == '__main__':
run()
43 changes: 42 additions & 1 deletion test_orc/python/src/test_orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def _run_test_module(self, module, device):
read_only=True),
],
environment={
"HOST_USER": getpass.getuser(),
"HOST_USER": self._get_host_user(),
"DEVICE_MAC": device.mac_addr,
"DEVICE_TEST_MODULES": device.test_modules,
"IPV4_SUBNET": self._net_orc.network_config.ipv4_network,
Expand Down Expand Up @@ -206,6 +206,47 @@ def _get_module_container(self, module):
LOGGER.error(error)
return container

def _get_host_user(self):
user = self._get_os_user()

# If primary method failed, try secondary
if user is None:
user = self._get_user()

LOGGER.debug("Test orchestrator host user: " + user)
return user

def _get_os_user(self):
user = None
try:
user = os.getlogin()
except OSError as e:
# Handle the OSError exception
LOGGER.error("An OS error occurred while retrieving the login name.")
except Exception as e:
# Catch any other unexpected exceptions
LOGGER.error("An exception occurred:", e)
return user

def _get_user(self):
user = None
try:
user = getpass.getuser()
except (KeyError, ImportError, ModuleNotFoundError, OSError) as e:
# Handle specific exceptions individually
if isinstance(e, KeyError):
LOGGER.error("USER environment variable not set or unavailable.")
elif isinstance(e, ImportError):
LOGGER.error("Unable to import the getpass module.")
elif isinstance(e, ModuleNotFoundError):
LOGGER.error("The getpass module was not found.")
elif isinstance(e, OSError):
LOGGER.error("An OS error occurred while retrieving the username.")
else:
LOGGER.error("An exception occurred:", e)
return user


def _load_test_modules(self):
"""Load network modules from module_config.json."""
LOGGER.debug("Loading test modules from /" + TEST_MODULES_DIR)
Expand Down