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
Xavier Thompson
slapos.core
Commits
ff2fd95e
Commit
ff2fd95e
authored
Apr 01, 2022
by
Thomas Gambier
🚴🏼
Committed by
Xavier Thompson
Nov 17, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
slapos.core: introduce ipv6_range for each partition
parent
48d46cca
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
239 additions
and
84 deletions
+239
-84
slapos.cfg.example
slapos.cfg.example
+1
-0
slapos/format.py
slapos/format.py
+144
-77
slapos/slap/standalone.py
slapos/slap/standalone.py
+27
-7
slapos/util.py
slapos/util.py
+67
-0
No files found.
slapos.cfg.example
View file @
ff2fd95e
...
...
@@ -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]
...
...
slapos/format.py
View file @
ff2fd95e
...
...
@@ -58,7 +58,7 @@ import six
import
lxml.etree
import
xml_marshaller.xml_marshaller
from
slapos.util
import
dumps
,
mkdir_p
,
ipv6FromBin
,
binFromIpv6
,
lenNetmaskIpv6
from
slapos.util
import
dumps
,
mkdir_p
,
ipv6FromBin
,
binFromIpv6
,
lenNetmaskIpv6
,
getPartitionIpv6Addr
,
getPartitionIpv6Range
,
getTapIpv6Range
,
netmaskFromLenIPv6
import
slapos.slap
as
slap
from
slapos
import
version
from
slapos
import
manager
as
slapmanager
...
...
@@ -243,7 +243,7 @@ class Computer(object):
"""Object representing the computer"""
def
__init__
(
self
,
reference
,
interface
=
None
,
addr
=
None
,
netmask
=
None
,
ipv6_interface
=
None
,
software_user
=
'slapsoft'
,
ipv6_interface
=
None
,
partition_has_ipv6_range
=
None
,
software_user
=
'slapsoft'
,
tap_gateway_interface
=
None
,
tap_ipv6
=
None
,
instance_root
=
None
,
software_root
=
None
,
instance_storage_home
=
None
,
partition_list
=
None
,
config
=
None
):
...
...
@@ -260,6 +260,9 @@ class Computer(object):
self
.
address
=
addr
self
.
netmask
=
netmask
self
.
ipv6_interface
=
ipv6_interface
self
.
partition_has_ipv6_range
=
partition_has_ipv6_range
print
(
"DEBUG CONF1"
)
print
(
self
.
partition_has_ipv6_range
)
self
.
software_user
=
software_user
self
.
tap_gateway_interface
=
tap_gateway_interface
self
.
tap_ipv6
=
tap_ipv6
...
...
@@ -410,7 +413,7 @@ class Computer(object):
archive
.
writestr
(
saved_filename
,
xml_content
,
zipfile
.
ZIP_DEFLATED
)
@
classmethod
def
load
(
cls
,
path_to_xml
,
reference
,
ipv6_interface
,
tap_gateway_interface
,
def
load
(
cls
,
path_to_xml
,
reference
,
ipv6_interface
,
partition_has_ipv6_range
,
tap_gateway_interface
,
tap_ipv6
,
instance_root
=
None
,
software_root
=
None
,
config
=
None
):
"""
Create a computer object from a valid xml file.
...
...
@@ -431,6 +434,7 @@ class Computer(object):
addr
=
dumped_dict
[
'address'
],
netmask
=
dumped_dict
[
'netmask'
],
ipv6_interface
=
ipv6_interface
,
partition_has_ipv6_range
=
partition_has_ipv6_range
,
software_user
=
dumped_dict
.
get
(
'software_user'
,
'slapsoft'
),
tap_gateway_interface
=
tap_gateway_interface
,
tap_ipv6
=
tap_ipv6
,
...
...
@@ -467,6 +471,7 @@ class Computer(object):
tun
=
Tun
(
"slaptun"
+
str
(
partition_index
),
partition_index
,
partition_amount
)
address_list
=
partition_dict
[
'address_list'
]
ipv6_range
=
partition_dict
.
get
(
'ipv6_range'
,
{})
external_storage_list
=
partition_dict
.
get
(
'external_storage_list'
,
[])
partition
=
Partition
(
...
...
@@ -474,6 +479,7 @@ class Computer(object):
path
=
partition_dict
[
'path'
],
user
=
user
,
address_list
=
address_list
,
ipv6_range
=
ipv6_range
,
tap
=
tap
,
tun
=
tun
if
config
.
create_tun
else
None
,
external_storage_list
=
external_storage_list
,
...
...
@@ -562,7 +568,7 @@ class Computer(object):
####################
if
alter_network
:
if
self
.
address
is
not
None
:
self
.
interface
.
addIPv6
Address
(
self
.
address
,
self
.
netmask
)
self
.
interface
.
_addSystem
Address
(
self
.
address
,
self
.
netmask
)
if
create_tap
and
self
.
tap_gateway_interface
:
gateway_addr_dict
=
getIfaceAddressIPv4
(
self
.
tap_gateway_interface
)
...
...
@@ -571,6 +577,11 @@ class Computer(object):
len
(
self
.
partition_list
))
assert
(
len
(
self
.
partition_list
)
<=
len
(
tap_address_list
))
if
self
.
partition_has_ipv6_range
:
print
(
"WITH RANGE"
)
print
(
alter_network
)
self
.
interface
.
allowUseInexistingIpv6Address
()
self
.
_speedHackAddAllOldIpsToInterface
()
try
:
...
...
@@ -614,12 +625,13 @@ class Computer(object):
if
self
.
tap_ipv6
:
if
not
partition
.
tap
.
ipv6_addr
:
# create a new IPv6 randomly for the tap
ipv6_dict
=
self
.
interface
.
addIPv6Address
(
tap
=
partition
.
tap
)
ipv6_dict
=
self
.
interface
.
addIPv6Address
(
partition_index
,
tap
=
partition
.
tap
)
partition
.
tap
.
ipv6_addr
=
ipv6_dict
[
'addr'
]
partition
.
tap
.
ipv6_netmask
=
ipv6_dict
[
'netmask'
]
else
:
# make sure the tap has its IPv6
self
.
interface
.
addIPv6Address
(
partition_index
=
partition_index
,
addr
=
partition
.
tap
.
ipv6_addr
,
netmask
=
partition
.
tap
.
ipv6_netmask
,
tap
=
partition
.
tap
)
...
...
@@ -645,19 +657,15 @@ class Computer(object):
partition
.
tun
.
createWithOwner
(
owner
)
partition
.
tun
.
createRoutes
()
# Reconstructing partition's directory
partition
.
createPath
(
alter_user
)
partition
.
createExternalPath
(
alter_user
)
# Reconstructing partition's address
# There should be two addresses on each Computer Partition:
# * local IPv4, took from slapformat:ipv4_local_network
# * global IPv6
if
not
partition
.
address_list
:
# regenerate
# generate new addresses
partition
.
address_list
.
append
(
self
.
interface
.
addIPv4LocalAddress
())
partition
.
address_list
.
append
(
self
.
interface
.
addIPv6Address
(
))
elif
alter_network
:
partition
.
address_list
.
append
(
self
.
interface
.
addIPv6Address
(
partition_index
))
else
:
# regenerate list of addresses
old_partition_address_list
=
partition
.
address_list
partition
.
address_list
=
[]
...
...
@@ -667,21 +675,40 @@ class Computer(object):
(
old_partition_address_list
,))
if
not
any
(
netaddr
.
valid_ipv6
(
q
[
'addr'
])
for
q
in
old_partition_address_list
):
raise
ValueError
(
'Not valid ipv6 addresses loaded
'
)
raise
ValueError
(
'No valid IPv6 address loaded from XML config
'
)
if
not
any
(
netaddr
.
valid_ipv4
(
q
[
'addr'
])
for
q
in
old_partition_address_list
):
raise
ValueError
(
'Not valid ipv6 addresses loaded
'
)
raise
ValueError
(
'No valid IPv4 address loaded from XML config
'
)
for
address
in
old_partition_address_list
:
if
netaddr
.
valid_ipv6
(
address
[
'addr'
]):
partition
.
address_list
.
append
(
self
.
interface
.
addIPv6Address
(
partition_index
,
address
[
'addr'
],
address
[
'netmask'
]))
elif
netaddr
.
valid_ipv4
(
address
[
'addr'
]):
partition
.
address_list
.
append
(
self
.
interface
.
addIPv4LocalAddress
(
address
[
'addr'
]))
else
:
# should never happen since there are exactly 1 valid IPv6 and 1
# valid IPv4 in old_partition_address_list
raise
ValueError
(
'Address %r is incorrect'
%
address
[
'addr'
])
# Reconstructing partiton's IPv6 range
if
self
.
partition_has_ipv6_range
:
if
not
partition
.
ipv6_range
:
# generate new IPv6 range
partition
.
ipv6_range
=
self
.
interface
.
generateIPv6Range
(
partition_index
)
else
:
if
not
netaddr
.
valid_ipv6
(
partition
.
ipv6_range
[
'addr'
]):
raise
ValueError
(
'existing IPv6 range %r is incorrect'
,
partition
.
ipv6_range
[
'addr'
])
else
:
partition
.
ipv6_range
=
{}
# Reconstructing partition's directory
partition
.
createPath
(
alter_user
)
partition
.
createExternalPath
(
alter_user
)
finally
:
for
manager
in
self
.
_manager_list
:
manager
.
formatTearDown
(
self
)
...
...
@@ -693,13 +720,14 @@ class Partition(object):
resource_file
=
".slapos-resource"
def
__init__
(
self
,
reference
,
path
,
user
,
address_list
,
tap
,
external_storage_list
=
[],
tun
=
None
):
ipv6_range
,
tap
,
external_storage_list
=
[],
tun
=
None
):
"""
Attributes:
reference: String, the name of the partition.
path: String, the path to the partition folder.
user: User, the user linked to this partition.
address_list: List of associated IP addresses.
ipv6_range: IPv6 range given to this partiton (dict with 'addr' and 'netmask').
tap: Tap, the tap interface linked to this partition e.g. used as a gateway for kvm
tun: Tun interface used for special apps simulating ethernet connections
external_storage_list: Base path list of folder to format for data storage
...
...
@@ -709,12 +737,13 @@ class Partition(object):
self
.
path
=
str
(
path
)
self
.
user
=
user
self
.
address_list
=
address_list
or
[]
self
.
ipv6_range
=
ipv6_range
or
{}
self
.
tap
=
tap
self
.
tun
=
tun
self
.
external_storage_list
=
[]
def
__getinitargs__
(
self
):
return
(
self
.
reference
,
self
.
path
,
self
.
user
,
self
.
address_list
,
self
.
tap
,
self
.
tun
)
return
(
self
.
reference
,
self
.
path
,
self
.
user
,
self
.
address_list
,
self
.
ipv6_range
,
self
.
tap
,
self
.
tun
)
def
createPath
(
self
,
alter_user
=
True
):
"""
...
...
@@ -1072,13 +1101,10 @@ class Interface(object):
for
q
in
netifaces
.
ifaddresses
(
interface_name
)[
af
]
]:
# add an address
callAndRead
([
'ip'
,
'addr'
,
'add'
,
address_string
,
'dev'
,
interface_name
])
# Fake success for local ipv4
if
not
ipv6
:
return
True
code
,
_
=
callAndRead
([
'ip'
,
'addr'
,
'add'
,
address_string
,
'dev'
,
interface_name
])
# wait few moments
if
code
!=
0
:
return
False
time
.
sleep
(
2
)
# Fake success for local ipv4
...
...
@@ -1132,7 +1158,7 @@ class Interface(object):
# confirmed to be configured
return
dict
(
addr
=
addr
,
netmask
=
netmask
)
def
addIPv6Address
(
self
,
addr
=
None
,
netmask
=
None
,
tap
=
None
):
def
addIPv6Address
(
self
,
partition_index
,
addr
=
None
,
netmask
=
None
,
tap
=
None
):
"""
Adds IPv6 address to interface.
...
...
@@ -1142,6 +1168,9 @@ class Interface(object):
address. If it is not possible (ex. because network changed), calculate new
address.
If tap is specified, tap will get actually an IPv6 range (and not a single
address) 16 bits smaller than the range of the interface.
Args:
addr: Wished address to be added to interface.
netmask: Wished netmask to be used.
...
...
@@ -1197,38 +1226,65 @@ class Interface(object):
self
.
_logger
.
warning
(
'Impossible to add old public IPv6 %s. '
'Generating new IPv6 address.'
%
addr
)
# Try 10 times to add address, raise in case if not possible
try_num
=
10
netmask
=
address_dict
[
'netmask'
]
address_dict
[
'netmask'
]
=
lenNetmaskIpv6
(
address_dict
[
'netmask'
])
if
tap
:
netmask_len
=
lenNetmaskIpv6
(
netmask
)
prefix
=
binFromIpv6
(
address_dict
[
'addr'
])[:
netmask_len
]
netmask_len
+=
16
# we generate a subnetwork for the tap
# the subnetwork has 16 bits more than the interface network
# make sure we have at least 2 IPs in the subnetwork
if
netmask_len
>=
128
:
self
.
_logger
.
error
(
'Interface %s has netmask %s which is too big for generating IPv6 on taps.'
%
(
interface_name
,
netmask
))
raise
AddressGenerationError
(
addr
)
netmask
=
ipv6FromBin
(
'1'
*
128
)
# the netmask of the tap itself is always 128 bits
while
try_num
>
0
:
if
tap
:
addr
=
ipv6FromBin
(
prefix
+
bin
(
random
.
randint
(
1
,
65000
))[
2
:].
zfill
(
16
)
+
'1'
*
(
128
-
netmask_len
))
result_addr
=
getTapIpv6Range
(
address_dict
,
partition_index
)
else
:
addr
=
':'
.
join
(
address_dict
[
'addr'
].
split
(
':'
)[:
-
1
]
+
[
'%x'
%
(
random
.
randint
(
1
,
65000
),
)])
socket
.
inet_pton
(
socket
.
AF_INET6
,
addr
)
if
(
dict
(
addr
=
addr
,
netmask
=
netmask
)
not
in
self
.
getGlobalScopeAddressList
(
tap
=
tap
)):
# Checking the validity of the IPv6 address
if
self
.
_addSystemAddress
(
addr
,
netmask
,
tap
=
tap
):
return
dict
(
addr
=
addr
,
netmask
=
netmask
)
try_num
-=
1
result_addr
=
getPartitionIpv6Addr
(
address_dict
,
partition_index
)
# restore netmask as bitmask
result_addr
[
'netmask'
]
=
netmaskFromLenIPv6
(
result_addr
[
'netmask'
])
raise
AddressGenerationError
(
addr
)
self
.
_addSystemAddress
(
result_addr
[
'addr'
],
result_addr
[
'netmask'
],
tap
=
tap
)
return
result_addr
def
generateIPv6Range
(
self
,
i
):
"""
Generate an IPv6 range included in the IPv6 range of the interface. The IPv6 range depends on the partition index i.
There is no need to actually add this range anywhere because allowUseInexistingIpv6Address() has already been called.
Returns:
dict(addr=address, netmask=netmask, network=addr/CIDR).
Raises:
ValueError: Couldn't construct valid address with existing
one's on the interface.
NoAddressOnInterface: There's no address on the interface to construct
an address with.
"""
interface_name
=
self
.
ipv6_interface
or
self
.
name
# Getting one address of the interface as base of the next addresses
interface_addr_list
=
self
.
getGlobalScopeAddressList
()
# No address found
if
len
(
interface_addr_list
)
==
0
:
raise
NoAddressOnInterface
(
interface_name
)
address_dict
=
interface_addr_list
[
0
]
address_dict
[
'netmask'
]
=
lenNetmaskIpv6
(
address_dict
[
'netmask'
])
ipv6_range
=
getPartitionIpv6Range
(
address_dict
,
i
)
ipv6_range
[
'network'
]
=
'{addr}/{netmask}'
.
format
(
**
ipv6_range
)
ipv6_range
[
'netmask'
]
=
netmaskFromLenIPv6
(
ipv6_range
[
'netmask'
])
return
ipv6_range
def
allowUseInexistingIpv6Address
(
self
):
# This will allow the usage of unexisting IPv6 adrdresses.
# Getting the global IPv6 range of the computer
interface_addr_list
=
self
.
getGlobalScopeAddressList
()
# No address found
if
len
(
interface_addr_list
)
==
0
:
raise
NoAddressOnInterface
(
interface_name
)
address_dict
=
interface_addr_list
[
0
]
addr
=
address_dict
[
'addr'
]
netmask
=
address_dict
[
'netmask'
].
split
(
'/'
)[
1
]
self
.
_logger
.
debug
(
'sysctl net.ipv6.ip_nonlocal_bind=1'
)
callAndRead
([
'sysctl'
,
'net.ipv6.ip_nonlocal_bind=1'
])
_
,
result
=
callAndRead
([
'ip'
,
'-6'
,
'route'
,
'show'
,
'table'
,
'local'
,
'%s/%s'
%
(
addr
,
netmask
)])
if
not
'dev lo'
in
result
:
self
.
_logger
.
debug
(
' ip -6 route add local %s/%s dev lo'
,
addr
,
netmask
)
callAndRead
([
'ip'
,
'-6'
,
'route'
,
'add'
,
'local'
,
'%s/%s'
%
(
addr
,
netmask
),
'dev'
,
'lo'
])
def
parse_computer_definition
(
conf
,
definition_path
):
...
...
@@ -1254,6 +1310,7 @@ def parse_computer_definition(conf, definition_path):
addr
=
address
,
netmask
=
netmask
,
ipv6_interface
=
conf
.
ipv6_interface
,
partition_has_ipv6_range
=
conf
.
partition_has_ipv6_range
,
software_user
=
computer_definition
.
get
(
'computer'
,
'software_user'
),
tap_gateway_interface
=
conf
.
tap_gateway_interface
,
tap_ipv6
=
conf
.
tap_ipv6
,
...
...
@@ -1268,6 +1325,10 @@ def parse_computer_definition(conf, definition_path):
for
a
in
computer_definition
.
get
(
section
,
'address'
).
split
():
address
,
netmask
=
a
.
split
(
'/'
)
address_list
.
append
(
dict
(
addr
=
address
,
netmask
=
netmask
))
ipv6_range_network
=
computer_definition
.
get
(
section
,
'ipv6_range'
)
addr
,
netmask
=
ipv6_range_network
.
split
(
'/'
)
netmask
=
netmaskFromLenIPv6
(
int
(
netmask
))
ipv6_range
=
{
'addr'
:
address
,
'netmask'
:
netmask
,
'network'
:
ipv6_range_network
}
tap
=
Tap
(
computer_definition
.
get
(
section
,
'network_interface'
))
tun
=
Tun
(
"slaptun"
+
str
(
partition_number
),
partition_number
,
...
...
@@ -1277,6 +1338,7 @@ def parse_computer_definition(conf, definition_path):
computer_definition
.
get
(
section
,
'pathname'
)),
user
=
user
,
address_list
=
address_list
,
ipv6_range
=
ipv6_range
,
tap
=
tap
,
tun
=
tun
)
partition_list
.
append
(
partition
)
computer
.
partition_list
=
partition_list
...
...
@@ -1294,6 +1356,7 @@ def parse_computer_xml(conf, xml_path):
computer
=
Computer
.
load
(
xml_path
,
reference
=
conf
.
computer_id
,
ipv6_interface
=
conf
.
ipv6_interface
,
partition_has_ipv6_range
=
conf
.
partition_has_ipv6_range
,
tap_gateway_interface
=
conf
.
tap_gateway_interface
,
tap_ipv6
=
conf
.
tap_ipv6
,
software_root
=
conf
.
software_root
,
...
...
@@ -1312,6 +1375,7 @@ def parse_computer_xml(conf, xml_path):
addr
=
None
,
netmask
=
None
,
ipv6_interface
=
conf
.
ipv6_interface
,
partition_has_ipv6_range
=
conf
.
partition_has_ipv6_range
,
software_user
=
conf
.
software_user
,
tap_gateway_interface
=
conf
.
tap_gateway_interface
,
tap_ipv6
=
conf
.
tap_ipv6
,
...
...
@@ -1338,6 +1402,7 @@ def parse_computer_xml(conf, xml_path):
conf
.
partition_base_name
,
i
)),
user
=
User
(
'%s%s'
%
(
conf
.
user_base_name
,
i
)),
address_list
=
None
,
ipv6_range
=
None
,
tap
=
Tap
(
'%s%s'
%
(
conf
.
tap_base_name
,
i
)),
tun
=
Tun
(
'slaptun'
+
str
(
i
),
i
,
partition_amount
)
if
conf
.
create_tun
else
None
)
...
...
@@ -1359,6 +1424,7 @@ def write_computer_definition(conf, computer):
for
address
in
partition
.
address_list
:
address_list
.
append
(
'/'
.
join
([
address
[
'addr'
],
address
[
'netmask'
]]))
computer_definition
.
set
(
section
,
'address'
,
' '
.
join
(
address_list
))
computer_definition
.
set
(
section
,
'ipv6_range'
,
partition
.
ipv6_range
[
'network'
])
computer_definition
.
set
(
section
,
'user'
,
partition
.
user
.
name
)
computer_definition
.
set
(
section
,
'network_interface'
,
partition
.
tap
.
name
)
computer_definition
.
set
(
section
,
'pathname'
,
partition
.
reference
)
...
...
@@ -1424,6 +1490,7 @@ class FormatConfig(object):
alter_network
=
'True'
# modifiable by cmdline
interface_name
=
None
ipv6_interface
=
None
partition_has_ipv6_range
=
True
create_tap
=
True
create_tun
=
False
tap_base_name
=
None
...
...
@@ -1488,7 +1555,7 @@ class FormatConfig(object):
raise
UsageError
(
message
)
# Convert strings to booleans
for
option
in
[
'alter_network'
,
'alter_user'
,
'create_tap'
,
'create_tun'
,
'tap_ipv6'
]:
for
option
in
[
'alter_network'
,
'alter_user'
,
'
partition_has_ipv6_range'
,
'
create_tap'
,
'create_tun'
,
'tap_ipv6'
]:
attr
=
getattr
(
self
,
option
)
if
isinstance
(
attr
,
str
):
if
attr
.
lower
()
==
'true'
:
...
...
slapos/slap/standalone.py
View file @
ff2fd95e
...
...
@@ -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
)
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'
:
{
...
...
slapos/util.py
View file @
ff2fd95e
...
...
@@ -205,6 +205,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
)
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",
...
...
@@ -215,6 +278,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
...
...
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