diff --git a/.checkstyle.xml b/.checkstyle.xml index a214cc83f6..469a132853 100644 --- a/.checkstyle.xml +++ b/.checkstyle.xml @@ -42,7 +42,7 @@ - + diff --git a/.gitignore b/.gitignore index ada16ef8f5..0ee48512c9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,16 +21,15 @@ validations/ *.save # Runtime or sub-module files -inst/ -faucet/ -forch/ -mininet/ -local/ -local_xxx -local.old -firebase/.firebaserc -firebase/.firebase -firebase/functions/package-lock.json +/inst/ +/faucet/ +/forch/ +/udmi/ +/mininet/ +/local/ +/firebase/.firebaserc +/firebase/.firebase +/firebase/functions/package-lock.json nohup.out **/node_modules/ .vscode/ diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000000..b9d18bf599 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index b8fa9bb7a4..3fc93409e7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -36,6 +36,10 @@ + + + + \ No newline at end of file diff --git a/bin/alt_faucet b/bin/alt_faucet new file mode 100755 index 0000000000..757ad64218 --- /dev/null +++ b/bin/alt_faucet @@ -0,0 +1,24 @@ +#!/bin/bash -e + +ROOT=$(realpath $(dirname $0)/..) +cd $ROOT +source etc/config_base.sh + +if [ -z "$switch_setup_ext_br" ]; then + echo switch_setup.ext_br not defined for alternate faucet setup. + false +fi + +if [ -z "$switch_setup_alt_port" ]; then + echo switch_setup.alt_port not defined for alternate faucet setup. + false +fi + +inst_name=$switch_setup_ext_br + +inst_dir=inst/faucet/daq-faucet-$inst_name +mkdir -p $inst_dir +cp config/faucet/faucet_$inst_name.yaml $inst_dir/faucet.yaml +echo Launching alternate faucet install $inst_name on $switch_setup_alt_port +echo DAQ autoclean docker kill daq-faucet-$inst_name +cmd/faucet $inst_name $switch_setup_alt_port diff --git a/bin/build_proto b/bin/build_proto index ad07980e9e..cd20e074ef 100755 --- a/bin/build_proto +++ b/bin/build_proto @@ -32,6 +32,11 @@ sha1sum $proto_files > $WEB_ROOT/protos.hash gen_path=$ROOT/protoc-gen-doc/bin/protoc-gen-doc +if [ -d venv ]; then + echo Entering virtual python environment... + source venv/bin/activate +fi + mkdir -p build/daq/proto build/proto cp $proto_files build/daq/proto/ proto_files2= @@ -56,3 +61,5 @@ mkdir -p libs/proto/ touch libs/proto/__init__.py cp build/daq/proto/*.py libs/proto/ cp build/protos.html $WEB_ROOT/ + +python3 -m grpc_tools.protoc -I usi/src/main/proto/ --python_out=libs/proto/ --grpc_python_out=libs/proto/ usi/src/main/proto/usi.proto diff --git a/bin/build_release b/bin/build_release new file mode 100755 index 0000000000..ac035a50bf --- /dev/null +++ b/bin/build_release @@ -0,0 +1,82 @@ +#!/bin/bash -e + +if [ $# != 1 ]; then + echo $0 RELEASE_VERSION + false +fi + +VERSION=$1 +shift + +ROOT=$(realpath $(dirname $0)/..) +cd $ROOT + +changes=`git status --porcelain` +if [ -n "$changes" ]; then + echo Working tree not clean. + false +fi + +git checkout master + +changed=`git diff --name-only release_stable docs/changelog.md` +if [ -z "$changed" ]; then + git log release_stable..HEAD --pretty=oneline | sed -e 's/[a-z0-9]+/\*/g' + echo docs/changelog.md has not been updated since last release_stable + echo Use the log lines above for inspiration. + false +fi + +tagged=`git rev-list -n 1 $VERSION 2>/dev/null` || true +if [ -n "$tagged" ]; then + echo Tag $VERSION already exists. Try the next version. + false +fi + +source etc/config_base.sh + +if [ "$host_tests" != config/modules/all.conf ]; then + echo Configure your system with host_tests=config/modules/all.conf + false +fi + +cmd/build force $VERSION + +cmd/build push + +cat > /tmp/git_expected.expected < /tmp/git_status.found + +if ! diff /tmp/git_status.expected /tmp/git_status.found; then + echo Expected build images not found. Something went wrong. + false +fi +rm -f /tmp/git_status.* + +git commit -a -m "$VERSION release" +git tag -a $VERSION -m "$VERSION release" +git push +git push --tags + +# Check to see if a remote 'faucet' is defined, and if so, also update that. +faucetgit=`git config remote.faucet.url` +if [ -n "$faucetgit" ]; then + git push faucet + git push faucet --tags +fi + +firebase/deploy.sh bos-daq-testing +git checkout release_testing && git reset --hard $VERSION + +if [ -n "$faucetgit" ]; then + git push faucet +fi + +# QA pass to make sure everything is ok. +# `firebase/deploy.sh daq-qualification-labs` +# `git checkout release_stable && git reset --hard $VERSION` +# `git push` diff --git a/bin/external_ovs b/bin/external_ovs index a289bd9cff..080fdcdecb 100755 --- a/bin/external_ovs +++ b/bin/external_ovs @@ -6,14 +6,19 @@ source etc/config_base.sh ext_intf=$switch_setup_data_intf ext_dpid=$switch_setup_of_dpid -ext_ofpt=$switch_setup_lo_port ext_brid=$switch_setup_ext_br ext_brpt=$switch_setup_uplink_port ext_pri=${ext_intf} ext_sec=${ext_intf%-pri}-sec -echo ext_dpid is $ext_dpid +if [ -z "$switch_setup_alt_port" ]; then + ext_ofpt=$switch_setup_lo_port +else + ext_ofpt=$switch_setup_alt_port +fi + +echo ext_dpid is $ext_dpid on port $ext_ofpt echo network_config is $network_config dpid=$(printf %016x $ext_dpid) diff --git a/bin/physical_sec b/bin/physical_sec index 82463e474d..939d6c4d5c 100755 --- a/bin/physical_sec +++ b/bin/physical_sec @@ -119,6 +119,9 @@ else sudo ip addr flush dev $ext_ctrl fi +echo Warmup ping for $ext_addr +ping -n -c 2 $ext_addr || true + echo Checking external connection to $ext_addr if ! ping -n -c 2 $ext_addr; then echo diff --git a/bin/python/combine_reports_from_date_range.py b/bin/python/combine_reports_from_date_range.py index f5deb04b43..9b304c7e76 100644 --- a/bin/python/combine_reports_from_date_range.py +++ b/bin/python/combine_reports_from_date_range.py @@ -61,7 +61,7 @@ def _get_local_reports(device, reports_dir, start, end, count): LOGGER.info('Looking for reports locally') report_re = re.compile(r'^report_%s_(\d{4}-\d{2}-\d{2}T\d{6})\.json$' % device) json_files = [f for f in os.listdir(reports_dir) if report_re.match(f)] - json_files.sort() + json_files.sort(reverse=True) # Match gcp behavior if count and len(json_files) > count: json_files = json_files[len(json_files) - count:] for json_file in json_files: diff --git a/bin/registrar b/bin/registrar deleted file mode 100755 index e2278951e4..0000000000 --- a/bin/registrar +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -e - -ROOT=$(realpath $(dirname $0)/..) -cd $ROOT - -if [ $# != 1 ]; then - echo $0 [project_id] - false -fi -project_id=$1 -shift - -source etc/config_base.sh - -if [ -z "$site_path" ]; then - echo Need to define [site_path] config variable. - false -fi - -if [ -z "$schema_path" ]; then - echo Need to define [schema_path] config variable. - false -fi - -echo Building validator... -validator/bin/build > /dev/null - -echo Running tools version `git describe` - -validator/bin/registrar $project_id $site_path $schema_path $* diff --git a/bin/setup_dev b/bin/setup_dev index 62223aa9c3..65c9441987 100755 --- a/bin/setup_dev +++ b/bin/setup_dev @@ -20,8 +20,13 @@ FORCHB=${DAQ_FORCH_BRANCH} FORCHX=$(cat etc/FORCH_VERSION) FORCHV=${DAQ_FORCH_VER:-$FORCHX} +UDMIR=${DAQ_UDMI_REPO:-https://github.com/faucetsdn/udmi} +UDMIB=${DAQ_UDMI_BRANCH} +UDMIX=$(cat etc/UDMI_VERSION) +UDMIV=${DAQ_UDMI_VER:-$UDMIX} + MININET=https://github.com/mininet/mininet -MININETV=2.3.0d6 +MININETV=$(cat etc/MININET_VERSION) if [ -f .daq.local ]; then echo Loading config from .daq.local @@ -36,6 +41,10 @@ if [ "$FORCHX" != "$FORCHV" ]; then echo $FORCHV > etc/FORCH_VERSION fi +if [ "$UDMIX" != "$UDMIV" ]; then + echo $UDMIV > etc/UDMI_VERSION +fi + if [ -z "$AG" ]; then AG="sudo apt-get -qqy --no-install-recommends" fi @@ -75,10 +84,6 @@ $AG install \ python$PVERSION python3-pkg-resources python3-setuptools \ python$PVERSION-dev python3-pip python emacs-nox python$PVERSION-venv -# Jump through some hoops for mininet, which still has some python2 deps. -$AG install python-pip -python2 -m pip install setuptools - if [ -d mininet ]; then echo Checking mininet version matches $MININETV... targetrev=$(cd mininet; git rev-parse $MININETV) @@ -137,8 +142,9 @@ $PIP install --upgrade --index-url=https://pypi.python.org/simple Jinja2 \ google-api-core==1.16.0 \ google-cloud-storage==1.16.1 \ google-cloud-firestore==1.6.0 \ - google-cloud-logging==1.14.0 - + google-cloud-logging==1.14.0 \ + grpcio-tools==1.30.0 + $PIP freeze echo Resetting .cache directory permissions... test -n "$USER" && sudo chown $USER -R $HOME/.cache @@ -167,6 +173,18 @@ else (cd forch; git fetch; git checkout $FORCHV) fi +if [ -z "$UDMIV" ]; then + echo No udmi version found, skipping. +else + if [ ! -d udmi ]; then + echo Cloning $UDMIR... + git clone $UDMIR udmi + fi + + echo Setting udmi version $UDMIV + (cd udmi; git fetch; git checkout $UDMIV) +fi + echo -n "DAQ commit " git log -n 1 --pretty=format:"%h - %an, %ar : %s" || true echo @@ -179,6 +197,10 @@ echo -n "Last FORCH commit " (cd forch; git log -n 1 --pretty=format:"%h - %an, %ar : %s" || true) echo +echo -n "Last UDMI commit " +(cd udmi; git log -n 1 --pretty=format:"%h - %an, %ar : %s" || true) +echo + docker --version if ! docker images > /dev/null; then diff --git a/bin/setup_testing b/bin/setup_testing deleted file mode 100755 index f5e73ca8b1..0000000000 --- a/bin/setup_testing +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -e - -ROOT=$(dirname $0)/.. -cd $ROOT - -bin/build_hash check - -TARGET_ROOT=inst/faucet/daq-faucet-faucet - -for postfix in 1 2; do - TARGET=${TARGET_ROOT}$postfix - echo Preparing $TARGET - sudo rm -rf $TARGET && mkdir -p $TARGET - cp topology/alta-dev/faucet.yaml $TARGET/faucet.yaml - cp topology/alta-dev/gauge.yaml $TARGET/gauge.yaml -done - -cmd/faucet faucet1 6655 -cmd/faucet gauge faucet1 6656 9306 -cmd/faucet faucet2 6657 -cmd/faucet gauge faucet2 6658 9308 - -sudo ip addr flush ganga -sudo ip addr add 192.0.2.10/24 dev ganga - -sudo ovs-vsctl --if-exists del-br upstream -- add-br upstream -sudo ip link del daqnw || true -sudo ip link add daqnw type veth peer name t1bond -sudo ip link set daqnw up -sudo ip link set t1bond up -sudo ovs-vsctl add-port upstream daqnw - -sudo ip link del up_bond || true -sudo ip link add up_bond type bond mode 802.3ad lacp_rate fast -sudo ip link set up_bond up -sudo ip link set yamuna down -sudo ip link set yamuna master up_bond -sudo ip link set beas down -sudo ip link set beas master up_bond -sudo ovs-vsctl add-port upstream up_bond - -cmd/faux -n :t1bond -cmd/faux :satlej -cmd/faux :ravi -cmd/faux :tapti - -echo -docker exec daq-networking-t1bond ip addr -echo Waiting for DHCP... -sleep 30 -echo -docker exec daq-faux-satlej ip addr show dev satlej -echo -docker exec daq-faux-ravi ip addr show dev ravi -echo -docker exec daq-faux-tapti ip addr show dev tapti -echo -docker exec daq-faux-satlej ping -c 3 google.com -docker exec daq-faux-ravi ping -c 3 google.com -docker exec daq-faux-tapti ping -c 3 google.com -docker exec daq-faux-satlej ping -c 3 daq-faux-tapti -echo -echo Done with testing setup. diff --git a/bin/test_daq b/bin/test_daq index 279e3bc53b..779cef8998 100755 --- a/bin/test_daq +++ b/bin/test_daq @@ -31,6 +31,16 @@ echo -n "DAQ version " git describe --dirty --always echo +TAGGED_VERSION=`cat etc/docker_images.ver` +if ! git show $TAGGED_VERSION > /dev/null; then + echo + echo Tagged version $TAGGED_VERSION not found. + echo Maybe you need to fetch tags: git fetch --tags. + echo If this is on Travis, ensure tags were pushed to your repo. + echo + false +fi + if [ -d faucet ]; then echo -n "Last FAUCET commit " (cd $FAUCET; git log -n 1 --pretty=format:"%h - %an, %ar : %s" || true) diff --git a/bin/troubleshoot b/bin/troubleshoot new file mode 100755 index 0000000000..06b3432bd3 --- /dev/null +++ b/bin/troubleshoot @@ -0,0 +1,29 @@ +#!/bin/bash + +ROOT=$(realpath $(dirname $0)/..) +cd $ROOT + +if [ ! -d inst ]; then + echo "Error: run this script after a test run completes" + exit 1 +fi + +# After the system settles (early on some dpid=1 messages are expected) if we see +# unknown dpid in faucet log, dpid might be misconfigured +unknown_dpid=`fgrep 'unknown datapath' inst/faucet.log | wc -l` +if [ "$unknown_dpid" -gt 20 ]; then + echo "Error: Faucet reports unknown datapath DPID:" + fgrep 'unknown datapath' inst/faucet.log | tail -n1 + echo "Check if switch_setup:of_dpid in config matches the DPID on the physical switch" +else + echo "Checking DPID misconfig: ok" +fi + +# If the switch test failed with a monitoring timeout, switch login info could be wrong +switch_timeout=`fgrep 'Monitoring timeout for switch' inst/cmdrun.log` +if [ -n "$switch_timeout" ]; then + echo "Error: Timeout connecting to physical switch" + echo "Check switch username/password configuration" +else + echo "Checking Switch timeout: ok" +fi diff --git a/bin/validate b/bin/validate deleted file mode 100755 index bd13b42612..0000000000 --- a/bin/validate +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -e - -ROOT=$(realpath $(dirname $0)/..) -cd $ROOT - -source etc/config_base.sh - -if [ -z "$gcp_cred" ]; then - echo Please make sure gcp_cred is defined in local/system.conf - false -fi - -if [ -z "$gcp_topic" ]; then - echo Please make sure gcp_topic is defined in local/system.conf - false -fi - -if [ -z "$schema_path" ]; then - echo Please make sure schema_path is defined in local/system.conf - false -fi - -validator/bin/build - -unset GOOGLE_CLOUD_PROJECT -export GOOGLE_APPLICATION_CREDENTIALS=$PWD/$gcp_cred -echo Using credentials from $GOOGLE_APPLICATION_CREDENTIALS -echo Configured topic is $gcp_topic -echo Configured schema is $schema_path -if [ -n "$site_path" ]; then - echo Configured site path is $site_path -fi -echo - -validator/bin/validate $schema_path pubsub:$gcp_topic dev $site_path diff --git a/cmd/build b/cmd/build index dc428ba90d..5a2273d234 100755 --- a/cmd/build +++ b/cmd/build @@ -26,11 +26,12 @@ DOCKER_IMAGE_VER=docker_images.ver cd $ROOT source etc/config_base.sh -host_tests=$host_tests bin/docker_build_files +echo host_tests=$host_tests +test_targets=$(host_tests=$host_tests bin/docker_build_files) function pull_images { TAG=$1 declare -A test_set - for target in $(host_tests=$host_tests bin/docker_build_files); do + for target in $test_targets; do target=$(echo $target | sed 's|^.*/Dockerfile.||' | echo daqf/$( /dev/null 2>&1 || service docker start @@ -99,12 +100,19 @@ if [ -n "$switch_setup_ext_br" ]; then autostart bin/external_ovs fi +if [ -n "$switch_setup_alt_port" ]; then + autostart bin/alt_faucet +fi + if [ -n "$switch_setup_model" ]; then autostart bin/physical_sec else echo No external switch model specified. fi +docker rm -f daq-usi || true +autostart cmd/usi + # Kill any gateways so that they don't prematurely assign an IP address. gwids=$(docker ps --format '{{ .Image }} {{ .Names }}' | fgrep daqf/networking | awk '{print $2}') || true for gwid in $gwids; do diff --git a/cmd/usi b/cmd/usi new file mode 100755 index 0000000000..79fa946d9a --- /dev/null +++ b/cmd/usi @@ -0,0 +1,12 @@ +#!/bin/bash -e + +ROOT=$(realpath $(dirname $0)/..) +USI_DIR=$ROOT/inst/network + +echo Starting USI + +rm -rf $USI_DIR +mkdir -p $USI_DIR +docker run -d -v $USI_DIR:/ovs --privileged --network=host --name daq-usi daqf/usi + +echo DAQ autoclean docker kill daq-usi diff --git a/config/faucet/faucet_alt-switch.yaml b/config/faucet/faucet_alt-switch.yaml new file mode 100644 index 0000000000..876cf786fd --- /dev/null +++ b/config/faucet/faucet_alt-switch.yaml @@ -0,0 +1,22 @@ +dps: + alt-switch: + dp_id: 2 + interfaces: + 1: + native_vlan: 1001 + 2: + native_vlan: 1002 + 3: + native_vlan: 1003 + 4: + native_vlan: 1004 + 5: + native_vlan: 1005 + 100: + tagged_vlans: [1001, 1002, 1003, 1004, 1005] +vlans: + 1001: + 1002: + 1003: + 1004: + 1005: diff --git a/config/modules/all.conf b/config/modules/all.conf index 4d897ae7c5..59b4b74367 100644 --- a/config/modules/all.conf +++ b/config/modules/all.conf @@ -7,4 +7,5 @@ include subset/connection/build.conf include subset/bacnet/build.conf include subset/security/build.conf include subset/cloud/build.conf -include subset/manual/build.conf \ No newline at end of file +include subset/manual/build.conf +include subset/ntp/build.conf diff --git a/config/modules/host.conf b/config/modules/host.conf index e6ec5e37ef..cd9e9421b4 100644 --- a/config/modules/host.conf +++ b/config/modules/host.conf @@ -12,6 +12,10 @@ add mudgee # Additional base modules include subset/pentests/build.conf +include usi/build.conf + +# Extended dhcp tests +add ipaddr # Example of how to remove something. remove unused diff --git a/config/modules/topo.conf b/config/modules/topo.conf index 4d47ec6cf9..ba02ce2374 100644 --- a/config/modules/topo.conf +++ b/config/modules/topo.conf @@ -3,3 +3,4 @@ build docker/modules # Use ping with runtime configuration for topo testing. add ping +include usi/build.conf diff --git a/config/system/all.conf b/config/system/all.conf index 0fe77da8fb..612cdc89cb 100644 --- a/config/system/all.conf +++ b/config/system/all.conf @@ -3,7 +3,7 @@ # Load defaults. source config/system/default.yaml -# Description description for dashboard. +# Description for dashboard. site_description="Multi-Device All-Tests Configuration" # Upstream dataplane port from the external (secondary) switch. diff --git a/config/system/alt.yaml b/config/system/alt.yaml new file mode 100644 index 0000000000..e429326c7f --- /dev/null +++ b/config/system/alt.yaml @@ -0,0 +1,20 @@ +# Example configuration file for using an OVS switch not managed by DAQ. + +# Load defaults. +include: config/system/default.yaml + +# Description for dashboard. +site_description: "Alternate (not managed by DAQ) OVS switch configuration" + +# Network switch configuration. +switch_setup: + data_intf: alt-intf + alt_port: 6669 + uplink_port: 100 + ext_br: alt-switch + +# Faux device connection for testing. +interfaces: + faux: + opts: + port: 2 diff --git a/config/system/default.yaml b/config/system/default.yaml index 644993b96e..538ae0090f 100644 --- a/config/system/default.yaml +++ b/config/system/default.yaml @@ -37,3 +37,11 @@ long_dhcp_response_sec: 105 # finish hook: executed at the end of every test finish_hook: bin/dump_network + +# topology hook: executed when device topology changes +topology_hook: bin/dump_network + +# usi url for DAQ to connect to +usi_setup: + url: localhost:5000 + rpc_timeout_sec: 10 diff --git a/config/system/ext.conf b/config/system/ext.conf index 8625109734..28dc34b707 100644 --- a/config/system/ext.conf +++ b/config/system/ext.conf @@ -3,7 +3,7 @@ # Load defaults. source config/system/default.yaml -# Description description for dashboard. +# Description for dashboard. site_description="External (not integrated with DAQ) OVS switch configuration" # Network switch configuration. diff --git a/config/system/ext.yaml b/config/system/ext.yaml index 7ad626341e..4fef079c1e 100644 --- a/config/system/ext.yaml +++ b/config/system/ext.yaml @@ -3,7 +3,7 @@ # Load defaults. include: config/system/default.yaml -# Description description for dashboard. +# Description for dashboard. site_description: "External (not integrated with DAQ) OVS switch configuration" # Network switch configuration. diff --git a/config/system/muddy.conf b/config/system/muddy.conf index 6510e2b113..3d3a17b30c 100644 --- a/config/system/muddy.conf +++ b/config/system/muddy.conf @@ -3,7 +3,7 @@ # Load defaults. source config/system/default.yaml -# Description description for dashboard. +# Description for dashboard. site_description="Multi-Device Configuration" # Upstream dataplane port from the external (secondary) switch. diff --git a/config/system/multi.conf b/config/system/multi.conf index 185bbc40df..367a94e86b 100644 --- a/config/system/multi.conf +++ b/config/system/multi.conf @@ -3,7 +3,7 @@ # Load defaults. source config/system/default.yaml -# Description description for dashboard. +# Description for dashboard. site_description="Multi-Device Configuration" # Upstream dataplane port from the external (secondary) switch. diff --git a/daq/docker_test.py b/daq/docker_test.py index fdabebd0f7..c38b210b8d 100644 --- a/daq/docker_test.py +++ b/daq/docker_test.py @@ -19,18 +19,17 @@ class DockerTest: CONTAINER_PREFIX = 'daq' # pylint: disable=too-many-arguments - def __init__(self, runner, target_port, tmpdir, test_name, env_vars=None): + def __init__(self, host, target_port, tmpdir, test_name, module_config): self.target_port = target_port self.tmpdir = tmpdir self.test_name = test_name - self.runner = runner + self.runner = host.runner self.host_name = '%s%02d' % (test_name, self.target_port) self.docker_log = None self.docker_host = None self.callback = None self.start_time = None self.pipe = None - self.env_vars = env_vars or [] self._finish_hook = None def start(self, port, params, callback, finish_hook): @@ -44,7 +43,7 @@ def start(self, port, params, callback, finish_hook): def opt_param(key): return params.get(key) or '' # Substitute empty string for None - env_vars = self.env_vars + [ + env_vars = [ "TARGET_NAME=" + self.host_name, "TARGET_IP=" + params['target_ip'], "TARGET_MAC=" + params['target_mac'], @@ -168,3 +167,6 @@ def _docker_complete(self): LOGGER.info("Target port %d test %s passed %ss", self.target_port, self.test_name, delay) self.callback(return_code=return_code, exception=exception) + + def ip_listener(self, target_ip): + """Do nothing b/c docker tests don't care about ip notifications""" diff --git a/daq/gateway.py b/daq/gateway.py index c7c54182a5..4ee9bc2fd1 100644 --- a/daq/gateway.py +++ b/daq/gateway.py @@ -12,6 +12,7 @@ LOGGER = logger.get_logger('gateway') + class Gateway(): """Gateway collection class for managing testing services""" @@ -37,8 +38,8 @@ def __init__(self, runner, name, port_set, network): self.dummy = None self.tmpdir = None self.targets = {} - self.test_ports = {} - self.ready = {} + self.test_ports = set() + self.ready = set() self.activated = False self.result_linger = False self._scan_monitor = None @@ -125,6 +126,18 @@ def request_new_ip(self, mac): """Requests a new ip for the device""" self.execute_script('new_ip', mac) + def change_dhcp_response_time(self, mac, time): + """Change dhcp response time for device mac""" + self.execute_script('change_dhcp_response_time', mac, time) + + def stop_dhcp_response(self, mac): + """Stops DHCP response for the device""" + self.change_dhcp_response_time(mac, -1) + + def change_dhcp_range(self, start, end, prefix_length): + """Change dhcp range for devices""" + self.execute_script('change_dhcp_range', start, end, prefix_length) + def allocate_test_port(self): """Get the test port to use for this gateway setup""" test_port = self._switch_port(self.TEST_OFFSET_START) @@ -132,7 +145,7 @@ def allocate_test_port(self): test_port = test_port + 1 limit_port = self._switch_port(self.NUM_SET_PORTS) assert test_port < limit_port, 'no test ports available' - self.test_ports[test_port] = True + self.test_ports.add(test_port) return test_port def _startup_scan(self, host): @@ -160,7 +173,7 @@ def _scan_error(self, e): def release_test_port(self, test_port): """Release the given port from the gateway""" assert test_port in self.test_ports, 'test port not allocated' - del self.test_ports[test_port] + self.test_ports.remove(test_port) def _switch_port(self, offset): return self.port_set * self.SET_SPACING + offset @@ -207,7 +220,7 @@ def target_ready(self, target_mac): """Mark a target ready, and return set of ready targets""" if not target_mac in self.ready: LOGGER.info('Ready target %s from gateway group %s', target_mac, self.name) - self.ready[target_mac] = True + self.ready.add(target_mac) return self.ready def get_targets(self): diff --git a/daq/gcp.py b/daq/gcp.py index 17051870a1..67db631e0b 100644 --- a/daq/gcp.py +++ b/daq/gcp.py @@ -24,6 +24,7 @@ # pylint: disable=no-member DESCENDING = firestore.Query.DESCENDING + def get_timestamp(): """"Get a JSON-compatible formatted timestamp""" return to_timestamp(datetime.datetime.now(datetime.timezone.utc)) @@ -49,7 +50,7 @@ def __init__(self, config, callback_handler): self._callback_handler = callback_handler cred_file = self.config.get('gcp_cred') if not cred_file: - LOGGER.info('No gcp_cred filr specified in config, disabling gcp use.') + LOGGER.info('No gcp_cred file specified in config, disabling gcp use.') self._pubber = None self._storage = None self._firestore = None diff --git a/daq/host.py b/daq/host.py index dc13f9b659..16562b929a 100644 --- a/daq/host.py +++ b/daq/host.py @@ -5,17 +5,20 @@ import shutil import time from datetime import timedelta, datetime +import grpc from clib import tcpdump_helper + from report import ResultType, ReportGenerator +from proto import usi_pb2 as usi +from proto import usi_pb2_grpc as usi_service import configurator import docker_test import gcp +import ipaddr_test import logger -LOGGER = logger.get_logger('host') - class _STATE: """Host state enum for testing cycle""" @@ -46,21 +49,29 @@ class MODE: LONG = 'long' MERR = 'merr' + def pre_states(): """Return pre-test states for basic operation""" - return ['startup', 'sanity', 'ipaddr', 'base', 'monitor'] + return ['startup', 'sanity', 'acquire', 'base', 'monitor'] def post_states(): """Return post-test states for recording finalization""" return ['finish', 'info', 'timer'] +def get_test_config(config, test): + """Get a single test module's config""" + return config["modules"].get(test) + + class ConnectedHost: """Class managing a device-under-test""" _STARTUP_MIN_TIME_SEC = 5 + _RPC_TIMEOUT_SEC = 10 _INST_DIR = "inst/" _DEVICE_PATH = "device/%s" + _NETWORK_DIR = "inst/network" _MODULE_CONFIG = "module_config.json" _CONTROL_PATH = "control/port-%s" _CORE_TESTS = ['pass', 'fail', 'ping', 'hold'] @@ -68,6 +79,7 @@ class ConnectedHost: _CONFIG_DIR = "config/" _TIMEOUT_EXCEPTION = TimeoutError('Timeout expired') + # pylint: disable=too-many-statements def __init__(self, runner, gateway, target, config): self.configurator = configurator.Configurator() self.runner = runner @@ -81,6 +93,7 @@ def __init__(self, runner, gateway, target, config): self.devdir = self._init_devdir() self.run_id = self.make_runid() self.scan_base = os.path.abspath(os.path.join(self.devdir, 'scans')) + self.logger = logger.get_logger('host%s' % self.target_port) self._port_base = self._get_port_base() self._device_base = self._get_device_base() self.state = None @@ -96,6 +109,8 @@ def __init__(self, runner, gateway, target, config): _default_timeout_sec = int(config.get('default_timeout_sec', 0)) self._default_timeout_sec = _default_timeout_sec if _default_timeout_sec else None self._finish_hook_script = config.get('finish_hook') + self._usi_config = config.get('usi_setup', {}) + self._topology_hook_script = config.get('topology_hook') self._mirror_intf_name = None self._monitor_ref = None self._monitor_start = None @@ -106,7 +121,8 @@ def __init__(self, runner, gateway, target, config): assert self._loaded_config, 'config was not loaded' self._write_module_config(self._loaded_config, self._device_aux_path()) self.remaining_tests = self._get_enabled_tests() - LOGGER.info('Host %s running with enabled tests %s', self.target_port, self.remaining_tests) + self.logger.info('Host %s running with enabled tests %s', self.target_port, + self.remaining_tests) self._report = ReportGenerator(config, self._INST_DIR, self.target_mac, self._loaded_config) self.record_result('startup', state=MODE.PREP) @@ -115,6 +131,7 @@ def __init__(self, runner, gateway, target, config): self._startup_file = None self.timeout_handler = self._aux_module_timeout_handler self._all_ips = [] + self._ip_listener = None @staticmethod def make_runid(): @@ -133,7 +150,7 @@ def _get_port_base(self): return None conf_base = os.path.abspath(os.path.join(test_config, 'port-%02d' % self.target_port)) if not os.path.isdir(conf_base): - LOGGER.warning('Test config directory not found: %s', conf_base) + self.logger.warning('Test config directory not found: %s', conf_base) return None return conf_base @@ -148,22 +165,25 @@ def _make_control_bundle(self): 'paused': self.state == _STATE.READY } + def _get_test_config(self, test): + return get_test_config(self._loaded_config, test) + def _test_enabled(self, test): fallback_config = {'enabled': test in self._CORE_TESTS} - test_config = self._loaded_config['modules'].get(test, fallback_config) + test_config = self._get_test_config(test) or fallback_config return test_config.get('enabled', True) def _get_test_timeout(self, test): - test_module = self._loaded_config['modules'].get(test) if test == 'hold': return None + test_module = self._get_test_config(test) if not test_module: return self._default_timeout_sec return test_module.get('timeout_sec', self._default_timeout_sec) def get_port_flap_timeout(self, test): """Get port toggle timeout configuration that's specific to each test module""" - test_module = self._loaded_config['modules'].get(test) + test_module = self._get_test_config(test) if not test_module: return None return test_module.get('port_flap_timeout_sec') @@ -204,7 +224,7 @@ def _type_path(self): device_type = dev_config.get('device_type') if not device_type: return None - LOGGER.info('Configuring device %s as type %s', self.target_mac, device_type) + self.logger.info('Configuring device %s as type %s', self.target_mac, device_type) site_path = self.config.get('site_path') type_path = os.path.abspath(os.path.join(site_path, 'device_types', device_type)) return type_path @@ -215,20 +235,20 @@ def _type_aux_path(self): return None aux_path = os.path.join(type_path, self._AUX_DIR) if not os.path.exists(aux_path): - LOGGER.info('Skipping missing type dir %s', aux_path) + self.logger.info('Skipping missing type dir %s', aux_path) return None return aux_path def _create_device_dir(self, path): - LOGGER.warning('Creating new device dir: %s', path) + self.logger.warning('Creating new device dir: %s', path) os.makedirs(path) template_dir = self.config.get('device_template') if not template_dir: - LOGGER.warning('Skipping defaults since no device_template found') + self.logger.warning('Skipping defaults since no device_template found') return - LOGGER.info('Copying template files from %s to %s', template_dir, path) + self.logger.info('Copying template files from %s to %s', template_dir, path) for file in os.listdir(template_dir): - LOGGER.info('Copying %s...', file) + self.logger.info('Copying %s...', file) shutil.copy(os.path.join(template_dir, file), path) def _upload_file(self, path): @@ -237,7 +257,7 @@ def _upload_file(self, path): def initialize(self): """Fully initialize a new host set""" - LOGGER.info('Target port %d initializing...', self.target_port) + self.logger.info('Target port %d initializing...', self.target_port) # There is a race condition here with ovs assigning ports, so wait a bit. time.sleep(2) shutil.rmtree(self.devdir, ignore_errors=True) @@ -245,6 +265,7 @@ def initialize(self): self._initialize_config() network = self.runner.network self._mirror_intf_name = network.create_mirror_interface(self.target_port) + self._topology_hook() if self.config['test_list']: self._start_run() else: @@ -268,9 +289,27 @@ def _state_transition(self, target, expected=None): message = 'state was %s expected %s' % (self.state, expected) assert self.state == expected, message assert self.state != _STATE.TERM, 'host already terminated' - LOGGER.debug('Target port %d state: %s -> %s', self.target_port, self.state, target) + self.logger.debug('Target port %d state: %s -> %s', self.target_port, self.state, target) self.state = target + def _build_switch_info(self) -> usi.SwitchInfo: + switch_config = self._get_switch_config() + model_str = switch_config['model'] + if model_str == 'FAUX_SWITCH': + return None + if model_str: + switch_model = usi.SwitchModel.Value(model_str) + else: + switch_model = usi.SwitchModel.OVS_SWITCH + params = { + "ip_addr": switch_config["ip"], + "device_port": self.target_port, + "model": switch_model, + "username": switch_config["username"], + "password": switch_config["password"] + } + return usi.SwitchInfo(**params) + def is_running(self): """Return True if this host is running active test.""" return self.state != _STATE.ERROR and self.state != _STATE.DONE @@ -285,14 +324,35 @@ def notify_activate(self): self._record_result('startup', state=MODE.HOLD) return self.state == _STATE.WAITING + def connect_port(self, connect): + """Connects/Disconnects port for this host""" + switch_info = self._build_switch_info() + if not switch_info: + self.logger.info('No switch model found, skipping port connect') + return False + try: + with grpc.insecure_channel(self._usi_config.get('url')) as channel: + timeout = self._usi_config.get('rpc_timeout_sec', self._RPC_TIMEOUT_SEC) + stub = usi_service.USIServiceStub(channel) + if connect: + res = stub.connect(switch_info, timeout=timeout) + else: + res = stub.disconnect(switch_info, timeout=timeout) + self.logger.info('Target port %s %s successful? %s', self.target_port, "connect" + if connect else "disconnect", res.success) + except Exception as e: + self.logger.error(e) + raise e + return True + def _prepare(self): - LOGGER.info('Target port %d waiting for ip as %s', self.target_port, self.target_mac) + self.logger.info('Target port %d waiting for ip as %s', self.target_port, self.target_mac) self._state_transition(_STATE.WAITING, _STATE.INIT) self.record_result('sanity', state=MODE.DONE) - self.record_result('ipaddr', state=MODE.EXEC) + self.record_result('acquire', state=MODE.EXEC) static_ip = self._get_static_ip() if static_ip: - LOGGER.info('Target port %d using static ip', self.target_port) + self.logger.info('Target port %d using static ip', self.target_port) time.sleep(self._STARTUP_MIN_TIME_SEC) self.runner.ip_notify(MODE.NOPE, { 'mac': self.target_mac, @@ -304,9 +364,9 @@ def _prepare(self): # enables dhcp response for this device wait_time = self.runner.config.get("long_dhcp_response_sec") \ if dhcp_mode == 'long_response' else 0 - LOGGER.info('Target port %d using %s DHCP mode, wait %s', - self.target_port, dhcp_mode, wait_time) - self.gateway.execute_script('change_dhcp_response_time', self.target_mac, wait_time) + self.logger.info('Target port %d using %s DHCP mode, wait %s', + self.target_port, dhcp_mode, wait_time) + self.gateway.change_dhcp_response_time(self.target_mac, wait_time) _ = [listener(self) for listener in self._dhcp_listeners] def _aux_module_timeout_handler(self): @@ -315,7 +375,7 @@ def _aux_module_timeout_handler(self): def _main_module_timeout_handler(self): self.test_host.terminate() - self._docker_callback(exception=self._TIMEOUT_EXCEPTION) + self._module_callback(exception=self._TIMEOUT_EXCEPTION) def heartbeat(self): """Checks module run time for each event loop""" @@ -326,7 +386,8 @@ def heartbeat(self): nowtime = gcp.parse_timestamp(gcp.get_timestamp()) if nowtime >= timeout: if self.timeout_handler: - LOGGER.error('Monitoring timeout for %s after %ds', self.test_name, timeout_sec) + self.logger.error('Monitoring timeout for %s after %ds', self.test_name, + timeout_sec) # ensure it's called once handler, self.timeout_handler = self.timeout_handler, None handler() @@ -340,15 +401,15 @@ def _finalize_report(self): report_paths = self._report.finalize() if self._trigger_path: report_paths.update({'trigger_path': self._trigger_path}) - LOGGER.info('Finalized with reports %s', list(report_paths.keys())) + self.logger.info('Finalized with reports %s', list(report_paths.keys())) report_blobs = {name: self._upload_file(path) for name, path in report_paths.items()} self.record_result('terminate', state=MODE.TERM, **report_blobs) self._report = None def terminate(self, reason, trigger=True): """Terminate this host""" - LOGGER.info('Target port %d terminate, running %s, trigger %s: %s', self.target_port, - self._host_name(), trigger, reason) + self.logger.info('Target port %d terminate, running %s, trigger %s: %s', self.target_port, + self._host_name(), trigger, reason) self._state_transition(_STATE.TERM) self._release_config() self._monitor_cleanup() @@ -360,8 +421,8 @@ def terminate(self, reason, trigger=True): self.test_host = None self.timeout_handler = None except Exception as e: - LOGGER.error('Target port %d terminating test: %s', self.target_port, e) - LOGGER.exception(e) + self.logger.error('Target port %d terminating test: %s', self.target_port, e) + self.logger.exception(e) if trigger: self.runner.target_set_complete(self.target_port, 'Target port %d termination: %s' % ( @@ -380,8 +441,11 @@ def ip_notify(self, target_ip, state=MODE.DONE, delta_sec=-1): with open(self._trigger_path, 'a') as output_stream: output_stream.write('%s %s %d\n' % (target_ip, state, delta_sec)) self._all_ips.append({"ip": target_ip, "timestamp": time.time()}) - if self._get_dhcp_mode() == "ip_change" and len(self._all_ips) == 1: - self.gateway.request_new_ip(self.target_mac) + # Update ip directly if it's already triggered. + if self.target_ip: + self.target_ip = target_ip + if self.test_host: + self.test_host.ip_listener(target_ip) def trigger_ready(self): """Check if this host is ready to be triggered""" @@ -397,41 +461,41 @@ def trigger_ready(self): def trigger(self, state=MODE.DONE, target_ip=None, exception=None, delta_sec=-1): """Handle device trigger""" if not self.target_ip and not self.trigger_ready(): - LOGGER.warn('Target port %d ignoring premature trigger', self.target_port) + self.logger.warn('Target port %d ignoring premature trigger', self.target_port) return False if self.target_ip: - LOGGER.debug('Target port %d already triggered', self.target_port) + self.logger.debug('Target port %d already triggered', self.target_port) assert self.target_ip == target_ip, "target_ip mismatch" return True self.target_ip = target_ip self._record_result('info', state='%s/%s' % (self.target_mac, target_ip)) - self.record_result('ipaddr', ip=target_ip, state=state, exception=exception) + self.record_result('acquire', ip=target_ip, state=state, exception=exception) if exception: self._state_transition(_STATE.ERROR) self.runner.target_set_error(self.target_port, exception) else: - LOGGER.info('Target port %d triggered as %s', self.target_port, target_ip) + self.logger.info('Target port %d triggered as %s', self.target_port, target_ip) self._state_transition(_STATE.BASE, _STATE.WAITING) return True def _ping_test(self, src, dst, src_addr=None): if not src or not dst: - LOGGER.error('Invalid ping test params, src=%s, dst=%s', src, dst) + self.logger.error('Invalid ping test params, src=%s, dst=%s', src, dst) return False return self.runner.ping_test(src, dst, src_addr=src_addr) def _startup_scan(self): self._startup_file = os.path.join(self.scan_base, 'startup.pcap') self._startup_time = datetime.now() - LOGGER.info('Target port %d startup pcap capture', self.target_port) + self.logger.info('Target port %d startup pcap capture', self.target_port) self._monitor_scan(self._startup_file) def _monitor_scan(self, output_file, timeout=None): assert not self._monitor_ref, 'tcp_monitor already active' network = self.runner.network tcp_filter = '' - LOGGER.info('Target port %d pcap intf %s for %ss output in %s', - self.target_port, self._mirror_intf_name, timeout, output_file) + self.logger.info('Target port %d pcap intf %s for %ss output in %s', + self.target_port, self._mirror_intf_name, timeout, output_file) helper = tcpdump_helper.TcpdumpHelper(network.pri, tcp_filter, packets=None, intf_name=self._mirror_intf_name, timeout=timeout, pcap_out=output_file, @@ -447,10 +511,10 @@ def _base_start(self): success = self._base_tests() self._monitor_cleanup() if not success: - LOGGER.warning('Target port %d base tests failed', self.target_port) + self.logger.warning('Target port %d base tests failed', self.target_port) self._state_transition(_STATE.ERROR) return - LOGGER.info('Target port %d done with base.', self.target_port) + self.logger.info('Target port %d done with base.', self.target_port) self._background_scan() except Exception as e: self._monitor_cleanup() @@ -458,7 +522,7 @@ def _base_start(self): def _monitor_cleanup(self, forget=True): if self._monitor_ref: - LOGGER.info('Target port %d network pcap complete', self.target_port) + self.logger.info('Target port %d network pcap complete', self.target_port) active = self._monitor_ref.stream() and not self._monitor_ref.stream().closed assert active == forget, 'forget and active mismatch' self._upload_file(self._startup_file) @@ -468,7 +532,7 @@ def _monitor_cleanup(self, forget=True): self._monitor_ref = None def _monitor_error(self, exception, forget=False): - LOGGER.error('Target port %d monitor error: %s', self.target_port, exception) + self.logger.error('Target port %d monitor error: %s', self.target_port, exception) self._monitor_cleanup(forget=forget) self.record_result(self.test_name, exception=exception) self._state_transition(_STATE.ERROR) @@ -477,13 +541,13 @@ def _monitor_error(self, exception, forget=False): def _background_scan(self): self._state_transition(_STATE.MONITOR, _STATE.BASE) if not self._monitor_scan_sec: - LOGGER.info('Target port %d skipping background pcap', self.target_port) + self.logger.info('Target port %d skipping background pcap', self.target_port) self._monitor_continue() return self.record_result('monitor', time=self._monitor_scan_sec, state=MODE.EXEC) monitor_file = os.path.join(self.scan_base, 'monitor.pcap') - LOGGER.info('Target port %d background pcap for %ds', - self.target_port, self._monitor_scan_sec) + self.logger.info('Target port %d background pcap for %ds', + self.target_port, self._monitor_scan_sec) self._monitor_scan(monitor_file, timeout=self._monitor_scan_sec) def _monitor_timeout(self, timeout): @@ -494,19 +558,20 @@ def _monitor_timeout(self, timeout): self._monitor_complete() def _monitor_complete(self): - LOGGER.info('Target port %d pcap complete', self.target_port) + self.logger.info('Target port %d pcap complete', self.target_port) self._monitor_cleanup(forget=False) self.record_result('monitor', state=MODE.DONE) self._monitor_continue() def _monitor_continue(self): self._state_transition(_STATE.NEXT, _STATE.MONITOR) + self.test_name = None self._run_next_test() def _base_tests(self): self.record_result('base', state=MODE.EXEC) if not self._ping_test(self.gateway.host, self.target_ip): - LOGGER.debug('Target port %d warmup ping failed', self.target_port) + self.logger.debug('Target port %d warmup ping failed', self.target_port) try: success1 = self._ping_test(self.gateway.host, self.target_ip), 'simple ping failed' success2 = self._ping_test(self.gateway.host, self.target_ip, @@ -521,20 +586,19 @@ def _base_tests(self): return True def _run_next_test(self): + assert not self.test_name, 'test_name defined: %s' % self.test_name try: if self.remaining_tests: - LOGGER.debug('Target port %d executing tests %s', - self.target_port, self.remaining_tests) - self.timeout_handler = self._main_module_timeout_handler - self._docker_test(self.remaining_tests.pop(0)) + self.logger.debug('Target port %d executing tests %s', + self.target_port, self.remaining_tests) + self._run_test(self.remaining_tests.pop(0)) else: - LOGGER.info('Target port %d no more tests remaining', self.target_port) + self.logger.info('Target port %d no more tests remaining', self.target_port) self.timeout_handler = self._aux_module_timeout_handler self._state_transition(_STATE.DONE, _STATE.NEXT) - self.test_name = None self.record_result('finish', state=MODE.FINE) except Exception as e: - LOGGER.error('Target port %d start error: %s', self.target_port, e) + self.logger.error('Target port %d start error: %s', self.target_port, e) self._state_transition(_STATE.ERROR) self.runner.target_set_error(self.target_port, e) @@ -547,12 +611,15 @@ def _device_aux_path(self): os.makedirs(path) return path - def _docker_test(self, test_name): - self.test_name = test_name - self.test_start = gcp.get_timestamp() - self.test_host = docker_test.DockerTest(self.runner, self.target_port, - self.devdir, test_name) - LOGGER.debug('test_host start %s/%s', test_name, self._host_name()) + def _new_test(self, test_name): + clazz = ipaddr_test.IpAddrTest if test_name == 'ipaddr' else docker_test.DockerTest + return clazz(self, self.target_port, self.devdir, test_name, self._loaded_config) + + def _run_test(self, test_name): + self.timeout_handler = self._main_module_timeout_handler + self.test_host = self._new_test(test_name) + + self.logger.info('Target port %d start %s', self.target_port, self._host_name()) try: self.test_port = self.runner.allocate_test_port(self.target_port) @@ -561,7 +628,9 @@ def _docker_test(self, test_name): raise e try: - self._start_test_host() + self._start_test(test_name) + params = self._get_module_params() + self.test_host.start(self.test_port, params, self._module_callback, self._finish_hook) except Exception as e: self.test_host = None self.runner.release_test_port(self.target_port, self.test_port) @@ -569,14 +638,34 @@ def _docker_test(self, test_name): self._monitor_cleanup() raise e - def _start_test_host(self): - params = self._get_module_params() + def _start_test(self, test_name): + self.test_name = test_name + self.test_start = gcp.get_timestamp() self._write_module_config(self._loaded_config, self._host_tmp_path()) self._record_result(self.test_name, config=self._loaded_config, state=MODE.CONF) self.record_result(self.test_name, state=MODE.EXEC) self._monitor_scan(os.path.join(self.scan_base, 'test_%s.pcap' % self.test_name)) self._state_transition(_STATE.TESTING, _STATE.NEXT) - self.test_host.start(self.test_port, params, self._docker_callback, self._finish_hook) + + def _end_test(self, state=MODE.DONE, return_code=None, exception=None): + self._monitor_cleanup() + self._state_transition(_STATE.NEXT, _STATE.TESTING) + report_path = os.path.join(self._host_tmp_path(), 'report.txt') + activation_log_path = os.path.join(self._host_dir_path(), 'activate.log') + module_config_path = os.path.join(self._host_tmp_path(), self._MODULE_CONFIG) + remote_paths = {} + for result_type, path in ((ResultType.REPORT_PATH, report_path), + (ResultType.ACTIVATION_LOG_PATH, activation_log_path), + (ResultType.MODULE_CONFIG_PATH, module_config_path)): + if os.path.isfile(path): + self._report.accumulate(self.test_name, {result_type: path}) + remote_paths[result_type.value] = self._upload_file(path) + self.record_result(self.test_name, state=state, code=return_code, exception=exception, + **remote_paths) + self.test_name = None + self.test_host = None + self.timeout_handler = None + self._run_next_test() def _get_module_params(self): switch_setup = self.switch_setup if 'mods_addr' in self.switch_setup else None @@ -620,35 +709,27 @@ def _finish_hook(self): finish_dir = os.path.join(self.devdir, 'finish', self._host_name()) shutil.rmtree(finish_dir, ignore_errors=True) os.makedirs(finish_dir) - LOGGER.info('Executing finish_hook: %s %s', self._finish_hook_script, finish_dir) + self.logger.info('Executing finish_hook: %s %s', self._finish_hook_script, finish_dir) os.system('%s %s 2>&1 > %s/finish.out' % (self._finish_hook_script, finish_dir, finish_dir)) - def _docker_callback(self, return_code=None, exception=None): + def _topology_hook(self): + if self._topology_hook_script: + update_dir = self._NETWORK_DIR + self.logger.info('Executing topology_hook: %s %s', + self._topology_hook_script, update_dir) + os.system('%s %s 2>&1 > %s/update.out' % + (self._topology_hook_script, update_dir, update_dir)) + + def _module_callback(self, return_code=None, exception=None): host_name = self._host_name() - LOGGER.info('Host callback %s/%s was %s with %s', - self.test_name, host_name, return_code, exception) - self._monitor_cleanup() + self.logger.info('Host callback %s/%s was %s with %s', + self.test_name, host_name, return_code, exception) failed = return_code or exception state = MODE.MERR if failed else MODE.DONE - report_path = os.path.join(self._host_tmp_path(), 'report.txt') - activation_log_path = os.path.join(self._host_dir_path(), 'activate.log') - module_config_path = os.path.join(self._host_tmp_path(), self._MODULE_CONFIG) - remote_paths = {} - for result_type, path in ((ResultType.REPORT_PATH, report_path), - (ResultType.ACTIVATION_LOG_PATH, activation_log_path), - (ResultType.MODULE_CONFIG_PATH, module_config_path)): - if os.path.isfile(path): - self._report.accumulate(self.test_name, {result_type: path}) - remote_paths[result_type.value] = self._upload_file(path) - self.record_result(self.test_name, state=state, code=return_code, exception=exception, - **remote_paths) self.runner.release_test_port(self.target_port, self.test_port) - self._state_transition(_STATE.NEXT, _STATE.TESTING) - assert self.test_host, '_docker_callback with no test_host defined' - self.test_host = None - self.timeout_handler = None - self._run_next_test() + assert self.test_host, '_module_callback with no test_host defined' + self._end_test(state=state, return_code=return_code, exception=exception) def _merge_run_info(self, config): config['run_info'] = { @@ -672,8 +753,8 @@ def record_result(self, name, **kwargs): """Record a named result for this test""" current = gcp.get_timestamp() if name != self.test_name: - LOGGER.debug('Target port %d report %s start %s', - self.target_port, name, current) + self.logger.debug('Target port %d report %s start %s', + self.target_port, name, current) self.test_name = name self.test_start = current if name: @@ -709,12 +790,12 @@ def _exception_message(self, exception): return str(exception) def _control_updated(self, control_config): - LOGGER.info('Updated control config: %s %s', self.target_mac, control_config) + self.logger.info('Updated control config: %s %s', self.target_mac, control_config) paused = control_config.get('paused') if not paused and self.is_ready(): self._start_run() elif paused and not self.is_ready(): - LOGGER.warning('Inconsistent control state for update of %s', self.target_mac) + self.logger.warning('Inconsistent control state for update of %s', self.target_mac) def reload_config(self): """Trigger a config reload due to an external config change.""" @@ -723,12 +804,12 @@ def reload_config(self): if device_ready: self._loaded_config = new_config config_bundle = self._make_config_bundle(new_config) - LOGGER.info('Device config reloaded: %s %s', device_ready, self.target_mac) + self.logger.info('Device config reloaded: %s %s', device_ready, self.target_mac) self._record_result(None, run_info=device_ready, config=config_bundle) return new_config def _dev_config_updated(self, dev_config): - LOGGER.info('Device config update: %s %s', self.target_mac, dev_config) + self.logger.info('Device config update: %s %s', self.target_mac, dev_config) self._write_module_config(dev_config, self._device_base) self.reload_config() diff --git a/daq/ipaddr_test.py b/daq/ipaddr_test.py new file mode 100644 index 0000000000..a7473925ce --- /dev/null +++ b/daq/ipaddr_test.py @@ -0,0 +1,92 @@ +"""Test module encapsulating ip-address tests (including DHCP)""" + +from __future__ import absolute_import +import time +import os +import copy +import logger + +LOGGER = logger.get_logger('ipaddr') + + +class IpAddrTest: + """Module for inline ipaddr tests""" + + # pylint: disable=too-many-arguments + def __init__(self, host, target_port, tmpdir, test_name, module_config): + self.host = host + self.target_port = target_port + self.tmpdir = tmpdir + self.test_config = module_config.get('modules').get('ipaddr') + self.test_dhcp_ranges = copy.copy(self.test_config.get('dhcp_ranges', [])) + self.test_name = test_name + self.host_name = '%s%02d' % (test_name, self.target_port) + self.log_path = os.path.join(self.tmpdir, 'nodes', self.host_name, 'activate.log') + self.log_file = None + self.callback = None + self._ip_callback = None + self.tests = [ + ('dhcp port_toggle test', self._dhcp_port_toggle_test), + ('dhcp multi subnet test', self._multi_subnet_test), + ('ip change test', self._ip_change_test), + ('finalize', self._finalize) + ] + + def start(self, port, params, callback, finish_hook): + """Start the ip-addr tests""" + self.callback = callback + LOGGER.debug('Target port %d starting ipaddr test %s', self.target_port, self.test_name) + self.log_file = open(self.log_path, 'w') + self._next_test() + + def _next_test(self): + try: + name, func = self.tests.pop(0) + self.log('Running ' + name) + func() + except Exception as e: + self.log(str(e)) + self._finalize(exception=e) + + def log(self, message): + """Log an activation message""" + LOGGER.info(message) + self.log_file.write(message + '\n') + + def _dhcp_port_toggle_test(self): + if not self.host.connect_port(False): + self.log('disconnect port not enabled') + return + time.sleep(self.host.config.get("port_debounce_sec", 0) + 1) + self.host.connect_port(True) + self._ip_callback = self._next_test + + def _multi_subnet_test(self): + if not self.test_dhcp_ranges: + self._next_test() + return + dhcp_range = self.test_dhcp_ranges.pop(0) + self.log('Testing dhcp range: ' + str(dhcp_range)) + args = (dhcp_range["start"], dhcp_range["end"], dhcp_range["prefix_length"]) + self.host.gateway.change_dhcp_range(*args) + self._ip_callback = self._multi_subnet_test if self.test_dhcp_ranges else self._next_test + + def _ip_change_test(self): + self.host.gateway.request_new_ip(self.host.target_mac) + self._ip_callback = self._next_test + + def _finalize(self, exception=None): + self.terminate() + self.callback(exception=exception) + + def terminate(self): + """Terminate this set of tests""" + self.log('Module terminating') + self.log_file.close() + self.log_file = None + + def ip_listener(self, target_ip): + """Respond to a ip notification event""" + self.log('ip notification %s' % target_ip) + if self._ip_callback: + self._ip_callback() diff --git a/daq/network.py b/daq/network.py index b622205926..255a6bd259 100644 --- a/daq/network.py +++ b/daq/network.py @@ -136,7 +136,7 @@ def _attach_sec_device_links(self): def is_system_port(self, dpid, port): """Check if the dpid/port combo is the system trunk port""" - return dpid == self.topology.PRI_DPID and port == self.topology.PRI_STACK_PORT + return dpid == self.topology.PRI_DPID and port == self.topology.PRI_TRUNK_PORT def is_device_port(self, dpid, port): """Check if the dpid/port combo is for a valid device""" diff --git a/daq/report.py b/daq/report.py index 311c8fe89e..d3ee8e5046 100644 --- a/daq/report.py +++ b/daq/report.py @@ -16,7 +16,6 @@ import gcp import logger - LOGGER = logger.get_logger('report') class ResultType(Enum): @@ -306,6 +305,7 @@ def _get_test_info(self, test_name): return self._module_config.get('tests', {}).get(test_name, {}) def _write_repitems(self): + from host import get_test_config # Deferring import for (test_name, result_dict) in self._repitems.items(): # To not write a module header if there is nothing to report def writeln(line, test_name=test_name): @@ -318,7 +318,8 @@ def writeln(line, test_name=test_name): writeln(self._TEST_SUBHEADER % "Report") self._append_file(result_dict[ResultType.REPORT_PATH]) if ResultType.MODULE_CONFIG in result_dict: - config = result_dict[ResultType.MODULE_CONFIG].get("modules", {}).get(test_name) + module_configs = result_dict[ResultType.MODULE_CONFIG] + config = get_test_config(module_configs, test_name) if config and len(config) > 0: writeln(self._TEST_SUBHEADER % "Module Config") table = MdTable(["Attribute", "Value"]) diff --git a/daq/runner.py b/daq/runner.py index 631aa43526..5895045271 100644 --- a/daq/runner.py +++ b/daq/runner.py @@ -393,7 +393,7 @@ def _target_set_trigger(self, target_port): # Stops all DHCP response initially # Selectively enables dhcp response at ipaddr stage based on dhcp mode - gateway.execute_script('change_dhcp_response_time', target_mac, -1) + gateway.stop_dhcp_response(target_mac) gateway.attach_target(target_port, target) try: diff --git a/daq/topology.py b/daq/topology.py index 2438b49012..2cda43ebe4 100644 --- a/daq/topology.py +++ b/daq/topology.py @@ -31,13 +31,14 @@ class FaucetTopology: INCOMING_ACL_FORMAT = "dp_%s_incoming_acl" PORTSET_ACL_FORMAT = "dp_%s_portset_%d_acl" LOCAL_ACL_FORMAT = "dp_%s_local_acl" - _DEFAULT_STACK_PORT_NAME = "stack_sec" + _DEFAULT_SEC_TRUNK_NAME = "trunk_sec" _MIRROR_IFACE_FORMAT = "mirror-%d" _MIRROR_PORT_BASE = 1000 _SWITCH_LOCAL_PORT = _MIRROR_PORT_BASE _VLAN_BASE = 1000 PRI_DPID = 1 - PRI_STACK_PORT = 1 + PRI_TRUNK_PORT = 1 + PRI_TRUNK_NAME = 'trunk_pri' _NO_VLAN = "0x0000/0x1000" def __init__(self, config): @@ -92,7 +93,7 @@ def get_sec_dpid(self): return self.sec_dpid def get_sec_port(self): - """Return the secondary stacking port""" + """Return the secondary trunk port""" return self.sec_port def get_device_intfs(self): @@ -173,20 +174,23 @@ def _update_port_vlan(self, port_no, port_set): def _port_set_vlan(self, port_set=None): return self._VLAN_BASE + (port_set if port_set else 0) - def _make_pri_stack_interface(self): + def _make_pri_trunk_interface(self): interface = {} interface['acl_in'] = self.INCOMING_ACL_FORMAT % self.pri_name - interface['stack'] = {'dp': self.sec_name, 'port': self.sec_port} - interface['name'] = 'stack_pri' + interface['tagged_vlans'] = self._vlan_tags() + interface['name'] = self.PRI_TRUNK_NAME return interface - def _make_sec_stack_interface(self): + def _make_sec_trunk_interface(self): interface = {} interface['acl_in'] = self.INCOMING_ACL_FORMAT % self.sec_name - interface['stack'] = {'dp': self.pri_name, 'port': self.PRI_STACK_PORT} - interface['name'] = self.get_ext_intf() or self._DEFAULT_STACK_PORT_NAME + interface['tagged_vlans'] = self._vlan_tags() + interface['name'] = self.get_ext_intf() or self._DEFAULT_SEC_TRUNK_NAME return interface + def _vlan_tags(self): + return list(range(self._VLAN_BASE, self._VLAN_BASE + self.sec_port)) + def _make_default_acl_rules(self): rules = [] if not self._append_acl_template(rules, 'raw'): @@ -201,7 +205,7 @@ def _make_sec_port_interface(self, port_no): def _make_pri_interfaces(self): interfaces = {} - interfaces[self.PRI_STACK_PORT] = self._make_pri_stack_interface() + interfaces[self.PRI_TRUNK_PORT] = self._make_pri_trunk_interface() for port_set in range(1, self.sec_port): for port in self._get_gw_ports(port_set): interfaces[port] = self._make_gw_interface(port_set) @@ -212,7 +216,7 @@ def _make_pri_interfaces(self): def _make_sec_interfaces(self): interfaces = {} - interfaces[self.sec_port] = self._make_sec_stack_interface() + interfaces[self.sec_port] = self._make_sec_trunk_interface() for port in range(1, self.sec_port): interfaces[port] = self._make_sec_port_interface(port) return interfaces @@ -227,23 +231,24 @@ def _make_acl_include(self): def _make_pri_topology(self): pri_dp = {} pri_dp['dp_id'] = self.PRI_DPID - pri_dp['name'] = self.pri_name - pri_dp['stack'] = {'priority':1} pri_dp['interfaces'] = self._make_pri_interfaces() return pri_dp def _make_sec_topology(self): sec_dp = {} sec_dp['dp_id'] = self.sec_dpid - sec_dp['name'] = self.sec_name sec_dp['interfaces'] = self._make_sec_interfaces() return sec_dp + def _has_sec_switch(self): + return self.sec_dpid and self.sec_port + def _make_base_network_topology(self): assert self.pri, 'pri dataplane not configured' dps = {} dps['pri'] = self._make_pri_topology() - dps['sec'] = self._make_sec_topology() + if self._has_sec_switch(): + dps['sec'] = self._make_sec_topology() topology = {} topology['dps'] = dps topology['vlans'] = self._make_vlan_description(10) diff --git a/docker/include/bacnet/bacnetFaux/src/main/java/FauxDeviceEngine/helper/FileManager.java b/docker/include/bacnet/bacnetFaux/src/main/java/FauxDeviceEngine/helper/FileManager.java new file mode 100644 index 0000000000..35ef1bc27c --- /dev/null +++ b/docker/include/bacnet/bacnetFaux/src/main/java/FauxDeviceEngine/helper/FileManager.java @@ -0,0 +1,74 @@ +package helper; + +import java.io.File; + +public class FileManager { + + private String filePath = ""; + private String csvName = "pics"; + private String csvExtension = ".csv"; + private boolean debug = false; + + /** + * Checks if pics.csv exists. + * @return if pics.csv exists + */ + public boolean checkDevicePicCSV() { + String csvFolder = getCSVPath(); + try { + File[] listFiles = new File(csvFolder).listFiles(); + for (int i = 0; i < listFiles.length; i++) { + if (listFiles[i].isFile()) { + String fileName = listFiles[i].getName(); + if (fileName.contains(csvName) + && fileName.endsWith(csvExtension)) { + System.out.println("pics.csv file found in " + csvFolder); + setFilePath(fileName); + return true; + } + } + } + String errorMessage = "pics.csv not found.\n"; + System.err.println(errorMessage); + } catch (Exception e) { + System.out.println("Error in reading " + csvName + csvExtension + " in " + csvFolder); + } + return false; + } + + private void setFilePath(String fileName) { + String absolutePath = getCSVPath(); + this.filePath = absolutePath + "/" + fileName; + } + + public String getFilePath() { + return this.filePath; + } + + /** + * Returns absolute path to the working directory. + */ + public String getAbsolutePath() { + String absolutePath = ""; + String systemPath = System.getProperty("user.dir"); + System.out.println("system_path: " + systemPath); + String[] pathArr = systemPath.split("/"); + for (int count = 0; count < pathArr.length; count++) { + if (pathArr[count].equals("bacnetTests")) { + break; + } + absolutePath += pathArr[count] + "/"; + } + return absolutePath; + } + + /** + * Returns directory pics.csv is located within test container + */ + public String getCSVPath() { + if (debug) { + return "src/main/resources"; + } + return "/config/type"; + } +} diff --git a/docker/include/bin/start_faux b/docker/include/bin/start_faux index 94c9711ab3..bd1cb160a1 100755 --- a/docker/include/bin/start_faux +++ b/docker/include/bin/start_faux @@ -126,6 +126,15 @@ if [ -n "${options[telnet]}" ]; then (while true; do echo Telnet `hostname`; nc -nvlt -p 23 -e `which hostname`; done) & fi +if [ -n "${options[ssh]}" ]; then + echo Starting SSH server + /usr/local/sbin/sshd +elif [ -n "${options[sshv1]}" ]; then + echo Starting SSHv1 server + echo 'Protocol 1' >> /usr/local/etc/sshd_config + /usr/local/sbin/sshd +fi + if [ -n "${options[bacnet]}" ]; then echo Starting bacnet loop device. java -cp bacnetTests/build/libs/bacnet-1.0-SNAPSHOT-all.jar \ @@ -136,9 +145,21 @@ elif [ -n "${options[bacnetfail]}" ]; then FauxDeviceEngine.EntryPoint $local_ip $broadcast_ip "Faux-Device-Fail.json" & fi -if [ -n "${options[ntp_client]}" ]; then - echo Starting ntp client. - java -jar NTPClient/build/libs/NTPClient-1.0-SNAPSHOT.jar "time.google.com" "123" "3" & +# NTPv4 query to the NTP server learnt from DHCP. +# NTPv3 query to the IP of time.google.com (since resolv.conf is modified by other tests) +STATIC_NTP_SERVER=216.239.35.8 +if [ -n "${options[ntpv4]}" ]; then + dhcp_ntp=$(fgrep NTPSERVERS= /run/ntpdate.dhcp) + ntp_server=`echo $dhcp_ntp | cut -d "'" -f 2` + echo Transmitting NTP query to $ntp_server using NTPv4 + java -jar NTPClient/build/libs/NTPClient-1.0-SNAPSHOT.jar $ntp_server 123 4 2 & + sleep 5 +elif [ -n "${options[ntpv3]}" ]; then + (while date; do + echo Transmitting NTP query to $STATIC_NTP_SERVER using NTPv3 + java -jar NTPClient/build/libs/NTPClient-1.0-SNAPSHOT.jar $STATIC_NTP_SERVER 123 3 2 & + sleep 5 + done) & fi # ntp_pass queries the NTP server learnt from DHCP. ntp_fail sends to time.google.com @@ -155,7 +176,7 @@ if [ -n "${options[ntp_pass]}" -o -n "${options[ntp_fail]}" ]; then fi echo Transmitting NTP query to $ntp_server ntpdate -q -p 1 $ntp_server - sleep 10 + sleep 5 done) & fi @@ -201,10 +222,10 @@ fi if [ -n "${options[pubber]}" ]; then echo Running cloud pubber tool... (while date; do - pubber/bin/run - # Do https query in case pubber is not configured, for testing port 443 - curl -o /dev/null https://google.com - sleep 30 + pubber/bin/run local/pubber.json + # Do https query in case pubber is not configured, for testing port 443 + curl -o /dev/null https://google.com + sleep 30 done) & fi diff --git a/docker/include/bin/test_ping b/docker/include/bin/test_ping index 99bc957d83..b66393a079 100755 --- a/docker/include/bin/test_ping +++ b/docker/include/bin/test_ping @@ -88,8 +88,8 @@ echo Done with basic connectivity tests | tee -a $MONO_LOG echo Checking startup NTP ntp_target=${TARGET_IP%.*}.2 -ntp_request=`tcpdump -env -c 1 -r /scans/startup.pcap dst port 123 | wc -l` -ntp_proper=`tcpdump -env -c 1 -r /scans/startup.pcap dst port 123 and dst host $ntp_target | wc -l` +ntp_request=`tcpdump -env -c 1 -r /scans/monitor.pcap dst port 123 | wc -l` +ntp_proper=`tcpdump -env -c 1 -r /scans/monitor.pcap dst port 123 and dst host $ntp_target | wc -l` if [ "$ntp_request" == 0 ]; then ntp_result=skip ntp_summary="No NTP traffic detected" diff --git a/docker/include/networking_scripts/change_dhcp_range b/docker/include/networking_scripts/change_dhcp_range new file mode 100755 index 0000000000..0c45cd6bae --- /dev/null +++ b/docker/include/networking_scripts/change_dhcp_range @@ -0,0 +1,24 @@ +#!/bin/bash -e +# +# Dynamically change DHCP lease range, requires killing and restarting +# dnsmasq as per documentation (SIGHUP does not reload configuration file). +LOCAL_IF=${LOCAL_IF:-$HOSTNAME-eth0} + +range_start=$1 +range_end=$2 +prefix_len=$3 +if [ -z $range_start -o -z $range_end -o -z $prefix_len ]; then + echo "Usage: change_dhcp_range range_start range_end prefix_len" + exit 1 +fi +while [ $(cat /etc/dnsmasq.conf | egrep "^dhcp-range=" | wc -l) == 0 ]; do + sleep 1 +done +ip addr add $range_start/$prefix_len dev $LOCAL_IF || true +original=$(cat /etc/dnsmasq.conf | egrep "^dhcp-range=" | head -1) +lease=$(echo $original | cut -d',' -f 3) +if [ -n "lease" ]; then + lease=",$lease" +fi +new="dhcp-range=$range_start,$range_end$lease" +flock /etc/dnsmasq.conf sed -i s/$original/$new/ /etc/dnsmasq.conf \ No newline at end of file diff --git a/docker/include/networking_scripts/change_lease_time b/docker/include/networking_scripts/change_lease_time index 306e985604..0cb8986c8a 100755 --- a/docker/include/networking_scripts/change_lease_time +++ b/docker/include/networking_scripts/change_lease_time @@ -7,10 +7,10 @@ if [ -z $lease ]; then echo "Lease time not defined." exit 1 fi -while [ $(cat /etc/dnsmasq.conf | grep dhcp-range=10.20 | wc -l) == 0 ]; do +while [ $(cat /etc/dnsmasq.conf | grep "^dhcp-range=" | wc -l) == 0 ]; do sleep 1 done -original=$(cat /etc/dnsmasq.conf | grep dhcp-range=10.20 | head -1) +original=$(cat /etc/dnsmasq.conf | grep "^dhcp-range=" | head -1) new="$(echo $original | cut -d',' -f 1,2),$lease" flock /etc/dnsmasq.conf sed -i s/$original/$new/ /etc/dnsmasq.conf diff --git a/docker/modules/Dockerfile.faux1 b/docker/modules/Dockerfile.faux1 index 7c8e9c0be0..c6e76a865b 100644 --- a/docker/modules/Dockerfile.faux1 +++ b/docker/modules/Dockerfile.faux1 @@ -15,21 +15,31 @@ ENV BACHASH=94a794a756ee0d37c6a2e53e08747ee021415aa8 RUN bin/retry_cmd git clone https://github.com/grafnu/bacnet4j.git --single-branch \ && cd bacnet4j && git reset --hard $BACHASH && ../bin/retry_cmd ./gradlew shadow -COPY pubber/ pubber/ +COPY udmi/pubber/ pubber/ RUN pubber/bin/build +# Seperate stage to build older version of SSH and SSL +FROM daqf/aardvark:latest as ssh_build + +RUN $AG update && $AG install wget make build-essential gcc libz-dev ca-certificates + +# Build SSH, OpenSSL from source and configure + +COPY subset/security/sshfaux/*.sh ./ +RUN sh ssh_build.sh + FROM daqf/aardvark:latest # Run this separately so it can be shared with other builds. RUN $AG update && $AG install openjdk-8-jre RUN $AG update && $AG install openjdk-8-jdk git RUN $AG update && $AG install isc-dhcp-client ethtool network-manager netcat curl\ - python ifupdown openssl ssh nano apache2-utils ntpdate + python ifupdown openssl nano apache2-utils ntpdate # Additional OS dependencies RUN $AG update && $AG install -y telnetd && $AG install xinetd nginx -COPY subset/network/NTPClient NTPClient +COPY subset/ntp/NTPClient NTPClient RUN cd NTPClient && ./gradlew build COPY subset/network/TransportClient TransportClient @@ -42,7 +52,7 @@ COPY --from=java_build /root/bacnet4j/*.jar bacnet4j/ COPY docker/include/bin/bacnet_discover bin/ COPY --from=java_build /root/pubber/build/libs/*.jar pubber/build/libs/ -COPY pubber/bin/run pubber/bin/ +COPY udmi/pubber/bin/run pubber/bin/ COPY subset/pentests/brute_server.py pentests/ COPY subset/security/tlsfaux tlsfaux/ @@ -52,17 +62,19 @@ COPY subset/bacnet/bacnetTests/src/main/resources/Faux*.json tmp/ COPY --from=java_build /root/bacnet4j/bacnet4j-1.0-SNAPSHOT-all.jar bacnetTests/libs/ RUN cd bacnetTests && ./gradlew build -# SSH dependency -COPY subset/security/ssh_additions.config ssh_additions.config -RUN cat ssh_additions.config >> /etc/ssh/sshd_config - # HTTP/HTTPS dependency COPY subset/security/nginxpass.conf /root/nginx/ COPY subset/security/nginxfail.conf /root/nginx/ COPY subset/security/nginx-site /var/www/nginx-site -# SSH login fix. Otherwise user is kicked off after login -RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd +COPY --from=ssh_build /usr/local/openssl/* /usr/local/openssl/ +COPY --from=ssh_build /usr/local/sbin/* /usr/local/sbin/ +COPY --from=ssh_build /usr/local/bin/* /usr/local/bin/ +COPY --from=ssh_build /usr/local/etc/* /usr/local/etc/ + +COPY subset/security/sshfaux/ssh_privsep.sh ssh_privsep.sh +RUN sh ssh_privsep.sh +RUN /usr/local/bin/ssh-keygen -A # Weird workaround for problem running tcdump in a privlidged container. RUN mv /usr/sbin/tcpdump /usr/bin/tcpdump diff --git a/docs/add_test.md b/docs/add_test.md index f279359570..e460137584 100644 --- a/docs/add_test.md +++ b/docs/add_test.md @@ -34,7 +34,7 @@ A setup for the `pass` test, as an example, woud be configured as follows * `echo host_tests=local/local_tests.conf >> local/system.conf` -- Set tests configuration. This, of course, only works for local development when using the `local_tests.conf` config. To -formalize a test and include it in the overal system build it should be included in +formalize a test and include it in the overall system build it should be included in `config/modules/all.conf`. ## Component Build diff --git a/docs/changelog.md b/docs/changelog.md index a67a7cfd32..54c014b97a 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,33 @@ # Changelog +* 1.8.2 + * GRPC timeouts + usi first command wait fix. (#555) + * Numerous renovate bot updates. +* 1.8.0 + * add security.ssh.version test (#523) + * Refactor UDMI to external repo (#544) + * Additional DHCP test part 3: IP change test (#543) + * Additional DHCP test part 2: Multisubnet test (#539) + * Additional DHCP test part 1 (#532) + * Support for alternate sec switch (not managed by DAQ) (#531) + * Add troubleshooting script (#529) + * Using usi in daq (#520) + * Use trunk rather than stack between switches (#526) + * NTPv4 support (#487) + * Feature/usi OVS switch (#521) +* 1.7.0 + * Add DAQ version to origin summary (#522) + * Add check for git version tag in Travis (#519) + * Minor UDMI updates for pubber keygen + * Update Minimum Send Test (#498) + * Universal Switch Interface (USI) (#496) +* 1.6.1 + * fix image pull in cmd/build (#503) +* 1.6.0 + * cloud test setup documentation (#495) + * Baseline for NTP tests (#494) + * Baseline for DNS test (#492) + * Add manual test summary to test report (#481) + * UDMI logentry schema update (#391) * 1.5.1 * Fix for local-port-as-string issue (#477) * 1.5.0 diff --git a/docs/cloud_tests.md b/docs/cloud_tests.md new file mode 100644 index 0000000000..6ed8a9efed --- /dev/null +++ b/docs/cloud_tests.md @@ -0,0 +1,133 @@ +# Cloud Connection Testing + +A number of additional setup steps are required for enabling testing against "smart devices" +that communicate with the cloud. The tests themselves are part of the `subset/cloud/test_udmi` +module included in the standard DAQ distro. The same basic device-to-cloud validation test +pipeline can be done manually and automatically (through DAQ); it's instructive to fully +understand the manual test pipeline before engaging with the automated setup. + +## Manual Test Pipeline + +The overall device-to-cloud pipeline looks something like the following: + +* Device sends data to the cloud. There's two kinds of devices: + * A faux _reference design_ device called [pubber](pubber.md), which is a completely contained + software device. + * An actual physical device. The setup and configuration of that device will be manufacturer + dependent and so is out of scope for this (DAQ) documentation. +* A configured GCP IoT Core project, registry, and device entry. The +[GCP docs for IoT Core](https://cloud.google.com/iot/docs/how-tos/devices) describe the basics. The +key part is the _authentication key_ (hahaha) that needs to be setup between the local device and +cloud device entry. +* The IoT Core registry is configured with a _PubSub topic_ (not to be confused with an _MQTT topic_), +that provides the bridge between incoming data and consumers of that data. See the GCP documentation +on PubSub for more details. +* (optional) The `gcloud` command line can be used to validate that data is being sent from the +device to the cloud. Something like +`gcloud pubsub subscriptions pull --auto-ack projects/{project}/subscriptions/{sub_id}`. +(Complete documentation for how to use `gcloud` commands is out of scope of this documentation.) +* The [validator tool](validator.md) is what programmatically validates a device data stream, and +is what is ultimately used by `test_udmi` to validate device-cloud communication. + +## Base Local Test Setup + +* The `udmi` module needs to be enabled in build. When running `cmd/build` there should be a line +like `subset/cloud/Dockerfile.test_udmi` in the startup logs. +This is enabled through the `host_tests` config parameter, +which can be set to `config/modules/all.conf` if necessary. On startup, there should be a log +message that includes `udmi`: +``` +Jun 22 08:32:52 runner INFO Configured with tests pass, fail, ping, bacnet, mudgee, nmap, discover, switch, macoui, bacext, tls, password, udmi, manual +``` +* A testing gcp service account `gcp_cred` needs to be setup as described in +[service account setup instructions](service.md). +* The system's default `module_config` needs to enable the `udmi` test, e.g. as per +`resources/setups/baseline/module_config.json`. This can be validated by (runtime) checking +`inst/run-port-01/nodes/udmi01/tmp/module_config.json` to see if it has something like the following: +``` + "udmi": { + "enabled": true + } +``` +* `site_path` config needs to point to a site definition directory, or defaults to `local/site`. +This contains all the site-specific information about devices needed for testing. +* `{site_path}/mac_addrs/{mac_addr}/module_config.json` needs to have a `device_id` defined, e.g. +as in `resources/test_site/mac_addrs/3c5ab41e8f0b/module_config.json`. +* The GCP IoT Core setup needs to have a proper registry and device configred. This can either +be done manually or using the [registrar tool](registrar.md) tool. + +## Integration Testing + +If developing cloud-tests, then the CI build system also needs to have a service account configured +pointing at a suitable GCP project. To run cloud-based tests, setup the Travis `GCP_BASE64_CRED` +env variable with a `base64` encoded service account key for your project. It's recommended to +use a dedicated key with a nice name like `daq-travis`, but not required. Encode the key value +as per below, and cut/paste the resulting string into a +[Travis environment variable](https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-settings) +for a `GCP_BASE64_CRED` variable. Note the `-w 0` option is required for proper parsing/formatting, +as there can't be any newlines in the copied string. + + +$ base64 -w 0 local/gcp_service_account.json +ewoICJ1eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAiYm9zLWRhcS10ZXN0aW5nIiwKICAicHJpd +… +iOiAiaHR0cHM6Ly93LWRhcS10ZXN0aW5nLmlhbS5nc2VydmljZWFjY291bnQuY29tIgp9Cg== + + +### Travis CI Testing + +* Run the [registrar tool](registrar.md) to properly configure the cloud project. +* `gcp_topic` config to `local/system.conf` as described in this doc. +* Configure test subsystem with proper cloud endpoint in `{test_site}/cloud_iot_config.json`. +* Configure the DUT with the proper cloud device credentials (device specific). For _faux_ devices, this means copying +the associated `rsa_private.pkcs8` file to something like `inst/faux/daq-faux-2/local/` (exact path depends on which faux). +* Test with `bin/registrar`, `pubber/bin/run`, and `bin/validate` manually, before integrated testing through DAQ. + +### Is my Travis set up correctly? + +If Travis is set up correctly, you should see messages at the beginning of the log file: +``` +Setting environment variables from repository settings +$ export DOCKER_USERNAME=[secure] +$ export DOCKER_PASSWORD=[secure] +$ export GCP_BASE64_CRED=[secure] +``` + +Further down there would be more details about the cred itself: +``` +Running test script testing/test_aux.sh +Writing test results to inst/test_aux.out and inst/test_aux.gcp +Decoding GCP_BASE64_CRED to inst/config/gcp_service_account.json +base64 wc: 1 1 3097 +GCP service account is "daq-travis@daq-testing.iam.gserviceaccount.com" +``` + +If the `3097` character count is wildly off, then likely something went wrong with the newlines. + +### Travis Build For "External" Pull Requests + +Travis will not use encrypted environment variables when testing against pull requests +from foreign github repositories, even if you've forked from another repository that you +have full control of via Github. Travis authorization != Github authorization, even if +you sign into Travis using Github! This is as it should be b/c security. see the following +for more info: + +- https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-settings +- https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions + +If your test is failing from a PR, you'll see something like in a similar log location: + +``` +Encrypted environment variables have been removed for security reasons. +See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions +Setting environment variables from .travis.yml +$ export DOCKER_STARTUP_TIMEOUT_MS=60000 +$ export DAQ_TEST=aux +``` + +### Other Travis Caveats + +Take note the URL in your browser's address bar when running Travis. You might be on either +travis-ci.com or travis-ci.org. Any particular setup +may end up across both sites for undetermined reasons. Please consult with your browser's +exact URL for more clarity. diff --git a/docs/device_report.md b/docs/device_report.md index 2ab3ab3320..74d7445460 100644 --- a/docs/device_report.md +++ b/docs/device_report.md @@ -56,7 +56,7 @@ Overall device result FAIL |---|---|---|---|---| |Required|1|0|0|0| |Recommended|2|0|0|0| -|Other|1|2|22|2| +|Other|3|2|22|2| |Result|Test|Category|Expectation|Notes| |---|---|---|---|---| @@ -67,6 +67,8 @@ Overall device result FAIL |skip|cloud.udmi.state|Other|Other|No device id| |skip|cloud.udmi.system|Other|Other|No device id| |fail|connection.mac_oui|Other|Other|Manufacturer prefix not found!| +|pass|connection.network.ntp_support|Other|Other|Using NTPv4.| +|pass|connection.network.ntp_update|Other|Other|Device clock synchronized.| |skip|connection.port_duplex|Other|Other|No local IP has been set, check system config| |skip|connection.port_link|Other|Other|No local IP has been set, check system config| |skip|connection.port_speed|Other|Other|No local IP has been set, check system config| @@ -92,15 +94,6 @@ Overall device result FAIL |gone|unknown.fake.monkey|Other|Other|| -## Module ipaddr - - -#### Module Config - -|Attribute|Value| -|---|---| -|timeout_sec|300| - ## Module pass @@ -567,5 +560,31 @@ RESULT pass manual.test.travis Manual test - for testing |---|---| |enabled|True| +## Module ntp + + +#### Report + +``` +-------------------- +connection.network.ntp_support +-------------------- +Device supports NTP version 4. +-------------------- +RESULT pass connection.network.ntp_support Using NTPv4. +-------------------- +connection.network.ntp_update +-------------------- +Device synchronizes its time to the NTP server. +-------------------- +RESULT pass connection.network.ntp_update Device clock synchronized. +``` + +#### Module Config + +|Attribute|Value| +|---|---| +|enabled|True| + ## Report complete diff --git a/docs/integration_testing.md b/docs/integration_testing.md deleted file mode 100644 index 1c6435a9b0..0000000000 --- a/docs/integration_testing.md +++ /dev/null @@ -1,83 +0,0 @@ -# Integration Testing - -DAQ currently uses Travis CI for integration testing: https://travis-ci.org/ - -## Configuration - -The `test_udmi` test module uses the Registrar and Validator to check that a device is -properly communicating through Cloud IoT, automated through DAQ. - -### GCP Credential - -To run cloud-based tests, setup the Travis `GCP_BASE64_CRED` env variable with a `base64` encoded -service account key for your project. It's recommended to use a dedicated key with a nice name -like `daq-travis`, but not required. Encode the key value as per below, and cut/paste the -resulting string into a -[Travis environment variable](https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-settings) -for a `GCP_BASE64_CRED` varaible. Note the `-w 0` option is required for proper parsing/formatting, -as there can't be any newlines in the copied string. - - -$ base64 -w 0 local/gcp_service_account.json -ewoICJ1eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAiYm9zLWRhcS10ZXN0aW5nIiwKICAicHJpd -… -iOiAiaHR0cHM6Ly93LWRhcS10ZXN0aW5nLmlhbS5nc2VydmljZWFjY291bnQuY29tIgp9Cg== - - -## Travis CI Testing - -* Run the [registrar tool](registrar.md) to properly configure the cloud project. -* `gcp_topic` config to `local/system.conf` as described in this doc. -* Configure test subsystem with proper cloud endpoint in `{test_site}/cloud_iot_config.json`. -* Configure the DUT with the proper cloud device credentials (device specific). For _faux_ devices, this means copying -the assocatied `rsa_private.pkcs8` file to someting like `inst/faux/daq-faux-2/local/` (exact path depends on which faux). -* Test with `bin/registrar`, `pubber/bin/run`, and `bin/validate` manually, before integrated testing through DAQ. - -### Is my Travis set up correctly? - -If Travis is set up correctly, you should see messages at the beginning of the log file: -``` -Setting environment variables from repository settings -$ export DOCKER_USERNAME=[secure] -$ export DOCKER_PASSWORD=[secure] -$ export GCP_BASE64_CRED=[secure] -``` - -Further down there would be more details about the cred itself: -``` -Running test script testing/test_aux.sh -Writing test results to inst/test_aux.out and inst/test_aux.gcp -Decoding GCP_BASE64_CRED to inst/config/gcp_service_account.json -base64 wc: 1 1 3097 -GCP service account is "daq-travis@daq-testing.iam.gserviceaccount.com" -``` - -If the `3097` character count is wildly off, then likely something went wrong with the newlines. - -### Travis Build For "External" Pull Requests - -Travis will not use encrypted environment variables when testing against pull requests -from foreign github repositories, even if you've forked from another repository that you -have full control of via Github. Travis authorization != Github authorization, even if -you sign into Travis using Github! This is as it should be b/c security. see the following -for more info: - -- https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-settings -- https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions - -If your test is failing from a PR, you'll see something like in a similar log location: - -``` -Encrypted environment variables have been removed for security reasons. -See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions -Setting environment variables from .travis.yml -$ export DOCKER_STARTUP_TIMEOUT_MS=60000 -$ export DAQ_TEST=aux -``` - -### Other Travis Caveats - -Take note the URL in your browser's address bar when running Travis. You might be on either -travis-ci.com or travis-ci.org. Any particular setup -may end up across both sites for undertermined reasons. Please consult with your browser's -exact URL for more clarity. diff --git a/docs/orchestration.md b/docs/orchestration.md index 4804ec356f..703c5235a0 100644 --- a/docs/orchestration.md +++ b/docs/orchestration.md @@ -11,7 +11,7 @@ to change. ## Data Rouces -The overal orchestration capability relies on several simple data sources: +The overall orchestration capability relies on several simple data sources: 1. [Overall network topology](topologies.md), which indicates how the network hardware is configured. 2. [Device MUD files](../mud_files), which provide an [IETF Standard MUD descriptor](https://datatracker.ietf.org/doc/draft-ietf-opsawg-mud/) that describes diff --git a/docs/pubber.md b/docs/pubber.md deleted file mode 100644 index 588396d1ac..0000000000 --- a/docs/pubber.md +++ /dev/null @@ -1,81 +0,0 @@ -# Pubber Reference Client - -The _Pubber_ reference client is a sample implementation of a client-side 'device' that implements -the [UDMI Schema](../schemas/udmi/README.md). It's not intended to be any sort of production-worthy -code or library, rather just a proof-of-concept of what needs to happen. - -## Build Pubber - -
-~/daq$ pubber/bin/build
-Running in /home/peringknife/daq/pubber
-
-> Task :compileJava
-…
-
-BUILD SUCCESSFUL in 2s
-2 actionable tasks: 1 executed, 1 up-to-date
-
- -## Key Generation - -
-~/daq$ pubber/bin/keygen
-Generating a 2048 bit RSA private key
-............+++
-......................................+++
-writing new private key to 'local/rsa_private.pem'
------
-~/daq$ ls -l local/rsa_*
--rw-r--r-- 1 user primarygroup 1094 Nov 19 18:56 local/rsa_cert.pem
--rw------- 1 user primarygroup 1704 Nov 19 18:56 local/rsa_private.pem
--rw-r--r-- 1 user primarygroup 1216 Nov 19 18:56 local/rsa_private.pkcs8
-
- -After generating the key pair, you'll have to upload/associate the `pubber_cert.pem` public certificate -with the device entry in the cloud console as an _RS256_cert_. (This can be done when the device is -created, or anytime after.) - -## Configuration - -The `local/pubber.json` file configures the key cloud parameters needed for operation -(the actual values in the file shold match your GCP setup): -
-~/daq$ cat local/pubber.json
-{
-  "projectId": "gcp-account",
-  "cloudRegion": "us-central1",
-  "registryId": "sensor_hub",
-  "deviceId": "AHU-1"
-}
-
- -## Operation - -
-~/daq$ pubber/bin/run
-[main] INFO daq.pubber.Pubber - Reading configuration from /home/user/daq/local/pubber.json
-[main] INFO daq.pubber.Pubber - Starting instance for registry sensor_hub
-[main] INFO daq.pubber.MqttPublisher - Creating new publisher-client for GAT-001
-[main] INFO daq.pubber.MqttPublisher - Attempting connection to sensor_hub:GAT-001
-[MQTT Call: projects/gcp-account/locations/us-central1/registries/sensor_hub/devices/GAT-001] INFO daq.pubber.Pubber - Received new config daq.udmi.Message$Config@209307c7
-[MQTT Call: projects/gcp-account/locations/us-central1/registries/sensor_hub/devices/GAT-001] INFO daq.pubber.Pubber - Starting executor with send message delay 2000
-[main] INFO daq.pubber.Pubber - synchronized start config result true
-[MQTT Call: projects/gcp-account/locations/us-central1/registries/sensor_hub/devices/GAT-001] INFO daq.pubber.Pubber - Sending state message for device GAT-001
-…
-[pool-1-thread-1] INFO daq.pubber.Pubber - Sending test message for sensor_hub/GAT-001
-[pool-1-thread-1] INFO daq.pubber.Pubber - Sending test message for sensor_hub/GAT-001
-
- - -## Cloud Setup - -To use Pubber, there needs to be a cloud-side device entry configured in a GCP project configured to -use [Cloud IoT](https://cloud.google.com/iot/docs/). The -[Creating or Editing a Device](https://cloud.google.com/iot/docs/how-tos/devices#creating_or_editing_a_device) -section of the documentation describe how to create a simple device and key-pair (see next section for -a helper script). You can/should substitute the relevant values in the configuration below for your -specific setup. The relevant bits of configuration are the information in the local/pubber.json -file (see above), and the generated public key (also see above). - -Alternatively, you can use the [registrar tool](registrar.md) to automate device registration. diff --git a/docs/registrar.md b/docs/registrar.md deleted file mode 100644 index f63dfc43c4..0000000000 --- a/docs/registrar.md +++ /dev/null @@ -1,182 +0,0 @@ -# Registrar Overview - -The `registrar` is a utility program that registers and updates devies in Cloud IoT. -Running `bin/registrar` will pull the necessary configuraiton values from `local/system.conf`, -build the executable, and register/update devices. - -## Configuration - -The `local/system.conf` file should have the following parameters (in `x=y` syntax): -* `gcp_cred`: Defines the target project and [service account](service.md) to use for configuration. -* `site_path`: [Site-specific configuration](site_path.md) for the devices that need to be registered. -* `schema_path`: Path to metadata schema (see the [DAQ PubSub documentation](pubsub.md) for more details/examples). - -The target `gcp_cred` service account will need the _Cloud IoT Provisioner_ and _Pub/Sub Publisher_ roles. -There also needs to be an existing `registrar` topic (or as configured in `cloud_iot_config.json`, below). - -## Theory Of Operation - -* The target set of _expected_ devices is determined from directory entries in -_{site_path}_/devices/. -* Existing devices that are not listed in the site config are blocked (as per -Cloud IoT device setting). -* If a device directory does not have an appropriate key, one will be automaticaly generated. -* Devices not found in the target registry are automatically created. -* Existing device registy entries are unblocked and updated with the appropriate keys. - -## Device Settings - -When registering or updating a device, the Registrar manipulates a few key pieces of device -information: -* Auth keys: Public authentiation keys for the device. -* Metadata: Various information about a device (e.g. site-code, location in the building). - -This information is sourced from a few key files: - -* `{site_dir}/cloud_iot_config.json`: -Cloud project configuration parameters (`registry_id`, `cloud_region`, etc...). -* `{site_dir}/devices/{device_id}/metadata.json`: -Device metadata (e.g. location, key type). -* `{site_dir}/devices/{device_id}/rsa_private.pem`: -Generated private key for device (used on-device). - -## Sample Output - -The produced `registration_summary.json` document provides an overview of the analyzed files, -clearly any errors that should be addressed for full spec compliance. Additionaly, an -`errors.json` - -
-user@machine:~/daq$ cat local/site/cloud_iot_config.json 
-{
-  "cloud_region": "us-central1",
-  "site_name": "SG-MBC2-B80",
-  "registry_id": "iotRegistry",
-  "registrar_topic": "registrar"
-}
-user@machine:~/daq$ bin/registrar daq-testing
-Activating venv
-Flattening config from local/system.yaml into inst/config/system.conf
-Note: Some input files use or override a deprecated API.
-Note: Recompile with -Xlint:deprecation for details.
-Running tools version 1.5.1-16-g9ed5861
-Using cloud project bos-daq-testing
-Using site config dir local/site
-Using schema root dir schemas/udmi
-Using device filter
-Reading Cloud IoT config from /home/user/daq/local/site/cloud_iot_config.json
-Initializing with default credentials...
-Jun 12, 2020 1:24:37 PM com.google.auth.oauth2.DefaultCredentialsProvider warnAboutProblematicCredentials
-WARNING: Your application has authenticated using end user credentials from Google Cloud SDK. We recommend that most server applications use service accounts instead. If your application continues to use end user credentials from Cloud SDK, you might receive a "quota exceeded" or "API not enabled" error. For more information about service accounts, see https://cloud.google.com/docs/authentication/.
-Created service for project bos-daq-testing
-Working with project bos-daq-testing registry iotRegistry
-Loading local device AHU-1-1
-Loading local device AHU-1-2
-Fetching remote registry iotRegistry
-Updated device entry AHU-1-1
-Sending metadata message for AHU-1-1
-WARNING: An illegal reflective access operation has occurred
-WARNING: Illegal reflective access by com.google.protobuf.UnsafeUtil (file:/home/user/daq/validator/build/libs/validator-1.0-SNAPSHOT-all.jar) to field java.nio.Buffer.address
-WARNING: Please consider reporting this to the maintainers of com.google.protobuf.UnsafeUtil
-WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
-WARNING: All illegal access operations will be denied in a future release
-Updated device entry AHU-1-2
-Sending metadata message for AHU-1-2
-Processed 2 devices
-Updating local/site/devices/AHU-1-1/errors.json
-Updating local/site/devices/AHU-1-2/errors.json
-
-Summary:
-  Device Envelope: 2
-  Device Key: 1
-  Device Validating: 2
-Out of 2 total.
-Done with PubSubPusher
-Registrar complete, exit 0
-user@machine:~/daq$ cat local/site/registration_summary.json 
-{
-  "Envelope" : {
-    "AHU-1-1" : "java.lang.IllegalStateException: Validating envelope AHU-1-1",
-    "AHU-1-2" : "java.lang.IllegalStateException: Validating envelope AHU-1-2"
-  },
-  "Key" : {
-    "AHU-1-2" : "java.lang.RuntimeException: Duplicate credentials found for AHU-1-1 & AHU-1-2"
-  },
-  "Validating" : {
-    "AHU-1-1" : "org.everit.json.schema.ValidationException: #: 43 schema violations found",
-    "AHU-1-2" : "org.everit.json.schema.ValidationException: #: 43 schema violations found"
-  }
-}
-user@machine:~/daq$ head local/site/devices/AHU-1-1/errors.json 
-Exceptions for AHU-1-1
-  Validating envelope AHU-1-1
-    #/deviceId: string [AHU-1-1] does not match pattern ^[A-Z]{2,6}-[1-9][0-9]{0,2}$
-  #: 43 schema violations found
-    #/pointset/points: 40 schema violations found
-      #/pointset/points/chilled_return_water_temperature_sensor/units: °C is not a valid enum value
-      #/pointset/points/chilled_supply_water_temperature_sensor/units: °C is not a valid enum value
-      #/pointset/points/chilled_water_valve_percentage_command/units: % is not a valid enum value
-
- -## Sequence Diagram - -Expected workflow to configure a registry using Registrar: - -* `Device`: Target IoT Device -* `Local`: Local clone of site configuration repo -* `Registrar`: This utility program -* `Registry`: Target Cloud IoT Core registry -* `Repo`: Remote site configuration repo - -All operations are manaul except those involving the `Registrar` tool. - -
-+---------+                +-------+                 +-----------+                 +-----------+ +-------+
-| Device  |                | Local |                 | Registrar |                 | Registry  | | Repo  |
-+---------+                +-------+                 +-----------+                 +-----------+ +-------+
-     |                         |                           |                             |           |
-     |                         |                           |                       Pull repo locally |
-     |                         |<--------------------------------------------------------------------|
-     |                         |    ---------------------\ |                             |           |
-     |                         |    | Run Registrar tool |-|                             |           |
-     |                         |    |--------------------| |                             |           |
-     |                         |                           |                             |           |
-     |                         | Read device configs       |                             |           |
-     |                         |-------------------------->|                             |           |
-     |                         |                           |                             |           |
-     |                         |                           |            Read device list |           |
-     |                         |                           |<----------------------------|           |
-     |                         |                           |                             |           |
-     |                         |           Write auth keys |                             |           |
-     |                         |<--------------------------|                             |           |
-     |                         |                           |                             |           |
-     |                         |                           | Update device entries       |           |
-     |                         |                           |---------------------------->|           |
-     |                         |   ----------------------\ |                             |           |
-     |                         |   | Registrar tool done |-|                             |           |
-     |                         |   |---------------------| |                             |           |
-     |                         |                           |                             |           |
-     |     Install private key |                           |                             |           |
-     |<------------------------|                           |                             |           |
-     |                         |                           |                             |           |
-     |                         | Push changes              |                             |           |
-     |                         |-------------------------------------------------------------------->|
-     |                         |                           |                             |           |
-
- -### Source - -Use with [ASCII Sequence Diagram Creator](https://textart.io/sequence#) - -
-object Device Local Registrar Registry Repo
-Repo -> Local: Pull repo locally
-note left of Registrar: Run Registrar tool
-Local -> Registrar: Read device configs
-Registry -> Registrar: Read device list
-Registrar -> Local: Write auth keys
-Registrar -> Registry: Update device entries
-note left of Registrar: Registrar tool done
-Local -> Device: Install private key
-Local -> Repo: Push changes
-
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 4a8fa1ba09..05aca2c9d6 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -9,7 +9,7 @@ mailing list, and use it as the primary source of troubleshooting. email somebody directly, but will likely result in a slower response time. * The `inst/cmdrun.log` file contains a copy of the console output from DAQ. * This file should be attached to communications about resolving DAQ issues. - * It's not necessary to include any assocaited `local/system.yaml` file, since the + * It's not necessary to include any associated `local/system.yaml` file, since the contents of that are already included. * Make sure everything is running properly using the internal simulation setup before tackling anything to do with external switches or physical devices. @@ -29,12 +29,17 @@ a summary of all test results. * The determination of _PASS_ vs. _FAIL_ is one of policy, not a technical consideration. If the question is "Is it OK if this tests fails or not?" then you need to contact whomever is responsible for policy, not DAQ-proper. - * The reports are _optionally_ available trough the _optionally_ configured + * The reports are _optionally_ available through the _optionally_ configured GCP instance, but that's only relevant after the basics are working. -* Capturing a complete zip of the `inst/` directory should encompass all the -state neesary to diagnose/debug problems, so simply captuing that and sending -it along would be sufficient in most cases. Be wary of file size, as `inst/` -can collect cruft over time and occasionally need to be cleaned. +* Running `bin/techsupport.sh` will create a zipped techsupport file that + contains all configuration, packet captures and runtime logs of a run. + Sending that file is sufficient in most cases. Be wary of file + size, as `inst/` might have large pcap files or older files that can be + trimmed to get more manageable file sizes for email attachments. +* Unless you are developing for DAQ and want the latest code, ensure that you + are on the latest stable software version tracked by the git tag `release_stable`. +* If a test run blocks or errors out, try running `bin/troubleshoot` to detect + some common misconfiguration and setup related issues. ## Test-Specific @@ -82,4 +87,4 @@ directory. * Filter results for the device's MAC address with something like: tcpdump -en -r testing.pacp ether host de:vi:ce:ma:ca:dr. * There is no one-size-fits-all guidance here, because what is expected is - extremeley test-specific. + extremely test-specific. diff --git a/docs/validator.md b/docs/validator.md deleted file mode 100644 index 80ab8c4b24..0000000000 --- a/docs/validator.md +++ /dev/null @@ -1,152 +0,0 @@ -# Validator Setup - -The `validator` is a sub-component of DAQ that can be used to validate JSON files or stream against a schema -defined by the standard [JSON Schema](https://json-schema.org/) format. The validator does not itself specify -any policy, i.e. which schema to use when, rather just a mechanism to test and validate. - -The "schema set" is a configurable variable, and the system maps various events to different sub-schemas within -that set. Direct file-based validations run against an explicitly specified sub-schema, while the dynamic PubSub -validator dynamically chooses the sub-schema based off of message parameters. There's currently two schemas -available, defined in the `schemas/` subdirectory: -* `simple`, which is really just there to make sure the system works. -* [`UDMI`](../schemas/udmi/README.md), which is a building-oriented schema for data collection. - -## Validation Mechanisms - -There are several different ways to run the validator depending on the specific objective: -* Local File Validation -* Integration Testing -* PubSub Stream Validation - -### Local File Validation - -Local file validation runs the code against a set of local schemas and inputs. The example below shows -validating one schema file against one specific test input. -Specifying a directory, rather than a specific schema or input, will run against the entire set. -An output file is generated that has details about the schema validation result. - -
-~/daq$ validator/bin/validate schemas/simple/simple.json schemas/simple/simple.tests/example.json
-Executing validator schemas/simple/simple.json schemas/simple/simple.tests/example.json...
-Running schema simple.json in /home/user/daq/schemas/simple
-Validating example.json against simple.json
-Validation complete, exit 0
-~/daq$
-
- -### Integration Testing - -The `validator/bin/test` script runs a regression suite of all schemas against all tests. -This must pass before any PR can be approved. If there is any failure, a bunch of diagnostic -information will be included about what exactly went wrong. - -
-~/daq/validator$ bin/test
-
-BUILD SUCCESSFUL in 3s
-2 actionable tasks: 2 executed
-
-BUILD SUCCESSFUL in 3s
-2 actionable tasks: 2 executed
-Validating empty.json against config.json
-Validating errors.json against config.json
-
-Validating example.json against state.json
-Validating error.json against simple.json
-Validating example.json against simple.json
-
-Done with validation.
-
- -### PubSub Stream Validation - -Validating a live PubSub stream requires more setup, but ultimately most closely reflects what an -actual system would be doing during operation. The [DAQ PubSub Documentation](pubsub.md) details -how to set this up. It uses the same underlying schema files as the techniques above, but routes -it though a live stream in the cloud. - -Streaming validation validates a stream of messages pulled from a GCP PubSub topic. -There are three configuration values required in the `local/system.yaml` file to make it work: -* `gcp_cred`: The service account credentials, as per the general [DAQ Firebase setup](firebase.md). -* `gcp_topic`: The _PubSub_ (not MQTT) topic name. -* `schema_path`: Indicates which schema to validate against. - -You will need to add full Project Editor permissions for the service account. -E.g., to validate messages on the `projects/gcp-account/topics/telemetry` topic, -there should be something like: - -
-~/daq$ fgrep gcp_ local/system.conf
-gcp_cred=local/gcp-project-ce6716521378.json
-gcp_topic=telemetry
-schema_path=schemas/abacab/
-
- -Running `bin/validate` will parse the configuration file and automatically start -verifying PubSub messages against the indicated schema. -The execution output has a link to a location in the Firestore setup -where schema results will be stored, along with a local directory of results. - -
-~/daq$ bin/validate
-Using credentials from /home/user/daq/local/gcp-project-ce6716521378.json
-
-BUILD SUCCESSFUL in 3s
-2 actionable tasks: 2 executed
-Executing validator /home/user/daq/validator/schemas/abacab/ pubsub:telemetry_topic...
-Running schema . in /home/user/daq/validator/schemas/abacab
-Ignoring subfolders []
-Results will be uploaded to https://console.cloud.google.com/firestore/data/registries/?project=gcp-project
-Also found in such directories as /home/user/daq/validator/schemas/abacab/out
-Connecting to pubsub topic telemetry
-Entering pubsub message loop on projects/gcp-project/subscriptions/daq-validator
-Success validating out/pointset_FCU_09_INT_NE_07.json
-Success validating out/pointset_FCU_07_EXT_SW_06.json
-Error validating out/logentry_TCE01_01_NE_Controls.json: DeviceId TCE01_01_NE_Controls must match pattern ^([a-z][_a-z0-9-]*[a-z0-9]|[A-Z][_A-Z0-9-]*[A-Z0-9])$
-Success validating out/logentry_FCU_01_NE_08.json
-Error validating out/pointset_TCE01_01_NE_Controls.json: DeviceId TCE01_01_NE_Controls must match pattern ^([a-z][_a-z0-9-]*[a-z0-9]|[A-Z][_A-Z0-9-]*[A-Z0-9])$
-Success validating out/logentry_FCU_01_SE_04.json
-
-
- -## Site Validation - -Following on from individual-device validation, it is possible to validate against an entire building model -This is a WIP provisional feature. But, roughly speaking, it looks like this: - -
-~/daq$ export GOOGLE_APPLICATION_CREDENTIALS=local/essential-monkey.json
-~/daq$ validator/bin/validate schemas/udmi pubsub:topic dev site_model/
-
- -* `schemas/udmi` is the schema to validate against. -* `pubsub:topic` points to the pub-sub topic stream to validate. -* `dev` is an arbitrary designator for running different clients against the same project. -* `site_model/` is a directory containing the requisite building model. - -Output from a site validation run will be in `validations/metadata_report.json`. - -### Types and Topics - -When using the -[GCP Cloud IoT Core MQTT Bridge](https://cloud.google.com/iot/docs/how-tos/mqtt-bridge#publishing_telemetry_events) -there are multiple ways the subschema used during validation is chosen. -* All messages have their attributes validated against the `.../attributes.json` schema. These attributes are -automatically defined server-side by the MQTT Client ID and Topic, and are not explicitly included in any message payload. -* A [device event message](https://cloud.google.com/iot/docs/how-tos/mqtt-bridge#publishing_telemetry_events) -is validated against the sub-schema indicated by the MQTT topic `subFolder`. E.g., the MQTT -topic `/devices/{device-id}/events/pointset` will be validated against `.../pointset.json`. -* [Device state messages](https://cloud.google.com/iot/docs/how-tos/config/getting-state#reporting_device_state) -are validated against the `.../state.json` schema on `/devices/{device-id}/state` MQTT topic. -* (There currently is no stream validation of -[device config messages](https://cloud.google.com/iot/docs/how-tos/config/configuring-devices#mqtt), which are sent on the -`/devices/{device-id}/config` topic.) - -See this handy-dandy table: - -| Type | Category | subFolder | MQTT Topic | Schema File | -|----------|----------|-----------|----------------------------------------|---------------| -| state | state | _n/a_ | `/devices/{device_id}/state` | state.json | -| config | config | _n/a_ | `/devices/{device-id}/config` | config.json | -| pointset | event | pointset | `/devices/{device-id}/events/pointset` | pointset.json | -| logentry | event | logentry | `/devices/{device-id}/events/logentry` | logentry.json | diff --git a/etc/MININET_VERSION b/etc/MININET_VERSION new file mode 100644 index 0000000000..2357edf889 --- /dev/null +++ b/etc/MININET_VERSION @@ -0,0 +1 @@ +2.3.0d6 diff --git a/etc/UDMI_VERSION b/etc/UDMI_VERSION new file mode 100644 index 0000000000..3eefcb9dd5 --- /dev/null +++ b/etc/UDMI_VERSION @@ -0,0 +1 @@ +1.0.0 diff --git a/etc/docker_images.txt b/etc/docker_images.txt index 193e733424..a4b7dc8af8 100644 --- a/etc/docker_images.txt +++ b/etc/docker_images.txt @@ -1,23 +1,27 @@ -daqf/aardvark 34718b2f3fd5 -daqf/default 3ac95db36ee4 -daqf/faucet 45c13344a8ed -daqf/faux1 ecff07f12534 -daqf/faux2 39914ae11741 -daqf/gauge 1431053cf25e -daqf/networking af56b0732100 -daqf/switch 67954aca8dce -daqf/test_bacext 363b6d476ac8 -daqf/test_bacnet 073a0eb5529f -daqf/test_brute 700d986d5e83 -daqf/test_discover ad34b17b41e6 -daqf/test_fail c9a7e6b43bd0 -daqf/test_hold cb120980c658 -daqf/test_macoui a828288c855b -daqf/test_mudgee d4ed15ef1dfc -daqf/test_nmap 78aa5def41e5 -daqf/test_pass 74167ef0df55 -daqf/test_password 471bd1290918 -daqf/test_ping 5618e0243643 -daqf/test_switch 47585fc0876e -daqf/test_tls 9c5f28b74fed -daqf/test_udmi fc13d4c80b0d +daqf/aardvark 6fb0f6c52222 +daqf/default f8652a12fdd8 +daqf/faucet 380da46f6fda +daqf/faux1 befad911308a +daqf/faux2 588b260e9316 +daqf/gauge 157decf291db +daqf/networking 1b5d992ef9a9 +daqf/switch b2113d0aa5d9 +daqf/test_bacext 67df87afaf77 +daqf/test_bacnet 53c268d102eb +daqf/test_brute aa76b01d5eed +daqf/test_discover 0ca76d766349 +daqf/test_fail 8ef4103069a5 +daqf/test_hold 5c923cd1a464 +daqf/test_macoui a605473e0f8d +daqf/test_manual 8026fdd99a5b +daqf/test_mudgee 189aa0b635fd +daqf/test_nmap 2205363f02a4 +daqf/test_ntp a5b21e0039e6 +daqf/test_pass 62dd10381336 +daqf/test_password 486b405827b2 +daqf/test_ping fe8e4dd5ddc2 +daqf/test_ssh 054efbf1b3c3 +daqf/test_switch bfca153bb3fe +daqf/test_tls 50bf58dd9a6f +daqf/test_udmi 41c2ab08ec86 +daqf/usi ab9976d57693 diff --git a/etc/docker_images.ver b/etc/docker_images.ver index 26ca594609..53adb84c82 100644 --- a/etc/docker_images.ver +++ b/etc/docker_images.ver @@ -1 +1 @@ -1.5.1 +1.8.2 diff --git a/firebase/functions/index.js b/firebase/functions/index.js index f17a3d2c6c..12b6a11875 100644 --- a/firebase/functions/index.js +++ b/firebase/functions/index.js @@ -123,7 +123,7 @@ function handleTestResult(origin, siteName, message) { const deviceDoc = originDoc.collection('device').doc(message.device_id); const updates = [ - originDoc.set({ 'updated': timestamp }), + originDoc.set({ 'updated': timestamp }, { merge: true }), siteDoc.set({ 'updated': timestamp }), portDoc.set({ 'updated': timestamp }), deviceDoc.set({ 'updated': timestamp }) @@ -193,17 +193,22 @@ function handleTestResult(origin, siteName, message) { function handleHeartbeat(origin, message) { const timestamp = new Date().toJSON(); const originDoc = db.collection('origin').doc(origin); - console.log('heartbeat', timestamp, origin) + console.log('heartbeat', timestamp, origin, message) const heartbeatDoc = originDoc.collection('runner').doc('heartbeat'); return Promise.all([ - originDoc.set({ 'updated': timestamp }), + originDoc.set({ + 'updated': timestamp, + 'version': message.version + }), heartbeatDoc.get().then((result) => { const current = result.data(); - if (!current || !current.message || current.message.timestamp < message.timestamp) + const defined = current && current.message && current.message.timestamp; + if (!defined || current.message.timestamp < message.timestamp) { return heartbeatDoc.set({ 'updated': timestamp, message }); + } }) ]); } diff --git a/firebase/functions/package-lock.json b/firebase/functions/package-lock.json index 3d7970d0d1..0ed8a55711 100644 --- a/firebase/functions/package-lock.json +++ b/firebase/functions/package-lock.json @@ -14,26 +14,26 @@ "integrity": "sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw==" }, "@firebase/component": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.13.tgz", - "integrity": "sha512-DuSIM96NQkE3Yo77IOa5BWw8VBdvCR5cbMLNiFT4X3dTU15Dm0zHjncQHt/6rQpABGNYWAfOCJmSU1v6vc3DFA==", + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.16.tgz", + "integrity": "sha512-FvffvFN0LWgv1H/FIyruTECOL69Dhy+JfwoTq+mV39V8Mz9lNpo41etonL5AOr7KmXxYJVbNwkx0L9Ei88i7JA==", "requires": { - "@firebase/util": "0.2.48", - "tslib": "1.11.1" + "@firebase/util": "0.2.50", + "tslib": "^1.11.1" } }, "@firebase/database": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.4.tgz", - "integrity": "sha512-m3jaElEEXhr3a9D+M/kbDuRCQG5EmrnSqyEq7iNk3s5ankIrALid0AYm2RZF764F/DIeMFtAzng4EyyEqsaQlQ==", + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.7.tgz", + "integrity": "sha512-vm0ch2zNSoHfXWnDG6WVjf0p/BdXOMBL1lAfkGu3DYH/Rkl4p97x57w0WNOURNfL4GY2LIqScSYKCidV7jqTog==", "requires": { "@firebase/auth-interop-types": "0.1.5", - "@firebase/component": "0.1.13", + "@firebase/component": "0.1.16", "@firebase/database-types": "0.5.1", - "@firebase/logger": "0.2.5", - "@firebase/util": "0.2.48", + "@firebase/logger": "0.2.6", + "@firebase/util": "0.2.50", "faye-websocket": "0.11.3", - "tslib": "1.11.1" + "tslib": "^1.11.1" } }, "@firebase/database-types": { @@ -45,48 +45,117 @@ } }, "@firebase/logger": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.5.tgz", - "integrity": "sha512-qqw3m0tWs/qrg7axTZG/QZq24DIMdSY6dGoWuBn08ddq7+GLF5HiqkRj71XznYeUUbfRq5W9C/PSFnN4JxX+WA==" + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" }, "@firebase/util": { - "version": "0.2.48", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.48.tgz", - "integrity": "sha512-6Wzq6IBF//3mrMTmTQ+JmceM0PMQpxV2GVfXhZn/4sMMkkhB0MA908nPDnatoHwUKyWE3BMw+uTLkyBnkuTu5A==", + "version": "0.2.50", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.50.tgz", + "integrity": "sha512-vFE6+Jfc25u0ViSpFxxq0q5s+XmuJ/y7CL3ud79RQe+WLFFg+j0eH1t23k0yNSG9vZNM7h3uHRIXbV97sYLAyw==", "requires": { - "tslib": "1.11.1" + "tslib": "^1.11.1" } }, "@google-cloud/common": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-2.4.0.tgz", - "integrity": "sha512-zWFjBS35eI9leAHhjfeOYlK5Plcuj/77EzstnrJIZbKgF/nkqjcQuGiMCpzCwOfPyUbz8ZaEOYgbHa759AKbjg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.3.2.tgz", + "integrity": "sha512-W7JRLBEJWYtZQQuGQX06U6GBOSLrSrlvZxv6kGNwJtFrusu6AVgZltQ9Pajuz9Dh9aSXy9aTnBcyxn2/O0EGUw==", "optional": true, "requires": { - "@google-cloud/projectify": "^1.0.0", - "@google-cloud/promisify": "^1.0.0", - "arrify": "^2.0.0", - "duplexify": "^3.6.0", + "@google-cloud/projectify": "^2.0.0", + "@google-cloud/promisify": "^2.0.0", + "arrify": "^2.0.1", + "duplexify": "^4.1.1", "ent": "^2.2.0", "extend": "^3.0.2", - "google-auth-library": "^5.5.0", - "retry-request": "^4.0.0", - "teeny-request": "^6.0.0" - } - }, - "@google-cloud/firestore": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-3.8.4.tgz", - "integrity": "sha512-LCZeqB6goNKzD5G/wcoqWaQ2uf3FV/dtU5OSypqOWl+vHMTEVh1ap2H21JXaEydxq53lCayGfqjhDQzs0J3Qew==", - "optional": true, - "requires": { - "deep-equal": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "google-gax": "^1.13.0", - "readable-stream": "^3.4.0", - "through2": "^3.0.0" + "google-auth-library": "^6.0.0", + "retry-request": "^4.1.1", + "teeny-request": "^7.0.0" }, "dependencies": { + "duplexify": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz", + "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==", + "optional": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "gaxios": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.4.tgz", + "integrity": "sha512-97NmFuMETFQh6gqPUxkqjxRMjmY8aRKRMphIkgO/b90AbCt5wAVuXsp8oWjIXlLN2pIK/fsXD8edcM7ULkFMLg==", + "optional": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + } + }, + "gcp-metadata": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.1.0.tgz", + "integrity": "sha512-r57SV28+olVsflPlKyVig3Muo/VDlcsObMtvDGOEtEJXj+DDE8bEl0coIkXh//hbkSDTvo+f5lbihZOndYXQQQ==", + "optional": true, + "requires": { + "gaxios": "^3.0.0", + "json-bigint": "^0.3.0" + } + }, + "google-auth-library": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.0.5.tgz", + "integrity": "sha512-Wj31lfTm2yR4g3WfOOB1Am1tt478Xq9OvzTPQJi17tn/I9R5IcsxjANBsE93nYmxYxtwDedhOdIb8l3vSPG49Q==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^3.0.0", + "gcp-metadata": "^4.1.0", + "gtoken": "^5.0.0", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-p12-pem": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.2.tgz", + "integrity": "sha512-tbjzndQvSIHGBLzHnhDs3cL4RBjLbLXc2pYvGH+imGVu5b4RMAttUTdnmW2UH0t11QeBTXZ7wlXPS7hrypO/tg==", + "optional": true, + "requires": { + "node-forge": "^0.9.0" + } + }, + "gtoken": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.2.tgz", + "integrity": "sha512-lull70rHCTvRTmAt+R/6W5bTtx4MjHku7AwJwK5fGqhOmygcZud0nrZcX+QUNfBJwCzqy7S5i1Bc4NYnr5PMMA==", + "optional": true, + "requires": { + "gaxios": "^3.0.0", + "google-p12-pem": "^3.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -97,6 +166,153 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "@google-cloud/firestore": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.1.1.tgz", + "integrity": "sha512-HFy2OEOrYJ7jYUir90Kg7+AWM6fsFoWYiHiryoseHfkL9//AnXm2sn0CiaOhsTsxphc69G8LBBvUj6ws0QDa7g==", + "optional": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^2.2.0" + }, + "dependencies": { + "@grpc/grpc-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.2.tgz", + "integrity": "sha512-k2u86Bkm/3xrjUaSWeIyzXScBt/cC8uE7BznR0cpueQi11R33W6qfJdMrkrsmSHirp5likR55JSXUrcWG6ybHA==", + "optional": true, + "requires": { + "semver": "^6.2.0" + } + }, + "gaxios": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.4.tgz", + "integrity": "sha512-97NmFuMETFQh6gqPUxkqjxRMjmY8aRKRMphIkgO/b90AbCt5wAVuXsp8oWjIXlLN2pIK/fsXD8edcM7ULkFMLg==", + "optional": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + } + }, + "gcp-metadata": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.1.0.tgz", + "integrity": "sha512-r57SV28+olVsflPlKyVig3Muo/VDlcsObMtvDGOEtEJXj+DDE8bEl0coIkXh//hbkSDTvo+f5lbihZOndYXQQQ==", + "optional": true, + "requires": { + "gaxios": "^3.0.0", + "json-bigint": "^0.3.0" + } + }, + "google-auth-library": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.0.5.tgz", + "integrity": "sha512-Wj31lfTm2yR4g3WfOOB1Am1tt478Xq9OvzTPQJi17tn/I9R5IcsxjANBsE93nYmxYxtwDedhOdIb8l3vSPG49Q==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^3.0.0", + "gcp-metadata": "^4.1.0", + "gtoken": "^5.0.0", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-gax": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.6.3.tgz", + "integrity": "sha512-hqY6H53Qmaku8rE8dGAM89RSUc1nc4JYG81whrVJRmDQZ2jhJK8AwCd3pJQ3V48rgp9xiWBzBQsyeaxnb3Eikw==", + "optional": true, + "requires": { + "@grpc/grpc-js": "~1.1.1", + "@grpc/proto-loader": "^0.5.1", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^3.6.0", + "google-auth-library": "^6.0.0", + "is-stream-ended": "^0.1.4", + "lodash.at": "^4.6.0", + "lodash.has": "^4.5.2", + "node-fetch": "^2.6.0", + "protobufjs": "^6.9.0", + "retry-request": "^4.0.0", + "semver": "^6.0.0", + "walkdir": "^0.4.0" + } + }, + "google-p12-pem": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.2.tgz", + "integrity": "sha512-tbjzndQvSIHGBLzHnhDs3cL4RBjLbLXc2pYvGH+imGVu5b4RMAttUTdnmW2UH0t11QeBTXZ7wlXPS7hrypO/tg==", + "optional": true, + "requires": { + "node-forge": "^0.9.0" + } + }, + "gtoken": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.2.tgz", + "integrity": "sha512-lull70rHCTvRTmAt+R/6W5bTtx4MjHku7AwJwK5fGqhOmygcZud0nrZcX+QUNfBJwCzqy7S5i1Bc4NYnr5PMMA==", + "optional": true, + "requires": { + "gaxios": "^3.0.0", + "google-p12-pem": "^3.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "protobufjs": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.0.tgz", + "integrity": "sha512-Hdz1+CXkrlmGDKkP6DczxysdnUyUuhM1mjeaydnBxOcjxQPbJldLZ8eGE1gX0UTsgv+0QkFfn6dioo5yt9XORw==", + "optional": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": "^13.7.0", + "long": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true } } }, @@ -109,9 +325,9 @@ } }, "@google-cloud/paginator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-2.0.3.tgz", - "integrity": "sha512-kp/pkb2p/p0d8/SKUu4mOq8+HGwF8NPzHWkj+VKrIPQPyMRw8deZtrO/OcSiy9C/7bpfU5Txah5ltUNfPkgEXg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.2.tgz", + "integrity": "sha512-kXK+Dbz4pNvv8bKU80Aw5HsIdgOe0WuMTd8/fI6tkANUxzvJOVJQQRsWVqcHSWK2RXHPTA9WBniUCwY6gAJDXw==", "optional": true, "requires": { "arrify": "^2.0.0", @@ -119,26 +335,26 @@ } }, "@google-cloud/precise-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-2.0.1.tgz", - "integrity": "sha512-uXrLK/1rYx6pWNHL5U8NurHwmqLX7CwDFuJtRoaZe9lhe8RU7AJS67CMsMvHB0OziCcBAiKdAFzHm9zljI2nKQ==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-2.0.2.tgz", + "integrity": "sha512-eEnWN8vzy4Gji9dOlcr8rsX0Oz52eI6ZZZj0AIrUbqTXM8JFPqKzx53DpWIYuXW6c8AfiyY1txjOsg1cXvsoyQ==" }, "@google-cloud/projectify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-1.0.4.tgz", - "integrity": "sha512-ZdzQUN02eRsmTKfBj9FDL0KNDIFNjBn/d6tHQmA/+FImH5DO6ZV8E7FzxMgAUiVAUq41RFAkb25p1oHOZ8psfg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.0.1.tgz", + "integrity": "sha512-ZDG38U/Yy6Zr21LaR3BTiiLtpJl6RkPS/JwoRT453G+6Q1DhlV0waNf8Lfu+YVYGIIxgKnLayJRfYlFJfiI8iQ==", "optional": true }, "@google-cloud/promisify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.4.tgz", - "integrity": "sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.1.tgz", + "integrity": "sha512-82EQzwrNauw1fkbUSr3f+50Bcq7g4h0XvLOk8C5e9ABkXYHei7ZPi9tiMMD7Vh3SfcdH97d1ibJ3KBWp2o1J+w==", "optional": true }, "@google-cloud/pubsub": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-2.1.0.tgz", - "integrity": "sha512-9k4ucPR4X9/BKu1ht9RfXAqGpQzLZOGYpGgoq9Cnxhp9SDjAXkgIKN02pYCXZDdoLng25Mf+xkMnc3AfzJimnA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-2.3.0.tgz", + "integrity": "sha512-lWFwuzg+d7UN7YY6TGwIFPxiA2pFFHx1ApN0X5xIe0jtuUuF2iPaRNIJwZTOnvZ8xmOSpQqiaj/SwEDgr4b46A==", "requires": { "@google-cloud/paginator": "^3.0.0", "@google-cloud/precise-date": "^2.0.0", @@ -157,37 +373,41 @@ }, "dependencies": { "@google-cloud/paginator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.0.tgz", - "integrity": "sha512-iPdxTujlZQlMGNLHPtYoVwRu8IuLFr6y0GJwsX9hKULMgqGXrP/z0MV4ROGpRAkNE1FIfa1aDfNlwZHfF2z4bQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.2.tgz", + "integrity": "sha512-kXK+Dbz4pNvv8bKU80Aw5HsIdgOe0WuMTd8/fI6tkANUxzvJOVJQQRsWVqcHSWK2RXHPTA9WBniUCwY6gAJDXw==", "requires": { "arrify": "^2.0.0", "extend": "^3.0.2" } }, "@google-cloud/projectify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.0.0.tgz", - "integrity": "sha512-7wZ+m4N3Imtb5afOPfqNFyj9cKrlfVQ+t5YRxLS7tUpn8Pn/i7QuVubZRTXllaWjO4T5t/gm/r2x7oy5ajjvFQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.0.1.tgz", + "integrity": "sha512-ZDG38U/Yy6Zr21LaR3BTiiLtpJl6RkPS/JwoRT453G+6Q1DhlV0waNf8Lfu+YVYGIIxgKnLayJRfYlFJfiI8iQ==" }, "@google-cloud/promisify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.1.tgz", - "integrity": "sha512-82EQzwrNauw1fkbUSr3f+50Bcq7g4h0XvLOk8C5e9ABkXYHei7ZPi9tiMMD7Vh3SfcdH97d1ibJ3KBWp2o1J+w==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.2.tgz", + "integrity": "sha512-EvuabjzzZ9E2+OaYf+7P9OAiiwbTxKYL0oGLnREQd+Su2NTQBpomkdlkBowFvyWsaV0d1sSGxrKpSNcrhPqbxg==" }, "@grpc/grpc-js": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.0.4.tgz", - "integrity": "sha512-Qawt6HUrEmljQMPWnLnIXpcjelmtIAydi3M9awiG02WWJ1CmIvFEx4IOC1EsWUWUlabOGksRbpfvoIeZKFTNXw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.2.tgz", + "integrity": "sha512-k2u86Bkm/3xrjUaSWeIyzXScBt/cC8uE7BznR0cpueQi11R33W6qfJdMrkrsmSHirp5likR55JSXUrcWG6ybHA==", "requires": { - "google-auth-library": "^6.0.0", "semver": "^6.2.0" } }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, "gaxios": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.3.tgz", - "integrity": "sha512-PkzQludeIFhd535/yucALT/Wxyj/y2zLyrMwPcJmnLHDugmV49NvAi/vb+VUq/eWztATZCNcb8ue+ywPG+oLuw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.4.tgz", + "integrity": "sha512-97NmFuMETFQh6gqPUxkqjxRMjmY8aRKRMphIkgO/b90AbCt5wAVuXsp8oWjIXlLN2pIK/fsXD8edcM7ULkFMLg==", "requires": { "abort-controller": "^3.0.0", "extend": "^3.0.2", @@ -197,18 +417,18 @@ } }, "gcp-metadata": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.1.0.tgz", - "integrity": "sha512-r57SV28+olVsflPlKyVig3Muo/VDlcsObMtvDGOEtEJXj+DDE8bEl0coIkXh//hbkSDTvo+f5lbihZOndYXQQQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.1.4.tgz", + "integrity": "sha512-5J/GIH0yWt/56R3dNaNWPGQ/zXsZOddYECfJaqxFWgrZ9HC2Kvc5vl9upOgUUHKzURjAVf2N+f6tEJiojqXUuA==", "requires": { "gaxios": "^3.0.0", - "json-bigint": "^0.3.0" + "json-bigint": "^1.0.0" } }, "google-auth-library": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.0.1.tgz", - "integrity": "sha512-NWEM9W0o+fmUJMK/wEuJ1vAc8H/JAseOWB8tjOAAkz8yobU+5IDtO/rPCbbRwFF1obIOCe0lj1pkq9ld2OFZeg==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.0.5.tgz", + "integrity": "sha512-Wj31lfTm2yR4g3WfOOB1Am1tt478Xq9OvzTPQJi17tn/I9R5IcsxjANBsE93nYmxYxtwDedhOdIb8l3vSPG49Q==", "requires": { "arrify": "^2.0.0", "base64-js": "^1.3.0", @@ -218,15 +438,15 @@ "gcp-metadata": "^4.1.0", "gtoken": "^5.0.0", "jws": "^4.0.0", - "lru-cache": "^5.0.0" + "lru-cache": "^6.0.0" } }, "google-gax": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.5.0.tgz", - "integrity": "sha512-Xqh+rinq93qSGOcs5aQdlrwBUR+/9AaFArLCvSGnx7Mye9p4u0dC98r2TO7wB4m1W138Swd6UPYGQyBg9BM/4g==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.6.3.tgz", + "integrity": "sha512-hqY6H53Qmaku8rE8dGAM89RSUc1nc4JYG81whrVJRmDQZ2jhJK8AwCd3pJQ3V48rgp9xiWBzBQsyeaxnb3Eikw==", "requires": { - "@grpc/grpc-js": "~1.0.0", + "@grpc/grpc-js": "~1.1.1", "@grpc/proto-loader": "^0.5.1", "@types/long": "^4.0.0", "abort-controller": "^3.0.0", @@ -243,9 +463,9 @@ }, "dependencies": { "protobufjs": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz", - "integrity": "sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg==", + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.1.tgz", + "integrity": "sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -265,35 +485,56 @@ } }, "google-p12-pem": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.1.tgz", - "integrity": "sha512-VlQgtozgNVVVcYTXS36eQz4PXPt9gIPqLOhHN0QiV6W6h4qSCNVKPtKC5INtJsaHHF2r7+nOIa26MJeJMTaZEQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.2.tgz", + "integrity": "sha512-tbjzndQvSIHGBLzHnhDs3cL4RBjLbLXc2pYvGH+imGVu5b4RMAttUTdnmW2UH0t11QeBTXZ7wlXPS7hrypO/tg==", "requires": { "node-forge": "^0.9.0" } }, "gtoken": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.1.tgz", - "integrity": "sha512-33w4FNDkUcyIOq/TqyC+drnKdI4PdXmWp9lZzssyEQKuvu9ZFN3KttaSnDKo52U3E51oujVGop93mKxmqO8HHg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.2.tgz", + "integrity": "sha512-lull70rHCTvRTmAt+R/6W5bTtx4MjHku7AwJwK5fGqhOmygcZud0nrZcX+QUNfBJwCzqy7S5i1Bc4NYnr5PMMA==", "requires": { "gaxios": "^3.0.0", "google-p12-pem": "^3.0.0", "jws": "^4.0.0", "mime": "^2.2.0" } + }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, "@google-cloud/storage": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-4.7.0.tgz", - "integrity": "sha512-f0guAlbeg7Z0m3gKjCfBCu7FG9qS3M3oL5OQQxlvGoPtK7/qg3+W+KQV73O2/sbuS54n0Kh2mvT5K2FWzF5vVQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.1.2.tgz", + "integrity": "sha512-j2blsBVv6Tt5Z7ff6kOSIg5zVQPdlcTQh/4zMb9h7xMj4ekwndQA60le8c1KEa+Y6SR3EM6ER2AvKYK53P7vdQ==", "optional": true, "requires": { - "@google-cloud/common": "^2.1.1", - "@google-cloud/paginator": "^2.0.0", - "@google-cloud/promisify": "^1.0.0", + "@google-cloud/common": "^3.0.0", + "@google-cloud/paginator": "^3.0.0", + "@google-cloud/promisify": "^2.0.0", "arrify": "^2.0.0", "compressible": "^2.0.12", "concat-stream": "^2.0.0", @@ -301,24 +542,24 @@ "duplexify": "^3.5.0", "extend": "^3.0.2", "gaxios": "^3.0.0", - "gcs-resumable-upload": "^2.2.4", + "gcs-resumable-upload": "^3.0.0", "hash-stream-validation": "^0.2.2", "mime": "^2.2.0", "mime-types": "^2.0.8", "onetime": "^5.1.0", - "p-limit": "^2.2.0", + "p-limit": "^3.0.1", "pumpify": "^2.0.0", "readable-stream": "^3.4.0", "snakeize": "^0.1.0", "stream-events": "^1.0.1", - "through2": "^3.0.0", + "through2": "^4.0.0", "xdg-basedir": "^4.0.0" }, "dependencies": { "gaxios": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.3.tgz", - "integrity": "sha512-PkzQludeIFhd535/yucALT/Wxyj/y2zLyrMwPcJmnLHDugmV49NvAi/vb+VUq/eWztATZCNcb8ue+ywPG+oLuw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.4.tgz", + "integrity": "sha512-97NmFuMETFQh6gqPUxkqjxRMjmY8aRKRMphIkgO/b90AbCt5wAVuXsp8oWjIXlLN2pIK/fsXD8edcM7ULkFMLg==", "optional": true, "requires": { "abort-controller": "^3.0.0", @@ -338,6 +579,15 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "optional": true, + "requires": { + "readable-stream": "3" + } } } }, @@ -454,9 +704,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz", - "integrity": "sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw==", + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz", + "integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -530,12 +780,6 @@ "debug": "4" } }, - "array-filter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", - "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", - "optional": true - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -546,15 +790,6 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" }, - "available-typed-arrays": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", - "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", - "optional": true, - "requires": { - "array-filter": "^1.0.0" - } - }, "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", @@ -725,44 +960,6 @@ "ms": "^2.1.1" } }, - "deep-equal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz", - "integrity": "sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA==", - "optional": true, - "requires": { - "es-abstract": "^1.17.5", - "es-get-iterator": "^1.1.0", - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.2", - "is-regex": "^1.0.5", - "isarray": "^2.0.5", - "object-is": "^1.1.2", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.2", - "which-boxed-primitive": "^1.0.1", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.2" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "optional": true - } - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -833,57 +1030,6 @@ "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", "optional": true }, - "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-get-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", - "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", - "optional": true, - "requires": { - "es-abstract": "^1.17.4", - "has-symbols": "^1.0.1", - "is-arguments": "^1.0.4", - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "optional": true - } - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -961,6 +1107,12 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true + }, "fast-text-encoding": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.1.tgz", @@ -1004,35 +1156,30 @@ } }, "firebase-admin": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-8.12.1.tgz", - "integrity": "sha512-DZ4Q7QQJYaO2BhnhZLrhL+mGRTCLS5WrxjbJtuKGmbKRBepwMhx++EQA5yhnGnIXgDHnp5SrZnVKygNdXtH8BQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-9.0.0.tgz", + "integrity": "sha512-LP4xD+JxfEZ+e1kBIKT2kbDa9UFChwgL4488NexvTjhynNcJsKCGmawl2FMvZ2UPwXKgWBpLXJ07cYp6gk5lcw==", "requires": { "@firebase/database": "^0.6.0", - "@google-cloud/firestore": "^3.0.0", - "@google-cloud/storage": "^4.1.2", - "@types/node": "^8.10.59", + "@google-cloud/firestore": "^4.0.0", + "@google-cloud/storage": "^5.0.0", + "@types/node": "^10.10.0", "dicer": "^0.3.0", - "jsonwebtoken": "8.1.0", - "node-forge": "0.7.4" + "jsonwebtoken": "^8.5.1", + "node-forge": "^0.9.1" }, "dependencies": { "@types/node": { - "version": "8.10.61", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.61.tgz", - "integrity": "sha512-l+zSbvT8TPRaCxL1l9cwHCb0tSqGAGcjPJFItGGYat5oCTiq1uQQKYg5m7AF1mgnEBzFXGLJ2LRmNjtreRX76Q==" - }, - "node-forge": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.4.tgz", - "integrity": "sha512-8Df0906+tq/omxuCZD6PqhPaQDYuyJ1d+VITgxoIA8zvQd1ru+nMJcDChHH324MWitIgbVkAkQoGEEVJNpn/PA==" + "version": "10.17.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.27.tgz", + "integrity": "sha512-J0oqm9ZfAXaPdwNXMMgAhylw5fhmXkToJd06vuDUSAgEDZ/n/69/69UmyBZbc+zT34UnShuDSBqvim3SPnozJg==" } } }, "firebase-functions": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.7.0.tgz", - "integrity": "sha512-+ROj2Gs2/KyM+T8jYo7AKaHynFsN49sXbgZMll3zuGa9/8oiDsXp9e1Iy2JMkFmSZg67jeYw5Ue2OSpz0XiqFQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.8.0.tgz", + "integrity": "sha512-RFvoS7ZcXrk2sQ918czsjv94p4hnSoD0/e4cZ86XFpa1HbNZBI7ZuSgBCzRvlv6dJ1ArytAL13NpB1Bp2tJ6Yg==", "requires": { "@types/express": "4.17.3", "cors": "^2.8.5", @@ -1040,12 +1187,6 @@ "lodash": "^4.17.14" } }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "optional": true - }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -1056,11 +1197,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -1089,17 +1225,96 @@ } }, "gcs-resumable-upload": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-2.3.3.tgz", - "integrity": "sha512-sf896I5CC/1AxeaGfSFg3vKMjUq/r+A3bscmVzZm10CElyRanN0XwPu/MxeIO4LSP+9uF6yKzXvNsaTsMXUG6Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-3.1.1.tgz", + "integrity": "sha512-RS1osvAicj9+MjCc6jAcVL1Pt3tg7NK2C2gXM5nqD1Gs0klF2kj5nnAFSBy97JrtslMIQzpb7iSuxaG8rFWd2A==", "optional": true, "requires": { "abort-controller": "^3.0.0", "configstore": "^5.0.0", - "gaxios": "^2.0.0", - "google-auth-library": "^5.0.0", + "extend": "^3.0.2", + "gaxios": "^3.0.0", + "google-auth-library": "^6.0.0", "pumpify": "^2.0.0", "stream-events": "^1.0.4" + }, + "dependencies": { + "gaxios": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.4.tgz", + "integrity": "sha512-97NmFuMETFQh6gqPUxkqjxRMjmY8aRKRMphIkgO/b90AbCt5wAVuXsp8oWjIXlLN2pIK/fsXD8edcM7ULkFMLg==", + "optional": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + } + }, + "gcp-metadata": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.1.0.tgz", + "integrity": "sha512-r57SV28+olVsflPlKyVig3Muo/VDlcsObMtvDGOEtEJXj+DDE8bEl0coIkXh//hbkSDTvo+f5lbihZOndYXQQQ==", + "optional": true, + "requires": { + "gaxios": "^3.0.0", + "json-bigint": "^0.3.0" + } + }, + "google-auth-library": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.0.5.tgz", + "integrity": "sha512-Wj31lfTm2yR4g3WfOOB1Am1tt478Xq9OvzTPQJi17tn/I9R5IcsxjANBsE93nYmxYxtwDedhOdIb8l3vSPG49Q==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^3.0.0", + "gcp-metadata": "^4.1.0", + "gtoken": "^5.0.0", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-p12-pem": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.2.tgz", + "integrity": "sha512-tbjzndQvSIHGBLzHnhDs3cL4RBjLbLXc2pYvGH+imGVu5b4RMAttUTdnmW2UH0t11QeBTXZ7wlXPS7hrypO/tg==", + "optional": true, + "requires": { + "node-forge": "^0.9.0" + } + }, + "gtoken": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.2.tgz", + "integrity": "sha512-lull70rHCTvRTmAt+R/6W5bTtx4MjHku7AwJwK5fGqhOmygcZud0nrZcX+QUNfBJwCzqy7S5i1Bc4NYnr5PMMA==", + "optional": true, + "requires": { + "gaxios": "^3.0.0", + "google-p12-pem": "^3.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } } }, "google-auth-library": { @@ -1165,19 +1380,6 @@ "mime": "^2.2.0" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, "hash-stream-validation": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.3.tgz", @@ -1267,66 +1469,12 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "optional": true - }, - "is-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz", - "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==", - "optional": true - }, - "is-boolean-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", - "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", - "optional": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" - }, - "is-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", - "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", - "optional": true - }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "optional": true - }, "is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "optional": true }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-set": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", - "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", - "optional": true - }, "is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", @@ -1337,50 +1485,12 @@ "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==" }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "optional": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-typed-array": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz", - "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==", - "optional": true, - "requires": { - "available-typed-arrays": "^1.0.0", - "es-abstract": "^1.17.4", - "foreach": "^2.0.5", - "has-symbols": "^1.0.1" - } - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "optional": true }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "optional": true - }, - "is-weakset": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", - "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==", - "optional": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -1395,11 +1505,11 @@ } }, "jsonwebtoken": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", - "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", "requires": { - "jws": "^3.1.4", + "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -1407,8 +1517,8 @@ "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", - "ms": "^2.0.0", - "xtend": "^4.0.1" + "ms": "^2.1.1", + "semver": "^5.6.0" }, "dependencies": { "jwa": { @@ -1429,6 +1539,11 @@ "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -1452,9 +1567,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, "lodash.at": { "version": "4.6.0", @@ -1597,37 +1712,6 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" - }, - "object-is": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", - "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", - "optional": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -1659,9 +1743,9 @@ "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==" }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", "optional": true, "requires": { "p-try": "^2.0.0" @@ -1812,16 +1896,6 @@ } } }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "optional": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, "retry-request": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.1.1.tgz", @@ -1909,16 +1983,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, - "side-channel": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", - "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", - "optional": true, - "requires": { - "es-abstract": "^1.17.0-next.1", - "object-inspect": "^1.7.0" - } - }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -1955,44 +2019,6 @@ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimleft": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", - "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimstart": "^1.0.0" - } - }, - "string.prototype.trimright": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", - "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimend": "^1.0.0" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -2015,16 +2041,16 @@ "optional": true }, "teeny-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.3.tgz", - "integrity": "sha512-TZG/dfd2r6yeji19es1cUIwAlVD8y+/svB1kAC2Y0bjEyysrfbO8EZvJBRwIE6WkwmUoB7uvWLwTIhJbMXZ1Dw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.0.0.tgz", + "integrity": "sha512-kWD3sdGmIix6w7c8ZdVKxWq+3YwVPGWz+Mq0wRZXayEKY/YHb63b8uphfBzcFDmyq8frD9+UTc3wLyOhltRbtg==", "optional": true, "requires": { "http-proxy-agent": "^4.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.2.0", "stream-events": "^1.0.5", - "uuid": "^7.0.0" + "uuid": "^8.0.0" } }, "through2": { @@ -2041,9 +2067,9 @@ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" }, "type-is": { "version": "1.6.18", @@ -2094,9 +2120,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==", "optional": true }, "vary": { @@ -2124,45 +2150,6 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" }, - "which-boxed-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", - "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==", - "optional": true, - "requires": { - "is-bigint": "^1.0.0", - "is-boolean-object": "^1.0.0", - "is-number-object": "^1.0.3", - "is-string": "^1.0.4", - "is-symbol": "^1.0.2" - } - }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "optional": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-typed-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz", - "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==", - "optional": true, - "requires": { - "available-typed-arrays": "^1.0.2", - "es-abstract": "^1.17.5", - "foreach": "^2.0.5", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.1", - "is-typed-array": "^1.1.3" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2189,7 +2176,8 @@ "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "optional": true }, "yallist": { "version": "3.1.1", diff --git a/firebase/functions/package.json b/firebase/functions/package.json index b4eebe0523..d75ce0b03f 100644 --- a/firebase/functions/package.json +++ b/firebase/functions/package.json @@ -9,13 +9,13 @@ "logs": "firebase functions:log" }, "engines": { - "node": "8" + "node": "10" }, "dependencies": { - "@google-cloud/pubsub": "2.1.0", + "@google-cloud/pubsub": "2.3.0", "@google-cloud/iot": "1.8.0", - "firebase-admin": "8.12.1", - "firebase-functions": "3.7.0", + "firebase-admin": "9.0.0", + "firebase-functions": "3.8.0", "extend": "3.0.2" }, "private": true diff --git a/firebase/public/config.html b/firebase/public/config.html index f94216c57f..3149596f26 100644 --- a/firebase/public/config.html +++ b/firebase/public/config.html @@ -11,8 +11,8 @@ - - + +
diff --git a/firebase/public/index.html b/firebase/public/index.html index d9ce546c59..c4928cd090 100644 --- a/firebase/public/index.html +++ b/firebase/public/index.html @@ -31,14 +31,14 @@

Filters:

-
- - -
+
+ + +
@@ -52,10 +52,10 @@

Filters:

-

Sites

-

Origins

+

Sites

+

Users

@@ -84,4 +84,4 @@

Users

if (typeof daq_deploy_version !== 'undefined') { document.getElementById('deploy-version').innerHTML = daq_deploy_version; } - \ No newline at end of file + diff --git a/firebase/public/main.js b/firebase/public/main.js index 09f4237a5e..a6eeee087f 100644 --- a/firebase/public/main.js +++ b/firebase/public/main.js @@ -8,11 +8,6 @@ const display_columns = []; const display_rows = []; const row_timestamps = {}; -const data_state = {}; - -let last_result_time_sec = 0; -let heartbeatTimestamp = 0; - const origin_id = getQueryParam('origin'); const site_name = getQueryParam('site'); const port_id = getQueryParam('port'); @@ -21,8 +16,13 @@ const device_id = getQueryParam('device'); const run_id = getQueryParam('runid'); const from = getQueryParam('from'); const to = getQueryParam('to'); + +const data_state = {}; +let last_result_time_sec = 0; +let heartbeatTimestamp = 0; var db; -var activePorts = []; +var activePorts = new Set(); + document.addEventListener('DOMContentLoaded', () => { db = firebase.firestore(); const settings = { @@ -289,7 +289,7 @@ function watcherAdd(ref, collection, limit, handler) { }, (e) => console.error(e)); } -function listSites(db) { +function listSites() { const linkGroup = document.querySelector('#listings .sites'); db.collection('site').get().then((snapshot) => { snapshot.forEach((site_doc) => { @@ -303,21 +303,31 @@ function listSites(db) { }).catch((e) => statusUpdate('registry list error', e)); } -function listOrigins(db) { - const linkGroup = document.querySelector('#listings .origins'); +function addOrigin(originId) { + db.collection('origin').doc(originId).get().then((result) => { + const linkGroup = document.querySelector('#listings .origins'); + const originLink = document.createElement('a'); + originLink.setAttribute('href', '/?origin=' + originId); + originLink.innerHTML = originId; + linkGroup.appendChild(originLink); + const originInfo = document.createElement('span'); + const version = result.data() && result.data().version; + const updated = result.data() && result.data().updated; + originInfo.innerHTML = ` ${version}, ${updated}`; + linkGroup.appendChild(originInfo); + linkGroup.appendChild(document.createElement('p')); + }); +} + +function listOrigins() { db.collection('origin').get().then((snapshot) => { snapshot.forEach((originDoc) => { - const origin = originDoc.id; - const originLink = document.createElement('a'); - originLink.setAttribute('href', '/?origin=' + origin); - originLink.innerHTML = origin; - linkGroup.appendChild(originLink); - linkGroup.appendChild(document.createElement('p')); + addOrigin(originDoc.id); }); }).catch((e) => statusUpdate('origin list error', e)); } -function listUsers(db) { +function listUsers() { const link_group = document.querySelector('#listings .users'); db.collection('users').get().then((snapshot) => { snapshot.forEach((user_doc) => { @@ -354,9 +364,9 @@ function dashboardSetup() { triggerOrigin(db, origin_id); } else { document.getElementById('listings').classList.add('active'); - listSites(db); - listOrigins(db); - listUsers(db); + listOrigins(); + listSites(); + listUsers(); } return origin_id; diff --git a/firebase/public/protos.hash b/firebase/public/protos.hash index bab39e76c2..5d00da6704 100644 --- a/firebase/public/protos.hash +++ b/firebase/public/protos.hash @@ -1 +1 @@ -b7a56a30dafe26576d6bdef00dfb57dc07a016ac proto/system_config.proto +1f6e7f1a7517da9544eab551d16b7bd650c2d4ae proto/system_config.proto diff --git a/firebase/public/protos.html b/firebase/public/protos.html index d24bed4958..b0929b316a 100644 --- a/firebase/public/protos.html +++ b/firebase/public/protos.html @@ -198,6 +198,10 @@

Table of Contents

MSwitchSetup +
  • + MUSISetup +
  • + @@ -430,10 +434,10 @@

    DaqConfig

    - fail_hook + topology_hook string -

    Hook for failure diagnostics.

    +

    Hook for device topology updates.

    @@ -478,6 +482,13 @@

    DaqConfig

    Set time between port disconnect and host tests shutdown

    + + usi_setup + USISetup + +

    USI url

    + + @@ -613,7 +624,14 @@

    SwitchSetup

    lo_port int32 -

    Local port of open flow controller

    +

    Local port of DAQ OpenFlow controller

    + + + + alt_port + int32 + +

    Local port for an alternate OpenFlow controller

    @@ -679,6 +697,37 @@

    SwitchSetup

    +

    USISetup

    +

    USI paramters

    + + + + + + + + + + + + + + + + + + + + + + + +
    FieldTypeLabelDescription
    urlstring

    rpc_timeout_secint32

    + + + + + diff --git a/libs/proto/system_config_pb2.py b/libs/proto/system_config_pb2.py index e4746e687f..89ee2bc00b 100644 --- a/libs/proto/system_config_pb2.py +++ b/libs/proto/system_config_pb2.py @@ -1,7 +1,8 @@ -# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: daq/proto/system_config.proto +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -18,7 +19,7 @@ package='', syntax='proto3', serialized_options=None, - serialized_pb=b'\n\x1d\x64\x61q/proto/system_config.proto\"\xfb\x07\n\tDaqConfig\x12\x18\n\x10site_description\x18\x01 \x01(\t\x12\x18\n\x10monitor_scan_sec\x18\x02 \x01(\x05\x12\x1b\n\x13\x64\x65\x66\x61ult_timeout_sec\x18\x03 \x01(\x05\x12\x12\n\nsettle_sec\x18& \x01(\x05\x12\x11\n\tbase_conf\x18\x04 \x01(\t\x12\x11\n\tsite_path\x18\x05 \x01(\t\x12\x1f\n\x17initial_dhcp_lease_time\x18\x06 \x01(\t\x12\x17\n\x0f\x64hcp_lease_time\x18\x07 \x01(\t\x12\x19\n\x11\x64hcp_response_sec\x18\' \x01(\x05\x12\x1e\n\x16long_dhcp_response_sec\x18\x08 \x01(\x05\x12\"\n\x0cswitch_setup\x18\t \x01(\x0b\x32\x0c.SwitchSetup\x12\x12\n\nhost_tests\x18\x10 \x01(\t\x12\x13\n\x0b\x62uild_tests\x18$ \x01(\x08\x12\x11\n\trun_limit\x18\x11 \x01(\x05\x12\x11\n\tfail_mode\x18\x12 \x01(\x08\x12\x13\n\x0bsingle_shot\x18\" \x01(\x08\x12\x15\n\rresult_linger\x18\x13 \x01(\x08\x12\x0f\n\x07no_test\x18\x14 \x01(\x08\x12\x11\n\tkeep_hold\x18( \x01(\x08\x12\x14\n\x0c\x64\x61q_loglevel\x18\x15 \x01(\t\x12\x18\n\x10mininet_loglevel\x18\x16 \x01(\t\x12\x13\n\x0b\x66inish_hook\x18# \x01(\t\x12\x10\n\x08gcp_cred\x18\x17 \x01(\t\x12\x11\n\tgcp_topic\x18\x18 \x01(\t\x12\x13\n\x0bschema_path\x18\x19 \x01(\t\x12\x11\n\tmud_files\x18\x1a \x01(\t\x12\x14\n\x0c\x64\x65vice_specs\x18\x1b \x01(\t\x12\x13\n\x0btest_config\x18\x1c \x01(\t\x12\x19\n\x11port_debounce_sec\x18\x1d \x01(\x05\x12\x11\n\tfail_hook\x18\x1e \x01(\t\x12\x17\n\x0f\x64\x65vice_template\x18\x1f \x01(\t\x12\x14\n\x0csite_reports\x18 \x01(\t\x12\x1f\n\x17run_data_retention_days\x18! \x01(\x02\x12.\n\ninterfaces\x18% \x03(\x0b\x32\x1a.DaqConfig.InterfacesEntry\x12/\n\x0b\x66\x61il_module\x18/ \x03(\x0b\x32\x1a.DaqConfig.FailModuleEntry\x12\x1d\n\x15port_flap_timeout_sec\x18\x30 \x01(\x05\x1a=\n\x0fInterfacesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x19\n\x05value\x18\x02 \x01(\x0b\x32\n.Interface:\x02\x38\x01\x1a\x31\n\x0f\x46\x61ilModuleEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xe2\x01\n\x0bSwitchSetup\x12\x11\n\tctrl_intf\x18\t \x01(\t\x12\x0f\n\x07ip_addr\x18\x0b \x01(\t\x12\x13\n\x0buplink_port\x18\r \x01(\x05\x12\x0f\n\x07lo_port\x18\x0e \x01(\x05\x12\x0f\n\x07lo_addr\x18\x0f \x01(\t\x12\x11\n\tmods_addr\x18\x10 \x01(\t\x12\x0f\n\x07of_dpid\x18) \x01(\t\x12\x11\n\tdata_intf\x18* \x01(\t\x12\x0e\n\x06\x65xt_br\x18+ \x01(\t\x12\r\n\x05model\x18, \x01(\t\x12\x10\n\x08username\x18- \x01(\t\x12\x10\n\x08password\x18. \x01(\t\"\'\n\tInterface\x12\x0c\n\x04opts\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\x05\x62\x06proto3' + serialized_pb=_b('\n\x1d\x64\x61q/proto/system_config.proto\"\x9d\x08\n\tDaqConfig\x12\x18\n\x10site_description\x18\x01 \x01(\t\x12\x18\n\x10monitor_scan_sec\x18\x02 \x01(\x05\x12\x1b\n\x13\x64\x65\x66\x61ult_timeout_sec\x18\x03 \x01(\x05\x12\x12\n\nsettle_sec\x18& \x01(\x05\x12\x11\n\tbase_conf\x18\x04 \x01(\t\x12\x11\n\tsite_path\x18\x05 \x01(\t\x12\x1f\n\x17initial_dhcp_lease_time\x18\x06 \x01(\t\x12\x17\n\x0f\x64hcp_lease_time\x18\x07 \x01(\t\x12\x19\n\x11\x64hcp_response_sec\x18\' \x01(\x05\x12\x1e\n\x16long_dhcp_response_sec\x18\x08 \x01(\x05\x12\"\n\x0cswitch_setup\x18\t \x01(\x0b\x32\x0c.SwitchSetup\x12\x12\n\nhost_tests\x18\x10 \x01(\t\x12\x13\n\x0b\x62uild_tests\x18$ \x01(\x08\x12\x11\n\trun_limit\x18\x11 \x01(\x05\x12\x11\n\tfail_mode\x18\x12 \x01(\x08\x12\x13\n\x0bsingle_shot\x18\" \x01(\x08\x12\x15\n\rresult_linger\x18\x13 \x01(\x08\x12\x0f\n\x07no_test\x18\x14 \x01(\x08\x12\x11\n\tkeep_hold\x18( \x01(\x08\x12\x14\n\x0c\x64\x61q_loglevel\x18\x15 \x01(\t\x12\x18\n\x10mininet_loglevel\x18\x16 \x01(\t\x12\x13\n\x0b\x66inish_hook\x18# \x01(\t\x12\x10\n\x08gcp_cred\x18\x17 \x01(\t\x12\x11\n\tgcp_topic\x18\x18 \x01(\t\x12\x13\n\x0bschema_path\x18\x19 \x01(\t\x12\x11\n\tmud_files\x18\x1a \x01(\t\x12\x14\n\x0c\x64\x65vice_specs\x18\x1b \x01(\t\x12\x13\n\x0btest_config\x18\x1c \x01(\t\x12\x19\n\x11port_debounce_sec\x18\x1d \x01(\x05\x12\x15\n\rtopology_hook\x18\x1e \x01(\t\x12\x17\n\x0f\x64\x65vice_template\x18\x1f \x01(\t\x12\x14\n\x0csite_reports\x18 \x01(\t\x12\x1f\n\x17run_data_retention_days\x18! \x01(\x02\x12.\n\ninterfaces\x18% \x03(\x0b\x32\x1a.DaqConfig.InterfacesEntry\x12/\n\x0b\x66\x61il_module\x18/ \x03(\x0b\x32\x1a.DaqConfig.FailModuleEntry\x12\x1d\n\x15port_flap_timeout_sec\x18\x30 \x01(\x05\x12\x1c\n\tusi_setup\x18\x31 \x01(\x0b\x32\t.USISetup\x1a=\n\x0fInterfacesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x19\n\x05value\x18\x02 \x01(\x0b\x32\n.Interface:\x02\x38\x01\x1a\x31\n\x0f\x46\x61ilModuleEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"0\n\x08USISetup\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x17\n\x0frpc_timeout_sec\x18\x02 \x01(\x05\"\xf4\x01\n\x0bSwitchSetup\x12\x11\n\tctrl_intf\x18\t \x01(\t\x12\x0f\n\x07ip_addr\x18\x0b \x01(\t\x12\x13\n\x0buplink_port\x18\r \x01(\x05\x12\x0f\n\x07lo_port\x18\x0e \x01(\x05\x12\x10\n\x08\x61lt_port\x18\x10 \x01(\x05\x12\x0f\n\x07lo_addr\x18\x12 \x01(\t\x12\x11\n\tmods_addr\x18\x14 \x01(\t\x12\x0f\n\x07of_dpid\x18) \x01(\t\x12\x11\n\tdata_intf\x18* \x01(\t\x12\x0e\n\x06\x65xt_br\x18+ \x01(\t\x12\r\n\x05model\x18, \x01(\t\x12\x10\n\x08username\x18- \x01(\t\x12\x10\n\x08password\x18. \x01(\t\"\'\n\tInterface\x12\x0c\n\x04opts\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\x05\x62\x06proto3') ) @@ -34,7 +35,7 @@ _descriptor.FieldDescriptor( name='key', full_name='DaqConfig.InterfacesEntry.key', index=0, number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -51,14 +52,14 @@ nested_types=[], enum_types=[ ], - serialized_options=b'8\001', + serialized_options=_b('8\001'), is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], - serialized_start=941, - serialized_end=1002, + serialized_start=975, + serialized_end=1036, ) _DAQCONFIG_FAILMODULEENTRY = _descriptor.Descriptor( @@ -71,14 +72,14 @@ _descriptor.FieldDescriptor( name='key', full_name='DaqConfig.FailModuleEntry.key', index=0, number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='value', full_name='DaqConfig.FailModuleEntry.value', index=1, number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -88,14 +89,14 @@ nested_types=[], enum_types=[ ], - serialized_options=b'8\001', + serialized_options=_b('8\001'), is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], - serialized_start=1004, - serialized_end=1053, + serialized_start=1038, + serialized_end=1087, ) _DAQCONFIG = _descriptor.Descriptor( @@ -108,7 +109,7 @@ _descriptor.FieldDescriptor( name='site_description', full_name='DaqConfig.site_description', index=0, number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -136,28 +137,28 @@ _descriptor.FieldDescriptor( name='base_conf', full_name='DaqConfig.base_conf', index=4, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='site_path', full_name='DaqConfig.site_path', index=5, number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='initial_dhcp_lease_time', full_name='DaqConfig.initial_dhcp_lease_time', index=6, number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='dhcp_lease_time', full_name='DaqConfig.dhcp_lease_time', index=7, number=7, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -185,7 +186,7 @@ _descriptor.FieldDescriptor( name='host_tests', full_name='DaqConfig.host_tests', index=11, number=16, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -241,63 +242,63 @@ _descriptor.FieldDescriptor( name='daq_loglevel', full_name='DaqConfig.daq_loglevel', index=19, number=21, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='mininet_loglevel', full_name='DaqConfig.mininet_loglevel', index=20, number=22, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='finish_hook', full_name='DaqConfig.finish_hook', index=21, number=35, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='gcp_cred', full_name='DaqConfig.gcp_cred', index=22, number=23, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='gcp_topic', full_name='DaqConfig.gcp_topic', index=23, number=24, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='schema_path', full_name='DaqConfig.schema_path', index=24, number=25, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='mud_files', full_name='DaqConfig.mud_files', index=25, number=26, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='device_specs', full_name='DaqConfig.device_specs', index=26, number=27, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='test_config', full_name='DaqConfig.test_config', index=27, number=28, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -309,23 +310,23 @@ is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='fail_hook', full_name='DaqConfig.fail_hook', index=29, + name='topology_hook', full_name='DaqConfig.topology_hook', index=29, number=30, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='device_template', full_name='DaqConfig.device_template', index=30, number=31, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='site_reports', full_name='DaqConfig.site_reports', index=31, number=32, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -357,6 +358,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='usi_setup', full_name='DaqConfig.usi_setup', index=36, + number=49, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -370,7 +378,45 @@ oneofs=[ ], serialized_start=34, - serialized_end=1053, + serialized_end=1087, +) + + +_USISETUP = _descriptor.Descriptor( + name='USISetup', + full_name='USISetup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='url', full_name='USISetup.url', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='rpc_timeout_sec', full_name='USISetup.rpc_timeout_sec', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1089, + serialized_end=1137, ) @@ -384,14 +430,14 @@ _descriptor.FieldDescriptor( name='ctrl_intf', full_name='SwitchSetup.ctrl_intf', index=0, number=9, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='ip_addr', full_name='SwitchSetup.ip_addr', index=1, number=11, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -410,58 +456,65 @@ is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='lo_addr', full_name='SwitchSetup.lo_addr', index=4, - number=15, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + name='alt_port', full_name='SwitchSetup.alt_port', index=4, + number=16, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='mods_addr', full_name='SwitchSetup.mods_addr', index=5, - number=16, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + name='lo_addr', full_name='SwitchSetup.lo_addr', index=5, + number=18, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='of_dpid', full_name='SwitchSetup.of_dpid', index=6, + name='mods_addr', full_name='SwitchSetup.mods_addr', index=6, + number=20, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='of_dpid', full_name='SwitchSetup.of_dpid', index=7, number=41, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='data_intf', full_name='SwitchSetup.data_intf', index=7, + name='data_intf', full_name='SwitchSetup.data_intf', index=8, number=42, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='ext_br', full_name='SwitchSetup.ext_br', index=8, + name='ext_br', full_name='SwitchSetup.ext_br', index=9, number=43, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='model', full_name='SwitchSetup.model', index=9, + name='model', full_name='SwitchSetup.model', index=10, number=44, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='username', full_name='SwitchSetup.username', index=10, + name='username', full_name='SwitchSetup.username', index=11, number=45, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='password', full_name='SwitchSetup.password', index=11, + name='password', full_name='SwitchSetup.password', index=12, number=46, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -477,8 +530,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1056, - serialized_end=1282, + serialized_start=1140, + serialized_end=1384, ) @@ -492,7 +545,7 @@ _descriptor.FieldDescriptor( name='opts', full_name='Interface.opts', index=0, number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -515,8 +568,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1284, - serialized_end=1323, + serialized_start=1386, + serialized_end=1425, ) _DAQCONFIG_INTERFACESENTRY.fields_by_name['value'].message_type = _INTERFACE @@ -525,46 +578,55 @@ _DAQCONFIG.fields_by_name['switch_setup'].message_type = _SWITCHSETUP _DAQCONFIG.fields_by_name['interfaces'].message_type = _DAQCONFIG_INTERFACESENTRY _DAQCONFIG.fields_by_name['fail_module'].message_type = _DAQCONFIG_FAILMODULEENTRY +_DAQCONFIG.fields_by_name['usi_setup'].message_type = _USISETUP DESCRIPTOR.message_types_by_name['DaqConfig'] = _DAQCONFIG +DESCRIPTOR.message_types_by_name['USISetup'] = _USISETUP DESCRIPTOR.message_types_by_name['SwitchSetup'] = _SWITCHSETUP DESCRIPTOR.message_types_by_name['Interface'] = _INTERFACE _sym_db.RegisterFileDescriptor(DESCRIPTOR) -DaqConfig = _reflection.GeneratedProtocolMessageType('DaqConfig', (_message.Message,), { +DaqConfig = _reflection.GeneratedProtocolMessageType('DaqConfig', (_message.Message,), dict( - 'InterfacesEntry' : _reflection.GeneratedProtocolMessageType('InterfacesEntry', (_message.Message,), { - 'DESCRIPTOR' : _DAQCONFIG_INTERFACESENTRY, - '__module__' : 'daq.proto.system_config_pb2' + InterfacesEntry = _reflection.GeneratedProtocolMessageType('InterfacesEntry', (_message.Message,), dict( + DESCRIPTOR = _DAQCONFIG_INTERFACESENTRY, + __module__ = 'daq.proto.system_config_pb2' # @@protoc_insertion_point(class_scope:DaqConfig.InterfacesEntry) - }) + )) , - 'FailModuleEntry' : _reflection.GeneratedProtocolMessageType('FailModuleEntry', (_message.Message,), { - 'DESCRIPTOR' : _DAQCONFIG_FAILMODULEENTRY, - '__module__' : 'daq.proto.system_config_pb2' + FailModuleEntry = _reflection.GeneratedProtocolMessageType('FailModuleEntry', (_message.Message,), dict( + DESCRIPTOR = _DAQCONFIG_FAILMODULEENTRY, + __module__ = 'daq.proto.system_config_pb2' # @@protoc_insertion_point(class_scope:DaqConfig.FailModuleEntry) - }) + )) , - 'DESCRIPTOR' : _DAQCONFIG, - '__module__' : 'daq.proto.system_config_pb2' + DESCRIPTOR = _DAQCONFIG, + __module__ = 'daq.proto.system_config_pb2' # @@protoc_insertion_point(class_scope:DaqConfig) - }) + )) _sym_db.RegisterMessage(DaqConfig) _sym_db.RegisterMessage(DaqConfig.InterfacesEntry) _sym_db.RegisterMessage(DaqConfig.FailModuleEntry) -SwitchSetup = _reflection.GeneratedProtocolMessageType('SwitchSetup', (_message.Message,), { - 'DESCRIPTOR' : _SWITCHSETUP, - '__module__' : 'daq.proto.system_config_pb2' +USISetup = _reflection.GeneratedProtocolMessageType('USISetup', (_message.Message,), dict( + DESCRIPTOR = _USISETUP, + __module__ = 'daq.proto.system_config_pb2' + # @@protoc_insertion_point(class_scope:USISetup) + )) +_sym_db.RegisterMessage(USISetup) + +SwitchSetup = _reflection.GeneratedProtocolMessageType('SwitchSetup', (_message.Message,), dict( + DESCRIPTOR = _SWITCHSETUP, + __module__ = 'daq.proto.system_config_pb2' # @@protoc_insertion_point(class_scope:SwitchSetup) - }) + )) _sym_db.RegisterMessage(SwitchSetup) -Interface = _reflection.GeneratedProtocolMessageType('Interface', (_message.Message,), { - 'DESCRIPTOR' : _INTERFACE, - '__module__' : 'daq.proto.system_config_pb2' +Interface = _reflection.GeneratedProtocolMessageType('Interface', (_message.Message,), dict( + DESCRIPTOR = _INTERFACE, + __module__ = 'daq.proto.system_config_pb2' # @@protoc_insertion_point(class_scope:Interface) - }) + )) _sym_db.RegisterMessage(Interface) diff --git a/libs/proto/usi_pb2.py b/libs/proto/usi_pb2.py new file mode 100644 index 0000000000..c9189dc119 --- /dev/null +++ b/libs/proto/usi_pb2.py @@ -0,0 +1,449 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: usi.proto + +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='usi.proto', + package='usi', + syntax='proto3', + serialized_options=b'\n\004grpcB\010USIProtoP\001', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\tusi.proto\x12\x03usi\"\'\n\x14SwitchActionResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"\x9b\x01\n\rPowerResponse\x12!\n\x19\x63urrent_power_consumption\x18\x01 \x01(\x02\x12\x1d\n\x15max_power_consumption\x18\x02 \x01(\x02\x12$\n\x0bpoe_support\x18\x03 \x01(\x0e\x32\x0f.usi.POESupport\x12\"\n\npoe_status\x18\x04 \x01(\x0e\x32\x0e.usi.POEStatus\"]\n\x11InterfaceResponse\x12$\n\x0blink_status\x18\x01 \x01(\x0e\x32\x0f.usi.LinkStatus\x12\x12\n\nlink_speed\x18\x02 \x01(\x05\x12\x0e\n\x06\x64uplex\x18\x03 \x01(\t\"w\n\nSwitchInfo\x12\x0f\n\x07ip_addr\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65vice_port\x18\x03 \x01(\x05\x12\x1f\n\x05model\x18\x04 \x01(\x0e\x32\x10.usi.SwitchModel\x12\x10\n\x08username\x18\x05 \x01(\t\x12\x10\n\x08password\x18\x06 \x01(\t*F\n\x0bSwitchModel\x12\x17\n\x13\x41LLIED_TELESIS_X230\x10\x00\x12\x0e\n\nCISCO_9300\x10\x01\x12\x0e\n\nOVS_SWITCH\x10\x02*\x1e\n\nLinkStatus\x12\x06\n\x02UP\x10\x00\x12\x08\n\x04\x44OWN\x10\x01*\'\n\nPOESupport\x12\x0b\n\x07\x45NABLED\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01*1\n\tPOEStatus\x12\x06\n\x02ON\x10\x00\x12\x07\n\x03OFF\x10\x01\x12\t\n\x05\x46\x41ULT\x10\x02\x12\x08\n\x04\x44\x45NY\x10\x03\x32\xef\x01\n\nUSIService\x12\x31\n\x08GetPower\x12\x0f.usi.SwitchInfo\x1a\x12.usi.PowerResponse\"\x00\x12\x39\n\x0cGetInterface\x12\x0f.usi.SwitchInfo\x1a\x16.usi.InterfaceResponse\"\x00\x12:\n\ndisconnect\x12\x0f.usi.SwitchInfo\x1a\x19.usi.SwitchActionResponse\"\x00\x12\x37\n\x07\x63onnect\x12\x0f.usi.SwitchInfo\x1a\x19.usi.SwitchActionResponse\"\x00\x42\x12\n\x04grpcB\x08USIProtoP\x01\x62\x06proto3' +) + +_SWITCHMODEL = _descriptor.EnumDescriptor( + name='SwitchModel', + full_name='usi.SwitchModel', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='ALLIED_TELESIS_X230', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CISCO_9300', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OVS_SWITCH', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=433, + serialized_end=503, +) +_sym_db.RegisterEnumDescriptor(_SWITCHMODEL) + +SwitchModel = enum_type_wrapper.EnumTypeWrapper(_SWITCHMODEL) +_LINKSTATUS = _descriptor.EnumDescriptor( + name='LinkStatus', + full_name='usi.LinkStatus', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='UP', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DOWN', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=505, + serialized_end=535, +) +_sym_db.RegisterEnumDescriptor(_LINKSTATUS) + +LinkStatus = enum_type_wrapper.EnumTypeWrapper(_LINKSTATUS) +_POESUPPORT = _descriptor.EnumDescriptor( + name='POESupport', + full_name='usi.POESupport', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='ENABLED', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DISABLED', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=537, + serialized_end=576, +) +_sym_db.RegisterEnumDescriptor(_POESUPPORT) + +POESupport = enum_type_wrapper.EnumTypeWrapper(_POESUPPORT) +_POESTATUS = _descriptor.EnumDescriptor( + name='POEStatus', + full_name='usi.POEStatus', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='ON', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OFF', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='FAULT', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DENY', index=3, number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=578, + serialized_end=627, +) +_sym_db.RegisterEnumDescriptor(_POESTATUS) + +POEStatus = enum_type_wrapper.EnumTypeWrapper(_POESTATUS) +ALLIED_TELESIS_X230 = 0 +CISCO_9300 = 1 +OVS_SWITCH = 2 +UP = 0 +DOWN = 1 +ENABLED = 0 +DISABLED = 1 +ON = 0 +OFF = 1 +FAULT = 2 +DENY = 3 + + + +_SWITCHACTIONRESPONSE = _descriptor.Descriptor( + name='SwitchActionResponse', + full_name='usi.SwitchActionResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='success', full_name='usi.SwitchActionResponse.success', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=18, + serialized_end=57, +) + + +_POWERRESPONSE = _descriptor.Descriptor( + name='PowerResponse', + full_name='usi.PowerResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='current_power_consumption', full_name='usi.PowerResponse.current_power_consumption', index=0, + number=1, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='max_power_consumption', full_name='usi.PowerResponse.max_power_consumption', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='poe_support', full_name='usi.PowerResponse.poe_support', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='poe_status', full_name='usi.PowerResponse.poe_status', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=60, + serialized_end=215, +) + + +_INTERFACERESPONSE = _descriptor.Descriptor( + name='InterfaceResponse', + full_name='usi.InterfaceResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='link_status', full_name='usi.InterfaceResponse.link_status', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='link_speed', full_name='usi.InterfaceResponse.link_speed', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='duplex', full_name='usi.InterfaceResponse.duplex', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=217, + serialized_end=310, +) + + +_SWITCHINFO = _descriptor.Descriptor( + name='SwitchInfo', + full_name='usi.SwitchInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='ip_addr', full_name='usi.SwitchInfo.ip_addr', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='device_port', full_name='usi.SwitchInfo.device_port', index=1, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='model', full_name='usi.SwitchInfo.model', index=2, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='username', full_name='usi.SwitchInfo.username', index=3, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='password', full_name='usi.SwitchInfo.password', index=4, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=312, + serialized_end=431, +) + +_POWERRESPONSE.fields_by_name['poe_support'].enum_type = _POESUPPORT +_POWERRESPONSE.fields_by_name['poe_status'].enum_type = _POESTATUS +_INTERFACERESPONSE.fields_by_name['link_status'].enum_type = _LINKSTATUS +_SWITCHINFO.fields_by_name['model'].enum_type = _SWITCHMODEL +DESCRIPTOR.message_types_by_name['SwitchActionResponse'] = _SWITCHACTIONRESPONSE +DESCRIPTOR.message_types_by_name['PowerResponse'] = _POWERRESPONSE +DESCRIPTOR.message_types_by_name['InterfaceResponse'] = _INTERFACERESPONSE +DESCRIPTOR.message_types_by_name['SwitchInfo'] = _SWITCHINFO +DESCRIPTOR.enum_types_by_name['SwitchModel'] = _SWITCHMODEL +DESCRIPTOR.enum_types_by_name['LinkStatus'] = _LINKSTATUS +DESCRIPTOR.enum_types_by_name['POESupport'] = _POESUPPORT +DESCRIPTOR.enum_types_by_name['POEStatus'] = _POESTATUS +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +SwitchActionResponse = _reflection.GeneratedProtocolMessageType('SwitchActionResponse', (_message.Message,), { + 'DESCRIPTOR' : _SWITCHACTIONRESPONSE, + '__module__' : 'usi_pb2' + # @@protoc_insertion_point(class_scope:usi.SwitchActionResponse) + }) +_sym_db.RegisterMessage(SwitchActionResponse) + +PowerResponse = _reflection.GeneratedProtocolMessageType('PowerResponse', (_message.Message,), { + 'DESCRIPTOR' : _POWERRESPONSE, + '__module__' : 'usi_pb2' + # @@protoc_insertion_point(class_scope:usi.PowerResponse) + }) +_sym_db.RegisterMessage(PowerResponse) + +InterfaceResponse = _reflection.GeneratedProtocolMessageType('InterfaceResponse', (_message.Message,), { + 'DESCRIPTOR' : _INTERFACERESPONSE, + '__module__' : 'usi_pb2' + # @@protoc_insertion_point(class_scope:usi.InterfaceResponse) + }) +_sym_db.RegisterMessage(InterfaceResponse) + +SwitchInfo = _reflection.GeneratedProtocolMessageType('SwitchInfo', (_message.Message,), { + 'DESCRIPTOR' : _SWITCHINFO, + '__module__' : 'usi_pb2' + # @@protoc_insertion_point(class_scope:usi.SwitchInfo) + }) +_sym_db.RegisterMessage(SwitchInfo) + + +DESCRIPTOR._options = None + +_USISERVICE = _descriptor.ServiceDescriptor( + name='USIService', + full_name='usi.USIService', + file=DESCRIPTOR, + index=0, + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_start=630, + serialized_end=869, + methods=[ + _descriptor.MethodDescriptor( + name='GetPower', + full_name='usi.USIService.GetPower', + index=0, + containing_service=None, + input_type=_SWITCHINFO, + output_type=_POWERRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='GetInterface', + full_name='usi.USIService.GetInterface', + index=1, + containing_service=None, + input_type=_SWITCHINFO, + output_type=_INTERFACERESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='disconnect', + full_name='usi.USIService.disconnect', + index=2, + containing_service=None, + input_type=_SWITCHINFO, + output_type=_SWITCHACTIONRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='connect', + full_name='usi.USIService.connect', + index=3, + containing_service=None, + input_type=_SWITCHINFO, + output_type=_SWITCHACTIONRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), +]) +_sym_db.RegisterServiceDescriptor(_USISERVICE) + +DESCRIPTOR.services_by_name['USIService'] = _USISERVICE + +# @@protoc_insertion_point(module_scope) diff --git a/libs/proto/usi_pb2_grpc.py b/libs/proto/usi_pb2_grpc.py new file mode 100644 index 0000000000..c8e57501c9 --- /dev/null +++ b/libs/proto/usi_pb2_grpc.py @@ -0,0 +1,161 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import usi_pb2 as usi__pb2 + + +class USIServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.GetPower = channel.unary_unary( + '/usi.USIService/GetPower', + request_serializer=usi__pb2.SwitchInfo.SerializeToString, + response_deserializer=usi__pb2.PowerResponse.FromString, + ) + self.GetInterface = channel.unary_unary( + '/usi.USIService/GetInterface', + request_serializer=usi__pb2.SwitchInfo.SerializeToString, + response_deserializer=usi__pb2.InterfaceResponse.FromString, + ) + self.disconnect = channel.unary_unary( + '/usi.USIService/disconnect', + request_serializer=usi__pb2.SwitchInfo.SerializeToString, + response_deserializer=usi__pb2.SwitchActionResponse.FromString, + ) + self.connect = channel.unary_unary( + '/usi.USIService/connect', + request_serializer=usi__pb2.SwitchInfo.SerializeToString, + response_deserializer=usi__pb2.SwitchActionResponse.FromString, + ) + + +class USIServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def GetPower(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetInterface(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def disconnect(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def connect(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_USIServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'GetPower': grpc.unary_unary_rpc_method_handler( + servicer.GetPower, + request_deserializer=usi__pb2.SwitchInfo.FromString, + response_serializer=usi__pb2.PowerResponse.SerializeToString, + ), + 'GetInterface': grpc.unary_unary_rpc_method_handler( + servicer.GetInterface, + request_deserializer=usi__pb2.SwitchInfo.FromString, + response_serializer=usi__pb2.InterfaceResponse.SerializeToString, + ), + 'disconnect': grpc.unary_unary_rpc_method_handler( + servicer.disconnect, + request_deserializer=usi__pb2.SwitchInfo.FromString, + response_serializer=usi__pb2.SwitchActionResponse.SerializeToString, + ), + 'connect': grpc.unary_unary_rpc_method_handler( + servicer.connect, + request_deserializer=usi__pb2.SwitchInfo.FromString, + response_serializer=usi__pb2.SwitchActionResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'usi.USIService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class USIService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def GetPower(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/usi.USIService/GetPower', + usi__pb2.SwitchInfo.SerializeToString, + usi__pb2.PowerResponse.FromString, + options, channel_credentials, + call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def GetInterface(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/usi.USIService/GetInterface', + usi__pb2.SwitchInfo.SerializeToString, + usi__pb2.InterfaceResponse.FromString, + options, channel_credentials, + call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def disconnect(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/usi.USIService/disconnect', + usi__pb2.SwitchInfo.SerializeToString, + usi__pb2.SwitchActionResponse.FromString, + options, channel_credentials, + call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def connect(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/usi.USIService/connect', + usi__pb2.SwitchInfo.SerializeToString, + usi__pb2.SwitchActionResponse.FromString, + options, channel_credentials, + call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/mudacl/build.gradle b/mudacl/build.gradle index 13f3fd4017..f3667604bb 100644 --- a/mudacl/build.gradle +++ b/mudacl/build.gradle @@ -5,12 +5,12 @@ buildscript { } } dependencies { - classpath "com.github.jengelman.gradle.plugins:shadow:5.2.0" + classpath "com.github.jengelman.gradle.plugins:shadow:6.0.0" } } plugins { - id 'com.github.johnrengelman.shadow' version '5.2.0' + id 'com.github.johnrengelman.shadow' version '6.0.0' id 'java' id 'maven' } @@ -32,7 +32,7 @@ repositories { } dependencies { - compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.11.0' - compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.11.0' + compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.11.1' + compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.11.1' testCompile group: 'junit', name: 'junit', version: '4.13' } diff --git a/mudacl/gradle/wrapper/gradle-wrapper.properties b/mudacl/gradle/wrapper/gradle-wrapper.properties index 16871c71a0..af94776b0b 100644 --- a/mudacl/gradle/wrapper/gradle-wrapper.properties +++ b/mudacl/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip diff --git a/proto/system_config.proto b/proto/system_config.proto index a0cbfbda48..5c334e728b 100644 --- a/proto/system_config.proto +++ b/proto/system_config.proto @@ -94,8 +94,8 @@ message DaqConfig { // Set port-debounce for flaky connections. Zero to disable. int32 port_debounce_sec = 29; - // Hook for failure diagnostics. - string fail_hook = 30; + // Hook for device topology updates. + string topology_hook = 30; // Directory of defaults for new devices. string device_template = 31; @@ -114,8 +114,18 @@ message DaqConfig { // Set time between port disconnect and host tests shutdown int32 port_flap_timeout_sec = 48; + + // USI url + USISetup usi_setup = 49; } +/** + * USI paramters +**/ +message USISetup { + string url = 1; + int32 rpc_timeout_sec = 2; +} /* * System configuraiton of the access switch. This is used by the system @@ -131,14 +141,17 @@ message SwitchSetup { // Dataplane uplink port int32 uplink_port = 13; - // Local port of open flow controller + // Local port of DAQ OpenFlow controller int32 lo_port = 14; + // Local port for an alternate OpenFlow controller + int32 alt_port = 16; + // IP address and subnet for local control plane interface - string lo_addr = 15; + string lo_addr = 18; // IP address template and subnet for module ip addresses - string mods_addr = 16; + string mods_addr = 20; // Dataplane id of external OpenFlow switch string of_dpid = 41; diff --git a/pubber/.idea/codeStyles/codeStyleConfig.xml b/pubber/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index c79f34ced8..0000000000 --- a/pubber/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/pubber/.idea/dictionaries/peringknife.xml b/pubber/.idea/dictionaries/peringknife.xml deleted file mode 100644 index 1f2f3fc05a..0000000000 --- a/pubber/.idea/dictionaries/peringknife.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - pubber - - - \ No newline at end of file diff --git a/pubber/.idea/encodings.xml b/pubber/.idea/encodings.xml deleted file mode 100644 index 15a15b218a..0000000000 --- a/pubber/.idea/encodings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/pubber/.idea/gradle.xml b/pubber/.idea/gradle.xml deleted file mode 100644 index a931762ec9..0000000000 --- a/pubber/.idea/gradle.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/jarRepositories.xml b/pubber/.idea/jarRepositories.xml deleted file mode 100644 index 6f70f42344..0000000000 --- a/pubber/.idea/jarRepositories.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_bugsnag_bugsnag_3_6_1.xml b/pubber/.idea/libraries/Gradle__com_bugsnag_bugsnag_3_6_1.xml deleted file mode 100644 index a61dc7e59a..0000000000 --- a/pubber/.idea/libraries/Gradle__com_bugsnag_bugsnag_3_6_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_annotations_2_10_3.xml b/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_annotations_2_10_3.xml deleted file mode 100644 index 940abc9cd6..0000000000 --- a/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_annotations_2_10_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_core_2_10_3.xml b/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_core_2_10_3.xml deleted file mode 100644 index c39a1aad89..0000000000 --- a/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_core_2_10_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_databind_2_10_3.xml b/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_databind_2_10_3.xml deleted file mode 100644 index 401e4470cc..0000000000 --- a/pubber/.idea/libraries/Gradle__com_fasterxml_jackson_core_jackson_databind_2_10_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_api_api_common_1_1_0.xml b/pubber/.idea/libraries/Gradle__com_google_api_api_common_1_1_0.xml deleted file mode 100644 index 6a37163770..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_api_api_common_1_1_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_api_client_google_api_client_1_22_0.xml b/pubber/.idea/libraries/Gradle__com_google_api_client_google_api_client_1_22_0.xml deleted file mode 100644 index f7052b657f..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_api_client_google_api_client_1_22_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_api_gax_1_8_1.xml b/pubber/.idea/libraries/Gradle__com_google_api_gax_1_8_1.xml deleted file mode 100644 index 5afd4e53b5..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_api_gax_1_8_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_api_gax_grpc_0_25_1.xml b/pubber/.idea/libraries/Gradle__com_google_api_gax_grpc_0_25_1.xml deleted file mode 100644 index 7dd2f70770..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_api_gax_grpc_0_25_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_cloud_logging_v2_0_1_20.xml b/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_cloud_logging_v2_0_1_20.xml deleted file mode 100644 index f653b75d6a..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_cloud_logging_v2_0_1_20.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_common_protos_0_1_20.xml b/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_common_protos_0_1_20.xml deleted file mode 100644 index 3ab192cf7d..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_common_protos_0_1_20.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_iam_v1_0_1_20.xml b/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_iam_v1_0_1_20.xml deleted file mode 100644 index 831f72e025..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_api_grpc_proto_google_iam_v1_0_1_20.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_apis_google_api_services_cloudiot_v1_rev20170922_1_22_0.xml b/pubber/.idea/libraries/Gradle__com_google_apis_google_api_services_cloudiot_v1_rev20170922_1_22_0.xml deleted file mode 100644 index 409ca08042..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_apis_google_api_services_cloudiot_v1_rev20170922_1_22_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_auth_google_auth_library_credentials_0_8_0.xml b/pubber/.idea/libraries/Gradle__com_google_auth_google_auth_library_credentials_0_8_0.xml deleted file mode 100644 index 19f8e9622f..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_auth_google_auth_library_credentials_0_8_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_auth_google_auth_library_oauth2_http_0_8_0.xml b/pubber/.idea/libraries/Gradle__com_google_auth_google_auth_library_oauth2_http_0_8_0.xml deleted file mode 100644 index a9aba07437..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_auth_google_auth_library_oauth2_http_0_8_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_auto_value_auto_value_1_2.xml b/pubber/.idea/libraries/Gradle__com_google_auto_value_auto_value_1_2.xml deleted file mode 100644 index aeea865ae3..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_auto_value_auto_value_1_2.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_core_1_7_0.xml b/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_core_1_7_0.xml deleted file mode 100644 index 49ddf929e7..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_core_1_7_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_core_grpc_1_7_0.xml b/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_core_grpc_1_7_0.xml deleted file mode 100644 index f09079becb..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_core_grpc_1_7_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_logging_1_7_0.xml b/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_logging_1_7_0.xml deleted file mode 100644 index 42054ea1de..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_cloud_google_cloud_logging_1_7_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_0.xml b/pubber/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_0.xml deleted file mode 100644 index c6616f41e4..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_code_findbugs_jsr305_3_0_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_code_gson_gson_2_7.xml b/pubber/.idea/libraries/Gradle__com_google_code_gson_gson_2_7.xml deleted file mode 100644 index cbe1b3266b..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_code_gson_gson_2_7.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_errorprone_error_prone_annotations_2_0_19.xml b/pubber/.idea/libraries/Gradle__com_google_errorprone_error_prone_annotations_2_0_19.xml deleted file mode 100644 index b4cd21969d..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_errorprone_error_prone_annotations_2_0_19.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_guava_guava_22_0.xml b/pubber/.idea/libraries/Gradle__com_google_guava_guava_22_0.xml deleted file mode 100644 index 4c947ec6df..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_guava_guava_22_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_http_client_google_http_client_1_22_0.xml b/pubber/.idea/libraries/Gradle__com_google_http_client_google_http_client_1_22_0.xml deleted file mode 100644 index 6c259c21e1..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_http_client_google_http_client_1_22_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_http_client_google_http_client_jackson2_1_22_0.xml b/pubber/.idea/libraries/Gradle__com_google_http_client_google_http_client_jackson2_1_22_0.xml deleted file mode 100644 index b4ec53cbea..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_http_client_google_http_client_jackson2_1_22_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_instrumentation_instrumentation_api_0_4_3.xml b/pubber/.idea/libraries/Gradle__com_google_instrumentation_instrumentation_api_0_4_3.xml deleted file mode 100644 index 07c6748fa9..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_instrumentation_instrumentation_api_0_4_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_1.xml b/pubber/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_1.xml deleted file mode 100644 index ab45264c2d..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_j2objc_j2objc_annotations_1_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_oauth_client_google_oauth_client_1_22_0.xml b/pubber/.idea/libraries/Gradle__com_google_oauth_client_google_oauth_client_1_22_0.xml deleted file mode 100644 index 8549a6371c..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_oauth_client_google_oauth_client_1_22_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_protobuf_protobuf_java_3_3_1.xml b/pubber/.idea/libraries/Gradle__com_google_protobuf_protobuf_java_3_3_1.xml deleted file mode 100644 index e294c29fa5..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_protobuf_protobuf_java_3_3_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_google_protobuf_protobuf_java_util_3_3_1.xml b/pubber/.idea/libraries/Gradle__com_google_protobuf_protobuf_java_util_3_3_1.xml deleted file mode 100644 index 6866f74bf0..0000000000 --- a/pubber/.idea/libraries/Gradle__com_google_protobuf_protobuf_java_util_3_3_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_hazelcast_hazelcast_3_5_4.xml b/pubber/.idea/libraries/Gradle__com_hazelcast_hazelcast_3_5_4.xml deleted file mode 100644 index 6b097056b4..0000000000 --- a/pubber/.idea/libraries/Gradle__com_hazelcast_hazelcast_3_5_4.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_librato_metrics_librato_java_2_1_0.xml b/pubber/.idea/libraries/Gradle__com_librato_metrics_librato_java_2_1_0.xml deleted file mode 100644 index d3ab2fa027..0000000000 --- a/pubber/.idea/libraries/Gradle__com_librato_metrics_librato_java_2_1_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_librato_metrics_metrics_librato_5_1_0.xml b/pubber/.idea/libraries/Gradle__com_librato_metrics_metrics_librato_5_1_0.xml deleted file mode 100644 index c588bf6754..0000000000 --- a/pubber/.idea/libraries/Gradle__com_librato_metrics_metrics_librato_5_1_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__com_sun_xml_bind_jaxb_impl_2_3_2.xml b/pubber/.idea/libraries/Gradle__com_sun_xml_bind_jaxb_impl_2_3_2.xml deleted file mode 100644 index 35a975da46..0000000000 --- a/pubber/.idea/libraries/Gradle__com_sun_xml_bind_jaxb_impl_2_3_2.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__commons_codec_commons_codec_1_10.xml b/pubber/.idea/libraries/Gradle__commons_codec_commons_codec_1_10.xml deleted file mode 100644 index c84796132f..0000000000 --- a/pubber/.idea/libraries/Gradle__commons_codec_commons_codec_1_10.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__commons_logging_commons_logging_1_1_1.xml b/pubber/.idea/libraries/Gradle__commons_logging_commons_logging_1_1_1.xml deleted file mode 100644 index b9fb75155c..0000000000 --- a/pubber/.idea/libraries/Gradle__commons_logging_commons_logging_1_1_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_dropwizard_metrics_metrics_core_3_2_2.xml b/pubber/.idea/libraries/Gradle__io_dropwizard_metrics_metrics_core_3_2_2.xml deleted file mode 100644 index f2223bcf6b..0000000000 --- a/pubber/.idea/libraries/Gradle__io_dropwizard_metrics_metrics_core_3_2_2.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_dropwizard_metrics_metrics_jvm_3_2_2.xml b/pubber/.idea/libraries/Gradle__io_dropwizard_metrics_metrics_jvm_3_2_2.xml deleted file mode 100644 index a4fb7c1897..0000000000 --- a/pubber/.idea/libraries/Gradle__io_dropwizard_metrics_metrics_jvm_3_2_2.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_grpc_grpc_auth_1_6_1.xml b/pubber/.idea/libraries/Gradle__io_grpc_grpc_auth_1_6_1.xml deleted file mode 100644 index 8308d1661d..0000000000 --- a/pubber/.idea/libraries/Gradle__io_grpc_grpc_auth_1_6_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_grpc_grpc_context_1_6_1.xml b/pubber/.idea/libraries/Gradle__io_grpc_grpc_context_1_6_1.xml deleted file mode 100644 index 42b3336f05..0000000000 --- a/pubber/.idea/libraries/Gradle__io_grpc_grpc_context_1_6_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_grpc_grpc_core_1_6_1.xml b/pubber/.idea/libraries/Gradle__io_grpc_grpc_core_1_6_1.xml deleted file mode 100644 index f4249256ab..0000000000 --- a/pubber/.idea/libraries/Gradle__io_grpc_grpc_core_1_6_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_grpc_grpc_netty_1_6_1.xml b/pubber/.idea/libraries/Gradle__io_grpc_grpc_netty_1_6_1.xml deleted file mode 100644 index 3b8ead556e..0000000000 --- a/pubber/.idea/libraries/Gradle__io_grpc_grpc_netty_1_6_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_grpc_grpc_protobuf_1_6_1.xml b/pubber/.idea/libraries/Gradle__io_grpc_grpc_protobuf_1_6_1.xml deleted file mode 100644 index 95d433c45d..0000000000 --- a/pubber/.idea/libraries/Gradle__io_grpc_grpc_protobuf_1_6_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_6_1.xml b/pubber/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_6_1.xml deleted file mode 100644 index 9a3dd1b89b..0000000000 --- a/pubber/.idea/libraries/Gradle__io_grpc_grpc_protobuf_lite_1_6_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_grpc_grpc_stub_1_6_1.xml b/pubber/.idea/libraries/Gradle__io_grpc_grpc_stub_1_6_1.xml deleted file mode 100644 index f282c5df26..0000000000 --- a/pubber/.idea/libraries/Gradle__io_grpc_grpc_stub_1_6_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_jsonwebtoken_jjwt_0_7_0.xml b/pubber/.idea/libraries/Gradle__io_jsonwebtoken_jjwt_0_7_0.xml deleted file mode 100644 index c255c18f27..0000000000 --- a/pubber/.idea/libraries/Gradle__io_jsonwebtoken_jjwt_0_7_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_moquette_moquette_broker_0_10.xml b/pubber/.idea/libraries/Gradle__io_moquette_moquette_broker_0_10.xml deleted file mode 100644 index 0751597837..0000000000 --- a/pubber/.idea/libraries/Gradle__io_moquette_moquette_broker_0_10.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_buffer_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_buffer_4_1_14_Final.xml deleted file mode 100644 index 30fb818235..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_buffer_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_codec_4_1_14_Final.xml deleted file mode 100644 index 97cd8c9cb9..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_http2_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_codec_http2_4_1_14_Final.xml deleted file mode 100644 index 54abbbe3aa..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_http2_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_http_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_codec_http_4_1_14_Final.xml deleted file mode 100644 index 58ac06ba5b..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_http_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_mqtt_4_1_12_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_codec_mqtt_4_1_12_Final.xml deleted file mode 100644 index 68118cd002..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_mqtt_4_1_12_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_socks_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_codec_socks_4_1_14_Final.xml deleted file mode 100644 index 614e913e87..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_codec_socks_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_common_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_common_4_1_14_Final.xml deleted file mode 100644 index 1a98e17a91..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_common_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_handler_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_handler_4_1_14_Final.xml deleted file mode 100644 index 9298ca6e14..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_handler_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_handler_proxy_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_handler_proxy_4_1_14_Final.xml deleted file mode 100644 index ca38677084..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_handler_proxy_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_resolver_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_resolver_4_1_14_Final.xml deleted file mode 100644 index b70942e76b..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_resolver_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_tcnative_boringssl_static_2_0_3_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_tcnative_boringssl_static_2_0_3_Final.xml deleted file mode 100644 index e00975f2d7..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_tcnative_boringssl_static_2_0_3_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_transport_4_1_14_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_transport_4_1_14_Final.xml deleted file mode 100644 index f055031276..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_transport_4_1_14_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_transport_native_epoll_4_1_12_Final_linux_x86_64.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_transport_native_epoll_4_1_12_Final_linux_x86_64.xml deleted file mode 100644 index 467269eee3..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_transport_native_epoll_4_1_12_Final_linux_x86_64.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_netty_netty_transport_native_unix_common_4_1_12_Final.xml b/pubber/.idea/libraries/Gradle__io_netty_netty_transport_native_unix_common_4_1_12_Final.xml deleted file mode 100644 index a3b889ee62..0000000000 --- a/pubber/.idea/libraries/Gradle__io_netty_netty_transport_native_unix_common_4_1_12_Final.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__io_opencensus_opencensus_api_0_5_1.xml b/pubber/.idea/libraries/Gradle__io_opencensus_opencensus_api_0_5_1.xml deleted file mode 100644 index 5cdfe84133..0000000000 --- a/pubber/.idea/libraries/Gradle__io_opencensus_opencensus_api_0_5_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__javax_activation_javax_activation_api_1_2_0.xml b/pubber/.idea/libraries/Gradle__javax_activation_javax_activation_api_1_2_0.xml deleted file mode 100644 index f480add6e2..0000000000 --- a/pubber/.idea/libraries/Gradle__javax_activation_javax_activation_api_1_2_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__javax_xml_bind_jaxb_api_2_3_1.xml b/pubber/.idea/libraries/Gradle__javax_xml_bind_jaxb_api_2_3_1.xml deleted file mode 100644 index 434a174d24..0000000000 --- a/pubber/.idea/libraries/Gradle__javax_xml_bind_jaxb_api_2_3_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__joda_time_joda_time_2_9_7.xml b/pubber/.idea/libraries/Gradle__joda_time_joda_time_2_9_7.xml deleted file mode 100644 index f45e0d77bd..0000000000 --- a/pubber/.idea/libraries/Gradle__joda_time_joda_time_2_9_7.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__junit_junit_4_13.xml b/pubber/.idea/libraries/Gradle__junit_junit_4_13.xml deleted file mode 100644 index 0cef6bc81e..0000000000 --- a/pubber/.idea/libraries/Gradle__junit_junit_4_13.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_apache_httpcomponents_httpclient_4_0_1.xml b/pubber/.idea/libraries/Gradle__org_apache_httpcomponents_httpclient_4_0_1.xml deleted file mode 100644 index 80d562c2fb..0000000000 --- a/pubber/.idea/libraries/Gradle__org_apache_httpcomponents_httpclient_4_0_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_apache_httpcomponents_httpcore_4_0_1.xml b/pubber/.idea/libraries/Gradle__org_apache_httpcomponents_httpcore_4_0_1.xml deleted file mode 100644 index e203c6b668..0000000000 --- a/pubber/.idea/libraries/Gradle__org_apache_httpcomponents_httpcore_4_0_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_codehaus_mojo_animal_sniffer_annotations_1_14.xml b/pubber/.idea/libraries/Gradle__org_codehaus_mojo_animal_sniffer_annotations_1_14.xml deleted file mode 100644 index 72ee118d97..0000000000 --- a/pubber/.idea/libraries/Gradle__org_codehaus_mojo_animal_sniffer_annotations_1_14.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_eclipse_paho_org_eclipse_paho_client_mqttv3_1_1_0.xml b/pubber/.idea/libraries/Gradle__org_eclipse_paho_org_eclipse_paho_client_mqttv3_1_1_0.xml deleted file mode 100644 index 01970270a7..0000000000 --- a/pubber/.idea/libraries/Gradle__org_eclipse_paho_org_eclipse_paho_client_mqttv3_1_1_0.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3.xml b/pubber/.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3.xml deleted file mode 100644 index 8262f729c2..0000000000 --- a/pubber/.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_json_json_20160810.xml b/pubber/.idea/libraries/Gradle__org_json_json_20160810.xml deleted file mode 100644 index 64dc62f3d4..0000000000 --- a/pubber/.idea/libraries/Gradle__org_json_json_20160810.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_mockito_mockito_core_1_10_19.xml b/pubber/.idea/libraries/Gradle__org_mockito_mockito_core_1_10_19.xml deleted file mode 100644 index 6aa377ef4f..0000000000 --- a/pubber/.idea/libraries/Gradle__org_mockito_mockito_core_1_10_19.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_objenesis_objenesis_2_1.xml b/pubber/.idea/libraries/Gradle__org_objenesis_objenesis_2_1.xml deleted file mode 100644 index e6b52ad30d..0000000000 --- a/pubber/.idea/libraries/Gradle__org_objenesis_objenesis_2_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_slf4j_slf4j_api_1_7_25.xml b/pubber/.idea/libraries/Gradle__org_slf4j_slf4j_api_1_7_25.xml deleted file mode 100644 index dd23f3e0c1..0000000000 --- a/pubber/.idea/libraries/Gradle__org_slf4j_slf4j_api_1_7_25.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_slf4j_slf4j_simple_1_7_5.xml b/pubber/.idea/libraries/Gradle__org_slf4j_slf4j_simple_1_7_5.xml deleted file mode 100644 index 586ac1e599..0000000000 --- a/pubber/.idea/libraries/Gradle__org_slf4j_slf4j_simple_1_7_5.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/libraries/Gradle__org_threeten_threetenbp_1_3_3.xml b/pubber/.idea/libraries/Gradle__org_threeten_threetenbp_1_3_3.xml deleted file mode 100644 index 0fcafe29d0..0000000000 --- a/pubber/.idea/libraries/Gradle__org_threeten_threetenbp_1_3_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/misc.xml b/pubber/.idea/misc.xml deleted file mode 100644 index 012255a52d..0000000000 --- a/pubber/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/pubber/.idea/modules.xml b/pubber/.idea/modules.xml deleted file mode 100644 index f4ca1e7a1b..0000000000 --- a/pubber/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/modules/datafmt.iml b/pubber/.idea/modules/datafmt.iml deleted file mode 100644 index baed4f134d..0000000000 --- a/pubber/.idea/modules/datafmt.iml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/uiDesigner.xml b/pubber/.idea/uiDesigner.xml deleted file mode 100644 index e96534fb27..0000000000 --- a/pubber/.idea/uiDesigner.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/.idea/vcs.xml b/pubber/.idea/vcs.xml deleted file mode 100644 index 26b269dd99..0000000000 --- a/pubber/.idea/vcs.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/pubber/bin/build b/pubber/bin/build deleted file mode 100755 index a2bd6be40a..0000000000 --- a/pubber/bin/build +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -e - -rundir=$(dirname $0) -cd $rundir/.. - -echo Running in $PWD - -rm -rf build - -./gradlew build -./gradlew shadow diff --git a/pubber/bin/keygen b/pubber/bin/keygen deleted file mode 100755 index 1b3cf60d67..0000000000 --- a/pubber/bin/keygen +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -e - -ROOT=$(realpath $(dirname $0)/../..) -cd $ROOT - -TARGET_PREFIX=local/rsa_ - -PUBLIC_CERT=${TARGET_PREFIX}cert.pem -PRIVATE_CERT=${TARGET_PREFIX}private.pem -PRIVATE_KEY=${TARGET_PREFIX}private.pkcs8 - -if [ -f $PUBLIC_CERT ]; then - echo $PUBLIC_CERT already exists, exiting. - false -fi -if [ -f $PRIVATE_CERT ]; then - echo $PRIVATE_CERT already exists, exiting. - false -fi -if [ -f $PRIVATE_KEY ]; then - echo $PRIVATE_KEY already exists, exiting. - false -fi - -openssl req -x509 -nodes -newkey rsa:2048 -keyout $PRIVATE_CERT -days 1000000 -out $PUBLIC_CERT -subj "/CN=unused" -openssl pkcs8 -topk8 -inform PEM -outform DER -in $PRIVATE_CERT -nocrypt > $PRIVATE_KEY diff --git a/pubber/bin/run b/pubber/bin/run deleted file mode 100755 index ee14f351aa..0000000000 --- a/pubber/bin/run +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -e - -ROOT=$(realpath $(dirname $0)/../..) -cd $ROOT - -conf_file=local/pubber.json - -if [ ! -f $conf_file ]; then - echo Pubber config file not found: $(realpath $conf_file) - false -fi - -java -jar pubber/build/libs/pubber-1.0-SNAPSHOT-all.jar $conf_file diff --git a/pubber/build.gradle b/pubber/build.gradle deleted file mode 100644 index 1bdfb151a3..0000000000 --- a/pubber/build.gradle +++ /dev/null @@ -1,54 +0,0 @@ -buildscript { - repositories { - maven { - url "https://plugins.gradle.org/m2/" - } - } - dependencies { - classpath "com.github.jengelman.gradle.plugins:shadow:5.2.0" - } -} - -plugins { - id 'com.github.johnrengelman.shadow' version '5.2.0' - id 'java' - id 'maven' -} - -group 'daq-pubber' -version '1.0-SNAPSHOT' - -sourceCompatibility = 1.8 - -jar { - manifest { - attributes 'Main-Class': 'daq.pubber.Pubber' - } -} - -repositories { - mavenCentral() - mavenLocal() - jcenter() -} - -dependencies { - compile group: 'org.slf4j', name: 'slf4j-simple', version:'1.7.5' - compile 'io.jsonwebtoken:jjwt:0.7.0' - compile 'javax.xml.bind:jaxb-api:2.3.1' - compile 'com.sun.xml.bind:jaxb-impl:2.3.2' - compile 'com.google.guava:guava:22.0' - compile 'com.google.cloud:google-cloud-logging:1.7.0' - compile('com.google.api-client:google-api-client:1.22.0') { - exclude group: 'com.google.guava', module: 'guava-jdk5' - } - compile 'com.fasterxml.jackson.core:jackson-databind:2.11.0' - compile('com.google.apis:google-api-services-cloudiot:v1-rev20170922-1.22.0') { - exclude group: 'com.google.guava', module: 'guava-jdk5' - } - compile 'joda-time:joda-time:2.9.7' - compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0' - compile 'io.moquette:moquette-broker:0.10' - testCompile group: 'junit', name: 'junit', version: '4.13' - testCompile 'org.mockito:mockito-core:1.10.19' -} diff --git a/pubber/gradle/wrapper/gradle-wrapper.jar b/pubber/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 01b8bf6b1f..0000000000 Binary files a/pubber/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/pubber/gradle/wrapper/gradle-wrapper.properties b/pubber/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index f07e1a85bc..0000000000 --- a/pubber/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Feb 11 09:15:14 PST 2020 -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStorePath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME diff --git a/pubber/gradlew b/pubber/gradlew deleted file mode 100755 index 4453ccea33..0000000000 --- a/pubber/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save ( ) { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/pubber/local b/pubber/local deleted file mode 120000 index 0a4de1e828..0000000000 --- a/pubber/local +++ /dev/null @@ -1 +0,0 @@ -../local/ \ No newline at end of file diff --git a/pubber/pubber.iml b/pubber/pubber.iml deleted file mode 100644 index e0065ccd31..0000000000 --- a/pubber/pubber.iml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pubber/settings.gradle b/pubber/settings.gradle deleted file mode 100644 index 8b13789179..0000000000 --- a/pubber/settings.gradle +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pubber/src/main/java/daq/pubber/AbstractPoint.java b/pubber/src/main/java/daq/pubber/AbstractPoint.java deleted file mode 100644 index 44bd581c68..0000000000 --- a/pubber/src/main/java/daq/pubber/AbstractPoint.java +++ /dev/null @@ -1,15 +0,0 @@ -package daq.pubber; - -import daq.udmi.Message.PointData; -import daq.udmi.Message.PointState; - -public interface AbstractPoint { - - String getName(); - - PointData getData(); - - void updateData(); - - PointState getState(); -} diff --git a/pubber/src/main/java/daq/pubber/Configuration.java b/pubber/src/main/java/daq/pubber/Configuration.java deleted file mode 100644 index 7c362781ef..0000000000 --- a/pubber/src/main/java/daq/pubber/Configuration.java +++ /dev/null @@ -1,17 +0,0 @@ -package daq.pubber; - -/** - */ -public class Configuration { - public String bridgeHostname = "mqtt.googleapis.com"; - public String bridgePort = "443"; - public String projectId; - public String cloudRegion; - public String registryId; - public String gatewayId; - public String deviceId; - public String keyFile = "local/rsa_private.pkcs8"; - public byte[] keyBytes; - public String algorithm = "RS256"; - public Object extraField; -} diff --git a/pubber/src/main/java/daq/pubber/GatewayError.java b/pubber/src/main/java/daq/pubber/GatewayError.java deleted file mode 100644 index fcbc4954c9..0000000000 --- a/pubber/src/main/java/daq/pubber/GatewayError.java +++ /dev/null @@ -1,14 +0,0 @@ -package daq.pubber; - -public class GatewayError { - public String error_type; - public String description; - public String device_id; - public MqttMessageInfo mqtt_message_info; - - public static class MqttMessageInfo { - public String message_type; - public String topic; - public String packet_id; - } -} diff --git a/pubber/src/main/java/daq/pubber/JwtAuthorization.java b/pubber/src/main/java/daq/pubber/JwtAuthorization.java deleted file mode 100644 index cd17be9ba7..0000000000 --- a/pubber/src/main/java/daq/pubber/JwtAuthorization.java +++ /dev/null @@ -1,11 +0,0 @@ -package daq.pubber; - -import java.util.Arrays; - -public class JwtAuthorization { - public String authorization; - - public JwtAuthorization(String jwtToken) { - authorization = jwtToken; - } -} diff --git a/pubber/src/main/java/daq/pubber/MqttPublisher.java b/pubber/src/main/java/daq/pubber/MqttPublisher.java deleted file mode 100644 index 9358ee3546..0000000000 --- a/pubber/src/main/java/daq/pubber/MqttPublisher.java +++ /dev/null @@ -1,364 +0,0 @@ -package daq.pubber; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.util.ISO8601DateFormat; -import com.google.common.base.Preconditions; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.RemovalNotification; -import io.jsonwebtoken.JwtBuilder; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import org.eclipse.paho.client.mqttv3.*; -import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; -import org.joda.time.DateTime; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.charset.StandardCharsets; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.spec.PKCS8EncodedKeySpec; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Handle publishing sensor data to a Cloud IoT MQTT endpoint. - */ -public class MqttPublisher { - - private static final Logger LOG = LoggerFactory.getLogger(MqttPublisher.class); - - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() - .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - .setDateFormat(new ISO8601DateFormat()) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - - // Indicate if this message should be a MQTT 'retained' message. - private static final boolean SHOULD_RETAIN = false; - - private static final int MQTT_QOS = 1; - private static final String CONFIG_UPDATE_TOPIC_FMT = "/devices/%s/config"; - private static final String ERRORS_TOPIC_FMT = "/devices/%s/errors"; - private static final String UNUSED_ACCOUNT_NAME = "unused"; - private static final int INITIALIZE_TIME_MS = 20000; - - private static final String MESSAGE_TOPIC_FORMAT = "/devices/%s/%s"; - private static final String BROKER_URL_FORMAT = "ssl://%s:%s"; - private static final String CLIENT_ID_FORMAT = "projects/%s/locations/%s/registries/%s/devices/%s"; - private static final int PUBLISH_THREAD_COUNT = 10; - private static final String HANDLER_KEY_FORMAT = "%s/%s"; - - private final Semaphore connectionLock = new Semaphore(1); - - private final Map mqttClients = new ConcurrentHashMap<>(); - - private final ExecutorService publisherExecutor = - Executors.newFixedThreadPool(PUBLISH_THREAD_COUNT); - - private final Configuration configuration; - private final String registryId; - - private final AtomicInteger publishCounter = new AtomicInteger(0); - private final AtomicInteger errorCounter = new AtomicInteger(0); - private final AtomicInteger expiredCounter = new AtomicInteger(0); - private final Map> handlers = new ConcurrentHashMap<>(); - private final Map> handlersType = new ConcurrentHashMap<>(); - private final Consumer onError; - - MqttPublisher(Configuration configuration, Consumer onError) { - this.configuration = configuration; - this.registryId = configuration.registryId; - this.onError = onError; - validateCloudIoTOptions(); - } - - void publish(String deviceId, String topic, Object data) { - Preconditions.checkNotNull(deviceId, "publish deviceId"); - LOG.debug("Publishing in background " + registryId + "/" + deviceId); - publisherExecutor.submit(() -> publishCore(deviceId, topic, data)); - } - - private void publishCore(String deviceId, String topic, Object data) { - try { - String payload = OBJECT_MAPPER.writeValueAsString(data); - sendMessage(deviceId, getMessageTopic(deviceId, topic), payload.getBytes()); - LOG.debug("Publishing complete " + registryId + "/" + deviceId); - } catch (Exception e) { - errorCounter.incrementAndGet(); - LOG.warn(String.format("Publish failed for %s: %s", deviceId, e)); - if (configuration.gatewayId == null) { - closeDeviceClient(deviceId); - } else { - close(); - } - } - } - - private void closeDeviceClient(String deviceId) { - MqttClient removed = mqttClients.remove(deviceId); - if (removed != null) { - try { - removed.close(); - } catch (Exception e) { - LOG.error("Error closing MQTT client: " + e.toString()); - } - } - } - - void close() { - Set clients = mqttClients.keySet(); - for (String client : clients) { - closeDeviceClient(client); - } - } - - long clientCount() { - return mqttClients.size(); - } - - private void validateCloudIoTOptions() { - try { - checkNotNull(configuration.bridgeHostname, "bridgeHostname"); - checkNotNull(configuration.bridgePort, "bridgePort"); - checkNotNull(configuration.projectId, "projectId"); - checkNotNull(configuration.cloudRegion, "cloudRegion"); - checkNotNull(configuration.keyBytes, "keyBytes"); - checkNotNull(configuration.algorithm, "algorithm"); - } catch (Exception e) { - throw new IllegalStateException("Invalid Cloud IoT Options", e); - } - } - - private MqttClient newBoundClient(String deviceId) { - try { - String gatewayId = configuration.gatewayId; - LOG.debug("Connecting through gateway " + gatewayId); - MqttClient mqttClient = getConnectedClient(gatewayId); - String topic = String.format("/devices/%s/attach", deviceId); - String payload = ""; - LOG.info("Publishing attach message to topic " + topic); - mqttClient.publish(topic, payload.getBytes(StandardCharsets.UTF_8.name()), MQTT_QOS, SHOULD_RETAIN); - return mqttClient; - } catch (Exception e) { - throw new RuntimeException("While binding client " + deviceId, e); - } - } - - private MqttClient newMqttClient(String deviceId) { - try { - Preconditions.checkNotNull(registryId, "registryId is null"); - Preconditions.checkNotNull(deviceId, "deviceId is null"); - MqttClient mqttClient = new MqttClient(getBrokerUrl(), getClientId(deviceId), - new MemoryPersistence()); - return mqttClient; - } catch (Exception e) { - errorCounter.incrementAndGet(); - throw new RuntimeException("Creating new MQTT client " + deviceId, e); - } - } - - private MqttClient connectMqttClient(String deviceId) { - try { - if (!connectionLock.tryAcquire(INITIALIZE_TIME_MS, TimeUnit.MILLISECONDS)) { - throw new RuntimeException("Timeout waiting for connection lock"); - } - MqttClient mqttClient = newMqttClient(deviceId); - if (mqttClient.isConnected()) { - return mqttClient; - } - LOG.info("Attempting connection to " + registryId + ":" + deviceId); - - mqttClient.setCallback(new MqttCallbackHandler(deviceId)); - mqttClient.setTimeToWait(INITIALIZE_TIME_MS); - - MqttConnectOptions options = new MqttConnectOptions(); - options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1); - options.setUserName(UNUSED_ACCOUNT_NAME); - options.setMaxInflight(PUBLISH_THREAD_COUNT * 2); - options.setConnectionTimeout(INITIALIZE_TIME_MS); - - options.setPassword(createJwt()); - - mqttClient.connect(options); - - subscribeToUpdates(mqttClient, deviceId); - return mqttClient; - } catch (Exception e) { - throw new RuntimeException("While connecting mqtt client " + deviceId, e); - } finally { - connectionLock.release(); - } - } - - private char[] createJwt() throws Exception { - return createJwt(configuration.projectId, configuration.keyBytes, configuration.algorithm) - .toCharArray(); - } - - private String getClientId(String deviceId) { - // Create our MQTT client. The mqttClientId is a unique string that identifies this device. For - // Google Cloud IoT, it must be in the format below. - return String.format(CLIENT_ID_FORMAT, configuration.projectId, configuration.cloudRegion, - registryId, deviceId); - } - - private String getBrokerUrl() { - // Build the connection string for Google's Cloud IoT MQTT server. Only SSL connections are - // accepted. For server authentication, the JVM's root certificates are used. - return String.format(BROKER_URL_FORMAT, configuration.bridgeHostname, configuration.bridgePort); - } - - private String getMessageTopic(String deviceId, String topic) { - return String.format(MESSAGE_TOPIC_FORMAT, deviceId, topic); - } - - private void subscribeToUpdates(MqttClient client, String deviceId) { - subscribeTopic(client, String.format(CONFIG_UPDATE_TOPIC_FMT, deviceId)); - subscribeTopic(client, String.format(ERRORS_TOPIC_FMT, deviceId)); - } - - private void subscribeTopic(MqttClient client, String updateTopic) { - try { - client.subscribe(updateTopic); - } catch (MqttException e) { - throw new RuntimeException("While subscribing to MQTT topic " + updateTopic, e); - } - } - - public PublisherStats getStatistics() { - return new PublisherStats(); - } - - @SuppressWarnings("unchecked") - public void registerHandler(String deviceId, String mqttTopic, - Consumer handler, Class messageType) { - String key = getHandlerKey(getMessageTopic(deviceId, mqttTopic)); - if (handler == null) { - handlers.remove(key); - handlersType.remove(key); - } else if (handlers.put(key, (Consumer) handler) == null) { - handlersType.put(key, (Class) messageType); - } else { - throw new IllegalStateException("Overwriting existing handler for " + key); - } - } - - private String getHandlerKey(String configTopic) { - return String.format(HANDLER_KEY_FORMAT, registryId, configTopic); - } - - public void connect(String deviceId) { - getConnectedClient(deviceId); - } - - private class MqttCallbackHandler implements MqttCallback { - - private final String deviceId; - - MqttCallbackHandler(String deviceId) { - this.deviceId = deviceId; - } - - /** - * @see MqttCallback#connectionLost(Throwable) - */ - public void connectionLost(Throwable cause) { - LOG.warn("MQTT Connection Lost", cause); - } - - /** - * @see MqttCallback#deliveryComplete(IMqttDeliveryToken) - */ - public void deliveryComplete(IMqttDeliveryToken token) { - } - - /** - * @see MqttCallback#messageArrived(String, MqttMessage) - */ - public void messageArrived(String topic, MqttMessage message) { - String handlerKey = getHandlerKey(topic); - Consumer handler = handlers.get(handlerKey); - Class type = handlersType.get(handlerKey); - if (handler == null) { - onError.accept(new RuntimeException("No registered handler for " + handlerKey)); - } else if (message.toString().length() == 0) { - LOG.warn("Received message is empty for " + handlerKey); - handler.accept(null); - } else { - try { - handler.accept(OBJECT_MAPPER.readValue(message.toString(), type)); - } catch (Exception e) { - onError.accept(e); - } - } - } - } - - private void sendMessage(String deviceId, String mqttTopic, - byte[] mqttMessage) throws Exception { - LOG.debug("Sending message to " + mqttTopic); - getConnectedClient(deviceId).publish(mqttTopic, mqttMessage, MQTT_QOS, SHOULD_RETAIN); - publishCounter.incrementAndGet(); - } - - private MqttClient getConnectedClient(String deviceId) { - try { - String gatewayId = configuration.gatewayId; - if (gatewayId != null && !gatewayId.equals(deviceId)) { - return mqttClients.computeIfAbsent(deviceId, this::newBoundClient); - } - return mqttClients.computeIfAbsent(deviceId, this::connectMqttClient); - } catch (Exception e) { - throw new RuntimeException("While getting mqtt client " + deviceId + ": " + e.toString(), e); - } - } - - /** Load a PKCS8 encoded keyfile from the given path. */ - private PrivateKey loadKeyBytes(byte[] keyBytes, String algorithm) throws Exception { - try { - PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); - KeyFactory kf = KeyFactory.getInstance(algorithm); - return kf.generatePrivate(spec); - } catch (Exception e) { - throw new IllegalArgumentException("Loading key bytes", e); - } - } - - /** Create a Cloud IoT JWT for the given project id, signed with the given private key */ - protected String createJwt(String projectId, byte[] privateKeyBytes, String algorithm) - throws Exception { - DateTime now = new DateTime(); - // Create a JWT to authenticate this device. The device will be disconnected after the token - // expires, and will have to reconnect with a new token. The audience field should always be set - // to the GCP project id. - JwtBuilder jwtBuilder = - Jwts.builder() - .setIssuedAt(now.toDate()) - .setExpiration(now.plusMinutes(60).toDate()) - .setAudience(projectId); - - if (algorithm.equals("RS256")) { - PrivateKey privateKey = loadKeyBytes(privateKeyBytes, "RSA"); - return jwtBuilder.signWith(SignatureAlgorithm.RS256, privateKey).compact(); - } else if (algorithm.equals("ES256")) { - PrivateKey privateKey = loadKeyBytes(privateKeyBytes, "EC"); - return jwtBuilder.signWith(SignatureAlgorithm.ES256, privateKey).compact(); - } else { - throw new IllegalArgumentException( - "Invalid algorithm " + algorithm + ". Should be one of 'RS256' or 'ES256'."); - } - } - - public class PublisherStats { - public long clientCount = mqttClients.size(); - public int publishCount = publishCounter.getAndSet(0); - public int errorCount = errorCounter.getAndSet(0); - } -} diff --git a/pubber/src/main/java/daq/pubber/Pubber.java b/pubber/src/main/java/daq/pubber/Pubber.java deleted file mode 100644 index 5f28a08efa..0000000000 --- a/pubber/src/main/java/daq/pubber/Pubber.java +++ /dev/null @@ -1,282 +0,0 @@ -package daq.pubber; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Preconditions; -import daq.udmi.Entry; -import daq.udmi.Message; -import daq.udmi.Message.Pointset; -import daq.udmi.Message.PointsetState; -import daq.udmi.Message.State; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -public class Pubber { - - private static final Logger LOG = LoggerFactory.getLogger(Pubber.class); - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - - private static final String POINTSET_TOPIC = "events/pointset"; - private static final String SYSTEM_TOPIC = "events/system"; - private static final String STATE_TOPIC = "state"; - private static final String CONFIG_TOPIC = "config"; - private static final String ERROR_TOPIC = "errors"; - - private static final int MIN_REPORT_MS = 200; - private static final int DEFAULT_REPORT_MS = 5000; - private static final int CONFIG_WAIT_TIME_MS = 10000; - private static final int STATE_THROTTLE_MS = 1500; - private static final String CONFIG_ERROR_STATUS_KEY = "config_error"; - private static final int LOGGING_MOD_COUNT = 10; - - private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); - - private final Configuration configuration; - private final AtomicInteger messageDelayMs = new AtomicInteger(DEFAULT_REPORT_MS); - private final CountDownLatch configLatch = new CountDownLatch(1); - - private final State deviceState = new State(); - private final Pointset devicePoints = new Pointset(); - private final Set allPoints = new HashSet<>(); - - private MqttPublisher mqttPublisher; - private ScheduledFuture scheduledFuture; - private long lastStateTimeMs; - private int sendCount; - - public static void main(String[] args) throws Exception { - if (args.length != 1) { - throw new IllegalArgumentException("Expected [configPath] as argument"); - } - Pubber pubber = new Pubber(args[0]); - pubber.initialize(); - pubber.startConnection(); - LOG.info("Done with main"); - } - - private Pubber(String configFile) { - File configurationFile = new File(configFile); - LOG.info("Reading configuration from " + configurationFile.getAbsolutePath()); - try { - configuration = OBJECT_MAPPER.readValue(configurationFile, Configuration.class); - } catch (Exception e) { - throw new RuntimeException("While reading configuration file " + configurationFile.getAbsolutePath(), e); - } - info(String.format("Starting instance for project %s registry %s", - configuration.projectId, configuration.registryId)); - - initializeDevice(); - addPoint(new RandomPoint("superimposition_reading", 0, 100, "Celsius")); - addPoint(new RandomPoint("recalcitrant_angle", 0, 360, "deg" )); - addPoint(new RandomPoint("faulty_finding", 1, 1, "truth")); - } - - private void initializeDevice() { - deviceState.system.make_model = "DAQ_pubber"; - deviceState.system.firmware.version = "v1"; - deviceState.pointset = new PointsetState(); - devicePoints.extraField = configuration.extraField; - } - - private synchronized void maybeRestartExecutor(int intervalMs) { - if (scheduledFuture == null || intervalMs != messageDelayMs.get()) { - cancelExecutor(); - messageDelayMs.set(intervalMs); - startExecutor(); - } - } - - private synchronized void startExecutor() { - Preconditions.checkState(scheduledFuture == null); - int delay = messageDelayMs.get(); - LOG.info("Starting executor with send message delay " + delay); - scheduledFuture = executor - .scheduleAtFixedRate(this::sendMessages, delay, delay, TimeUnit.MILLISECONDS); - } - - private synchronized void cancelExecutor() { - if (scheduledFuture != null) { - scheduledFuture.cancel(false); - scheduledFuture = null; - } - } - - private void sendMessages() { - try { - sendDeviceMessage(configuration.deviceId); - updatePoints(); - if (sendCount % LOGGING_MOD_COUNT == 0) { - publishLogMessage(configuration.deviceId,"Sent " + sendCount + " messages"); - } - sendCount++; - } catch (Exception e) { - LOG.error("Fatal error during execution", e); - terminate(); - } - } - - private void updatePoints() { - allPoints.forEach(AbstractPoint::updateData); - } - - private void terminate() { - try { - info("Terminating"); - mqttPublisher.close(); - cancelExecutor(); - } catch (Exception e) { - info("Error terminating: " + e.getMessage()); - } - } - - private void startConnection() throws InterruptedException { - connect(); - boolean result = configLatch.await(CONFIG_WAIT_TIME_MS, TimeUnit.MILLISECONDS); - LOG.info("synchronized start config result " + result); - if (!result) { - mqttPublisher.close(); - } - } - - private void addPoint(AbstractPoint point) { - String pointName = point.getName(); - if (devicePoints.points.put(pointName, point.getData()) != null) { - throw new IllegalStateException("Duplicate pointName " + pointName); - } - deviceState.pointset.points.put(pointName, point.getState()); - allPoints.add(point); - } - - private void initialize() { - Preconditions.checkState(mqttPublisher == null, "mqttPublisher already defined"); - Preconditions.checkNotNull(configuration.keyFile, "configuration keyFile not defined"); - System.err.println("Loading device key file from " + configuration.keyFile); - configuration.keyBytes = getFileBytes(configuration.keyFile); - mqttPublisher = new MqttPublisher(configuration, this::reportError); - if (configuration.gatewayId != null) { - mqttPublisher.registerHandler(configuration.gatewayId, CONFIG_TOPIC, - this::configHandler, Message.Config.class); - mqttPublisher.registerHandler(configuration.gatewayId, ERROR_TOPIC, - this::errorHandler, GatewayError.class); - } - mqttPublisher.registerHandler(configuration.deviceId, CONFIG_TOPIC, - this::configHandler, Message.Config.class); - } - - private void connect() { - try { - mqttPublisher.connect(configuration.deviceId); - LOG.info("Connection complete."); - } catch (Exception e) { - LOG.error("Connection error", e); - LOG.error("Forcing termination"); - System.exit(-1); - } - } - - private void reportError(Exception toReport) { - if (toReport != null) { - LOG.error("Error receiving message: " + toReport); - Entry report = new Entry(toReport); - deviceState.system.statuses.put(CONFIG_ERROR_STATUS_KEY, report); - publishStateMessage(configuration.deviceId); - } else { - Entry previous = deviceState.system.statuses.remove(CONFIG_ERROR_STATUS_KEY); - if (previous != null) { - publishStateMessage(configuration.deviceId); - } - } - } - - private void info(String msg) { - LOG.info(msg); - } - - private void configHandler(Message.Config config) { - try { - info("Received new config " + config); - final int actualInterval; - if (config != null) { - Integer reportInterval = config.system == null ? null : config.system.report_interval_ms; - actualInterval = Integer.max(MIN_REPORT_MS, - reportInterval == null ? DEFAULT_REPORT_MS : reportInterval); - deviceState.system.last_config = config.timestamp; - } else { - actualInterval = DEFAULT_REPORT_MS; - } - maybeRestartExecutor(actualInterval); - configLatch.countDown(); - publishStateMessage(configuration.deviceId); - reportError(null); - } catch (Exception e) { - reportError(e); - } - } - - private void errorHandler(GatewayError error) { - // TODO: Handle error and give up on device. - info(String.format("%s for %s: %s", - error.error_type, error.device_id, error.description)); - } - - private byte[] getFileBytes(String dataFile) { - Path dataPath = Paths.get(dataFile); - try { - return Files.readAllBytes(dataPath); - } catch (Exception e) { - throw new RuntimeException("While getting data from " + dataPath.toAbsolutePath(), e); - } - } - - private void sendDeviceMessage(String deviceId) { - if (mqttPublisher.clientCount() == 0) { - LOG.error("No connected clients, exiting."); - System.exit(-2); - } - info(String.format("Sending test message for %s/%s", configuration.registryId, deviceId)); - devicePoints.timestamp = new Date(); - mqttPublisher.publish(deviceId, POINTSET_TOPIC, devicePoints); - } - - private void publishLogMessage(String deviceId, String logMessage) { - info(String.format("Sending log message for %s/%s", configuration.registryId, deviceId)); - Message.SystemEvent systemEvent = new Message.SystemEvent(); - systemEvent.logentries.add(new Entry(logMessage)); - mqttPublisher.publish(deviceId, SYSTEM_TOPIC, systemEvent); - } - - private void publishStateMessage(String deviceId) { - lastStateTimeMs = sleepUntil(lastStateTimeMs + STATE_THROTTLE_MS); - info("Sending state message for device " + deviceId); - deviceState.timestamp = new Date(); - mqttPublisher.publish(deviceId, STATE_TOPIC, deviceState); - } - - private long sleepUntil(long targetTimeMs) { - long currentTime = System.currentTimeMillis(); - long delay = targetTimeMs - currentTime; - try { - if (delay > 0) { - Thread.sleep(delay); - } - return System.currentTimeMillis(); - } catch (Exception e) { - throw new RuntimeException("While sleeping for " + delay, e); - } - } -} diff --git a/pubber/src/main/java/daq/pubber/RandomPoint.java b/pubber/src/main/java/daq/pubber/RandomPoint.java deleted file mode 100644 index dcf0ff0a03..0000000000 --- a/pubber/src/main/java/daq/pubber/RandomPoint.java +++ /dev/null @@ -1,42 +0,0 @@ -package daq.pubber; - -import daq.udmi.Message.PointData; -import daq.udmi.Message.PointState; - -public class RandomPoint implements AbstractPoint { - - private final String name; - private final double min; - private final double max; - private final PointData data = new PointData(); - private final PointState state = new PointState(); - - public RandomPoint(String name, double min, double max, String units) { - this.name = name; - this.min = min; - this.max = max; - this.state.fault = max == min; - this.state.units = units; - updateData(); - } - - @Override - public void updateData() { - data.present_value = Math.round(Math.random() * (max - min) + min); - } - - @Override - public PointState getState() { - return state; - } - - @Override - public String getName() { - return name; - } - - @Override - public PointData getData() { - return data; - } -} diff --git a/pubber/src/main/java/daq/udmi/Entry.java b/pubber/src/main/java/daq/udmi/Entry.java deleted file mode 100644 index 25201edc72..0000000000 --- a/pubber/src/main/java/daq/udmi/Entry.java +++ /dev/null @@ -1,26 +0,0 @@ -package daq.udmi; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.Date; - -public class Entry { - public String message; - public String detail; - public String category = "com.acme.pubber"; - public Integer level = 500; - public Date timestamp = new Date(); - - public Entry(String message) { - this.message = message; - } - - public Entry(Exception e) { - message = e.toString(); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - e.printStackTrace(new PrintStream(outputStream)); - detail = outputStream.toString(); - category = e.getStackTrace()[0].getClassName(); - level = 800; - } -} diff --git a/pubber/src/main/java/daq/udmi/Message.java b/pubber/src/main/java/daq/udmi/Message.java deleted file mode 100644 index c15f9c842c..0000000000 --- a/pubber/src/main/java/daq/udmi/Message.java +++ /dev/null @@ -1,76 +0,0 @@ -package daq.udmi; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@SuppressWarnings("unused") -public class Message { - - public static class State extends UdmiBase { - public SystemState system = new SystemState(); - public PointsetState pointset; - } - - public static class Config extends UdmiBase { - public SystemConfig system; - public PointsetConfig pointset; - public GatewayConfig gateway; - } - - public static class Pointset extends UdmiBase { - public Map points = new HashMap<>(); - public Object extraField; - } - - public static class SystemEvent extends UdmiBase { - public List logentries = new ArrayList<>(); - } - - public static class PointsetState { - public Map points = new HashMap<>(); - } - - public static class PointsetConfig { - public Map points = new HashMap<>(); - } - - public static class PointConfig { - } - - public static class GatewayConfig { - public List proxy_ids; - } - - public static class SystemState { - public String make_model; - public Bundle firmware = new Bundle(); - public boolean operational; - public Date last_config; - public Map statuses = new HashMap<>(); - } - - public static class SystemConfig { - public Integer report_interval_ms; - } - - public static class PointData { - public Object present_value; - } - - public static class PointState { - public String units; - public Boolean fault; - } - - public static class Bundle { - public String version; - } - - public static class UdmiBase { - public Integer version = 1; - public Date timestamp = new Date(); - } -} diff --git a/resources/device_types/deltacontrols_o3-din-cpu/module_config.json b/resources/device_types/deltacontrols_o3-din-cpu/module_config.json index 066bf35abb..a17a5a6997 100644 --- a/resources/device_types/deltacontrols_o3-din-cpu/module_config.json +++ b/resources/device_types/deltacontrols_o3-din-cpu/module_config.json @@ -24,6 +24,9 @@ "nmap": { "enabled": true }, + "ntp": { + "enabled": true + }, "switch": { "enabled": true, "poe": { diff --git a/resources/device_types/distech_ecy-s1000/module_config.json b/resources/device_types/distech_ecy-s1000/module_config.json index d790899c5c..b9a1847754 100644 --- a/resources/device_types/distech_ecy-s1000/module_config.json +++ b/resources/device_types/distech_ecy-s1000/module_config.json @@ -24,6 +24,9 @@ "nmap": { "enabled": true }, + "ntp": { + "enabled": true + }, "switch": { "enabled": true, "poe": { diff --git a/resources/setups/baseline/module_config.json b/resources/setups/baseline/module_config.json index 8ebd56cc57..be0cb97454 100644 --- a/resources/setups/baseline/module_config.json +++ b/resources/setups/baseline/module_config.json @@ -1,7 +1,10 @@ { "modules": { "ipaddr": { - "timeout_sec": 300 + "enabled": false, + "timeout_sec": 900, + "port_flap_timeout_sec": 20, + "dhcp_ranges": [{"start": "192.168.0.1", "end": "192.168.255.254", "prefix_length": 16}] }, "pass": { "enabled": true @@ -32,6 +35,9 @@ }, "network": { "enabled": true + }, + "ntp": { + "enabled": true } } } diff --git a/resources/setups/qualification/device_module_config.json b/resources/setups/qualification/device_module_config.json index 6019735d2b..9713c5723b 100644 --- a/resources/setups/qualification/device_module_config.json +++ b/resources/setups/qualification/device_module_config.json @@ -39,6 +39,9 @@ "nmap": { "enabled": true }, + "ntp": { + "enabled": true + }, "switch": { "enabled": true, "poe": { diff --git a/resources/setups/qualification/device_type_module_config.json b/resources/setups/qualification/device_type_module_config.json index f183d5527c..9d3181460b 100644 --- a/resources/setups/qualification/device_type_module_config.json +++ b/resources/setups/qualification/device_type_module_config.json @@ -33,6 +33,9 @@ "nmap": { "enabled": true }, + "ntp": { + "enabled": true + }, "switch": { "enabled": true, "poe": { diff --git a/resources/setups/qualification/system_module_config.json b/resources/setups/qualification/system_module_config.json index de3cc56461..be6d1bf2ef 100644 --- a/resources/setups/qualification/system_module_config.json +++ b/resources/setups/qualification/system_module_config.json @@ -24,6 +24,9 @@ "nmap": { "enabled": true }, + "ntp": { + "enabled": true + }, "switch": { "enabled": true, "poe": { @@ -90,6 +93,11 @@ "required": "pass", "expected": "Required Pass" }, + "connection.network.ntp_update": { + "category": "Network Time", + "required": "pass", + "expected": "Required Pass" + }, "connection.network.communication_type": { "category": "Communication", "required": "info", diff --git a/resources/setups/remediation/device_module_config.json b/resources/setups/remediation/device_module_config.json index 976761c762..65223dac27 100644 --- a/resources/setups/remediation/device_module_config.json +++ b/resources/setups/remediation/device_module_config.json @@ -35,6 +35,9 @@ "nmap": { "enabled": true }, + "ntp": { + "enabled": true + }, "switch": { "enabled": true, "poe": { diff --git a/resources/setups/remediation/system_module_config.json b/resources/setups/remediation/system_module_config.json index 17e7793758..58fb3fa9f4 100644 --- a/resources/setups/remediation/system_module_config.json +++ b/resources/setups/remediation/system_module_config.json @@ -24,6 +24,9 @@ "nmap": { "enabled": true }, + "ntp": { + "enabled": true + }, "switch": { "enabled": true, "poe": { @@ -86,6 +89,11 @@ "required": "pass", "expected": "Recommended Pass" }, + "connection.network.ntp_update": { + "category": "Network Time", + "required": "pass", + "expected": "Recommended Pass" + }, "connection.network.communication_type": { "category": "Communication", "required": "info", diff --git a/resources/test_site/devices/AHU-1/metadata.json b/resources/test_site/devices/AHU-1/metadata.json index cdee5cc055..09eb5ce94d 100644 --- a/resources/test_site/devices/AHU-1/metadata.json +++ b/resources/test_site/devices/AHU-1/metadata.json @@ -1,13 +1,13 @@ { "pointset": { "points": { - "filter_alarm_pressure_status": { + "faulty_finding": { "units": "Bars" }, - "filter_differential_pressure_sensor": { + "recalcitrant_angle": { "units": "Degrees-Celsius" }, - "filter_differential_pressure_setpoint": { + "superimposition_reading": { "units": "No-units" } } diff --git a/resources/test_site/module_config.json b/resources/test_site/module_config.json index 4d672b67aa..ac17f224b1 100644 --- a/resources/test_site/module_config.json +++ b/resources/test_site/module_config.json @@ -17,6 +17,12 @@ }, "manual": { "enabled": true + }, + "ntp": { + "enabled": true + }, + "ssh": { + "enabled": false } }, "process": { diff --git a/schemas/simple/simple.json b/schemas/simple/simple.json deleted file mode 100644 index fa31b8e8d0..0000000000 --- a/schemas/simple/simple.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type" : "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "properties" : { - "rectangle" : {"$ref" : "#/definitions/Rectangle" } - }, - "required": [ - "rectangle" - ], - "definitions" : { - "size" : { - "type" : "number", - "minimum" : 0 - }, - "Rectangle" : { - "type" : "object", - "required": [ - "a", - "b" - ], - "properties" : { - "a" : {"$ref" : "#/definitions/size"}, - "b" : {"$ref" : "#/definitions/size"} - } - } - } -} \ No newline at end of file diff --git a/schemas/simple/simple.tests/error.json b/schemas/simple/simple.tests/error.json deleted file mode 100644 index 361ce8baae..0000000000 --- a/schemas/simple/simple.tests/error.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rectangle" : { - "a" : -4, - "b" : 5 - } -} diff --git a/schemas/simple/simple.tests/error.out b/schemas/simple/simple.tests/error.out deleted file mode 100644 index d5320ed8a3..0000000000 --- a/schemas/simple/simple.tests/error.out +++ /dev/null @@ -1,4 +0,0 @@ -Validating 1 schemas - Validating 1 files against simple.json - Against input simple.tests/error.json - #/rectangle/a: -4 is not greater or equal to 0 diff --git a/schemas/simple/simple.tests/example.json b/schemas/simple/simple.tests/example.json deleted file mode 100644 index e6751b6099..0000000000 --- a/schemas/simple/simple.tests/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rectangle" : { - "a" : 4, - "b" : 5 - } -} diff --git a/schemas/simple/simple.tests/example.out b/schemas/simple/simple.tests/example.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/simple/simple.tests/simple.json b/schemas/simple/simple.tests/simple.json deleted file mode 100644 index fa31b8e8d0..0000000000 --- a/schemas/simple/simple.tests/simple.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type" : "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "properties" : { - "rectangle" : {"$ref" : "#/definitions/Rectangle" } - }, - "required": [ - "rectangle" - ], - "definitions" : { - "size" : { - "type" : "number", - "minimum" : 0 - }, - "Rectangle" : { - "type" : "object", - "required": [ - "a", - "b" - ], - "properties" : { - "a" : {"$ref" : "#/definitions/size"}, - "b" : {"$ref" : "#/definitions/size"} - } - } - } -} \ No newline at end of file diff --git a/schemas/simple/simple.tests/simple.out b/schemas/simple/simple.tests/simple.out deleted file mode 100644 index 85d5807ab3..0000000000 --- a/schemas/simple/simple.tests/simple.out +++ /dev/null @@ -1,4 +0,0 @@ -Validating 1 schemas - Validating 1 files against simple.json - Against input simple.tests/simple.json - #: required key [rectangle] not found diff --git a/schemas/udmi/README.md b/schemas/udmi/README.md deleted file mode 100644 index b0c450fa94..0000000000 --- a/schemas/udmi/README.md +++ /dev/null @@ -1,163 +0,0 @@ -# UDMI Schema - -The Universal Device Management Interface (UDMI) provides a high-level specification for the -management and operation of physical IoT systems. This data is typically exchanged -with a cloud entity that can maintain a "digital twin" or "shadow device" in the cloud. -Nominally meant for use with [Googe's Cloud IoT Core](https://cloud.google.com/iot/docs/), -as a schema it can be applied to any set of data or hosting setup. Additionally, the schema -has provisions for basic telemetry ingestion, such as datapoint streaming from an IoT device. - -By deisgn, this schema is intended to be: -* Universal: Apply to all subsystems in a building, not a singular vertical solution. -* Device: Operations on an IoT _device_, a managed entity in physical space. -* Management: Focus on device _management_, rather than command & control. -* Interface: Define an interface specification, rather than a client-library or -RPC mechanism. - -See the associated [UDMI Tech Stack](TECH_STACK.md) for details about transport mechanism -outside of the core schema definition. For questions and discussion pertaining to this topic, -please join/monitor the -[daq-users@googlegroups.com](https://groups.google.com/forum/#!forum/daq-users) email list - -## Use Cases - -The essence behind UDMI is an automated mechanism for IoT system management. Many current -systems require direct-to-device access, such as through a web browser or telnet/ssh session. -These techniques do not scale to robust managed ecosystems since they rely too heavily on -manual operation (aren't automated), and increase the security exposure of the system -(since they need to expose these management ports). - -UDMI is intended to support a few primary use-cases: -* _Telemetry Ingestion_: Ingest device data points in a standardized format. -* [_Gateway Proxy_](docs/gateway.md): Proxy data/connection for non-UDMI devices, -allowing adaptation to legacy systems. -* _On-Prem Actuation_: Ability to effect on-prem device behavior. -* _Device Testability_: e.g. Trigger a fake alarm to test reporting mechanims. -* _Commissioning Tools_: Streamline complete system setup and install. -* _Operational Diagnostics_: Make it easy for system operators to diagnoe basic faults. -* _Status and Logging_: Report system operational metrics to hosting infrastructure. -* _Key Rotation_: Manage encryption keys and certificates in accordance with best practice. -* _Credential Exchange_: Bootstrap higher-layer authentication to restricted resources. -* _Firmware Updates_: Initiate, monitor, and track firmware updates across an entire fleet -of devices. -* _On-Prem Discovery_: Enumerate and on-prem devices to aid setup or anomaly detection. - -All these situations are conceptually about _management_ of devices, which is conceptually -different than the _control_ or _operation_. These concepts are similar to the _management_, -_control_, and _data_ planes of -[Software Defined Networks](https://queue.acm.org/detail.cfm?id=2560327). -Once operational, the system should be able to operate completely autonomoulsy from the -management capabilities, which are only required to diagnose or tweak system behavior. - -## Design Philiosphy - -In order to provide for management automation, UDMI strives for the following principles: -* Secure and Authenticated: Requires a propertly secure and authenticated channel -from the device to managing infrastructure. -* Declarative Specification: The schema describes the _desired_ state of the system, -relying on the underlying mechanisms to match actual state with desired state. This is -conceptually similar to Kubernetes-style configuraiton files. -* Minimal Elegant Design: Initially underspecified, with an eye towards making it easy to -add new capabilities in the future. It is easier to add something than it is to remove it. -* Reduced Choices: In the long run, choice leads to more work -to implement, and more ambiguity. Strive towards having only _one_ way of doing each thing. -* Structure and Clarity: This is not a "compressed" format and not designed for -very large structures or high-bandwidth streams. -* Property Names:Uses snake_case convention for property names. -* Resource Names: Overall structure (when flattened to paths), follows the -[API Resource Names guidline](https://cloud.google.com/apis/design/resource_names). - -## Schema Structure - -Schemas are broken down into several top-level sub-schemas that are invoked for -different aspects of device management: -* Device _state_ ([example](state.tests/example.json)), sent from device to cloud, -defined by [state.json](state.json). There is one current _state_ per device, -which is considered sticky until a new state message is sent. -is comprised of several subsections (e.g. _system_ or _pointset_) that describe the -relevant sub-state components. -* Device _config_ ([example](config.tests/example.json)), passed from cloud to device, -defined by [config.json](config.json). There is one active _config_ per device, -which is considered current until a new config is recevied. -* Message _envelope_ ([example](envelope.tests/example.json)) for server-side -attributes of received messages, defined by [envelope.json](envelope.json). This is -automatically generated by the transport layer and is then available for server-side -processing. -* Device _metadata_ ([example](metadata.tests/example.json)) stored in the cloud about a device, -but not directly available to or on the device, defined by [metadata.json](metadata.json). -This is essentially a specification about how the device should be configured or -expectations about what the device should be doing. -* Streaming device telemetry, which can take on several different forms, depending on the intended -use, e.g.: - * Streaming _pointset_ ([example](pointset.tests/example.json)) from device to cloud, - defined by [pointset.json](pointset.json). _pointset_ is used for delivering a - set of data point telemetry. - * Core _system_ messages ([example](system.tests/example.json)) from devices, such as log - entries and access logs, defined by [system.json](system.json). - * Local _discover_ messages ([example](discover.tests/example.json)) that show the - results of local scans or probes to determine which devices are on the local network, - defined by [discover.json](discover.json). - -A device client implementation will typically only be aware of the _state_, _config_, and -one or more telemetry messages (e.g. _pointset_), while all others are meant for the supporting -infrastructure. Additionally, the _state_ and _config_ parts are comprised of several distinct -subsections (e.g. _system_, _pointset_, or _gateway_) that relate to various bits of functionality. - -## Validation - -To verify correct operation of a real system, follow the instructions outlined in the -[validator subsystem docs](../../docs/validator.md), which provides for a suitable -communication channel. Additional sample messages are easy to include in the regression -suite if there are new cases to test. - -## Message Detail Notes - -### State Message - -* See notes below about 'State status' fields. -* There is an implicit minimum update interval of _one second_ applied to state updates, and it -is considered an error to update device state more often than that. -* `last_config` should be the timestamp _from_ the `timestamp` field of the last successfully -parsed `config` message. - -### Config Message - -* `sample_rate_sec`: Sampling rate for the system, which should proactively send an -update (e.g. _pointset_, _logentry_, _discover_ message) at this interval. -* `sample_limit_sec`: Minimum time between sample updates. Updates that happen faster than this time -(e.g. due to _cov_ events) should be coalesced so that only the most recent update is sent. -* `fix_value`: Fix a value to be used during diagnostics and operational use. Should -override any operational values, but not override alarm conditions. -* `min_loglevel`: Indicates the minimum loglevel for reporting log messages below which log entries -should not be sent. See note below for a description of the level value. - -### Logentry Message - -* See notes below about 'logentry entries' fields. - -### State status and logentry entries fields - -The State and System/logentry messages both have `status` and `entries` sub-fields, respectivly, that -follow the same structure. -* State `status` entries represent 'sticky' conditions that persist until the situation is cleared, -e.g. "device disconnected". -* A `statuses` entry is a map of 'sticky' conditions that are keyed on a value that can be -used to manage updates by a particular (device dependent) subsystem. -* Logentry `entries` fields are transitory event that happen, e.g. "connection failed". -* The log `entries` field is an array that can be used to collaesce multiple log updates into -one message. -* Config parse errors should be represented as a system-level device state `status` entry. -* The `message` field sould be a one-line representation of the triggering condition. -* The `detail` field can be multi-line and include more detail, e.g. a complete program -stack-trace. -* The `category` field is a device-specific representation of which sub-system the message comes -from. In a Java environment, for example, it would be the fully qualified path name of the Class -triggering the message. -* A `status` or `statuses` `timestamp` field should be the timestamp the condition was triggered, -or most recently updated. It might be different than the top-level message `timestamp` if the -condition is not checked often or is sticky until it's cleared. -* A logentry `entries` `timestamp` field is the time that the event occured, which is potentially -different than the top-level `timestamp` field (which is when the log was sent). -* The status `level` should conform to the numerical -[Stackdriver LogEntry](https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity) -levels. The `DEFAULT` value of 0 is not allowed (lowest value is 100, maximum 800). diff --git a/schemas/udmi/TECH_STACK.md b/schemas/udmi/TECH_STACK.md deleted file mode 100644 index 86d3c0ab4e..0000000000 --- a/schemas/udmi/TECH_STACK.md +++ /dev/null @@ -1,46 +0,0 @@ -# UDMI Technology Stack - -The complete UDMI specificaiton (super set of the base schema), specifies a complete -technology stack for compliant IoT devices. - -# Core Requirements - -* [Google Cloud's MQTT Protocol Bridge](https://cloud.google.com/iot/docs/how-tos/mqtt-bridge). - * This is _not_ the same as a generic MQTT Broker, but it is compatible with standard client-side libraries. - * Other transports (non-Google MQTT, CoAP, etc...) are acceptable with prior approval. - * Connected to a specific Cloud IoT Registry designated for each site-specific project. -* Utilizes the MQTT Topic table listed below. -* JSON encoding following the core [UDMI Schema](README.md), specifying the semantic structure of the data. -* Passes the [DAQ Validation Tool](../../docs/validator.md) for all requirements. - -# MQTT Topic Table - -| Type | Category | subFolder | MQTT Topic | Schema File | -|----------|----------|-----------|----------------------------------------|---------------| -| state | state | _n/a_ | `/devices/{device_id}/state` | state.json | -| config | config | _n/a_ | `/devices/{device-id}/config` | config.json | -| pointset | event | pointset | `/devices/{device-id}/events/pointset` | pointset.json | -| system | event | system | `/devices/{device-id}/events/system` | system.json | - -# Backend Systems - -Any backend system (in a GCP project) should adhere to the following guidelines: -* All messages to/from the devices should conform to the UDMI schema payloads (pass validation). -* All exchanges with the devices should go through a PubSub topic: - * The _state_ and _event_ messages are published to a topic configured through the IoT Core registry. - * If necessary, any _config_ or _command_ messages should go through a PubSub topic, and then converted to the requisite Cloud IoT - config write using a simple cloud function. -* To make data persistent, it can be written to a back-end database, e.g. Firestore. See the `device_telemetry` and - `device_state` [example cloud functions](../../firebase/functions/index.js) for details. -* A similar function called `device_config` shows how PubSub can be used to update the Cloud IoT configuration. - -A config push can be tested with something like: - -``` -gcloud pubsub topics publish target \ - --attribute subFolder=config,deviceId=AHU-1,projectId=bos-daq-testing,cloudRegion=us-central1,deviceRegistryId=registrar_test \ - --message '{"version": 1, "timestamp": "2019-01-17T14:02:29.364Z"}' -``` - -The reason for the redirection of any data through a PubSub topic is so that the Cloud IoT registry, if necessary, -can be housed in a different cloud project from the backend applications. diff --git a/schemas/udmi/config.json b/schemas/udmi/config.json deleted file mode 100644 index 73f19b0b4b..0000000000 --- a/schemas/udmi/config.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "title": "Device Config Schema", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "required": [ - "timestamp", - "version" - ], - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" - }, - "version": { - "enum": [ - 1 - ] - }, - "system": { - "$ref": "file:config_system.json#" - }, - "gateway": { - "$ref": "file:config_gateway.json#" - }, - "localnet": { - "$ref": "file:config_localnet.json#" - }, - "pointset": { - "$ref": "file:config_pointset.json#" - } - } -} diff --git a/schemas/udmi/config.tests/empty.json b/schemas/udmi/config.tests/empty.json deleted file mode 100644 index 2c63c08510..0000000000 --- a/schemas/udmi/config.tests/empty.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/schemas/udmi/config.tests/empty.out b/schemas/udmi/config.tests/empty.out deleted file mode 100644 index c9aa2803fc..0000000000 --- a/schemas/udmi/config.tests/empty.out +++ /dev/null @@ -1,6 +0,0 @@ -Validating 1 schemas - Validating 1 files against config.json - Against input config.tests/empty.json - #: 2 schema violations found - #: required key [timestamp] not found - #: required key [version] not found diff --git a/schemas/udmi/config.tests/errors.json b/schemas/udmi/config.tests/errors.json deleted file mode 100644 index 407a7c9eb0..0000000000 --- a/schemas/udmi/config.tests/errors.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "properties": { - "make_model": "com.yoyodine.flux_capacitor", - "whoowhoo": true, - "release": "231_rev_8" - }, - "type": "config", - "system": { - }, - "points": { - }, - "pointset": { - "sample_rate_sec": "5", - "version": 1, - "id": "miXeD_CaSE", - "timestamp": "2018-08-26T21:39:29.364Z", - "properties": { - "device_id": "33895507", - "object_name": "UK-BRH-XX_AHU-001", - }, - "points": { - "return_air_temperature_sensor": { - "object_type": "analog_input", - "units": "Degrees Celsius" - } - } - } -} diff --git a/schemas/udmi/config.tests/errors.out b/schemas/udmi/config.tests/errors.out deleted file mode 100644 index 80edaa341f..0000000000 --- a/schemas/udmi/config.tests/errors.out +++ /dev/null @@ -1,16 +0,0 @@ -Validating 1 schemas - Validating 1 files against config.json - Against input config.tests/errors.json - #: 10 schema violations found - #/pointset: 7 schema violations found - #/pointset/points/return_air_temperature_sensor: 2 schema violations found - #/pointset/points/return_air_temperature_sensor: extraneous key [object_type] is not permitted - #/pointset/points/return_air_temperature_sensor: extraneous key [units] is not permitted - #/pointset/sample_rate_sec: expected type: Number, found: String - #/pointset: extraneous key [id] is not permitted - #/pointset: extraneous key [properties] is not permitted - #/pointset: extraneous key [timestamp] is not permitted - #/pointset: extraneous key [version] is not permitted - #: extraneous key [points] is not permitted - #: extraneous key [properties] is not permitted - #: extraneous key [type] is not permitted diff --git a/schemas/udmi/config.tests/example.json b/schemas/udmi/config.tests/example.json deleted file mode 100644 index 164fb358b2..0000000000 --- a/schemas/udmi/config.tests/example.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "min_loglevel": 500 - }, - "pointset": { - "sample_limit_sec": 2, - "sample_rate_sec": 500, - "points": { - "return_air_temperature_sensor": { - }, - "nexus_sensor": { - "fix_value": 21.1 - } - } - } -} diff --git a/schemas/udmi/config.tests/example.out b/schemas/udmi/config.tests/example.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/config.tests/fcu.json b/schemas/udmi/config.tests/fcu.json deleted file mode 100644 index 03380428c8..0000000000 --- a/schemas/udmi/config.tests/fcu.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": 1, - "timestamp": "2019-01-17T14:02:29.364Z", - "system": { - "max_update_ms": 50000, - "min_loglevel": 500 - }, - "pointset": { - "points": { - "space_temperature_sensor": { - }, - "fan_run_status": { - "fix_value": true - }, - "fan_run_enable": { - "fix_value": false - }, - "chilled_water_valve_percentage_command": { - "min_update_ms": 1000 - } - } - } -} diff --git a/schemas/udmi/config.tests/fcu.out b/schemas/udmi/config.tests/fcu.out deleted file mode 100644 index f81283bace..0000000000 --- a/schemas/udmi/config.tests/fcu.out +++ /dev/null @@ -1,6 +0,0 @@ -Validating 1 schemas - Validating 1 files against config.json - Against input config.tests/fcu.json - #: 2 schema violations found - #/pointset/points/chilled_water_valve_percentage_command: extraneous key [min_update_ms] is not permitted - #/system: extraneous key [max_update_ms] is not permitted diff --git a/schemas/udmi/config.tests/gateway.json b/schemas/udmi/config.tests/gateway.json deleted file mode 100644 index 294aabb2ce..0000000000 --- a/schemas/udmi/config.tests/gateway.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "gateway": { - "proxy_ids": [ "AHU-123", "SMS-81", "991" ] - } -} diff --git a/schemas/udmi/config.tests/gateway.out b/schemas/udmi/config.tests/gateway.out deleted file mode 100644 index 1f85426706..0000000000 --- a/schemas/udmi/config.tests/gateway.out +++ /dev/null @@ -1,4 +0,0 @@ -Validating 1 schemas - Validating 1 files against config.json - Against input config.tests/gateway.json - #/gateway/proxy_ids/2: string [991] does not match pattern ^[A-Z]{3}-[1-9][0-9]{0,2}$ diff --git a/schemas/udmi/config.tests/proxy.json b/schemas/udmi/config.tests/proxy.json deleted file mode 100644 index 6f56202964..0000000000 --- a/schemas/udmi/config.tests/proxy.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "min_loglevel": 500 - }, - "localnet": { - "subsystem": { - "bacnet": { - "local_id": "0x78ce1900" - } - } - }, - "pointset": { - "sample_limit_sec": 2, - "sample_rate_sec": 500, - "points": { - "return_air_temperature_sensor": { - "ref": "BV23.present_value" - } - } - } -} diff --git a/schemas/udmi/config.tests/proxy.out b/schemas/udmi/config.tests/proxy.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/config.tests/rotate.json b/schemas/udmi/config.tests/rotate.json deleted file mode 100644 index 652a698ba0..0000000000 --- a/schemas/udmi/config.tests/rotate.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "auth_key": { - "private": "pkcs8:MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD2PpibhV7vs1ZqGXsV3bCW2p1+WScg6QUNQQb1Ua8pjwIrOQzPfTROpAlxuBAlSbC+aDIz/NrAF0E7tNJx5N8Zk0ekIoqCEVGx/0XuJtyvSYESBclCD7bD3d6KUHcVOK/7hVo7nVnrEjjmihdsz1TSqxmIiNcSe55xboqtJBJLMb9yE646Y/P/kRKCOurR73h3a1N5ipVgpflyMVEW0z/B6GPTc4FRMCAv/6+Mp7v9kjZ/rJa7VwgSMLl/AJ1xyiH3ScQN2dBTCxeGlOu2Ed4v8Rse3OKbOyIbiXQqPeOdys7+CdAtng7qgDLQzinA1r+1YDeSgpLIEHnsnXHBBz1zAgMBAAECggEACm8ilkxzdmK6AarsvUN0jR/cVpM+hjV5glNEETcR3gfyRpSXR199zOtEfy4WeQ4DUD4oCm3ncwZJPFdwJ2VUUsgb3AeeqN5FAO7ZLrs01LSfpHzcR1FVJD2NhXzdXufVBSpkZWxIeB6AjLxDO9gZNwgK/+8UdfMJBrNxat7Ba7AtrYCaAcqh8ewsoGNJte9OC1ubLSvw5p/88XaBYyhN2MLrrOvv7hezsxVakUquPK0xCekV+ScK+6ezrtZVIkvg2ozlF2cffHRoQEjBDju/qQD3dsBAkqol7Lw25KntrM+wBSyCwD04eFzICeDYUBER20SeKEzYRCOek5TgKIeb8QKBgQD/syGWNfE7ZnlswdXYTaHCgCEgQg4N4wwqUva81agAuJbXYXPiBLq0qDiieyyPIT7qU/uCF+R25OJAl/228cVbkhyXa4TAjM5EAAuHeyOwJi+ZBE+c2Mo4Z4mJoXjLzNSvF+ytRQjoAXiErZ4+Kl6wI7zgeIA+SsA0Yy2qStJSKwKBgQD2iJ9bL0FtC/HkkgiCOblLJ1nSiMiTbDAcm9KbeeRDRVpbsYzdVkOoq1s5z6M6MdWVFIqmXL1ROlVyfesG5Dk3AbssbBt0qiF5ZXEF7N33Bqft/LW2U3mdwLVfQLJwtRZ/Uu+yGJ0y7tCEIdCsuaYRkNtZmSIU+ZcwUMr5ks5F2QKBgQC8R6mmkqfDhmxIod4VvOwsbO53c0wn+5RcoeRfHa/sf/9KLs8GkVbtaaTyN2KTLfbG0voyS+eFiHn0+DXw/MvG5qq48Im6wrOrLKFQrGKV9Tg9IwiARL16lPqYZlatMnE1UJeM6nVpaJPWloUb31UDu/z7CJ/dvmsS6Cia6Sc/KwKBgQC3LK/qmmPsV/G0uORljeok8uoESeltz/a3avfC2YBGk2MdugBF/HBtBFTV0XcgKCLfj9Gs5j8r+UG/vdtA1ZXFTx35VaHYvwf8IOknU+VgQ6vGYfvJqqA0HBkm2vU6VPKQS9kY5Lz4OQTpCA76Jz5C0vSH0AXIu+If3gfSA8gLkQKBgGcnKKp2lgIWh76ed4fpHD1dLH9naSF9GvxBEVAxfhfndMSx/hpkmbkO+78FPSDGqPLL5pc72davdrJfRg8aGi5+e2qb67y0Kd0+vlnUY/xv970/LEKDZmNhQreLTDo/wPpOSW75B6GjPhfNdc5znDUUibn6RMqyYcVOm8bLpqkZ" - } - }, - "pointset": { - "points": { - "return_air_temperature_sensor": { - "fix_value": 21.1 - } - } - } -} diff --git a/schemas/udmi/config.tests/rotate.out b/schemas/udmi/config.tests/rotate.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/config.tests/smartprimus.json b/schemas/udmi/config.tests/smartprimus.json deleted file mode 100644 index 971290d1d5..0000000000 --- a/schemas/udmi/config.tests/smartprimus.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "version": 1, - "timestamp": "2019-01-17T14:02:29.364Z", - "system": { - }, - "pointset": { - "sample_rate_sec": 2, - "points": { - "space_temperature_sensor": { - }, - "fan_run_status": { - "fix_value": true - }, - "fan_run_enable": { - "fix_value": false - }, - "chilled_water_valve_percentage_command": { - } - } - } -} diff --git a/schemas/udmi/config.tests/smartprimus.out b/schemas/udmi/config.tests/smartprimus.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/config_gateway.json b/schemas/udmi/config_gateway.json deleted file mode 100644 index be0ba44063..0000000000 --- a/schemas/udmi/config_gateway.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "title": "Gateway Config Snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "required": [ - "proxy_ids" - ], - "properties": { - "proxy_ids": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[A-Z]{3}-[1-9][0-9]{0,2}$" - } - } - } -} diff --git a/schemas/udmi/config_localnet.json b/schemas/udmi/config_localnet.json deleted file mode 100644 index 4177f240d6..0000000000 --- a/schemas/udmi/config_localnet.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "title": "Proxy Device Config Snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "subsystem": { - "type": "object", - "patternProperties": { - "^[a-z0-9-]+$": { - "additionalProperties": false, - "properties": { - "local_id": { - "type": "string" - } - }, - "required": [ - "local_id" - ] - } - } - } - }, - "required": [ - "subsystem" - ] -} diff --git a/schemas/udmi/config_pointset.json b/schemas/udmi/config_pointset.json deleted file mode 100644 index a7ec32f936..0000000000 --- a/schemas/udmi/config_pointset.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "title": "pointset config snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "sample_limit_sec": { - "type": "number", - "minimum": 1, - "maximum": 86400 - }, - "sample_rate_sec": { - "type": "number", - "minimum": 1, - "maximum": 86400 - }, - "points": { - "additionalProperties": false, - "patternProperties": { - "^[a-z][a-z0-9]*(_[a-z0-9]+)*$": { - "additionalProperties": false, - "properties": { - "ref": { - "type": "string" - }, - "fix_value": { - "type": ["number", "string", "boolean"] - } - } - } - } - } - } -} diff --git a/schemas/udmi/config_system.json b/schemas/udmi/config_system.json deleted file mode 100644 index 10a3da3ba2..0000000000 --- a/schemas/udmi/config_system.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "title": "System Config snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "min_loglevel": { - "type": "number", - "minimum": 100, - "maximum": 800 - }, - "auth_key": { - "type": "object", - "additionalProperties": false, - "properties": { - "private": { - "type": "string" - } - }, - "required": [ - "private" - ] - } - } -} diff --git a/schemas/udmi/discover.json b/schemas/udmi/discover.json deleted file mode 100644 index 8abd70e24c..0000000000 --- a/schemas/udmi/discover.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "title": "Device discover schema", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" - }, - "version": { - "enum": [ - 1 - ] - }, - "protocol": { - "type": "string" - }, - "local_id": { - "type": "string" - }, - "points": { - "additionalProperties": false, - "patternProperties": { - "^[a-z][a-z0-9]*(_[a-z0-9]+)*$": { - "$ref": "#/definitions/point_property_names" - } - } - } - }, - "required": [ - "timestamp", - "version", - "protocol", - "local_id", - "points" - ], - "definitions": { - "point_property_names": { - "propertyNames": { - "oneOf": [ - { - "enum": [ - "units", - "present_value" - ] - } - ] - } - } - } -} diff --git a/schemas/udmi/discover.tests/empty.json b/schemas/udmi/discover.tests/empty.json deleted file mode 100644 index 2c63c08510..0000000000 --- a/schemas/udmi/discover.tests/empty.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/schemas/udmi/discover.tests/empty.out b/schemas/udmi/discover.tests/empty.out deleted file mode 100644 index f9fdc0c692..0000000000 --- a/schemas/udmi/discover.tests/empty.out +++ /dev/null @@ -1,9 +0,0 @@ -Validating 1 schemas - Validating 1 files against discover.json - Against input discover.tests/empty.json - #: 5 schema violations found - #: required key [local_id] not found - #: required key [points] not found - #: required key [protocol] not found - #: required key [timestamp] not found - #: required key [version] not found diff --git a/schemas/udmi/discover.tests/errors.json b/schemas/udmi/discover.tests/errors.json deleted file mode 100644 index aa3540a596..0000000000 --- a/schemas/udmi/discover.tests/errors.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "id": "sneakyCASE", - "properties": { - "$comment": "Common error cases for target telemetry." - }, - "points": { - "bad_entity_name_": { - "present_value": 21.30108642578125 - }, - "yoyo_motion_sensor": { - "bad_property_name": true - }, - "bad___sensor": { - "present_value": 21.30108642578125 - }, - "missing_present_value": { - }, - "old_properties": { - "properties": { - "present_value": true - } - }, - "magic_voice_recognizer": { - "present_value": { - "present_value": true - } - } - } -} diff --git a/schemas/udmi/discover.tests/errors.out b/schemas/udmi/discover.tests/errors.out deleted file mode 100644 index 2a972276f9..0000000000 --- a/schemas/udmi/discover.tests/errors.out +++ /dev/null @@ -1,15 +0,0 @@ -Validating 1 schemas - Validating 1 files against discover.json - Against input discover.tests/errors.json - #: 8 schema violations found - #/points: 4 schema violations found - #/points/old_properties/properties: #: 0 subschemas matched instead of one - #/points/old_properties/properties: properties is not a valid enum value - #/points/yoyo_motion_sensor/bad_property_name: #: 0 subschemas matched instead of one - #/points/yoyo_motion_sensor/bad_property_name: bad_property_name is not a valid enum value - #/points: extraneous key [bad___sensor] is not permitted - #/points: extraneous key [bad_entity_name_] is not permitted - #: extraneous key [id] is not permitted - #: extraneous key [properties] is not permitted - #: required key [local_id] not found - #: required key [protocol] not found diff --git a/schemas/udmi/discover.tests/example.json b/schemas/udmi/discover.tests/example.json deleted file mode 100644 index 9852ad3818..0000000000 --- a/schemas/udmi/discover.tests/example.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "local_id": "92EA09", - "protocol": "bacnet", - "points": { - "reading_value": { - "units": "C", - "present_value": 21.30108642578125 - }, - "yoyo_motion_sensor": { - "present_value": true - }, - "enum_value": { - "present_value": "hello" - } - } -} diff --git a/schemas/udmi/discover.tests/example.out b/schemas/udmi/discover.tests/example.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/docs/gateway.md b/schemas/udmi/docs/gateway.md deleted file mode 100644 index 33f31a0152..0000000000 --- a/schemas/udmi/docs/gateway.md +++ /dev/null @@ -1,120 +0,0 @@ -# Device Gateway - -The _gateway_ functionality is used for systems that have legacy, heritage, -or traditional devices that do not communicate directly to the cloud using -the [UDMI specification](../README.md). For example, an older BacNET based -system could use a gateway to translate on-prem communications into UDMI. - -The -[Google Clout IoT Core Gateway Documentation](https://cloud.google.com/iot/docs/how-tos/gateways) -for an overview of the cloud-side implementation of a gateway. UDMI, then, -specifies an additional layer of specification around the associated -message formats. - -Conceptually, there are two types of -entities involved: the _gateway device_, and the _proxied device_. Both of -these are 'devices' in the sense that they have an entry in a cloud registry -and have device-level UDMI data, but they have fundamentally different roles. - -The process of _discovery_, which is where something discovers other devices -on the local network, is conceptually related but functionally distinct and -separate than a gateway. - -## Gateway Operation - -There are two modes for gateway operation: _static_ and _dynamic_. In the -_dynamic_ mode, the gateway functionality if configured dynamically through -gateway _config_ messages, which tell it the local devices it should proxy -for. In a _static_ gateway configuraiton, the gateway will be statically -configured to proxy a set of devices, essentally ignoring any information -in the associated _config_ block. - -The general sequence of events for gateway operation is: -1. Optional metadata specifies configuration paramaters that should be used -at install time to properly (manually) setup the device. -2. (_dynamic_ only) On startup, the gateway connects to the cloud and receives a configuration -block that details which _proxy devices_ the gateway should proxy for. -4. Gateway 'attaches' (Cloud IoT terminology) to the proxied devices, -receiving a configuration block for each proxied device. Any attch errors are -indicated in the gateway _status_ block and sent along as a _logentry_ event. -5. (_dynamic_ only) The proxied device's _config_ block specifies any local connection -parameters for the proxied device, e.g. the BacNET device id. -6. The gateway proxies communication to/from the device, translating between -native (e.g. BacNET) communications and UDMI-based messages. - -### config - -The [gateway config block](../config.tests/gateway.json) -simply specifies the list of target proxy devices. -On a config update, the gateway is responsible for handling any change in -this list (added or removed devices). The details of proxied devices are -kept to a minimum here (IDs only) to avoid overflowing the allowed block -size in cases where there are a large number of devices. - -### state - -Any attach errors, e.g. the gateway can not successfully attach to the target -device, should be reported in the [gateway state](../state.tests/gateway.json) -and a _logentry_ message used to detail the -nature of the problem. If the gateway can attach successfully, any other -errors, e.g. the inability to communicate with the device over the local -network, should be indicated as part of the proxy device status block. - -### telemetry - -Telemety from the gateway would primarily consist of standard -[_logentry_](../logentry.tests/logentry.json) messages, which -provide a running comentary about gateway operation. Specificaly, if there -is an error attaching, then there should be appropriate logging to help -diagnose the problem. - -### metadata - -The gateway [metadata block](../metadata.tests/gateway.json) specifies -any information necessary either for the -initial (manual) configuration of the device or ongoing validation of -operation. E.g., if a gateway device has a unique MAC address used for -local communications, it would be indicated here. - -## Proxy Device Operation - -Proxy devices are those that have a logical cloud device entry (in a registry), -and are associated (bound) to a particular gateway. On-prem, the device -itself talks a local protocol (e.g. BacNET), but does not have a direct -cloud connection. - -### config - -[Proxy device config blocks](../config.tests/proxy.json) contain a special -_localnet_ section that -specifies information required by the gateway to contact the local device. -E.g., the fact that a device is 'BacNET' and also the device's BacNET object -ID. Based on this, the gateway can communicate with the target device and proxy -all other messages. - -Additionally, the gateway is responsible for proxying all other supported -operations of the config bundle. E.g., if a _pointset_ 'force_value" parameter -is specified, the gateway would need to convert that into the local protocol -and trigger the required functionality. - -### state - -There is no gateway-specific _state_ information, but similarly to _config_ the -gateway is responsible for proxying all relevant state from the local device -into the proxied device's state block. E.g., if the device is in an alarm -state, then the gateway would have to transform that from the local format -into the appropriate UDMI message. - -### telemetry - -Telemetry is handled similarly, with the gateway responsible for proxying data -from local devices through to UDMI. In many cases, this would be translating -specific device points into a [_pointset_ message](../pointset.tests/example.json). - -### metadata - -A [proxy device metadata section](../metadata.tests/proxy.json) describes -_localnet_ with the presence of the -device on a local network. This can/should be used for initial programming -and configuration of the device, or to validate proper device configuration. -The gateway implementation itself would not directly deal with this block. diff --git a/schemas/udmi/envelope.json b/schemas/udmi/envelope.json deleted file mode 100644 index 9458e08ba5..0000000000 --- a/schemas/udmi/envelope.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "title": "Message envelope schema", - "additionalProperties": true, - "properties": { - "deviceId": { - "type": "string", - "pattern": "^[A-Z]{2,6}-[0-9]{1,6}$" - }, - "deviceNumId": { - "type": "string", - "pattern": "^[0-9]+$" - }, - "deviceRegistryId": { - "type": "string", - "pattern": "^[a-zA-Z][-a-zA-Z0-9._+~%]*[a-zA-Z0-9]$" - }, - "projectId": { - "type": "string", - "pattern": "^([.a-z]+:)?[a-z][-a-z0-9]*[a-z0-9]$" - }, - "subFolder": { - "enum": [ - "config", - "discover", - "system", - "metadata", - "pointset", - "state" - ] - } - }, - "required": [ - "projectId", - "deviceRegistryId", - "deviceNumId", - "deviceId", - "subFolder" - ] -} diff --git a/schemas/udmi/envelope.tests/empty.json b/schemas/udmi/envelope.tests/empty.json deleted file mode 100644 index 2c63c08510..0000000000 --- a/schemas/udmi/envelope.tests/empty.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/schemas/udmi/envelope.tests/empty.out b/schemas/udmi/envelope.tests/empty.out deleted file mode 100644 index d4d84fce5c..0000000000 --- a/schemas/udmi/envelope.tests/empty.out +++ /dev/null @@ -1,9 +0,0 @@ -Validating 1 schemas - Validating 1 files against envelope.json - Against input envelope.tests/empty.json - #: 5 schema violations found - #: required key [deviceId] not found - #: required key [deviceNumId] not found - #: required key [deviceRegistryId] not found - #: required key [projectId] not found - #: required key [subFolder] not found diff --git a/schemas/udmi/envelope.tests/errors1.json b/schemas/udmi/envelope.tests/errors1.json deleted file mode 100644 index ff059c78e0..0000000000 --- a/schemas/udmi/envelope.tests/errors1.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "deviceRegistryId": "test/registry", - "deviceNumId": "921302198324X", - "deviceId": "fcu-1" -} diff --git a/schemas/udmi/envelope.tests/errors1.out b/schemas/udmi/envelope.tests/errors1.out deleted file mode 100644 index 601887a26a..0000000000 --- a/schemas/udmi/envelope.tests/errors1.out +++ /dev/null @@ -1,9 +0,0 @@ -Validating 1 schemas - Validating 1 files against envelope.json - Against input envelope.tests/errors1.json - #: 5 schema violations found - #/deviceId: string [fcu-1] does not match pattern ^[A-Z]{2,6}-[0-9]{1,6}$ - #/deviceNumId: string [921302198324X] does not match pattern ^[0-9]+$ - #/deviceRegistryId: string [test/registry] does not match pattern ^[a-zA-Z][-a-zA-Z0-9._+~%]*[a-zA-Z0-9]$ - #: required key [projectId] not found - #: required key [subFolder] not found diff --git a/schemas/udmi/envelope.tests/errors2.json b/schemas/udmi/envelope.tests/errors2.json deleted file mode 100644 index 9cbb163ade..0000000000 --- a/schemas/udmi/envelope.tests/errors2.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "deviceRegistryId": "test-registry", - "deviceNumId": "-9213923812", - "deviceId": "FCUs_02_NW_12" -} diff --git a/schemas/udmi/envelope.tests/errors2.out b/schemas/udmi/envelope.tests/errors2.out deleted file mode 100644 index 0c02908e03..0000000000 --- a/schemas/udmi/envelope.tests/errors2.out +++ /dev/null @@ -1,8 +0,0 @@ -Validating 1 schemas - Validating 1 files against envelope.json - Against input envelope.tests/errors2.json - #: 4 schema violations found - #/deviceId: string [FCUs_02_NW_12] does not match pattern ^[A-Z]{2,6}-[0-9]{1,6}$ - #/deviceNumId: string [-9213923812] does not match pattern ^[0-9]+$ - #: required key [projectId] not found - #: required key [subFolder] not found diff --git a/schemas/udmi/envelope.tests/example.json b/schemas/udmi/envelope.tests/example.json deleted file mode 100644 index b48f45a49a..0000000000 --- a/schemas/udmi/envelope.tests/example.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "projectId": "daq-test-suite", - "deviceRegistryId": "test_registry", - "deviceNumId": "921302198324", - "deviceId": "FCU-2", - "subFolder": "pointset" -} diff --git a/schemas/udmi/envelope.tests/example.out b/schemas/udmi/envelope.tests/example.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/envelope.tests/example2.json b/schemas/udmi/envelope.tests/example2.json deleted file mode 100644 index 572406ce32..0000000000 --- a/schemas/udmi/envelope.tests/example2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "projectId": "daq-test-suite", - "deviceRegistryId": "test-registry", - "deviceNumId": "23812", - "deviceId": "FCU-002", - "subFolder": "system", -} diff --git a/schemas/udmi/envelope.tests/example2.out b/schemas/udmi/envelope.tests/example2.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/envelope.tests/lgtw.json b/schemas/udmi/envelope.tests/lgtw.json deleted file mode 100644 index 8e7b88cbd9..0000000000 --- a/schemas/udmi/envelope.tests/lgtw.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "projectId": "daq-test-suite", - "deviceRegistryId": "test_registry", - "deviceNumId": "921302198324", - "deviceId": "LGTW-2", - "subFolder": "discover" -} diff --git a/schemas/udmi/envelope.tests/lgtw.out b/schemas/udmi/envelope.tests/lgtw.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/metadata.json b/schemas/udmi/metadata.json deleted file mode 100644 index e01dbe16cc..0000000000 --- a/schemas/udmi/metadata.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "title": "Device metadata schema", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "required": [ - "timestamp", - "version", - "system" - ], - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" - }, - "version": { - "enum": [ - 1 - ] - }, - "hash": { - "type": "string", - "pattern": "^[0-9a-z]{8}$" - }, - "cloud": { - "$ref": "file:metadata_cloud.json#" - }, - "system": { - "$ref": "file:metadata_system.json#" - }, - "gateway": { - "$ref": "file:metadata_gateway.json#" - }, - "localnet": { - "$ref": "file:metadata_localnet.json#" - }, - "pointset": { - "$ref": "file:metadata_pointset.json#" - } - } -} diff --git a/schemas/udmi/metadata.tests/empty.json b/schemas/udmi/metadata.tests/empty.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/schemas/udmi/metadata.tests/empty.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/schemas/udmi/metadata.tests/empty.out b/schemas/udmi/metadata.tests/empty.out deleted file mode 100644 index 159f05c268..0000000000 --- a/schemas/udmi/metadata.tests/empty.out +++ /dev/null @@ -1,7 +0,0 @@ -Validating 1 schemas - Validating 1 files against metadata.json - Against input metadata.tests/empty.json - #: 3 schema violations found - #: required key [system] not found - #: required key [timestamp] not found - #: required key [version] not found diff --git a/schemas/udmi/metadata.tests/errors.json b/schemas/udmi/metadata.tests/errors.json deleted file mode 100644 index 395b19e45f..0000000000 --- a/schemas/udmi/metadata.tests/errors.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "guid": "bim://04aEp5ymD_$u5IxhJN2aGi", - "location": { - "site": "New Zealand" - }, - "physical_tag": { - "asset": { - "site": "US-SFO-XYY_Noope!", - "name": "AHU-A01_extension11-option" - } - } - }, - "pointset": { - "rabbits": true, - "points": { - "return_air_temperature_sensor": { - "units": "Celsius", - "monkeys": "elephants" - } - } - } -} diff --git a/schemas/udmi/metadata.tests/errors.out b/schemas/udmi/metadata.tests/errors.out deleted file mode 100644 index c315c2fd40..0000000000 --- a/schemas/udmi/metadata.tests/errors.out +++ /dev/null @@ -1,16 +0,0 @@ -Validating 1 schemas - Validating 1 files against metadata.json - Against input metadata.tests/errors.json - #: 8 schema violations found - #/pointset: 3 schema violations found - #/pointset/points/return_air_temperature_sensor: 2 schema violations found - #/pointset/points/return_air_temperature_sensor/units: Celsius is not a valid enum value - #/pointset/points/return_air_temperature_sensor: extraneous key [monkeys] is not permitted - #/pointset: extraneous key [rabbits] is not permitted - #/system: 5 schema violations found - #/system/location/site: string [New Zealand] does not match pattern ^[A-Z]{2}-[A-Z]{3}-[A-Z0-9]{2,9}$ - #/system/physical_tag/asset: 3 schema violations found - #/system/physical_tag/asset/name: string [AHU-A01_extension11-option] does not match pattern ^[A-Z]{2,6}-[0-9]{1,6}$ - #/system/physical_tag/asset/site: string [US-SFO-XYY_Noope!] does not match pattern ^[A-Z]{2}-[A-Z]{3}-[A-Z0-9]{2,9}$ - #/system/physical_tag/asset: required key [guid] not found - #/system: extraneous key [guid] is not permitted diff --git a/schemas/udmi/metadata.tests/example.json b/schemas/udmi/metadata.tests/example.json deleted file mode 100644 index 4f1df64175..0000000000 --- a/schemas/udmi/metadata.tests/example.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "location": { - "site": "US-SFO-XYY", - "section": "NW-2F", - "position": { - "x": 10, - "y": 20 - } - }, - "physical_tag": { - "asset": { - "guid": "bim://04aEp5ymD_$u5IxhJN2aGi", - "site": "US-SFO-XYY", - "name": "AHU-1" - } - }, - "aux": { - "suffix": "extention11-optional", - } - }, - "pointset": { - "points": { - "return_air_temperature_sensor": { - "units": "Degrees-Celsius" - } - } - } -} diff --git a/schemas/udmi/metadata.tests/example.out b/schemas/udmi/metadata.tests/example.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/metadata.tests/example2.out b/schemas/udmi/metadata.tests/example2.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/metadata.tests/gateway.json b/schemas/udmi/metadata.tests/gateway.json deleted file mode 100644 index 2da945023e..0000000000 --- a/schemas/udmi/metadata.tests/gateway.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "location": { - "site": "US-SFO-XYY", - "section": "NW-2F", - "position": { - "x": 10, - "y": 20 - } - }, - "physical_tag": { - "asset": { - "guid": "bim://04aEp5ymD_$u5IxhJN2aGi", - "site": "US-SFO-XYY", - "name": "AHU-01" - } - } - }, - "cloud": { - "auth_type": "RS256", - }, - "gateway": { - "proxy_ids": ["AHU-22"] - }, - "pointset": { - "points": { - "return_air_temperature_sensor": { - "units": "Degrees-Celsius" - } - } - }, - "localnet": { - "subsystem": { - "bacnet": { - "local_id": "0x991132ec" - } - } - } -} diff --git a/schemas/udmi/metadata.tests/gateway.out b/schemas/udmi/metadata.tests/gateway.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/metadata.tests/proxy.json b/schemas/udmi/metadata.tests/proxy.json deleted file mode 100644 index bbc522af3c..0000000000 --- a/schemas/udmi/metadata.tests/proxy.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "location": { - "site": "US-SFO-XYY", - "section": "NW-2F", - "position": { - "x": 10, - "y": 20 - } - }, - "physical_tag": { - "asset": { - "guid": "bim://04aEp5ymD_$u5IxhJN2aGi", - "site": "US-SFO-XYY", - "name": "AHU-1", - } - }, - "aux": { - "suffix": "extention11-optional" - } - }, - "localnet": { - "subsystem": { - "bacnet": { - "local_id": "0x82eecd" - } - } - }, - "pointset": { - "points": { - "return_air_temperature_sensor": { - "units": "Degrees-Celsius", - "ref": "BV23.present_value" - } - } - }, - "gateway": { - "subsystem": "bacnet", - "gateway_id": "GAT-123" - } -} diff --git a/schemas/udmi/metadata.tests/proxy.out b/schemas/udmi/metadata.tests/proxy.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/metadata.tests/toomany.json b/schemas/udmi/metadata.tests/toomany.json deleted file mode 100644 index 6c5b9671e0..0000000000 --- a/schemas/udmi/metadata.tests/toomany.json +++ /dev/null @@ -1,2035 +0,0 @@ -{ - "system": { - "location": { - "site": "UK-LON-S2" - }, - "physical_tag": { - "asset": { - "name": "UK-LON-S2_LTGW-3", - "guid": "ifc://27UivR75r3481CVsBDvlfl" - } - } - }, - "pointset": { - "points": { - "bw4_group_brightness12": { - "units": "Percent" - }, - "bw4_group_brightness13": { - "units": "Percent" - }, - "bw4_group_brightness10": { - "units": "Percent" - }, - "bw4_group_brightness11": { - "units": "Percent" - }, - "bw4_group_brightness16": { - "units": "Percent" - }, - "bw4_group_brightness14": { - "units": "Percent" - }, - "bw4_group_brightness15": { - "units": "Percent" - }, - "bw4_light_level1": { - "units": "Luxes" - }, - "bw4_light_level2": { - "units": "Luxes" - }, - "bw4_light_level7": { - "units": "Luxes" - }, - "bw4_light_level8": { - "units": "Luxes" - }, - "bw4_light_level9": { - "units": "Luxes" - }, - "bw4_light_level3": { - "units": "Luxes" - }, - "bw4_light_level4": { - "units": "Luxes" - }, - "bw4_light_level5": { - "units": "Luxes" - }, - "bw4_light_level6": { - "units": "Luxes" - }, - "bw5_lamp_brightness61": { - "units": "Percent" - }, - "bw5_lamp_brightness62": { - "units": "Percent" - }, - "bw5_lamp_brightness63": { - "units": "Percent" - }, - "bw5_lamp_brightness64": { - "units": "Percent" - }, - "bw5_lamp_brightness60": { - "units": "Percent" - }, - "bw6_lamp_brightness63": { - "units": "Percent" - }, - "bw6_lamp_brightness62": { - "units": "Percent" - }, - "bw6_lamp_brightness61": { - "units": "Percent" - }, - "bw6_lamp_brightness60": { - "units": "Percent" - }, - "bw6_lamp_brightness64": { - "units": "Percent" - }, - "bw4_lamp_brightness60": { - "units": "Percent" - }, - "bw4_occupancy5": { - "units": "No-units" - }, - "bw5_lamp_brightness58": { - "units": "Percent" - }, - "bw4_lamp_brightness61": { - "units": "Percent" - }, - "bw4_occupancy6": { - "units": "No-units" - }, - "bw5_lamp_brightness59": { - "units": "Percent" - }, - "bw4_occupancy7": { - "units": "No-units" - }, - "bw4_occupancy8": { - "units": "No-units" - }, - "bw4_lamp_brightness64": { - "units": "Percent" - }, - "bw4_occupancy9": { - "units": "No-units" - }, - "bw5_lamp_brightness54": { - "units": "Percent" - }, - "bw5_lamp_brightness55": { - "units": "Percent" - }, - "bw4_lamp_brightness62": { - "units": "Percent" - }, - "bw5_lamp_brightness56": { - "units": "Percent" - }, - "bw4_lamp_brightness63": { - "units": "Percent" - }, - "bw5_lamp_brightness57": { - "units": "Percent" - }, - "bw5_lamp_brightness50": { - "units": "Percent" - }, - "bw5_lamp_brightness51": { - "units": "Percent" - }, - "bw5_lamp_brightness52": { - "units": "Percent" - }, - "bw5_lamp_brightness53": { - "units": "Percent" - }, - "bw4_occupancy1": { - "units": "No-units" - }, - "bw4_occupancy2": { - "units": "No-units" - }, - "bw4_occupancy3": { - "units": "No-units" - }, - "bw4_occupancy4": { - "units": "No-units" - }, - "bw1_group_brightness16": { - "units": "Percent" - }, - "bw1_group_brightness15": { - "units": "Percent" - }, - "bw1_group_brightness12": { - "units": "Percent" - }, - "bw1_group_brightness11": { - "units": "Percent" - }, - "bw1_group_brightness14": { - "units": "Percent" - }, - "bw1_group_brightness13": { - "units": "Percent" - }, - "bw1_group_brightness10": { - "units": "Percent" - }, - "bw5_lamp_brightness47": { - "units": "Percent" - }, - "bw5_lamp_brightness48": { - "units": "Percent" - }, - "bw5_lamp_brightness9": { - "units": "Percent" - }, - "bw5_lamp_brightness49": { - "units": "Percent" - }, - "bw5_lamp_brightness43": { - "units": "Percent" - }, - "bw6_occupancy7": { - "units": "No-units" - }, - "bw5_lamp_brightness44": { - "units": "Percent" - }, - "bw6_occupancy8": { - "units": "No-units" - }, - "bw5_lamp_brightness45": { - "units": "Percent" - }, - "bw6_occupancy9": { - "units": "No-units" - }, - "bw5_lamp_brightness46": { - "units": "Percent" - }, - "bw6_occupancy3": { - "units": "No-units" - }, - "bw2_lamp_brightness64": { - "units": "Percent" - }, - "bw5_lamp_brightness40": { - "units": "Percent" - }, - "bw6_occupancy4": { - "units": "No-units" - }, - "bw5_lamp_brightness41": { - "units": "Percent" - }, - "bw6_occupancy5": { - "units": "No-units" - }, - "bw5_lamp_brightness42": { - "units": "Percent" - }, - "bw6_occupancy6": { - "units": "No-units" - }, - "bw2_lamp_brightness61": { - "units": "Percent" - }, - "bw2_lamp_brightness60": { - "units": "Percent" - }, - "bw2_lamp_brightness63": { - "units": "Percent" - }, - "bw6_occupancy1": { - "units": "No-units" - }, - "bw2_lamp_brightness62": { - "units": "Percent" - }, - "bw6_occupancy2": { - "units": "No-units" - }, - "bw3_lamp_brightness6": { - "units": "Percent" - }, - "bw5_lamp_brightness36": { - "units": "Percent" - }, - "bw3_lamp_brightness5": { - "units": "Percent" - }, - "bw5_lamp_brightness37": { - "units": "Percent" - }, - "bw3_lamp_brightness4": { - "units": "Percent" - }, - "bw5_lamp_brightness38": { - "units": "Percent" - }, - "bw3_lamp_brightness3": { - "units": "Percent" - }, - "bw5_lamp_brightness39": { - "units": "Percent" - }, - "bw2_lamp_brightness58": { - "units": "Percent" - }, - "bw3_lamp_brightness2": { - "units": "Percent" - }, - "bw5_lamp_brightness32": { - "units": "Percent" - }, - "bw2_lamp_brightness57": { - "units": "Percent" - }, - "bw3_lamp_brightness1": { - "units": "Percent" - }, - "bw5_lamp_brightness33": { - "units": "Percent" - }, - "bw5_lamp_brightness34": { - "units": "Percent" - }, - "bw6_lamp_brightness29": { - "units": "Percent" - }, - "bw2_lamp_brightness59": { - "units": "Percent" - }, - "bw5_lamp_brightness35": { - "units": "Percent" - }, - "bw6_lamp_brightness28": { - "units": "Percent" - }, - "bw2_lamp_brightness54": { - "units": "Percent" - }, - "bw2_lamp_brightness53": { - "units": "Percent" - }, - "bw2_lamp_brightness56": { - "units": "Percent" - }, - "bw5_lamp_brightness30": { - "units": "Percent" - }, - "bw2_lamp_brightness55": { - "units": "Percent" - }, - "bw5_lamp_brightness31": { - "units": "Percent" - }, - "bw2_lamp_brightness50": { - "units": "Percent" - }, - "bw2_lamp_brightness52": { - "units": "Percent" - }, - "bw2_lamp_brightness51": { - "units": "Percent" - }, - "bw2_light_level1": { - "units": "Luxes" - }, - "bw3_lamp_brightness55": { - "units": "Percent" - }, - "bw6_lamp_brightness30": { - "units": "Percent" - }, - "bw2_light_level2": { - "units": "Luxes" - }, - "bw3_lamp_brightness54": { - "units": "Percent" - }, - "bw2_light_level3": { - "units": "Luxes" - }, - "bw3_lamp_brightness53": { - "units": "Percent" - }, - "bw2_light_level4": { - "units": "Luxes" - }, - "bw3_lamp_brightness52": { - "units": "Percent" - }, - "bw2_light_level5": { - "units": "Luxes" - }, - "bw3_lamp_brightness51": { - "units": "Percent" - }, - "bw6_light_level1": { - "units": "Luxes" - }, - "bw2_light_level6": { - "units": "Luxes" - }, - "bw3_lamp_brightness50": { - "units": "Percent" - }, - "bw6_light_level2": { - "units": "Luxes" - }, - "bw2_light_level7": { - "units": "Luxes" - }, - "bw6_light_level3": { - "units": "Luxes" - }, - "bw2_light_level8": { - "units": "Luxes" - }, - "bw6_light_level4": { - "units": "Luxes" - }, - "bw6_lamp_brightness38": { - "units": "Percent" - }, - "bw6_light_level5": { - "units": "Luxes" - }, - "bw6_lamp_brightness37": { - "units": "Percent" - }, - "bw6_light_level6": { - "units": "Luxes" - }, - "bw6_lamp_brightness36": { - "units": "Percent" - }, - "bw6_light_level7": { - "units": "Luxes" - }, - "bw6_lamp_brightness35": { - "units": "Percent" - }, - "bw6_light_level8": { - "units": "Luxes" - }, - "bw3_lamp_brightness59": { - "units": "Percent" - }, - "bw5_lamp_brightness29": { - "units": "Percent" - }, - "bw6_lamp_brightness34": { - "units": "Percent" - }, - "bw6_light_level9": { - "units": "Luxes" - }, - "bw3_lamp_brightness58": { - "units": "Percent" - }, - "bw6_lamp_brightness33": { - "units": "Percent" - }, - "bw3_lamp_brightness57": { - "units": "Percent" - }, - "bw6_lamp_brightness32": { - "units": "Percent" - }, - "bw3_lamp_brightness56": { - "units": "Percent" - }, - "bw6_lamp_brightness31": { - "units": "Percent" - }, - "bw5_lamp_brightness25": { - "units": "Percent" - }, - "bw5_lamp_brightness26": { - "units": "Percent" - }, - "bw5_lamp_brightness27": { - "units": "Percent" - }, - "bw5_lamp_brightness28": { - "units": "Percent" - }, - "bw2_lamp_brightness47": { - "units": "Percent" - }, - "bw5_lamp_brightness21": { - "units": "Percent" - }, - "bw2_lamp_brightness46": { - "units": "Percent" - }, - "bw5_lamp_brightness22": { - "units": "Percent" - }, - "bw6_lamp_brightness19": { - "units": "Percent" - }, - "bw2_lamp_brightness49": { - "units": "Percent" - }, - "bw5_lamp_brightness23": { - "units": "Percent" - }, - "bw6_lamp_brightness18": { - "units": "Percent" - }, - "bw2_lamp_brightness48": { - "units": "Percent" - }, - "bw5_lamp_brightness24": { - "units": "Percent" - }, - "bw6_lamp_brightness17": { - "units": "Percent" - }, - "bw2_lamp_brightness43": { - "units": "Percent" - }, - "bw2_lamp_brightness42": { - "units": "Percent" - }, - "bw2_lamp_brightness45": { - "units": "Percent" - }, - "bw2_lamp_brightness44": { - "units": "Percent" - }, - "bw5_lamp_brightness20": { - "units": "Percent" - }, - "bw2_lamp_brightness41": { - "units": "Percent" - }, - "bw2_lamp_brightness40": { - "units": "Percent" - }, - "bw3_lamp_brightness44": { - "units": "Percent" - }, - "bw3_lamp_brightness43": { - "units": "Percent" - }, - "bw3_lamp_brightness42": { - "units": "Percent" - }, - "bw3_lamp_brightness41": { - "units": "Percent" - }, - "bw3_lamp_brightness40": { - "units": "Percent" - }, - "bw6_lamp_brightness27": { - "units": "Percent" - }, - "bw6_lamp_brightness26": { - "units": "Percent" - }, - "bw6_lamp_brightness25": { - "units": "Percent" - }, - "bw3_lamp_brightness49": { - "units": "Percent" - }, - "bw6_lamp_brightness24": { - "units": "Percent" - }, - "bw3_lamp_brightness48": { - "units": "Percent" - }, - "bw5_lamp_brightness18": { - "units": "Percent" - }, - "bw6_lamp_brightness23": { - "units": "Percent" - }, - "bw3_lamp_brightness47": { - "units": "Percent" - }, - "bw5_lamp_brightness19": { - "units": "Percent" - }, - "bw6_lamp_brightness22": { - "units": "Percent" - }, - "bw3_lamp_brightness46": { - "units": "Percent" - }, - "bw6_lamp_brightness21": { - "units": "Percent" - }, - "bw3_lamp_brightness45": { - "units": "Percent" - }, - "bw6_lamp_brightness20": { - "units": "Percent" - }, - "bw5_lamp_brightness14": { - "units": "Percent" - }, - "bw2_lamp_brightness39": { - "units": "Percent" - }, - "bw5_lamp_brightness15": { - "units": "Percent" - }, - "bw5_lamp_brightness16": { - "units": "Percent" - }, - "bw5_lamp_brightness17": { - "units": "Percent" - }, - "bw2_lamp_brightness36": { - "units": "Percent" - }, - "bw5_lamp_brightness10": { - "units": "Percent" - }, - "bw2_lamp_brightness35": { - "units": "Percent" - }, - "bw5_lamp_brightness11": { - "units": "Percent" - }, - "bw2_lamp_brightness38": { - "units": "Percent" - }, - "bw5_lamp_brightness12": { - "units": "Percent" - }, - "bw2_lamp_brightness37": { - "units": "Percent" - }, - "bw5_lamp_brightness13": { - "units": "Percent" - }, - "bw2_lamp_brightness32": { - "units": "Percent" - }, - "bw2_lamp_brightness31": { - "units": "Percent" - }, - "bw2_lamp_brightness34": { - "units": "Percent" - }, - "bw2_lamp_brightness33": { - "units": "Percent" - }, - "bw2_lamp_brightness30": { - "units": "Percent" - }, - "bw6_lamp_brightness52": { - "units": "Percent" - }, - "bw3_light_level1": { - "units": "Luxes" - }, - "bw6_lamp_brightness51": { - "units": "Percent" - }, - "bw6_lamp_brightness50": { - "units": "Percent" - }, - "bw1_occupancy1": { - "units": "No-units" - }, - "bw1_occupancy5": { - "units": "No-units" - }, - "bw3_light_level8": { - "units": "Luxes" - }, - "bw1_occupancy4": { - "units": "No-units" - }, - "bw3_light_level9": { - "units": "Luxes" - }, - "bw6_lamp_brightness59": { - "units": "Percent" - }, - "bw1_occupancy3": { - "units": "No-units" - }, - "bw3_light_level6": { - "units": "Luxes" - }, - "bw6_lamp_brightness58": { - "units": "Percent" - }, - "bw1_occupancy2": { - "units": "No-units" - }, - "bw3_light_level7": { - "units": "Luxes" - }, - "bw6_lamp_brightness57": { - "units": "Percent" - }, - "bw1_occupancy9": { - "units": "No-units" - }, - "bw3_light_level4": { - "units": "Luxes" - }, - "bw6_lamp_brightness56": { - "units": "Percent" - }, - "bw1_occupancy8": { - "units": "No-units" - }, - "bw3_light_level5": { - "units": "Luxes" - }, - "bw6_lamp_brightness55": { - "units": "Percent" - }, - "bw1_occupancy7": { - "units": "No-units" - }, - "bw3_light_level2": { - "units": "Luxes" - }, - "bw6_lamp_brightness54": { - "units": "Percent" - }, - "bw1_occupancy6": { - "units": "No-units" - }, - "bw3_light_level3": { - "units": "Luxes" - }, - "bw6_lamp_brightness53": { - "units": "Percent" - }, - "bw2_lamp_brightness29": { - "units": "Percent" - }, - "bw2_lamp_brightness28": { - "units": "Percent" - }, - "bw2_lamp_brightness25": { - "units": "Percent" - }, - "bw2_lamp_brightness24": { - "units": "Percent" - }, - "bw2_lamp_brightness27": { - "units": "Percent" - }, - "bw2_lamp_brightness26": { - "units": "Percent" - }, - "bw6_lamp_brightness39": { - "units": "Percent" - }, - "bw2_lamp_brightness21": { - "units": "Percent" - }, - "bw2_lamp_brightness20": { - "units": "Percent" - }, - "bw2_lamp_brightness23": { - "units": "Percent" - }, - "bw2_lamp_brightness22": { - "units": "Percent" - }, - "bw6_lamp_brightness41": { - "units": "Percent" - }, - "bw6_lamp_brightness40": { - "units": "Percent" - }, - "bw3_lamp_brightness64": { - "units": "Percent" - }, - "bw3_lamp_brightness63": { - "units": "Percent" - }, - "bw3_lamp_brightness62": { - "units": "Percent" - }, - "bw3_lamp_brightness61": { - "units": "Percent" - }, - "bw3_lamp_brightness60": { - "units": "Percent" - }, - "bw6_lamp_brightness49": { - "units": "Percent" - }, - "bw6_lamp_brightness48": { - "units": "Percent" - }, - "bw6_lamp_brightness47": { - "units": "Percent" - }, - "bw6_lamp_brightness46": { - "units": "Percent" - }, - "bw6_lamp_brightness45": { - "units": "Percent" - }, - "bw3_lamp_brightness9": { - "units": "Percent" - }, - "bw6_lamp_brightness44": { - "units": "Percent" - }, - "bw3_lamp_brightness8": { - "units": "Percent" - }, - "bw6_lamp_brightness43": { - "units": "Percent" - }, - "bw3_lamp_brightness7": { - "units": "Percent" - }, - "bw6_lamp_brightness42": { - "units": "Percent" - }, - "bw1_lamp_brightness20": { - "units": "Percent" - }, - "bw1_lamp_brightness24": { - "units": "Percent" - }, - "bw1_group_brightness1": { - "units": "Percent" - }, - "bw1_lamp_brightness23": { - "units": "Percent" - }, - "bw1_group_brightness2": { - "units": "Percent" - }, - "bw1_lamp_brightness22": { - "units": "Percent" - }, - "bw1_group_brightness3": { - "units": "Percent" - }, - "bw1_lamp_brightness21": { - "units": "Percent" - }, - "bw1_lamp_brightness28": { - "units": "Percent" - }, - "bw1_lamp_brightness27": { - "units": "Percent" - }, - "bw1_lamp_brightness26": { - "units": "Percent" - }, - "bw1_lamp_brightness25": { - "units": "Percent" - }, - "bw1_lamp_brightness29": { - "units": "Percent" - }, - "bw1_lamp_brightness31": { - "units": "Percent" - }, - "bw1_light_level13": { - "units": "Luxes" - }, - "bw1_lamp_brightness30": { - "units": "Percent" - }, - "bw1_light_level14": { - "units": "Luxes" - }, - "bw1_light_level11": { - "units": "Luxes" - }, - "bw1_light_level12": { - "units": "Luxes" - }, - "bw1_lamp_brightness35": { - "units": "Percent" - }, - "bw1_lamp_brightness34": { - "units": "Percent" - }, - "bw1_lamp_brightness33": { - "units": "Percent" - }, - "bw1_light_level15": { - "units": "Luxes" - }, - "bw1_lamp_brightness32": { - "units": "Percent" - }, - "bw1_light_level16": { - "units": "Luxes" - }, - "bw1_lamp_brightness39": { - "units": "Percent" - }, - "bw1_lamp_brightness38": { - "units": "Percent" - }, - "bw1_lamp_brightness37": { - "units": "Percent" - }, - "bw1_lamp_brightness36": { - "units": "Percent" - }, - "bw1_light_level10": { - "units": "Luxes" - }, - "bw3_group_brightness10": { - "units": "Percent" - }, - "bw5_group_brightness15": { - "units": "Percent" - }, - "bw5_group_brightness16": { - "units": "Percent" - }, - "bw3_group_brightness12": { - "units": "Percent" - }, - "bw3_group_brightness11": { - "units": "Percent" - }, - "bw3_group_brightness14": { - "units": "Percent" - }, - "bw5_group_brightness11": { - "units": "Percent" - }, - "bw3_group_brightness13": { - "units": "Percent" - }, - "bw5_group_brightness12": { - "units": "Percent" - }, - "bw3_group_brightness16": { - "units": "Percent" - }, - "bw5_group_brightness13": { - "units": "Percent" - }, - "bw3_group_brightness15": { - "units": "Percent" - }, - "bw5_group_brightness14": { - "units": "Percent" - }, - "bw6_lamp_brightness16": { - "units": "Percent" - }, - "bw6_lamp_brightness15": { - "units": "Percent" - }, - "bw6_lamp_brightness14": { - "units": "Percent" - }, - "bw5_group_brightness10": { - "units": "Percent" - }, - "bw6_lamp_brightness13": { - "units": "Percent" - }, - "bw6_lamp_brightness12": { - "units": "Percent" - }, - "bw6_lamp_brightness11": { - "units": "Percent" - }, - "bw6_lamp_brightness10": { - "units": "Percent" - }, - "bw3_occupancy10": { - "units": "No-units" - }, - "bw6_occupancy16": { - "units": "No-units" - }, - "bw2_occupancy10": { - "units": "No-units" - }, - "bw2_occupancy11": { - "units": "No-units" - }, - "bw1_lamp_brightness4": { - "units": "Percent" - }, - "bw1_lamp_brightness13": { - "units": "Percent" - }, - "bw2_occupancy12": { - "units": "No-units" - }, - "bw3_occupancy14": { - "units": "No-units" - }, - "bw6_occupancy12": { - "units": "No-units" - }, - "bw1_lamp_brightness3": { - "units": "Percent" - }, - "bw1_lamp_brightness12": { - "units": "Percent" - }, - "bw2_occupancy13": { - "units": "No-units" - }, - "bw3_occupancy13": { - "units": "No-units" - }, - "bw6_occupancy13": { - "units": "No-units" - }, - "bw1_lamp_brightness2": { - "units": "Percent" - }, - "bw1_lamp_brightness11": { - "units": "Percent" - }, - "bw2_occupancy14": { - "units": "No-units" - }, - "bw3_occupancy12": { - "units": "No-units" - }, - "bw6_occupancy14": { - "units": "No-units" - }, - "bw1_lamp_brightness1": { - "units": "Percent" - }, - "bw1_lamp_brightness10": { - "units": "Percent" - }, - "bw2_occupancy15": { - "units": "No-units" - }, - "bw3_occupancy11": { - "units": "No-units" - }, - "bw6_occupancy15": { - "units": "No-units" - }, - "bw1_lamp_brightness17": { - "units": "Percent" - }, - "bw2_light_level9": { - "units": "Luxes" - }, - "bw1_lamp_brightness16": { - "units": "Percent" - }, - "bw1_lamp_brightness15": { - "units": "Percent" - }, - "bw1_lamp_brightness14": { - "units": "Percent" - }, - "bw1_lamp_brightness19": { - "units": "Percent" - }, - "bw1_lamp_brightness18": { - "units": "Percent" - }, - "bw1_group_brightness4": { - "units": "Percent" - }, - "bw2_occupancy16": { - "units": "No-units" - }, - "bw1_group_brightness5": { - "units": "Percent" - }, - "bw1_group_brightness6": { - "units": "Percent" - }, - "bw3_occupancy16": { - "units": "No-units" - }, - "bw6_occupancy10": { - "units": "No-units" - }, - "bw1_group_brightness7": { - "units": "Percent" - }, - "bw3_occupancy15": { - "units": "No-units" - }, - "bw6_occupancy11": { - "units": "No-units" - }, - "bw1_group_brightness8": { - "units": "Percent" - }, - "bw1_group_brightness9": { - "units": "Percent" - }, - "bw1_lamp_brightness64": { - "units": "Percent" - }, - "bw1_lamp_brightness63": { - "units": "Percent" - }, - "bw1_lamp_brightness62": { - "units": "Percent" - }, - "bw1_lamp_brightness61": { - "units": "Percent" - }, - "bw1_lamp_brightness8": { - "units": "Percent" - }, - "bw1_lamp_brightness7": { - "units": "Percent" - }, - "bw1_lamp_brightness6": { - "units": "Percent" - }, - "bw1_lamp_brightness5": { - "units": "Percent" - }, - "bw1_lamp_brightness60": { - "units": "Percent" - }, - "bw1_lamp_brightness9": { - "units": "Percent" - }, - "bw1_lamp_brightness42": { - "units": "Percent" - }, - "bw1_lamp_brightness41": { - "units": "Percent" - }, - "bw1_lamp_brightness40": { - "units": "Percent" - }, - "bw1_lamp_brightness46": { - "units": "Percent" - }, - "bw1_lamp_brightness45": { - "units": "Percent" - }, - "bw1_lamp_brightness44": { - "units": "Percent" - }, - "bw1_lamp_brightness43": { - "units": "Percent" - }, - "bw1_lamp_brightness49": { - "units": "Percent" - }, - "bw1_lamp_brightness48": { - "units": "Percent" - }, - "bw1_lamp_brightness47": { - "units": "Percent" - }, - "bw1_light_level3": { - "units": "Luxes" - }, - "bw1_light_level2": { - "units": "Luxes" - }, - "bw1_light_level1": { - "units": "Luxes" - }, - "bw1_light_level7": { - "units": "Luxes" - }, - "bw1_light_level6": { - "units": "Luxes" - }, - "bw1_light_level5": { - "units": "Luxes" - }, - "bw1_light_level4": { - "units": "Luxes" - }, - "bw1_lamp_brightness53": { - "units": "Percent" - }, - "bw1_lamp_brightness52": { - "units": "Percent" - }, - "bw1_lamp_brightness51": { - "units": "Percent" - }, - "bw1_lamp_brightness50": { - "units": "Percent" - }, - "bw1_lamp_brightness57": { - "units": "Percent" - }, - "bw1_lamp_brightness56": { - "units": "Percent" - }, - "bw1_lamp_brightness55": { - "units": "Percent" - }, - "bw1_lamp_brightness54": { - "units": "Percent" - }, - "bw1_lamp_brightness59": { - "units": "Percent" - }, - "bw1_light_level9": { - "units": "Luxes" - }, - "bw1_lamp_brightness58": { - "units": "Percent" - }, - "bw1_light_level8": { - "units": "Luxes" - }, - "bw4_lamp_brightness1": { - "units": "Percent" - }, - "bw4_lamp_brightness3": { - "units": "Percent" - }, - "bw4_lamp_brightness2": { - "units": "Percent" - }, - "bw4_lamp_brightness5": { - "units": "Percent" - }, - "bw4_lamp_brightness4": { - "units": "Percent" - }, - "bw4_lamp_brightness7": { - "units": "Percent" - }, - "bw4_lamp_brightness6": { - "units": "Percent" - }, - "bw5_occupancy8": { - "units": "No-units" - }, - "bw5_occupancy9": { - "units": "No-units" - }, - "bw5_occupancy6": { - "units": "No-units" - }, - "bw5_occupancy7": { - "units": "No-units" - }, - "bw5_occupancy1": { - "units": "No-units" - }, - "bw5_occupancy4": { - "units": "No-units" - }, - "bw5_occupancy5": { - "units": "No-units" - }, - "bw5_occupancy2": { - "units": "No-units" - }, - "bw5_occupancy3": { - "units": "No-units" - }, - "bw4_lamp_brightness9": { - "units": "Percent" - }, - "bw4_lamp_brightness8": { - "units": "Percent" - }, - "bw6_group_brightness16": { - "units": "Percent" - }, - "bw6_group_brightness7": { - "units": "Percent" - }, - "bw6_group_brightness14": { - "units": "Percent" - }, - "bw6_group_brightness8": { - "units": "Percent" - }, - "bw6_group_brightness15": { - "units": "Percent" - }, - "bw6_group_brightness9": { - "units": "Percent" - }, - "bw6_group_brightness12": { - "units": "Percent" - }, - "bw6_group_brightness13": { - "units": "Percent" - }, - "bw2_light_level15": { - "units": "Luxes" - }, - "bw6_group_brightness3": { - "units": "Percent" - }, - "bw2_light_level14": { - "units": "Luxes" - }, - "bw6_group_brightness4": { - "units": "Percent" - }, - "bw6_group_brightness5": { - "units": "Percent" - }, - "bw2_light_level16": { - "units": "Luxes" - }, - "bw6_group_brightness6": { - "units": "Percent" - }, - "bw2_light_level11": { - "units": "Luxes" - }, - "bw2_light_level10": { - "units": "Luxes" - }, - "bw2_light_level13": { - "units": "Luxes" - }, - "bw6_group_brightness1": { - "units": "Percent" - }, - "bw2_light_level12": { - "units": "Luxes" - }, - "bw6_group_brightness2": { - "units": "Percent" - }, - "bw2_group_brightness16": { - "units": "Percent" - }, - "bw2_group_brightness15": { - "units": "Percent" - }, - "bw6_group_brightness10": { - "units": "Percent" - }, - "bw2_group_brightness14": { - "units": "Percent" - }, - "bw6_group_brightness11": { - "units": "Percent" - }, - "bw2_group_brightness13": { - "units": "Percent" - }, - "bw2_group_brightness12": { - "units": "Percent" - }, - "bw2_group_brightness11": { - "units": "Percent" - }, - "bw2_group_brightness10": { - "units": "Percent" - }, - "bw5_group_brightness1": { - "units": "Percent" - }, - "bw5_group_brightness3": { - "units": "Percent" - }, - "bw5_group_brightness2": { - "units": "Percent" - }, - "bw5_group_brightness5": { - "units": "Percent" - }, - "bw5_group_brightness4": { - "units": "Percent" - }, - "bw5_group_brightness7": { - "units": "Percent" - }, - "bw5_group_brightness6": { - "units": "Percent" - }, - "bw5_group_brightness9": { - "units": "Percent" - }, - "bw5_group_brightness8": { - "units": "Percent" - }, - "bw4_light_level16": { - "units": "Luxes" - }, - "bw3_occupancy3": { - "units": "No-units" - }, - "bw3_occupancy2": { - "units": "No-units" - }, - "bw3_occupancy1": { - "units": "No-units" - }, - "bw5_light_level10": { - "units": "Luxes" - }, - "bw5_light_level11": { - "units": "Luxes" - }, - "bw5_light_level12": { - "units": "Luxes" - }, - "bw5_light_level13": { - "units": "Luxes" - }, - "bw5_light_level14": { - "units": "Luxes" - }, - "bw3_occupancy9": { - "units": "No-units" - }, - "bw3_occupancy8": { - "units": "No-units" - }, - "bw3_occupancy7": { - "units": "No-units" - }, - "bw3_occupancy6": { - "units": "No-units" - }, - "bw3_occupancy5": { - "units": "No-units" - }, - "bw3_occupancy4": { - "units": "No-units" - }, - "bw4_light_level12": { - "units": "Luxes" - }, - "bw4_light_level13": { - "units": "Luxes" - }, - "bw4_light_level14": { - "units": "Luxes" - }, - "bw4_light_level15": { - "units": "Luxes" - }, - "bw4_light_level10": { - "units": "Luxes" - }, - "bw4_light_level11": { - "units": "Luxes" - }, - "bw2_group_brightness5": { - "units": "Percent" - }, - "bw2_group_brightness6": { - "units": "Percent" - }, - "bw2_group_brightness3": { - "units": "Percent" - }, - "bw2_group_brightness4": { - "units": "Percent" - }, - "bw6_lamp_brightness1": { - "units": "Percent" - }, - "bw2_group_brightness9": { - "units": "Percent" - }, - "bw2_group_brightness7": { - "units": "Percent" - }, - "bw2_group_brightness8": { - "units": "Percent" - }, - "bw3_light_level10": { - "units": "Luxes" - }, - "bw6_lamp_brightness6": { - "units": "Percent" - }, - "bw6_lamp_brightness7": { - "units": "Percent" - }, - "bw3_light_level12": { - "units": "Luxes" - }, - "bw6_lamp_brightness8": { - "units": "Percent" - }, - "bw3_light_level11": { - "units": "Luxes" - }, - "bw6_lamp_brightness9": { - "units": "Percent" - }, - "bw3_light_level14": { - "units": "Luxes" - }, - "bw6_lamp_brightness2": { - "units": "Percent" - }, - "bw3_light_level13": { - "units": "Luxes" - }, - "bw6_lamp_brightness3": { - "units": "Percent" - }, - "bw3_light_level16": { - "units": "Luxes" - }, - "bw6_lamp_brightness4": { - "units": "Percent" - }, - "bw3_light_level15": { - "units": "Luxes" - }, - "bw6_lamp_brightness5": { - "units": "Percent" - }, - "bw2_lamp_brightness18": { - "units": "Percent" - }, - "bw2_lamp_brightness17": { - "units": "Percent" - }, - "bw2_lamp_brightness19": { - "units": "Percent" - }, - "bw2_lamp_brightness14": { - "units": "Percent" - }, - "bw2_lamp_brightness13": { - "units": "Percent" - }, - "bw2_lamp_brightness16": { - "units": "Percent" - }, - "bw2_lamp_brightness15": { - "units": "Percent" - }, - "bw2_lamp_brightness10": { - "units": "Percent" - }, - "bw2_lamp_brightness12": { - "units": "Percent" - }, - "bw2_lamp_brightness11": { - "units": "Percent" - }, - "bw2_lamp_brightness7": { - "units": "Percent" - }, - "bw2_lamp_brightness6": { - "units": "Percent" - }, - "bw2_lamp_brightness9": { - "units": "Percent" - }, - "bw2_lamp_brightness8": { - "units": "Percent" - }, - "bw3_lamp_brightness11": { - "units": "Percent" - }, - "bw3_lamp_brightness10": { - "units": "Percent" - }, - "bw3_lamp_brightness19": { - "units": "Percent" - }, - "bw3_lamp_brightness18": { - "units": "Percent" - }, - "bw3_lamp_brightness17": { - "units": "Percent" - }, - "bw3_lamp_brightness16": { - "units": "Percent" - }, - "bw2_group_brightness1": { - "units": "Percent" - }, - "bw3_lamp_brightness15": { - "units": "Percent" - }, - "bw6_light_level13": { - "units": "Luxes" - }, - "bw2_group_brightness2": { - "units": "Percent" - }, - "bw3_lamp_brightness14": { - "units": "Percent" - }, - "bw6_light_level12": { - "units": "Luxes" - }, - "bw3_lamp_brightness13": { - "units": "Percent" - }, - "bw6_light_level11": { - "units": "Luxes" - }, - "bw3_lamp_brightness12": { - "units": "Percent" - }, - "bw6_light_level10": { - "units": "Luxes" - }, - "bw2_occupancy2": { - "units": "No-units" - }, - "bw2_occupancy1": { - "units": "No-units" - }, - "bw4_lamp_brightness10": { - "units": "Percent" - }, - "bw2_occupancy8": { - "units": "No-units" - }, - "bw4_lamp_brightness13": { - "units": "Percent" - }, - "bw2_occupancy7": { - "units": "No-units" - }, - "bw4_lamp_brightness14": { - "units": "Percent" - }, - "bw4_lamp_brightness11": { - "units": "Percent" - }, - "bw2_occupancy9": { - "units": "No-units" - }, - "bw4_lamp_brightness12": { - "units": "Percent" - }, - "bw2_occupancy4": { - "units": "No-units" - }, - "bw4_lamp_brightness17": { - "units": "Percent" - }, - "bw2_occupancy3": { - "units": "No-units" - }, - "bw4_lamp_brightness18": { - "units": "Percent" - }, - "bw2_occupancy6": { - "units": "No-units" - }, - "bw4_lamp_brightness15": { - "units": "Percent" - }, - "bw2_occupancy5": { - "units": "No-units" - }, - "bw4_lamp_brightness16": { - "units": "Percent" - }, - "bw2_lamp_brightness3": { - "units": "Percent" - }, - "bw2_lamp_brightness2": { - "units": "Percent" - }, - "bw2_lamp_brightness5": { - "units": "Percent" - }, - "bw2_lamp_brightness4": { - "units": "Percent" - }, - "bw3_group_brightness1": { - "units": "Percent" - }, - "bw2_lamp_brightness1": { - "units": "Percent" - }, - "bw3_group_brightness6": { - "units": "Percent" - }, - "bw5_light_level15": { - "units": "Luxes" - }, - "bw3_group_brightness7": { - "units": "Percent" - }, - "bw5_light_level16": { - "units": "Luxes" - }, - "bw3_group_brightness8": { - "units": "Percent" - }, - "bw3_group_brightness9": { - "units": "Percent" - }, - "bw3_group_brightness2": { - "units": "Percent" - }, - "bw3_group_brightness3": { - "units": "Percent" - }, - "bw3_group_brightness4": { - "units": "Percent" - }, - "bw3_group_brightness5": { - "units": "Percent" - }, - "bw3_lamp_brightness33": { - "units": "Percent" - }, - "bw3_lamp_brightness32": { - "units": "Percent" - }, - "bw3_lamp_brightness31": { - "units": "Percent" - }, - "bw3_lamp_brightness30": { - "units": "Percent" - }, - "bw3_lamp_brightness39": { - "units": "Percent" - }, - "bw3_lamp_brightness38": { - "units": "Percent" - }, - "bw3_lamp_brightness37": { - "units": "Percent" - }, - "bw3_lamp_brightness36": { - "units": "Percent" - }, - "bw3_lamp_brightness35": { - "units": "Percent" - }, - "bw3_lamp_brightness34": { - "units": "Percent" - }, - "bw4_occupancy12": { - "units": "No-units" - }, - "bw5_occupancy14": { - "units": "No-units" - }, - "bw4_occupancy13": { - "units": "No-units" - }, - "bw5_occupancy13": { - "units": "No-units" - }, - "bw6_light_level16": { - "units": "Luxes" - }, - "bw4_occupancy10": { - "units": "No-units" - }, - "bw5_occupancy16": { - "units": "No-units" - }, - "bw6_light_level15": { - "units": "Luxes" - }, - "bw4_occupancy11": { - "units": "No-units" - }, - "bw5_occupancy15": { - "units": "No-units" - }, - "bw6_light_level14": { - "units": "Luxes" - }, - "bw1_occupancy14": { - "units": "No-units" - }, - "bw1_occupancy13": { - "units": "No-units" - }, - "bw1_occupancy16": { - "units": "No-units" - }, - "bw1_occupancy15": { - "units": "No-units" - }, - "bw1_occupancy10": { - "units": "No-units" - }, - "bw1_occupancy12": { - "units": "No-units" - }, - "bw1_occupancy11": { - "units": "No-units" - }, - "bw3_lamp_brightness22": { - "units": "Percent" - }, - "bw3_lamp_brightness21": { - "units": "Percent" - }, - "bw3_lamp_brightness20": { - "units": "Percent" - }, - "bw3_lamp_brightness29": { - "units": "Percent" - }, - "bw3_lamp_brightness28": { - "units": "Percent" - }, - "bw3_lamp_brightness27": { - "units": "Percent" - }, - "bw3_lamp_brightness26": { - "units": "Percent" - }, - "bw4_occupancy16": { - "units": "No-units" - }, - "bw5_occupancy10": { - "units": "No-units" - }, - "bw3_lamp_brightness25": { - "units": "Percent" - }, - "bw3_lamp_brightness24": { - "units": "Percent" - }, - "bw4_occupancy14": { - "units": "No-units" - }, - "bw5_occupancy12": { - "units": "No-units" - }, - "bw3_lamp_brightness23": { - "units": "Percent" - }, - "bw4_occupancy15": { - "units": "No-units" - }, - "bw5_occupancy11": { - "units": "No-units" - }, - "bw4_lamp_brightness42": { - "units": "Percent" - }, - "bw4_lamp_brightness43": { - "units": "Percent" - }, - "bw4_lamp_brightness40": { - "units": "Percent" - }, - "bw4_lamp_brightness41": { - "units": "Percent" - }, - "bw4_lamp_brightness46": { - "units": "Percent" - }, - "bw4_lamp_brightness47": { - "units": "Percent" - }, - "bw4_lamp_brightness44": { - "units": "Percent" - }, - "bw4_lamp_brightness45": { - "units": "Percent" - }, - "bw4_lamp_brightness48": { - "units": "Percent" - }, - "bw4_lamp_brightness49": { - "units": "Percent" - }, - "bw5_lamp_brightness3": { - "units": "Percent" - }, - "bw5_lamp_brightness4": { - "units": "Percent" - }, - "bw5_lamp_brightness1": { - "units": "Percent" - }, - "bw5_lamp_brightness2": { - "units": "Percent" - }, - "bw5_lamp_brightness7": { - "units": "Percent" - }, - "bw5_lamp_brightness8": { - "units": "Percent" - }, - "bw5_lamp_brightness5": { - "units": "Percent" - }, - "bw5_lamp_brightness6": { - "units": "Percent" - }, - "bw4_lamp_brightness50": { - "units": "Percent" - }, - "bw4_lamp_brightness53": { - "units": "Percent" - }, - "bw4_lamp_brightness54": { - "units": "Percent" - }, - "bw4_lamp_brightness51": { - "units": "Percent" - }, - "bw4_lamp_brightness52": { - "units": "Percent" - }, - "bw4_lamp_brightness57": { - "units": "Percent" - }, - "bw4_lamp_brightness58": { - "units": "Percent" - }, - "bw4_lamp_brightness55": { - "units": "Percent" - }, - "bw4_lamp_brightness56": { - "units": "Percent" - }, - "bw4_lamp_brightness59": { - "units": "Percent" - }, - "bw4_group_brightness8": { - "units": "Percent" - }, - "bw4_group_brightness7": { - "units": "Percent" - }, - "bw4_group_brightness6": { - "units": "Percent" - }, - "bw4_group_brightness5": { - "units": "Percent" - }, - "bw4_group_brightness4": { - "units": "Percent" - }, - "bw4_group_brightness3": { - "units": "Percent" - }, - "bw4_group_brightness2": { - "units": "Percent" - }, - "bw4_group_brightness1": { - "units": "Percent" - }, - "bw4_group_brightness9": { - "units": "Percent" - }, - "bw4_lamp_brightness20": { - "units": "Percent" - }, - "bw4_lamp_brightness21": { - "units": "Percent" - }, - "bw4_lamp_brightness24": { - "units": "Percent" - }, - "bw4_lamp_brightness25": { - "units": "Percent" - }, - "bw4_lamp_brightness22": { - "units": "Percent" - }, - "bw4_lamp_brightness23": { - "units": "Percent" - }, - "bw4_lamp_brightness28": { - "units": "Percent" - }, - "bw4_lamp_brightness29": { - "units": "Percent" - }, - "bw4_lamp_brightness26": { - "units": "Percent" - }, - "bw4_lamp_brightness27": { - "units": "Percent" - }, - "bw4_lamp_brightness19": { - "units": "Percent" - }, - "bw5_light_level2": { - "units": "Luxes" - }, - "bw5_light_level3": { - "units": "Luxes" - }, - "bw5_light_level1": { - "units": "Luxes" - }, - "bw5_light_level6": { - "units": "Luxes" - }, - "bw5_light_level7": { - "units": "Luxes" - }, - "bw5_light_level4": { - "units": "Luxes" - }, - "bw5_light_level5": { - "units": "Luxes" - }, - "bw5_light_level8": { - "units": "Luxes" - }, - "bw5_light_level9": { - "units": "Luxes" - }, - "bw4_lamp_brightness31": { - "units": "Percent" - }, - "bw4_lamp_brightness32": { - "units": "Percent" - }, - "bw4_lamp_brightness30": { - "units": "Percent" - }, - "bw4_lamp_brightness35": { - "units": "Percent" - }, - "bw4_lamp_brightness36": { - "units": "Percent" - }, - "bw4_lamp_brightness33": { - "units": "Percent" - }, - "bw4_lamp_brightness34": { - "units": "Percent" - }, - "bw4_lamp_brightness39": { - "units": "Percent" - }, - "bw4_lamp_brightness37": { - "units": "Percent" - }, - "bw4_lamp_brightness38": { - "units": "Percent" - } - } - }, - "version": 1, - "timestamp": "2020-03-05T14:42:59.743Z" -} diff --git a/schemas/udmi/metadata.tests/toomany.out b/schemas/udmi/metadata.tests/toomany.out deleted file mode 100644 index c4e33ac250..0000000000 --- a/schemas/udmi/metadata.tests/toomany.out +++ /dev/null @@ -1,6 +0,0 @@ -Validating 1 schemas - Validating 1 files against metadata.json - Against input metadata.tests/toomany.json - #: 2 schema violations found - #/pointset/points: maximum size: [150], found: [672] - #/system/physical_tag/asset/name: string [UK-LON-S2_LTGW-3] does not match pattern ^[A-Z]{2,6}-[0-9]{1,6}$ diff --git a/schemas/udmi/metadata_cloud.json b/schemas/udmi/metadata_cloud.json deleted file mode 100644 index 5ca41285a7..0000000000 --- a/schemas/udmi/metadata_cloud.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "title": "Cloud configuration metadata snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "auth_type": { - "enum": [ - "RS256", - "RS256_X506" - ] - }, - "is_gateway": { - "type": "boolean" - } - }, - "required": [ - "auth_type" - ] -} diff --git a/schemas/udmi/metadata_gateway.json b/schemas/udmi/metadata_gateway.json deleted file mode 100644 index f15dee7344..0000000000 --- a/schemas/udmi/metadata_gateway.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "title": "Gateway metadata snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "gateway_id": { - "type": "string", - "pattern": "^[A-Z]{3}-[1-9][0-9]{0,2}$" - }, - "subsystem": { - "type": "string", - "pattern": "^[a-z0-9-]+$" - }, - "proxy_ids": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[A-Z]{3}-[1-9][0-9]{0,2}$" - } - } - }, - "oneOf": [ - { "required": ["gateway_id"] }, - { "required": ["proxy_ids"] } - ] -} diff --git a/schemas/udmi/metadata_localnet.json b/schemas/udmi/metadata_localnet.json deleted file mode 100644 index be7de102b5..0000000000 --- a/schemas/udmi/metadata_localnet.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "title": "Local network metadata snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "subsystem": { - "type": "object", - "patternProperties": { - "^[a-z0-9-]+$": { - "additionalProperties": false, - "properties": { - "local_id": { - "type": "string" - } - }, - "required": [ - "local_id" - ] - } - } - } - }, - "required": [ - "subsystem" - ] -} diff --git a/schemas/udmi/metadata_pointset.json b/schemas/udmi/metadata_pointset.json deleted file mode 100644 index 4d6ac05dce..0000000000 --- a/schemas/udmi/metadata_pointset.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Pointset metadata snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "points": { - "additionalProperties": false, - "maxProperties": 150, - "patternProperties": { - "^[a-z][a-z0-9]*(_[a-z0-9]+)*$": { - "additionalProperties": false, - "properties": { - "units": { - "$ref": "file:units.json#" - }, - "ref": { - "type": "string" - } - } - } - } - } - }, - "required": [ - "points" - ] -} diff --git a/schemas/udmi/metadata_system.json b/schemas/udmi/metadata_system.json deleted file mode 100644 index f1d48da2fd..0000000000 --- a/schemas/udmi/metadata_system.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "title": "System metadata snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "location": { - "type": "object", - "additionalProperties": false, - "properties": { - "site": { - "type": "string", - "pattern": "^[A-Z]{2}-[A-Z]{3}-[A-Z0-9]{2,9}$" - }, - "section": { - "type": "string", - "pattern": "^[A-Z0-9-]+$" - }, - "position": { - "type": "object", - "additionalProperties": false, - "properties": { - "x": { - "type": "number" - }, - "y": { - "type": "number" - } - }, - "required": [ - "x", - "y" - ] - } - }, - "required": [ - "site" - ] - }, - "physical_tag": { - "type": "object", - "additionalProperties": false, - "properties": { - "asset": { - "type": "object", - "additionalProperties": false, - "properties": { - "guid": { - "type": "string", - "pattern": "^[a-z]+://[-0-9a-zA-Z_$]+$" - }, - "site": { - "type": "string", - "pattern": "^[A-Z]{2}-[A-Z]{3}-[A-Z0-9]{2,9}$" - }, - "name": { - "type": "string", - "pattern": "^[A-Z]{2,6}-[0-9]{1,6}$" - } - }, - "required": [ - "guid", - "name" - ] - } - }, - "required": [ - "asset" - ] - }, - "aux": { - "type": "object", - "additionalProperties": false, - "properties": { - "suffix": { - "type": "string", - "pattern": "^[a-zA-Z0-9-]+$" - } - } - } - }, - "required": [ - "location", - "physical_tag" - ] -} diff --git a/schemas/udmi/pointset.json b/schemas/udmi/pointset.json deleted file mode 100644 index b18d31eda8..0000000000 --- a/schemas/udmi/pointset.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "title": "Pointset telemetry schema", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" - }, - "version": { - "enum": [ - 1 - ] - }, - "points": { - "additionalProperties": false, - "patternProperties": { - "^[a-z][a-z0-9]*(_[a-z0-9]+)*$": { - "$ref": "#/definitions/point_property_names" - } - } - } - }, - "required": [ - "timestamp", - "version", - "points" - ], - "definitions": { - "point_property_names": { - "type": "object", - "propertyNames": { - "oneOf": [ - { - "enum": [ - "present_value" - ] - } - ] - }, - "required": [ - "present_value" - ] - } - } -} diff --git a/schemas/udmi/pointset.tests/empty.json b/schemas/udmi/pointset.tests/empty.json deleted file mode 100644 index 2c63c08510..0000000000 --- a/schemas/udmi/pointset.tests/empty.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/schemas/udmi/pointset.tests/empty.out b/schemas/udmi/pointset.tests/empty.out deleted file mode 100644 index 5f645ca58a..0000000000 --- a/schemas/udmi/pointset.tests/empty.out +++ /dev/null @@ -1,7 +0,0 @@ -Validating 1 schemas - Validating 1 files against pointset.json - Against input pointset.tests/empty.json - #: 3 schema violations found - #: required key [points] not found - #: required key [timestamp] not found - #: required key [version] not found diff --git a/schemas/udmi/pointset.tests/errors.json b/schemas/udmi/pointset.tests/errors.json deleted file mode 100644 index 321ea7c4a5..0000000000 --- a/schemas/udmi/pointset.tests/errors.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "id": "sneakyCASE", - "comment$string": "world", - "properties": { - "$comment": "Common error cases for target telemetry." - }, - "points": { - "comment$string": "world", - "analogValue_1": { - "present_value": true - }, - "bad_entity_name_": { - "present_value": 21.30108642578125 - }, - "guid": "ab9402fa-2c5a-42d1-b4f3-d40b440dea13", - "yoyo_motion_sensor": { - "bad_property_name": true - }, - "bad_____sensor": { - "present_value": true - }, - "missing_present_value": { - }, - "old_properties": { - "properties": { - "present_value": true - } - }, - "magic_voice_recognizer": { - "present_value": { - "present_value": true - } - } - } -} diff --git a/schemas/udmi/pointset.tests/errors.out b/schemas/udmi/pointset.tests/errors.out deleted file mode 100644 index e973a0e733..0000000000 --- a/schemas/udmi/pointset.tests/errors.out +++ /dev/null @@ -1,22 +0,0 @@ -Validating 1 schemas - Validating 1 files against pointset.json - Against input pointset.tests/errors.json - #: 13 schema violations found - #/points: 10 schema violations found - #/points/guid: expected type: JSONObject, found: String - #/points/missing_present_value: required key [present_value] not found - #/points/old_properties: 2 schema violations found - #/points/old_properties/properties: #: 0 subschemas matched instead of one - #/points/old_properties/properties: properties is not a valid enum value - #/points/old_properties: required key [present_value] not found - #/points/yoyo_motion_sensor: 2 schema violations found - #/points/yoyo_motion_sensor/bad_property_name: #: 0 subschemas matched instead of one - #/points/yoyo_motion_sensor/bad_property_name: bad_property_name is not a valid enum value - #/points/yoyo_motion_sensor: required key [present_value] not found - #/points: extraneous key [analogValue_1] is not permitted - #/points: extraneous key [bad_____sensor] is not permitted - #/points: extraneous key [bad_entity_name_] is not permitted - #/points: extraneous key [comment$string] is not permitted - #: extraneous key [comment$string] is not permitted - #: extraneous key [id] is not permitted - #: extraneous key [properties] is not permitted diff --git a/schemas/udmi/pointset.tests/example.json b/schemas/udmi/pointset.tests/example.json deleted file mode 100644 index 7af10743e5..0000000000 --- a/schemas/udmi/pointset.tests/example.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "points": { - "reading_value": { - "present_value": 21.30108642578125 - }, - "nexus_sensor": { - "present_value": 21.1 - }, - "yoyo_motion_sensor": { - "present_value": true - }, - "enum_value": { - "present_value": "hello" - } - } -} diff --git a/schemas/udmi/pointset.tests/example.out b/schemas/udmi/pointset.tests/example.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/pointset.tests/fcu.json b/schemas/udmi/pointset.tests/fcu.json deleted file mode 100644 index 9b45dfbfe6..0000000000 --- a/schemas/udmi/pointset.tests/fcu.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": 1, - "timestamp": "2019-01-17T14:02:29.364Z", - "points": { - "space_temperature_sensor": { - "present_value": 21.30108642578125 - }, - "fan_run_status": { - "present_value": true - }, - "fan_run_enable": { - "present_value": false - }, - "chilled_water_valve_percentage_command": { - "present_value": 76 - } - } -} diff --git a/schemas/udmi/pointset.tests/fcu.out b/schemas/udmi/pointset.tests/fcu.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/pointset.tests/smartprimus.json b/schemas/udmi/pointset.tests/smartprimus.json deleted file mode 100644 index 9b45dfbfe6..0000000000 --- a/schemas/udmi/pointset.tests/smartprimus.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": 1, - "timestamp": "2019-01-17T14:02:29.364Z", - "points": { - "space_temperature_sensor": { - "present_value": 21.30108642578125 - }, - "fan_run_status": { - "present_value": true - }, - "fan_run_enable": { - "present_value": false - }, - "chilled_water_valve_percentage_command": { - "present_value": 76 - } - } -} diff --git a/schemas/udmi/pointset.tests/smartprimus.out b/schemas/udmi/pointset.tests/smartprimus.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/properties.json b/schemas/udmi/properties.json deleted file mode 100644 index 8b4375c07a..0000000000 --- a/schemas/udmi/properties.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "title": "Device Properties Schema", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "required": [ - "key_type", - "version", - "connect" - ], - "properties": { - "key_type": { - "enum": [ - "RSA_PEM", - "RSA_X509_PEM" - ] - }, - "version": { - "enum": [ - 1 - ] - }, - "connect": { - "enum": [ - "direct" - ] - } - } -} diff --git a/schemas/udmi/state.json b/schemas/udmi/state.json deleted file mode 100644 index 117881e3cb..0000000000 --- a/schemas/udmi/state.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "title": "Device State schema", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "required": [ - "timestamp", - "version", - "system" - ], - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" - }, - "version": { - "enum": [ - 1 - ] - }, - "system": { - "$ref": "file:state_system.json#" - }, - "gateway": { - "$ref": "file:state_gateway.json#" - }, - "pointset": { - "$ref": "file:state_pointset.json#" - } - } -} diff --git a/schemas/udmi/state.tests/empty.json b/schemas/udmi/state.tests/empty.json deleted file mode 100644 index 2c63c08510..0000000000 --- a/schemas/udmi/state.tests/empty.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/schemas/udmi/state.tests/empty.out b/schemas/udmi/state.tests/empty.out deleted file mode 100644 index 09d7bf88cf..0000000000 --- a/schemas/udmi/state.tests/empty.out +++ /dev/null @@ -1,7 +0,0 @@ -Validating 1 schemas - Validating 1 files against state.json - Against input state.tests/empty.json - #: 3 schema violations found - #: required key [system] not found - #: required key [timestamp] not found - #: required key [version] not found diff --git a/schemas/udmi/state.tests/errors.json b/schemas/udmi/state.tests/errors.json deleted file mode 100644 index 5977f68e90..0000000000 --- a/schemas/udmi/state.tests/errors.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "id": "monkey_brains", - "system": { - "device_id": "33895507", - "device_status": "ok", - "object_name": "UK-BRH-XX_AHU-001", - "fling": "hello", - "firmware": { - "revision": "should be version" - }, - "system_status": "Operational", - "statuses": { - "default": { - "timestamp": "2018-08-26T21:39:30.364Z", - "level": 30 - } - }, - "status": "hunky-dory" - }, - "status": [ - { - "level": 30 - } - ], - "pointset": { - "points": { - "return_air_temperature_sensor": { - "object_type": "analog_input", - "instance_number": 4, - "cov_increment": 0.300000011920929, - "deadband": 0, - "rapt": "hello", - "high_limit": 0, - "low_limit": 0, - "resolution": 0.04952822998166084, - "units": "Degrees Celsius", - "status": "it's working!" - } - } - } -} diff --git a/schemas/udmi/state.tests/errors.out b/schemas/udmi/state.tests/errors.out deleted file mode 100644 index f58e247fc5..0000000000 --- a/schemas/udmi/state.tests/errors.out +++ /dev/null @@ -1,32 +0,0 @@ -Validating 1 schemas - Validating 1 files against state.json - Against input state.tests/errors.json - #: 24 schema violations found - #/pointset/points/return_air_temperature_sensor: 9 schema violations found - #/pointset/points/return_air_temperature_sensor/status: expected type: JSONObject, found: String - #/pointset/points/return_air_temperature_sensor: extraneous key [cov_increment] is not permitted - #/pointset/points/return_air_temperature_sensor: extraneous key [deadband] is not permitted - #/pointset/points/return_air_temperature_sensor: extraneous key [high_limit] is not permitted - #/pointset/points/return_air_temperature_sensor: extraneous key [instance_number] is not permitted - #/pointset/points/return_air_temperature_sensor: extraneous key [low_limit] is not permitted - #/pointset/points/return_air_temperature_sensor: extraneous key [object_type] is not permitted - #/pointset/points/return_air_temperature_sensor: extraneous key [rapt] is not permitted - #/pointset/points/return_air_temperature_sensor: extraneous key [resolution] is not permitted - #/system: 13 schema violations found - #/system/firmware: 2 schema violations found - #/system/firmware: extraneous key [revision] is not permitted - #/system/firmware: required key [version] not found - #/system/statuses/default: 3 schema violations found - #/system/statuses/default/level: 30 is not greater or equal to 100 - #/system/statuses/default: required key [category] not found - #/system/statuses/default: required key [message] not found - #/system: extraneous key [device_id] is not permitted - #/system: extraneous key [device_status] is not permitted - #/system: extraneous key [fling] is not permitted - #/system: extraneous key [object_name] is not permitted - #/system: extraneous key [status] is not permitted - #/system: extraneous key [system_status] is not permitted - #/system: required key [make_model] not found - #/system: required key [operational] not found - #: extraneous key [id] is not permitted - #: extraneous key [status] is not permitted diff --git a/schemas/udmi/state.tests/example.json b/schemas/udmi/state.tests/example.json deleted file mode 100644 index 92044b86a6..0000000000 --- a/schemas/udmi/state.tests/example.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "make_model": "ACME Bird Trap", - "firmware": { - "version": "3.2a" - }, - "last_config": "2018-08-26T21:49:29.364Z", - "operational": true, - "statuses": { - "base_system": { - "message": "Tickity Boo", - "category": "device.state.com", - "timestamp": "2018-08-26T21:39:30.364Z", - "level": 600 - } - } - }, - "pointset": { - "points": { - "return_air_temperature_sensor": { - "units": "Celsius", - "status": { - "message": "Invalid sample time", - "category": "device.config.validate", - "timestamp": "2018-08-26T21:39:28.364Z", - "level": 800 - } - }, - "nexus_sensor": { - "units": "Celsius", - "source": "fix" - } - } - } -} diff --git a/schemas/udmi/state.tests/example.out b/schemas/udmi/state.tests/example.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/state.tests/fcu.json b/schemas/udmi/state.tests/fcu.json deleted file mode 100644 index b2a55220e8..0000000000 --- a/schemas/udmi/state.tests/fcu.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "version": 1, - "timestamp": "2019-01-17T14:02:29.364Z", - "system": { - "make_model": "EasyIO FW-14", - "firmware": { - "version": "3.2a" - }, - "last_config": "2019-01-14T21:49:29.364Z", - "operational": true, - "statuses": { - "base_system": { - "message": "Time on the device is not synchronized", - "category": "com.acme.sync", - "timestamp": "2019-01-17T13:29:47.364Z", - "level": 600 - } - } - }, - "pointset": { - "points": { - "space_temperature_sensor": { - "units": "Degrees-Celsius", - "status": { - "message": "Present value out of limits", - "category": "com.acme.device.regulator", - "timestamp": "2019-01-17T11:39:28.364Z", - "level": 400 - } - }, - "fan_run_status": { - "status": { - "message": "Value overridden by fix_value", - "category": "com.acme.device.monitor", - "timestamp": "2019-01-17T10:59:11.364Z", - "level": 300 - } - }, - "fan_run_enable": { - "status": { - "message": "Value overridden by fix_value", - "category": "com.acme.device.manager", - "timestamp": "2019-01-17T13:14:55.364Z", - "level": 300 - } - }, - "chilled_water_valve_percentage_command": { - "units": "Percent" - } - } - } -} diff --git a/schemas/udmi/state.tests/fcu.out b/schemas/udmi/state.tests/fcu.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/state.tests/gateway.json b/schemas/udmi/state.tests/gateway.json deleted file mode 100644 index 72bbdbc4bb..0000000000 --- a/schemas/udmi/state.tests/gateway.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "make_model": "ACME Gateway v2", - "firmware": { - "version": "3.2a" - }, - "last_config": "2018-08-26T21:49:29.364Z", - "operational": true, - "statuses": { - "base_system": { - "message": "Tickity Boo", - "category": "device.state.com", - "timestamp": "2018-08-26T21:39:30.364Z", - "level": 600 - } - } - }, - "gateway": { - "error_ids": [ "991", "SMS-91" ] - } -} diff --git a/schemas/udmi/state.tests/gateway.out b/schemas/udmi/state.tests/gateway.out deleted file mode 100644 index ae5507e2c2..0000000000 --- a/schemas/udmi/state.tests/gateway.out +++ /dev/null @@ -1,4 +0,0 @@ -Validating 1 schemas - Validating 1 files against state.json - Against input state.tests/gateway.json - #/gateway/error_ids/0: string [991] does not match pattern ^[A-Z]{3}-[1-9][0-9]{0,2}$ diff --git a/schemas/udmi/state.tests/rotate.json b/schemas/udmi/state.tests/rotate.json deleted file mode 100644 index 9c77e543ea..0000000000 --- a/schemas/udmi/state.tests/rotate.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "system": { - "make_model": "ACME Bird Trap", - "firmware": { - "version": "3.2a" - }, - "auth_key": { - "private_hash": "sha512:4e61746f21abe6708ca81a45a1851b82efd1f3ad7f9e6f6fc2dcf431e0ff95cdbcc6f5940a4bfb77df7aeb2f057d19cf5f234a664775edc66175025a14a87c3b" - }, - "last_config": "2018-08-26T21:49:29.364Z", - "operational": true, - "statuses": { - "base_system": { - "message": "Tickity Boo", - "category": "device.state.com", - "timestamp": "2018-08-26T21:39:30.364Z", - "level": 600 - } - } - }, - "pointset": { - "points": { - "return_air_temperature_sensor": { - "units": "Celsius", - "status": { - "message": "Invalid sample time", - "category": "device.config.validate", - "timestamp": "2018-08-26T21:39:28.364Z", - "level": 800 - } - } - } - } -} - diff --git a/schemas/udmi/state.tests/rotate.out b/schemas/udmi/state.tests/rotate.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/state_gateway.json b/schemas/udmi/state_gateway.json deleted file mode 100644 index 45dfd6f35c..0000000000 --- a/schemas/udmi/state_gateway.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "title": "Gateway Config Snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "required": [ - "error_ids" - ], - "properties": { - "error_ids": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[A-Z]{3}-[1-9][0-9]{0,2}$" - } - } - } -} diff --git a/schemas/udmi/state_pointset.json b/schemas/udmi/state_pointset.json deleted file mode 100644 index b6d44061bd..0000000000 --- a/schemas/udmi/state_pointset.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "title": "pointset state snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "points": { - "additionalProperties": false, - "patternProperties": { - "^[a-z][a-z0-9]*(_[a-z0-9]+)*$": { - "additionalProperties": false, - "properties": { - "fault": { - "type": "boolean" - }, - "units": { - "type": "string", - }, - "source": { - "enum": [ - "fix" - ] - }, - "status": { - "$ref": "file:system.json#/definitions/entry" - } - } - } - } - } - }, - "required": [ - "points" - ] -} diff --git a/schemas/udmi/state_system.json b/schemas/udmi/state_system.json deleted file mode 100644 index 5fb326ac93..0000000000 --- a/schemas/udmi/state_system.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "title": "System state snippet", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "make_model": { - "type": "string" - }, - "auth_key": { - "type": "object", - "additionalProperties": false, - "properties": { - "private_hash": { - "type": "string" - } - }, - "required": [ - "private_hash" - ] - }, - "firmware": { - "type": "object", - "additionalProperties": false, - "properties": { - "version": { - "type": "string" - } - }, - "required": [ - "version" - ] - }, - "last_config": { - "type": "string", - "format": "date-time" - }, - "operational": { - "type": "boolean" - }, - "statuses": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z][a-z0-9]*(_[a-z0-9]+)*$": { - "$ref": "file:system.json#/definitions/entry" - } - } - } - }, - "required": [ - "make_model", - "firmware", - "operational" - ] -} diff --git a/schemas/udmi/system.json b/schemas/udmi/system.json deleted file mode 100644 index ca3d33d2d4..0000000000 --- a/schemas/udmi/system.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "title": "Log entry schema", - "type": "object", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" - }, - "version": { - "enum": [ - 1 - ] - }, - "logentries": { - "type": "array", - "items": { - "$ref": "#/definitions/entry" - } - } - }, - "required": [ - "timestamp", - "version" - ], - "definitions": { - "entry": { - "type": "object", - "additionalProperties": false, - "properties": { - "message": { - "type": "string" - }, - "detail": { - "type": "string" - }, - "category": { - "type": "string", - "pattern": "^[a-z][.a-zA-Z]*[a-zA-Z]$" - }, - "timestamp": { - "type": "string", - "format": "date-time" - }, - "level": { - "$comment": "https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity", - "type": "integer", - "multipleOf": 1, - "minimum": 100, - "maximum": 800 - } - }, - "required": [ - "message", - "category", - "timestamp", - "level" - ] - } - } -} diff --git a/schemas/udmi/system.tests/empty.json b/schemas/udmi/system.tests/empty.json deleted file mode 100644 index 2c63c08510..0000000000 --- a/schemas/udmi/system.tests/empty.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/schemas/udmi/system.tests/empty.out b/schemas/udmi/system.tests/empty.out deleted file mode 100644 index ad7bdffef5..0000000000 --- a/schemas/udmi/system.tests/empty.out +++ /dev/null @@ -1,6 +0,0 @@ -Validating 1 schemas - Validating 1 files against system.json - Against input system.tests/empty.json - #: 2 schema violations found - #: required key [timestamp] not found - #: required key [version] not found diff --git a/schemas/udmi/system.tests/errors.json b/schemas/udmi/system.tests/errors.json deleted file mode 100644 index ddf4c70815..0000000000 --- a/schemas/udmi/system.tests/errors.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "logentries": [ - { - "detail": "someplace, sometime", - "category": "com.testCategory$", - "level": 60 - }, - "nope" - ] -} diff --git a/schemas/udmi/system.tests/errors.out b/schemas/udmi/system.tests/errors.out deleted file mode 100644 index 3479a7a113..0000000000 --- a/schemas/udmi/system.tests/errors.out +++ /dev/null @@ -1,10 +0,0 @@ -Validating 1 schemas - Validating 1 files against system.json - Against input system.tests/errors.json - #/logentries: 5 schema violations found - #/logentries/0: 4 schema violations found - #/logentries/0/category: string [com.testCategory$] does not match pattern ^[a-z][.a-zA-Z]*[a-zA-Z]$ - #/logentries/0/level: 60 is not greater or equal to 100 - #/logentries/0: required key [message] not found - #/logentries/0: required key [timestamp] not found - #/logentries/1: expected type: JSONObject, found: String diff --git a/schemas/udmi/system.tests/example.json b/schemas/udmi/system.tests/example.json deleted file mode 100644 index 139253f721..0000000000 --- a/schemas/udmi/system.tests/example.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "logentries": [ - { - "message": "things are happening", - "detail": "someplace, sometime", - "timestamp": "2018-08-26T21:39:19.364Z", - "category": "com.testCategory", - "level": 600 - }, - { - "message": "something else happened", - "timestamp": "2018-08-26T21:39:39.364Z", - "detail": "someplace, sometime", - "category": "com.testCategory", - "level": 700 - } - ] -} diff --git a/schemas/udmi/system.tests/example.out b/schemas/udmi/system.tests/example.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/system.tests/fcu.json b/schemas/udmi/system.tests/fcu.json deleted file mode 100644 index ed4a8c7f1b..0000000000 --- a/schemas/udmi/system.tests/fcu.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": 1, - "timestamp": "2018-08-26T21:39:29.364Z", - "logentries": [ - { - "message": "System Booted", - "timestamp": "2018-08-26T20:39:19.364Z", - "category": "com.acme.system", - "level": 300 - }, - { - "message": "Device communication failed", - "detail": "Connection attempt to device 3564 failed", - "timestamp": "2018-08-26T21:39:19.364Z", - "category": "com.acme.comms", - "level": 700 - } - ] -} diff --git a/schemas/udmi/system.tests/fcu.out b/schemas/udmi/system.tests/fcu.out deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/schemas/udmi/units.json b/schemas/udmi/units.json deleted file mode 100644 index 3e375667d1..0000000000 --- a/schemas/udmi/units.json +++ /dev/null @@ -1,194 +0,0 @@ -{ - "description": "Taken from standard BACnet engineering units", - "enum": [ - "Square-meters", - "Square-feet", - "Milliamperes", - "Amperes", - "Ohms", - "Volts", - "Kilo-volts", - "Mega-volts", - "Volt-amperes", - "Kilo-volt-amperes", - "Mega-volt-amperes", - "Volt-amperes-reactive", - "Kilo-volt-amperes-reactive", - "Mega-volt-amperes-reactive", - "Degrees-phase", - "Power-factor", - "Joules", - "Kilojoules", - "Watt-hours", - "Kilowatt-hours", - "BTUs", - "Therms", - "Ton-hours", - "Joules-per-kilogram-dry-air", - "BTUs-per-pound-dry-air", - "Cycles-per-hour", - "Cycles-per-minute", - "Hertz", - "Grams-of-water-per-kilogram-dry-air", - "Percent-relative-humidity", - "Millimeters", - "Meters", - "Inches", - "Feet", - "Watts-per-square-foot", - "Watts-per-square-meter", - "Lumens", - "Luxes", - "Foot-candles", - "Kilograms", - "Pounds-mass", - "Tons", - "Kilograms-per-second", - "Kilograms-per-minute", - "Kilograms-per-hour", - "Pounds-mass-per-minute", - "Pounds-mass-per-hour", - "Watts", - "Kilowatts", - "Megawatts", - "BTUs-per-hour", - "Horsepower", - "Tons-refrigeration", - "Pascals", - "Kilopascals", - "Bars", - "Pounds-force-per-square-inch", - "Centimeters-of-water", - "Inches-of-water", - "Millimeters-of-mercury", - "Centimeters-of-mercury", - "Inches-of-mercury", - "Degrees-Celsius", - "Degrees-Kelvin", - "Degrees-Fahrenheit", - "Degree-days-Celsius", - "Degree-days-Fahrenheit", - "Years", - "Months", - "Weeks", - "Days", - "Hours", - "Minutes", - "Seconds", - "Meters-per-second", - "Kilometers-per-hour", - "Feet-per-second", - "Feet-per-minute", - "Miles-per-hour", - "Cubic-feet", - "Cubic-meters", - "Imperial-gallons", - "Liters", - "Us-gallons", - "Cubic-feet-per-minute", - "Cubic-meters-per-second", - "Imperial-gallons-per-minute", - "Liters-per-second", - "Liters-per-minute", - "Us-gallons-per-minute", - "Degrees-angular", - "Degrees-Celsius-per-hour", - "Degrees-Celsius-per-minute", - "Degrees-Fahrenheit-per-hour", - "Degrees-Fahrenheit-per-minute", - "No-units", - "Parts-per-million", - "Parts-per-billion", - "Percent", - "Percent-per-second", - "Per-minute", - "Per-second", - "Psi-per-Degree-Fahrenheit", - "Radians", - "Revolutions-per-minute", - "Currency1", - "Currency2", - "Currency3", - "Currency4", - "Currency5", - "Currency6", - "Currency7", - "Currency8", - "Currency9", - "Currency10", - "Square-inches", - "Square-centimeters", - "BTUs-per-pound", - "Centimeters", - "Pounds-mass-per-second", - "Delta-Degrees-Fahrenheit", - "Delta-Degrees-Kelvin", - "Kilohms", - "Megohms", - "Millivolts", - "Kilojoules-per-kilogram", - "Megajoules", - "Joules-per-degree-Kelvin", - "Joules-per-kilogram-degree-Kelvin", - "Kilohertz", - "Megahertz", - "Per-hour", - "Milliwatts", - "Hectopascals", - "Millibars", - "Cubic-meters-per-hour", - "Liters-per-hour", - "Kilowatt-hours-per-square-meter", - "Kilowatt-hours-per-square-foot", - "Megajoules-per-square-meter", - "Megajoules-per-square-foot", - "Watts-per-square-meter-Degree-Kelvin", - "Cubic-feet-per-second", - "Percent-obscuration-per-foot", - "Percent-obscuration-per-meter", - "Milliohms", - "Megawatt-hours", - "Kilo-BTUs", - "Mega-BTUs", - "Kilojoules-per-kilogram-dry-air", - "Megajoules-per-kilogram-dry-air", - "Kilojoules-per-degree-Kelvin", - "Megajoules-per-degree-Kelvin", - "Newton", - "Grams-per-second", - "Grams-per-minute", - "Tons-per-hour", - "Kilo-BTUs-per-hour", - "Hundredths-seconds", - "Milliseconds", - "Newton-meters", - "Millimeters-per-second", - "Millimeters-per-minute", - "Meters-per-minute", - "Meters-per-hour", - "Cubic-meters-per-minute", - "Meters-per-second-per-second", - "Amperes-per-meter", - "Amperes-per-square-meter", - "Ampere-square-meters", - "Farads", - "Henrys", - "Ohm-meters", - "Siemens", - "Siemens-per-meter", - "Teslas", - "Volts-per-degree-Kelvin", - "Volts-per-meter", - "Webers", - "Candelas", - "Candelas-per-square-meter", - "Kelvins-per-hour", - "Kelvins-per-minute", - "Joule-seconds", - "Square-meters-per-Newton", - "Kilogram-per-cubic-meter", - "Newton-seconds", - "Newtons-per-meter", - "Watts-per-meter-per-degree-Kelvin" - ] -} diff --git a/subset/bacnet/bacnetTests/gradle/wrapper/gradle-wrapper.properties b/subset/bacnet/bacnetTests/gradle/wrapper/gradle-wrapper.properties index 622ab64a3c..bb8b2fc26b 100644 --- a/subset/bacnet/bacnetTests/gradle/wrapper/gradle-wrapper.properties +++ b/subset/bacnet/bacnetTests/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/subset/cloud/Dockerfile.test_udmi b/subset/cloud/Dockerfile.test_udmi index 220bd01ba0..e0e78a3a13 100644 --- a/subset/cloud/Dockerfile.test_udmi +++ b/subset/cloud/Dockerfile.test_udmi @@ -9,11 +9,13 @@ FROM daqf/aardvark:latest RUN $AG update && $AG install openjdk-11-jre RUN $AG update && $AG install openjdk-11-jdk git -COPY validator/ validator/ +COPY udmi/validator/ validator/ RUN validator/bin/build -COPY schemas/udmi/ schemas/udmi/ +COPY udmi/schema/ schema/ COPY subset/cloud/test_udmi . +COPY resources/test_site/ local/ + CMD ./test_udmi diff --git a/subset/cloud/test_udmi b/subset/cloud/test_udmi index 4b0cfb2a32..2edaaf82ac 100755 --- a/subset/cloud/test_udmi +++ b/subset/cloud/test_udmi @@ -1,4 +1,5 @@ #!/bin/bash -e + source reporting.sh REPORT=/tmp/report.txt @@ -14,7 +15,8 @@ ip addr gcp_cred=/config/inst/gcp_service_account.json gcp_topic=target -schema_path=schemas/udmi +schema_path=schema +subscription=daq-validator-dev message_types="state pointset system" device_id=`jq -r .device_id /config/device/module_config.json` @@ -55,15 +57,14 @@ echo Using credentials from $GOOGLE_APPLICATION_CREDENTIALS echo Extracted project $project_id echo Extracted service $service_id echo Configured topic is $gcp_topic -echo Configured schema is $schema_path echo Target device is $device_id echo -timeout 60 validator/bin/validate $PWD/$schema_path pubsub:$gcp_topic $service_id-$HOSTNAME || true +timeout 90 validator/bin/validate $project_id $schema_path pubsub $subscription local/ || true function message_report { message_type=$1 - base=validations/devices/$device_id/$message_type + base=out/devices/$device_id/$message_type ls -l $base* || true if [ -f "$base.out" ]; then @@ -87,3 +88,7 @@ function message_report { for message_type in $message_types; do message_report $message_type done + +fgrep RESULT $REPORT + +echo Done with test_udmi diff --git a/subset/connection/mac_oui/build.gradle b/subset/connection/mac_oui/build.gradle index 476315bb29..0f0dc95fe6 100644 --- a/subset/connection/mac_oui/build.gradle +++ b/subset/connection/mac_oui/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath "com.github.jengelman.gradle.plugins:shadow:5.2.0" + classpath "com.github.jengelman.gradle.plugins:shadow:6.0.0" } } diff --git a/subset/connection/mac_oui/gradle/wrapper/gradle-wrapper.properties b/subset/connection/mac_oui/gradle/wrapper/gradle-wrapper.properties index 38c1d48d19..8db0d0d953 100644 --- a/subset/connection/mac_oui/gradle/wrapper/gradle-wrapper.properties +++ b/subset/connection/mac_oui/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip diff --git a/subset/network/NTPClient/gradle/wrapper/gradle-wrapper.properties b/subset/network/NTPClient/gradle/wrapper/gradle-wrapper.properties index 622ab64a3c..bb8b2fc26b 100644 --- a/subset/network/NTPClient/gradle/wrapper/gradle-wrapper.properties +++ b/subset/network/NTPClient/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/subset/network/network_tests.py b/subset/network/network_tests.py index 6dbaca3f85..d785debc67 100644 --- a/subset/network/network_tests.py +++ b/subset/network/network_tests.py @@ -1,5 +1,8 @@ import subprocess, time, sys, json +import re +import datetime + arguments = sys.argv test_request = str(arguments[1]) @@ -24,13 +27,18 @@ description_communication_type = 'Device sends unicast or broadcast packets.' description_ntp_support = 'Device sends NTP request packets.' -tcpdump_display_all_packets = 'tcpdump -n src host ' + device_address + ' -r ' + cap_pcap_file +tcpdump_display_all_packets = 'tcpdump -tttt -n src host ' + device_address + ' -r ' + cap_pcap_file tcpdump_display_udp_bacnet_packets = 'tcpdump -n udp dst portrange 47808-47809 -r ' + cap_pcap_file -tcpdump_display_arp_packets = 'tcpdump arp -r ' + cap_pcap_file +tcpdump_display_arp_packets = 'tcpdump arp -n src host ' + device_address + ' -r ' + cap_pcap_file tcpdump_display_ntp_packets = 'tcpdump dst port 123 -r ' + cap_pcap_file tcpdump_display_eapol_packets = 'tcpdump port 1812 or port 1813 or port 3799 -r ' + cap_pcap_file tcpdump_display_broadcast_packets = 'tcpdump broadcast and src host ' + device_address + ' -r ' + cap_pcap_file +system_conf_file = "/config/inst/system.conf" +tcpdump_date_format = "%Y-%m-%d %H:%M:%S.%f" +min_send_seconds = 300 +min_send_duration = "5 minutes" + def write_report(string_to_append): print(string_to_append.strip()) with open(report_filename, 'a+') as file_open: @@ -49,7 +57,7 @@ def add_packet_count_to_report(packet_type, packet_count): write_report("{i} {t} Packets recieved={p}\n".format(i=ignore, t=packet_type, p=packet_count)) def add_packet_info_to_report(packets_received): - packet_list = packets_received.rstrip().split("\n") + packet_list = packets_received.strip().split("\n") outnum = min(len(packet_list), max_packets_in_report) for x in range(0, outnum): write_report("{i} {p}\n".format(i=ignore, p=packet_list[x])) @@ -99,19 +107,95 @@ def decode_json_config(config_file, map_name, action): elif action == 'remove': remove_from_port_list(port_map) + +def get_scan_length(config_file): + """ Gets length of the monitor.pcap scan + + Reads the system.conf file to and returns the length of the monitor_scan + + Args: + config_file: Location of system.conf file within test container + + Returns: + Length of monitor scan in seconds + + If not defined, or system.conf could not be found + returns false + """ + + scan_length = False + try: + with open(config_file) as file: + for line in file: + match = re.search(r'^monitor_scan_sec=(\d+)', line) + if match: + matched_length = int(match.group(1)) + # If scan length = 0 or not found, then monitor scan does not exist + scan_length = matched_length if matched_length > 0 else False + return scan_length + except Exception as e: + write_report("Error encountered reading system.conf {}".format(e)) + return False + def test_connection_min_send(): + """ Runs the connection.min_send test + + Tests if the device sends data packets of any type (inc data, NTP, etc) + within a period of 5 minutes by looking through the monitor.pcap file + + The length of test can be configured using the min_send_seconds variable + at the start of the file + """ + + # Get scan length + scan_length = get_scan_length(system_conf_file) + min_send_delta = datetime.timedelta(seconds=min_send_seconds) + min_send_pass = False + + # The test scans the monitor.pcap, so if it's not found skip + if not scan_length: + add_summary("DAQ monitor scan not running, test skipped") + return 'skip' + arp_shell_result = shell_command_with_result(tcpdump_display_arp_packets, 0, False) arp_packets_received = packets_received_count(arp_shell_result) if arp_packets_received > 0: add_summary("ARP packets received.") + shell_result = shell_command_with_result(tcpdump_display_all_packets, 0, False) - all_packets_received = packets_received_count(shell_result) - app_packets_received = all_packets_received - arp_packets_received - if app_packets_received > 0: - add_summary("Other packets received.") - print('min_send_packets', arp_packets_received, all_packets_received) + all_packets = shell_result.splitlines() + + # Loop through tcpdump result and measure the time between succesive packets + for i, packet in enumerate(all_packets): + # datetime is the first 26 characters of the line + packet_time = datetime.datetime.strptime(packet[:26], tcpdump_date_format) + + if i == 0: + previous_packet_time = packet_time + continue + + delta = packet_time - previous_packet_time + if delta < min_send_delta: + min_send_pass = True + break + + previous_packet_time = packet_time + add_packet_info_to_report(shell_result) - return 'pass' if app_packets_received > 0 else 'fail' + + if not min_send_pass: + if scan_length > min_send_seconds: + add_summary('Data packets were not sent at a frequency less than ' + + min_send_duration) + return 'fail' + else: + add_summary('Please set DAQ monitor scan to be greater than ' + + min_send_duration) + return 'skip' + + add_summary('Data packets were sent at a frequency of less than ' + + min_send_duration) + return 'pass' def test_connection_dhcp_long(): shell_result = shell_command_with_result(tcpdump_display_arp_packets, 0, False) diff --git a/subset/ntp/Dockerfile.test_ntp b/subset/ntp/Dockerfile.test_ntp new file mode 100644 index 0000000000..017828d203 --- /dev/null +++ b/subset/ntp/Dockerfile.test_ntp @@ -0,0 +1,10 @@ +FROM daqf/aardvark:latest + +RUN $AG update && $AG install python python-setuptools python-pip netcat + +RUN pip install scapy + +COPY subset/ntp/test_ntp . +COPY subset/ntp/ntp_tests.py . + +CMD ["./test_ntp"] diff --git a/validator/.idea/codeStyles/codeStyleConfig.xml b/subset/ntp/NTPClient/.idea/codeStyles/codeStyleConfig.xml similarity index 100% rename from validator/.idea/codeStyles/codeStyleConfig.xml rename to subset/ntp/NTPClient/.idea/codeStyles/codeStyleConfig.xml diff --git a/validator/.idea/gradle.xml b/subset/ntp/NTPClient/.idea/gradle.xml similarity index 84% rename from validator/.idea/gradle.xml rename to subset/ntp/NTPClient/.idea/gradle.xml index 854749173b..5c0b931b2c 100644 --- a/validator/.idea/gradle.xml +++ b/subset/ntp/NTPClient/.idea/gradle.xml @@ -6,13 +6,12 @@ - diff --git a/validator/.idea/jarRepositories.xml b/subset/ntp/NTPClient/.idea/jarRepositories.xml similarity index 81% rename from validator/.idea/jarRepositories.xml rename to subset/ntp/NTPClient/.idea/jarRepositories.xml index f5a0c5d630..fdc392fe87 100644 --- a/validator/.idea/jarRepositories.xml +++ b/subset/ntp/NTPClient/.idea/jarRepositories.xml @@ -16,10 +16,5 @@