#2064: add handling of offline service to dns, ftp and database

This commit is contained in:
Czar Echavez
2023-11-23 21:48:11 +00:00
parent bd6c27244c
commit f0fc6518a0
8 changed files with 86 additions and 9 deletions

View File

@@ -173,6 +173,9 @@ class DatabaseService(Service):
:param session_id: The session identifier. :param session_id: The session identifier.
:return: True if the Status Code is 200, otherwise False. :return: True if the Status Code is 200, otherwise False.
""" """
if not super().receive(payload=payload, session_id=session_id, **kwargs):
return False
result = {"status_code": 500, "data": []} result = {"status_code": 500, "data": []}
if isinstance(payload, dict) and payload.get("type"): if isinstance(payload, dict) and payload.get("type"):
if payload["type"] == "connect_request": if payload["type"] == "connect_request":

View File

@@ -88,10 +88,14 @@ class DNSServer(Service):
:return: True if DNS request returns a valid IP, otherwise, False :return: True if DNS request returns a valid IP, otherwise, False
""" """
if not super().receive(payload=payload, session_id=session_id, **kwargs):
return False
# The payload should be a DNS packet # The payload should be a DNS packet
if not isinstance(payload, DNSPacket): if not isinstance(payload, DNSPacket):
_LOGGER.debug(f"{payload} is not a DNSPacket") _LOGGER.debug(f"{payload} is not a DNSPacket")
return False return False
# cast payload into a DNS packet # cast payload into a DNS packet
payload: DNSPacket = payload payload: DNSPacket = payload
if payload.dns_request is not None: if payload.dns_request is not None:

View File

@@ -86,10 +86,10 @@ class FTPServer(FTPServiceABC):
prevents an FTP request loop - FTP client and servers can exist on prevents an FTP request loop - FTP client and servers can exist on
the same node. the same node.
""" """
if payload.status_code is not None: if not super().receive(payload=payload, session_id=session_id, **kwargs):
return False return False
if not super().receive(payload=payload, session_id=session_id, **kwargs): if payload.status_code is not None:
return False return False
self.send(self._process_ftp_command(payload=payload, session_id=session_id), session_id) self.send(self._process_ftp_command(payload=payload, session_id=session_id), session_id)

View File

@@ -155,12 +155,12 @@ class WebServer(Service):
:param: payload: The payload to send. :param: payload: The payload to send.
:param: session_id: The id of the session. Optional. :param: session_id: The id of the session. Optional.
""" """
if not super().receive(payload=payload, session_id=session_id, **kwargs):
return False
# check if the payload is an HTTPPacket # check if the payload is an HTTPPacket
if not isinstance(payload, HttpRequestPacket): if not isinstance(payload, HttpRequestPacket):
self.sys_log.error("Payload is not an HTTPPacket") self.sys_log.error("Payload is not an HTTPPacket")
return False return False
if not super().receive(payload=payload, session_id=session_id, **kwargs):
return False
return self._process_http_request(payload=payload, session_id=session_id) return self._process_http_request(payload=payload, session_id=session_id)

View File

@@ -3,7 +3,7 @@ from enum import Enum
from ipaddress import IPv4Address from ipaddress import IPv4Address
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
from primaite.simulator.core import RequestManager, RequestType, SimComponent from primaite.simulator.core import _LOGGER, RequestManager, RequestType, SimComponent
from primaite.simulator.file_system.file_system import FileSystem, Folder from primaite.simulator.file_system.file_system import FileSystem, Folder
from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState
from primaite.simulator.network.transmission.transport_layer import Port from primaite.simulator.network.transmission.transport_layer import Port
@@ -264,5 +264,6 @@ class IOSoftware(Software):
""" """
# return false if node that software is on is off # return false if node that software is on is off
if self.software_manager and self.software_manager.node.operating_state is NodeOperatingState.OFF: if self.software_manager and self.software_manager.node.operating_state is NodeOperatingState.OFF:
_LOGGER.debug(f"{self.name} Error: {self.software_manager.node.hostname} is not online.")
return False return False
return True return True

View File

