Skip to content

Commit c37b15e

Browse files
authored
Merge pull request #170 from xcp-ng/ipv6
Adapt tests for IPv6 hosts
2 parents 8dfe66d + 3cc4b61 commit c37b15e

File tree

10 files changed

+46
-14
lines changed

10 files changed

+46
-14
lines changed

conftest.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from lib.common import wait_for, vm_image, is_uuid
1010
from lib.common import setup_formatted_and_mounted_disk, teardown_formatted_and_mounted_disk
11+
from lib.netutil import is_ipv6
1112
from lib.pool import Pool
1213
from lib.vm import VM
1314
from lib.xo import xo_cli
@@ -176,6 +177,11 @@ def xfail_on_xcpng_8_3(host, request):
176177
if host.xcp_version >= version.parse("8.3"):
177178
request.node.add_marker(pytest.mark.xfail)
178179

180+
@pytest.fixture(scope='session')
181+
def host_no_ipv6(host):
182+
if is_ipv6(host.hostname_or_ip):
183+
pytest.skip(f"This test requires an IPv4 XCP-ng")
184+
179185
@pytest.fixture(scope='session')
180186
def local_sr_on_hostA1(hostA1):
181187
""" A local SR on the pool's master. """
@@ -375,7 +381,8 @@ def second_network(request, host):
375381
pif_uuid = host.xe('pif-list', {'host-uuid': host.uuid, 'network-uuid': network_uuid}, minimal=True)
376382
if not pif_uuid:
377383
pytest.fail("The provided --second-network UUID doesn't exist or doesn't have a PIF on master host")
378-
ip = host.xe('pif-param-get', {'uuid': pif_uuid, 'param-name': 'IP'})
384+
ipv6 = (host.xe('pif-param-get', {'uuid': pif_uuid, 'param-name': 'primary-address-type'}) == "IPv6")
385+
ip = host.xe('pif-param-get', {'uuid': pif_uuid, 'param-name': 'IPv6' if ipv6 else 'IP'})
379386
if not ip:
380387
pytest.fail("The provided --second-network has a PIF but no IP")
381388
if network_uuid == host.management_network():

lib/commands.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import lib.config as config
66

7+
from lib.netutil import wrap_ip
78

