Skip to content

Commit 0060ffb

Browse files
authored
Fixed OpenWRT (#190)
* 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
1 parent a06d732 commit 0060ffb

File tree

5 files changed

+143
-53
lines changed

5 files changed

+143
-53
lines changed

openwrt/Makefile

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ IMAGE_GLOB=*.img
88
# openwrt-14.07-x86-kvm_guest-combined-ext4.img
99
# openwrt-15.05.1-x86-kvm_guest-combined-ext4.img
1010
# openwrt-15.05-x86-kvm_guest-combined-ext4.img
11-
VERSION=$(shell echo $(IMAGE) | sed -e 's/openwrt-\([0-9][0-9]\.[0-9][0-9]\(\.[0-9]\+\)\?\)-.*/\1/')
11+
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/')
1212

1313
-include ../makefile-sanity.include
1414
-include ../makefile.include
1515

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

2019
build: download
2120
$(MAKE) docker-image

openwrt/README.md

+34-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ repository and build them into vrnetlab docker images. `build` consists of the
1010

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

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

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

3132
Usage
3233
-----
3334
```
34-
docker run -d --privileged --name openwrt1 vr-openwrt:15.05
35+
docker run -d --privileged --name openwrt1 vr-openwrt:23.05.3
36+
```
37+
38+
Usage containerlab
39+
-----
40+
```
41+
name: openwrt
42+
43+
topology:
44+
nodes:
45+
openwrt:
46+
kind: linux
47+
image: vrnetlab/vr-openwrt:23.05.3
48+
mgmt-ipv4: 172.20.20.12
49+
mgmt_ipv6: 2001:172:20:20::12
50+
ports:
51+
- 8080:80
52+
- 8443:443
53+
env:
54+
USERNAME: root #(default)
55+
PASSWORD: mypassword #(default is VR-netlab9)
56+
CONNECTION_MODE: tc #(default)
3557
```
3658

3759
System requirements
@@ -47,3 +69,12 @@ FAQ - Frequently or Unfrequently Asked Questions
4769
##### Q: Has this been extensively tested?
4870
A: Nope. It starts and you can connect to it. Take it for a spin and provide
4971
some feedback :-)
72+
##### Q: How to delete all openwrt docker images?
73+
```
74+
docker rmi $(docker images --quiet --filter reference=vrnetlab/vr-openwrt)
75+
```
76+
##### Q: Why are new installed luci-proto not showing up?
77+
A: you need to reload the network process
78+
```
79+
/etc/init.d/network restart
80+
```

openwrt/docker/Dockerfile

+17-13
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
1-
FROM debian:stretch
2-
MAINTAINER Kristian Larsson <[email protected]>
1+
FROM alpine:3.18
2+
MAINTAINER Andreas Cymbal [email protected]
33