@@ -1,9 +1,11 @@
from ipaddress import IPv4Address from ipaddress import IPv4Address
from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState
from primaite.simulator.network.hardware.nodes.server import Server from primaite.simulator.network.hardware.nodes.server import Server
from primaite.simulator.system.applications.database_client import DatabaseClient from primaite.simulator.system.applications.database_client import DatabaseClient
from primaite.simulator.system.services.database.database_service import DatabaseService from primaite.simulator.system.services.database.database_service import DatabaseService
from primaite.simulator.system.services.ftp.ftp_server import FTPServer from primaite.simulator.system.services.ftp.ftp_server import FTPServer
from primaite.simulator.system.services.service import ServiceOperatingState
def test_database_client_server_connection(uc2_network): def test_database_client_server_connection(uc2_network):
@@ -55,7 +57,8 @@ def test_database_client_query(uc2_network):
"""Tests DB query across the network returns HTTP status 200 and date.""" """Tests DB query across the network returns HTTP status 200 and date."""
web_server: Server = uc2_network.get_node_by_hostname("web_server") web_server: Server = uc2_network.get_node_by_hostname("web_server")
db_client: DatabaseClient = web_server.software_manager.software["DatabaseClient"] db_client: DatabaseClient = web_server.software_manager.software["DatabaseClient"]
db_client.connect()
assert db_client.connected
assert db_client.query("SELECT") assert db_client.query("SELECT")
@@ -92,3 +95,28 @@ def test_restore_backup(uc2_network):
assert db_service.restore_backup() is True assert db_service.restore_backup() is True
assert db_service.file_system.get_file(folder_name="database", file_name="database.db") is not None assert db_service.file_system.get_file(folder_name="database", file_name="database.db") is not None
def test_database_client_cannot_query_offline_database_server(uc2_network):
"""Tests DB query across the network returns HTTP status 404 when db server is offline."""
db_server: Server = uc2_network.get_node_by_hostname("database_server")
db_service: DatabaseService = db_server.software_manager.software["DatabaseService"]
assert db_server.operating_state is NodeOperatingState.ON
assert db_service.operating_state is ServiceOperatingState.RUNNING
web_server: Server = uc2_network.get_node_by_hostname("web_server")
db_client: DatabaseClient = web_server.software_manager.software["DatabaseClient"]
assert db_client.connected
assert db_client.query("SELECT") is True
db_server.power_off()
for i in range(db_server.shut_down_duration + 1):
uc2_network.apply_timestep(timestep=i)
assert db_server.operating_state is NodeOperatingState.OFF
assert db_service.operating_state is ServiceOperatingState.STOPPED
assert db_client.query("SELECT") is False

View File

@@ -1,3 +1,4 @@
from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState
from primaite.simulator.network.hardware.nodes.computer import Computer from primaite.simulator.network.hardware.nodes.computer import Computer
from primaite.simulator.network.hardware.nodes.server import Server from primaite.simulator.network.hardware.nodes.server import Server
from primaite.simulator.system.services.dns.dns_client import DNSClient from primaite.simulator.system.services.dns.dns_client import DNSClient
@@ -24,3 +25,39 @@ def test_dns_client_server(uc2_network):
# arcd.com is registered in dns server and should be saved to cache # arcd.com is registered in dns server and should be saved to cache
assert dns_client.check_domain_exists(target_domain="arcd.com") assert dns_client.check_domain_exists(target_domain="arcd.com")
assert dns_client.dns_cache.get("arcd.com", None) is not None assert dns_client.dns_cache.get("arcd.com", None) is not None
assert len(dns_client.dns_cache) == 1
def test_dns_client_requests_offline_dns_server(uc2_network):
client_1: Computer = uc2_network.get_node_by_hostname("client_1")
domain_controller: Server = uc2_network.get_node_by_hostname("domain_controller")
dns_client: DNSClient = client_1.software_manager.software["DNSClient"]
dns_server: DNSServer = domain_controller.software_manager.software["DNSServer"]
assert dns_client.operating_state == ServiceOperatingState.RUNNING
assert dns_server.operating_state == ServiceOperatingState.RUNNING
dns_server.show()
# arcd.com is registered in dns server
assert dns_client.check_domain_exists(target_domain="arcd.com")
assert dns_client.dns_cache.get("arcd.com", None) is not None
assert len(dns_client.dns_cache) == 1
dns_client.dns_cache = {}
domain_controller.power_off()
for i in range(domain_controller.shut_down_duration + 1):
uc2_network.apply_timestep(timestep=i)
assert domain_controller.operating_state == NodeOperatingState.OFF
assert dns_server.operating_state == ServiceOperatingState.STOPPED
# this time it should not cache because dns server is not online
assert dns_client.check_domain_exists(target_domain="arcd.com") is False
assert dns_client.dns_cache.get("arcd.com", None) is None
assert len(dns_client.dns_cache) == 0

View File

@@ -3,6 +3,7 @@ from ipaddress import IPv4Address
import pytest import pytest
from primaite.simulator.network.hardware.base import Node from primaite.simulator.network.hardware.base import Node
from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState
from primaite.simulator.network.hardware.nodes.computer import Computer from primaite.simulator.network.hardware.nodes.computer import Computer
from primaite.simulator.network.hardware.nodes.server import Server from primaite.simulator.network.hardware.nodes.server import Server
from primaite.simulator.network.protocols.dns import DNSPacket, DNSReply, DNSRequest from primaite.simulator.network.protocols.dns import DNSPacket, DNSReply, DNSRequest
@@ -15,10 +16,13 @@ from primaite.simulator.system.services.dns.dns_server import DNSServer
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def dns_server() -> Node: def dns_server() -> Node:
node = Server( node = Server(
hostname="dns_server", ip_address="192.168.1.10", subnet_mask="255.255.255.0", default_gateway="192.168.1.1" hostname="dns_server",
ip_address="192.168.1.10",
subnet_mask="255.255.255.0",
default_gateway="192.168.1.1",
operating_state=NodeOperatingState.ON,
) )
node.software_manager.install(software_class=DNSServer) node.software_manager.install(software_class=DNSServer)
node.software_manager.software["DNSServer"].start()
return node return node