LXD per a SX

De Jose Castillo Aliaga
Ir a la navegación Ir a la búsqueda

Amb la tecnologia LXD es pot configurar un servidor que proporcione un entorn virtual per a fer pràctiques. Una forma de fer-ho ràpidament pot ser amb Proxmox. Aquest manual és per fer-ho sols amb LXD en un Ubuntu 16.04.

No cal entrar en detalls en alguns comandaments, la manera de fer-los està explicada en LXD.

El cas (real) que ens ocupa tracta de crear un servidor per a una classe de 15 alumnes per a que practiquen en Servicis en Xarxa. Es tracta de provar DHCP, DNS i altres servidors i clients. Cada alumne té accés a 2 contenidors prèviament configurats per a que tinguen l'estructura de xarxa típica de client servidor. Ells els controlen totalment, però no poden accedir als dels companys.

Configuració del servidor

Abans de tot, cal configurar el servidor correctament segons aquest manual.

En /etc/security/limits.conf:

* 	soft 	nofile 	1048576 	
* 	hard 	nofile 	1048576 	
root 	soft 	nofile 	1048576 	
root 	hard 	nofile 	1048576 	
* 	soft 	memlock 	unlimited 	
* 	hard 	memlock 	unlimited 	

En /etc/sysctrl.conf:

fs.inotify.max_queued_events=1048576 	
fs.inotify.max_user_instances=1048576 
fs.inotify.max_user_watches=1048576 	
vm.max_map_count=262144 	

Configurar ZFS

Anem a configurar ZFS per a fer un Striped Mirrored VDEVs que és similar a un RAID10, ja que volem rendiment i seguretat.


A continuació, cal iniciar lxd:

# lxd init
# Se configura amb quasi tot per defecte (Si pot ser en zfs en raid, millor)

# lxc launch ubuntu:16.04 plantillla -c security.nesting=true
# lxc config edit plantilla
# Es canvia la eth0 de bridged a macvlan amb la targeta del server (també es pot fer el mateix en 'profiles').

Dins del container cal fer algunes coses:

  • Reinstal·lar openssh-server per tindre la configuració per defecte.
  • Donar password a ubuntu per poder accedir per ssh.
  • Crear els containers:
    • Fer un pont br0 per a la xarxa interna sols accesible per els containers de dins.
    • Fer que el client tinga sols el pont i el servidor una en el br0 i l'altra en lxdbr0

D'aquesta manera, cada alumne entra per ssh a un container, canvia la contrasenya de ubuntu i té disponible una configuració de dos containers dins del seu o pot configurar el que necessite.

Una vegada tot configurat, es paren els containers de dins i el container plantilla. Després es copia la plantilla:

# for n in {1..15}; do echo "Copiant $n"; lxc copy plantilla alumne$n; done

Aquest for es pot utilitzar després per iniciar-los tots o parar-los. Al copiar un contenidor la MAC és modificada, però no la dels contenidors que conté. Si algú està en macvlan, pot donar problemes. Cal especificar manualment la MAC dels contenidors interns una vegada copiat en de l'alumne.

# for i in {1..24}; do lxc exec alumne$i -- lxc config set firewall volatile.wan.hwaddr 00:16:3e:e7:ba:$((10+$i)); done

Avís Cal pensar que són 15x2 + 15 = 45 contenidors en total els que té que suportar el servidor. Pot ser interessant fer un sleep en el for d'arrancar-los tots per donar temps a que es configuren totalment. L'arranc total pot durar uns minuts en els que els disc dur té molt de treball. Una vegada en marxa tot funciona perfectament. El coll de botella és el disc dur. El meu servidor és un i5 amb 8GB de RAM

Un altre problema és que els contenidors Ubuntu venen amb el unattended upgrades. Caldria desinstal·lar-lo

Pot ser que els contenidors no poden ser accedits per SSH. Cal modificar la contrasenya de ubuntu, el fitxer de ssh i reiniciar el servei.

# for i in {1..24}; do lxc file push shadow simulacre$i/etc/shadow; done
# for i in {1..24}; do lxc exec simulacre$i -- sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config; done
# for i in {1..24}; do lxc exec simulacre$i -- service sshd restart; done

Exemple de cóm queda:

