slapformat: Introduce IPv6 range for each partition
... | @@ -58,7 +58,7 @@ import six | ... | @@ -58,7 +58,7 @@ import six |
import lxml.etree | import lxml.etree | ||
import xml_marshaller.xml_marshaller | 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 | import slapos.slap as slap | ||
from slapos import version | from slapos import version | ||
from slapos import manager as slapmanager | from slapos import manager as slapmanager | ||
... | @@ -243,7 +243,7 @@ class Computer(object): | ... | @@ -243,7 +243,7 @@ class Computer(object): |
"""Object representing the computer""" | """Object representing the computer""" | ||
def __init__(self, reference, interface=None, addr=None, netmask=None, | 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, | tap_gateway_interface=None, tap_ipv6=None, | ||
instance_root=None, software_root=None, instance_storage_home=None, | instance_root=None, software_root=None, instance_storage_home=None, | ||
partition_list=None, config=None): | partition_list=None, config=None): | ||
... | @@ -260,6 +260,7 @@ class Computer(object): | ... | @@ -260,6 +260,7 @@ class Computer(object): |
self.address = addr | self.address = addr | ||
self.netmask = netmask | self.netmask = netmask | ||
self.ipv6_interface = ipv6_interface | self.ipv6_interface = ipv6_interface | ||
self.partition_has_ipv6_range = partition_has_ipv6_range | |||
self.software_user = software_user | self.software_user = software_user | ||
self.tap_gateway_interface = tap_gateway_interface | self.tap_gateway_interface = tap_gateway_interface | ||
self.tap_ipv6 = tap_ipv6 | self.tap_ipv6 = tap_ipv6 | ||
... | @@ -410,7 +411,7 @@ class Computer(object): | ... | @@ -410,7 +411,7 @@ class Computer(object): |
archive.writestr(saved_filename, xml_content, zipfile.ZIP_DEFLATED) | archive.writestr(saved_filename, xml_content, zipfile.ZIP_DEFLATED) | ||
@classmethod | @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): | tap_ipv6, instance_root=None, software_root=None, config=None): | ||
""" | """ | ||
Create a computer object from a valid xml file. | Create a computer object from a valid xml file. | ||
... | @@ -431,6 +432,7 @@ class Computer(object): | ... | @@ -431,6 +432,7 @@ class Computer(object): |
addr=dumped_dict['address'], | addr=dumped_dict['address'], | ||
netmask=dumped_dict['netmask'], | netmask=dumped_dict['netmask'], | ||
ipv6_interface=ipv6_interface, | ipv6_interface=ipv6_interface, | ||
partition_has_ipv6_range=partition_has_ipv6_range, | |||
software_user=dumped_dict.get('software_user', 'slapsoft'), | software_user=dumped_dict.get('software_user', 'slapsoft'), | ||
tap_gateway_interface=tap_gateway_interface, | tap_gateway_interface=tap_gateway_interface, | ||
tap_ipv6=tap_ipv6, | tap_ipv6=tap_ipv6, | ||
... | @@ -467,6 +469,7 @@ class Computer(object): | ... | @@ -467,6 +469,7 @@ class Computer(object): |
tun = Tun("slaptun" + str(partition_index), partition_index, partition_amount) | tun = Tun("slaptun" + str(partition_index), partition_index, partition_amount) | ||
address_list = partition_dict['address_list'] | address_list = partition_dict['address_list'] | ||
ipv6_range = partition_dict.get('ipv6_range', {}) | |||
external_storage_list = partition_dict.get('external_storage_list', []) | external_storage_list = partition_dict.get('external_storage_list', []) | ||
partition = Partition( | partition = Partition( | ||
... | @@ -474,6 +477,7 @@ class Computer(object): | ... | @@ -474,6 +477,7 @@ class Computer(object): |
path=partition_dict['path'], | path=partition_dict['path'], | ||
user=user, | user=user, | ||
address_list=address_list, | address_list=address_list, | ||
ipv6_range=ipv6_range, | |||
tap=tap, | tap=tap, | ||
tun=tun if config.create_tun else None, | tun=tun if config.create_tun else None, | ||
external_storage_list=external_storage_list, | external_storage_list=external_storage_list, | ||
... | @@ -562,7 +566,7 @@ class Computer(object): | ... | @@ -562,7 +566,7 @@ class Computer(object): |
#################### | #################### | ||
if alter_network: | if alter_network: | ||
if self.address is not None: | if self.address is not None: | ||
self.interface.addIPv6Address(self.address, self.netmask) | self.interface._addSystemAddress(self.address, self.netmask) | ||
|
|||
if create_tap and self.tap_gateway_interface: | if create_tap and self.tap_gateway_interface: | ||
gateway_addr_dict = getIfaceAddressIPv4(self.tap_gateway_interface) | gateway_addr_dict = getIfaceAddressIPv4(self.tap_gateway_interface) | ||
... | @@ -571,6 +575,9 @@ class Computer(object): | ... | @@ -571,6 +575,9 @@ class Computer(object): |
len(self.partition_list)) | len(self.partition_list)) | ||
assert(len(self.partition_list) <= len(tap_address_list)) | assert(len(self.partition_list) <= len(tap_address_list)) | ||
if self.partition_has_ipv6_range: | |||
self.interface.allowUseInexistingIpv6Address() | |||
self._speedHackAddAllOldIpsToInterface() | self._speedHackAddAllOldIpsToInterface() | ||
try: | try: | ||
... | @@ -614,12 +621,13 @@ class Computer(object): | ... | @@ -614,12 +621,13 @@ class Computer(object): |
if self.tap_ipv6: | if self.tap_ipv6: | ||
if not partition.tap.ipv6_addr: | if not partition.tap.ipv6_addr: | ||
# create a new IPv6 randomly for the tap | # 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_addr = ipv6_dict['addr'] | ||
partition.tap.ipv6_netmask = ipv6_dict['netmask'] | partition.tap.ipv6_netmask = ipv6_dict['netmask'] | ||
else: | else: | ||
# make sure the tap has its IPv6 | # make sure the tap has its IPv6 | ||
self.interface.addIPv6Address( | self.interface.addIPv6Address( | ||
partition_index=partition_index, | |||
addr=partition.tap.ipv6_addr, | addr=partition.tap.ipv6_addr, | ||
netmask=partition.tap.ipv6_netmask, | netmask=partition.tap.ipv6_netmask, | ||
tap=partition.tap) | tap=partition.tap) | ||
... | @@ -645,19 +653,19 @@ class Computer(object): | ... | @@ -645,19 +653,19 @@ class Computer(object): |
partition.tun.createWithOwner(owner) | partition.tun.createWithOwner(owner) | ||
partition.tun.createRoutes() | partition.tun.createRoutes() | ||
# Reconstructing partition's directory | |||
partition.createPath(alter_user) | |||
partition.createExternalPath(alter_user) | |||
# Reconstructing partition's address | # Reconstructing partition's address | ||
# There should be two addresses on each Computer Partition: | # There should be two addresses on each Computer Partition: | ||
# * local IPv4, took from slapformat:ipv4_local_network | # * local IPv4, took from slapformat:ipv4_local_network | ||
# * global IPv6 | # * global IPv6 | ||
if not partition.address_list: | if not partition.address_list: | ||
# regenerate | # generate new addresses | ||
partition.address_list.append(self.interface.addIPv4LocalAddress()) | partition.address_list.append(self.interface.addIPv4LocalAddress()) | ||
partition.address_list.append(self.interface.addIPv6Address()) | partition_ipv6_dict = self.interface.addIPv6Address(partition_index) | ||
elif alter_network: | # Avoid leaking prefixlen in dumped data because it is not loaded | ||
# otherwise format dumps a different result after the first run | |||
del partition_ipv6_dict['prefixlen'] | |||
partition.address_list.append(partition_ipv6_dict) | |||
else: | |||
# regenerate list of addresses | # regenerate list of addresses | ||
old_partition_address_list = partition.address_list | old_partition_address_list = partition.address_list | ||
partition.address_list = [] | partition.address_list = [] | ||
... | @@ -667,21 +675,40 @@ class Computer(object): | ... | @@ -667,21 +675,40 @@ class Computer(object): |
(old_partition_address_list,)) | (old_partition_address_list,)) | ||
if not any(netaddr.valid_ipv6(q['addr']) | if not any(netaddr.valid_ipv6(q['addr']) | ||
for q in old_partition_address_list): | 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']) | if not any(netaddr.valid_ipv4(q['addr']) | ||
for q in old_partition_address_list): | 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: | for address in old_partition_address_list: | ||
if netaddr.valid_ipv6(address['addr']): | if netaddr.valid_ipv6(address['addr']): | ||
partition.address_list.append(self.interface.addIPv6Address( | partition.address_list.append(self.interface.addIPv6Address( | ||
partition_index, | |||
address['addr'], | address['addr'], | ||
address['netmask'])) | address['netmask'])) | ||
elif netaddr.valid_ipv4(address['addr']): | elif netaddr.valid_ipv4(address['addr']): | ||
partition.address_list.append(self.interface.addIPv4LocalAddress( | partition.address_list.append(self.interface.addIPv4LocalAddress( | ||
address['addr'])) | address['addr'])) | ||
else: | 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']) | raise ValueError('Address %r is incorrect' % address['addr']) | ||
# Reconstructing partition'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: | finally: | ||
for manager in self._manager_list: | for manager in self._manager_list: | ||
manager.formatTearDown(self) | manager.formatTearDown(self) | ||
... | @@ -693,13 +720,14 @@ class Partition(object): | ... | @@ -693,13 +720,14 @@ class Partition(object): |
resource_file = ".slapos-resource" | resource_file = ".slapos-resource" | ||
def __init__(self, reference, path, user, address_list, | def __init__(self, reference, path, user, address_list, | ||
tap, external_storage_list=[], tun=None): | ipv6_range, tap, tun=None, external_storage_list=[]): | ||
""" | """ | ||
Attributes: | Attributes: | ||
reference: String, the name of the partition. | reference: String, the name of the partition. | ||
path: String, the path to the partition folder. | path: String, the path to the partition folder. | ||
user: User, the user linked to this partition. | user: User, the user linked to this partition. | ||
address_list: List of associated IP addresses. | address_list: List of associated IP addresses. | ||
ipv6_range: IPv6 range given to this partition (dict with 'addr' and 'netmask'). | |||
tap: Tap, the tap interface linked to this partition e.g. used as a gateway for kvm | 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 | tun: Tun interface used for special apps simulating ethernet connections | ||
external_storage_list: Base path list of folder to format for data storage | external_storage_list: Base path list of folder to format for data storage | ||
... | @@ -709,12 +737,13 @@ class Partition(object): | ... | @@ -709,12 +737,13 @@ class Partition(object): |
self.path = str(path) | self.path = str(path) | ||
self.user = user | self.user = user | ||
self.address_list = address_list or [] | self.address_list = address_list or [] | ||
self.ipv6_range = ipv6_range or {} | |||
self.tap = tap | self.tap = tap | ||
self.tun = tun | self.tun = tun | ||
self.external_storage_list = [] | self.external_storage_list = [] | ||
def __getinitargs__(self): | 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): | def createPath(self, alter_user=True): | ||
""" | """ | ||
... | @@ -1066,13 +1095,10 @@ class Interface(object): | ... | @@ -1066,13 +1095,10 @@ class Interface(object): |
for q in netifaces.ifaddresses(interface_name)[af] | for q in netifaces.ifaddresses(interface_name)[af] | ||
]: | ]: | ||
# add an address | # add an address | ||
callAndRead(['ip', 'addr', 'add', address_string, 'dev', interface_name]) | code, _ = callAndRead(['ip', 'addr', 'add', address_string, 'dev', interface_name]) | ||
# Fake success for local ipv4 | |||
if not ipv6: | |||
return True | |||
# wait few moments | if code != 0: | ||
return False | |||
time.sleep(2) | time.sleep(2) | ||
# Fake success for local ipv4 | # Fake success for local ipv4 | ||
... | @@ -1126,7 +1152,28 @@ class Interface(object): | ... | @@ -1126,7 +1152,28 @@ class Interface(object): |
# confirmed to be configured | # confirmed to be configured | ||
return dict(addr=addr, netmask=netmask) | return dict(addr=addr, netmask=netmask) | ||
def addIPv6Address(self, addr=None, netmask=None, tap=None): | def _generateRandomIPv6Addr(self, address_dict): | ||
netmask = address_dict['netmask'] | |||
netmask_len = lenNetmaskIpv6(netmask) | |||
r = random.randint(1, 65000) | |||
addr = ':'.join(address_dict['addr'].split(':')[:-1] + ['%x' % r]) | |||
socket.inet_pton(socket.AF_INET6, address) | |||
return dict(addr=addr, netmask=netmask) | |||
def _generateRandomIPv6Range(self, address_dict, suffix): | |||
prefixlen = lenNetmaskIpv6(address_dict['netmask']) | |||
prefix = binFromIpv6(address_dict['addr'])[:prefixlen] | |||
prefixlen += 16 | |||
if prefixlen >= 128: | |||
msg = 'Address range %r is too small for IPv6 subranges' | |||
self._logger.error(msg, address_dict) | |||
raise AddressGenerationError('%s/%d' % (address_dict['addr'], prefixlen)) | |||
addr = ipv6FromBin(prefix | |||
+ bin(random.randint(1, 65000))[2:].zfill(16) | |||
+ suffix * (128 - prefixlen)) | |||
return dict(addr=addr, prefixlen=prefixlen, netmask=netmaskFromLenIPv6(prefixlen)) | |||
def addIPv6Address(self, partition_index, addr=None, netmask=None, tap=None): | |||
""" | """ | ||
Adds IPv6 address to interface. | Adds IPv6 address to interface. | ||
... | @@ -1136,6 +1183,9 @@ class Interface(object): | ... | @@ -1136,6 +1183,9 @@ class Interface(object): |
address. If it is not possible (ex. because network changed), calculate new | address. If it is not possible (ex. because network changed), calculate new | ||
address. | 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: | Args: | ||
addr: Wished address to be added to interface. | addr: Wished address to be added to interface. | ||
netmask: Wished netmask to be used. | netmask: Wished netmask to be used. | ||
... | @@ -1189,38 +1239,73 @@ class Interface(object): | ... | @@ -1189,38 +1239,73 @@ class Interface(object): |
self._logger.warning('Impossible to add old public IPv6 %s. ' | self._logger.warning('Impossible to add old public IPv6 %s. ' | ||
'Generating new IPv6 address.' % addr) | 'Generating new IPv6 address.' % addr) | ||
# Try 10 times to add address, raise in case if not possible | # Try to use the IPv6 mapping based on partition index | ||
try_num = 10 | address_dict['prefixlen'] = lenNetmaskIpv6(address_dict['netmask']) | ||
netmask = address_dict['netmask'] | |||
if tap: | if tap: | ||
netmask_len = lenNetmaskIpv6(netmask) | result_addr = getTapIpv6Range(address_dict, partition_index) | ||
prefix = binFromIpv6(address_dict['addr'])[:netmask_len] | # the netmask of the tap itself is always 128 bits | ||
netmask_len += 16 | result_addr['netmask'] = netmaskFromLenIPv6(128) | ||
# we generate a subnetwork for the tap | else: | ||
# the subnetwork has 16 bits more than the interface network | result_addr = getPartitionIpv6Addr(address_dict, partition_index) | ||
# make sure we have at least 2 IPs in the subnetwork | result_addr['netmask'] = netmaskFromLenIPv6(result_addr.pop('prefixlen')) | ||
if netmask_len >= 128: | if self._addSystemAddress(result_addr['addr'], result_addr['netmask'], tap=tap): | ||
self._logger.error('Interface %s has netmask %s which is too big for generating IPv6 on taps.' % (interface_name, netmask)) | return result_addr | ||
raise AddressGenerationError(addr) | |||
netmask = ipv6FromBin('1'*128) # the netmask of the tap itself is always 128 bits | |||
while try_num > 0: | # Try 10 times to add address, raise in case if not possible | ||
for _ in range(10): | |||
if tap: | if tap: | ||
addr = ipv6FromBin(prefix | result_addr = self._generateRandomIPv6Range(address_dict, suffix='1') | ||
+ bin(random.randint(1, 65000))[2:].zfill(16) | # the netmask of the tap itself is always 128 bits | ||
+ '1' * (128 - netmask_len)) | result_addr['netmask'] = netmaskFromLenIPv6(128) | ||
else: | else: | ||
addr = ':'.join(address_dict['addr'].split(':')[:-1] + ['%x' % ( | result_addr = self._generateRandomIPv6Addr(address_dict) | ||
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 | # Checking the validity of the IPv6 address | ||
if self._addSystemAddress(addr, netmask, tap=tap): | if self._addSystemAddress(result_addr['addr'], result_addr['netmask'], tap=tap): | ||
return dict(addr=addr, netmask=netmask) | return result_addr | ||
try_num -= 1 | |||
raise AddressGenerationError(addr) | raise AddressGenerationError(result_addr['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() | |||
address_dict = interface_addr_list[0] | |||
address_dict['prefixlen'] = lenNetmaskIpv6(address_dict['netmask']) | |||
ipv6_range = getPartitionIpv6Range(address_dict, i) | |||
ipv6_range['netmask'] = netmaskFromLenIPv6(ipv6_range['prefixlen']) | |||
ipv6_range['network'] = '%(addr)s/%(prefixlen)d' % ipv6_range | |||
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() | |||
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): | def parse_computer_definition(conf, definition_path): | ||
... | @@ -1246,6 +1331,7 @@ def parse_computer_definition(conf, definition_path): | ... | @@ -1246,6 +1331,7 @@ def parse_computer_definition(conf, definition_path): |
addr=address, | addr=address, | ||
netmask=netmask, | netmask=netmask, | ||
ipv6_interface=conf.ipv6_interface, | ipv6_interface=conf.ipv6_interface, | ||
partition_has_ipv6_range=conf.partition_has_ipv6_range, | |||
software_user=computer_definition.get('computer', 'software_user'), | software_user=computer_definition.get('computer', 'software_user'), | ||
tap_gateway_interface=conf.tap_gateway_interface, | tap_gateway_interface=conf.tap_gateway_interface, | ||
tap_ipv6=conf.tap_ipv6, | tap_ipv6=conf.tap_ipv6, | ||
... | @@ -1260,6 +1346,13 @@ def parse_computer_definition(conf, definition_path): | ... | @@ -1260,6 +1346,13 @@ def parse_computer_definition(conf, definition_path): |
for a in computer_definition.get(section, 'address').split(): | for a in computer_definition.get(section, 'address').split(): | ||
address, netmask = a.split('/') | address, netmask = a.split('/') | ||
address_list.append(dict(addr=address, netmask=netmask)) | address_list.append(dict(addr=address, netmask=netmask)) | ||
if computer_definition.has_option(section, 'ipv6_range'): | |||
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} | |||
else: | |||
ipv6_range = {} | |||
tap = Tap(computer_definition.get(section, 'network_interface')) | tap = Tap(computer_definition.get(section, 'network_interface')) | ||
tun = Tun("slaptun" + str(partition_number), | tun = Tun("slaptun" + str(partition_number), | ||
partition_number, | partition_number, | ||
... | @@ -1269,6 +1362,7 @@ def parse_computer_definition(conf, definition_path): | ... | @@ -1269,6 +1362,7 @@ def parse_computer_definition(conf, definition_path): |
computer_definition.get(section, 'pathname')), | computer_definition.get(section, 'pathname')), | ||
user=user, | user=user, | ||
address_list=address_list, | address_list=address_list, | ||
ipv6_range=ipv6_range, | |||
tap=tap, tun=tun) | tap=tap, tun=tun) | ||
partition_list.append(partition) | partition_list.append(partition) | ||
computer.partition_list = partition_list | computer.partition_list = partition_list | ||
... | @@ -1286,6 +1380,7 @@ def parse_computer_xml(conf, xml_path): | ... | @@ -1286,6 +1380,7 @@ def parse_computer_xml(conf, xml_path): |
computer = Computer.load(xml_path, | computer = Computer.load(xml_path, | ||
reference=conf.computer_id, | reference=conf.computer_id, | ||
ipv6_interface=conf.ipv6_interface, | ipv6_interface=conf.ipv6_interface, | ||
partition_has_ipv6_range=conf.partition_has_ipv6_range, | |||
tap_gateway_interface=conf.tap_gateway_interface, | tap_gateway_interface=conf.tap_gateway_interface, | ||
tap_ipv6=conf.tap_ipv6, | tap_ipv6=conf.tap_ipv6, | ||
software_root=conf.software_root, | software_root=conf.software_root, | ||
... | @@ -1304,6 +1399,7 @@ def parse_computer_xml(conf, xml_path): | ... | @@ -1304,6 +1399,7 @@ def parse_computer_xml(conf, xml_path): |
addr=None, | addr=None, | ||
netmask=None, | netmask=None, | ||
ipv6_interface=conf.ipv6_interface, | ipv6_interface=conf.ipv6_interface, | ||
partition_has_ipv6_range=conf.partition_has_ipv6_range, | |||
software_user=conf.software_user, | software_user=conf.software_user, | ||
tap_gateway_interface=conf.tap_gateway_interface, | tap_gateway_interface=conf.tap_gateway_interface, | ||
tap_ipv6=conf.tap_ipv6, | tap_ipv6=conf.tap_ipv6, | ||
... | @@ -1330,6 +1426,7 @@ def parse_computer_xml(conf, xml_path): | ... | @@ -1330,6 +1426,7 @@ def parse_computer_xml(conf, xml_path): |
conf.partition_base_name, i)), | conf.partition_base_name, i)), | ||
user=User('%s%s' % (conf.user_base_name, i)), | user=User('%s%s' % (conf.user_base_name, i)), | ||
address_list=None, | address_list=None, | ||
ipv6_range=None, | |||
tap=Tap('%s%s' % (conf.tap_base_name, i)), | tap=Tap('%s%s' % (conf.tap_base_name, i)), | ||
tun=Tun('slaptun' + str(i), i, partition_amount) if conf.create_tun else None | tun=Tun('slaptun' + str(i), i, partition_amount) if conf.create_tun else None | ||
) | ) | ||
... | @@ -1351,6 +1448,7 @@ def write_computer_definition(conf, computer): | ... | @@ -1351,6 +1448,7 @@ def write_computer_definition(conf, computer): |
for address in partition.address_list: | for address in partition.address_list: | ||
address_list.append('/'.join([address['addr'], address['netmask']])) | address_list.append('/'.join([address['addr'], address['netmask']])) | ||
computer_definition.set(section, 'address', ' '.join(address_list)) | 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, 'user', partition.user.name) | ||
computer_definition.set(section, 'network_interface', partition.tap.name) | computer_definition.set(section, 'network_interface', partition.tap.name) | ||
computer_definition.set(section, 'pathname', partition.reference) | computer_definition.set(section, 'pathname', partition.reference) | ||
... | @@ -1416,6 +1514,7 @@ class FormatConfig(object): | ... | @@ -1416,6 +1514,7 @@ class FormatConfig(object): |
alter_network = 'True' # modifiable by cmdline | alter_network = 'True' # modifiable by cmdline | ||
interface_name = None | interface_name = None | ||
ipv6_interface = None | ipv6_interface = None | ||
partition_has_ipv6_range = True | |||
create_tap = True | create_tap = True | ||
create_tun = False | create_tun = False | ||
tap_base_name = None | tap_base_name = None | ||
... | @@ -1480,7 +1579,7 @@ class FormatConfig(object): | ... | @@ -1480,7 +1579,7 @@ class FormatConfig(object): |
raise UsageError(message) | raise UsageError(message) | ||
# Convert strings to booleans | # 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) | attr = getattr(self, option) | ||
if isinstance(attr, str): | if isinstance(attr, str): | ||
if attr.lower() == 'true': | if attr.lower() == 'true': | ||
... | ... |