See code below. I took some information from the wifi connect block as well as the documentation from DBUS (add-connection.py\dbus\python\examples - NetworkManager/NetworkManager - Network connection manager and user applications (mirrored from https://gitlab.freedesktop.org/NetworkManager/NetworkManager)).
Multiple issues arose:
- Balena documentation says that Python base images have DBUS interface already installed but it was not. I tried -python images as well as -ubuntu-python -debian-python etc. And none of them gave me access to the DBUS. They all gave the error that my python script could not import dbus. So I went through a lot of different build setups and finally got is working by manually installing dependencies via apt-get and then installing the pip package dbus-python.
- Once that was done I was able to set a static IP with the defaults in the script below and that worked fine.
- Once the device rebooted it completely lost connection. I distinctly set the interface to the second ethernet port enp2s0 and all the settings you see in the script. The device was connected to a wifi network as well and never had any issues until this instance. It also has an ethernet connection in the primary ethernet port. Now I can no longer connect.
Did I do something wrong in the python script below with the settings or what? In my mind this should not have affected the wifi connection.
Background:
- this is hosted on balena cloud with the most up to date generic amd64 ext OS as of 6 weeks ago.
- was accessible via the wifi connect for weeks prior
- Device is an off the shelf intel mini PC
Dockerfile
FROM balenalib/%%BALENA_MACHINE_NAME%%-debian-python:3.9.7-buster
RUN apt-get update -y && apt-get install build-essential python-dbus libdbus-1-3 -y libdbus-glib-1-dev libdbus-1-dev libglib2.0-dev python3-dbus gcc meson
RUN apt-get install -y dbus-x11
RUN pip3 install --upgrade pip
RUN pip3 install dbus-python
COPY ./static_ip_service/set_ip.py /app/set_ip.py
# Run your Python script
CMD ["python3", "/app/set_ip.py"]
set_ip.py
#!/usr/bin/env python
import os
import dbus
import uuid
import socket
import struct
def ip_to_int(ip_string):
return struct.unpack("=I", socket.inet_aton(ip_string))[0]
# Read environment variables or set to default values
INTERFACE = os.environ.get('INTERFACE', 'enp2s0')
IP_ADDRESS = os.environ.get('IP_ADDRESS', '192.168.1.1')
NETMASK = os.environ.get('NETMASK', '255.255.255.0')
GATEWAY = os.environ.get('GATEWAY', '192.168.1.1')
DNS = os.environ.get('DNS', '192.168.1.1')
# full duplex
s_wired = dbus.Dictionary({"duplex": "full"})
# Prepare dictionaries for dbus
s_con = dbus.Dictionary({
'type': '802-3-ethernet',
'uuid': str(uuid.uuid4()),
'id': INTERFACE,
})
addr1 = dbus.Array(
[ip_to_int(IP_ADDRESS),
ip_to_int(NETMASK), ip_to_int(GATEWAY)],
signature=dbus.Signature("u"),
)
print(addr1)
addr1 = (
dbus.UInt32(ip_to_int(IP_ADDRESS)),
dbus.UInt32(ip_to_int(NETMASK)),
dbus.UInt32(ip_to_int(GATEWAY)),
)
addr1 = dbus.Dictionary({"address": IP_ADDRESS, "prefix": dbus.UInt32(8)})
s_ip4 = dbus.Dictionary(
{
"address-data": dbus.Array([addr1], signature=dbus.Signature("a{sv}")),
"gateway": GATEWAY,
"dns": dbus.Array([dbus.UInt32(int(ip_to_int(DNS)))], signature=dbus.Signature("u")),
"method": "manual",
}
)
print(s_ip4)
# s_ip4 = dbus.Dictionary({
# 'addresses': dbus.Array([addr1], signature=dbus.Signature('aau')),
# # s_ip4 = dbus.Dictionary({
# # 'addresses': dbus.Array([addr1], signature=dbus.Signature("au")),
# 'method': 'manual',
# 'dns': dbus.Array([dbus.UInt32(int(ip_to_int(DNS)))], signature=dbus.Signature('u'))
# })
# print(s_ip4)
s_ip6 = dbus.Dictionary({"method": "ignore"})
con = dbus.Dictionary(
{"802-3-ethernet": s_wired, "connection": s_con, "ipv4": s_ip4, "ipv6": s_ip6}
)
print(con)
try:
# Initialize dbus connection
bus = dbus.SystemBus()
proxy = bus.get_object("org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager/Settings")
settings = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Settings")
# List existing connections
conn_list = settings.ListConnections()
print("Listing existing connections...")
# Loop through to find if connection already exists
for path in conn_list:
conn_proxy = bus.get_object("org.freedesktop.NetworkManager", path)
conn_settings = dbus.Interface(
conn_proxy, "org.freedesktop.NetworkManager.Settings.Connection")
config = conn_settings.GetSettings()
# Match by some unique property, like 'id'
if config['connection']['id'] == INTERFACE:
print(
f"Found existing connection with ID {INTERFACE}. Updating...")
# Update existing connection
new_settings = {"ipv4": s_ip4}
conn_settings.Update(new_settings)
print(f"Updated connection {INTERFACE}")
break
else:
# Add new connection
print(
f"No existing connection with ID {INTERFACE} found. Creating a new one...")
settings.AddConnection(con)
# print("New connection added.")
print("Creating connection:", s_con["id"], "-", s_con["uuid"])
print("Static IP address set successfully"
f"\nInterface: {INTERFACE}"
f"\nIP Address: {IP_ADDRESS}"
f"\nNetmask: {NETMASK}"
f"\nGateway: {GATEWAY}"
f"\nDNS: {DNS}"
)
except dbus.exceptions.DBusException as e:
print(f"An error occurred: {e}")
# Initialize dbus connection
# bus = dbus.SystemBus()
# proxy = bus.get_object("org.freedesktop.NetworkManager",
# "/org/freedesktop/NetworkManager/Settings")
# settings = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Settings")
# Add Connection
# settings.AddConnection(con)