diff --git a/framework/python/src/api/api.py b/framework/python/src/api/api.py index 0ae7becd4..2bba5e62f 100644 --- a/framework/python/src/api/api.py +++ b/framework/python/src/api/api.py @@ -277,7 +277,9 @@ async def start_testrun(self, request: Request, response: Response): if self._testrun.get_session().get_status() in [ TestrunStatus.IN_PROGRESS, TestrunStatus.WAITING_FOR_DEVICE, - TestrunStatus.MONITORING + TestrunStatus.MONITORING, + TestrunStatus.VALIDATING + ]: LOGGER.debug("Testrun is already running. Cannot start another instance") response.status_code = status.HTTP_409_CONFLICT @@ -338,7 +340,8 @@ async def stop_testrun(self, response: Response): if (self._testrun.get_session().get_status() not in [TestrunStatus.IN_PROGRESS, TestrunStatus.WAITING_FOR_DEVICE, - TestrunStatus.MONITORING]): + TestrunStatus.MONITORING, + TestrunStatus.VALIDATING]): response.status_code = 404 return self._generate_msg(False, "Testrun is not currently running") diff --git a/framework/python/src/common/statuses.py b/framework/python/src/common/statuses.py index 4817d7cf8..c7487868a 100644 --- a/framework/python/src/common/statuses.py +++ b/framework/python/src/common/statuses.py @@ -23,6 +23,7 @@ class TestrunStatus: COMPLIANT = "Compliant" NON_COMPLIANT = "Non-Compliant" STOPPING = "Stopping" + VALIDATING = "Validating Network" class TestResult: diff --git a/framework/python/src/net_orc/network_orchestrator.py b/framework/python/src/net_orc/network_orchestrator.py index b2429275c..37858c4e1 100644 --- a/framework/python/src/net_orc/network_orchestrator.py +++ b/framework/python/src/net_orc/network_orchestrator.py @@ -136,10 +136,16 @@ def start_network(self): self.create_net() self.start_network_services() - if 'validate' in self._session.get_runtime_params(): - # Start the validator after network is ready - self.validator.start() - + try: + if 'validate' in self._session.get_runtime_params(): + # Start the validator after network is ready + self._session.set_status(TestrunStatus.VALIDATING) + self.validator.start() + self.validator.stop() + except Exception as e: + LOGGER.error(f'Validation failed {e}') + + self._session.set_status('Waiting for Device') # Get network ready (via Network orchestrator) LOGGER.debug('Network is ready') diff --git a/framework/python/src/net_orc/network_validator.py b/framework/python/src/net_orc/network_validator.py index d760970a3..c50d2463d 100644 --- a/framework/python/src/net_orc/network_validator.py +++ b/framework/python/src/net_orc/network_validator.py @@ -22,6 +22,7 @@ import getpass from common import logger from common import util +from net_orc.ovs_control import OVSControl LOGGER = logger.get_logger('validator') OUTPUT_DIR = 'runtime/validation' @@ -46,6 +47,8 @@ def __init__(self): shutil.rmtree(os.path.join(self._path, OUTPUT_DIR), ignore_errors=True) + self._ovs = OVSControl(session=None) + def start(self): """Start the network validator.""" LOGGER.debug('Starting validator') @@ -87,6 +90,8 @@ def _build_device(self, net_device): def _load_devices(self): LOGGER.info(f'Loading validators from {self._device_dir}') + # Reset device list before loading + self._net_devices = [] loaded_devices = 'Loaded the following validators: ' @@ -286,7 +291,6 @@ def _stop_network_device(self, net_device, kill=False): LOGGER.error(e) def _get_device_container(self, net_device): - LOGGER.debug('Resolving device container: ' + net_device.container_name) container = None try: client = docker.from_env() @@ -305,6 +309,9 @@ def _stop_network_devices(self, kill=False): if not net_device.enable_container: continue self._stop_network_device(net_device, kill) + # Remove the device port form the ovs bridge once validation is done + bridge_intf = DEVICE_BRIDGE + 'i-' + net_device.dir_name + self._ovs.delete_port(DEVICE_BRIDGE,bridge_intf) class FauxDevice: # pylint: disable=too-few-public-methods,too-many-instance-attributes diff --git a/framework/python/src/net_orc/ovs_control.py b/framework/python/src/net_orc/ovs_control.py index 08faa52c1..2c1e17776 100644 --- a/framework/python/src/net_orc/ovs_control.py +++ b/framework/python/src/net_orc/ovs_control.py @@ -59,6 +59,14 @@ def delete_flow(self, bridge_name, flow): success = util.run_command(f'ovs-ofctl del-flows {bridge_name} \'{flow}\'') return success + def delete_port(self, bridge_name, port): + # Delete a port from the bridge using ovs-ofctl commands + success=True + if self.port_exists(bridge_name, port): + LOGGER.debug(f'Deleting port {port} from bridge: {bridge_name}') + success = util.run_command(f'ovs-vsctl del-port {bridge_name} \'{port}\'') + return success + def get_bridge_ports(self, bridge_name): # Get a list of all the ports on a bridge response = util.run_command(f'ovs-vsctl list-ports {bridge_name}', diff --git a/modules/ui/src/app/mocks/testrun.mock.ts b/modules/ui/src/app/mocks/testrun.mock.ts index c90927cd3..3decf9973 100644 --- a/modules/ui/src/app/mocks/testrun.mock.ts +++ b/modules/ui/src/app/mocks/testrun.mock.ts @@ -159,6 +159,12 @@ export const MOCK_PROGRESS_DATA_WAITING_FOR_DEVICE: TestrunStatus = { started: null, }; +export const MOCK_PROGRESS_DATA_VALIDATING: TestrunStatus = { + ...MOCK_PROGRESS_DATA_IN_PROGRESS, + status: StatusOfTestrun.Validating, + started: null, +}; + export const MOCK_PROGRESS_DATA_WITH_ERROR: TestrunStatus = PROGRESS_DATA_RESPONSE(StatusOfTestrun.InProgress, null, { ...TEST_DATA, diff --git a/modules/ui/src/app/model/testrun-status.ts b/modules/ui/src/app/model/testrun-status.ts index faa707f92..f14dce652 100644 --- a/modules/ui/src/app/model/testrun-status.ts +++ b/modules/ui/src/app/model/testrun-status.ts @@ -66,6 +66,7 @@ export enum StatusOfTestrun { Idle = 'Idle', Monitoring = 'Monitoring', Error = 'Error', + Validating = 'Validating Network', } export enum StatusOfTestResult { diff --git a/modules/ui/src/app/pages/testrun/components/testrun-status-card/testrun-status-card.component.html b/modules/ui/src/app/pages/testrun/components/testrun-status-card/testrun-status-card.component.html index be4d3b259..9ca1d80b2 100644 --- a/modules/ui/src/app/pages/testrun/components/testrun-status-card/testrun-status-card.component.html +++ b/modules/ui/src/app/pages/testrun/components/testrun-status-card/testrun-status-card.component.html @@ -27,6 +27,10 @@

