]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/mgr/test_module_selftest.py
6 from teuthology
.exceptions
import CommandFailedError
8 from tasks
.mgr
.mgr_test_case
import MgrTestCase
10 log
= logging
.getLogger(__name__
)
13 class TestModuleSelftest(MgrTestCase
):
15 That modules with a self-test command can be loaded and execute it
18 This is not a substitute for really testing the modules, but it
19 is quick and is designed to catch regressions that could occur
20 if data structures change in a way that breaks how the modules
28 def _selftest_plugin(self
, module_name
):
29 self
._load
_module
("selftest")
30 self
._load
_module
(module_name
)
32 # Execute the module's self_test() method
33 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
34 "mgr", "self-test", "module", module_name
)
36 def test_zabbix(self
):
37 # Set these mandatory config fields so that the zabbix module
38 # won't trigger health/log errors on load/serve.
39 self
.mgr_cluster
.set_module_conf("zabbix", "zabbix_host", "localhost")
40 self
.mgr_cluster
.set_module_conf("zabbix", "identifier", "foo")
41 self
._selftest
_plugin
("zabbix")
43 def test_prometheus(self
):
44 self
._assign
_ports
("prometheus", "server_port", min_port
=8100)
45 self
._selftest
_plugin
("prometheus")
47 def test_influx(self
):
48 self
._selftest
_plugin
("influx")
50 def test_diskprediction_local(self
):
51 self
._selftest
_plugin
("diskprediction_local")
53 def test_diskprediction_cloud(self
):
54 self
._selftest
_plugin
("diskprediction_cloud")
56 def test_telegraf(self
):
57 self
._selftest
_plugin
("telegraf")
59 def test_iostat(self
):
60 self
._selftest
_plugin
("iostat")
62 def test_devicehealth(self
):
63 self
._selftest
_plugin
("devicehealth")
64 # Clean up the pool that the module creates, because otherwise
65 # it's low PG count causes test failures.
66 pool_name
= "device_health_metrics"
67 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
68 "osd", "pool", "delete", pool_name
, pool_name
,
69 "--yes-i-really-really-mean-it")
71 def test_selftest_run(self
):
72 self
._load
_module
("selftest")
73 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd("mgr", "self-test", "run")
75 def test_telemetry(self
):
76 self
._selftest
_plugin
("telemetry")
79 self
._selftest
_plugin
("crash")
81 def test_selftest_config_update(self
):
83 That configuration updates are seen by running mgr modules
85 self
._load
_module
("selftest")
88 return self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
89 "mgr", "self-test", "config", "get", "testkey").strip()
91 self
.assertEqual(get_value(), "None")
92 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
93 "config", "set", "mgr", "mgr/selftest/testkey", "foo")
94 self
.wait_until_equal(get_value
, "foo", timeout
=10)
96 def get_localized_value():
97 return self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
98 "mgr", "self-test", "config", "get_localized", "testkey").strip()
100 self
.assertEqual(get_localized_value(), "foo")
101 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
102 "config", "set", "mgr", "mgr/selftest/{}/testkey".format(
103 self
.mgr_cluster
.get_active_id()),
105 self
.wait_until_equal(get_localized_value
, "bar", timeout
=10)
107 def test_selftest_config_upgrade(self
):
109 That pre-mimic config-key config settings are migrated into
110 mimic-style config settings and visible from mgr modules.
112 self
._load
_module
("selftest")
115 return self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
116 "mgr", "self-test", "config", "get", "testkey").strip()
119 lines
= self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
123 for line
in lines
[1:]:
124 tokens
= line
.strip().split()
125 log
.info("tokens: {0}".format(tokens
))
126 subsys
, key
, value
= tokens
[0], tokens
[2], tokens
[3]
127 result
.append((subsys
, key
, value
))
131 # Stop ceph-mgr while we synthetically create a pre-mimic
132 # configuration scenario
133 for mgr_id
in self
.mgr_cluster
.mgr_daemons
.keys():
134 self
.mgr_cluster
.mgr_stop(mgr_id
)
135 self
.mgr_cluster
.mgr_fail(mgr_id
)
137 # Blow away any modern-style mgr module config options
138 # (the ceph-mgr implementation may only do the upgrade if
139 # it doesn't see new style options)
141 for subsys
, key
, value
in get_config():
142 if subsys
== "mgr" and key
.startswith("mgr/"):
143 log
.info("Removing config key {0} ahead of upgrade".format(
145 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
146 "config", "rm", subsys
, key
)
147 stash
.append((subsys
, key
, value
))
149 # Inject an old-style configuration setting in config-key
150 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
151 "config-key", "set", "mgr/selftest/testkey", "testvalue")
153 # Inject configuration settings that looks data-ish and should
154 # not be migrated to a config key
155 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
156 "config-key", "set", "mgr/selftest/testnewline", "foo\nbar")
158 # Inject configuration setting that does not appear in the
159 # module's config schema
160 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
161 "config-key", "set", "mgr/selftest/kvitem", "foo\nbar")
163 # Bring mgr daemons back online, the one that goes active
164 # should be doing the upgrade.
165 for mgr_id
in self
.mgr_cluster
.mgr_daemons
.keys():
166 self
.mgr_cluster
.mgr_restart(mgr_id
)
168 # Wait for a new active
169 self
.wait_until_true(
170 lambda: self
.mgr_cluster
.get_active_id() != "", timeout
=30)
172 # Check that the selftest module sees the upgraded value
173 self
.assertEqual(get_value(), "testvalue")
175 # Check that the upgraded value is visible in the configuration
176 seen_keys
= [k
for s
,k
,v
in get_config()]
177 self
.assertIn("mgr/selftest/testkey", seen_keys
)
179 # ...and that the non-config-looking one isn't
180 self
.assertNotIn("mgr/selftest/testnewline", seen_keys
)
182 # ...and that the not-in-schema one isn't
183 self
.assertNotIn("mgr/selftest/kvitem", seen_keys
)
185 # Restore previous configuration
186 for subsys
, key
, value
in stash
:
187 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
188 "config", "set", subsys
, key
, value
)
190 def test_selftest_command_spam(self
):
191 # Use the selftest module to stress the mgr daemon
192 self
._load
_module
("selftest")
194 # Use the dashboard to test that the mgr is still able to do its job
195 self
._assign
_ports
("dashboard", "ssl_server_port")
196 self
._load
_module
("dashboard")
197 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd("dashboard",
198 "create-self-signed-cert")
200 original_active
= self
.mgr_cluster
.get_active_id()
201 original_standbys
= self
.mgr_cluster
.get_standby_ids()
203 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd("mgr", "self-test",
204 "background", "start",
207 dashboard_uri
= self
._get
_uri
("dashboard")
211 for i
in range(0, periods
):
213 # Check that an HTTP module remains responsive
214 r
= requests
.get(dashboard_uri
, verify
=False)
215 self
.assertEqual(r
.status_code
, 200)
217 # Check that a native non-module command remains responsive
218 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd("osd", "df")
220 time
.sleep(delay
- (time
.time() - t1
))
222 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd("mgr", "self-test",
223 "background", "stop")
225 # Check that all mgr daemons are still running
226 self
.assertEqual(original_active
, self
.mgr_cluster
.get_active_id())
227 self
.assertEqual(original_standbys
, self
.mgr_cluster
.get_standby_ids())
229 def test_module_commands(self
):
231 That module-handled commands have appropriate behavior on
232 disabled/failed/recently-enabled modules.
235 # Calling a command on a disabled module should return the proper
237 self
._load
_module
("selftest")
238 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
239 "mgr", "module", "disable", "selftest")
240 with self
.assertRaises(CommandFailedError
) as exc_raised
:
241 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
242 "mgr", "self-test", "run")
244 self
.assertEqual(exc_raised
.exception
.exitstatus
, errno
.EOPNOTSUPP
)
246 # Calling a command that really doesn't exist should give me EINVAL.
247 with self
.assertRaises(CommandFailedError
) as exc_raised
:
248 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
251 self
.assertEqual(exc_raised
.exception
.exitstatus
, errno
.EINVAL
)
253 # Enabling a module and then immediately using ones of its commands
254 # should work (#21683)
255 self
._load
_module
("selftest")
256 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
257 "mgr", "self-test", "config", "get", "testkey")
259 # Calling a command for a failed module should return the proper
261 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
262 "mgr", "self-test", "background", "start", "throw_exception")
263 with self
.assertRaises(CommandFailedError
) as exc_raised
:
264 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
265 "mgr", "self-test", "run"
267 self
.assertEqual(exc_raised
.exception
.exitstatus
, errno
.EIO
)
269 # A health alert should be raised for a module that has thrown
270 # an exception from its serve() method
271 self
.wait_for_health(
272 "Module 'selftest' has failed: Synthetic exception in serve",
275 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
276 "mgr", "module", "disable", "selftest")
278 self
.wait_for_health_clear(timeout
=30)
280 def test_module_remote(self
):
282 Use the selftest module to exercise inter-module communication
284 self
._load
_module
("selftest")
285 # The "self-test remote" operation just happens to call into
287 self
._load
_module
("influx")
289 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
290 "mgr", "self-test", "remote")
292 def test_selftest_cluster_log(self
):
294 Use the selftest module to test the cluster/audit log interface.
302 self
._load
_module
("selftest")
303 for priority
in priority_map
.keys():
304 message
= "foo bar {}".format(priority
)
305 log_message
= "[{}] {}".format(priority_map
[priority
], message
)
306 # Check for cluster/audit logs:
307 # 2018-09-24 09:37:10.977858 mgr.x [INF] foo bar info
308 # 2018-09-24 09:37:10.977860 mgr.x [SEC] foo bar security
309 # 2018-09-24 09:37:10.977863 mgr.x [WRN] foo bar warning
310 # 2018-09-24 09:37:10.977866 mgr.x [ERR] foo bar error
311 with self
.assert_cluster_log(log_message
):
312 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
313 "mgr", "self-test", "cluster-log", "cluster",
315 with self
.assert_cluster_log(log_message
, watch_channel
="audit"):
316 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
317 "mgr", "self-test", "cluster-log", "audit",
320 def test_selftest_cluster_log_unknown_channel(self
):
322 Use the selftest module to test the cluster/audit log interface.
324 with self
.assertRaises(CommandFailedError
) as exc_raised
:
325 self
.mgr_cluster
.mon_manager
.raw_cluster_cmd(
326 "mgr", "self-test", "cluster-log", "xyz",
327 "ERR", "The channel does not exist")
328 self
.assertEqual(exc_raised
.exception
.exitstatus
, errno
.EOPNOTSUPP
)