Merge "Add rpm,image directories and SLA options to Livemigration"
[yardstick.git] / yardstick / benchmark / scenarios / compute / qemu_migrate.py
1 from __future__ import absolute_import
2 from __future__ import print_function
3
4 import logging
5 import os
6 import re
7 import time
8
9
10 import pkg_resources
11 from oslo_serialization import jsonutils
12
13 import yardstick.ssh as ssh
14 from yardstick.benchmark.scenarios import base
15
16 LOG = logging.getLogger(__name__)
17 LOG.setLevel(logging.DEBUG)
18
19
20 class QemuMigrate(base.Scenario):
21     """
22     Execute a live migration for two host using qemu
23
24     """
25
26     __scenario_type__ = "QemuMigrate"
27
28     TARGET_SCRIPT = "qemu_migrate_benchmark.bash"
29     WORKSPACE = "/root/workspace"
30     REBOOT_CMD_PATTERN = r";\s*reboot\b"
31
32     def __init__(self, scenario_cfg, context_cfg):
33         self.scenario_cfg = scenario_cfg
34         self.context_cfg = context_cfg
35         self.setup_done = False
36
37     def _connect_host(self):
38         host = self.context_cfg["host"]
39         self.host = ssh.SSH.from_node(host, defaults={"user": "root"})
40         self.host.wait(timeout=600)
41
42     def _put_files(self, client):
43         setup_options = self.scenario_cfg["setup_options"]
44         rpm_dir = setup_options["rpm_dir"]
45         script_dir = setup_options["script_dir"]
46         image_dir = setup_options["image_dir"]
47         LOG.debug("Send RPMs from %s to workspace %s",
48                   rpm_dir, self.WORKSPACE)
49         client.put(rpm_dir, self.WORKSPACE, recursive=True)
50         LOG.debug("Send scripts from %s to workspace %s",
51                   script_dir, self.WORKSPACE)
52         client.put(script_dir, self.WORKSPACE, recursive=True)
53         LOG.debug("Send guest image from %s to workspace %s",
54                   image_dir, self.WORKSPACE)
55         client.put(image_dir, self.WORKSPACE, recursive=True)
56
57     def _run_setup_cmd(self, client, cmd):
58         LOG.debug("Run cmd: %s", cmd)
59         status, stdout, stderr = client.execute(cmd)
60         if status:
61             if re.search(self.REBOOT_CMD_PATTERN, cmd):
62                 LOG.debug("Error on reboot")
63             else:
64                 raise RuntimeError(stderr)
65
66     def _run_host_setup_scripts(self, scripts):
67         setup_options = self.scenario_cfg["setup_options"]
68         script_dir = os.path.basename(setup_options["script_dir"])
69
70         for script in scripts:
71             cmd = "cd %s/%s; export PATH=./:$PATH; %s" %\
72                   (self.WORKSPACE, script_dir, script)
73             self._run_setup_cmd(self.host, cmd)
74
75             if re.search(self.REBOOT_CMD_PATTERN, cmd):
76                 time.sleep(3)
77                 self._connect_host()
78
79     def setup(self):
80         """scenario setup"""
81         setup_options = self.scenario_cfg["setup_options"]
82         host_setup_seqs = setup_options["host_setup_seqs"]
83
84         self._connect_host()
85         self._put_files(self.host)
86         self._run_host_setup_scripts(host_setup_seqs)
87
88         # copy script to host
89         self.target_script = pkg_resources.resource_filename(
90             "yardstick.benchmark.scenarios.compute",
91             QemuMigrate.TARGET_SCRIPT)
92         self.host.put_file(self.target_script, "~/qemu_migrate_benchmark.sh")
93
94         self.setup_done = True
95
96     def run(self, result):
97         """execute the benchmark"""
98
99         options = self.scenario_cfg["options"]
100         smp = options.get("smp", 2)
101         qmp_sock_src = options.get("qmp_src_path", "/tmp/qmp-sock-src")
102         qmp_sock_dst = options.get("qmp_dst_path", "/tmp/qmp-sock-dst")
103         incoming_ip = options.get("incoming_ip", 0)
104         migrate_to_port = options.get("migrate_to_port", 4444)
105         max_down_time = options.get("max_down_time", 0.10)
106         cmd_args = " %s %s %s %s %s %s" %\
107                    (smp, qmp_sock_src, qmp_sock_dst, incoming_ip,
108                     migrate_to_port, max_down_time)
109         cmd = "bash migrate_benchmark.sh %s" % (cmd_args)
110         LOG.debug("Executing command: %s", cmd)
111         status, stdout, stderr = self.host.execute(cmd)
112         if status:
113             raise RuntimeError(stderr)
114
115         result.update(jsonutils.loads(stdout))
116
117         if "sla" in self.scenario_cfg:
118             sla_error = ""
119             for t, timevalue in result.items():
120                 if 'max_%s' % t not in self.scenario_cfg['sla']:
121                     continue
122
123                 sla_time = int(self.scenario_cfg['sla'][
124                                'max_%s' % t])
125                 timevalue = int(timevalue)
126                 if timevalue > sla_time:
127                     sla_error += "%s timevalue %d > sla:max_%s(%d); " % \
128                         (t, timevalue, t, sla_time)
129             assert sla_error == "", sla_error
130
131
132 def _test():    # pragma: no cover
133     """internal test function"""
134     key_filename = pkg_resources.resource_filename("yardstick.resources",
135                                                    "files/yardstick_key")
136     ctx = {
137         "host": {
138             "ip": "10.229.47.137",
139             "user": "root",
140             "key_filename": key_filename
141         }
142     }
143
144     logger = logging.getLogger("yardstick")
145     logger.setLevel(logging.DEBUG)
146     options = {
147         "smp": 2,
148         "migrate_to_port": 4444,
149         "incoming_ip": 0,
150         "qmp_sock_src": "/tmp/qmp-sock-src",
151         "qmp_sock_dst": "/tmp/qmp-sock-dst",
152         "max_down_time": 0.10
153     }
154     sla = {
155         "max_totaltime": 10,
156         "max_downtime": 0.10,
157         "max_setuptime": 0.50,
158     }
159     args = {
160         "options": options,
161         "sla": sla
162     }
163     result = {}
164
165     migrate = QemuMigrate(args, ctx)
166     migrate.run(result)
167     print(result)
168
169 if __name__ == '__main__':    # pragma: no cover
170     _test()