blob: d6271c2cf72306a36637d742194716d92d365f11 [file] [log] [blame]
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +00001import pytest
2import json
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +03003import utils
Hanna Arhipova56eab942019-05-06 20:14:18 +03004import logging
Hanna Arhipova2d538412021-08-17 10:44:41 +03005import itertools
6from functools import lru_cache
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +03007
Hanna Arhipova2d538412021-08-17 10:44:41 +03008
9@lru_cache(maxsize=32)
10def targeted_minions(target):
11 """
12 Returns nodes associated with salt target
13 :param target: str, salt target in COMPOUND notation like I@nova:server
14 More here https://docs.saltproject.io/en/latest/topics/targeting/compound.html
15 :return: list of nodes or []
16 """
17 salt_client = pytest.local_salt_client
18 return list(salt_client.test_ping(
19 tgt=target,
20 expr_form='compound'))
21
22
23def is_deb_in_exception(inconsistency_rule, package_name, node_hostname):
24 for salt_target, excluded_packages in inconsistency_rule.items():
25 if package_name in excluded_packages \
26 and node_hostname in targeted_minions(salt_target):
Ekaterina Chernovab4806752019-07-26 16:02:18 +030027 return True
28 return False
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +000029
Hanna Arhipova2d538412021-08-17 10:44:41 +030030
Oleksii Zhurba5b15b9b2019-05-09 18:53:40 -050031@pytest.mark.full
Oleksii Zhurbad0ae87f2018-03-26 13:36:25 -050032def test_check_package_versions(local_salt_client, nodes_in_group):
Ekaterina Chernovab4806752019-07-26 16:02:18 +030033 """Validate package has same versions on all the nodes.
34 Steps:
35 1) Collect packages for nodes_in_group
36 "salt -C '<group_of_nodes>' cmd.run 'lowpkg.list_pkgs'"
37 2) Exclude nodes without packages and exceptions
Ekaterina Chernova7ea97152019-07-29 17:09:12 +030038 3) Go through each package and save it with version from each node to the
Ekaterina Chernovab4806752019-07-26 16:02:18 +030039 list. Mark 'No version' if package is not found.
Hanna Arhipova2d538412021-08-17 10:44:41 +030040 If package name in the exception list or in inconsistency_rule,
41 ignore it.
Ekaterina Chernovab4806752019-07-26 16:02:18 +030042 4) Compare items in that list - they should be equal and match the amout of nodes
43
44 """
Hanna Arhipova2d538412021-08-17 10:44:41 +030045 salt = local_salt_client
46 # defines packages specific to the nodes
47 inconsistency_rule = {
48 "I@backupninja:server": [
49 "rsync", "sysstat", "xz-utils"],
50 "I@elasticsearch:server": [
51 "python-elasticsearch"],
52 # PROD-30833
53 "I@octavia:manager:controller_worker:loadbalancer_topology:SINGLE": [
54 "netfilter-persistent",
55 "gunicorn",
56 "octavia-worker",
57 "octavia-health-manager",
Hanna Arhipovaae2e05b2021-08-18 10:47:39 +030058 "octavia-housekeeping",
59 'python-automaton',
60 'python-setproctitle',
61 'python-glanceclient',
62 'libnss3-nssdb',
63 'python-json-pointer',
64 'debootstrap',
65 'python-cotyledon',
66 'librbd1',
67 'qemu-block-extra:amd64',
68 'python-diskimage-builder',
69 'liburcu4:amd64',
70 'python-networkx',
71 'librados2',
72 'kpartx',
73 'python-taskflow',
74 'libnss3:amd64',
75 'libibverbs1',
76 'python-itsdangerous',
77 'liblttng-ust0:amd64',
78 'python-wsme',
79 'python-werkzeug',
80 'liblttng-ust-ctl2:amd64',
81 'python-gunicorn',
82 'python-octavia',
83 'python-warlock',
84 'python-barbicanclient',
85 'iptables-persistent',
86 'python-psycopg2',
87 'octavia-common',
88 'python-flask',
89 'libpq5:amd64',
90 'python-dib-utils',
91 'python-jsonpatch',
92 'libnspr4:amd64',
93 'qemu-utils',
94 'python-pyasn1-modules',
95 'libonig2:amd64',
96 'jq',
97 'libaio1:amd64',
98 'python-kazoo',
99 'python-ipaddr',
100 'libiscsi2:amd64']
Hanna Arhipova2d538412021-08-17 10:44:41 +0300101 }
Hanna Arhipova8fd295c2019-03-07 13:46:43 +0200102 exclude_packages = utils.get_configuration().get("skipped_packages", [])
Hanna Arhipova2d538412021-08-17 10:44:41 +0300103
104 group_name, nodes = nodes_in_group
105 packages_versions_by_nodes = salt.cmd(tgt="L@"+','.join(nodes),
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500106 fun='lowpkg.list_pkgs',
107 expr_form='compound')
Oleksii Zhurbadad1acc2018-03-26 14:09:38 -0500108 # Let's exclude cid01 and dbs01 nodes from this check
Hanna Arhipova2d538412021-08-17 10:44:41 +0300109 exclude_nodes = targeted_minions("I@galera:master or I@gerrit:client")
Oleksii Zhurba599801a2019-06-04 17:26:51 -0500110
Hanna Arhipova2d538412021-08-17 10:44:41 +0300111 total_nodes = [i
112 for i in nodes
113 if i not in exclude_nodes]
Oleksii Zhurba5f768c52018-08-07 17:27:57 -0500114 if len(total_nodes) < 2:
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000115 pytest.skip("Nothing to compare - only 1 node")
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000116
Hanna Arhipova2d538412021-08-17 10:44:41 +0300117 packages_with_different_versions = dict()
118 packages_names = set(itertools.chain.from_iterable(
119 [packages_versions_by_nodes[node].keys()
120 for node in total_nodes])
121 )
122
Hanna Arhipova8fd295c2019-03-07 13:46:43 +0200123 for deb in packages_names:
124 if deb in exclude_packages:
125 continue
Ekaterina Chernovab4806752019-07-26 16:02:18 +0300126
Hanna Arhipova2d538412021-08-17 10:44:41 +0300127 node_and_version = [
128 (node, packages_versions_by_nodes[node].get(deb, "No package"))
129 for node in total_nodes
130 if not is_deb_in_exception(inconsistency_rule, deb, node)
131 ]
132
133 if set([version for node, version in node_and_version]).__len__() > 1:
134 packages_with_different_versions[deb] = [
135 f"{node}: {version}"
136 for node, version in node_and_version]
137
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200138 assert len(packages_with_different_versions) == 0, (
139 "Non-uniform package versions are installed on '{}' group of nodes:\n"
140 "{}".format(
Hanna Arhipova2d538412021-08-17 10:44:41 +0300141 group_name, json.dumps(packages_with_different_versions, indent=4))
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200142 )
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000143
144
Oleksii Zhurba5b15b9b2019-05-09 18:53:40 -0500145@pytest.mark.full
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300146def test_packages_are_latest(local_salt_client, nodes_in_group):
147 config = utils.get_configuration()
148 skip = config.get("test_packages")["skip_test"]
Ievgeniia Zadorozhna0c306fd2019-11-12 16:03:51 +0300149 if skip.lower() == 'true':
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300150 pytest.skip("Test for the latest packages is disabled")
151 skipped_pkg = config.get("test_packages")["skipped_packages"]
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200152 group, nodes = nodes_in_group
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300153 info_salt = local_salt_client.cmd(
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200154 tgt='L@' + ','.join(nodes),
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500155 param='apt list --upgradable 2>/dev/null | grep -v Listing',
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300156 expr_form='compound')
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200157 for node in nodes:
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300158 result = []
159 if info_salt[node]:
160 upg_list = info_salt[node].split('\n')
161 for i in upg_list:
162 if i.split('/')[0] not in skipped_pkg:
163 result.append(i)
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200164 assert not result, (
165 "Packages are not of latest version on '{}' node:\n{}".format(
166 node, "\n".join(result))
167 )
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300168
169
Oleksii Zhurba5b15b9b2019-05-09 18:53:40 -0500170@pytest.mark.full
Oleksii Zhurbad0ae87f2018-03-26 13:36:25 -0500171def test_check_module_versions(local_salt_client, nodes_in_group):
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300172 # defines modules specific to the nodes
173 inconsistency_rule = {
174 "I@elasticsearch:server": ["elasticsearch"],
175 # PROD-30833
Hanna Arhipovaae2e05b2021-08-18 10:47:39 +0300176 "I@octavia:manager:controller_worker:loadbalancer_topology:SINGLE": [
177 'octavia',
178 'setproctitle',
179 'automaton',
180 'warlock',
181 'python-glanceclient',
182 'taskflow',
183 'diskimage-builder',
184 'pyasn1-modules',
185 'python-barbicanclient',
186 'WSME',
187 'jsonpatch',
188 'cotyledon',
189 'dib-utils',
190 'itsdangerous',
191 'kazoo',
192 'psycopg2',
193 'Flask',
194 'networkx',
195 'Werkzeug',
196 'jsonpointer',
197 'gunicorn',
198 'ipaddr']
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300199 }
Hanna Arhipova8fd295c2019-03-07 13:46:43 +0200200 exclude_modules = utils.get_configuration().get("skipped_modules", [])
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200201 group, nodes = nodes_in_group
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300202
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000203 pre_check = local_salt_client.cmd(
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300204 tgt="L@{nodes}".format(nodes=','.join(nodes)),
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500205 param='dpkg -l | grep "python-pip "',
Oleksii Zhurba5f768c52018-08-07 17:27:57 -0500206 expr_form='compound')
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300207 exclude_nodes = targeted_minions("I@galera:master or I@gerrit:client")
Ekaterina Chernovae32e3f92019-11-12 14:56:03 +0300208 if list(pre_check.values()).count('') > 0:
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000209 pytest.skip("pip is not installed on one or more nodes")
Oleksii Zhurba5f768c52018-08-07 17:27:57 -0500210
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300211 total_nodes = [node
212 for node in nodes
213 if node not in exclude_nodes]
Oleksii Zhurba5f768c52018-08-07 17:27:57 -0500214 if len(total_nodes) < 2:
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000215 pytest.skip("Nothing to compare - only 1 node")
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200216 list_of_pip_packages = local_salt_client.cmd(
217 tgt="L@"+','.join(nodes),
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300218 fun='pip.list', expr_form='compound')
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000219
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300220 modules_with_different_versions = dict()
221 packages_names = set(itertools.chain.from_iterable(
222 list_of_pip_packages.values()
223 ))
Oleksii Zhurbaa32d92f2018-03-29 16:22:35 -0500224
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300225 for package in packages_names:
226 if package in exclude_modules:
Hanna Arhipova8fd295c2019-03-07 13:46:43 +0200227 continue
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300228 node_and_version = [
229 (node, list_of_pip_packages[node].get(package, "No module"))
230 for node in total_nodes
231 if not is_deb_in_exception(inconsistency_rule, package, node)
232 ]
233
234 if set([version for node, version in node_and_version]).__len__() > 1:
235 modules_with_different_versions[package] = [
236 f"{node}: {version}"
237 for node, version in node_and_version
238 ]
239
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200240 assert len(modules_with_different_versions) == 0, (
241 "Non-uniform pip modules are installed on '{}' group of nodes:\n"
242 "{}".format(
243 group, json.dumps(modules_with_different_versions, indent=4))
244 )
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200245
246
247@pytest.mark.full
248def test_restricted_updates_repo(local_salt_client):
249 restricted_repo_enabled = local_salt_client.pillar_get(
250 tgt="I@salt:master",
Hanna Arhipova1d87dbe2021-02-16 19:26:27 +0200251 param='_param:updates_mirantis_login',
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200252 expr_form='compound')
253 if not restricted_repo_enabled:
Hanna Arhipova2d538412021-08-17 10:44:41 +0300254 pytest.skip("This env doesn't require the restricted ubuntu repo")
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200255
256 repos_by_nodes=local_salt_client.cmd(
257 tgt="*",
258 param="apt-cache policy |grep updates.mirantis.com"
259 )
260
Hanna Arhipova1d87dbe2021-02-16 19:26:27 +0200261 assert all(list(repos_by_nodes.values())), \
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200262 "Next nodes don't have updates.mirantis.com in sources.list: {}".\
263 format({node for node, repo
264 in repos_by_nodes.items()
265 if not repo})