+ + @@ -105,6 +109,12 @@
+ +
+

Validating virtual network

+
+
+

diff --git a/modules/ui/src/app/pages/testrun/components/testrun-status-card/testrun-status-card.component.ts b/modules/ui/src/app/pages/testrun/components/testrun-status-card/testrun-status-card.component.ts index d84b692e1..101591c98 100644 --- a/modules/ui/src/app/pages/testrun/components/testrun-status-card/testrun-status-card.component.ts +++ b/modules/ui/src/app/pages/testrun/components/testrun-status-card/testrun-status-card.component.ts @@ -92,7 +92,8 @@ export class TestrunStatusCardComponent { return ( status === StatusOfTestrun.Monitoring || status === StatusOfTestrun.InProgress || - status === StatusOfTestrun.WaitingForDevice + status === StatusOfTestrun.WaitingForDevice || + status === StatusOfTestrun.Validating ); } diff --git a/modules/ui/src/app/pages/testrun/testrun.store.spec.ts b/modules/ui/src/app/pages/testrun/testrun.store.spec.ts index 449ffb408..24ffc6ba2 100644 --- a/modules/ui/src/app/pages/testrun/testrun.store.spec.ts +++ b/modules/ui/src/app/pages/testrun/testrun.store.spec.ts @@ -43,6 +43,7 @@ import { MOCK_PROGRESS_DATA_IN_PROGRESS_EMPTY, MOCK_PROGRESS_DATA_MONITORING, MOCK_PROGRESS_DATA_WAITING_FOR_DEVICE, + MOCK_PROGRESS_DATA_VALIDATING, TEST_DATA_RESULT_WITH_RECOMMENDATIONS, TEST_DATA_TABLE_RESULT, } from '../../mocks/testrun.mock'; @@ -171,6 +172,21 @@ describe('TestrunStore', () => { }); }); + it('should set value with empty values for status "Validating Network"', done => { + const expectedResult = EMPTY_RESULT; + + store.overrideSelector( + selectSystemStatus, + MOCK_PROGRESS_DATA_VALIDATING + ); + store.refreshState(); + + testrunStore.viewModel$.pipe(take(1)).subscribe(store => { + expect(store.dataSource).toEqual(expectedResult); + done(); + }); + }); + it('should set value with empty values for status "Cancelled" and empty result', done => { const expectedResult = EMPTY_RESULT; diff --git a/modules/ui/src/app/pages/testrun/testrun.store.ts b/modules/ui/src/app/pages/testrun/testrun.store.ts index 2dc0c19f1..351ec10d1 100644 --- a/modules/ui/src/app/pages/testrun/testrun.store.ts +++ b/modules/ui/src/app/pages/testrun/testrun.store.ts @@ -99,6 +99,7 @@ export class TestrunStore extends ComponentStore { // perform some additional actions tap(res => { if ( + res?.status === StatusOfTestrun.Validating || res?.status === StatusOfTestrun.WaitingForDevice || res?.status === StatusOfTestrun.Monitoring || (res?.status === StatusOfTestrun.InProgress && @@ -119,6 +120,7 @@ export class TestrunStore extends ComponentStore { tap(res => { const results = (res?.tests as TestsData)?.results || []; if ( + res?.status === StatusOfTestrun.Validating || res?.status === StatusOfTestrun.Monitoring || res?.status === StatusOfTestrun.WaitingForDevice || (res?.status === StatusOfTestrun.Cancelled && !results.length) @@ -208,7 +210,8 @@ export class TestrunStore extends ComponentStore { return ( status === StatusOfTestrun.InProgress || status === StatusOfTestrun.WaitingForDevice || - status === StatusOfTestrun.Monitoring + status === StatusOfTestrun.Monitoring || + status === StatusOfTestrun.Validating ); } diff --git a/modules/ui/src/app/services/test-run.service.spec.ts b/modules/ui/src/app/services/test-run.service.spec.ts index 113f72c8f..d50a9e8fc 100644 --- a/modules/ui/src/app/services/test-run.service.spec.ts +++ b/modules/ui/src/app/services/test-run.service.spec.ts @@ -366,6 +366,7 @@ describe('TestRunService', () => { StatusOfTestrun.InProgress, StatusOfTestrun.WaitingForDevice, StatusOfTestrun.Monitoring, + StatusOfTestrun.Validating, ]; const resultsNotInProgress = [ diff --git a/modules/ui/src/app/services/test-run.service.ts b/modules/ui/src/app/services/test-run.service.ts index c517f7004..d7539d2ab 100644 --- a/modules/ui/src/app/services/test-run.service.ts +++ b/modules/ui/src/app/services/test-run.service.ts @@ -192,7 +192,8 @@ export class TestRunService { return ( status === StatusOfTestrun.InProgress || status === StatusOfTestrun.WaitingForDevice || - status === StatusOfTestrun.Monitoring + status === StatusOfTestrun.Monitoring || + status === StatusOfTestrun.Validating ); }