Testing dockerized xbeenet on isolated computers

This commit is contained in:
Emran Billah 2024-08-26 16:57:24 -03:00
parent c2e84c0d6d
commit 960a8e16e8
7 changed files with 134 additions and 205 deletions

14
.env
View File

@ -1,14 +1,14 @@
# Base params # Base params
BASE_SUBNET=10.10.10 BASE_SUBNET=6.6.6
XBEE_INDEX=1 XBEE_INDEX=1
# Default params # Default params
DEFAULT_GATEWAY=10.10.10.1 DEFAULT_GATEWAY=6.6.6.1
DEFAULT_IPVLAN_IP=10.10.10.20 # Required only when running ipvlan net (look in docker compose) DEFAULT_IPVLAN_IP=6.6.6.20 # Required only when running ipvlan net (look in docker compose)
DEFAULT_MACVLAN_IP=10.10.10.30 # Required only when running macvlan net (look in docker compose) DEFAULT_MACVLAN_IP=6.6.6.30 # Required only when running macvlan net (look in docker compose)
# Configuration for xbnet0 # Configuration for xbnet
XBEE_PORT=/dev/ttyUSB0 XBEE_PORT=/dev/ttyUSB0
XBEE_BAUDRATE=230400 XBEE_BAUDRATE=230400
XBEE_NET_SRC_IP=10.10.10.201 # Ensure this IP matches the network range XBEE_NET_SRC_IP=6.6.6.201 # Ensure this IP matches the network range
XBEE_NET_IFACE_NAME=xbnet0 XBEE_NET_IFACE_NAME=xbnet1

View File

@ -1,62 +1,3 @@
# # Use an official Rust image as the base
# FROM rust:latest
# # Install necessary packages
# RUN apt-get update && apt-get install -y \
# libudev-dev \
# iproute2 \
# iputils-ping \
# net-tools \
# bridge-utils \
# iptables \
# supervisor \
# traceroute \
# nmap \
# tcpdump \
# vim \
# && rm -rf /var/lib/apt/lists/*
# # Clone the xbnet repository
# # The xbnet repository contains the source code needed to set up and manage the XBee network
# RUN git clone https://github.com/jgoerzen/xbnet.git /usr/src/xbnet
# # Build xbnet
# # We build the xbnet project from source using Cargo, Rust's package manager and build system
# WORKDIR /usr/src/xbnet
# RUN cargo build --release
# # Copy the built binary to /usr/local/bin
# # The xbnet binary will be placed in /usr/local/bin to be accessible system-wide
# RUN cp target/release/xbnet /usr/local/bin/xbnet
# # Copy the entrypoint script
# # The entrypoint script handles the setup and monitoring of the XBee network
# COPY ./scripts/entrypoint.sh /entrypoint.sh
# RUN chmod +x /entrypoint.sh
# # Copy the supervisor config file
# # Supervisor configuration ensures that the XBee network service is managed and stays running
# COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# # Copy the health check script
# # The health check script will be used by Docker to monitor the health of the container
# COPY ./scripts/health_check.sh /health_check.sh
# RUN chmod +x /health_check.sh
# # Start supervisord as the main command
# # Supervisord will manage and monitor the services, including the XBee network
# CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
# # Add healthcheck
# # The health check command periodically checks the health of the container using a custom script
# HEALTHCHECK CMD /health_check.sh || exit 1
###########################################################
# Use an official Rust image as the base
FROM rust:latest FROM rust:latest
# Install necessary packages # Install necessary packages

View File

@ -70,13 +70,12 @@ services:
env_file: .env env_file: .env
networks: networks:
xbee_net: xbee_net:
ipv4_address: 192.168.2.201 # IP for the xbnet in the Docker network ipv4_address: ${XBEE_NET_SRC_IP} # Ensure this IP belongs to the xbee_net subnet
networks: networks:
xbee_net: xbee_net:
driver: bridge driver: bridge
ipam: ipam:
config: config:
- subnet: 192.168.2.0/24 # Docker network on 192.168.2.x - subnet: ${BASE_SUBNET}.0/24 # Match the network's subnet
gateway: 192.168.2.1 gateway: ${DEFAULT_GATEWAY} # Gateway for central router
ip_range: 192.168.2.200/29

View File

