Two stage build to reduce image size and build improvements provided by @imrehg.

Add (optional) metering support for use with Prometheus.
This commit is contained in:
Jac Kersing 2018-02-12 18:32:11 +01:00
parent e40d71b4a8
commit 2922f63a85
8 changed files with 125 additions and 38 deletions

View File

@ -1,18 +1,29 @@
FROM resin/%%RESIN_MACHINE_NAME%%-buildpack-deps FROM resin/%%RESIN_MACHINE_NAME%%-debian:latest AS buildstep
# Enable systemd, as Resin requires this
ENV INITSYSTEM on
# Make the hardware type available as a runtime env var
ENV RESIN_ARCH %%RESIN_ARCH%%
ENV RESIN_MACHINE_NAME %%RESIN_MACHINE_NAME%%
# Copy the build and run environment
COPY . /opt/ttn-gateway/
WORKDIR /opt/ttn-gateway/ WORKDIR /opt/ttn-gateway/
# Build the gateway (or comment this out if debugging on-device) # downloading utils
RUN ./dev/build.sh && rm -rf ./dev RUN apt-get update && \
apt-get install wget build-essential libc6-dev git pkg-config protobuf-compiler libprotobuf-dev libprotoc-dev automake libtool autoconf python-dev python-rpi.gpio
# Start it up COPY dev dev
CMD ["sh", "-c", "./run.py"] RUN ./dev/build.sh
FROM resin/%%RESIN_MACHINE_NAME%%-debian:latest
WORKDIR /opt/ttn-gateway
RUN apt-get update && \
apt-get install python-rpi.gpio && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
COPY --from=buildstep /opt/ttn-gateway/mp_pkt_fwd .
COPY --from=buildstep /usr/local/lib/libpaho-embed-* /usr/lib/
COPY --from=buildstep /usr/lib/libttn* /usr/lib/
COPY run.py ./
COPY start.sh ./
# run when container lands on device
CMD ["bash", "start.sh"]

View File

@ -0,0 +1,58 @@
FROM resin/%%RESIN_MACHINE_NAME%%-debian:latest AS buildstep
# downloading utils
RUN apt-get update && \
apt-get install wget build-essential libc6-dev git pkg-config protobuf-compiler libprotobuf-dev libprotoc-dev automake libtool autoconf python-dev python-rpi.gpio
WORKDIR /etc
# versions
ENV NODE_EXPORTER_VERSION 0.12.0
ENV DIST_ARCH linux-armv7
RUN wget https://github.com/prometheus/node_exporter/releases/download/${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.${DIST_ARCH}.tar.gz \
&& tar xvfz node_exporter-${NODE_EXPORTER_VERSION}.${DIST_ARCH}.tar.gz \
&& rm node_exporter-${NODE_EXPORTER_VERSION}.${DIST_ARCH}.tar.gz
COPY gwexporter.tgz /opt/ttn-gateway/gwexporter.tgz
WORKDIR /opt/gwexporter
RUN tar xvzf /opt/ttn-gateway/gwexporter.tgz
RUN wget https://nodejs.org/dist/v8.8.1/node-v8.8.1-linux-armv6l.tar.gz \
&& tar xvzf node-v8.8.1-linux-armv6l.tar.gz \
&& mv node-v8.8.1-linux-armv6l/* . \
&& rm -rf node-v8.8.1-linux-armv6l
WORKDIR /opt/ttn-gateway/
COPY dev dev
RUN ./dev/build.sh
FROM resin/%%RESIN_MACHINE_NAME%%-debian:latest
RUN apt-get update && \
apt-get install python-rpi.gpio && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Enable systemd
ENV INITSYSTEM on
# versions
ENV NODE_EXPORTER_VERSION 0.12.0
ENV DIST_ARCH linux-armv7
WORKDIR /etc
COPY --from=buildstep /etc/node_exporter-${NODE_EXPORTER_VERSION}.${DIST_ARCH} .
WORKDIR /opt/gwexporter
COPY --from=buildstep /opt/gwexporter .
WORKDIR /opt/ttn-gateway
COPY --from=buildstep /opt/ttn-gateway/mp_pkt_fwd .
COPY --from=buildstep /usr/local/lib/libpaho-embed-* /usr/lib/
COPY --from=buildstep /usr/lib/libttn* /usr/lib/
COPY run.py run.py
WORKDIR /
COPY start.sh.metering start.sh
# run when container lands on device
CMD ["bash", "start.sh"]

View File

@ -14,6 +14,7 @@ Currently any Raspberry Pi with one of the following gateway boards, communicati
* [IMST iC880A-SPI](http://webshop.imst.de/ic880a-spi-lorawan-concentrator-868mhz.html). Preferable configured as described [by TTN-ZH](https://github.com/ttn-zh/ic880a-gateway/wiki). You **do not** need to follow the **Setting up the software** step, as the setup scripts in this repository does it for you. * [IMST iC880A-SPI](http://webshop.imst.de/ic880a-spi-lorawan-concentrator-868mhz.html). Preferable configured as described [by TTN-ZH](https://github.com/ttn-zh/ic880a-gateway/wiki). You **do not** need to follow the **Setting up the software** step, as the setup scripts in this repository does it for you.
* [LinkLabs Raspberry Pi "Hat"](http://link-labs.myshopify.com/products/lorawan-raspberry-pi-board) * [LinkLabs Raspberry Pi "Hat"](http://link-labs.myshopify.com/products/lorawan-raspberry-pi-board)
* [RisingHF IoT Dicovery](http://www.risinghf.com/product/risinghf-iot-dicovery/?lang=en) * [RisingHF IoT Dicovery](http://www.risinghf.com/product/risinghf-iot-dicovery/?lang=en)
* [RAK831](http://www.rakwireless.com/en/WisKeyOSH/RAK831)
## Prerequisites ## Prerequisites
@ -37,7 +38,7 @@ For a more complete list of possible environment variables, see [CONFIGURATION](
### Device environment variables - no GPS ### Device environment variables - no GPS
For example, for an IMST iC880A with no GPS, the MINIMUM environment variables that you should configure at this screen should look something like this: For example, for an IMST iC880A or RAK831 with no GPS, the MINIMUM environment variables that you should configure at this screen should look something like this:
Name | Value Name | Value
------------------|-------------------------- ------------------|--------------------------
@ -47,7 +48,7 @@ GW_ID | The gateway ID from the TTN console
GW_KEY | The gateway KEY from the TTN console GW_KEY | The gateway KEY from the TTN console
GW_RESET_PIN | 22 (optional) GW_RESET_PIN | 22 (optional)
GW_RESET_PIN can be left out if you are using Gonzalo Casas' backplane board, or any other setup using pin 22 as reset pin. This is because pin 22 is the default reset pin used by this resin.io setup. GW_RESET_PIN can be left out if you are using Gonzalo Casas' backplane board, the RAK backplane for the RAK831, or any other setup using pin 22 as reset pin. This is because pin 22 is the default reset pin used by this resin.io setup.
### Device environment variables - with GPS ### Device environment variables - with GPS
@ -77,6 +78,7 @@ Linklabs Rasberry Pi Hat<br />https://www.amazon.co.uk/868-MHz-LoRaWAN-RPi-Shiel
Rising HF Board<br />http://www.risinghf.com/product/risinghf-iot-dicovery/?lang=en | 26 Rising HF Board<br />http://www.risinghf.com/product/risinghf-iot-dicovery/?lang=en | 26
IMST backplane or Lite gateway<br />https://wireless-solutions.de/products/long-range-radio/lora_lite_gateway.html | 29 (untested) IMST backplane or Lite gateway<br />https://wireless-solutions.de/products/long-range-radio/lora_lite_gateway.html | 29 (untested)
Coredump backplane<br />https://github.com/dbrgn/ic880a-backplane/<br />https://shop.coredump.ch/product/ic880a-lorawan-gateway-backplane/ | 22 Coredump backplane<br />https://github.com/dbrgn/ic880a-backplane/<br />https://shop.coredump.ch/product/ic880a-lorawan-gateway-backplane/ | 22
RAK backplane<br /> | 11
If you get the message If you get the message
@ -84,7 +86,7 @@ If you get the message
after resin.io is finished downloading the application, or when restarting the gateway, it most likely means the `GW_RESET_PIN` you defined is incorrect. Alternatively the problem can be caused by the hardware, typically for the `IMST iC880A-SPI` board with insufficient voltage, try another power supply or slightly increase the voltage. after resin.io is finished downloading the application, or when restarting the gateway, it most likely means the `GW_RESET_PIN` you defined is incorrect. Alternatively the problem can be caused by the hardware, typically for the `IMST iC880A-SPI` board with insufficient voltage, try another power supply or slightly increase the voltage.
## Special note for using the LinkLabs gateway on a Raspberry Pi 3 ## Special note for using a Raspberry Pi 3
There is a backward incomatibility between the Raspberry Pi 1 and 2 hardware, and Raspberry Pi 3. For Raspberry Pi 3, it is necessary to make a small additional configuration change. There is a backward incomatibility between the Raspberry Pi 1 and 2 hardware, and Raspberry Pi 3. For Raspberry Pi 3, it is necessary to make a small additional configuration change.
@ -156,11 +158,22 @@ If you get the error below please check if your ssh public key has been added to
``` ```
git add . git add .
git commit -m "Updated gateway version" git commit -m "Updated gateway version"
git push -f resin master" git push -f resin master
``` ```
- For devices without a GPS, the location that is configured on the TTN console is used. This location is only read at startup of the gateway. Therefore, after you set or changed the location, restart the application from the resin.io console. - For devices without a GPS, the location that is configured on the TTN console is used. This location is only read at startup of the gateway. Therefore, after you set or changed the location, restart the application from the resin.io console.
# Device statistics
If you want to show nice looking statistics for your gateway(s) there are a couple of additional steps to take. First,
copy Dockerfile.template.metering to Dockerfile.template . Next copy start.sh.metering to start.sh . Now use the instructions above to
update the resin image.
Once the new image is deployed, go to the resin.io dashboard for your devices and select 'Enable Public device URL' in the drop down menu
(the one to the right of the light bulb). That is all that is required to provide metrics. Now you will need to install a metrics collector
on a seperate system as outlined in [Fleet-wide Machine Metrics Monitoring in 20mins](https://resin.io/blog/prometheusv2/)
(To show packet forwarder graphs you need to add your own graphs to the provided templates)
# Credits # Credits
* [Gonzalo Casas](https://github.com/gonzalocasas) on the [iC880a-based gateway](https://github.com/ttn-zh/ic880a-gateway/tree/spi) * [Gonzalo Casas](https://github.com/gonzalocasas) on the [iC880a-based gateway](https://github.com/ttn-zh/ic880a-gateway/tree/spi)

View File

@ -5,17 +5,6 @@ INSTALL_DIR="/opt/ttn-gateway"
mkdir -p $INSTALL_DIR/dev mkdir -p $INSTALL_DIR/dev
cd $INSTALL_DIR/dev cd $INSTALL_DIR/dev
if [ ! -d wiringPi ]; then
git clone git://git.drogon.net/wiringPi || { echo 'Cloning wiringPi failed.' ; exit 1; }
cd wiringPi
else
cd wiringPi
git reset --hard
git pull
fi
./build
cd ..
if [ ! -d lora_gateway ]; then if [ ! -d lora_gateway ]; then
git clone https://github.com/kersing/lora_gateway.git || { echo 'Cloning lora_gateway failed.' ; exit 1; } git clone https://github.com/kersing/lora_gateway.git || { echo 'Cloning lora_gateway failed.' ; exit 1; }
else else
@ -70,13 +59,10 @@ else
cd .. cd ..
fi fi
apt-get update
apt-get -y install protobuf-compiler libprotobuf-dev libprotoc-dev automake libtool autoconf python-dev python-rpi.gpio
cd $INSTALL_DIR/dev/lora_gateway/libloragw cd $INSTALL_DIR/dev/lora_gateway/libloragw
sed -i -e 's/PLATFORM= .*$/PLATFORM= imst_rpi/g' library.cfg sed -i -e 's/PLATFORM= .*$/PLATFORM= imst_rpi/g' library.cfg
sed -i -e 's/CFG_SPI= .*$/CFG_SPI= native/g' library.cfg sed -i -e 's/CFG_SPI= .*$/CFG_SPI= native/g' library.cfg
make make -j$(nproc)
cd $INSTALL_DIR/dev/protobuf-c cd $INSTALL_DIR/dev/protobuf-c
./autogen.sh ./autogen.sh
@ -92,11 +78,11 @@ make install
cd $INSTALL_DIR/dev/ttn-gateway-connector cd $INSTALL_DIR/dev/ttn-gateway-connector
cp config.mk.in config.mk cp config.mk.in config.mk
make make -j$(nproc)
cp bin/libttn-gateway-connector.so /usr/lib/ cp bin/libttn-gateway-connector.so /usr/lib/
cd $INSTALL_DIR/dev/packet_forwarder/mp_pkt_fwd/ cd $INSTALL_DIR/dev/packet_forwarder/mp_pkt_fwd/
make make -j$(nproc)
# Copy things needed at runtime to where they'll be expected # Copy things needed at runtime to where they'll be expected
cp $INSTALL_DIR/dev/packet_forwarder/mp_pkt_fwd/mp_pkt_fwd $INSTALL_DIR/mp_pkt_fwd cp $INSTALL_DIR/dev/packet_forwarder/mp_pkt_fwd/mp_pkt_fwd $INSTALL_DIR/mp_pkt_fwd

BIN
gwexporter.tgz Normal file

Binary file not shown.

7
run.py
View File

@ -23,7 +23,7 @@ except RuntimeError:
GWID_PREFIX="FFFE" GWID_PREFIX="FFFE"
if not os.path.exists("mp_pkt_fwd"): if not os.path.exists("/opt/ttn-gateway/mp_pkt_fwd"):
print ("ERROR: gateway executable not found. Is it built yet?") print ("ERROR: gateway executable not found. Is it built yet?")
sys.exit(0) sys.exit(0)
@ -172,6 +172,7 @@ gateway_conf = {}
gateway_conf['gateway_ID'] = my_eui gateway_conf['gateway_ID'] = my_eui
gateway_conf['contact_email'] = os.getenv('GW_CONTACT_EMAIL', "") gateway_conf['contact_email'] = os.getenv('GW_CONTACT_EMAIL', "")
gateway_conf['description'] = description gateway_conf['description'] = description
gateway_conf['stat_file'] = 'loragwstat.json'
if(os.getenv('GW_FWD_CRC_ERR', "false")=="true"): if(os.getenv('GW_FWD_CRC_ERR', "false")=="true"):
#default is False #default is False
@ -291,7 +292,7 @@ if(os.getenv('SERVER_3_ENABLED', "false")=="true"):
# We merge the json objects from the global_conf and local_conf and save it to the global_conf. # We merge the json objects from the global_conf and local_conf and save it to the global_conf.
# Therefore there will not be a local_conf.json file. # Therefore there will not be a local_conf.json file.
local_conf = {'SX1301_conf': sx1301_conf, 'gateway_conf': gateway_conf} local_conf = {'SX1301_conf': sx1301_conf, 'gateway_conf': gateway_conf}
with open('global_conf.json', 'w') as the_file: with open('/opt/ttn-gateway/global_conf.json', 'w') as the_file:
the_file.write(json.dumps(local_conf, indent=4)) the_file.write(json.dumps(local_conf, indent=4))
@ -332,5 +333,5 @@ while True:
GPIO.cleanup(22) GPIO.cleanup(22)
# Start forwarder # Start forwarder
subprocess.call(["./mp_pkt_fwd"]) subprocess.call("/opt/ttn-gateway/mp_pkt_fwd -c /opt/ttn-gateway", shell=True)
time.sleep(15) time.sleep(15)

3
start.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/bash
python /opt/ttn-gateway/run.py

15
start.sh.metering Normal file
View File

@ -0,0 +1,15 @@
#!/bin/bash
# Start the node exporter
mkdir /mnt/ramdisk
mount -t tmpfs -o size=8m tmpfs /mnt/ramdisk
cd /mnt/ramdisk
/opt/ttn-gateway/run.py &
# WORKAROUND: Add symlink, as gwexporter otherwise currently don't seem to find this file
ln -s /mnt/ramdisk/loragwstat.json /opt/gwexporter/loragwstat.json
export PATH=$PATH:/opt/gwexporter/bin
node /opt/gwexporter/gwexporter.js &
cd /etc && ./node_exporter -web.listen-address ":81"