Skip to content

Commit

Permalink
fix: updates to enable snap support
Browse files Browse the repository at this point in the history
- Add support for defining provision watcher directory
- Adding auto-scan script to snap
- Adding support for Consul token to auto-scan script
- Other minor changes

See also: edgexfoundry#52

Signed-off-by: Siggi Skulason <siggi.skulason@canonical.com>
  • Loading branch information
Siggi Skulason committed Feb 10, 2022
1 parent fdb8dc9 commit c7b3141
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 2 deletions.
3 changes: 3 additions & 0 deletions internal/driver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ type CustomConfig struct {
// MaxDiscoverDurationSeconds is the maximum amount of seconds for a discovery to run. It is important
// to have this configured in the case of larger subnets such as /16 and /8
MaxDiscoverDurationSeconds int

// Location of Provision Watchers
ProvisionWatcherDir string
}

// ServiceConfig a struct that wraps CustomConfig which holds the values for driver configuration
Expand Down
8 changes: 7 additions & 1 deletion internal/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ const (

// enable this by default, otherwise discovery will not work.
registerProvisionWatchers = true
provisionWatcherFolder = "res/provision_watchers"

// discoverDebounceDuration is the amount of time to wait for additional changes to discover
// configuration before auto-triggering a discovery
Expand Down Expand Up @@ -713,6 +712,13 @@ func getAddr(protocols protocolMap) (net.Addr, error) {
}

func (d *Driver) addProvisionWatchers() error {

provisionWatcherFolder := driver.config.AppCustom.ProvisionWatcherDir
if provisionWatcherFolder == "" {
provisionWatcherFolder = "res/provision_watchers"
}
d.lc.Infof("Adding provision watchers from %s", provisionWatcherFolder)

files, err := ioutil.ReadDir(provisionWatcherFolder)
if err != nil {
return err
Expand Down
28 changes: 28 additions & 0 deletions snap/local/hooks/cmd/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ func installConfig() error {
return nil
}

func installProvisionWatchers() error {
var err error

profs := [...]string{"impinj", "llrp"}

for _, v := range profs {
path := fmt.Sprintf("/config/device-rfid-llrp/res/provision_watchers/%s.provision.watcher.json", v)
destFile := hooks.SnapData + path
srcFile := hooks.Snap + path

if err := os.MkdirAll(filepath.Dir(destFile), 0755); err != nil {
return err
}

if err = hooks.CopyFile(srcFile, destFile); err != nil {
return err
}
}

return nil
}

func installDevices() error {
//No device files

Expand Down Expand Up @@ -101,4 +123,10 @@ func main() {
hooks.Error(fmt.Sprintf("edgex-device-rfid-llrp:install: %v", err))
os.Exit(1)
}

err = installProvisionWatchers()
if err != nil {
hooks.Error(fmt.Sprintf("edgex-device-rfid-llrp:install: %v", err))
os.Exit(1)
}
}
155 changes: 155 additions & 0 deletions snap/local/runtime-helpers/bin/auto-configure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/usr/bin/env bash

#
# Copyright (C) 2020-2021 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#

#
# The purpose of this script is to make it easier for an end user to configure LLRP device discovery
# without the need to have knowledge about subnets and/or CIDR format. The "DiscoverySubnets" config
# option defaults to blank in the configuration.toml file, and needs to be provided before a discovery can occur.
# This allows the LLRP device service to be run in a NAT-ed environment without host-mode networking because the subnet information
# is user-provided and does not rely on the device-rfid-llrp service to detect it.
#
# Essentially how this script works is it polls the machine it is running on and finds the active subnet for
# any and all network interfaces that are on the machine which are physical (non-virtual) and online.
# It uses this information to automatically fill out the "DiscoverySubnets" configuration option through Consul of a deployed
# device-rfid-llrp instance.
#
# NOTE 1: This script requires EdgeX Consul and the device-rfid-llrp service to have been run before this
# script will function.
#
# NOTE 2: If the "DiscoverySubnets" config is provided via "configuration.toml" this script does
# not need to be run.
#

set -eu

# If ran with DEBUG=1, enable bash command tracing
DEBUG=${DEBUG:-0}
if [ "${DEBUG}" == "1" ]; then
set -x
fi

# Snap-specific settings
# This script must run using snapcraft-runner, to set the shared libraries path correctly
# network-control and network-observe are required.
CURL=$SNAP/usr/bin/curl
CONSUL_TOKEN=$1


spacing=18; prev_line="\e[1A\e[$((spacing + 2))C"
green="\e[32m"; red="\e[31m"; clear="\e[0m"; bold="\e[1m"; normal="\e[22;24m"

trap 'err' ERR
err() {
echo -e "${red}${bold}Failed!${clear}"
exit 1
}

CONSUL_URL=${CONSUL_URL:-http://localhost:8500}
url="${CONSUL_URL}/v1/kv/edgex/devices/2.0/device-rfid-llrp/AppCustom/DiscoverySubnets"


### Dependencies Check
# Note: trailing ${red} is to colorize red all potential error output from the following commands
printf "${bold}%${spacing}s${clear}: ...\n${red}" "Dependencies Check"
if ! type -P curl >/dev/null; then
echo -e "${bold}${red}Failed!${normal} Please install ${bold}curl${normal} in order to use this script!${clear}"
exit 1
fi
echo -e "${prev_line}${green}Success${clear}"

### Consul Check
# Note: trailing ${red} is to colorize red all potential error output from the following commands
printf "${bold}%${spacing}s${clear}: ...\n${red}" "Consul Check"
echo "$CURL -X GET -H "X-Consul-Token:$CONSUL_TOKEN" -w "%{http_code}" -o /dev/null -s "${url}" || echo $?"
code=$($CURL -X GET -H "X-Consul-Token:$CONSUL_TOKEN" -w "%{http_code}" -o /dev/null -s "${url}" || echo $?)
if [ $((code)) -ne 200 ]; then
echo -e "${red}${bold}Failed!${normal} curl returned a status code of '${bold}$((code))'${normal}"
# Special message for error code 7
if [ $((code)) -eq 7 ]; then
echo -e "* Error code '7' denotes 'Failed to connect to host or proxy'"
fi
# Error 404 means it connected to consul but couldn't find the key
if [ $((code)) -eq 404 ]; then
echo -e "* Have you deployed the ${bold}device-rfid-llrp${normal} service?${clear}"
else
echo -e "* Is Consul deployed and accessible?${clear}"
fi
exit $((code))
fi
echo -e "${prev_line}${green}Success${clear}"

### Detect Interfaces
printf "${bold}%${spacing}s${clear}: ...\n${red}" "Interfaces"
# find all online non-virtual network interfaces and print them separated by `|` for regex matching.
# example output: eno1|eno2|eno3|...|
# note: a trailing '|' is produced which is removed in a later step
ifaces=$(
find /sys/class/net -mindepth 1 -maxdepth 2 `# list all network interfaces` \
-not -lname '*devices/virtual*' `# filter out all virtual interfaces` \
-execdir grep -q 'up' "{}/operstate" \; `# ensure interface is online (operstate == up)` \
-printf '%f|' `# print them separated by | for regex matching`
)
if [ -z "${ifaces}" ]; then
echo "Error, no online physical network interfaces detected.${clear}"
exit 1
fi
echo -e "${prev_line}${clear}${ifaces//|/ }"

### Detect Subnets
printf "${bold}%${spacing}s${clear}: ...\n${red}" "Subnets"
# print all ipv4 subnets, filter for just the ones associated with our physical interfaces,
# grab the unique ones and join them by commas
#
# sed -n followed by "s///p" means find and print (with replacements) only the lines containing a match
# '::-1' strips the last character (trailing |)
# 'eno1|eno2|' becomes "s/ dev (eno1|eno2).+//p"
# (eno1|eno2) is a matched group of possible values (| means OR)
# .+ is a catch all to prevent printing the rest of the line
#
# Example Input:
# 10.0.0.0/24 dev eno1 proto kernel src 10.0.0.212 metric 600
# 192.168.1.0/24 dev eno2 proto kernel src 192.168.1.134 metric 900
# 172.17.0.0/16 dev docker0 proto kernel src 172.17.0.1 linkdown
#
# Example Output:
# 10.0.0.0/24
# 192.168.1.0/24
#
# Explanation:
# - The first line matched the 'eno1' interface, so everything starting from " dev eno1 ..."
# is stripped out, and we are left with just the subnet (10.0.0.0/24).
# - The second line matched the 'eno2' interface, same process as before and we are left with just the subnet.
# - The third line does not match either interface and is not printed.

subnets=$(
# Print all IPv4 routes, one per line
ip -4 -o route list scope link |
# Regex match it against all of our online physical interfaces
sed -En "s/ dev (${ifaces::-1}).+//p" |
# Remove [link-local subnet](https://en.wikipedia.org/wiki/Link-local_address) using grep reverse match (-v)
grep -v "169.254.0.0/16" |
# Sort and remove potential duplicates
sort -u |
# Merge all lines into a single line separated by commas (no trailing ,)
paste -sd, -
)

if [ -z "${subnets}" ]; then
echo -e "Error, no subnets detected.${clear}"
exit 1
fi
echo -e "${prev_line}${clear}${subnets}"

### Configure Consul
printf "${bold}%${spacing}s${clear}: ...\n${red}" "Configure"
code=$(curl -X PUT -H "X-Consul-Token:$CONSUL_TOKEN" --data "${subnets}" -w "%{http_code}" -o /dev/null -s "${url}" || echo $?)
if [ $((code)) -ne 200 ]; then
echo -e "${red}${bold}Failed!${normal} curl returned a status code of '${bold}${code}'${clear}"
exit $((code))
fi
echo -e "${prev_line}${green}Success${clear}"
20 changes: 19 additions & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,29 @@ slots:
write: [$SNAP_DATA/device-rfid-llrp]

apps:
auto-configure:
adapter: none
command-chain:
- snap/command-chain/snapcraft-runner
command: bin/auto-configure.sh
plugs:
- network
- network-observe
- network-control

device-rfid-llrp:
adapter: full
command: bin/device-rfid-llrp $CONFIG_PRO_ARG $CONF_ARG $REGISTRY_ARG
command-chain:
- bin/startup-env-var.sh
environment:
CONFIG_PRO_ARG: "--cp=consul.http://localhost:8500"
CONFIG_PRO_ARG: "--cp=consul://localhost:8500"
CONF_ARG: "--confdir=$SNAP_DATA/config/device-rfid-llrp/res"
REGISTRY_ARG: "--registry"
DEVICE_PROFILESDIR: "$SNAP_DATA/config/device-rfid-llrp/res/profiles"
# DEVICE_DEVICESDIR: "$SNAP_DATA/config/device-rfid-llrp/res/devices"
SECRETSTORE_TOKENFILE: $SNAP_DATA/device-rfid-llrp/secrets-token.json
APPCUSTOM_PROVISION_WATCHER_FOLDER: $SNAP_DATA/config/device-rfid-llrp/res/provision_watchers
daemon: simple
passthrough:
install-mode: disable
Expand Down Expand Up @@ -125,3 +136,10 @@ parts:
config-common:
plugin: dump
source: snap/local/runtime-helpers

# required for device discovery
static-packages:
source: snap/local
plugin: nil
stage-packages:
- curl

0 comments on commit c7b3141

Please sign in to comment.