Skip to content

Commit

Permalink
Fixed OpenWRT (#190)
Browse files Browse the repository at this point in the history
* use alpine instead of debian to reduce the image size by 814 mb

* fixed the download.py, added support for minor versions eg 23.05.3, unzip is now part of the download.py instead of the Makefile, download.py will skip the download if file is allready downloaded.

* fixed launch.py, replaced argparse with click(support for environment variables - username, password and connection_mode) default connection mode is tc

* updating the readme
  • Loading branch information
Takalele authored Apr 27, 2024
1 parent a06d732 commit 0060ffb
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 53 deletions.
3 changes: 1 addition & 2 deletions openwrt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ IMAGE_GLOB=*.img
# openwrt-14.07-x86-kvm_guest-combined-ext4.img
# openwrt-15.05.1-x86-kvm_guest-combined-ext4.img
# openwrt-15.05-x86-kvm_guest-combined-ext4.img
VERSION=$(shell echo $(IMAGE) | sed -e 's/openwrt-\([0-9][0-9]\.[0-9][0-9]\(\.[0-9]\+\)\?\)-.*/\1/')
VERSION=$(shell echo $(IMAGE) | sed -E 's/openwrt-([0-9]{1,2}.[0-9]{1,2}|[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2})-.*/\1/')

-include ../makefile-sanity.include
-include ../makefile.include

download:
python3 download.py
for F in `ls *.img.gz`; do gunzip -f $$F; done

build: download
$(MAKE) docker-image
37 changes: 34 additions & 3 deletions openwrt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repository and build them into vrnetlab docker images. `build` consists of the

Use `make download` to automatically download images from the public OpenWRT
image repository at https://downloads.openwrt.org. The download script will get
everything that has a two-digit major version, e.g. 12.09, 14.07, 15.05 etc.
everything major and minor version, e.g. 12.09, 14.07, 15.05, 23.05.3 etc.

You can also download images manually by navigating to
https://downloads.openwrt.org/ and grabbing the file. You have to gunzip it.
Expand All @@ -26,12 +26,34 @@ As per OpenWRT defaults, `br-lan`(`eth0`) is the LAN interface and `eth1` the
WAN interface.

Tested booting and responding to SSH:
* openwrt-15.05-x86-kvm_guest-combined-ext4.img MD5:3d9b51a7e0cd728137318989a9fd35fb
* openwrt-23.05.3-x86-64-generic-ext4-combined.img 818f6ba04103915ad53f2d003c42aa84
* openwrt-15.05.1-x86-64-combined-ext4.img MD5:307d8cdb11faeb1b5e27fe55078bd152

Usage
-----
```
docker run -d --privileged --name openwrt1 vr-openwrt:15.05
docker run -d --privileged --name openwrt1 vr-openwrt:23.05.3
```

Usage containerlab
-----
```
name: openwrt
topology:
nodes:
openwrt:
kind: linux
image: vrnetlab/vr-openwrt:23.05.3
mgmt-ipv4: 172.20.20.12
mgmt_ipv6: 2001:172:20:20::12
ports:
- 8080:80
- 8443:443
env:
USERNAME: root #(default)
PASSWORD: mypassword #(default is VR-netlab9)
CONNECTION_MODE: tc #(default)
```

System requirements
Expand All @@ -47,3 +69,12 @@ FAQ - Frequently or Unfrequently Asked Questions
##### Q: Has this been extensively tested?
A: Nope. It starts and you can connect to it. Take it for a spin and provide
some feedback :-)
##### Q: How to delete all openwrt docker images?
```
docker rmi $(docker images --quiet --filter reference=vrnetlab/vr-openwrt)
```
##### Q: Why are new installed luci-proto not showing up?
A: you need to reload the network process
```
/etc/init.d/network restart
```
30 changes: 17 additions & 13 deletions openwrt/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
FROM debian:stretch
MAINTAINER Kristian Larsson <kristian@spritelink.net>
FROM alpine:3.18
MAINTAINER Andreas Cymbal takalele@konnex.me

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update -qy \
&& apt-get upgrade -qy \
&& apt-get install -y \
bridge-utils \
iproute2 \
python3-ipy \
RUN apk add --no-cache bash \
qemu-system-x86_64 \
qemu-img \
socat \
qemu-kvm \
&& rm -rf /var/lib/apt/lists/*
net-tools \
iproute2 \
bridge-utils \
python3 \
py3-click \
nano \
vim \
py3-pip && ln -sf python3 /usr/bin/python

RUN pip3 install --no-cache --upgrade pip setuptools
RUN pip install IPy

ARG IMAGE
COPY $IMAGE* /
COPY *.py /

EXPOSE 22 161/udp 80 830 5000 10000-10099
HEALTHCHECK CMD ["/healthcheck.py"]
ENTRYPOINT ["/launch.py"]
ENTRYPOINT ["/launch.py"]
71 changes: 50 additions & 21 deletions openwrt/docker/launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ def trace(self, message, *args, **kws):
logging.Logger.trace = trace

class OpenWRT_vm(vrnetlab.VM):
def __init__(self, username, password):
def __init__(self, username, password, conn_mode, hostname, lan_ip, lan_netmask):
for e in os.listdir("/"):
if re.search(".img$", e):
disk_image = "/" + e
super(OpenWRT_vm, self).__init__(username, password, disk_image=disk_image, ram=128)
self.nic_type = "virtio-net-pci"
self.num_nics = 1
self.conn_mode=conn_mode
self.hostname=hostname
self.lan_ip=lan_ip
self.lan_netmask=lan_netmask

def bootstrap_spin(self):
""" This function should be called periodically to do work.
Expand Down Expand Up @@ -80,7 +84,7 @@ def bootstrap_config(self):
# Get a prompt
self.wait_write("\r", None)
# Configure interface
self.wait_write("ifconfig br-lan 10.0.0.15 netmask 255.255.255.0", "#")
self.wait_write("ifconfig br-lan " + self.lan_ip + " netmask " + self.lan_netmask, "#")
# Set root password (ssh login prerequisite)
self.wait_write("passwd", "#")
self.wait_write(self.password, "New password:")
Expand All @@ -96,28 +100,53 @@ def bootstrap_config(self):
# Create home dir
self.wait_write("mkdir -p /home/%s" %(self.username))
self.wait_write("chown %s /home/%s" %(self.username, self.username))
self.wait_write("chown %s /etc/config/ -R" %(self.username))
self.logger.info("completed bootstrap configuration")

class OpenWRT(vrnetlab.VR):
def __init__(self, username, password):
def __init__(self, username, password, conn_mode, hostname, lan_ip, lan_netmask):
super(OpenWRT, self).__init__(username, password)
self.vms = [ OpenWRT_vm(username, password) ]
self.vms = [ OpenWRT_vm(username, password, conn_mode, hostname, lan_ip, lan_netmask) ]

import click
@click.command()
@click.option('--tracing', is_flag=True, help='enable trace level logging')
@click.option('--username','-u', default='root', envvar='USERNAME', required=True, help="Username")
@click.option('--password','-p', default='VR-netlab9', envvar='PASSWORD', required=True, help="Password")
@click.option('--connection-mode','-c', default='tc', envvar='CONNECTION_MODE', required=True, help="connection mode")
@click.option('--hostname','-h', default='OpenWRT', envvar='HOSTNAME', required=True, help="Hostname")
@click.option('--lan-ip','-ip', default='10.0.0.15', envvar='LAN_IP', required=True, help="Lan IP")
@click.option('--lan-netmask','-mask', default='255.255.255.0', envvar='LAN_NETMASK', required=True, help="Lan netmask")

def args(tracing,username,password,connection_mode,hostname,lan_ip,lan_netmask):
LOG_FORMAT = "%(asctime)s: %(module)-10s %(levelname)-8s %(message)s"
logging.basicConfig(format=LOG_FORMAT)
logger = logging.getLogger()

logger.setLevel(logging.DEBUG)
if tracing:
logger.setLevel(1)

vr = OpenWRT(username, password, connection_mode, hostname, lan_ip, lan_netmask)
vr.start()

if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('--trace', action='store_true', help='enable trace level logging')
parser.add_argument('--username', default='vrnetlab', help='Username')
parser.add_argument('--password', default='VR-netlab9', help='Password')
args = parser.parse_args()

LOG_FORMAT = "%(asctime)s: %(module)-10s %(levelname)-8s %(message)s"
logging.basicConfig(format=LOG_FORMAT)
logger = logging.getLogger()

logger.setLevel(logging.DEBUG)
if args.trace:
logger.setLevel(1)

vr = OpenWRT(args.username, args.password)
vr.start()
args()
# import argparse
# parser = argparse.ArgumentParser(description='')
# parser.add_argument('--trace', action='store_true', help='enable trace level logging')
# parser.add_argument('--username', default='vrnetlab', help='Username')
# parser.add_argument('--password', default='VR-netlab9', help='Password')
# parser.add_argument(
# "--connection-mode",
# default="vrxcon",
# help="Connection mode to use in the datapath",
# )
# args = parser.parse_args()







55 changes: 41 additions & 14 deletions openwrt/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import re
import shutil
import sys
import os
import gzip

import requests
from bs4 import BeautifulSoup
from bs4 import BeautifulSoup, Tag

base_url = "https://downloads.openwrt.org/"

Expand All @@ -16,19 +19,40 @@ def get_rel(url, version):
soup = BeautifulSoup(c, "lxml")
links = soup.find_all("a")
for l in links:
filename = l.string.strip()
if not re.search('combined-ext4.img.gz', filename):
#print(l)

#filename = l.string.strip()
filename = l['href']
if not (re.search('combined-ext4.img.gz', filename) or re.search('generic-ext4-combined.img.gz', filename)):
#print("ignoring {}".format(filename))
continue
if re.search('^openwrt-x86-', filename):
local_filename = re.sub('^openwrt-x86-', 'openwrt-{}-x86-'.format(version), filename)
else:
local_filename = "openwrt-{}-x86-kvm_guest-{}".format(version, filename)
file_url = "{}{}".format(url, filename)
print("Downloading {} -> {}".format(file_url, local_filename))
r = requests.get(file_url, stream=True)
with open(local_filename, 'wb') as f:
shutil.copyfileobj(r.raw, f)
if not os.path.exists(filename):
print("Downloading {} -> {}".format(file_url, filename))
r = requests.get(file_url, stream=True)
print(filename)
base_name, file_extension = os.path.splitext(filename)
if file_extension == ".gz":
output_file = base_name
print(output_file)
with open(filename, 'wb') as f:
shutil.copyfileobj(r.raw, f)
try:
with gzip.open(filename, 'rb') as f_in:
with open(output_file, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
print(f"The file was successfully unpacked: {output_file}")
except gzip.BadGzipFile:
if not os.path.exists(output_file):
print(f"Warning: The file '{filename}' is not a valid GZIP file and could not be unpacked.")
else:
print(f"gzip: {filename}: decompression OK, trailing garbage ignored. ")
except Exception as e:
print(f"Error unpacking the file '{filename}': {e}")
else:
print("File '{}' already exists. Skipping download.".format(filename))


def main():
Expand All @@ -39,15 +63,18 @@ def main():
soup = BeautifulSoup(c, "lxml")
links = soup.find_all("a")
for l in links:
m = re.search('^http(s|):\/\/', l.attrs['href'])
m = re.search('\/\/', l.attrs['href'])
if not m:
rel_url = "{}{}x86/kvm_guest/".format(base_url, l.attrs['href'])
rel_url = "{}{}x86/64/".format(base_url, l.attrs['href'])
else:
rel_url = "{}x86/kvm_guest/".format(l.attrs['href'])
m = re.search('[^0-9]([0-9]{2}\.[0-9]{2})[^0-9]', l.attrs['href'])
current_href = l['href']
new_href = 'https:' + current_href
l['href'] = new_href
rel_url = "{}x86/64/".format(l.attrs['href'])
m = re.search('[^0-9]([0-9]{2}\.[0-9]{2}[^0-9](?:[0-9]{1,2}))|[^0-9]([0-9]{2}\.[0-9]{2})', l.attrs['href'])
if not m:
continue
print(l.string.strip(), l.attrs['href'], rel_url)
#print(l.string.strip(), l.attrs['href'], rel_url)
get_rel(rel_url, m.group(1))


Expand Down

0 comments on commit 0060ffb

Please sign in to comment.