]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/mgr/mgr_test_case.py
update sources to v12.2.3
[ceph.git] / ceph / qa / tasks / mgr / mgr_test_case.py
CommitLineData
7c673cae
FG
1
2from unittest import case
3import json
3efd9988 4import logging
7c673cae
FG
5
6from teuthology import misc
7from tasks.ceph_test_case import CephTestCase
8
3efd9988 9# TODO move definition of CephCluster away from the CephFS stuff
7c673cae
FG
10from tasks.cephfs.filesystem import CephCluster
11
12
3efd9988
FG
13log = logging.getLogger(__name__)
14
15
7c673cae
FG
16class MgrCluster(CephCluster):
17 def __init__(self, ctx):
18 super(MgrCluster, self).__init__(ctx)
19 self.mgr_ids = list(misc.all_roles_of_type(ctx.cluster, 'mgr'))
20
21 if len(self.mgr_ids) == 0:
22 raise RuntimeError(
23 "This task requires at least one manager daemon")
24
25 self.mgr_daemons = dict(
26 [(mgr_id, self._ctx.daemons.get_daemon('mgr', mgr_id)) for mgr_id
27 in self.mgr_ids])
28
29 def mgr_stop(self, mgr_id):
30 self.mgr_daemons[mgr_id].stop()
31
32 def mgr_fail(self, mgr_id):
33 self.mon_manager.raw_cluster_cmd("mgr", "fail", mgr_id)
34
35 def mgr_restart(self, mgr_id):
36 self.mgr_daemons[mgr_id].restart()
37
38 def get_mgr_map(self):
39 status = json.loads(
40 self.mon_manager.raw_cluster_cmd("status", "--format=json-pretty"))
41
42 return status["mgrmap"]
43
44 def get_active_id(self):
45 return self.get_mgr_map()["active_name"]
46
47 def get_standby_ids(self):
48 return [s['name'] for s in self.get_mgr_map()["standbys"]]
49
b32b8144
FG
50 def set_module_conf(self, module, key, val):
51 self.mon_manager.raw_cluster_cmd("config-key", "set",
52 "mgr/{0}/{1}".format(
53 module, key
54 ), val)
55
3efd9988
FG
56 def set_module_localized_conf(self, module, mgr_id, key, val):
57 self.mon_manager.raw_cluster_cmd("config-key", "set",
58 "mgr/{0}/{1}/{2}".format(
59 module, mgr_id, key
60 ), val)
61
7c673cae
FG
62
63class MgrTestCase(CephTestCase):
64 MGRS_REQUIRED = 1
65
66 def setUp(self):
67 super(MgrTestCase, self).setUp()
68
69 # The test runner should have populated this
70 assert self.mgr_cluster is not None
71
72 if len(self.mgr_cluster.mgr_ids) < self.MGRS_REQUIRED:
73 raise case.SkipTest("Only have {0} manager daemons, "
74 "{1} are required".format(
75 len(self.mgr_cluster.mgr_ids), self.MGRS_REQUIRED))
76
77 # Restart all the daemons
78 for daemon in self.mgr_cluster.mgr_daemons.values():
79 daemon.stop()
80
81 for mgr_id in self.mgr_cluster.mgr_ids:
82 self.mgr_cluster.mgr_fail(mgr_id)
83
84 for daemon in self.mgr_cluster.mgr_daemons.values():
85 daemon.restart()
86
87 # Wait for an active to come up
88 self.wait_until_true(lambda: self.mgr_cluster.get_active_id() != "",
89 timeout=20)
90
91 expect_standbys = set(self.mgr_cluster.mgr_ids) \
92 - {self.mgr_cluster.get_active_id()}
93 self.wait_until_true(
94 lambda: set(self.mgr_cluster.get_standby_ids()) == expect_standbys,
95 timeout=20)
3efd9988
FG
96
97 def _load_module(self, module_name):
98 loaded = json.loads(self.mgr_cluster.mon_manager.raw_cluster_cmd(
99 "mgr", "module", "ls"))['enabled_modules']
100 if module_name in loaded:
101 # The enable command is idempotent, but our wait for a restart
102 # isn't, so let's return now if it's already loaded
103 return
104
105 initial_gid = self.mgr_cluster.get_mgr_map()['active_gid']
106 self.mgr_cluster.mon_manager.raw_cluster_cmd("mgr", "module", "enable",
107 module_name)
108
109 # Wait for the module to load
110 def has_restarted():
111 mgr_map = self.mgr_cluster.get_mgr_map()
112 done = mgr_map['active_gid'] != initial_gid and mgr_map['available']
113 if done:
114 log.info("Restarted after module load (new active {0}/{1})".format(
115 mgr_map['active_name'] , mgr_map['active_gid']))
116 return done
117 self.wait_until_true(has_restarted, timeout=30)
118
119
120 def _get_uri(self, service_name):
121 # Little dict hack so that I can assign into this from
122 # the get_or_none function
123 mgr_map = {'x': None}
124
125 def _get_or_none():
126 mgr_map['x'] = self.mgr_cluster.get_mgr_map()
127 result = mgr_map['x']['services'].get(service_name, None)
128 return result
129
130 self.wait_until_true(lambda: _get_or_none() is not None, 30)
131
132 uri = mgr_map['x']['services'][service_name]
133
134 log.info("Found {0} at {1} (daemon {2}/{3})".format(
135 service_name, uri, mgr_map['x']['active_name'],
136 mgr_map['x']['active_gid']))
137
138 return uri
139
140
141 def _assign_ports(self, module_name, config_name, min_port=7789):
142 """
143 To avoid the need to run lots of hosts in teuthology tests to
144 get different URLs per mgr, we will hand out different ports
145 to each mgr here.
146
147 This is already taken care of for us when running in a vstart
148 environment.
149 """
150 # Start handing out ports well above Ceph's range.
151 assign_port = min_port
152
153 for mgr_id in self.mgr_cluster.mgr_ids:
154 self.mgr_cluster.mgr_stop(mgr_id)
155 self.mgr_cluster.mgr_fail(mgr_id)
156
157 for mgr_id in self.mgr_cluster.mgr_ids:
158 log.info("Using port {0} for {1} on mgr.{2}".format(
159 assign_port, module_name, mgr_id
160 ))
161 self.mgr_cluster.set_module_localized_conf(module_name, mgr_id,
162 config_name,
163 str(assign_port))
164 assign_port += 1
165
166 for mgr_id in self.mgr_cluster.mgr_ids:
167 self.mgr_cluster.mgr_restart(mgr_id)
168
169 def is_available():
170 mgr_map = self.mgr_cluster.get_mgr_map()
171 done = mgr_map['available']
172 if done:
173 log.info("Available after assign ports (new active {0}/{1})".format(
174 mgr_map['active_name'] , mgr_map['active_gid']))
175 return done
176 self.wait_until_true(is_available, timeout=30)