adjacentlink / python-etce-tutorial

python-etce introduction by demonstration
Other
4 stars 0 forks source link

Multiple "private" bridges in lxcplan #1

Closed vinsworldcom closed 5 years ago

vinsworldcom commented 5 years ago

Is it possible to have LXC plan create multiple "private" bridges between given LXC containers? For example:

image

I've figured out the lxc plan for everything except how to create private-br0 and private-br1 and connect them to only LXC 1 and 2, then 3 and 4 respectively.

Cheers.

vinsworldcom commented 5 years ago

I think I've figured it out, but it's a bit messy with 3 different containertemplate entries and lots of repeated blocks (i.e., interface bridge="emanenode0", initscript).

Is there a way to - for example - say:

<initscript filename="script.sh">

and have the script.sh file contain the code? Or create an interface by name (e.g., emanenode0 above) and then reference that in the tags like so:

<interfaces>
  <interface bridge="emanenode0"/>
</intefaces>

Looking at the lxcplanfile.xsd doesn't seem to indicate this is possible.

Cheers.

eschreiber-alink commented 5 years ago

Here's an example that does something similar to what you are asking for, but not the same. It launches a modified version of the network from Demonstration 3 where, now, each node container connects to its own host over a local "private" lan:

<?xml version="1.0" encoding="UTF-8"?>
<lxcplan>
  <containertemplates>
    <containertemplate name="basenode">
      <parameters>
        <parameter name="lxc.tty" value="1"/>
        <parameter name="lxc.pts" value="128"/>
        <parameter name="lxc.console" value="none"/>
        <parameter name="lxc.mount.auto" value="proc sys"/>
      </parameters>
      <interfaces>
        <interface bridge="br.ctl" hosts_entry_ipv4="${lxc_name}">
          <parameter name="lxc.network.type" value="veth"/>
          <parameter name="lxc.network.name" value="backchan0"/>
          <parameter name="lxc.network.flags" value="up"/>
          <parameter name="lxc.network.hwaddr" value="02:00:${'%02x' % lxc_index}:01:00:${'%02x' % lxc_index}"/>
          <parameter name="lxc.network.ipv4" value="10.76.0.${lxc_index}/16"/>
          <parameter name="lxc.network.veth.pair" value="veth.ctl.${lxc_index}"/>
        </interface>
      </interfaces>
      <initscript>#!/bin/bash

# make node for tun device
mkdir /dev/net
mknod /dev/net/tun c 10 200

pidfile="${lxc_directory}/var/run/sshd.pid"
/usr/sbin/sshd -o "PidFile=$pidfile" -o "PermitRootLogin=yes" -o "PasswordAuthentication=no"
      </initscript>
    </containertemplate>

    <containertemplate name="radio" parent="basenode">
      <interfaces>
        <interface bridge="br.ota">
          <parameter name="lxc.network.type" value="veth"/>
          <parameter name="lxc.network.name" value="ota0"/>
          <parameter name="lxc.network.flags" value="up"/>
          <parameter name="lxc.network.hwaddr" value="02:00:${'%02x' % lxc_index}:02:00:${'%02x' % lxc_index}"/>
          <parameter name="lxc.network.ipv4" value="10.77.0.${lxc_index}/16"/>
          <parameter name="lxc.network.veth.pair" value="veth.ota.${lxc_index}"/>
        </interface>
      </interfaces>
    </containertemplate>

    <containertemplate name="multihomedradio" parent="radio">
      <interfaces>
        <interface bridge="br.lan${nodeid}">
          <parameter name="lxc.network.type" value="veth"/>
          <parameter name="lxc.network.name" value="lan0"/>
          <parameter name="lxc.network.flags" value="up"/>
          <parameter name="lxc.network.hwaddr" value="04:00:01:00:00:01"/>
          <parameter name="lxc.network.ipv4" value="192.168.${nodeid}.1/24"/>
          <parameter name="lxc.network.veth.pair" value="veth.lan.${lxc_index}"/>
        </interface>
      </interfaces>
    </containertemplate>

    <containertemplate name="host" parent="basenode">
      <interfaces>
        <interface bridge="br.lan${nodeid}">
          <parameter name="lxc.network.type" value="veth"/>
          <parameter name="lxc.network.name" value="lan0"/>
          <parameter name="lxc.network.flags" value="up"/>
          <parameter name="lxc.network.hwaddr" value="04:00:02:00:00:02"/>
          <parameter name="lxc.network.ipv4" value="192.168.${nodeid}.2/24"/>
          <parameter name="lxc.network.veth.pair" value="veth.lan.${lxc_index}"/>
        </interface>
      </interfaces>
    </containertemplate>

  </containertemplates>

  <hosts>
    <host hostname="localhost">
      <bridges>
        <bridge name="br.ctl">
          <ipaddress>
            <ipv4>10.76.0.200/16</ipv4>
          </ipaddress>
        </bridge>
        <bridge name="br.ota">
          <ipaddress>
            <ipv4>10.77.0.200/16</ipv4>
          </ipaddress>
        </bridge>
      </bridges>

      <containers>
        <container lxc_name="helper" lxc_indices="201" template="radio"/>

        <container lxc_name="node-${'%03d' % nodeid}" lxc_indices="1-10" template="multihomedradio">
          <overlays>
            <overlaylist name="nodeid" values="1,2,3,4,5,6,7,8,9,10"/>
          </overlays>
        </container>

        <container lxc_name="host-${'%03d' % nodeid}" lxc_indices="11-20" template="host">
          <overlays>
            <overlaylist name="nodeid" values="1,2,3,4,5,6,7,8,9,10"/>
          </overlays>
        </container>
      </containers>
    </host>
  </hosts>
</lxcplan>

The container templates are built up incrementally by adding an interface as appropriate for each container type. The rules to keep in mind interpreting this:

  1. The values for the container lxc_indices attribute is unique across all containers - the value of lxc_index is unique for each container.
  2. A nodeid parameter is added to the node and host container elements as an overlaylist. The values of nodeid map one to one to the lxc_indices values for that container.
  3. The nodeid value is available to parametrize fields in the container template. This is especially used to name the bridge of the lan that connects each node and host pair and to assign unique subnet addresses to each.
  4. ETCE builds a set of all unique interface bridge names it discovers as it iterates over the container definitions and creates a bridge for each. The shared, unique bridge name for each node/host pair is the key to creating the bridge that connects them.

This is not the only way to do this. The goal here was to build up the container templates logically with a minimum of repetition. I think you'll be able to create your network along similar lines.

vinsworldcom commented 5 years ago

Thanks - that's much better. Using parent in containertemplate was what was missing for me.