Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
slapos.core
Commits
0e5a2482
Commit
0e5a2482
authored
Mar 15, 2023
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
slapformat: Allow customising IPv6 range sizes
parent
46e6b43e
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
53 additions
and
11 deletions
+53
-11
slapos/format.py
slapos/format.py
+41
-6
slapos/util.py
slapos/util.py
+12
-5
No files found.
slapos/format.py
View file @
0e5a2482
...
...
@@ -1024,7 +1024,7 @@ class Tun(Tap):
class
Interface
(
object
):
"""Represent a network interface on the system"""
def
__init__
(
self
,
logger
,
name
,
ipv4_local_network
,
ipv6_interface
=
None
):
def
__init__
(
self
,
logger
,
name
,
ipv4_local_network
,
ipv6_interface
=
None
,
ipv6_prefixshift
=
16
):
"""
Attributes:
name: String, the name of the interface
...
...
@@ -1036,6 +1036,8 @@ class Interface(object):
self
.
ipv6_interface
=
ipv6_interface
or
name
self
.
_ipv6_ranges
=
set
()
self
.
ipv6_prefixshift
=
ipv6_prefixshift
# XXX no __getinitargs__, as instances of this class are never deserialized.
def
getIPv4LocalAddressList
(
self
):
...
...
@@ -1292,7 +1294,7 @@ class Interface(object):
# Try to use the IPv6 mapping based on partition index
address_dict
[
'prefixlen'
]
=
lenNetmaskIpv6
(
address_dict
[
'netmask'
])
if
tap
:
result_addr
=
getTapIpv6Range
(
address_dict
,
partition_index
)
result_addr
=
getTapIpv6Range
(
address_dict
,
partition_index
,
self
.
ipv6_prefixshift
)
# the netmask of the tap itself is always 128 bits
result_addr
[
'netmask'
]
=
netmaskFromLenIPv6
(
128
)
else
:
...
...
@@ -1304,6 +1306,17 @@ class Interface(object):
self
.
_reserveIpv6Range
(
result_addr
[
'addr'
],
result_addr
[
'prefixlen'
])
return
result_addr
if
self
.
_ipv6_prefixshift
!=
16
:
self
.
_logger
.
error
(
"Address %s/%s for partition %s is already taken;"
" aborting because IPv6 prefixshift is %s != 16"
%
(
result_addr
[
'addr'
],
result_addr
[
'prefixlen'
],
'%s tap'
%
partition_index
if
tap
else
partition_index
,
self
.
_ipv6_prefixshift
,
))
raise
AddressGenerationError
(
addr
)
self
.
_logger
.
warning
(
"Falling back to random address selection for partition %s"
" because %s/%s is already taken"
%
(
...
...
@@ -1350,14 +1363,24 @@ class Interface(object):
address_dict
=
interface_addr_list
[
0
]
address_dict
[
'prefixlen'
]
=
lenNetmaskIpv6
(
address_dict
[
'netmask'
])
if
tun
:
ipv6_range
=
getTunIpv6Range
(
address_dict
,
i
)
ipv6_range
=
getTunIpv6Range
(
address_dict
,
i
,
self
.
ipv6_prefixshift
)
else
:
ipv6_range
=
getPartitionIpv6Range
(
address_dict
,
i
)
ipv6_range
=
getPartitionIpv6Range
(
address_dict
,
i
,
self
.
ipv6_prefixshift
)
ipv6_range
[
'netmask'
]
=
netmaskFromLenIPv6
(
ipv6_range
[
'prefixlen'
])
ipv6_range
[
'network'
]
=
'%(addr)s/%(prefixlen)d'
%
ipv6_range
if
self
.
_tryReserveIpv6Range
(
ipv6_range
[
'addr'
],
ipv6_range
[
'prefixlen'
]):
return
ipv6_range
if
self
.
_ipv6_prefixshift
!=
16
:
self
.
_logger
.
error
(
"Address % for partition %s is already taken;"
" aborting because IPv6 prefixshift is %s != 16"
%
(
ipv6_range
[
'network'
],
'%s tun'
%
i
if
tun
else
i
,
self
.
_ipv6_prefixshift
,
))
raise
AddressGenerationError
(
ipv6_range
[
'addr'
])
self
.
_logger
.
warning
(
"Falling back to random IPv6 range selection for partition %s"
" because %s is already taken"
%
(
...
...
@@ -1406,7 +1429,8 @@ def parse_computer_definition(conf, definition_path):
interface
=
Interface
(
logger
=
conf
.
logger
,
name
=
conf
.
interface_name
,
ipv4_local_network
=
conf
.
ipv4_local_network
,
ipv6_interface
=
conf
.
ipv6_interface
)
ipv6_interface
=
conf
.
ipv6_interface
,
ipv6_prefixshift
=
conf
.
ipv6_prefixshift
)
computer
=
Computer
(
reference
=
conf
.
computer_id
,
interface
=
interface
,
...
...
@@ -1455,7 +1479,8 @@ def parse_computer_xml(conf, xml_path):
interface
=
Interface
(
logger
=
conf
.
logger
,
name
=
conf
.
interface_name
,
ipv4_local_network
=
conf
.
ipv4_local_network
,
ipv6_interface
=
conf
.
ipv6_interface
)
ipv6_interface
=
conf
.
ipv6_interface
,
ipv6_prefixshift
=
conf
.
ipv6_prefixshift
)
if
os
.
path
.
exists
(
xml_path
):
conf
.
logger
.
debug
(
'Loading previous computer data from %r'
%
xml_path
)
...
...
@@ -1597,6 +1622,7 @@ class FormatConfig(object):
interface_name
=
None
ipv6_interface
=
None
partition_has_ipv6_range
=
True
ipv6_prefixshift
=
16
create_tap
=
True
tap_base_name
=
None
tap_ipv6
=
True
...
...
@@ -1697,6 +1723,15 @@ class FormatConfig(object):
file_location
)
sys
.
exit
(
1
)
# Sanity check for prefixshift
self
.
ipv6_prefixshift
=
ipv6_prefixshift
=
int
(
self
.
ipv6_prefixshift
)
if
(
1
<<
ipv6_prefixshift
)
<
4
*
int
(
self
.
partition_amount
):
# Each partition needs at least 4 IPv6, for IPv6 address, range, tap and tun
self
.
logger
.
fatal
(
'ipv6_prefixshift %s is too small for partition_amount %s'
,
ipv6_prefixshift
,
self
.
partition_amount
)
sys
.
exit
(
1
)
self
.
logger
.
debug
(
'Started.'
)
if
self
.
dry_run
:
self
.
logger
.
info
(
"Dry-run mode enabled."
)
...
...
slapos/util.py
View file @
0e5a2482
...
...
@@ -221,7 +221,11 @@ def getPartitionIpv6Addr(ipv6_range, partition_index):
return
dict
(
addr
=
ipv6FromBin
(
prefix
+
bin
(
partition_index
+
2
)[
2
:].
zfill
(
128
-
prefixlen
)),
prefixlen
=
prefixlen
)
def
getIpv6RangeFactory
(
k
,
s
):
def
getIpv6Range
(
ipv6_range
,
partition_index
):
"""
k in (1, 2, 3)
s in ('0', '1')
"""
def
getIpv6Range
(
ipv6_range
,
partition_index
,
prefixshift
):
"""
from a IPv6 range in the form
{
...
...
@@ -230,20 +234,23 @@ def getIpv6RangeFactory(k, s):
}
returns the IPv6 range
{
'addr' : addr:(k*(2^
14
) + partition_index+1)
'prefixlen' : CIDR+
16
'addr' : addr:(k*(2^
(prefixshift-2)
) + partition_index+1)
'prefixlen' : CIDR+
prefixshift
}
"""
addr
=
ipv6_range
[
'addr'
]
prefixlen
=
ipv6_range
[
'prefixlen'
]
prefix
=
binFromIpv6
(
addr
)[:
prefixlen
]
n
=
prefixshift
# 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
prefixlen
+=
16
prefixlen
+=
n
if
prefixlen
>=
128
:
raise
ValueError
(
'The IPv6 range has prefixlen {} which is too big for generating IPv6 range for partitions.'
.
format
(
prefixlen
))
return
dict
(
addr
=
ipv6FromBin
(
prefix
+
bin
((
k
<<
14
)
+
partition_index
+
1
)[
2
:].
zfill
(
16
)
+
s
*
(
128
-
prefixlen
)),
prefixlen
=
prefixlen
)
return
dict
(
addr
=
ipv6FromBin
(
prefix
+
bin
((
k
<<
(
n
-
2
))
+
partition_index
+
1
)[
2
:].
zfill
(
n
)
+
s
*
(
128
-
prefixlen
)),
prefixlen
=
prefixlen
)
return
getIpv6Range
getPartitionIpv6Range
=
getIpv6RangeFactory
(
1
,
'0'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment