]>
Commit | Line | Data |
---|---|---|
3efd9988 FG |
1 | |
2 | import time | |
3 | import requests | |
11fdf7f2 TL |
4 | import errno |
5 | import logging | |
f67539c2 TL |
6 | import sys |
7 | ||
11fdf7f2 | 8 | from teuthology.exceptions import CommandFailedError |
3efd9988 | 9 | |
f67539c2 TL |
10 | from .mgr_test_case import MgrTestCase |
11 | ||
3efd9988 | 12 | |
11fdf7f2 TL |
13 | log = logging.getLogger(__name__) |
14 | ||
3efd9988 FG |
15 | |
16 | class TestModuleSelftest(MgrTestCase): | |
17 | """ | |
18 | That modules with a self-test command can be loaded and execute it | |
19 | without errors. | |
20 | ||
21 | This is not a substitute for really testing the modules, but it | |
22 | is quick and is designed to catch regressions that could occur | |
23 | if data structures change in a way that breaks how the modules | |
24 | touch them. | |
25 | """ | |
26 | MGRS_REQUIRED = 1 | |
27 | ||
11fdf7f2 | 28 | def setUp(self): |
9f95a23c | 29 | super(TestModuleSelftest, self).setUp() |
11fdf7f2 TL |
30 | self.setup_mgrs() |
31 | ||
3efd9988 | 32 | def _selftest_plugin(self, module_name): |
11fdf7f2 | 33 | self._load_module("selftest") |
3efd9988 FG |
34 | self._load_module(module_name) |
35 | ||
11fdf7f2 TL |
36 | # Execute the module's self_test() method |
37 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
38 | "mgr", "self-test", "module", module_name) | |
3efd9988 FG |
39 | |
40 | def test_zabbix(self): | |
b32b8144 FG |
41 | # Set these mandatory config fields so that the zabbix module |
42 | # won't trigger health/log errors on load/serve. | |
43 | self.mgr_cluster.set_module_conf("zabbix", "zabbix_host", "localhost") | |
44 | self.mgr_cluster.set_module_conf("zabbix", "identifier", "foo") | |
3efd9988 FG |
45 | self._selftest_plugin("zabbix") |
46 | ||
47 | def test_prometheus(self): | |
94b18763 | 48 | self._assign_ports("prometheus", "server_port", min_port=8100) |
3efd9988 FG |
49 | self._selftest_plugin("prometheus") |
50 | ||
51 | def test_influx(self): | |
52 | self._selftest_plugin("influx") | |
53 | ||
11fdf7f2 | 54 | def test_diskprediction_local(self): |
f67539c2 TL |
55 | if sys.version_info >= (3, 8): |
56 | # https://tracker.ceph.com/issues/45147 | |
57 | python_version = f'python {sys.version_info.major}.{sys.version_info.minor}' | |
58 | self.skipTest(f'{python_version} not compatible with diskprediction_local') | |
11fdf7f2 TL |
59 | self._selftest_plugin("diskprediction_local") |
60 | ||
11fdf7f2 TL |
61 | def test_telegraf(self): |
62 | self._selftest_plugin("telegraf") | |
63 | ||
64 | def test_iostat(self): | |
65 | self._selftest_plugin("iostat") | |
66 | ||
67 | def test_devicehealth(self): | |
68 | self._selftest_plugin("devicehealth") | |
69 | # Clean up the pool that the module creates, because otherwise | |
70 | # it's low PG count causes test failures. | |
71 | pool_name = "device_health_metrics" | |
72 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
73 | "osd", "pool", "delete", pool_name, pool_name, | |
74 | "--yes-i-really-really-mean-it") | |
75 | ||
3efd9988 FG |
76 | def test_selftest_run(self): |
77 | self._load_module("selftest") | |
78 | self.mgr_cluster.mon_manager.raw_cluster_cmd("mgr", "self-test", "run") | |
79 | ||
11fdf7f2 TL |
80 | def test_telemetry(self): |
81 | self._selftest_plugin("telemetry") | |
82 | ||
83 | def test_crash(self): | |
84 | self._selftest_plugin("crash") | |
85 | ||
9f95a23c TL |
86 | def test_orchestrator(self): |
87 | self._selftest_plugin("orchestrator") | |
eafe8130 TL |
88 | |
89 | ||
11fdf7f2 TL |
90 | def test_selftest_config_update(self): |
91 | """ | |
92 | That configuration updates are seen by running mgr modules | |
93 | """ | |
94 | self._load_module("selftest") | |
95 | ||
96 | def get_value(): | |
97 | return self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
98 | "mgr", "self-test", "config", "get", "testkey").strip() | |
99 | ||
100 | self.assertEqual(get_value(), "None") | |
101 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
102 | "config", "set", "mgr", "mgr/selftest/testkey", "foo") | |
103 | self.wait_until_equal(get_value, "foo", timeout=10) | |
104 | ||
105 | def get_localized_value(): | |
106 | return self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
107 | "mgr", "self-test", "config", "get_localized", "testkey").strip() | |
108 | ||
109 | self.assertEqual(get_localized_value(), "foo") | |
110 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
111 | "config", "set", "mgr", "mgr/selftest/{}/testkey".format( | |
112 | self.mgr_cluster.get_active_id()), | |
113 | "bar") | |
114 | self.wait_until_equal(get_localized_value, "bar", timeout=10) | |
115 | ||
11fdf7f2 | 116 | |
3efd9988 FG |
117 | def test_selftest_command_spam(self): |
118 | # Use the selftest module to stress the mgr daemon | |
119 | self._load_module("selftest") | |
120 | ||
121 | # Use the dashboard to test that the mgr is still able to do its job | |
11fdf7f2 | 122 | self._assign_ports("dashboard", "ssl_server_port") |
3efd9988 | 123 | self._load_module("dashboard") |
11fdf7f2 TL |
124 | self.mgr_cluster.mon_manager.raw_cluster_cmd("dashboard", |
125 | "create-self-signed-cert") | |
3efd9988 FG |
126 | |
127 | original_active = self.mgr_cluster.get_active_id() | |
128 | original_standbys = self.mgr_cluster.get_standby_ids() | |
129 | ||
130 | self.mgr_cluster.mon_manager.raw_cluster_cmd("mgr", "self-test", | |
131 | "background", "start", | |
132 | "command_spam") | |
133 | ||
134 | dashboard_uri = self._get_uri("dashboard") | |
135 | ||
136 | delay = 10 | |
137 | periods = 10 | |
138 | for i in range(0, periods): | |
139 | t1 = time.time() | |
140 | # Check that an HTTP module remains responsive | |
11fdf7f2 | 141 | r = requests.get(dashboard_uri, verify=False) |
3efd9988 FG |
142 | self.assertEqual(r.status_code, 200) |
143 | ||
144 | # Check that a native non-module command remains responsive | |
145 | self.mgr_cluster.mon_manager.raw_cluster_cmd("osd", "df") | |
146 | ||
147 | time.sleep(delay - (time.time() - t1)) | |
148 | ||
149 | self.mgr_cluster.mon_manager.raw_cluster_cmd("mgr", "self-test", | |
150 | "background", "stop") | |
151 | ||
152 | # Check that all mgr daemons are still running | |
153 | self.assertEqual(original_active, self.mgr_cluster.get_active_id()) | |
154 | self.assertEqual(original_standbys, self.mgr_cluster.get_standby_ids()) | |
11fdf7f2 TL |
155 | |
156 | def test_module_commands(self): | |
157 | """ | |
158 | That module-handled commands have appropriate behavior on | |
159 | disabled/failed/recently-enabled modules. | |
160 | """ | |
161 | ||
162 | # Calling a command on a disabled module should return the proper | |
163 | # error code. | |
164 | self._load_module("selftest") | |
165 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
166 | "mgr", "module", "disable", "selftest") | |
167 | with self.assertRaises(CommandFailedError) as exc_raised: | |
168 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
169 | "mgr", "self-test", "run") | |
170 | ||
171 | self.assertEqual(exc_raised.exception.exitstatus, errno.EOPNOTSUPP) | |
172 | ||
173 | # Calling a command that really doesn't exist should give me EINVAL. | |
174 | with self.assertRaises(CommandFailedError) as exc_raised: | |
175 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
176 | "osd", "albatross") | |
177 | ||
178 | self.assertEqual(exc_raised.exception.exitstatus, errno.EINVAL) | |
179 | ||
180 | # Enabling a module and then immediately using ones of its commands | |
181 | # should work (#21683) | |
182 | self._load_module("selftest") | |
183 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
184 | "mgr", "self-test", "config", "get", "testkey") | |
185 | ||
186 | # Calling a command for a failed module should return the proper | |
187 | # error code. | |
188 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
189 | "mgr", "self-test", "background", "start", "throw_exception") | |
190 | with self.assertRaises(CommandFailedError) as exc_raised: | |
191 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
192 | "mgr", "self-test", "run" | |
193 | ) | |
194 | self.assertEqual(exc_raised.exception.exitstatus, errno.EIO) | |
195 | ||
196 | # A health alert should be raised for a module that has thrown | |
197 | # an exception from its serve() method | |
198 | self.wait_for_health( | |
199 | "Module 'selftest' has failed: Synthetic exception in serve", | |
200 | timeout=30) | |
201 | ||
202 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
203 | "mgr", "module", "disable", "selftest") | |
204 | ||
205 | self.wait_for_health_clear(timeout=30) | |
206 | ||
207 | def test_module_remote(self): | |
208 | """ | |
209 | Use the selftest module to exercise inter-module communication | |
210 | """ | |
211 | self._load_module("selftest") | |
212 | # The "self-test remote" operation just happens to call into | |
213 | # influx. | |
214 | self._load_module("influx") | |
215 | ||
216 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
217 | "mgr", "self-test", "remote") | |
218 | ||
219 | def test_selftest_cluster_log(self): | |
220 | """ | |
221 | Use the selftest module to test the cluster/audit log interface. | |
222 | """ | |
223 | priority_map = { | |
224 | "info": "INF", | |
225 | "security": "SEC", | |
226 | "warning": "WRN", | |
227 | "error": "ERR" | |
228 | } | |
229 | self._load_module("selftest") | |
230 | for priority in priority_map.keys(): | |
231 | message = "foo bar {}".format(priority) | |
232 | log_message = "[{}] {}".format(priority_map[priority], message) | |
233 | # Check for cluster/audit logs: | |
234 | # 2018-09-24 09:37:10.977858 mgr.x [INF] foo bar info | |
235 | # 2018-09-24 09:37:10.977860 mgr.x [SEC] foo bar security | |
236 | # 2018-09-24 09:37:10.977863 mgr.x [WRN] foo bar warning | |
237 | # 2018-09-24 09:37:10.977866 mgr.x [ERR] foo bar error | |
238 | with self.assert_cluster_log(log_message): | |
239 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
240 | "mgr", "self-test", "cluster-log", "cluster", | |
241 | priority, message) | |
242 | with self.assert_cluster_log(log_message, watch_channel="audit"): | |
243 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
244 | "mgr", "self-test", "cluster-log", "audit", | |
245 | priority, message) | |
246 | ||
247 | def test_selftest_cluster_log_unknown_channel(self): | |
248 | """ | |
249 | Use the selftest module to test the cluster/audit log interface. | |
250 | """ | |
251 | with self.assertRaises(CommandFailedError) as exc_raised: | |
252 | self.mgr_cluster.mon_manager.raw_cluster_cmd( | |
253 | "mgr", "self-test", "cluster-log", "xyz", | |
254 | "ERR", "The channel does not exist") | |
255 | self.assertEqual(exc_raised.exception.exitstatus, errno.EOPNOTSUPP) |