4-
ENV DEBIAN_FRONTEND=noninteractive
5-
6-
RUN apt-get update -qy \
7-
&& apt-get upgrade -qy \
8-
&& apt-get install -y \
9-
bridge-utils \
10-
iproute2 \
11-
python3-ipy \
4+
RUN apk add --no-cache bash \
5+
qemu-system-x86_64 \
6+
qemu-img \
127
socat \
13-
qemu-kvm \
14-
&& rm -rf /var/lib/apt/lists/*
8+
net-tools \
9+
iproute2 \
10+
bridge-utils \
11+
python3 \
12+
py3-click \
13+
nano \
14+
vim \
15+
py3-pip && ln -sf python3 /usr/bin/python
16+
17+
RUN pip3 install --no-cache --upgrade pip setuptools
18+
RUN pip install IPy
1519

1620
ARG IMAGE
1721
COPY $IMAGE* /
1822
COPY *.py /
1923

2024
EXPOSE 22 161/udp 80 830 5000 10000-10099
2125
HEALTHCHECK CMD ["/healthcheck.py"]
22-
ENTRYPOINT ["/launch.py"]
26+
ENTRYPOINT ["/launch.py"]

openwrt/docker/launch.py

+50-21
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ def trace(self, message, *args, **kws):
2929
logging.Logger.trace = trace
3030

3131
class OpenWRT_vm(vrnetlab.VM):
32-
def __init__(self, username, password):
32+
def __init__(self, username, password, conn_mode, hostname, lan_ip, lan_netmask):
3333
for e in os.listdir("/"):
3434
if re.search(".img$", e):
3535
disk_image = "/" + e
3636
super(OpenWRT_vm, self).__init__(username, password, disk_image=disk_image, ram=128)
3737
self.nic_type = "virtio-net-pci"
3838
self.num_nics = 1
39+
self.conn_mode=conn_mode
40+
self.hostname=hostname
41+
self.lan_ip=lan_ip
42+
self.lan_netmask=lan_netmask
3943

4044
def bootstrap_spin(self):
4145
""" This function should be called periodically to do work.
@@ -80,7 +84,7 @@ def bootstrap_config(self):
8084
# Get a prompt
8185
self.wait_write("\r", None)
8286
# Configure interface
83-
self.wait_write("ifconfig br-lan 10.0.0.15 netmask 255.255.255.0", "#")
87+
self.wait_write("ifconfig br-lan " + self.lan_ip + " netmask " + self.lan_netmask, "#")
8488
# Set root password (ssh login prerequisite)
8589
self.wait_write("passwd", "#")
8690
self.wait_write(self.password, "New password:")
@@ -96,28 +100,53 @@ def bootstrap_config(self):
96100
# Create home dir
97101
self.wait_write("mkdir -p /home/%s" %(self.username))
98102
self.wait_write("chown %s /home/%s" %(self.username, self.username))
103+
self.wait_write("chown %s /etc/config/ -R" %(self.username))
99104
self.logger.info("completed bootstrap configuration")
100105

101106
class OpenWRT(vrnetlab.VR):
102-
def __init__(self, username, password):
107+
def __init__(self, username, password, conn_mode, hostname, lan_ip, lan_netmask):
103108
super(OpenWRT, self).__init__(username, password)
104-
self.vms = [ OpenWRT_vm(username, password) ]
109+
self.vms = [ OpenWRT_vm(username, password, conn_mode, hostname, lan_ip, lan_netmask) ]
110+
111+
import click
112+
@click.command()
113+
@click.option('--tracing', is_flag=True, help='enable trace level logging')
114+
@click.option('--username','-u', default='root', envvar='USERNAME', required=True, help="Username")
115+
@click.option('--password','-p', default='VR-netlab9', envvar='PASSWORD', required=True, help="Password")
116+
@click.option('--connection-mode','-c', default='tc', envvar='CONNECTION_MODE', required=True, help="connection mode")
117+
@click.option('--hostname','-h', default='OpenWRT', envvar='HOSTNAME', required=True, help="Hostname")
118+
@click.option('--lan-ip','-ip', default='10.0.0.15', envvar='LAN_IP', required=True, help="Lan IP")
119+
@click.option('--lan-netmask','-mask', default='255.255.255.0', envvar='LAN_NETMASK', required=True, help="Lan netmask")
120+
121+
def args(tracing,username,password,connection_mode,hostname,lan_ip,lan_netmask):
122+
LOG_FORMAT = "%(asctime)s: %(module)-10s %(levelname)-8s %(message)s"
123+
logging.basicConfig(format=LOG_FORMAT)
124+
logger = logging.getLogger()
125+
126+
logger.setLevel(logging.DEBUG)
127+
if tracing:
128+
logger.setLevel(1)
129+
130+
vr = OpenWRT(username, password, connection_mode, hostname, lan_ip, lan_netmask)
131+
vr.start()
105132

106133
if __name__ == '__main__':
107-
import argparse
108-
parser = argparse.ArgumentParser(description='')
109-
parser.add_argument('--trace', action='store_true', help='enable trace level logging')
110-
parser.add_argument('--username', default='vrnetlab', help='Username')
111-
parser.add_argument('--password', default='VR-netlab9', help='Password')
112-
args = parser.parse_args()
113-
114-
LOG_FORMAT = "%(asctime)s: %(module)-10s %(levelname)-8s %(message)s"
115-
logging.basicConfig(format=LOG_FORMAT)
116-
logger = logging.getLogger()
117-
118-
logger.setLevel(logging.DEBUG)
119-
if args.trace:
120-
logger.setLevel(1)
121-
122-
vr = OpenWRT(args.username, args.password)
123-
vr.start()
134+
args()
135+
# import argparse
136+
# parser = argparse.ArgumentParser(description='')
137+
# parser.add_argument('--trace', action='store_true', help='enable trace level logging')
138+
# parser.add_argument('--username', default='vrnetlab', help='Username')
139+
# parser.add_argument('--password', default='VR-netlab9', help='Password')
140+
# parser.add_argument(
141+
# "--connection-mode",
142+
# default="vrxcon",
143+
# help="Connection mode to use in the datapath",
144+
# )
145+
# args = parser.parse_args()
146+
147+
148+
149+
150+
151+
152+

openwrt/download.py

+41-14
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
import re
44
import shutil
5+
import sys
6+
import os
7+
import gzip
58

69
import requests
7-
from bs4 import BeautifulSoup
10+
from bs4 import BeautifulSoup, Tag
811

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

@@ -16,19 +19,40 @@ def get_rel(url, version):
1619
soup = BeautifulSoup(c, "lxml")
1720
links = soup.find_all("a")
1821
for l in links:
19-
filename = l.string.strip()
20-
if not re.search('combined-ext4.img.gz', filename):
22+
#print(l)
23+
24+
#filename = l.string.strip()
25+
filename = l['href']
26+
if not (re.search('combined-ext4.img.gz', filename) or re.search('generic-ext4-combined.img.gz', filename)):
2127
#print("ignoring {}".format(filename))
2228
continue
2329
if re.search('^openwrt-x86-', filename):
2430
local_filename = re.sub('^openwrt-x86-', 'openwrt-{}-x86-'.format(version), filename)
25-
else:
26-
local_filename = "openwrt-{}-x86-kvm_guest-{}".format(version, filename)
2731
file_url = "{}{}".format(url, filename)
28-
print("Downloading {} -> {}".format(file_url, local_filename))
29-
r = requests.get(file_url, stream=True)
30-
with open(local_filename, 'wb') as f:
31-
shutil.copyfileobj(r.raw, f)
32+
if not os.path.exists(filename):
33+
print("Downloading {} -> {}".format(file_url, filename))
34+
r = requests.get(file_url, stream=True)
35+
print(filename)
36+
base_name, file_extension = os.path.splitext(filename)
37+
if file_extension == ".gz":
38+
output_file = base_name
39+
print(output_file)
40+
with open(filename, 'wb') as f:
41+
shutil.copyfileobj(r.raw, f)
42+
try:
43+
with gzip.open(filename, 'rb') as f_in:
44+
with open(output_file, 'wb') as f_out:
45+
shutil.copyfileobj(f_in, f_out)
46+
print(f"The file was successfully unpacked: {output_file}")
47+
except gzip.BadGzipFile:
48+
if not os.path.exists(output_file):
49+
print(f"Warning: The file '{filename}' is not a valid GZIP file and could not be unpacked.")
50+
else:
51+
print(f"gzip: {filename}: decompression OK, trailing garbage ignored. ")
52+
except Exception as e:
53+
print(f"Error unpacking the file '{filename}': {e}")
54+
else:
55+
print("File '{}' already exists. Skipping download.".format(filename))
3256

3357

3458
def main():
@@ -39,15 +63,18 @@ def main():
3963
soup = BeautifulSoup(c, "lxml")
4064
links = soup.find_all("a")
4165
for l in links:
42-
m = re.search('^http(s|):\/\/', l.attrs['href'])
66+
m = re.search('\/\/', l.attrs['href'])
4367
if not m:
44-
rel_url = "{}{}x86/kvm_guest/".format(base_url, l.attrs['href'])
68+
rel_url = "{}{}x86/64/".format(base_url, l.attrs['href'])
4569
else:
46-
rel_url = "{}x86/kvm_guest/".format(l.attrs['href'])
47-
m = re.search('[^0-9]([0-9]{2}\.[0-9]{2})[^0-9]', l.attrs['href'])
70+
current_href = l['href']
71+
new_href = 'https:' + current_href
72+
l['href'] = new_href
73+
rel_url = "{}x86/64/".format(l.attrs['href'])
74+
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'])
4875
if not m:
4976
continue
50-
print(l.string.strip(), l.attrs['href'], rel_url)
77+
#print(l.string.strip(), l.attrs['href'], rel_url)
5178
get_rel(rel_url, m.group(1))
5279

5380

0 commit comments

Comments
 (0)