#2064: add handling of offline service to dns, ftp and database
This commit is contained in:
@@ -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":
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user