Fixed bugs regarding waiting for monkeys to die, readability improvements
This commit is contained in:
parent
91fe7c22a8
commit
018d3ddc08
|
@ -0,0 +1,17 @@
|
||||||
|
LOG_INIT_MESSAGE = "Analysis didn't run."
|
||||||
|
|
||||||
|
|
||||||
|
class AnalyzerLog(object):
|
||||||
|
|
||||||
|
def __init__(self, analyzer_name):
|
||||||
|
self.contents = LOG_INIT_MESSAGE
|
||||||
|
self.name = analyzer_name
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self.contents = ""
|
||||||
|
|
||||||
|
def add_entry(self, message):
|
||||||
|
self.contents = "{}\n{}".format(self.contents, message)
|
||||||
|
|
||||||
|
def get_contents(self):
|
||||||
|
return "{}: {}\n".format(self.name, self.contents)
|
|
@ -1,4 +1,4 @@
|
||||||
LOG_INIT_MESSAGE = "Analysis didn't run."
|
from envs.monkey_zoo.blackbox.analyzers.analyzer_log import AnalyzerLog
|
||||||
|
|
||||||
|
|
||||||
class CommunicationAnalyzer(object):
|
class CommunicationAnalyzer(object):
|
||||||
|
@ -10,29 +10,15 @@ class CommunicationAnalyzer(object):
|
||||||
|
|
||||||
def analyze_test_results(self):
|
def analyze_test_results(self):
|
||||||
self.log.clear()
|
self.log.clear()
|
||||||
|
all_monkeys_communicated = True
|
||||||
for machine_ip in self.machine_ips:
|
for machine_ip in self.machine_ips:
|
||||||
if not self.did_monkey_communicate_back(machine_ip):
|
if not self.did_monkey_communicate_back(machine_ip):
|
||||||
self.log.add_entry("Monkey from {} didn't communicate back".format(machine_ip))
|
self.log.add_entry("Monkey from {} didn't communicate back".format(machine_ip))
|
||||||
return False
|
all_monkeys_communicated = False
|
||||||
|
else:
|
||||||
self.log.add_entry("Monkey from {} communicated back".format(machine_ip))
|
self.log.add_entry("Monkey from {} communicated back".format(machine_ip))
|
||||||
return True
|
return all_monkeys_communicated
|
||||||
|
|
||||||
def did_monkey_communicate_back(self, machine_ip):
|
def did_monkey_communicate_back(self, machine_ip):
|
||||||
query = {'ip_addresses': {'$elemMatch': {'$eq': machine_ip}}}
|
query = {'ip_addresses': {'$elemMatch': {'$eq': machine_ip}}}
|
||||||
return len(self.island_client.find_monkeys_in_db(query)) > 0
|
return len(self.island_client.find_monkeys_in_db(query)) > 0
|
||||||
|
|
||||||
|
|
||||||
class AnalyzerLog(object):
|
|
||||||
|
|
||||||
def __init__(self, analyzer_name):
|
|
||||||
self.contents = LOG_INIT_MESSAGE
|
|
||||||
self.name = analyzer_name
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self.contents = ""
|
|
||||||
|
|
||||||
def add_entry(self, message):
|
|
||||||
self.contents = "{}\n{}".format(self.contents, message)
|
|
||||||
|
|
||||||
def get_contents(self):
|
|
||||||
return "{}: {}\n".format(self.name, self.contents)
|
|
||||||
|
|
|
@ -82,5 +82,5 @@ class MonkeyIslandClient(object):
|
||||||
return json.loads(response.content)['results']
|
return json.loads(response.content)['results']
|
||||||
|
|
||||||
def is_all_monkeys_dead(self):
|
def is_all_monkeys_dead(self):
|
||||||
query = {'dead': 'false'}
|
query = {'dead': False}
|
||||||
return len(self.find_monkeys_in_db(query)) == 0
|
return len(self.find_monkeys_in_db(query)) == 0
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class LogParser(object):
|
||||||
|
|
||||||
|
def __init__(self, log_path):
|
||||||
|
self.log_path = log_path
|
||||||
|
self.log_contents = self.read_log()
|
||||||
|
|
||||||
|
def read_log(self):
|
||||||
|
with open(self.log_path, 'r') as log:
|
||||||
|
return log.read()
|
||||||
|
|
||||||
|
def print_errors(self):
|
||||||
|
print("Errors:")
|
||||||
|
for error_line in LogParser.get_errors(self.log_contents):
|
||||||
|
print(error_line)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_errors(log_contents):
|
||||||
|
searcher = re.compile(r"^.*:ERROR].*$", re.MULTILINE)
|
||||||
|
return searcher.findall(log_contents)
|
||||||
|
|
||||||
|
def print_warnings(self):
|
||||||
|
print("Warnings:")
|
||||||
|
for warning_line in LogParser.get_warnings(self.log_contents):
|
||||||
|
print(warning_line)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_warnings(log_contents):
|
||||||
|
searcher = re.compile(r"^.*:WARNING].*$", re.MULTILINE)
|
||||||
|
return searcher.findall(log_contents)
|
|
@ -0,0 +1,22 @@
|
||||||
|
from envs.monkey_zoo.blackbox.log_handlers.monkey_log import MonkeyLog
|
||||||
|
|
||||||
|
|
||||||
|
class LogsDownloader(object):
|
||||||
|
|
||||||
|
def __init__(self, island_client, log_dir_path):
|
||||||
|
self.island_client = island_client
|
||||||
|
self.log_dir_path = log_dir_path
|
||||||
|
self.monkey_log_paths = []
|
||||||
|
|
||||||
|
def download_monkey_logs(self):
|
||||||
|
print("Downloading each monkey log.")
|
||||||
|
all_monkeys = self.island_client.find_monkeys_in_db(None)
|
||||||
|
for monkey in all_monkeys:
|
||||||
|
downloaded_log_path = self._download_monkey_log(monkey)
|
||||||
|
if downloaded_log_path:
|
||||||
|
self.monkey_log_paths.append(downloaded_log_path)
|
||||||
|
|
||||||
|
def _download_monkey_log(self, monkey):
|
||||||
|
log_handler = MonkeyLog(monkey, self.log_dir_path)
|
||||||
|
download_successful = log_handler.download_log(self.island_client)
|
||||||
|
return log_handler.get_log_path_for_monkey(monkey) if download_successful else None
|
|
@ -12,8 +12,10 @@ class MonkeyLog(object):
|
||||||
log = island_client.find_log_in_db({'monkey_id': ObjectId(self.monkey['id'])})
|
log = island_client.find_log_in_db({'monkey_id': ObjectId(self.monkey['id'])})
|
||||||
if not log:
|
if not log:
|
||||||
print("Log for monkey {} not found".format(self.monkey['ip_addresses'][0]))
|
print("Log for monkey {} not found".format(self.monkey['ip_addresses'][0]))
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.write_log_to_file(log)
|
self.write_log_to_file(log)
|
||||||
|
return True
|
||||||
|
|
||||||
def write_log_to_file(self, log):
|
def write_log_to_file(self, log):
|
||||||
with open(self.get_log_path_for_monkey(self.monkey), 'w') as log_file:
|
with open(self.get_log_path_for_monkey(self.monkey), 'w') as log_file:
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from envs.monkey_zoo.blackbox.log_handlers.monkey_log import MonkeyLog
|
from envs.monkey_zoo.blackbox.log_handlers.log_parser import LogParser
|
||||||
|
from envs.monkey_zoo.blackbox.log_handlers.logs_downloader import LogsDownloader
|
||||||
|
|
||||||
LOG_DIR_NAME = 'logs'
|
LOG_DIR_NAME = 'logs'
|
||||||
|
|
||||||
|
@ -12,12 +13,18 @@ class TestLogsHandler(object):
|
||||||
self.island_client = island_client
|
self.island_client = island_client
|
||||||
self.log_dir_path = os.path.join(TestLogsHandler.get_log_dir_path(), self.test_name)
|
self.log_dir_path = os.path.join(TestLogsHandler.get_log_dir_path(), self.test_name)
|
||||||
|
|
||||||
|
def parse_test_logs(self):
|
||||||
|
log_paths = self.download_logs()
|
||||||
|
if not log_paths:
|
||||||
|
print("No logs were downloaded, maybe no monkeys were ran?")
|
||||||
|
return
|
||||||
|
TestLogsHandler.parse_logs(log_paths)
|
||||||
|
|
||||||
def download_logs(self):
|
def download_logs(self):
|
||||||
self.try_create_log_dir_for_test()
|
self.try_create_log_dir_for_test()
|
||||||
print("Downloading logs")
|
downloader = LogsDownloader(self.island_client, self.log_dir_path)
|
||||||
all_monkeys = self.island_client.find_monkeys_in_db(None)
|
downloader.download_monkey_logs()
|
||||||
for monkey in all_monkeys:
|
return downloader.monkey_log_paths
|
||||||
MonkeyLog(monkey, self.log_dir_path).download_log(self.island_client)
|
|
||||||
|
|
||||||
def try_create_log_dir_for_test(self):
|
def try_create_log_dir_for_test(self):
|
||||||
try:
|
try:
|
||||||
|
@ -33,3 +40,11 @@ class TestLogsHandler(object):
|
||||||
def delete_log_folder_contents():
|
def delete_log_folder_contents():
|
||||||
shutil.rmtree(TestLogsHandler.get_log_dir_path(), ignore_errors=True)
|
shutil.rmtree(TestLogsHandler.get_log_dir_path(), ignore_errors=True)
|
||||||
os.mkdir(TestLogsHandler.get_log_dir_path())
|
os.mkdir(TestLogsHandler.get_log_dir_path())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_logs(log_paths):
|
||||||
|
for log_path in log_paths:
|
||||||
|
print("Info from log at {}".format(log_path))
|
||||||
|
log_parser = LogParser(log_path)
|
||||||
|
log_parser.print_errors()
|
||||||
|
log_parser.print_warnings()
|
|
@ -6,7 +6,7 @@ from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import Communicat
|
||||||
from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandConfigParser
|
from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandConfigParser
|
||||||
from envs.monkey_zoo.blackbox.utils import gcp_machine_handlers
|
from envs.monkey_zoo.blackbox.utils import gcp_machine_handlers
|
||||||
from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest
|
from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest
|
||||||
from envs.monkey_zoo.blackbox.log_handlers.test_logs import TestLogsHandler
|
from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler
|
||||||
|
|
||||||
DEFAULT_TIMEOUT_SECONDS = 4*60
|
DEFAULT_TIMEOUT_SECONDS = 4*60
|
||||||
MACHINE_BOOTUP_WAIT_SECONDS = 30
|
MACHINE_BOOTUP_WAIT_SECONDS = 30
|
||||||
|
@ -53,7 +53,7 @@ class TestMonkeyBlackbox(object):
|
||||||
analyzer = CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets())
|
analyzer = CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets())
|
||||||
BasicTest(test_name,
|
BasicTest(test_name,
|
||||||
island_client,
|
island_client,
|
||||||
config_parser.config_raw,
|
config_parser,
|
||||||
[analyzer],
|
[analyzer],
|
||||||
timeout_in_seconds).run()
|
timeout_in_seconds).run()
|
||||||
|
|
||||||
|
|
|
@ -1,35 +1,42 @@
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from envs.monkey_zoo.blackbox.utils.test_timer import TestTimer
|
from envs.monkey_zoo.blackbox.utils.test_timer import TestTimer
|
||||||
from envs.monkey_zoo.blackbox.log_handlers.test_logs import TestLogsHandler
|
from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler
|
||||||
|
|
||||||
MAX_TIME_FOR_MONKEYS_TO_DIE = 5*60
|
MAX_TIME_FOR_MONKEYS_TO_DIE = 5*60
|
||||||
WAIT_TIME_BETWEEN_REQUESTS = 10
|
WAIT_TIME_BETWEEN_REQUESTS = 10
|
||||||
|
TIME_FOR_MONKEY_PROCESS_TO_FINISH = 20
|
||||||
|
|
||||||
|
|
||||||
class BasicTest(object):
|
class BasicTest(object):
|
||||||
|
|
||||||
def __init__(self, name, island_client, island_config, analyzers, timeout):
|
def __init__(self, name, island_client, config_parser, analyzers, timeout):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.island_client = island_client
|
self.island_client = island_client
|
||||||
self.island_config = island_config
|
self.config_parser = config_parser
|
||||||
self.analyzers = analyzers
|
self.analyzers = analyzers
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.island_client.import_config(self.island_config)
|
self.island_client.import_config(self.config_parser.config_raw)
|
||||||
|
self.print_test_starting_info()
|
||||||
try:
|
try:
|
||||||
self.island_client.run_monkey_local()
|
self.island_client.run_monkey_local()
|
||||||
self.test_until_timeout()
|
self.test_until_timeout()
|
||||||
except AssertionError:
|
|
||||||
print("Test {} failed. Downloading logs of all monkeys.".format(self.name))
|
|
||||||
TestLogsHandler(self.name, self.island_client).download_logs()
|
|
||||||
raise
|
|
||||||
finally:
|
finally:
|
||||||
self.island_client.kill_all_monkeys()
|
self.island_client.kill_all_monkeys()
|
||||||
self.wait_until_monkeys_die()
|
self.wait_until_monkeys_die()
|
||||||
|
self.wait_for_monkey_process_to_finish()
|
||||||
|
self.parse_logs()
|
||||||
self.island_client.reset_env()
|
self.island_client.reset_env()
|
||||||
|
|
||||||
|
def print_test_starting_info(self):
|
||||||
|
print("Started {} test".format(self.name))
|
||||||
|
print("Machines participating in test:")
|
||||||
|
for target_ip in self.config_parser.get_ips_of_targets():
|
||||||
|
print(" "+target_ip)
|
||||||
|
print("")
|
||||||
|
|
||||||
def test_until_timeout(self):
|
def test_until_timeout(self):
|
||||||
timer = TestTimer(self.timeout)
|
timer = TestTimer(self.timeout)
|
||||||
while not timer.timed_out():
|
while not timer.timed_out():
|
||||||
|
@ -68,3 +75,11 @@ class BasicTest(object):
|
||||||
if time_passed > MAX_TIME_FOR_MONKEYS_TO_DIE:
|
if time_passed > MAX_TIME_FOR_MONKEYS_TO_DIE:
|
||||||
print("Some monkeys didn't die after the test, passing")
|
print("Some monkeys didn't die after the test, passing")
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
def parse_logs(self):
|
||||||
|
print("\nParsing test logs:")
|
||||||
|
TestLogsHandler(self.name, self.island_client).parse_test_logs()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def wait_for_monkey_process_to_finish():
|
||||||
|
sleep(TIME_FOR_MONKEY_PROCESS_TO_FINISH)
|
||||||
|
|
Loading…
Reference in New Issue