Skip to content

Commit

Permalink
fix: update snap packaging (#61)
Browse files Browse the repository at this point in the history
* fix: updates to enable snap support

- 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: #52

Signed-off-by: Siggi Skulason <siggi.skulason@canonical.com>
  • Loading branch information
Siggi Skulason authored Feb 17, 2022
1 parent fdb8dc9 commit 4e518ee
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 187 deletions.
55 changes: 11 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ A ROAccessReport can be used to examine data read from one or more RFID tags see
The [LLRP RFID Inventory Service][inventory_service] can be used to automatically configure this service and readers it manages. This repository also provides a higher-level abstraction for working with RFID tag by parsing ROAccessReports and generating higher-level tag-specific readings (e.g. TAG_APPEARED, TAG_MOVED, etc).

## Table of contents

* [First Run](#first-run)
* [Device Discovery](#device-discovery)
* [Device Profiles, Custom LLRP Messages, and Service Limitations](#device-profiles-custom-llrp-messages-and-service-limitations)
* [Connection Management](#connection-management)
* [Example Scripts](#example-scripts)
* [Testing](#testing)
* [Snap Development and Testing](#snap-development-and-testing)
* [Footnotes](#footnotes)


## First Run
**Build Native**
```bash
Expand All @@ -35,7 +35,8 @@ make docker
- [Snap](https://snapcraft.io/edgexfoundry)

**Run device-rfid-llrp**
- [Run via Snap](#snap-development-and-testing)
- Snap
- For the snap, refer to the [snap](snap) directory.

- Docker
- Use [compose-builder](https://github.com/edgexfoundry/edgex-compose/tree/jakarta/compose-builder)
Expand Down Expand Up @@ -111,6 +112,13 @@ The easiest way of doing this is via the following script:
```bash
./bin/auto-configure.sh
```

This script requires access to Consul. If running with security enabled, then a Consul token is required. In that case it should be passed as an argument to the script, i.e:

```bash
./bin/auto-configure.sh a7910d82-69ae-ea21-214d-fd1326e68545
```

What this command does is check your local machine's network interfaces to see which ones are both online
and a physical device (instead of virtual). It uses that information to fill in the `DiscoverySubnets`
field in Consul for you.
Expand Down Expand Up @@ -542,47 +550,6 @@ The following are particularly useful:
[test_helper]: internal/llrp/test_helpers.go
## Snap Development and Testing
The Snap directory consists of the `snapcraft.yaml` file and the initialization file `install` for building a snap package for this Service.
### Build Device RFID LLRP Snap Packages
Execute the following commands from the project's root directory. If you try to build elsewhere, it will fail with a `source not found` error message.
- `snapcraft clean`
- `snapcraft`

On success, this creates a `*.snap` package under the root directory.
The package name format is `{snapName}_{versionNumber}_{architecture}.snap`, e.g.

`edgex-device-llrp_0.0.0-20201014+39fc566_amd64.snap`

Always delete the old snap package before rebuilding via `rm oldsnap.snap` & `snapcraft clean`.

To debug snap build issues, run `snapcraft --debug`.

If snapcraft encounters an error, it will open a shell within the virtualised build environment.
### Install Device RFID LLRP Snap Packages
- `sudo snap install --devmode --dangerous *.snap`

Use `snapcraft list` to verify the package was installed.
### Test Device RFID LLRP Snap Packages
The service registers itself with consul at initialization,
which requires Consul and other EdgeX Snap packages.

Make sure they are installed and running (`snap install edgexfoundry`),
then start the service with `sudo snap start edgex-device-llrp`
and verify there are no errors in the logs: `sudo snap logs edgex-device-llrp`.

Consul UI can also be used to verify if the service has started without any errors `http://localhost:8500`

Follow [First Run](#first-run) section to auto-configure subnet & trigger device discovery.
As part of testing, registered devices can be checked via EdgeX Core-Metadata API - `http://localhost:59881/api/v2/device/service/name/device-rfid-llrp`

#### Here are other helpful commands:
- List installed Snap packages: `snap list`
- View the Snap service status: `systemctl status snap.edgex-device-rfid-llrp.device-rfid-llrp-go.service`
- View System logs: `journalctl -xe`
- Stop the Snap service: `sudo snap stop edgex-device-rfid-llrp`
- Remove the Snap package: `sudo snap remove edgex-device-rfid-llrp`

## Footnotes
### Notes on configuration.toml
- Modifying the `configuration.toml` file will require you to rebuild the docker image
Expand Down
20 changes: 17 additions & 3 deletions bin/auto-configure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ err() {
echo -e "${red}${bold}Failed!${clear}"
exit 1
}


CONSUL_TOKEN=${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"
Expand All @@ -57,7 +59,13 @@ 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"
code=$(curl -X GET -w "%{http_code}" -o /dev/null -s "${url}" || echo $?)

if [ -z $CONSUL_TOKEN ]; then
code=$(curl -X GET -w "%{http_code}" -o /dev/null -s "${url}" || echo $?)
else
code=$(curl -X GET -H "X-Consul-Token:$CONSUL_TOKEN" -w "%{http_code}" -o /dev/null -s "${url}" || echo $?)
fi

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
Expand Down Expand Up @@ -85,6 +93,7 @@ ifaces=$(
-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
Expand Down Expand Up @@ -138,7 +147,12 @@ echo -e "${prev_line}${clear}${subnets}"

### Configure Consul
printf "${bold}%${spacing}s${clear}: ...\n${red}" "Configure"
code=$(curl -X PUT --data "${subnets}" -w "%{http_code}" -o /dev/null -s "${url}" || echo $?)
if [ -z $CONSUL_TOKEN ]; then
code=$(curl -X PUT --data "${subnets}" -w "%{http_code}" -o /dev/null -s "${url}" || echo $?)
else
code=$(curl -X PUT -H "X-Consul-Token:$CONSUL_TOKEN" --data "${subnets}" -w "%{http_code}" -o /dev/null -s "${url}" || echo $?)
fi

if [ $((code)) -ne 200 ]; then
echo -e "${red}${bold}Failed!${normal} curl returned a status code of '${bold}${code}'${clear}"
exit $((code))
Expand Down
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
11 changes: 10 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 @@ -712,7 +711,17 @@ func getAddr(protocols protocolMap) (net.Addr, error) {
"unable to create addr for tcp protocol (%q, %q)", host, port)
}

// todo: remove this method once the Device SDK has been updated as per https://github.com/edgexfoundry/device-sdk-go/issues/1100
func (d *Driver) addProvisionWatchers() error {

// this setting is a workaround for the fact that there is no standard way to define this directory using the SDK
// the snap needs to be able to change the location of the provision watchers
provisionWatcherFolder := d.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
99 changes: 54 additions & 45 deletions snap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ The latest stable version of the snap can be installed using:
$ sudo snap install edgex-device-rfid-llrp
```

The 2.0 (Ireland) release of the snap can be installed using:

```bash
$ sudo snap install edgex-device-rfid-llrp --channel=2.0
```

The latest development version of the snap can be installed using:

```bash
Expand Down Expand Up @@ -69,40 +63,51 @@ ensures that as well as starting the service now, it will be automatically start
$ sudo snap start --enable edgex-device-rfid-llrp.device-rfid-llrp
```

### Using a content interface to set device configuration
## Subnet setup

The `device-config` content interface allows another snap to seed this device
snap with configuration files under the `$SNAP_DATA/config/device-rfid-llrp/res` directory.
The `DiscoverySubnets` setting needs to be provided before a device discovery can occur. This can be done in a number of ways:

Note that the `device-config` content interface does NOT support seeding of the Secret Store Token because that file is expected at a different path.
- Using `snap set` to set your local subnet information. Example:

To use, create a new snap with a directory containing the configuration files.
Your `snapcraft.yaml` file then needs to define a slot with read access to the directory you are sharing.
```bash
$ sudo snap set edgex-device-rfid-llrp env.app-custom.discovery-subnets="192.168.10.0/24"

$ curl -X POST http://localhost:59989/api/v2/discovery
```

```
slots:
device-config:
interface: content
content: device-config
read:
- $SNAP/config
```
**NOTE:** This will only work after [this issue](https://github.com/edgexfoundry/app-functions-sdk-go/issues/1043) is resolved.

where `$SNAP/config` is configuration directory your snap is providing to the device snap.
- Using a [content interface](#using-a-content-interface-to-set-device-configuration) to set device configuration

Then connect the plug in the device snap to the slot in your snap, which will replace the configuration in the device snap. Do this with:

```bash
$ sudo snap connect edgex-device-rfid-llrp:device-config your-snap:device-config
```
- Using the `auto-configure` command.

This command finds all local network interfaces which are online and non-virtual and sets the value of `DiscoverySubnets`
in Consul. When running with security enabled, it requires a Consul token, so it needs to be run as follows:

This needs to be done before the device service is started for the first time. Once you have set the configuration the device service can be started and it will then be configured using the settings you provided:
```bash
# get Consul ACL token
CONSUL_TOKEN=$(sudo cat /var/snap/edgexfoundry/current/secrets/consul-acl-token/bootstrap_token.json | jq ".SecretID" | tr -d '"')
echo $CONSUL_TOKEN
```bash
$ sudo snap start edgex-device-rfid-llrp.device-rfid-llrp
```
# start the device service and connect the interfaces required for network interface discovery
sudo snap start edgex-device-rfid-llrp.device-rfid-llrp
sudo snap connect edgex-device-rfid-llrp:network-control
sudo snap connect edgex-device-rfid-llrp:network-observe
# run the nework interface discovery, providing the Consul token
edgex-device-rfid-llrp.auto-configure $CONSUL_TOKEN
```


### Using a content interface to set device configuration

The `device-config` content interface allows another snap to seed this snap with configuration directories under `$SNAP_DATA/config/device-rfid-llrp`.

Note that the `device-config` content interface does NOT support seeding of the Secret Store Token because that file is expected at a different path.

Please refer to [edgex-config-provider](https://github.com/canonical/edgex-config-provider), for an example and further instructions.

**Note** - content interfaces from snaps installed from the Snap Store that have the same publisher connect automatically. For more information on snap content interfaces please refer to the snapcraft.io [Content Interface](https://snapcraft.io/docs/content-interface) documentation.

### Autostart
By default, the edgex-device-rfid-llrp disables its service on install, as the expectation is that the default profile configuration files will be customized, and thus this behavior allows the profile `configuration.toml` files in $SNAP_DATA to be modified before the service is first started.
Expand All @@ -124,7 +129,6 @@ the overrides will be picked up when the services are first started.
The following syntax is used to specify service-specific configuration overrides:

```
env.<stanza>.<config option>
```
Expand All @@ -145,28 +149,33 @@ For details on the mapping of configuration options to Config options, please re

```
[Service]
service.boot-timeout // Service.BootTimeout
service.health-check-interval // Service.HealthCheckInterval
service.host // Service.Host
service.server-bind-addr // Service.ServerBindAddr
service.port // Service.Port
service.protocol // Service.Protocol
service.max-result-count // Service.MaxResultCount
service.max-request-size // Service.MaxRequestSize
service.startup-msg // Service.StartupMsg
service.request-timeout // Service.RequestTimeout
service.health-check-interval // Service.HealthCheckInterval
service.host // Service.Host
service.server-bind-addr // Service.ServerBindAddr
service.port // Service.Port
service.max-result-count // Service.MaxResultCount
service.max-request-size // Service.MaxRequestSize
service.startup-msg // Service.StartupMsg
service.request-timeout // Service.RequestTimeout
[SecretStore]
secret-store.secrets-file // SecretStore.SecretsFile
secret-store.disable-scrub-secrets-file // SecretStore.DisableScrubSecretsFile
[Clients.core-data]
clients.core-data.port // Clients.core-data.Port
clients.core-data.port // Clients.core-data.Port
[Clients.core-metadata]
clients.core-metadata.port // Clients.core-metadata.Port
clients.core-metadata.port // Clients.core-metadata.Port
[Device]
device.update-last-connected // Device.UpdateLastConnected
device.use-message-bus // Device.UseMessageBus
device.update-last-connected // Device.UpdateLastConnected
device.use-message-bus // Device.UseMessageBus
[AppCustom]
app-custom.discovery-subnets // AppCustom.DiscoverySubnets
app-custom.probe-async-limit // AppCustom.ProbeAsyncLimit
app-custom.probe-timeout-seconds // AppCustom.ProbeTimeoutSeconds
app-custom.scan-port // AppCustom.ScanPort
app-custom.max-discover-duration-seconds // AppCustom.MaxDiscoverDurationSeconds
```
Loading

0 comments on commit 4e518ee

Please sign in to comment.