Fixed bugs regarding waiting for monkeys to die, readability improvements

This commit is contained in:
VakarisZ 2019-09-17 09:17:29 +03:00
parent 91fe7c22a8
commit 018d3ddc08
9 changed files with 125 additions and 36 deletions

View File

@ -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)

View File

@ -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
self.log.add_entry("Monkey from {} communicated back".format(machine_ip)) else:
return True self.log.add_entry("Monkey from {} communicated back".format(machine_ip))
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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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:

View 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()

View File

@ -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()

View File

@ -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)