Skip to content

Commit e25d03c

Browse files
authored
Merge pull request #285 from innogames/ipv6_vms
Allow building VMs with only IPv6 address
2 parents 1e087ea + da7fd53 commit e25d03c

6 files changed

Lines changed: 46 additions & 22 deletions

File tree

igvm/commands.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from typing import List, Optional
1414

1515
from adminapi import parse
16-
from adminapi.dataset import Query
16+
from adminapi.dataset import Query, DatasetError
1717
from adminapi.filters import Any, BaseFilter, StartsWith, Contains
1818
from fabric.colors import green, red, white, yellow
1919
from fabric.network import disconnect_all
@@ -26,7 +26,7 @@
2626
HypervisorError,
2727
IGVMError,
2828
InconsistentAttributeError,
29-
InvalidStateError,
29+
InvalidStateError, NetworkError,
3030
)
3131
from igvm.host import with_fabric_settings
3232
from igvm.hypervisor import Hypervisor
@@ -268,14 +268,22 @@ def change_address(
268268
err = 'Current hypervisor does not support new subnet!'
269269
raise ConfigError(err)
270270

271-
new_network = Query(
272-
{
273-
'servertype': 'route_network',
274-
'state': 'online',
275-
'network_type': 'internal',
276-
'intern_ip': Contains(new_address),
277-
}
278-
).get()['hostname']
271+
for attr in ('ipv4', 'ipv6'):
272+
try:
273+
new_network = Query(
274+
{
275+
'servertype': 'route_network',
276+
'state': 'online',
277+
'network_type': 'internal',
278+
attr: Contains(new_address),
279+
}
280+
).get()['hostname']
281+
break
282+
except DatasetError:
283+
new_network = None
284+
285+
if new_network is None:
286+
raise NetworkError(f'Can\'t find a route_network for IP address {new_address}')
279287

280288
vm_was_running = vm.is_running()
281289

igvm/hypervisor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def get_vlan_network(self, ip_addr):
155155
its IP address changed.
156156
"""
157157
for vlan_network in self.dataset_obj['vlan_networks']:
158-
if ip_addr in vlan_network['intern_ip']:
158+
if ip_addr in vlan_network['ipv4'] or ip_addr in vlan_network['ipv6']:
159159
return vlan_network
160160
return None
161161

igvm/settings.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@
137137
{
138138
'vlan_networks': [
139139
'hostname',
140-
'intern_ip',
140+
'ipv4',
141+
'ipv6',
141142
'vlan_tag',
142143
],
143144
},

igvm/utils.py

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

66
from __future__ import division
77

8+
import ipaddress
89
import logging
910
import socket
1011
import time
@@ -49,7 +50,11 @@ def retry_wait_backoff(fn_check, fail_msg, max_wait=20):
4950

5051

5152
def ping_port(ip, port=22, timeout=1):
52-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
53+
ip_type = ipaddress.ip_address(ip)
54+
if ip_type.version == 4:
55+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
56+
else:
57+
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
5358
s.settimeout(timeout)
5459
try:
5560
s.connect((ip, port))

tests/conftest.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ def clean_all(route_network, datacenter_type, vm_hostname=None):
7474
# logic to assign them and we want to avoid IP address conflicts.
7575
# Index 1 is usually used for the test's subject VM,
7676
# 2 might be used for testing IP change.
77-
ips = [get_next_address(VM_NET, i) for i in [1, 2]]
78-
clean_serveradmin({'intern_ip': Any(*ips)})
77+
for ip_attr in ('ipv4', 'ipv6'):
78+
ips = [get_next_address(VM_NET, i, ip_attr) for i in [1, 2]]
79+
clean_serveradmin({ip_attr: Any(*ips)})
7980

8081

8182
def clean_hv(hv, pattern):
@@ -208,16 +209,16 @@ def _wait_for_state_reached(ec2_client, instance_id: str, state: str,
208209
raise
209210

210211

211-
def get_next_address(vm_net, index):
212+
def get_next_address(vm_net, index, ip_attr):
212213
non_vm_hosts = list(Query({
213214
'project_network': vm_net,
214215
'servertype': Not('vm'),
215-
}, ['intern_ip']))
216+
}, [ip_attr]))
216217
offset = 1 if len(non_vm_hosts) > 0 else 0
217218
subnet_levels = ceil(log(PYTEST_XDIST_WORKER_COUNT + offset, 2))
218-
project_network = Query({'hostname': vm_net}, ['intern_ip']).get()
219+
project_network = Query({'hostname': vm_net}, [ip_attr]).get()
219220
try:
220-
subnets = list(project_network['intern_ip'].subnets(subnet_levels))
221+
subnets = list(project_network[ip_attr].subnets(subnet_levels))
221222
except ValueError:
222223
raise IGVMTestError(
223224
'Can\'t split {} into enough subnets '

tests/test_integration.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ def teardown_module():
7373

7474

7575
class IGVMTest(TestCase):
76+
ip_attr = 'ipv4'
77+
7678
def setUp(self):
7779
"""Initialize VM object before every test
7880
@@ -112,7 +114,7 @@ def setUp(self):
112114
self.vm_obj['environment'] = 'testing'
113115
self.vm_obj['hostname'] = VM_HOSTNAME
114116
self.vm_obj['hypervisor'] = None
115-
self.vm_obj['intern_ip'] = get_next_address(VM_NET, 1)
117+
self.vm_obj['intern_ip'] = get_next_address(VM_NET, 1, self.ip_attr)
116118
self.vm_obj['memory'] = 2048
117119
self.vm_obj['no_monitoring'] = True
118120
self.vm_obj['num_cpu'] = 2
@@ -225,7 +227,7 @@ def test_kvm_hwmodel_to_cpumodel(self):
225227
msg='Missing hardware_model in KVM_HWMODEL_TO_CPUMODEL')
226228

227229

228-
class BuildTest(IGVMTest):
230+
class _BuildTest(IGVMTest):
229231
"""Test many possible VM building scenarios"""
230232

231233
def test_vm_build(self):
@@ -291,6 +293,13 @@ def test_rebuild(self):
291293
vm.run('test ! -f /root/initial_canary')
292294

293295

296+
class BuildTestIPv4(_BuildTest):
297+
ip_attr = 'ipv4'
298+
299+
300+
class BuildTestIPv6(_BuildTest):
301+
ip_attr = 'ipv6'
302+
294303
class CommandTest(IGVMTest):
295304
def setUp(self):
296305
super(CommandTest, self).setUp()
@@ -682,7 +691,7 @@ def test_new_address(self):
682691
# We don't have a way to ask for new IP address from Serveradmin
683692
# and lock it for us. The method below will usually work fine.
684693
# When it starts failing, we must develop retry method.
685-
new_address = get_next_address(VM_NET, 2)
694+
new_address = get_next_address(VM_NET, 2, 'ipv4')
686695

687696
change_address(VM_HOSTNAME, new_address, offline=True)
688697

0 commit comments

Comments
 (0)