@ -1,40 +1,53 @@
# run-single.sh # run-single.sh
# #
# This script sets up the environment for running a Docker Compose configuration with XBee networks. # This script sets up the environment for running a Docker Compose configuration with XBee networks.
# It accepts optional --index=<int> and --subnet=<subnet> arguments to specify the XBEE_INDEX and BASE_SUBNET values. # It accepts optional --index=<int>, --subnet=<subnet>, --serial-speed=<speed>, and --port=<port> arguments
# to specify the XBEE_INDEX, BASE_SUBNET, XBEE_BAUDRATE, and XBEE_PORT values.
# If no index is provided, it defaults to 1. If no subnet is provided, it defaults to 192.168.1. # If no index is provided, it defaults to 1. If no subnet is provided, it defaults to 192.168.1.
# If no serial-speed is provided, it defaults to 230400. If no port is provided, it defaults to /dev/ttyUSB0.
# #
# Usage: # Usage:
# ./run-single.sh # Runs with default index (1) and default subnet (192.168.1) # ./run-single.sh # Runs with default index (1), default subnet (192.168.1), default speed (230400), and default port (/dev/ttyUSB0)
# ./run-single.sh --index=2 # Runs with index 2 and default subnet (192.168.1) # ./run-single.sh --index=2 # Runs with index 2 and default values for other options
# ./run-single.sh --subnet=192.168.50 # Runs with default index (1) and subnet 192.168.50 # ./run-single.sh --subnet=192.168.50 # Runs with default index (1), specified subnet, and default values for other options
# ./run-single.sh --index=3 --subnet=192.168.50 # Runs with index 3 and subnet 192.168.50 # ./run-single.sh --index=3 --subnet=192.168.50 # Runs with specified index, specified subnet, and default values for speed and port
# # ./run-single.sh --serial-speed=115200 --port=/dev/ttyUSB1 # Runs with specified serial-speed and port with default values for other options
# IPs assigned: # IPs assigned:
# BASE_SUBNET: eg.: 192.168.1 # BASE_SUBNET: eg.: 10.10.10
# DEFAULT_GATEWAY: ${BASE_SUBNET}.1, eg.: 192.168.1.1 # DEFAULT_GATEWAY: ${BASE_SUBNET}.1, eg.: 10.10.10.1
# DEFAULT_IPVLAN_IP: ${BASE_SUBNET}.20 eg.: 192.168.1.20 # DEFAULT_IPVLAN_IP: ${BASE_SUBNET}.20 eg.: 10.10.10.20
# DEFAULT_MACVLAN_IP: ${BASE_SUBNET}.30 eg.: 192.168.1.30 # DEFAULT_MACVLAN_IP: ${BASE_SUBNET}.30 eg.: 10.10.10.30
# XBEE_NET_SRC_IP: ${BASE_SUBNET}.20${index} eg.: 192.168.1.201 (all Xbnets will be in the 200+ range) # XBEE_NET_SRC_IP: ${BASE_SUBNET}.20${index} eg.: 10.10.10.201 (all Xbnets will be in the 200+ range)
#!/bin/bash #!/bin/bash
# Default values # Default values
index=1 INDEX=1
BASE_SUBNET="192.168.1" BASE_SUBNET="10.10.10"
XBEE_BAUDRATE=230400
XBEE_PORT="/dev/ttyUSB0"
# Parse command-line arguments # Parse command-line arguments
for arg in "$@" for arg in "$@"
do do
case $arg in case $arg in
--index=*) --index=*)
index="${arg#*=}" INDEX="${arg#*=}"
shift # Remove --index=<int> from processing shift # Remove --index=<int> from processing
;; ;;
--subnet=*) --subnet=*)
BASE_SUBNET="${arg#*=}" BASE_SUBNET="${arg#*=}"
shift # Remove --subnet=<subnet> from processing shift # Remove --subnet=<subnet> from processing
;; ;;
--serial-speed=*)
XBEE_BAUDRATE="${arg#*=}"
shift # Remove --serial-speed=<speed> from processing
;;
--port=*)
XBEE_PORT="${arg#*=}"
shift # Remove --port=<port> from processing
;;
*) *)
;; ;;
esac esac
@ -44,18 +57,18 @@ done
cat <<EOF > .env cat <<EOF > .env
# Base params # Base params
BASE_SUBNET=${BASE_SUBNET} BASE_SUBNET=${BASE_SUBNET}
XBEE_INDEX=${index} XBEE_INDEX=${INDEX}
# Default params # Default params
DEFAULT_GATEWAY=${BASE_SUBNET}.1 DEFAULT_GATEWAY=${BASE_SUBNET}.1
DEFAULT_IPVLAN_IP=${BASE_SUBNET}.20 # Required only when running ipvlan net (look in docker compose) DEFAULT_IPVLAN_IP=${BASE_SUBNET}.20 # Required only when running ipvlan net (look in docker compose)
DEFAULT_MACVLAN_IP=${BASE_SUBNET}.30 # Required only when running macvlan net (look in docker compose) DEFAULT_MACVLAN_IP=${BASE_SUBNET}.30 # Required only when running macvlan net (look in docker compose)
# Configuration for xbnet0 # Configuration for xbnet
XBEE_PORT=/dev/ttyUSB0 XBEE_PORT=${XBEE_PORT}
XBEE_BAUDRATE=230400 XBEE_BAUDRATE=${XBEE_BAUDRATE}
XBEE_NET_SRC_IP=${BASE_SUBNET}.20${index} # Ensure this IP matches the network range XBEE_NET_SRC_IP=${BASE_SUBNET}.20${INDEX} # Ensure this IP matches the network range
XBEE_NET_IFACE_NAME=xbnet0 XBEE_NET_IFACE_NAME=xbnet${INDEX}
EOF EOF
# Restart Docker Compose services # Restart Docker Compose services

