Commit b21e68ff authored by Thomas Gambier's avatar Thomas Gambier 🚴🏼

slapos.core: introduce ipv6_range for each partition

parent 839ac0ef
......@@ -32,6 +32,7 @@ tap_ipv6 = true
# You can choose any other local network which does not conflict with your
# current machine configuration
ipv4_local_network = 10.0.0.0/16
partition_has_ipv6_range = true
# to enable, change to [firewall]
[disabled-firewall]
......
This diff is collapsed.
......@@ -59,11 +59,23 @@ from .interface.slap import IRequester
from ..grid.slapgrid import SLAPGRID_PROMISE_FAIL
from .slap import slap
from ..util import dumps, rmtree
from ..util import dumps, rmtree, getPartitionIpv6Addr, getPartitionIpv6Range
from ..grid.svcbackend import getSupervisorRPC
from ..grid.svcbackend import _getSupervisordSocketPath
def _getPartitionIpv6(ipv6_address, i):
# returns (single_ipv6_address, ipv6_range) for a partition
# ipv6_address can be either a range or a single IPv6 address (with no /)
if '/' in ipv6_address:
addr,netmask = ipv6_address.split('/')
single_ipv6_address = getPartitionIpv6Addr({'addr':addr, 'netmask':int(netmask)}, i)['addr']
ipv6_range = getPartitionIpv6Range({'addr':addr, 'netmask':int(netmask)}, i)
else:
ipv6_range = None
single_ipv6_address = ipv6_address
return (single_ipv6_address, ipv6_range)
@zope.interface.implementer(IException)
class SlapOSNodeCommandError(Exception):
......@@ -287,9 +299,7 @@ class SlapformatDefinitionWriter(ConfigWriter):
"""
def writeConfig(self, path):
ipv4 = self._standalone_slapos._ipv4_address
ipv6 = self._standalone_slapos._ipv6_address
ipv4_cidr = ipv4 + '/255.255.255.255' if ipv4 else ''
ipv6_cidr = ipv6 + '/64' if ipv6 else ''
user = pwd.getpwuid(os.getuid()).pw_name
partition_base_name = self._standalone_slapos._partition_base_name
with open(path, 'w') as f:
......@@ -300,11 +310,15 @@ class SlapformatDefinitionWriter(ConfigWriter):
address = {ipv4_cidr}\n
""").format(**locals()))
for i in range(self._standalone_slapos._partition_count):
print(i)
Please register or sign in to reply
single_ipv6_address, ipv6_range = _getPartitionIpv6(self._standalone_slapos._ipv6_address, i)
ipv6_range_network= '{addr}/{netmask}'.format(**ipv6_range)
f.write(
textwrap.dedent(
"""
[partition_{i}]
address = {ipv6_cidr} {ipv4_cidr}
address = {single_ipv6_address}/128 {ipv4_cidr}
ipv6_range = {ipv6_range_network}
pathname = {partition_base_name}{i}
user = {user}
network_interface =\n
......@@ -594,8 +608,12 @@ class StandaloneSlapOS(object):
partition_base_name="slappart"):
"""Creates `partition_count` partitions.
All partitions have the same `ipv4_address` and `ipv6_address` and
use the current system user.
All partitions have the same `ipv4_address` and use the current system
user.
`ipv6_address` can be a single address (in this case all partitions have
the same address) or a range in the form IPV6/CIDR (in this case each
partition has a subrange).
When calling this a second time with a lower `partition_count` or with
different `partition_base_name` will delete existing partitions.
......@@ -628,6 +646,7 @@ class StandaloneSlapOS(object):
if not (os.path.exists(partition_path)):
os.mkdir(partition_path)
os.chmod(partition_path, 0o750)
single_ipv6_address, ipv6_range = _getPartitionIpv6(ipv6_address, i)
partition_list.append({
'address_list': [
{
......@@ -635,10 +654,11 @@ class StandaloneSlapOS(object):
'netmask': '255.255.255.255'
},
{
'addr': ipv6_address,
'addr': single_ipv6_address,
'netmask': 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'
},
],
'ipv6_range' : ipv6_range,
'path': partition_path,
'reference': partition_reference,
'tap': {
......
......@@ -199,6 +199,69 @@ def ipv6FromBin(ip, suffix=''):
return socket.inet_ntop(socket.AF_INET6,
struct.pack('>QQ', int(ip[:64], 2), int(ip[64:], 2)))
def getPartitionIpv6Addr(ipv6_range, partition_index):
"""
from a IPv6 range in the form
{
'addr' : addr,
'natmask' : CIDR
}
returns the IPv6 addr
addr::(partition_index+2) (address 1 is is used by re6st)
"""
addr = ipv6_range['addr']
netmask = ipv6_range['netmask']
prefix = binFromIpv6(addr)[:netmask]
return dict(addr = ipv6FromBin(prefix + bin(partition_index+2)[2:].zfill(128 - netmask)), netmask = netmask)
def getPartitionIpv6Range(ipv6_range, partition_index):
"""
from a IPv6 range in the form
{
'addr' : addr,
'natmask' : CIDR
}
returns the IPv6 range
{
'addr' : addr:(partition_index+1)
'netmask : CIDR+16
}
"""
addr = ipv6_range['addr']
netmask = ipv6_range['netmask']
prefix = binFromIpv6(addr)[:netmask]
# we generate a subnetwork for the partition
# the subnetwork has 16 bits more than our IPv6 range
# make sure we have at least 2 IPs in the subnetwork
netmask += 16
if netmask >= 128:
raise ValueError('The IPv6 range has netmask {} which is too big for generating IPv6 range for partitions.'.format(netmask))
return dict(addr = ipv6FromBin(prefix + bin(partition_index+1)[2:].zfill(16) + '0' * (128 - netmask)), netmask=netmask)
def getTapIpv6Range(ipv6_range, partition_index):
"""
from a IPv6 range in the form
{
'addr' : addr,
'natmask' : CIDR
}
returns the IPv6 range
{
'addr' : addr:(2^15 + partition_index+1)
'netmask : CIDR+16
}
"""
addr = ipv6_range['addr']
netmask = ipv6_range['netmask']
prefix = binFromIpv6(addr)[:netmask]
# we generate a subnetwork for the partition
# the subnetwork has 16 bits more than our IPv6 range
# make sure we have at least 2 IPs in the subnetwork
netmask += 16
if netmask >= 128:
raise ValueError('The IPv6 range has netmask {} which is too big for generating IPv6 range for partitions.'.format(netmask))
return dict(addr = ipv6FromBin(prefix + bin(2^15 + partition_index+1)[2:].zfill(16) + '0' * (128 - netmask)), netmask=netmask)
  • I just noticed that 2^15 is a bitwise xor and not a power of 2. Either 2**15 or 1 << 15 should be used instead.

Please register or sign in to reply
def lenNetmaskIpv6(netmask):
"""Convert string represented netmask to its integer prefix"""
# Since version 0.10.7 of netifaces, the netmask is something like "ffff::/16",
......@@ -209,6 +272,10 @@ def lenNetmaskIpv6(netmask):
except ValueError:
return netaddr.IPNetwork(netmask).prefixlen
def netmaskFromLenIPv6(netmask_len):
""" opposite of lenNetmaskIpv6"""
return ipv6FromBin('1' * netmask_len)
# Used for Python 2-3 compatibility
if str is bytes:
bytes2str = str2bytes = lambda s: s
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment