1import logging, os, socket, time
2from autotest_lib.client.bin import utils
3from autotest_lib.client.common_lib import error
4
5def run_softlockup(test, params, env):
6    """
7    soft lockup/drift test with stress.
8
9    1) Boot up a VM.
10    2) Build stress on host and guest.
11    3) run heartbeat with the given options on server and host.
12    3) Run for a relatively long time length. ex: 12, 18 or 24 hours.
13    4) Output the test result and observe drift.
14
15    @param test: KVM test object.
16    @param params: Dictionary with the test parameters.
17    @param env: Dictionary with test environment.
18    """
19    stress_setup_cmd = params.get("stress_setup_cmd")
20    stress_cmd = params.get("stress_cmd")
21    server_setup_cmd = params.get("server_setup_cmd")
22    drift_cmd = params.get("drift_cmd")
23    kill_stress_cmd = params.get("kill_stress_cmd")
24    kill_monitor_cmd = params.get("kill_monitor_cmd")
25
26    threshold = int(params.get("stress_threshold"))
27    monitor_log_file_server = params.get("monitor_log_file_server")
28    monitor_log_file_client = params.get("monitor_log_file_client")
29    test_length = int(3600 * float(params.get("test_length")))
30    monitor_port = int(params.get("monitor_port"))
31
32    vm = env.get_vm(params["main_vm"])
33    login_timeout = int(params.get("login_timeout", 360))
34    stress_dir = os.path.join(os.environ['AUTODIR'], "tests/stress")
35    monitor_dir = os.path.join(test.bindir, 'deps')
36
37
38    def _kill_guest_programs(session, kill_stress_cmd, kill_monitor_cmd):
39        logging.info("Kill stress and monitor on guest")
40        try:
41            session.cmd(kill_stress_cmd)
42        except:
43            pass
44        try:
45            session.cmd(kill_monitor_cmd)
46        except:
47            pass
48
49
50    def _kill_host_programs(kill_stress_cmd, kill_monitor_cmd):
51        logging.info("Kill stress and monitor on host")
52        utils.run(kill_stress_cmd, ignore_status=True)
53        utils.run(kill_monitor_cmd, ignore_status=True)
54
55
56    def host():
57        logging.info("Setup monitor server on host")
58        # Kill previous instances of the host load programs, if any
59        _kill_host_programs(kill_stress_cmd, kill_monitor_cmd)
60        # Cleanup previous log instances
61        if os.path.isfile(monitor_log_file_server):
62            os.remove(monitor_log_file_server)
63        # Opening firewall ports on host
64        utils.run("iptables -F", ignore_status=True)
65
66        # Run heartbeat on host
67        utils.run(server_setup_cmd % (monitor_dir, threshold,
68                                      monitor_log_file_server, monitor_port))
69
70        logging.info("Build stress on host")
71        # Uncompress and build stress on host
72        utils.run(stress_setup_cmd % stress_dir)
73
74        logging.info("Run stress on host")
75        # stress_threads = 2 * n_cpus
76        threads_host = 2 * utils.count_cpus()
77        # Run stress test on host
78        utils.run(stress_cmd % (stress_dir, threads_host))
79
80
81    def guest():
82        try:
83            host_ip = socket.gethostbyname(socket.gethostname())
84        except socket.error:
85            try:
86                # Hackish, but works well on stand alone (laptop) setups
87                # with access to the internet. If this fails, well, then
88                # not much else can be done...
89                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
90                s.connect(("redhat.com", 80))
91                host_ip = s.getsockname()[0]
92            except socket.error, (value, e):
93                raise error.TestError("Could not determine host IP: %d %s" %
94                                      (value, e))
95
96        # Now, starting the guest
97        vm.verify_alive()
98        session = vm.wait_for_login(timeout=login_timeout)
99
100        # Kill previous instances of the load programs, if any
101        _kill_guest_programs(session, kill_stress_cmd, kill_monitor_cmd)
102        # Clean up previous log instances
103        session.cmd("rm -f %s" % monitor_log_file_client)
104
105        # Opening firewall ports on guest
106        try:
107            session.cmd("iptables -F")
108        except:
109            pass
110
111        # Get required files and copy them from host to guest
112        monitor_path = os.path.join(test.bindir, 'deps', 'heartbeat_slu.py')
113        stress_path = os.path.join(os.environ['AUTODIR'], "tests", "stress",
114                                   "stress-1.0.4.tar.gz")
115        vm.copy_files_to(monitor_path, "/tmp")
116        vm.copy_files_to(stress_path, "/tmp")
117
118        logging.info("Setup monitor client on guest")
119        # Start heartbeat on guest
120        session.cmd(params.get("client_setup_cmd") %
121                    ("/tmp", host_ip, monitor_log_file_client, monitor_port))
122
123        logging.info("Build stress on guest")
124        # Uncompress and build stress on guest
125        session.cmd(stress_setup_cmd % "/tmp", timeout=200)
126
127        logging.info("Run stress on guest")
128        # stress_threads = 2 * n_vcpus
129        threads_guest = 2 * int(params.get("smp", 1))
130        # Run stress test on guest
131        session.cmd(stress_cmd % ("/tmp", threads_guest))
132
133        # Wait and report
134        logging.debug("Wait for %d s", test_length)
135        time.sleep(test_length)
136
137        # Kill instances of the load programs on both guest and host
138        _kill_guest_programs(session, kill_stress_cmd, kill_monitor_cmd)
139        _kill_host_programs(kill_stress_cmd, kill_monitor_cmd)
140
141        # Collect drift
142        drift = utils.system_output(drift_cmd %  monitor_log_file_server)
143        logging.info("Drift noticed: %s", drift)
144
145
146    host()
147    guest()
148