lliurex@2smxv:~$ lxc list
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
|  NOMBRE  | ESTADO  |              IPV4              |                    IPV6                    |    TIPO    | SNAPSHOTS |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne1  | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe31:1c2d (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.218 (eth0)           |                                            |            |           |
|          |         | 10.235.78.1 (lxdbr0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne10 | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe67:f1f7 (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.227 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne11 | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:feb9:a80c (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.228 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne12 | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fecc:e507 (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.232 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne13 | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:feee:768d (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.229 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne14 | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe95:14d0 (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.230 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne15 | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe60:cc7c (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.231 (eth0)           |                                            |            |           |
|          |         | 10.235.78.1 (lxdbr0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne2  | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe21:6a76 (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.219 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne3  | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe6b:7f64 (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.220 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne4  | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fec2:86ea (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.221 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne5  | RUNNING | 192.168.0.222 (eth0)           | fd62:5f40:e210:0:216:3eff:fe9c:f3aa (eth0) | PERSISTENT | 0         |
|          |         | 192.168.66.1 (br0)             |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne6  | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe16:bea4 (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.223 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne7  | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe73:c391 (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.224 (eth0)           |                                            |            |           |
|          |         | 10.235.78.1 (lxdbr0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne8  | RUNNING | 192.168.66.1 (br0)             | fd62:5f40:e210:0:216:3eff:fe90:163e (eth0) | PERSISTENT | 0         |
|          |         | 192.168.0.225 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| alumne9  | RUNNING | 10.235.78.1 (lxdbr0)           | fd62:5f40:e210:0:216:3eff:feaa:d8 (eth0)   | PERSISTENT | 0         |
|          |         | 192.168.66.1 (br0)             |                                            |            |           |
|          |         | 192.168.0.226 (eth0)           |                                            |            |           |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+
| plantilla| STOPPED |                                |                                            | PERSISTENT | 0         |
+----------+---------+--------------------------------+--------------------------------------------+------------+-----------+

Script per gestionar targetes:

#!/bin/bash
 
function crear_ponts {
echo -e "Crear Ponts\nAquesta opció crea un pont de xarxa sense connexió a res. És útil per crear switchs virtuals"
read -p "Nom del pont: " nom
read -p "IP del pont: " adr
echo -e "\n\nauto $nom\niface $nom inet static\naddress $adr\nnetmask 255.255.255.0\nbridge-ports none" >> /etc/network/interfaces
 
brctl addbr $nom
ifup $nom
}
 
function crear_targeta {
echo "Crear targeta"
lxc list
read -p "Nom del container: " nom
echo "Configuració del contenidor:"
lxc config show --expanded $nom
read -p "Nom de la nova targeta: " eth
echo "Lista de targetes i ponts:"
ifconfig | grep "Link"
read -p "Nom del parent: " parent
read -p "Tipus de targeta [bridged macvlan]: " tipus
lxc config device add $nom $eth nic nictype=$tipus parent=$parent name=$eth
 
lxc config show --expanded $nom
}
 
function crear_targeta_bridged {
echo "Crear targeta bridged en varis containers"
lxc list
read -p "Nom dels container: " noms
ifconfig | grep "Link"
read -p "Nom del parent: " parent
read -p "Nom de la targeta (ha de ser compatible en tots els containers): " eth
for i in $noms
do
lxc config device add $i $eth nic nictype=bridged parent=$parent name=$eth
lxc config show --expanded $i
done
}
 
function crear_targeta_profile {
echo "Crear targeta"
lxc profile list
read -p "Nom del profile: " nom
echo "Configuració del profile:"
lxc profile show $nom
read -p "Nom de la nova targeta: " eth
echo "Lista de targetes i ponts:"
ifconfig | grep "Link"
read -p "Nom del parent: " parent
read -p "Tipus de targeta [bridged macvlan]: " tipus
lxc profile device add $nom $eth nic nictype=$tipus parent=$parent name=$eth
 
lxc profile show $nom
}
 
function ip_estatica {
echo "Donar una IP estàtica a una container"
lxc list
read -p "Nom del container: " nom
echo "Configuració del contenidor:"
lxc config show --expanded $nom
read -p "Nom de la targeta: " eth
read -p "IP de la targeta: " ip
read -p "Màscara de la targeta: " masc
echo -e "\n\nauto $eth\niface $eth inet static\naddress $ip\nnetmask $masc" > /tmp/${eth}.cfg && lxc file push /tmp/${eth}.cfg ${nom}/etc/network/interfaces.d/
lxc exec $nom -- ifdown $eth
lxc exec $nom -- ifup $eth
}
 
echo "Configurador LXD"
echo "MENU"
echo "1) Crear ponts"
echo "2) Crear una targeta en un container"
echo "3) Crear una targeta bridged en varis containers"
echo "4) Crear una targeta en un profile"
echo "5) IP estàtica a container"
 
read -p "Opció: " opcio
 
case $opcio in
 1) crear_ponts;;
 2) crear_targeta;;
 3) crear_targeta_bridged;;
 4) crear_targeta_profile;;
 5) ip_estatica;;
 *) echo "Opció no valida"
esac

Scripts per a crear xarxes completes

Projecte 2017

#!/bin/bash
 
lxc launch images:alpine/3.6 firewall
lxc launch images:alpine/3.6 router1
lxc launch ubuntu:16.04 servidorDHCP
lxc launch ubuntu:16.04 servidorWeb
lxc launch images:alpine/3.6 router2
lxc launch images:alpine/3.6 client1
lxc launch images:alpine/3.6 client2
lxc launch images:alpine/3.6 firewallintern
 
for i in {1..6}
do
echo -e "\n\nauto switch$i\niface switch$i inet static\naddress 192.168.99.$i\nnetmask 255.255.255.0\nbridge-ports none" >> /etc/network/interfaces
brctl addbr switch$i
ifup switch$i
done
 
lxc config device add firewall eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add firewall wan nic nictype=macvlan parent=eth0 name=wan
 
lxc config device add router1 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add router1 eth2 nic nictype=bridged parent=switch2 name=eth2
lxc config device add router1 eth3 nic nictype=bridged parent=switch3 name=eth3
 
lxc config device add firewallintern eth3 nic nictype=bridged parent=switch3 name=eth3
lxc config device add firewallintern eth4 nic nictype=bridged parent=switch4 name=eth4
 
lxc config device add router2 eth4 nic nictype=bridged parent=switch4 name=eth4
lxc config device add router2 eth5 nic nictype=bridged parent=switch5 name=eth5
lxc config device add router2 eth6 nic nictype=bridged parent=switch6 name=eth6
 
lxc config device add servidorDHCP eth1 nic nictype=bridged parent=switch2 name=eth1
lxc config device add servidorWeb eth1 nic nictype=bridged parent=switch2 name=eth1
#lxc config device add servidorDNS1 eth1 nic nictype=bridged parent=switch2 name=eth1
#lxc config device add servidorDNS2 eth1 nic nictype=bridged parent=switch2 name=eth1
lxc config device add client1 eth1 nic nictype=bridged parent=switch6 name=eth1
lxc config device add client2 eth1 nic nictype=bridged parent=switch5 name=eth1

Exemple

#!/bin/bash
 
lxc launch images:alpine/3.6 firewall
lxc launch images:alpine/3.6 router1
lxc launch ubuntu:16.04 servidorDHCP
lxc launch images:alpine/3.6 client1
lxc launch images:alpine/3.6 client2
echo "#Configuracio" > /etc/network/interfaces.d/99-conf.cfg 
for i in {1..3}
do
	echo -e "\n\nauto switch$i\niface switch$i inet static\naddress 192.168.99.$i\nnetmask 255.255.255.0\nbridge-ports none" >> /etc/network/interfaces.d/99-conf.cfg
brctl addbr switch$i
ifup switch$i
done
 
lxc config device add firewall eth1 nic nictype=bridged parent=switch1 name=eth1
 
lxc config device add router1 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add router1 eth2 nic nictype=bridged parent=switch2 name=eth2
lxc config device add router1 eth3 nic nictype=bridged parent=switch3 name=eth3
lxc config device remove router1 eth0
 
lxc config device add servidorDHCP eth2 nic nictype=bridged parent=switch2 name=eth2
lxc config device add servidorDHCP eth3 nic nictype=bridged parent=switch3 name=eth3
lxc config device remove servidorDHCP eth0

lxc config device add client1 eth1 nic nictype=bridged parent=switch2 name=eth1
lxc config device add client2 eth1 nic nictype=bridged parent=switch3 name=eth1
lxc config device remove client1 eth0
lxc config device remove client2 eth0

Exercici1

#!/bin/bash

#                  ---------
#                  |client1|
#                  ---------
#                      |      
#                   /switch3/
#                      |
#                  ---------
#                  |router1|
#                  ---------
#                  /       \              ----------
#           /switch4/    /switch1/--------|Firewall|
#           /               \             ----------
#    ---------              ---------
#    |router3|--/switch5/---|router2|
#    --------               ---------
#        |                      |
#    /switch6/               /switch2/
#        |                      |
#    ---------               ---------
#    |client3|               |client2|
#    ---------               ---------
#



lxc launch images:alpine/3.6 firewall
lxc launch images:alpine/3.6 router1
lxc launch images:alpine/3.6 router2
lxc launch images:alpine/3.6 router3
lxc launch images:alpine/3.6 client1
lxc launch images:alpine/3.6 client2
lxc launch images:alpine/3.6 client3

apt update
apt install bridge-utils 

echo "#Configuracio" > /etc/network/interfaces.d/99-conf.cfg 
for i in {1..6}
do
	echo -e "\n\nauto switch$i\niface switch$i inet static\naddress 192.168.99.$i\nnetmask 255.255.255.0\nbridge-ports none" >> /etc/network/interfaces.d/99-conf.cfg
brctl addbr switch$i
ifup switch$i
done
 
lxc config device add firewall eth1 nic nictype=bridged parent=switch1 name=eth1
 
lxc config device add router1 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add router1 eth3 nic nictype=bridged parent=switch3 name=eth3
lxc config device add router1 eth4 nic nictype=bridged parent=switch4 name=eth4

lxc config device add router2 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add router2 eth2 nic nictype=bridged parent=switch2 name=eth2
lxc config device add router2 eth5 nic nictype=bridged parent=switch5 name=eth5

lxc config device add router3 eth4 nic nictype=bridged parent=switch4 name=eth4
lxc config device add router3 eth5 nic nictype=bridged parent=switch5 name=eth5
lxc config device add router3 eth6 nic nictype=bridged parent=switch6 name=eth6
 
lxc config device add client1 eth1 nic nictype=bridged parent=switch3 name=eth1
lxc config device add client2 eth1 nic nictype=bridged parent=switch2 name=eth1
lxc config device add client3 eth1 nic nictype=bridged parent=switch6 name=eth1


lxc profile create xarxa
lxc profile set xarxa security.privileged true

lxc profile apply router1 xarxa
lxc profile apply router2 xarxa
lxc profile apply router3 xarxa
lxc profile apply client1 xarxa
lxc profile apply client2 xarxa
lxc profile apply client3 xarxa

Exercici2

#!/bin/bash

#                     
#                  ---------  ---------
#                  |router1|  |client2|
#                  ---------  ---------
#                  /       \  /          ----------
#           /switch2/   /switch1/--------|Firewall|
#           /    \       /     \         ----------
#    ---------   ---------    ---------
#    |client3|   |DHCP   |    |client1|
#    --------    ---------    ---------
#



lxc launch images:alpine/3.6 firewall
lxc launch images:alpine/3.6 router1
lxc launch images:alpine/3.6 client1
lxc launch images:alpine/3.6 client2
lxc launch ubuntu:16.04 dhcp

apt update
apt install bridge-utils 

echo "#Configuracio" > /etc/network/interfaces.d/99-conf.cfg 
for i in {1..2}
do
	echo -e "\n\nauto switch$i\niface switch$i inet static\naddress 192.168.99.$i\nnetmask 255.255.255.0\nbridge-ports none" >> /etc/network/interfaces.d/99-conf.cfg
brctl addbr switch$i
ifup switch$i
done
 
lxc config device add firewall eth1 nic nictype=bridged parent=switch1 name=eth1
 
lxc config device add router1 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add router1 eth2 nic nictype=bridged parent=switch2 name=eth2

lxc config device add client1 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add client2 eth1 nic nictype=bridged parent=switch1 name=eth1

lxc config device add dhcp eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add dhcp eth2 nic nictype=bridged parent=switch2 name=eth2


lxc profile create xarxa
lxc profile set xarxa security.privileged true

lxc profile apply router1 xarxa
lxc profile apply client1 xarxa
lxc profile apply client2 xarxa
lxc profile apply dhcp xarxa

Simulacre

Aques seria l'exemple més complet.

#!/bin/bash
 
#                     /switch3/
#                      /      \
#                  ---------  -----------
#                  |router1|  |client1-2|
#                  ---------  -----------
#                  /       \             ----------
#           /switch2/   /switch1/--------|Firewall|
#           /             /    \         ----------
#    -----------   ---------    -----------
#    |client3-6|   |DHCP   |    |client7-9|
#    ----------    ---------    -----------
#
 
lxc profile create xarxa
lxc profile set xarxa security.privileged true
 
 
lxc launch images:alpine/3.6 firewall 
lxc launch images:alpine/3.6 router1 --profile=xarxa
lxc launch images:alpine/3.6 client1  --profile=xarxa
lxc launch images:alpine/3.6 client2  --profile=xarxa
lxc launch images:alpine/3.6 client3  --profile=xarxa
lxc launch images:alpine/3.6 client4  --profile=xarxa
lxc launch images:alpine/3.6 client5  --profile=xarxa
lxc launch images:alpine/3.6 client6  --profile=xarxa
lxc launch images:alpine/3.6 client7  --profile=xarxa
lxc launch images:alpine/3.6 client8  --profile=xarxa
lxc launch images:alpine/3.6 client9  --profile=xarxa

lxc launch ubuntu:16.04 dhcp --profile=xarxa
 
apt update
apt install bridge-utils 
 
echo "#Configuracio" > /etc/network/interfaces.d/99-conf.cfg 
for i in {1..3}
do
	echo -e "\n\nauto switch$i\niface switch$i inet static\naddress 192.168.99.$i\nnetmask 255.255.255.0\nbridge-ports none" >> /etc/network/interfaces.d/99-conf.cfg
brctl addbr switch$i
ifup switch$i
done
 
lxc config device add firewall eth1 nic nictype=bridged parent=switch1 name=eth1
 
lxc config device add router1 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add router1 eth2 nic nictype=bridged parent=switch2 name=eth2
lxc config device add router1 eth3 nic nictype=bridged parent=switch3 name=eth3
 
lxc config device add client1 eth1 nic nictype=bridged parent=switch3 name=eth1
lxc config device add client2 eth1 nic nictype=bridged parent=switch3 name=eth1
lxc config device add client3 eth1 nic nictype=bridged parent=switch2 name=eth1
lxc config device add client4 eth1 nic nictype=bridged parent=switch2 name=eth1
lxc config device add client5 eth1 nic nictype=bridged parent=switch2 name=eth1
lxc config device add client6 eth1 nic nictype=bridged parent=switch2 name=eth1
lxc config device add client7 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add client8 eth1 nic nictype=bridged parent=switch1 name=eth1
lxc config device add client9 eth1 nic nictype=bridged parent=switch1 name=eth1
 
lxc config device add dhcp eth1 nic nictype=bridged parent=switch1 name=eth

I per fer que tots tinguen nano e iptables:

for i in client1 client2 client3 client4 client5 client6 client7 client8 client9 firewall router1; 
do 
 lxc start $i; sleep 5; 
 lxc profile apply $i default; 
 lxc exec $i -- reboot; sleep 10; 
 lxc exec $i -- apk update; 
 lxc exec $i -- apk add nano; 
 lxc exec $i -- apk add iptables; 
 lxc profile apply $i xarxa; 
done

Script per a generar un mapa de la xarxa:

#!/bin/bash
echo 'digraph {
graph [pad="0.5", nodesep="0.5", ranksep="2", splines=ortho,];
node [shape=none]
rankdir=LR;'
bridges=($(brctl show | tail -n +2 |cut -f1 | tr "\n" " "))
for i in ${bridges[@]}
do
	echo "$i [label=\"$i\" shape=box];"
done

containers=($(lxc list | egrep '(STOPPED|RUNNING)' | cut -d" " -f2 | tr "\n" " "))
xarxes="$(lxc list --format json | jq -r '.[] | {container: .name, dev: .expanded_devices[]} | [.container,.dev.name,.dev.parent,.dev.type] | @csv' | grep '"nic"$')"
relations=""

for i in ${containers[@]}
do
	pc="$i [label=<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\"><tr><td bgcolor=\"#CCCCCC\" >$i</td></tr>"
	while read dev
	do
		nom=$(echo $dev | cut -d "," -f2 | tr -d '"')
		switch=$(echo $dev | cut -d"," -f3 | tr -d '"')
		pc=$pc"<tr><td port=\"$nom\">$nom</td></tr>"
		#La IP
		ip=$(lxc info $i | tr "\t" " " | grep "$nom: inet " | tr -s " " | cut -d" " -f4)
		relations=$relations"$switch -> $i:$nom [dir=none headlabel=\"$ip\"] \n"
		relations=$relations"//$i:$nom -> $switch [dir=none taillabel=\"$ip\"] \n"
	done <<< "$(echo "$xarxes" | grep "$i")"
	pc=$pc"</table>>];"
	echo $pc
done

echo -e "$relations"
echo '}'