Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
give 2 workers to the monkey-masterworkers, so that the master don't gets killed...
[simgrid.git] / tools / simgrid-monkey
1 #! /usr/bin/python3
2
3 # The goal is to introduce random failures in a simulation, to test simgrid under extreme conditions.
4
5 # It is made of several components.
6
7 # * a plugin: cmonkey. Can be used from the command line as follows:
8 #   * --cfg=plugin:cmonkey --cfg=cmonkey/tell:1
9 #     Get information about the resource count and the timestamps of each scheduling rounds.
10 #   * --cfg=plugin:cmonkey --cfg=cmonkey/time:42 --cfg=cmonkey/host:1
11 #     Kill the host #1 after 42 seconds (using a kernel::Timer so that no actor gets involved in the killing)
12 #   * --cfg=plugin:cmonkey --cfg=cmonkey/time:42 --cfg=cmonkey/link:0
13 #     Kill the link #0 after 42 seconds (using a kernel::Timer)
14
15 # * a python script: tools/simgrid-monkey (this file)
16 #   * It takes a regular simgrid simulation as a parameter, use the cmonkey plugin to get the information about it, 
17 #     and then restart many runs, with one resource being turn_off() + turn_on() in each run.
18 #   * Each resource gets killed between each timestamps, and on each timestamp.
19 #   * So the amount of simulations is: 1 + (host_c+link_c) * timestamps * 2
20
21 # * Test program, written to resist these extreme conditions:
22 #   * teshsuite/s4u/monkey-masterworkers: tests synchronous comms and execs
23
24 import multiprocessing as mp
25 import sys
26 import os
27 import argparse
28 import subprocess
29 import copy
30 import re
31
32
33 def get_info(cmd):
34     cmd_tell = copy.deepcopy(cmd)
35     cmd_tell.append("--cfg=plugin:cmonkey")
36     cmd_tell.append("--cfg=cmonkey/tell:1")
37     cmd_tell.append("--log=root.t:critical")
38     cmd_tell.append("--log=cmonkey.t:info")
39     cmd_tell.append("--log=cmonkey.fmt:%m%n")
40     print(f"Get the initial info from the command ``{' '.join(cmd_tell)}``")
41     first_run = subprocess.run(cmd_tell, shell=False, cwd=os.getcwd(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
42
43     if first_run.returncode != 0:
44         msg = f"Peek run of the command raised an error (retcode: {first_run.returncode})\n"
45         msg += f"Full command was {' '.join(cmd_tell)}\n"
46         if first_run.stdout is not None:
47             msg += str(first_run.stdout, errors='replace')
48         raise Exception(msg)
49
50     host_count=0
51     link_count=0
52     timestamps=[]
53     for line in str(first_run.stdout, errors='replace').split("\n"):
54         if re.match("^HOST_COUNT=(.*)", line):
55             m = re.match("^HOST_COUNT=(.*)", line)
56             host_count = int(m.group(1))
57         if re.match("^LINK_COUNT=(.*)", line):
58             m = re.match("^LINK_COUNT=(.*)", line)
59             link_count = int(m.group(1))
60         if re.match("^TIMESTAMP=(.*)", line):
61             m = re.match("^TIMESTAMP=(.*)", line)
62             timestamps.append(float(m.group(1)))
63
64     #print(f"hosts:{host_count} links:{link_count} timestamps:{' '.join(([str(i) for i in timestamps]))}")
65     return (host_count,  link_count,  timestamps)
66
67 parser = argparse.ArgumentParser(description='Run a simgrid simulation, and turn off/on resources at random.')
68 parser.add_argument('--valgrind', help="Run the simulations in valgrind")
69 parser.add_argument('command', nargs='*')
70 args = parser.parse_args()
71
72 (host_count,  link_count,  timestamps) = get_info(args.command)
73 print(f"hosts:{host_count} links:{link_count} timestamps:{' '.join(([str(i) for i in timestamps]))}")
74
75 def do_run(cmd, extra_params):
76     cmd = copy.deepcopy(cmd)
77     cmd.append("--cfg=plugin:cmonkey")
78     for p in extra_params:
79         cmd.append(p)
80     print(f"\n#################################################################################\nStart {' '.join(cmd)}")
81     run = subprocess.run(cmd, shell=False, cwd=os.getcwd(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
82
83     if run.returncode != 0:
84         msg = f"ERROR (retcode: {run.returncode}). Output:\n"
85         msg += str(run.stdout, errors='replace')
86         print(msg)
87         os.exit(1)
88     print ("Success.")
89
90 def doit():
91     prev = 0
92     for pos in range(len(timestamps)):
93         now = timestamps[pos]
94         for host in range(host_count):
95             do_run(args.command, [f"--cfg=cmonkey/time:{(now-prev)/2}", f"--cfg=cmonkey/host:{host}"])
96             do_run(args.command, [f"--cfg=cmonkey/time:{now}", f"--cfg=cmonkey/host:{host}"])
97         for link in range(link_count):
98             do_run(args.command, [f"--cfg=cmonkey/time:{(now-prev)/2}", f"--cfg=cmonkey/link:{link}"])
99             do_run(args.command, [f"--cfg=cmonkey/time:{now}", f"--cfg=cmonkey/link:{link}"])
100 doit()