]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/mgr/mgr_test_case.py
update sources to 12.2.2
[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
3efd9988
FG
50 def set_module_localized_conf(self, module, mgr_id, key, val):
51 self.mon_manager.raw_cluster_cmd("config-key", "set",
52 "mgr/{0}/{1}/{2}".format(
53 module, mgr_id, key
54 ), val)
55
7c673cae
FG
56
57class MgrTestCase(CephTestCase):
58 MGRS_REQUIRED = 1
59
60 def setUp(self):
61 super(MgrTestCase, self).setUp()
62
63 # The test runner should have populated this
64 assert self.mgr_cluster is not None
65
66 if len(self.mgr_cluster.mgr_ids) < self.MGRS_REQUIRED:
67 raise case.SkipTest("Only have {0} manager daemons, "
68 "{1} are required".format(
69 len(self.mgr_cluster.mgr_ids), self.MGRS_REQUIRED))
70
71 # Restart all the daemons
72 for daemon in self.mgr_cluster.mgr_daemons.values():
73 daemon.stop()
74
75 for mgr_id in self.mgr_cluster.mgr_ids:
76 self.mgr_cluster.mgr_fail(mgr_id)
77
78 for daemon in self.mgr_cluster.mgr_daemons.values():
79 daemon.restart()
80
81 # Wait for an active to come up
82 self.wait_until_true(lambda: self.mgr_cluster.get_active_id() != "",
83 timeout=20)
84
85 expect_standbys = set(self.mgr_cluster.mgr_ids) \
86 - {self.mgr_cluster.get_active_id()}
87 self.wait_until_true(
88 lambda: set(self.mgr_cluster.get_standby_ids()) == expect_standbys,
89 timeout=20)
3efd9988
FG
90
91 def _load_module(self, module_name):
92 loaded = json.loads(self.mgr_cluster.mon_manager.raw_cluster_cmd(
93 "mgr", "module", "ls"))['enabled_modules']
94 if module_name in loaded:
95 # The enable command is idempotent, but our wait for a restart
96 # isn't, so let's return now if it's already loaded
97 return
98
99 initial_gid = self.mgr_cluster.get_mgr_map()['active_gid']
100 self.mgr_cluster.mon_manager.raw_cluster_cmd("mgr", "module", "enable",
101 module_name)
102
103 # Wait for the module to load
104 def has_restarted():
105 mgr_map = self.mgr_cluster.get_mgr_map()
106 done = mgr_map['active_gid'] != initial_gid and mgr_map['available']
107 if done:
108 log.info("Restarted after module load (new active {0}/{1})".format(
109 mgr_map['active_name'] , mgr_map['active_gid']))
110 return done
111 self.wait_until_true(has_restarted, timeout=30)
112
113
114 def _get_uri(self, service_name):
115 # Little dict hack so that I can assign into this from
116 # the get_or_none function
117 mgr_map = {'x': None}
118
119 def _get_or_none():
120 mgr_map['x'] = self.mgr_cluster.get_mgr_map()
121 result = mgr_map['x']['services'].get(service_name, None)
122 return result
123
124 self.wait_until_true(lambda: _get_or_none() is not None, 30)
125
126 uri = mgr_map['x']['services'][service_name]
127
128 log.info("Found {0} at {1} (daemon {2}/{3})".format(
129 service_name, uri, mgr_map['x']['active_name'],
130 mgr_map['x']['active_gid']))
131
132 return uri
133
134
135 def _assign_ports(self, module_name, config_name, min_port=7789):
136 """
137 To avoid the need to run lots of hosts in teuthology tests to
138 get different URLs per mgr, we will hand out different ports
139 to each mgr here.
140
141 This is already taken care of for us when running in a vstart
142 environment.
143 """
144 # Start handing out ports well above Ceph's range.
145 assign_port = min_port
146
147 for mgr_id in self.mgr_cluster.mgr_ids:
148 self.mgr_cluster.mgr_stop(mgr_id)
149 self.mgr_cluster.mgr_fail(mgr_id)
150
151 for mgr_id in self.mgr_cluster.mgr_ids:
152 log.info("Using port {0} for {1} on mgr.{2}".format(
153 assign_port, module_name, mgr_id
154 ))
155 self.mgr_cluster.set_module_localized_conf(module_name, mgr_id,
156 config_name,
157 str(assign_port))
158 assign_port += 1
159
160 for mgr_id in self.mgr_cluster.mgr_ids:
161 self.mgr_cluster.mgr_restart(mgr_id)
162
163 def is_available():
164 mgr_map = self.mgr_cluster.get_mgr_map()
165 done = mgr_map['available']
166 if done:
167 log.info("Available after assign ports (new active {0}/{1})".format(
168 mgr_map['active_name'] , mgr_map['active_gid']))
169 return done
170 self.wait_until_true(is_available, timeout=30)