View File

@ -179,130 +179,86 @@
# entrypoint.sh # entrypoint.sh
# #
# This script is responsible for setting up and maintaining an XBee network interface within a Docker container. # This script is responsible for setting up and maintaining an XBee network interface within a Docker container.
# It performs several key tasks, including checking for root privileges, setting up the XBee network interface, # It checks if a device is connected to the specified port, creates a TAP network interface, and monitors the connection.
# configuring network bridges, and monitoring the XBee device. The script runs in a loop to ensure continuous # If the device is disconnected, it cleans up and retries the connection process.
# operation, retrying the setup process if any steps fail.
# #
# Usage: # Usage:
# - This script is intended to be run as the entrypoint for a Docker container. # - This script is intended to be run as the entrypoint for a Docker container.
# - Ensure that the script has executable permissions (`chmod +x entrypoint.sh`) before running it. # - Ensure that the script has executable permissions (`chmod +x entrypoint.sh`) before running it.
# Check if the script is running with root privileges echo "Starting entrypoint.sh"
check_root() {
if [ "$(id -u)" -ne 0 ]; then loop() {
echo "This script must be run as root. Exiting..." while true; do
exit 1 # Check if the XBee device is connected
check_device_port
if [ $? -ne 0 ]; then
echo "No XBee device found at $XBEE_PORT. Waiting for device connection..."
cleanup
continue
fi
# Check if the network interface is up
check_network_state
if [ $? -eq 0 ]; then
echo "Network interface $XBEE_NET_IFACE_NAME is already up."
else
echo "Network interface $XBEE_NET_IFACE_NAME not found. Creating TAP interface..."
create_tap_interface
fi
# Log messages sent and received over xbnet
# log_xbnet_messages
done
}
# Function to check if the XBee device is connected
check_device_port() {
if [ -e "$XBEE_PORT" ]; then
return 0
else
return 1
fi fi
} }
# Clean up resources # Function to check if the network interface is up
# - Kill the background process used to create the xbnet interface check_network_state() {
# - Clean up any resources created or copied over. This includes: if ip link show $XBEE_NET_IFACE_NAME > /dev/null 2>&1; then
# - Bridge interface return 0
# - xbnet interface else
return 1
fi
}
# Function to create a TAP network interface
create_tap_interface() {
# Start xbnet and run it in the background
xbnet -d --serial-speed ${XBEE_BAUDRATE} ${XBEE_PORT} tap --iface-name ${XBEE_NET_IFACE_NAME} &
# Wait until the interface is created
while ! check_network_state; do
sleep 1
done
sudo ip addr add $XBEE_NET_SRC_IP/24 dev $XBEE_NET_IFACE_NAME
sudo ip link set $XBEE_NET_IFACE_NAME up
return 0
}
# Function to clean up resources and exit the script
cleanup() { cleanup() {
echo "Cleaning up resources..." echo "Cleaning up resources..."
pkill -f "xbnet -d --serial-speed $XBEE_BAUDRATE $XBEE_PORT tap" pkill -f "xbnet -d --serial-speed $XBEE_BAUDRATE $XBEE_PORT tap"
if ip link show br0 > /dev/null 2>&1; then
ip link set br0 down
brctl delbr br0
fi
if ip link show $XBEE_NET_IFACE_NAME > /dev/null 2>&1; then if ip link show $XBEE_NET_IFACE_NAME > /dev/null 2>&1; then
ip link set $XBEE_NET_IFACE_NAME down ip link set $XBEE_NET_IFACE_NAME down
ip link delete $XBEE_NET_IFACE_NAME ip link delete $XBEE_NET_IFACE_NAME
fi fi
} }
# Function to check if the XBee device is connected # Trap signals to clean up properly
# - Ensures that the XBee device is present at the specified port before proceeding trap cleanup EXIT
check_xbee_device() {
if [ -e "$XBEE_PORT" ]; then
echo "XBee device found at $XBEE_PORT. Proceeding with setup..."
return 0
else
echo "Error: No XBee device found at $XBEE_PORT. Please connect the device."
return 1
fi
}
# Start the xbnet interface # Start the loop to monitor the network and device
# - Attempts to start the xbnet interface in tap mode loop
# - Verifies if the interface is successfully created and returns the appropriate status code
start_xbnet_interface() {
echo "Starting XBee network interface..."
xbnet -d --serial-speed $XBEE_BAUDRATE $XBEE_PORT tap &
# Wait until the xbnet interface is created
while [ ! -d "/sys/class/net/$XBEE_NET_IFACE_NAME" ]; do
echo "Waiting for interface $XBEE_NET_IFACE_NAME to be created..."
sleep 1
done
# Get the xbnet interface name (e.g., xbnet0) automatically
XBEE_NET_IFACE_NAME=$(ls /sys/class/net | grep 'xbnet')
# Check if the xbnet interface is found
if [ -z "$XBEE_NET_IFACE_NAME" ]; then
echo "Error: No XBee network interface found. Retrying setup..."
cleanup
return 1
else
echo "XBee network interface $XBEE_NET_IFACE_NAME created successfully."
return 0
fi
}
# Configure the network interface and bridge
# - Creates the network interface with the name specified by XBEE_NET_IFACE_NAME in .env file
# - Creates a bridge interface and attaches the xbnet interface to it
# - Brings up the bridge interface
configure_network_and_bridge() {
ip addr add $XBEE_NET_SRC_IP/24 dev $XBEE_NET_IFACE_NAME
ip link set dev $XBEE_NET_IFACE_NAME up
brctl addbr br0
brctl addif br0 $XBEE_NET_IFACE_NAME
ip link set dev br0 up
}
# Function to monitor the XBee device and restart setup if disconnected
# - Periodically checks if the XBee device is still connected
# - If the device is disconnected, triggers cleanup and restarts the setup process
monitor_xbee_device() {
while [ -e "$XBEE_PORT" ]; do
sleep 5
done
echo "XBee device at $XBEE_PORT was removed. Cleaning up..."
cleanup
}
# Main function to set up the XBee network
# - Runs the setup process in a loop to ensure continuous operation
# - If any step fails, it retries the entire process after a short delay
setup_xbee_network() {
while true; do
check_xbee_device
if [ $? -ne 0 ]; then
sleep 5
continue
fi
start_xbnet_interface
if [ $? -ne 0 ]; then
cleanup
sleep 5
continue
fi
configure_network_and_bridge
monitor_xbee_device
done
}
# Run the setup only if the script is executed as root
check_root
setup_xbee_network

