]> git.proxmox.com Git - ceph.git/blame - ceph/src/cephadm/tests/test_cephadm.py
import 15.2.5
[ceph.git] / ceph / src / cephadm / tests / test_cephadm.py
CommitLineData
e306af50 1# type: ignore
9f95a23c
TL
2import argparse
3import mock
4import os
5import sys
6import unittest
7
8import pytest
9
10if sys.version_info >= (3, 3):
11 from importlib.machinery import SourceFileLoader
12 cd = SourceFileLoader('cephadm', 'cephadm').load_module()
13else:
14 import imp
15 cd = imp.load_source('cephadm', 'cephadm')
16
17class TestCephAdm(object):
18 def test_is_fsid(self):
19 assert not cd.is_fsid('no-uuid')
20
21 def test__get_parser_image(self):
22 args = cd._parse_args(['--image', 'foo', 'version'])
23 assert args.image == 'foo'
24
25 def test_CustomValidation(self):
26 assert cd._parse_args(['deploy', '--name', 'mon.a', '--fsid', 'fsid'])
27
28 with pytest.raises(SystemExit):
29 cd._parse_args(['deploy', '--name', 'wrong', '--fsid', 'fsid'])
30
31 @pytest.mark.parametrize("test_input, expected", [
32 ("podman version 1.6.2", (1,6,2)),
33 ("podman version 1.6.2-stable2", (1,6,2)),
34 ])
35 def test_parse_podman_version(self, test_input, expected):
36 assert cd._parse_podman_version(test_input) == expected
37
38 def test_parse_podman_version_invalid(self):
39 with pytest.raises(ValueError) as res:
40 cd._parse_podman_version('podman version inval.id')
41 assert 'inval' in str(res.value)
42
43 @pytest.mark.parametrize("test_input, expected", [
44 (
45"""
46default via 192.168.178.1 dev enxd89ef3f34260 proto dhcp metric 100
4710.0.0.0/8 via 10.4.0.1 dev tun0 proto static metric 50
4810.3.0.0/21 via 10.4.0.1 dev tun0 proto static metric 50
4910.4.0.1 dev tun0 proto kernel scope link src 10.4.0.2 metric 50
50137.1.0.0/16 via 10.4.0.1 dev tun0 proto static metric 50
51138.1.0.0/16 via 10.4.0.1 dev tun0 proto static metric 50
52139.1.0.0/16 via 10.4.0.1 dev tun0 proto static metric 50
53140.1.0.0/17 via 10.4.0.1 dev tun0 proto static metric 50
54141.1.0.0/16 via 10.4.0.1 dev tun0 proto static metric 50
55169.254.0.0/16 dev docker0 scope link metric 1000
56172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
57192.168.39.0/24 dev virbr1 proto kernel scope link src 192.168.39.1 linkdown
58192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown
59192.168.178.0/24 dev enxd89ef3f34260 proto kernel scope link src 192.168.178.28 metric 100
60192.168.178.1 dev enxd89ef3f34260 proto static scope link metric 100
61195.135.221.12 via 192.168.178.1 dev enxd89ef3f34260 proto static metric 100
62""",
63 {
64 '10.4.0.1': ['10.4.0.2'],
65 '172.17.0.0/16': ['172.17.0.1'],
66 '192.168.39.0/24': ['192.168.39.1'],
67 '192.168.122.0/24': ['192.168.122.1'],
68 '192.168.178.0/24': ['192.168.178.28']
69 }
70 ), (
71"""
72default via 10.3.64.1 dev eno1 proto static metric 100
7310.3.64.0/24 dev eno1 proto kernel scope link src 10.3.64.23 metric 100
7410.3.64.0/24 dev eno1 proto kernel scope link src 10.3.64.27 metric 100
7510.88.0.0/16 dev cni-podman0 proto kernel scope link src 10.88.0.1 linkdown
76172.21.0.0/20 via 172.21.3.189 dev tun0
77172.21.1.0/20 via 172.21.3.189 dev tun0
78172.21.2.1 via 172.21.3.189 dev tun0
79172.21.3.1 dev tun0 proto kernel scope link src 172.21.3.2
80172.21.4.0/24 via 172.21.3.1 dev tun0
81172.21.5.0/24 via 172.21.3.1 dev tun0
82172.21.6.0/24 via 172.21.3.1 dev tun0
83172.21.7.0/24 via 172.21.3.1 dev tun0
84192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown
85""",
86 {
87 '10.3.64.0/24': ['10.3.64.23', '10.3.64.27'],
88 '10.88.0.0/16': ['10.88.0.1'],
89 '172.21.3.1': ['172.21.3.2'],
90 '192.168.122.0/24': ['192.168.122.1']}
91 ),
92 ])
f6b5b4d7
TL
93 def test_parse_ipv4_route(self, test_input, expected):
94 assert cd._parse_ipv4_route(test_input) == expected
95
96 @pytest.mark.parametrize("test_routes, test_ips, expected", [
97 (
98"""
99::1 dev lo proto kernel metric 256 pref medium
100fdbc:7574:21fe:9200::/64 dev wlp2s0 proto ra metric 600 pref medium
101fdd8:591e:4969:6363::/64 dev wlp2s0 proto ra metric 600 pref medium
102fde4:8dba:82e1::/64 dev eth1 proto kernel metric 256 expires 1844sec pref medium
103fe80::/64 dev tun0 proto kernel metric 256 pref medium
104fe80::/64 dev wlp2s0 proto kernel metric 600 pref medium
105default dev tun0 proto static metric 50 pref medium
106default via fe80::2480:28ec:5097:3fe2 dev wlp2s0 proto ra metric 20600 pref medium
107""",
108"""
1091: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
110 inet6 ::1/128 scope host
111 valid_lft forever preferred_lft forever
1122: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
113 inet6 fdd8:591e:4969:6363:4c52:cafe:8dd4:dc4/64 scope global temporary dynamic
114 valid_lft 86394sec preferred_lft 14394sec
115 inet6 fdbc:7574:21fe:9200:4c52:cafe:8dd4:dc4/64 scope global temporary dynamic
116 valid_lft 6745sec preferred_lft 3145sec
117 inet6 fdd8:591e:4969:6363:103a:abcd:af1f:57f3/64 scope global temporary deprecated dynamic
118 valid_lft 86394sec preferred_lft 0sec
119 inet6 fdbc:7574:21fe:9200:103a:abcd:af1f:57f3/64 scope global temporary deprecated dynamic
120 valid_lft 6745sec preferred_lft 0sec
121 inet6 fdd8:591e:4969:6363:a128:1234:2bdd:1b6f/64 scope global temporary deprecated dynamic
122 valid_lft 86394sec preferred_lft 0sec
123 inet6 fdbc:7574:21fe:9200:a128:1234:2bdd:1b6f/64 scope global temporary deprecated dynamic
124 valid_lft 6745sec preferred_lft 0sec
125 inet6 fdd8:591e:4969:6363:d581:4321:380b:3905/64 scope global temporary deprecated dynamic
126 valid_lft 86394sec preferred_lft 0sec
127 inet6 fdbc:7574:21fe:9200:d581:4321:380b:3905/64 scope global temporary deprecated dynamic
128 valid_lft 6745sec preferred_lft 0sec
129 inet6 fe80::1111:2222:3333:4444/64 scope link noprefixroute
130 valid_lft forever preferred_lft forever
131 inet6 fde4:8dba:82e1:0:ec4a:e402:e9df:b357/64 scope global temporary dynamic
132 valid_lft 1074sec preferred_lft 1074sec
133 inet6 fde4:8dba:82e1:0:5054:ff:fe72:61af/64 scope global dynamic mngtmpaddr
134 valid_lft 1074sec preferred_lft 1074sec
13512: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 100
136 inet6 fe80::cafe:cafe:cafe:cafe/64 scope link stable-privacy
137 valid_lft forever preferred_lft forever
138""",
139 {
140 "::1": ["::1"],
141 "fdbc:7574:21fe:9200::/64": ["fdbc:7574:21fe:9200:4c52:cafe:8dd4:dc4",
142 "fdbc:7574:21fe:9200:103a:abcd:af1f:57f3",
143 "fdbc:7574:21fe:9200:a128:1234:2bdd:1b6f",
144 "fdbc:7574:21fe:9200:d581:4321:380b:3905"],
145 "fdd8:591e:4969:6363::/64": ["fdd8:591e:4969:6363:4c52:cafe:8dd4:dc4",
146 "fdd8:591e:4969:6363:103a:abcd:af1f:57f3",
147 "fdd8:591e:4969:6363:a128:1234:2bdd:1b6f",
148 "fdd8:591e:4969:6363:d581:4321:380b:3905"],
149 "fde4:8dba:82e1::/64": ["fde4:8dba:82e1:0:ec4a:e402:e9df:b357",
150 "fde4:8dba:82e1:0:5054:ff:fe72:61af"],
151 "fe80::/64": ["fe80::1111:2222:3333:4444",
152 "fe80::cafe:cafe:cafe:cafe"]
153 }
154 )])
155 def test_parse_ipv6_route(self, test_routes, test_ips, expected):
156 assert cd._parse_ipv6_route(test_routes, test_ips) == expected
157
158 def test_is_ipv6(self):
159 cd.logger = mock.Mock()
160 for good in ("[::1]", "::1",
161 "fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"):
162 assert cd.is_ipv6(good)
163 for bad in ("127.0.0.1",
164 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffg",
165 "1:2:3:4:5:6:7:8:9", "fd00::1::1", "[fg::1]"):
166 assert not cd.is_ipv6(bad)
167
168 def test_unwrap_ipv6(self):
169 def unwrap_test(address, expected):
170 assert cd.unwrap_ipv6(address) == expected
171
172 tests = [
173 ('::1', '::1'), ('[::1]', '::1'),
174 ('[fde4:8dba:82e1:0:5054:ff:fe6a:357]', 'fde4:8dba:82e1:0:5054:ff:fe6a:357'),
175 ('can actually be any string', 'can actually be any string'),
176 ('[but needs to be stripped] ', '[but needs to be stripped] ')]
177 for address, expected in tests:
178 unwrap_test(address, expected)
179
180 @mock.patch('cephadm.call_throws')
181 @mock.patch('cephadm.get_parm')
182 def test_registry_login(self, get_parm, call_throws):
183
184 # test normal valid login with url, username and password specified
185 call_throws.return_value = '', '', 0
186 args = cd._parse_args(['registry-login', '--registry-url', 'sample-url', '--registry-username', 'sample-user', '--registry-password', 'sample-pass'])
187 cd.args = args
188 retval = cd.command_registry_login()
189 assert retval == 0
190
191 # test bad login attempt with invalid arguments given
192 args = cd._parse_args(['registry-login', '--registry-url', 'bad-args-url'])
193 cd.args = args
194 with pytest.raises(Exception) as e:
195 assert cd.command_registry_login()
196 assert str(e.value) == ('Invalid custom registry arguments received. To login to a custom registry include '
197 '--registry-url, --registry-username and --registry-password options or --registry-json option')
198
199 # test normal valid login with json file
200 get_parm.return_value = {"url": "sample-url", "username": "sample-username", "password": "sample-password"}
201 args = cd._parse_args(['registry-login', '--registry-json', 'sample-json'])
202 cd.args = args
203 retval = cd.command_registry_login()
204 assert retval == 0
205
206 # test bad login attempt with bad json file
207 get_parm.return_value = {"bad-json": "bad-json"}
208 args = cd._parse_args(['registry-login', '--registry-json', 'sample-json'])
209 cd.args = args
210 with pytest.raises(Exception) as e:
211 assert cd.command_registry_login()
212 assert str(e.value) == ("json provided for custom registry login did not include all necessary fields. "
213 "Please setup json file as\n"
214 "{\n"
215 " \"url\": \"REGISTRY_URL\",\n"
216 " \"username\": \"REGISTRY_USERNAME\",\n"
217 " \"password\": \"REGISTRY_PASSWORD\"\n"
218 "}\n")
219
220 # test login attempt with valid arguments where login command fails
221 call_throws.side_effect = Exception
222 args = cd._parse_args(['registry-login', '--registry-url', 'sample-url', '--registry-username', 'sample-user', '--registry-password', 'sample-pass'])
223 cd.args = args
224 with pytest.raises(Exception) as e:
225 cd.command_registry_login()
226 assert str(e.value) == "Failed to login to custom registry @ sample-url as sample-user with given password"