Compare commits

...

3 commits

Author SHA1 Message Date
Théophile Bastian 82dcc54c71 Fix network addresses and indexing
Multiple fixes to make network addresses consistent
2020-03-11 11:29:13 +01:00
Théophile Bastian 5b8f16163d Containers: setup network addresses
Use systemd-networkd and config files
2020-03-11 11:28:47 +01:00
Théophile Bastian 8eb49fd01d Change XMLTemplate to JinjaTemplate 2020-03-11 11:27:38 +01:00
5 changed files with 64 additions and 21 deletions

View file

@ -2,7 +2,7 @@
from . import settings
from . import util
from .xml_template import XMLTemplate
from .jinja_template import JinjaTemplate
import libvirt
import tempfile
@ -150,13 +150,33 @@ class Container(util.LibvirtObject):
for net in self.networks
]
def _create_network_files(self):
""" Creates systemd-networkd .network files to set IP addresses """
if not self.overlay_root:
raise Exception("No root directory specified yet")
net_config_templ = JinjaTemplate("nic.network")
net_conf_dir = self.overlay_root.mount_point / "etc/systemd/network/"
for net in self.networks:
net_config = net_config_templ.inst(
mac=util.MACAddress(net.id, self.id),
ipv4=util.Addrv4(net.id, self.id),
ipv6=util.Addrv6(net.id, self.id),
)
net_config_path = net_conf_dir / "11-{link:02d}-{name}.network".format(
link=net.id, name=net.name
)
with open(net_config_path, "w") as handle:
handle.write(net_config)
def create(self):
if self.lxc_container:
raise self.AlreadyExists()
self.overlay_root = OverlayDirectory(settings.BASE_SYSTEM_ROOT, name=self.name)
xml = XMLTemplate("container.xml").inst(
self._create_network_files()
xml = JinjaTemplate("container.xml").inst(
name=self.name,
uuid=self.uuid,
mem=self.mem,

View file

@ -1,17 +1,17 @@
""" Reads an XML template from a file """
""" Reads a jinja template from a file """
import os
import jinja2
class XMLTemplate:
class JinjaTemplate:
""" Reads and instanciates a template from a file """
base_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates")
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(base_path),
autoescape=jinja2.select_autoescape(
enabled_extensions=("xml"), default_for_string=True,
enabled_extensions=("xml", "network"), default_for_string=True,
),
)

View file

@ -2,7 +2,7 @@
from . import settings
from . import util
from .xml_template import XMLTemplate
from .jinja_template import JinjaTemplate
class Network(util.LibvirtObject):
@ -19,15 +19,15 @@ class Network(util.LibvirtObject):
self.name = settings.PREFIX + "_link_" + name
self.bridge_id = settings.NETWORK_ID * 0xFF + self.id
self.bridge_mac = util.MACAddress(self.id, None)
self.ipv4 = util.Addrv4(self.id, None)
self.ipv6 = util.Addrv6(self.id, None)
self.ipv4 = util.Addrv4(self.id, None, host_address=True)
self.ipv6 = util.Addrv6(self.id, None, host_address=True)
self.lxc_network = None
def create(self):
if self.lxc_network:
raise self.AlreadyExists()
xml = XMLTemplate("network.xml").inst(
xml = JinjaTemplate("network.xml").inst(
name=self.name,
uuid=self.uuid,
bridge_id=self.bridge_id,

View file

@ -0,0 +1,8 @@
[Match]
MACAddress={{ mac }}
[Network]
DHCP=no
{% if ipv4 %}Address={{ ipv4 }}/{{ ipv4.prefix }}{% endif %}
{% if ipv6 %}Address={{ ipv6 }}/{{ ipv6.prefix }}{% endif %}
LinkLocalAddressing=ipv6

View file

@ -7,7 +7,7 @@ import uuid
class NumberedClass:
""" A class that counts its current instance number """
next_id = 0
next_id = 1 # Count from 1: IP addresses and id 0 are not a good mix.
@classmethod
def get_id(cls):
@ -49,12 +49,12 @@ class LibvirtObject(NumberedClass):
class MACAddress:
""" A MAC address for a NIC or bridge """
def __init__(self, link_id, dev_id):
def __init__(self, link_id, dev_id=None):
""" link_id: id of the current link
dev_id: id of the current NIC. If the device is a bridge, use None
"""
if not dev_id:
dev_id = 0xFF
if dev_id is None:
dev_id = 0xFE
self.link_id = link_id
self.dev_id = dev_id
@ -71,12 +71,20 @@ class MACAddress:
class Addrv4:
""" An address in IPv4 """
def __init__(self, link_id, dev_id):
def __init__(self, link_id, dev_id=None, host_address=False):
""" link_id: id of the current link
dev_id: id of the current NIC. Use None to get the base address
host_address: if True and dev_id is None, returns the host machine address
on this network instead of the base address
"""
if not dev_id:
dev_id = 0
self.host_address = host_address
if dev_id is None:
if host_address:
dev_id = 0xFE
else:
dev_id = 0
self.link_id = link_id
self.dev_id = dev_id
@ -85,7 +93,7 @@ class Addrv4:
def __str__(self):
return "{base_range}.{link_id}.{dev_id}".format(
base_range=settings.IPV4_RANGE, link_id=self.link_id, dev_id=self.dev_id
base_range=settings.IPV4_RANGE, link_id=self.link_id, dev_id=self.dev_id,
)
def __repr__(self):
@ -95,12 +103,19 @@ class Addrv4:
class Addrv6:
""" An address in IPv6 """
def __init__(self, link_id, dev_id):
def __init__(self, link_id, dev_id=None, host_address=False):
""" link_id: id of the current link
dev_id: id of the current NIC. Use None to get the base address
host_address: if True and dev_id is None, returns the host machine address
on this network instead of the base address
"""
if not dev_id:
dev_id = 0
self.host_address = host_address
if dev_id is None:
if host_address:
dev_id = 0xFE
else:
dev_id = 0
self.link_id = link_id
self.dev_id = dev_id
@ -108,5 +123,5 @@ class Addrv6:
def __str__(self):
return "{base_range}:{link_id:04x}::{dev_id:04x}".format(
base_range=settings.IPV6_RANGE, link_id=self.link_id, dev_id=self.dev_id
base_range=settings.IPV6_RANGE, link_id=self.link_id, dev_id=self.dev_id,
)