89
class BaseCommandFailed(Exception):
910
__slots__ = 'returncode', 'stdout', 'cmd'
@@ -157,10 +158,11 @@ def scp(hostname_or_ip, src, dest, check=True, suppress_fingerprint_warnings=Tru
157158
# Based on https://unix.stackexchange.com/a/365976/257493
158159
opts = '-o "StrictHostKeyChecking no" -o "LogLevel ERROR" -o "UserKnownHostsFile /dev/null"'
159160

161+
ip = wrap_ip(hostname_or_ip)
160162
if local_dest:
161-
src = 'root@{}:{}'.format(hostname_or_ip, src)
163+
src = 'root@{}:{}'.format(ip, src)
162164
else:
163-
dest = 'root@{}:{}'.format(hostname_or_ip, dest)
165+
dest = 'root@{}:{}'.format(ip, dest)
164166

165167
command = "scp {} {} {}".format(opts, src, dest)
166168
res = subprocess.run(

lib/host.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from lib.common import _param_get, safe_split, to_xapi_bool, wait_for, wait_for_not
1212
from lib.common import prefix_object_name
13+
from lib.netutil import wrap_ip
1314
from lib.sr import SR
1415
from lib.vm import VM
1516
from lib.xo import xo_cli, xo_object_exists
@@ -147,7 +148,7 @@ def _get_xensource_inventory(self):
147148
def xo_get_server_id(self, store=True):
148149
servers = xo_cli('server.getAll', use_json=True)
149150
for server in servers:
150-
if server['host'] == self.hostname_or_ip:
151+
if server['host'] == wrap_ip(self.hostname_or_ip):
151152
if store:
152153
self.xo_srv_id = server['id']
153154
return server['id']
@@ -159,7 +160,7 @@ def xo_server_remove(self):
159160
else:
160161
servers = xo_cli('server.getAll', use_json=True)
161162
for server in servers:
162-
if server['host'] == self.hostname_or_ip:
163+
if server['host'] == wrap_ip(self.hostname_or_ip):
163164
xo_cli('server.remove', {'id': server['id']})
164165

165166
def xo_server_add(self, username, password, label=None, unregister_first=True):
@@ -171,7 +172,7 @@ def xo_server_add(self, username, password, label=None, unregister_first=True):
171172
xo_srv_id = xo_cli(
172173
'server.add',
173174
{
174-
'host': self.hostname_or_ip,
175+
'host': wrap_ip(self.hostname_or_ip),
175176
'username': username,
176177
'password': password,
177178
'allowUnauthorized': 'true',
@@ -183,7 +184,7 @@ def xo_server_add(self, username, password, label=None, unregister_first=True):
183184
def xo_server_status(self):
184185
servers = xo_cli('server.getAll', use_json=True)
185186
for server in servers:
186-
if server['host'] == self.hostname_or_ip:
187+
if server['host'] == wrap_ip(self.hostname_or_ip):
187188
return server['status']
188189
return None
189190

lib/netutil.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import socket
2+
3+
def is_ipv6(ip):
4+
try:
5+
socket.inet_pton(socket.AF_INET6, ip)
6+
return True
7+
except Exception:
8+
return False
9+
10+
def wrap_ip(ip):
11+
""" Wrap an IP between brackets if and only if it's an IPv6. """
12+
return f"[{ip}]" if is_ipv6(ip) else ip

tests/migration/test_host_evacuate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,8 @@ def test_host_evacuate_with_network_not_present(self, host, hostA2, second_netwo
111111
pif_uuid = host.xe('pif-list', {'host-uuid': hostA2.uuid, 'network-uuid': second_network}, minimal=True)
112112
args['uuid'] = pif_uuid
113113
logging.info(f"Re-add and plug PIF {pif_uuid}")
114+
if ipv6:
115+
# Default is IPv4
116+
host.xe('pif-set-primary-address-type', {'uuid': pif_uuid, 'primary_address_type': 'ipv6'})
114117
host.xe(reconfigure_method, args)
115118
host.xe('pif-plug', {'uuid': pif_uuid})

tests/misc/test_file_server.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import re
33
import subprocess
44

5+
from lib.netutil import wrap_ip
6+
57
# These tests are meant to test an host fileserver behavior.
68
#
79
# Requirements:
@@ -14,15 +16,16 @@ def _header_equal(header, name, value):
1416

1517
def test_fileserver_redirect_https(host):
1618
path = "/path/to/dir/file.txt"
19+
ip = wrap_ip(host.hostname_or_ip)
1720
process = subprocess.Popen(
18-
["curl", "-i", "http://" + host.hostname_or_ip + path],
21+
["curl", "-i", "http://" + ip + path],
1922
stdout=subprocess.PIPE,
2023
stderr=subprocess.PIPE
2124
)
2225
stdout, _ = process.communicate()
2326
lines = stdout.decode().splitlines()
2427
assert lines[0].strip() == "HTTP/1.1 301 Moved Permanently"
25-
assert _header_equal(lines[2], "location", "https://" + host.hostname_or_ip + path)
28+
assert _header_equal(lines[2], "location", "https://" + ip + path)
2629

2730
@pytest.mark.usefixtures("host_at_least_8_3")
2831
class TestHSTS:
@@ -31,7 +34,7 @@ class TestHSTS:
3134

3235
def __get_header(host):
3336
process = subprocess.Popen(
34-
["curl", "-XGET", "-k", "-I", "https://" + host.hostname_or_ip],
37+
["curl", "-XGET", "-k", "-I", "https://" + wrap_ip(host.hostname_or_ip)],
3538
stdout=subprocess.PIPE,
3639
stderr=subprocess.PIPE
3740
)

tests/storage/moosefs/test_moosefs_sr.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ def test_create_moosefs_sr_without_mfsmount(self, host, moosefs_device_config):
3131
sr.destroy()
3232
assert False, "MooseFS SR creation should failed!"
3333

34+
# MooseFS doesn't support IPv6
35+
@pytest.mark.usefixtures("host_no_ipv6")
3436
def test_create_and_destroy_sr(self, moosefs_device_config, pool_with_moosefs_enabled):
3537
# Create and destroy tested in the same test to leave the host as unchanged as possible
3638
master = pool_with_moosefs_enabled.master
@@ -41,7 +43,8 @@ def test_create_and_destroy_sr(self, moosefs_device_config, pool_with_moosefs_en
4143
vm.destroy(verify=True)
4244
sr.destroy(verify=True)
4345

44-
@pytest.mark.usefixtures("moosefs_sr")
46+
# MooseFS doesn't support IPv6
47+
@pytest.mark.usefixtures("moosefs_sr", "host_no_ipv6")
4548
class TestMooseFSSR:
4649
@pytest.mark.quicktest
4750
def test_quicktest(self, moosefs_sr):

tests/storage/moosefs/test_moosefs_sr_crosspool_migration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
@pytest.mark.small_vm # run with a small VM to test the features
1414
@pytest.mark.big_vm # and ideally on a big VM to test it scales
15-
@pytest.mark.usefixtures("hostB1", "local_sr_on_hostB1")
15+
@pytest.mark.usefixtures("hostB1", "local_sr_on_hostB1", "host_no_ipv6") # MooseFS doesn't support IPv6
1616
class Test:
1717
def test_cold_crosspool_migration(self, host, hostB1, vm_on_moosefs_sr, moosefs_sr, local_sr_on_hostB1):
1818
cold_migration_then_come_back(vm_on_moosefs_sr, host, moosefs_sr, hostB1, local_sr_on_hostB1)

tests/storage/moosefs/test_moosefs_sr_intrapool_migration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
@pytest.mark.small_vm # run with a small VM to test the features
1414
@pytest.mark.big_vm # and ideally on a big VM to test it scales
15-
@pytest.mark.usefixtures("hostA2", "local_sr_on_hostA2")
15+
@pytest.mark.usefixtures("hostA2", "local_sr_on_hostA2", "host_no_ipv6") # MooseFS doesn't support IPv6
1616
class Test:
1717
def test_live_intrapool_shared_migration(self, host, hostA2, vm_on_moosefs_sr, moosefs_sr):
1818
live_storage_migration_then_come_back(vm_on_moosefs_sr, host, moosefs_sr, hostA2, moosefs_sr)

tests/xen/test_xtf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
# - host: XCP-ng host >= 8.2, with Xen booted with the hvm_fep command line parameter
99
# See https://xenbits.xen.org/docs/xtf/
1010

11-
@pytest.mark.usefixtures("host_with_hvm_fep", "host_with_dynamically_disabled_ept_sp")
11+
# XTF git repo is not available in IPv6
12+
@pytest.mark.usefixtures("host_with_hvm_fep", "host_with_dynamically_disabled_ept_sp", "host_no_ipv6")
1213
class TestXtf:
1314
_common_skips = [
1415
# UMIP requires hardware support, that is a recent enough CPU

0 commit comments

Comments
 (0)