blob: 179f66a6e569f5b747400cfce82debc91f60b05d [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.
Hanna Arhipova035dea42021-08-19 12:24:08 +030042 4) Compare items in that list - they should be equal and match the
43 amount of nodes
Ekaterina Chernovab4806752019-07-26 16:02:18 +030044
45 """
Hanna Arhipova2d538412021-08-17 10:44:41 +030046 salt = local_salt_client
47 # defines packages specific to the nodes
48 inconsistency_rule = {
49 "I@backupninja:server": [
50 "rsync", "sysstat", "xz-utils"],
51 "I@elasticsearch:server": [
52 "python-elasticsearch"],
53 # PROD-30833
54 "I@octavia:manager:controller_worker:loadbalancer_topology:SINGLE": [
55 "netfilter-persistent",
56 "gunicorn",
57 "octavia-worker",
58 "octavia-health-manager",
Hanna Arhipovaae2e05b2021-08-18 10:47:39 +030059 "octavia-housekeeping",
60 'python-automaton',
61 'python-setproctitle',
62 'python-glanceclient',
63 'libnss3-nssdb',
64 'python-json-pointer',
65 'debootstrap',
66 'python-cotyledon',
67 'librbd1',
68 'qemu-block-extra:amd64',
69 'python-diskimage-builder',
70 'liburcu4:amd64',
71 'python-networkx',
72 'librados2',
73 'kpartx',
74 'python-taskflow',
75 'libnss3:amd64',
76 'libibverbs1',
77 'python-itsdangerous',
78 'liblttng-ust0:amd64',
79 'python-wsme',
80 'python-werkzeug',
81 'liblttng-ust-ctl2:amd64',
82 'python-gunicorn',
83 'python-octavia',
84 'python-warlock',
85 'python-barbicanclient',
86 'iptables-persistent',
87 'python-psycopg2',
88 'octavia-common',
89 'python-flask',
90 'libpq5:amd64',
91 'python-dib-utils',
92 'python-jsonpatch',
93 'libnspr4:amd64',
94 'qemu-utils',
95 'python-pyasn1-modules',
96 'libonig2:amd64',
97 'jq',
98 'libaio1:amd64',
99 'python-kazoo',
100 'python-ipaddr',
101 'libiscsi2:amd64']
Hanna Arhipova035dea42021-08-19 12:24:08 +0300102 }
Hanna Arhipova8fd295c2019-03-07 13:46:43 +0200103 exclude_packages = utils.get_configuration().get("skipped_packages", [])
Hanna Arhipova2d538412021-08-17 10:44:41 +0300104
105 group_name, nodes = nodes_in_group
106 packages_versions_by_nodes = salt.cmd(tgt="L@"+','.join(nodes),
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500107 fun='lowpkg.list_pkgs',
108 expr_form='compound')
Oleksii Zhurbadad1acc2018-03-26 14:09:38 -0500109 # Let's exclude cid01 and dbs01 nodes from this check
Hanna Arhipova2d538412021-08-17 10:44:41 +0300110 exclude_nodes = targeted_minions("I@galera:master or I@gerrit:client")
Oleksii Zhurba599801a2019-06-04 17:26:51 -0500111
Hanna Arhipova2d538412021-08-17 10:44:41 +0300112 total_nodes = [i
113 for i in nodes
114 if i not in exclude_nodes]
Oleksii Zhurba5f768c52018-08-07 17:27:57 -0500115 if len(total_nodes) < 2:
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000116 pytest.skip("Nothing to compare - only 1 node")
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000117
Hanna Arhipova2d538412021-08-17 10:44:41 +0300118 packages_with_different_versions = dict()
119 packages_names = set(itertools.chain.from_iterable(
120 [packages_versions_by_nodes[node].keys()
121 for node in total_nodes])
122 )
123
Hanna Arhipova8fd295c2019-03-07 13:46:43 +0200124 for deb in packages_names:
125 if deb in exclude_packages:
126 continue
Ekaterina Chernovab4806752019-07-26 16:02:18 +0300127
Hanna Arhipova2d538412021-08-17 10:44:41 +0300128 node_and_version = [
129 (node, packages_versions_by_nodes[node].get(deb, "No package"))
130 for node in total_nodes
131 if not is_deb_in_exception(inconsistency_rule, deb, node)
132 ]
133
134 if set([version for node, version in node_and_version]).__len__() > 1:
135 packages_with_different_versions[deb] = [
Hanna Arhipova035dea42021-08-19 12:24:08 +0300136 "{}: {}".format(node, version)
Hanna Arhipova2d538412021-08-17 10:44:41 +0300137 for node, version in node_and_version]
138
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200139 assert len(packages_with_different_versions) == 0, (
140 "Non-uniform package versions are installed on '{}' group of nodes:\n"
141 "{}".format(
Hanna Arhipova2d538412021-08-17 10:44:41 +0300142 group_name, json.dumps(packages_with_different_versions, indent=4))
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200143 )
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000144
145
Oleksii Zhurba5b15b9b2019-05-09 18:53:40 -0500146@pytest.mark.full
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300147def test_packages_are_latest(local_salt_client, nodes_in_group):
148 config = utils.get_configuration()
149 skip = config.get("test_packages")["skip_test"]
Ievgeniia Zadorozhna0c306fd2019-11-12 16:03:51 +0300150 if skip.lower() == 'true':
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300151 pytest.skip("Test for the latest packages is disabled")
152 skipped_pkg = config.get("test_packages")["skipped_packages"]
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200153 group, nodes = nodes_in_group
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300154 info_salt = local_salt_client.cmd(
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200155 tgt='L@' + ','.join(nodes),
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500156 param='apt list --upgradable 2>/dev/null | grep -v Listing',
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300157 expr_form='compound')
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200158 for node in nodes:
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300159 result = []
160 if info_salt[node]:
161 upg_list = info_salt[node].split('\n')
162 for i in upg_list:
163 if i.split('/')[0] not in skipped_pkg:
164 result.append(i)
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200165 assert not result, (
166 "Packages are not of latest version on '{}' node:\n{}".format(
167 node, "\n".join(result))
168 )
Ievgeniia Zadorozhna6baf7872019-01-25 19:09:30 +0300169
170
Oleksii Zhurba5b15b9b2019-05-09 18:53:40 -0500171@pytest.mark.full
Oleksii Zhurbad0ae87f2018-03-26 13:36:25 -0500172def test_check_module_versions(local_salt_client, nodes_in_group):
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300173 # defines modules specific to the nodes
174 inconsistency_rule = {
175 "I@elasticsearch:server": ["elasticsearch"],
176 # PROD-30833
Hanna Arhipovaae2e05b2021-08-18 10:47:39 +0300177 "I@octavia:manager:controller_worker:loadbalancer_topology:SINGLE": [
178 'octavia',
179 'setproctitle',
180 'automaton',
181 'warlock',
182 'python-glanceclient',
183 'taskflow',
184 'diskimage-builder',
185 'pyasn1-modules',
186 'python-barbicanclient',
187 'WSME',
188 'jsonpatch',
189 'cotyledon',
190 'dib-utils',
191 'itsdangerous',
192 'kazoo',
193 'psycopg2',
194 'Flask',
195 'networkx',
196 'Werkzeug',
197 'jsonpointer',
198 'gunicorn',
199 'ipaddr']
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300200 }
Hanna Arhipova8fd295c2019-03-07 13:46:43 +0200201 exclude_modules = utils.get_configuration().get("skipped_modules", [])
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200202 group, nodes = nodes_in_group
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300203
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000204 pre_check = local_salt_client.cmd(
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300205 tgt="L@{nodes}".format(nodes=','.join(nodes)),
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500206 param='dpkg -l | grep "python-pip "',
Oleksii Zhurba5f768c52018-08-07 17:27:57 -0500207 expr_form='compound')
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300208 exclude_nodes = targeted_minions("I@galera:master or I@gerrit:client")
Ekaterina Chernovae32e3f92019-11-12 14:56:03 +0300209 if list(pre_check.values()).count('') > 0:
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000210 pytest.skip("pip is not installed on one or more nodes")
Oleksii Zhurba5f768c52018-08-07 17:27:57 -0500211
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300212 total_nodes = [node
213 for node in nodes
214 if node not in exclude_nodes]
Oleksii Zhurba5f768c52018-08-07 17:27:57 -0500215 if len(total_nodes) < 2:
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000216 pytest.skip("Nothing to compare - only 1 node")
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200217 list_of_pip_packages = local_salt_client.cmd(
218 tgt="L@"+','.join(nodes),
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300219 fun='pip.list', expr_form='compound')
Oleksii Zhurbaa10927b2017-09-27 22:09:23 +0000220
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300221 modules_with_different_versions = dict()
222 packages_names = set(itertools.chain.from_iterable(
223 list_of_pip_packages.values()
224 ))
Oleksii Zhurbaa32d92f2018-03-29 16:22:35 -0500225
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300226 for package in packages_names:
227 if package in exclude_modules:
Hanna Arhipova8fd295c2019-03-07 13:46:43 +0200228 continue
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300229 node_and_version = [
230 (node, list_of_pip_packages[node].get(package, "No module"))
231 for node in total_nodes
232 if not is_deb_in_exception(inconsistency_rule, package, node)
233 ]
234
235 if set([version for node, version in node_and_version]).__len__() > 1:
236 modules_with_different_versions[package] = [
Hanna Arhipova035dea42021-08-19 12:24:08 +0300237 "{}: {}".format(node, version)
Hanna Arhipovae7ebae62021-08-17 20:29:38 +0300238 for node, version in node_and_version
239 ]
240
Dmitriy Kruglova34a3042019-08-20 11:45:35 +0200241 assert len(modules_with_different_versions) == 0, (
242 "Non-uniform pip modules are installed on '{}' group of nodes:\n"
243 "{}".format(
244 group, json.dumps(modules_with_different_versions, indent=4))
245 )
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200246
247
248@pytest.mark.full
249def test_restricted_updates_repo(local_salt_client):
250 restricted_repo_enabled = local_salt_client.pillar_get(
251 tgt="I@salt:master",
Hanna Arhipova1d87dbe2021-02-16 19:26:27 +0200252 param='_param:updates_mirantis_login',
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200253 expr_form='compound')
254 if not restricted_repo_enabled:
Hanna Arhipova2d538412021-08-17 10:44:41 +0300255 pytest.skip("This env doesn't require the restricted ubuntu repo")
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200256
257 repos_by_nodes=local_salt_client.cmd(
258 tgt="*",
259 param="apt-cache policy |grep updates.mirantis.com"
Hanna Arhipova035dea42021-08-19 12:24:08 +0300260 )
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200261
Hanna Arhipova1d87dbe2021-02-16 19:26:27 +0200262 assert all(list(repos_by_nodes.values())), \
Hanna Arhipova5a56ae62021-02-11 16:27:52 +0200263 "Next nodes don't have updates.mirantis.com in sources.list: {}".\
264 format({node for node, repo
265 in repos_by_nodes.items()
Hanna Arhipova035dea42021-08-19 12:24:08 +0300266 if not repo})