View File

@ -1,11 +1,8 @@
#!/bin/bash #!/bin/bash
# Ensure the environment variables are loaded
source /etc/environment
# Perform the health check by pinging the xbnet interface # Perform the health check by pinging the xbnet interface
# - If the xbnet0 interface is successfully created, we should be able to ping the assigned IP # - If the xbnet0 interface is successfully created, we should be able to ping the assigned IP
ping -c 1 "$XBEE0_NET_SRC_IP" > /dev/null 2>&1 ping -c 1 "$XBEE_NET_SRC_IP" > /dev/null 2>&1
# Return the appropriate status based on ping success # Return the appropriate status based on ping success
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then

View File

@ -2,7 +2,30 @@
nodaemon=true nodaemon=true
[program:xbnet] [program:xbnet]
command=/entrypoint.sh command=/bin/bash /entrypoint.sh
autostart=true
autorestart=true autorestart=true
stderr_logfile=/var/log/xbnet.err.log startretries=3
stdout_logfile=/var/log/xbnet.out.log stderr_logfile=/var/log/supervisor/xbnet.err.log
stdout_logfile=/var/log/supervisor/xbnet.out.log
user=root
environment=HOME="/root",USER="root",PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Cmd line tool to check supervisor status
# Usage:
# eg. supervisorctl -c /etc/supervisor/conf.d/supervisord.conf status
# supervisorctl -c /etc/supervisor/conf.d/supervisord.conf restart
# supervisorctl -c /etc/supervisor/conf.d/supervisord.conf stop
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
# HTTP server used to monitor supervisorctl
# Usage:
# eg. curl --unix-socket /var/run/supervisor.sock http://localhost
[unix_http_server]
file=/var/run/supervisor.sock
chmod=0700
# RPC interface required for supervisorctl to communciate with supervisor
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface