diff --git a/Dockerfile.bordercontrol b/Dockerfile.bordercontrol index c3eafea8..4105b836 100644 --- a/Dockerfile.bordercontrol +++ b/Dockerfile.bordercontrol @@ -1,4 +1,4 @@ -FROM golang:1.21.4-bookworm AS builder +FROM golang:1.21.5-bookworm AS builder COPY / /src/pw-bordercontrol @@ -8,7 +8,7 @@ RUN go mod tidy && \ go build ./... && \ go install ./... -FROM debian:bookworm-20231030-slim +FROM debian:bookworm-20231120-slim ARG S6_OVERLAY_VERSION=3.1.6.0 diff --git a/Dockerfile.feeder b/Dockerfile.feeder index 0bf28f43..72b9f3c8 100644 --- a/Dockerfile.feeder +++ b/Dockerfile.feeder @@ -1,6 +1,6 @@ FROM ghcr.io/plane-watch/pw-pipeline:pw_ingest as pipeline -FROM debian:bookworm-20231030-slim +FROM debian:bookworm-20231120-slim ARG S6_OVERLAY_VERSION=3.1.6.0 @@ -16,42 +16,11 @@ RUN set -x && \ KEPT_PACKAGES+=(procps) && \ KEPT_PACKAGES+=(iproute2) && \ KEPT_PACKAGES+=(xz-utils) && \ - # packages needed to build - TEMP_PACKAGES+=(build-essential) && \ - TEMP_PACKAGES+=(cmake) && \ - TEMP_PACKAGES+=(pkg-config) && \ - # prerequisites for readsb-protobuf \ - KEPT_PACKAGES+=(protobuf-c-compiler) && \ - KEPT_PACKAGES+=(libprotobuf-c1) && \ - TEMP_PACKAGES+=(libprotobuf-c-dev) && \ - TEMP_PACKAGES+=(librrd-dev) && \ - KEPT_PACKAGES+=(libncurses6) && \ - TEMP_PACKAGES+=(libncurses5-dev) && \ - TEMP_PACKAGES+=(binutils) && \ apt-get update && \ apt-get install -y --no-install-recommends \ "${KEPT_PACKAGES[@]}" \ "${TEMP_PACKAGES[@]}" \ && \ - # install mictronics readsb - BRANCH_READSB="dev" && \ - # readsb: clone repo - git clone \ - --branch "$BRANCH_READSB" \ - --depth 1 \ - --single-branch \ - 'https://github.com/Mictronics/readsb-protobuf.git' \ - /src/readsb-protobuf \ - && \ - # readsb: build & install (note, -j seems to have issues, so not using...) - pushd /src/readsb-protobuf && \ - make BLADERF=no RTLSDR=no PLUTOSDR=no HAVE_BIASTEE=no && \ - find "/src/readsb-protobuf" -maxdepth 1 -executable -type f -exec cp -v {} /usr/local/bin/ \; && \ - popd && \ - ldconfig && \ - # readsb: simple tests - readsb --version && \ - viewadsb --version && \ # deploy healthchecks framework git clone \ --depth=1 \ @@ -81,7 +50,13 @@ RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64.tar.xz ENV S6_LOGGING=0 \ S6_VERBOSITY=1 +# Set defaults +ENV PW_INGEST_INPUT_MODE=listen \ + PW_INGEST_INPUT_PROTO=beast \ + PW_INGEST_INPUT_ADDR=0.0.0.0 \ + PW_INGEST_INPUT_PORT=12345 + # Set s6 init as entrypoint ENTRYPOINT [ "/init" ] -HEALTHCHECK --interval=60s --timeout=10s --start-period=300s --retries=5 CMD /scripts/healthcheck.sh +HEALTHCHECK --interval=300s --timeout=40s --start-period=600s --retries=5 CMD /scripts/healthcheck.sh diff --git a/Dockerfile.mux b/Dockerfile.mux index 3b0b5c5f..b657f975 100644 --- a/Dockerfile.mux +++ b/Dockerfile.mux @@ -1,4 +1,6 @@ -FROM debian:bookworm-20231030-slim +FROM ghcr.io/plane-watch/pw-pipeline:pw_ingest as pipeline + +FROM debian:bookworm-20231120-slim ARG S6_OVERLAY_VERSION=3.1.6.0 @@ -87,6 +89,7 @@ RUN set -x && \ apt-get autoremove -y && \ rm -rf /src/* /tmp/* /var/lib/apt/lists/* +COPY --from=pipeline /app/pw_ingest /usr/local/bin/pw_ingest COPY pw-mux/rootfs/ / # Deploy s6 overlay diff --git a/docker-compose.yml b/docker-compose.yml index 6def4410..138d49b6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,12 +15,7 @@ x-mux-common: &mux-common networks: - bordercontrol_feeder environment: - - READSB_NET_BEAST_OUTPUT_PORT=30005 - - READSB_NET_BEAST_REDUCE_OUT_PORT=30015 - - READSB_NET_BEAST_REDUCE_INTERVAL=0.5 - - READSB_NET_BEAST_INPUT_PORT=12345 - - READSB_NET_ENABLE=true - - READSB_NET_ONLY=true + - PW_INGEST_SINK=${PW_INGEST_SINK} tmpfs: - /run:exec,size=64M - /var/log @@ -55,6 +50,7 @@ services: - 12345:12345 # BEAST - 12346:12346 # MLAT + # feed-in image builder feed-in-builder: container_name: feed-in-builder build: @@ -63,98 +59,74 @@ services: image: feed-in entrypoint: /bin/true - # Multiplexer: Australia ACT + # MLAT: Australia ACT mux-act: container_name: mux-act hostname: mux-act <<: *mux-common - ports: - - 12601:30015 - # Multiplexer: Australia NSW + # MLAT: Australia NSW mux-nsw: container_name: mux-nsw hostname: mux-nsw <<: *mux-common - ports: - - 12001:30015 - # Multiplexer: Australia NT + # MLAT: Australia NT mux-nt: container_name: mux-nt hostname: mux-nt <<: *mux-common - ports: - - 10801:30015 - # Multiplexer: QLD + # MLAT: QLD mux-qld: container_name: mux-qld hostname: mux-qld <<: *mux-common - ports: - - 14001:30015 - # Multiplexer: SA + # MLAT: SA mux-sa: container_name: mux-sa hostname: mux-sa <<: *mux-common - ports: - - 15001:30015 - # Multiplexer: TAS + # MLAT: TAS mux-tas: container_name: mux-tas hostname: mux-tas <<: *mux-common - ports: - - 17001:30015 - # Multiplexer: VIC + # MLAT: VIC mux-vic: container_name: mux-vic hostname: mux-vic <<: *mux-common - ports: - - 13001:30015 - # Multiplexer: WA + # MLAT: WA mux-wa: container_name: mux-wa hostname: mux-wa <<: *mux-common - ports: - - 16001:30015 - # Multiplexer: NZ + # MLAT: NZ mux-nz: container_name: mux-nz hostname: mux-nz <<: *mux-common - ports: - - 19001:30015 - # Multiplexer: EU + # MLAT: EU mux-eu: container_name: mux-eu hostname: mux-eu <<: *mux-common - ports: - - 22001:30015 - # Multiplexer: USA + # MLAT: USA mux-us: container_name: mux-us hostname: mux-us <<: *mux-common - ports: - - 23001:30015 - # Multiplexer: ASIA + # MLAT: ASIA mux-asia: container_name: mux-asia hostname: mux-asia <<: *mux-common - ports: - - 24001:30015 diff --git a/pw-bordercontrol/cmd/bordercontrol/containers.go b/pw-bordercontrol/cmd/bordercontrol/containers.go index b2329b24..d767992a 100644 --- a/pw-bordercontrol/cmd/bordercontrol/containers.go +++ b/pw-bordercontrol/cmd/bordercontrol/containers.go @@ -184,6 +184,7 @@ func startFeederContainers( Str("label", string(containerToStart.clientDetails.label)). Str("uuid", string(containerToStart.clientDetails.clientApiKey.String())). Str("src", string(containerToStart.srcIP.String())). + Str("code", string(containerToStart.clientDetails.feederCode)). Logger() // determine if container is already running @@ -222,13 +223,12 @@ func startFeederContainers( fmt.Sprintf("FEEDER_LAT=%f", containerToStart.clientDetails.refLat), fmt.Sprintf("FEEDER_LON=%f", containerToStart.clientDetails.refLon), fmt.Sprintf("FEEDER_UUID=%s", containerToStart.clientDetails.clientApiKey.String()), - // "READSB_STATS_EVERY=300", - "READSB_NET_ENABLE=true", - "READSB_NET_BEAST_INPUT_PORT=12345", - "READSB_NET_BEAST_OUTPUT_PORT=30005", - "READSB_NET_ONLY=true", - fmt.Sprintf("READSB_NET_CONNECTOR=%s,12345,beast_out", containerToStart.clientDetails.mux), + fmt.Sprintf("FEEDER_TAG=%s", containerToStart.clientDetails.feederCode), "PW_INGEST_PUBLISH=location-updates", + "PW_INGEST_INPUT_MODE=listen", + "PW_INGEST_INPUT_PROTO=beast", + "PW_INGEST_INPUT_ADDR=0.0.0.0", + "PW_INGEST_INPUT_PORT=12345", fmt.Sprintf("PW_INGEST_SINK=%s", pwIngestPublish), } diff --git a/pw-bordercontrol/cmd/bordercontrol/containers_test.go b/pw-bordercontrol/cmd/bordercontrol/containers_test.go index 4cefdfd0..da193dd4 100644 --- a/pw-bordercontrol/cmd/bordercontrol/containers_test.go +++ b/pw-bordercontrol/cmd/bordercontrol/containers_test.go @@ -32,6 +32,7 @@ const ( TestFeederLatitude = 123.456789 TestFeederLongitude = 98.765432 TestFeederMux = "test-mux" + TestFeederCode = "ABCD-1234" TestPWIngestSink = "nats://pw-ingest-sink:12345" ) @@ -39,12 +40,6 @@ const ( func TestContainersWithKill(t *testing.T) { var ( - ContainerEnvVarFeederLatOK bool - ContainerEnvVarFeederLonOK bool - ContainerEnvVarFeederUUIDOK bool - ContainerEnvVarFeederReadsbNetConnectorOK bool - ContainerEnvVarFeederPWIngestSinkOK bool - ContainerNetworkOK bool ) @@ -124,7 +119,8 @@ func TestContainersWithKill(t *testing.T) { refLat: TestFeederLatitude, refLon: TestFeederLongitude, mux: TestFeederMux, - label: TestFeederMux, + label: TestFeederLabel, + feederCode: TestFeederCode, }, srcIP: net.IPv4(127, 0, 0, 1), } @@ -143,25 +139,21 @@ func TestContainersWithKill(t *testing.T) { // check environment variables t.Log("checking container environment variables") + envVars := make(map[string]string) for _, e := range ct.Config.Env { - switch e { - case fmt.Sprintf("FEEDER_LAT=%f", TestFeederLatitude): - ContainerEnvVarFeederLatOK = true - case fmt.Sprintf("FEEDER_LON=%f", TestFeederLongitude): - ContainerEnvVarFeederLonOK = true - case fmt.Sprintf("FEEDER_UUID=%s", strings.ToLower(TestFeederAPIKey)): - ContainerEnvVarFeederUUIDOK = true - case fmt.Sprintf("READSB_NET_CONNECTOR=%s,12345,beast_out", TestFeederMux): - ContainerEnvVarFeederReadsbNetConnectorOK = true - case fmt.Sprintf("PW_INGEST_SINK=%s", TestPWIngestSink): - ContainerEnvVarFeederPWIngestSinkOK = true - } + envVars[strings.Split(e, "=")[0]] = strings.Split(e, "=")[1] } - assert.True(t, ContainerEnvVarFeederLatOK) - assert.True(t, ContainerEnvVarFeederLonOK) - assert.True(t, ContainerEnvVarFeederUUIDOK) - assert.True(t, ContainerEnvVarFeederReadsbNetConnectorOK) - assert.True(t, ContainerEnvVarFeederPWIngestSinkOK) + + assert.Equal(t, fmt.Sprintf("%f", TestFeederLatitude), envVars["FEEDER_LAT"]) + assert.Equal(t, fmt.Sprintf("%f", TestFeederLongitude), envVars["FEEDER_LON"]) + assert.Equal(t, strings.ToLower(fmt.Sprintf("%s", TestFeederAPIKey)), envVars["FEEDER_UUID"]) + assert.Equal(t, TestFeederCode, envVars["FEEDER_TAG"]) + assert.Equal(t, TestPWIngestSink, envVars["PW_INGEST_SINK"]) + assert.Equal(t, "location-updates", envVars["PW_INGEST_PUBLISH"]) + assert.Equal(t, "listen", envVars["PW_INGEST_INPUT_MODE"]) + assert.Equal(t, "beast", envVars["PW_INGEST_INPUT_PROTO"]) + assert.Equal(t, "0.0.0.0", envVars["PW_INGEST_INPUT_ADDR"]) + assert.Equal(t, "12345", envVars["PW_INGEST_INPUT_PORT"]) // check container autoremove set to true t.Log("check container autoremove set to true") diff --git a/pw-bordercontrol/cmd/bordercontrol/feeder_conn.go b/pw-bordercontrol/cmd/bordercontrol/feeder_conn.go index 887e6e16..594f3e02 100644 --- a/pw-bordercontrol/cmd/bordercontrol/feeder_conn.go +++ b/pw-bordercontrol/cmd/bordercontrol/feeder_conn.go @@ -32,9 +32,9 @@ type ( // struct to hold feeder client information feederClient struct { - clientApiKey uuid.UUID - refLat, refLon float64 - mux, label string + clientApiKey uuid.UUID + refLat, refLon float64 + mux, label, feederCode string } // struct for proxy goroutines @@ -298,7 +298,10 @@ func authenticateFeeder(connIn net.Conn) (clientDetails *feederClient, err error if err != nil { return clientDetails, err } - log = log.With().Str("uuid", clientDetails.clientApiKey.String()).Logger() + log = log.With(). + Str("uuid", clientDetails.clientApiKey.String()). + Str("code", clientDetails.feederCode). + Logger() // log.Trace().Msg("feeder API key received from SNI") // check valid api key against atc @@ -500,6 +503,7 @@ func proxyClientConnection(connIn net.Conn, connProto string, connNum uint, cont Str("uuid", clientDetails.clientApiKey.String()). Str("mux", clientDetails.mux). Str("label", clientDetails.label). + Str("code", clientDetails.feederCode). Logger() // check number of connections, and drop connection if limit exceeded @@ -519,12 +523,20 @@ func proxyClientConnection(connIn net.Conn, connProto string, connNum uint, cont switch connProto { case protoBeast: - log = log.With().Str("dst", fmt.Sprintf("%s%s", feedInContainerPrefix, clientDetails.clientApiKey.String())).Logger() + log = log.With(). + Str("dst", fmt.Sprintf("%s%s", feedInContainerPrefix, clientDetails.clientApiKey.String())). + Logger() - // start the container - containersToStartRequests <- startContainerRequest{ + // request start of the feed-in container with submission timeout + select { + case containersToStartRequests <- startContainerRequest{ clientDetails: clientDetails, srcIP: remoteIP, + }: + case <-time.After(5 * time.Second): + err := errors.New("5s timeout waiting to submit container start request") + log.Err(err).Msg("could not start feed-in container") + return err } // wait for request to be actioned @@ -597,7 +609,7 @@ func proxyClientConnection(connIn net.Conn, connProto string, connNum uint, cont } // update stats - stats.addConnection(clientDetails.clientApiKey, connIn.RemoteAddr(), connOut.RemoteAddr(), connProto, connNum) + stats.addConnection(clientDetails.clientApiKey, connIn.RemoteAddr(), connOut.RemoteAddr(), connProto, clientDetails.feederCode, connNum) defer stats.delConnection(clientDetails.clientApiKey, connProto, connNum) // method to signal goroutines to exit diff --git a/pw-bordercontrol/cmd/bordercontrol/feeder_meta.go b/pw-bordercontrol/cmd/bordercontrol/feeder_meta.go index ccf4c977..0e628c43 100644 --- a/pw-bordercontrol/cmd/bordercontrol/feeder_meta.go +++ b/pw-bordercontrol/cmd/bordercontrol/feeder_meta.go @@ -47,6 +47,7 @@ func getFeederInfo(f *feederClient) error { f.refLon = v.Longitude f.mux = v.Mux f.label = v.Label + f.feederCode = v.FeederCode found = true break } diff --git a/pw-bordercontrol/cmd/bordercontrol/stats.go b/pw-bordercontrol/cmd/bordercontrol/stats.go index 8d6c8926..c633b46a 100644 --- a/pw-bordercontrol/cmd/bordercontrol/stats.go +++ b/pw-bordercontrol/cmd/bordercontrol/stats.go @@ -29,6 +29,7 @@ type FeederStats struct { Label string // feeder label Lat float64 // feeder lat Lon float64 // feeder lon + Code string // feeder_code // Connection details // string key = protocol (BEAST/MLAT, and in future ACARS/VDLM2 etc) @@ -192,6 +193,7 @@ func (stats *Statistics) setFeederDetails(f *feederClient) { y.Label = f.label y.Lat = f.refLat y.Lon = f.refLon + y.Code = f.feederCode y.TimeUpdated = time.Now() // write stats entry @@ -270,7 +272,7 @@ func (stats *Statistics) delConnection(uuid uuid.UUID, proto string, connNum uin // log.Debug().Msg("finished") } -func (stats *Statistics) addConnection(uuid uuid.UUID, src net.Addr, dst net.Addr, proto string, connNum uint) { +func (stats *Statistics) addConnection(uuid uuid.UUID, src net.Addr, dst net.Addr, proto, code string, connNum uint) { // updates the connected status of a feeder log := log.With(). @@ -279,6 +281,7 @@ func (stats *Statistics) addConnection(uuid uuid.UUID, src net.Addr, dst net.Add Str("src", src.String()). Str("dst", dst.String()). Str("proto", proto). + Str("code", code). Uint("connNum", connNum). Logger() @@ -303,10 +306,11 @@ func (stats *Statistics) addConnection(uuid uuid.UUID, src net.Addr, dst net.Add Name: "feeder_data_in_bytes_total", Help: "Per-feeder bytes received (in)", ConstLabels: prometheus.Labels{ - "protocol": strings.ToLower(proto), - "uuid": uuid.String(), - "label": stats.Feeders[uuid].Label, - "connnum": fmt.Sprintf("%d", connNum), + "protocol": strings.ToLower(proto), + "uuid": uuid.String(), + "label": stats.Feeders[uuid].Label, + "connnum": fmt.Sprintf("%d", connNum), + "feeder_code": code, }}) c.promMetricBytesOut = prometheus.NewCounter(prometheus.CounterOpts{ Namespace: promNamespace, @@ -314,10 +318,11 @@ func (stats *Statistics) addConnection(uuid uuid.UUID, src net.Addr, dst net.Add Name: "feeder_data_out_bytes_total", Help: "Per-feeder bytes sent (out)", ConstLabels: prometheus.Labels{ - "protocol": strings.ToLower(proto), - "uuid": uuid.String(), - "label": stats.Feeders[uuid].Label, - "connnum": fmt.Sprintf("%d", connNum), + "protocol": strings.ToLower(proto), + "uuid": uuid.String(), + "label": stats.Feeders[uuid].Label, + "connnum": fmt.Sprintf("%d", connNum), + "feeder_code": code, }}) err := prometheus.Register(c.promMetricBytesIn) if err != nil { diff --git a/pw-bordercontrol/cmd/bordercontrol/stats.tmpl b/pw-bordercontrol/cmd/bordercontrol/stats.tmpl index e8c6bed2..b265e592 100644 --- a/pw-bordercontrol/cmd/bordercontrol/stats.tmpl +++ b/pw-bordercontrol/cmd/bordercontrol/stats.tmpl @@ -17,6 +17,7 @@ Feeder UUID + Code Proto Conn # Src @@ -30,6 +31,7 @@ {{ $felement.Label }} {{ $index }} + {{ $felement.Code }} {{ $pindex }} {{ $cindex }} {{ $celement.Src }} diff --git a/pw-bordercontrol/cmd/bordercontrol/stats_test.go b/pw-bordercontrol/cmd/bordercontrol/stats_test.go index fbf6889d..411d5cdc 100644 --- a/pw-bordercontrol/cmd/bordercontrol/stats_test.go +++ b/pw-bordercontrol/cmd/bordercontrol/stats_test.go @@ -139,8 +139,8 @@ func TestStats(t *testing.T) { // add some fake feeder connections stats.setFeederDetails(&fc) - stats.addConnection(u, &ip, &ip, protoBeast, 1) - stats.addConnection(u, &ip, &ip, protoMLAT, 2) + stats.addConnection(u, &ip, &ip, protoBeast, "ABCD-1234", 1) + stats.addConnection(u, &ip, &ip, protoMLAT, "ABCD-1234", 2) // check num conns assert.Equal(t, 1, stats.getNumConnections(u, protoBeast)) @@ -165,10 +165,10 @@ func TestStats(t *testing.T) { `pw_bordercontrol_feeders 1`, `pw_bordercontrol_feeders_active{protocol="beast"} 1`, `pw_bordercontrol_feeders_active{protocol="mlat"} 1`, - fmt.Sprintf(`pw_bordercontrol_feeder_data_in_bytes_total{connnum="1",label="%s",protocol="beast",uuid="%s"} 100`, fc.label, fc.clientApiKey), - fmt.Sprintf(`pw_bordercontrol_feeder_data_in_bytes_total{connnum="2",label="%s",protocol="mlat",uuid="%s"} 300`, fc.label, fc.clientApiKey), - fmt.Sprintf(`pw_bordercontrol_feeder_data_out_bytes_total{connnum="1",label="%s",protocol="beast",uuid="%s"} 200`, fc.label, fc.clientApiKey), - fmt.Sprintf(`pw_bordercontrol_feeder_data_out_bytes_total{connnum="2",label="%s",protocol="mlat",uuid="%s"} 400`, fc.label, fc.clientApiKey), + fmt.Sprintf(`pw_bordercontrol_feeder_data_in_bytes_total{connnum="1",feeder_code="ABCD-1234",label="%s",protocol="beast",uuid="%s"} 100`, fc.label, fc.clientApiKey), + fmt.Sprintf(`pw_bordercontrol_feeder_data_in_bytes_total{connnum="2",feeder_code="ABCD-1234",label="%s",protocol="mlat",uuid="%s"} 300`, fc.label, fc.clientApiKey), + fmt.Sprintf(`pw_bordercontrol_feeder_data_out_bytes_total{connnum="1",feeder_code="ABCD-1234",label="%s",protocol="beast",uuid="%s"} 200`, fc.label, fc.clientApiKey), + fmt.Sprintf(`pw_bordercontrol_feeder_data_out_bytes_total{connnum="2",feeder_code="ABCD-1234",label="%s",protocol="mlat",uuid="%s"} 400`, fc.label, fc.clientApiKey), } // tests @@ -185,7 +185,7 @@ func TestStats(t *testing.T) { _ = getMetricsFromTestServer(t, fmt.Sprintf("%s", statsBaseURL)) // add another beast connection - stats.addConnection(u, &ip, &ip, protoBeast, 3) + stats.addConnection(u, &ip, &ip, protoBeast, "ABCD-1234", 3) // remove connections (working) stats.delConnection(u, protoBeast, 1) @@ -225,10 +225,10 @@ func TestStats(t *testing.T) { `pw_bordercontrol_feeders_active{protocol="mlat"} 0`, } notExpectedMetrics := []string{ - fmt.Sprintf(`pw_bordercontrol_feeder_data_in_bytes_total{connnum="1",label="%s",protocol="beast",uuid="%s"}`, fc.label, fc.clientApiKey), - fmt.Sprintf(`pw_bordercontrol_feeder_data_in_bytes_total{connnum="2",label="%s",protocol="mlat",uuid="%s"}`, fc.label, fc.clientApiKey), - fmt.Sprintf(`pw_bordercontrol_feeder_data_out_bytes_total{connnum="1",label="%s",protocol="beast",uuid="%s"}`, fc.label, fc.clientApiKey), - fmt.Sprintf(`pw_bordercontrol_feeder_data_out_bytes_total{connnum="2",label="%s",protocol="mlat",uuid="%s"}`, fc.label, fc.clientApiKey), + fmt.Sprintf(`pw_bordercontrol_feeder_data_in_bytes_total{connnum="1",feeder_code="ABCD-1234",label="%s",protocol="beast",uuid="%s"}`, fc.label, fc.clientApiKey), + fmt.Sprintf(`pw_bordercontrol_feeder_data_in_bytes_total{connnum="2",feeder_code="ABCD-1234",label="%s",protocol="mlat",uuid="%s"}`, fc.label, fc.clientApiKey), + fmt.Sprintf(`pw_bordercontrol_feeder_data_out_bytes_total{connnum="1",feeder_code="ABCD-1234",label="%s",protocol="beast",uuid="%s"}`, fc.label, fc.clientApiKey), + fmt.Sprintf(`pw_bordercontrol_feeder_data_out_bytes_total{connnum="2",feeder_code="ABCD-1234",label="%s",protocol="mlat",uuid="%s"}`, fc.label, fc.clientApiKey), } checkPromMetricsExist(t, body, expectedMetrics) diff --git a/pw-bordercontrol/go.mod b/pw-bordercontrol/go.mod index 9104e119..00102544 100644 --- a/pw-bordercontrol/go.mod +++ b/pw-bordercontrol/go.mod @@ -8,7 +8,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/rs/zerolog v1.31.0 github.com/stretchr/testify v1.8.4 - github.com/urfave/cli/v2 v2.25.7 + github.com/urfave/cli/v2 v2.26.0 ) require ( diff --git a/pw-bordercontrol/lib/atc/api.go b/pw-bordercontrol/lib/atc/api.go index a689fc4f..87a506f2 100644 --- a/pw-bordercontrol/lib/atc/api.go +++ b/pw-bordercontrol/lib/atc/api.go @@ -27,6 +27,7 @@ type ( Feeder struct { // part of schema for /api/v1/feeders.json atc endpoint Altitude float64 `json:",string"` ApiKey uuid.UUID + FeederCode string FeedDirection string FeedProtocol string ID int @@ -38,19 +39,6 @@ type ( User string } - FeederB struct { // schema for /api/v1/feeders/{uuid}.json atc endpoint - Feeder struct { - ApiKey uuid.UUID `json:"api_key"` - Label string `json:"label"` - MlatEnabled bool `json:"mlat_enabled"` - Latitude float64 `json:"latitude,string"` - Longitude float64 `json:"longitude,string"` - Protocol string `json:"protocol"` - Elevation float64 `json:"elevation,string"` - Mux string `json:"mux"` - } `json:"feeder"` - } - atcCredentials struct { // schema for atc credentials Email string `json:"email"` Password string `json:"password"` @@ -105,62 +93,6 @@ func authenticate(server *Server) (authToken string, err error) { return authToken, nil } -func GetFeederInfo(server *Server, feederApiKey uuid.UUID) (refLat float64, refLon float64, mux string, label string, err error) { - - authToken, err := authenticate(server) - if err != nil { - return refLat, refLon, mux, label, err - } - - atcUrl := server.Url.JoinPath(fmt.Sprintf("/api/v1/feeders/%s.json", feederApiKey.String())) - - req, err := http.NewRequest("GET", atcUrl.String(), nil) - if err != nil { - return refLat, refLon, mux, label, err - } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", authToken) - - client := &http.Client{} - response, err := client.Do(req) - if err != nil { - return refLat, refLon, mux, label, err - } - defer response.Body.Close() - - // fmt.Println("response Status:", response.Status) - // fmt.Println("response Headers:", response.Header) - // body, _ := ioutil.ReadAll(response.Body) - // fmt.Println("response Body:", string(body)) - - body, err := io.ReadAll(response.Body) - if err != nil { - return refLat, refLon, mux, label, err - } - - var feeder FeederB - - if response.StatusCode == 200 { - - err := json.Unmarshal(body, &feeder) - if err != nil { - return refLat, refLon, mux, label, err - } - - refLat = feeder.Feeder.Latitude - refLon = feeder.Feeder.Longitude - mux = feeder.Feeder.Mux - label = feeder.Feeder.Label - - } else { - errStr := fmt.Sprintf("ATC API response status: %s", response.Status) - return refLat, refLon, mux, label, errors.New(errStr) - } - - return refLat, refLon, mux, label, err - -} - func GetFeeders(server *Server) (feeders Feeders, err error) { authToken, err := authenticate(server) diff --git a/pw-bordercontrol/lib/atc/api_test.go b/pw-bordercontrol/lib/atc/api_test.go index cac84ddf..e5d0b6f4 100644 --- a/pw-bordercontrol/lib/atc/api_test.go +++ b/pw-bordercontrol/lib/atc/api_test.go @@ -120,12 +120,13 @@ func prepMockATCServer(t *testing.T, testScenario int) *httptest.Server { // mock response resp := fmt.Sprintf( - `{"Feeders":[{"ApiKey":"%s","Label":"%s","Latitude":"%f","Longitude":"%f","Mux":"%s"}]}`, + `{"Feeders":[{"ApiKey":"%s","Label":"%s","Latitude":"%f","Longitude":"%f","Mux":"%s", "FeederCode":"%s"}]}`, TestFeederAPIKeyWorking, TestFeederLabel, TestFeederLatitude, TestFeederLongitude, TestFeederMux, + TestFeederCode, ) // response code @@ -269,74 +270,6 @@ func TestAuthenticate_NoResponse(t *testing.T) { assert.Error(t, err) } -func TestGetFeederInfo_Working(t *testing.T) { - - server := prepMockATCServer(t, MockServerTestScenarioWorking) - defer server.Close() - - // prep url - u, err := url.Parse(server.URL) - assert.NoError(t, err) - - // function argument - s := Server{ - Url: (*u), - Username: TestUser, - Password: TestPassword, - } - - refLat, refLon, mux, label, err := GetFeederInfo(&s, uuid.MustParse(TestFeederAPIKeyWorking)) - assert.NoError(t, err) - assert.Equal(t, TestFeederLatitude, refLat) - assert.Equal(t, TestFeederLongitude, refLon) - assert.Equal(t, TestFeederMux, mux) - assert.Equal(t, TestFeederLabel, label) - -} - -func TestGetFeederInfo_BadResponse(t *testing.T) { - - // prep test server - server := prepMockATCServer(t, MockServerTestScenarioBadResponseCodeFeeder) - defer server.Close() - - // prep url - u, err := url.Parse(server.URL) - assert.NoError(t, err) - - // function argument - s := Server{ - Url: (*u), - Username: TestUser, - Password: TestPassword, - } - - _, _, _, _, err = GetFeederInfo(&s, uuid.MustParse(TestFeederAPIKeyWorking)) - assert.Error(t, err) - -} - -func TestGetFeederInfo_NoResponse(t *testing.T) { - - // prep test server - server := prepMockATCServer(t, MockServerTestScenarioNoResponse) - - // prep url - u, err := url.Parse(server.URL) - assert.NoError(t, err) - - // function argument - s := Server{ - Url: (*u), - Username: TestUser, - Password: TestPassword, - } - - _, _, _, _, err = GetFeederInfo(&s, uuid.MustParse(TestFeederAPIKeyWorking)) - assert.Error(t, err) - -} - func TestGetFeeders_Working(t *testing.T) { server := prepMockATCServer(t, MockServerTestScenarioWorking) @@ -358,11 +291,12 @@ func TestGetFeeders_Working(t *testing.T) { expectedFeeders := Feeders{ []Feeder{{ - ApiKey: uuid.MustParse(TestFeederAPIKeyWorking), - Label: TestFeederLabel, - Latitude: TestFeederLatitude, - Longitude: TestFeederLongitude, - Mux: TestFeederMux, + ApiKey: uuid.MustParse(TestFeederAPIKeyWorking), + Label: TestFeederLabel, + Latitude: TestFeederLatitude, + Longitude: TestFeederLongitude, + Mux: TestFeederMux, + FeederCode: TestFeederCode, }}, } diff --git a/pw-feed-in/README.MD b/pw-feed-in/README.MD new file mode 100644 index 00000000..d5f96bba --- /dev/null +++ b/pw-feed-in/README.MD @@ -0,0 +1,19 @@ +# pw-feed-in # + +a.k.a "feed-in" containers. + +Spawns an instance of `pw_ingest` configured as-per below. + +## Environment Variables ## + +| Variable | Detail | Default | +| -------- | ------ | ------- | +| `FEEDER_LAT` | (Optional) Feeder latitude | *unset* | +| `FEEDER_LON` | (Optional) Feeder longitude | *unset* | +| `FEEDER_TAG` | (Required) Feeder tag | *unset* | +| `PW_INGEST_INPUT_MODE` | Must be set to either `listen` or `fetch` | `listen` | +| `PW_INGEST_INPUT_PROTO` | Must be either `avr`, `beast` or `sbs1` | `beast` | +| `PW_INGEST_INPUT_ADDR` | The IP address to listen on / fetch from | `0.0.0.0` | +| `PW_INGEST_INPUT_PORT` | The TCP port to listen on / fetch from | `12345` | +| `PW_INGEST_SINK` | (Required) The place to send decoded JSON in URL Form, eg `nats://user:pass@host:port/vhost?ttl=60` | *unset* | +| `PW_INGEST_ENABLE_ADSC` | (Optional) Set to `true` to enable ADS-C | `false` | diff --git a/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/run b/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/run index 7d832c26..945fd0d9 100755 --- a/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/run +++ b/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/run @@ -4,11 +4,16 @@ # Set pw_ingest binary PW_INGEST_BIN="/usr/local/bin/pw_ingest" +# Set ADS-C mode +if [[ "${PW_INGEST_ENABLE_ADSC,,}" == "true" ]]; then + PW_INGEST_CMD+=("--ads-c") +fi + # Set feeder tag/uuid -PW_INGEST_CMD=("--tag" "${FEEDER_UUID}") +PW_INGEST_CMD=("--tag" "${FEEDER_TAG}") # Set input -PW_INGEST_CMD+=("--fetch" "beast://127.0.0.1:30005") +PW_INGEST_CMD+=("--${PW_INGEST_INPUT_MODE}" "${PW_INGEST_INPUT_PROTO}://${PW_INGEST_INPUT_ADDR}:${PW_INGEST_INPUT_PORT}") # Set output PW_INGEST_CMD+=("--sink" "${PW_INGEST_SINK}") @@ -27,6 +32,12 @@ fi # simple Gather ADSB data and sends it to the configured output. PW_INGEST_CMD+=("simple") +# show version +fdmove -c 2 1 \ + "${PW_INGEST_BIN}" \ + --version | + awk -W Interactive '{print "[pw_ingest] " $0}' + # shellcheck disable=SC2016 fdmove -c 2 1 \ "${PW_INGEST_BIN}" \ diff --git a/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/readsb/run b/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/readsb/run deleted file mode 100755 index 6d34fa7d..00000000 --- a/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/readsb/run +++ /dev/null @@ -1,341 +0,0 @@ -#!/command/with-contenv bash -#shellcheck shell=bash - -mkdir -p /run/readsb -chmod -R 755 /run/readsb - -# Set readsb binary -READSB_BIN="/usr/local/bin/readsb" - -##### DEFAULT OPTIONS ##### - -# Listen on 0.0.0.0 -READSB_CMD=("--net-bind-address=0.0.0.0") - -# Set quiet mode (TODO: unless verbose?) -READSB_CMD+=("--quiet") - -# TODO: Only do this if webserver is enabled -# Set path for protobuf output files -READSB_CMD+=("--write-output=/run/readsb") - -##### GENERAL OPTIONS ##### - -# Handle "--aggressive" -if [[ -n "$READSB_AGGRESSIVE" ]]; then - READSB_CMD+=("--aggressive") -fi - -# Handle "--dcfilter" -if [[ -n "$READSB_DCFILTER" ]]; then - READSB_CMD+=("--dcfilter") -fi - -# Handle "--device-type" -if [[ -n "$READSB_DEVICE_TYPE" ]]; then - READSB_CMD+=("--device-type=$READSB_DEVICE_TYPE") -fi - -# Handle "--enable-biastee" -if [[ -n "$READSB_ENABLE_BIASTEE" ]]; then - READSB_CMD+=("--enable-biastee") -fi - -# Handle "--fix" -#shellcheck disable=SC2153 -if [[ -n "$READSB_FIX" ]]; then - READSB_CMD+=("--fix") -fi - -# Handle "--forward-mlat" -if [[ -n "$READSB_FORWARD_MLAT" ]]; then - READSB_CMD+=("--forward-mlat") -fi - -# Handle "--freq=" -if [[ -n "$READSB_FREQ" ]]; then - READSB_CMD+=("--freq=$READSB_FREQ") -fi - -# Handle "--gain=" -# TODO - write specified gain to a file in a cont-init.d script, -# so we can change gain using an auto-gain script and tell s6 to restart this service. -# We can then read the gain from the file here. -# If file doesn't exist then go with max gain. -# if [[ -n "$READSB_GAIN" ]]; then -# READSB_CMD+=("--gain=$READSB_GAIN") -# fi -if [[ -e "$GAIN_VALUE_FILE" ]]; then - READSB_CMD+=("--gain=$(cat "$GAIN_VALUE_FILE")") -fi - -# Handle "--gnss" -if [[ -n "$READSB_GNSS" ]]; then - READSB_CMD+=("--gnss") -fi - -# Handle "--lat=" -if [[ -n "$FEEDER_LAT" ]]; then - READSB_CMD+=("--lat=$FEEDER_LAT") -fi - -# Handle "--lon=" -#shellcheck disable=SC2153 -if [[ -n "$FEEDER_LON" ]]; then - READSB_CMD+=("--lon=$FEEDER_LON") -fi - -# Handle "--max-range=" -if [[ -n "$READSB_MAX_RANGE" ]]; then - READSB_CMD+=("--max-range=$READSB_MAX_RANGE") -fi - -# Handle "--metric" -if [[ -n "$READSB_METRIC" ]]; then - READSB_CMD+=("--metric") -fi - -# Handle "--mlat" -if [[ -n "$READSB_MLAT" ]]; then - READSB_CMD+=("--mlat") -fi - -# Handle "--modeac" -if [[ -n "$READSB_MODEAC" ]]; then - READSB_CMD+=("--modeac") -fi - -# Handle "--no-crc-check" -if [[ -n "$READSB_NO_CRC_CHECK" ]]; then - READSB_CMD+=("--no-crc-check") -fi - -# Handle "--no-fix" -if [[ -n "$READSB_NO_FIX" ]]; then - READSB_CMD+=("--no-fix") -fi - -# Handle "--no-modeac-auto" -if [[ -n "$READSB_NO_MODEAC_AUTO" ]]; then - READSB_CMD+=("--no-modeac-auto") -fi - -# Handle "--preamble-threshold=" -if [[ -n "$READSB_PREAMBLE_THRESHOLD" ]]; then - READSB_CMD+=("--preamble-threshold=$READSB_PREAMBLE_THRESHOLD") -fi - -# Handle "--rx-location-accuracy=" -if [[ -n "$READSB_RX_LOCATION_ACCURACY" ]]; then - READSB_CMD+=("--rx-location-accuracy=$READSB_RX_LOCATION_ACCURACY") -fi - -# Handle "--stats-every=" -if [[ -n "$READSB_STATS_EVERY" ]]; then - READSB_CMD+=("--stats-every=$READSB_STATS_EVERY") -fi - -# Handle "--stats-range" -if [[ -n "$READSB_STATS_RANGE" ]]; then - READSB_CMD+=("--stats-range") -fi - -##### NETWORK OPTIONS ##### - -# Handle "--net" -if [[ -n "$READSB_NET_ENABLE" ]]; then - READSB_CMD+=("--net") -fi - -# Handle "--net-beast-reduce-interval=" -if [[ -n "$READSB_NET_BEAST_REDUCE_INTERVAL" ]]; then - READSB_CMD+=("--net-beast-reduce-interval=$READSB_NET_BEAST_REDUCE_INTERVAL") -fi - -# Handle "--net-beast-reduce-out-port=" -if [[ -n "$READSB_NET_BEAST_REDUCE_OUT_PORT" ]]; then - READSB_CMD+=("--net-beast-reduce-out-port=$READSB_NET_BEAST_REDUCE_OUT_PORT") -fi - -# Handle "--net-bi-port=" -if [[ -n "$READSB_NET_BEAST_INPUT_PORT" ]]; then - READSB_CMD+=("--net-bi-port=$READSB_NET_BEAST_INPUT_PORT") -fi - -# Handle "--net-bo-port=" -if [[ -n "$READSB_NET_BEAST_OUTPUT_PORT" ]]; then - READSB_CMD+=("--net-bo-port=$READSB_NET_BEAST_OUTPUT_PORT") -fi - -# Handle "--net-buffer=" -if [[ -n "$READSB_NET_BUFFER" ]]; then - READSB_CMD+=("--net-buffer=$READSB_NET_BUFFER") -fi - -# Handle "--net-connector=" -if [[ -n "$READSB_NET_CONNECTOR" ]]; then - IFS=';' read -r -a READSB_NET_CONNECTOR_ARRAY <<< "$READSB_NET_CONNECTOR" - for NET_CONNECTOR_ELEMENT in "${READSB_NET_CONNECTOR_ARRAY[@]}" - do - READSB_CMD+=("--net-connector=$NET_CONNECTOR_ELEMENT") - done -fi - -# Handle "--net-connector-delay=" -if [[ -n "$READSB_NET_CONNECTOR_DELAY" ]]; then - READSB_CMD+=("--net-connector-delay=$READSB_NET_CONNECTOR_DELAY") -fi - -# Handle "--net-heartbeat=" -if [[ -n "$READSB_NET_HEARTBEAT" ]]; then - READSB_CMD+=("--net-heartbeat=$READSB_NET_HEARTBEAT") -fi - -# Handle "--net-only" -if [[ -n "$READSB_NET_ONLY" ]]; then - READSB_CMD+=("--net-only") -fi - -# Handle "--net-ri-port=" -if [[ -n "$READSB_NET_RAW_INPUT_PORT" ]]; then - READSB_CMD+=("--net-ri-port=$READSB_NET_RAW_INPUT_PORT") -fi - -# Handle "--net-ro-interval=" -if [[ -n "$READSB_NET_RAW_OUTPUT_INTERVAL" ]]; then - READSB_CMD+=("--net-ro-interval=$READSB_NET_RAW_OUTPUT_INTERVAL") -fi - -# Handle "--net-ri-port=" -if [[ -n "$READSB_NET_RAW_OUTPUT_PORT" ]]; then - READSB_CMD+=("--net-ro-port=$READSB_NET_RAW_OUTPUT_PORT") -fi - -# Handle "--net-ro-size=" -if [[ -n "$READSB_NET_RAW_OUTPUT_SIZE" ]]; then - READSB_CMD+=("--net-ro-size=$READSB_NET_RAW_OUTPUT_SIZE") -fi - -# Handle "--net-sbs-in-port=" -if [[ -n "$READSB_NET_SBS_INPUT_PORT" ]]; then - READSB_CMD+=("--net-sbs-in-port=$READSB_NET_SBS_INPUT_PORT") -fi - -# Handle "--net-sbs-port=" -if [[ -n "$READSB_NET_SBS_OUTPUT_PORT" ]]; then - READSB_CMD+=("--net-sbs-port=$READSB_NET_SBS_OUTPUT_PORT") -fi - -# Handle "--net-verbatim" -if [[ -n "$REASSB_NET_VERBATIM" ]]; then - READSB_CMD+=("--net-verbatim") -fi - -# Handle "--net-vrs-port=" -if [[ -n "$READSB_NET_VRS_PORT" ]]; then - READSB_CMD+=("--net-vrs-port=$READSB_NET_VRS_PORT") - -# Telegraf needs the JSON output from readsb, so if this hasn't been enabled by the user, enable it -elif [ -z "$INFLUXDB_SKIP_AIRCRAFT" ] && { [ -n "$INFLUXDBURL" ] || [ -n "$ENABLE_PROMETHEUS" ]; } then - READSB_NET_VRS_PORT="33333" - READSB_CMD+=("--net-vrs-port=$READSB_NET_VRS_PORT") -fi - -##### RTL-SDR OPTIONS ##### - -# Handle "--device=" -if [[ -n "$READSB_RTLSDR_DEVICE" ]]; then - READSB_CMD+=("--device=$READSB_RTLSDR_DEVICE") -fi - -# Handle "--enable-agc" -if [[ -n "$READSB_RTLSDR_ENABLE_AGC" ]]; then - READSB_CMD+=("--enable-agc") -fi - -# Handle "--ppm=" -if [[ -n "$READSB_RTLSDR_PPM" ]]; then - READSB_CMD+=("--ppm=$READSB_RTLSDR_PPM") -fi - -##### BLADERF OPTIONS ##### - -# Handle "--device=" -if [[ -n "$READSB_BLADERF_DEVICE" ]]; then - READSB_CMD+=("--device=$READSB_BLADERF_DEVICE") -fi - -# Handle "--bladerf-bandwidth=" -if [[ -n "$READSB_BLADERF_BANDWIDTH" ]]; then - READSB_CMD+=("--bladerf-bandwidth=$READSB_BLADERF_BANDWIDTH") -fi - -# Handle "--bladerf-decimation=" -if [[ -n "$READSB_BLADERF_DECIMATION" ]]; then - READSB_CMD+=("--bladerf-decimation=$READSB_BLADERF_DECIMATION") -fi - -# Handle "--bladerf-fpga=" -if [[ -n "$READSB_BLADERF_FPGA" ]]; then - READSB_CMD+=("--bladerf-fpga=\"$READSB_BLADERF_FPGA\"") -fi - -##### MODE-S BEAST OPTIONS ##### - -# Handle "--beast-crc-off" -if [[ -n "$READSB_BEAST_CRC_OFF" ]]; then - READSB_CMD+=("--beast-crc-off") -fi - -# Handle "--beast-df045-on" -if [[ -n "$READSB_BEAST_DF045_ON" ]]; then - READSB_CMD+=("--beast-df045-on") -fi - -# Handle "--beast-df1117-on" -if [[ -n "$READSB_BEAST_DF1117_ON" ]]; then - READSB_CMD+=("--beast-df1117-on") -fi - -# Handle "--beast-fec-off" -if [[ -n "$READSB_BEAST_FEC_OFF" ]]; then - READSB_CMD+=("--beast-fec-off") -fi - -# Handle "--beast-mlat-off" -if [[ -n "$READSB_BEAST_MLAT_OFF" ]]; then - READSB_CMD+=("--beast-mlat-off") -fi - -# Handle "--beast-modeac" -if [[ -n "$READSB_BEAST_MODEAC" ]]; then - READSB_CMD+=("--beast-modeac") -fi - -# Handle "--beast-serial=" -if [[ -n "$READSB_BEAST_SERIAL" ]]; then - READSB_CMD+=("--beast-serial=$READSB_BEAST_SERIAL") -fi - -##### ADALM-Pluto SDR OPTIONS ##### - -# Handle "--pluto-network=" -if [[ -n "$READSB_PLUTO_NETWORK" ]]; then - READSB_CMD+=("--pluto-network=$READSB_PLUTO_NETWORK") -fi - -# Handle "--pluto-uri=" -if [[ -n "$READSB_PLUTO_URI" ]]; then - READSB_CMD+=("--pluto-uri=$READSB_PLUTO_URI") -fi - -##### LAUNCH READSB ##### - -set -eo pipefail - -# shellcheck disable=SC2016 -fdmove -c 2 1 \ - "${READSB_BIN}" \ - "${READSB_CMD[@]}" | - sed --unbuffered '/^$/d' | - awk -W Interactive '{print "[readsb] " strftime("%Y/%m/%d %H:%M:%S", systime()) " " $0}' \ No newline at end of file diff --git a/pw-feed-in/rootfs/scripts/healthcheck.sh b/pw-feed-in/rootfs/scripts/healthcheck.sh index 58b5e150..7bfb9cde 100755 --- a/pw-feed-in/rootfs/scripts/healthcheck.sh +++ b/pw-feed-in/rootfs/scripts/healthcheck.sh @@ -1,11 +1,14 @@ #!/usr/bin/env bash # shellcheck shell=bash +# Sleep for random seconds between 1 and 30 +sleep "$((1 + $RANDOM % 30))" + EXITCODE=0 # check beast connection inbound from bordercontrol CONNECTED_BEAST_IN=false -if ss -ntH state established | tr -s " " | cut -d " " -f 3 | grep ":12345" > /dev/null 2>&1; then +if ss -ntH state established | tr -s " " | cut -d " " -f 3 | grep ":${PW_INGEST_INPUT_PORT}" > /dev/null 2>&1; then CONNECTED_BEAST_IN=true echo "CONNECTED_BEAST_IN=true" else @@ -13,16 +16,6 @@ else EXITCODE=1 fi -# check beast connection outbound to mux -CONNECTED_BEAST_OUT=false -if ss -ntH state established | tr -s " " | cut -d " " -f 4 | grep ":12345" > /dev/null 2>&1; then - CONNECTED_BEAST_OUT=true - echo "CONNECTED_BEAST_OUT=true" -else - echo "CONNECTED_BEAST_OUT=false" - EXITCODE=1 -fi - # check nats connection outbound CONNECTED_NATS_OUT=false if ss -ntH state established | tr -s " " | cut -d " " -f 4 | grep ":4222" > /dev/null 2>&1; then @@ -33,6 +26,14 @@ else EXITCODE=1 fi +# check FEEDER_TAG exists +if /command/s6-env bash -c '[[ -n "$FEEDER_TAG" ]]'; then + echo "FEEDER_TAG_VALID=true" +else + echo "FEEDER_TAG_VALID=false" + EXITCODE=1 +fi + # update /run/healthcheck if [ "$(cat /run/healthcheck)" != "$EXITCODE" ]; then echo "$EXITCODE" > /run/healthcheck @@ -41,7 +42,9 @@ fi # if container has been unhealthy for 10mins+ then stop container if [ "$(cat /run/healthcheck)" != "0" ]; then if test "$(find /run/healthcheck -mmin +10)"; then - s6-svscanctl -t /var/run/s6/services + # kill container init, which will stop container + # as container should be started with autoremove, it should be deleted + kill 1 fi fi diff --git a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/mlat-server/run b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/mlat-server/run index b457ac2a..3146f77b 100755 --- a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/mlat-server/run +++ b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/mlat-server/run @@ -19,6 +19,7 @@ mkdir -p /run/mlat-server/workdir fdmove -c 2 1 \ /opt/mlat-server/mlat-server \ --client-listen 0.0.0.0:12346 \ + --basestation-listen 0.0.0.0:30003 \ --motd "plane.watch:${HOSTNAME}" \ --work-dir /run/mlat-server/workdir \ --status-interval 3600 | diff --git a/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/readsb/dependencies.d/base b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/dependencies.d/base similarity index 100% rename from pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/readsb/dependencies.d/base rename to pw-mux/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/dependencies.d/base diff --git a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/run b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/run new file mode 100755 index 00000000..14365645 --- /dev/null +++ b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/run @@ -0,0 +1,43 @@ +#!/command/with-contenv bash +# shellcheck shell=bash + +# Set pw_ingest binary +PW_INGEST_BIN="/usr/local/bin/pw_ingest" + +# Set feeder tag/uuid +PW_INGEST_CMD=("--tag" "mlat-$(hostname)") + +# Set input +PW_INGEST_CMD+=("--fetch" "sbs1://127.0.0.1:30003") + +# Set output +PW_INGEST_CMD+=("--sink" "${PW_INGEST_SINK}") + +# # Set LAT if given +# if [[ -n "${FEEDER_LAT}" ]]; then +# PW_INGEST_CMD+=("--ref-lat" "${FEEDER_LAT}") +# fi + +# # Set LON if given +# if [[ -n "${FEEDER_LON}" ]]; then +# PW_INGEST_CMD+=("--ref-lon" "${FEEDER_LON}") +# fi + +# "simple" mode +# simple Gather ADSB data and sends it to the configured output. +PW_INGEST_CMD+=("simple") + +# show version +fdmove -c 2 1 \ + "${PW_INGEST_BIN}" \ + --version | + awk -W Interactive '{print "[pw_ingest] " $0}' + +# shellcheck disable=SC2016 +fdmove -c 2 1 \ + "${PW_INGEST_BIN}" \ + "${PW_INGEST_CMD[@]}" | + awk -W Interactive '{print "[pw_ingest] " $0}' + +# prevent re-launching too fast +sleep 5 diff --git a/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/readsb/type b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/type similarity index 100% rename from pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/readsb/type rename to pw-mux/rootfs/etc/s6-overlay/s6-rc.d/pw-ingest/type diff --git a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/readsb/dependencies.d/base b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/readsb/dependencies.d/base deleted file mode 100644 index e69de29b..00000000 diff --git a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/readsb/run b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/readsb/run deleted file mode 100755 index 78a89a02..00000000 --- a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/readsb/run +++ /dev/null @@ -1,342 +0,0 @@ -#!/command/with-contenv bash -#shellcheck shell=bash - -mkdir -p /run/readsb -chmod -R 755 /run/readsb - -# Set readsb binary -READSB_BIN="/usr/local/bin/readsb" - -##### DEFAULT OPTIONS ##### - -# Listen on 0.0.0.0 -READSB_CMD=("--net-bind-address=0.0.0.0") - -# Set quiet mode (TODO: unless verbose?) -READSB_CMD+=("--quiet") - -# TODO: Only do this if webserver is enabled -# Set path for protobuf output files -READSB_CMD+=("--write-output=/run/readsb") - -##### GENERAL OPTIONS ##### - -# Handle "--aggressive" -if [[ -n "$READSB_AGGRESSIVE" ]]; then - READSB_CMD+=("--aggressive") -fi - -# Handle "--dcfilter" -if [[ -n "$READSB_DCFILTER" ]]; then - READSB_CMD+=("--dcfilter") -fi - -# Handle "--device-type" -if [[ -n "$READSB_DEVICE_TYPE" ]]; then - READSB_CMD+=("--device-type=$READSB_DEVICE_TYPE") -fi - -# Handle "--enable-biastee" -if [[ -n "$READSB_ENABLE_BIASTEE" ]]; then - READSB_CMD+=("--enable-biastee") -fi - -# Handle "--fix" -#shellcheck disable=SC2153 -if [[ -n "$READSB_FIX" ]]; then - READSB_CMD+=("--fix") -fi - -# Handle "--forward-mlat" -if [[ -n "$READSB_FORWARD_MLAT" ]]; then - READSB_CMD+=("--forward-mlat") -fi - -# Handle "--freq=" -if [[ -n "$READSB_FREQ" ]]; then - READSB_CMD+=("--freq=$READSB_FREQ") -fi - -# Handle "--gain=" -# TODO - write specified gain to a file in a cont-init.d script, -# so we can change gain using an auto-gain script and tell s6 to restart this service. -# We can then read the gain from the file here. -# If file doesn't exist then go with max gain. -# if [[ -n "$READSB_GAIN" ]]; then -# READSB_CMD+=("--gain=$READSB_GAIN") -# fi -if [[ -e "$GAIN_VALUE_FILE" ]]; then - READSB_CMD+=("--gain=$(cat "$GAIN_VALUE_FILE")") -fi - -# Handle "--gnss" -if [[ -n "$READSB_GNSS" ]]; then - READSB_CMD+=("--gnss") -fi - -# Handle "--lat=" -if [[ -n "$FEEDER_LAT" ]]; then - READSB_CMD+=("--lat=$FEEDER_LAT") -fi - -# Handle "--lon=" -#shellcheck disable=SC2153 -if [[ -n "$FEEDER_LON" ]]; then - READSB_CMD+=("--lon=$FEEDER_LON") -fi - -# Handle "--max-range=" -if [[ -n "$READSB_MAX_RANGE" ]]; then - READSB_CMD+=("--max-range=$READSB_MAX_RANGE") -fi - -# Handle "--metric" -if [[ -n "$READSB_METRIC" ]]; then - READSB_CMD+=("--metric") -fi - -# Handle "--mlat" -if [[ -n "$READSB_MLAT" ]]; then - READSB_CMD+=("--mlat") -fi - -# Handle "--modeac" -if [[ -n "$READSB_MODEAC" ]]; then - READSB_CMD+=("--modeac") -fi - -# Handle "--no-crc-check" -if [[ -n "$READSB_NO_CRC_CHECK" ]]; then - READSB_CMD+=("--no-crc-check") -fi - -# Handle "--no-fix" -if [[ -n "$READSB_NO_FIX" ]]; then - READSB_CMD+=("--no-fix") -fi - -# Handle "--no-modeac-auto" -if [[ -n "$READSB_NO_MODEAC_AUTO" ]]; then - READSB_CMD+=("--no-modeac-auto") -fi - -# Handle "--preamble-threshold=" -if [[ -n "$READSB_PREAMBLE_THRESHOLD" ]]; then - READSB_CMD+=("--preamble-threshold=$READSB_PREAMBLE_THRESHOLD") -fi - -# Handle "--rx-location-accuracy=" -if [[ -n "$READSB_RX_LOCATION_ACCURACY" ]]; then - READSB_CMD+=("--rx-location-accuracy=$READSB_RX_LOCATION_ACCURACY") -fi - -# Handle "--stats-every=" -if [[ -n "$READSB_STATS_EVERY" ]]; then - READSB_CMD+=("--stats-every=$READSB_STATS_EVERY") -fi - -# Handle "--stats-range" -if [[ -n "$READSB_STATS_RANGE" ]]; then - READSB_CMD+=("--stats-range") -fi - -##### NETWORK OPTIONS ##### - -# Handle "--net" -if [[ -n "$READSB_NET_ENABLE" ]]; then - READSB_CMD+=("--net") -fi - -# Handle "--net-beast-reduce-interval=" -if [[ -n "$READSB_NET_BEAST_REDUCE_INTERVAL" ]]; then - READSB_CMD+=("--net-beast-reduce-interval=$READSB_NET_BEAST_REDUCE_INTERVAL") -fi - -# Handle "--net-beast-reduce-out-port=" -if [[ -n "$READSB_NET_BEAST_REDUCE_OUT_PORT" ]]; then - READSB_CMD+=("--net-beast-reduce-out-port=$READSB_NET_BEAST_REDUCE_OUT_PORT") -fi - -# Handle "--net-bi-port=" -if [[ -n "$READSB_NET_BEAST_INPUT_PORT" ]]; then - READSB_CMD+=("--net-bi-port=$READSB_NET_BEAST_INPUT_PORT") -fi - -# Handle "--net-bo-port=" -if [[ -n "$READSB_NET_BEAST_OUTPUT_PORT" ]]; then - READSB_CMD+=("--net-bo-port=$READSB_NET_BEAST_OUTPUT_PORT") -fi - -# Handle "--net-buffer=" -if [[ -n "$READSB_NET_BUFFER" ]]; then - READSB_CMD+=("--net-buffer=$READSB_NET_BUFFER") -fi - -# Handle "--net-connector=" -if [[ -n "$READSB_NET_CONNECTOR" ]]; then - IFS=';' read -r -a READSB_NET_CONNECTOR_ARRAY <<< "$READSB_NET_CONNECTOR" - for NET_CONNECTOR_ELEMENT in "${READSB_NET_CONNECTOR_ARRAY[@]}" - do - READSB_CMD+=("--net-connector=$NET_CONNECTOR_ELEMENT") - done -fi - -# Handle "--net-connector-delay=" -if [[ -n "$READSB_NET_CONNECTOR_DELAY" ]]; then - READSB_CMD+=("--net-connector-delay=$READSB_NET_CONNECTOR_DELAY") -fi - -# Handle "--net-heartbeat=" -if [[ -n "$READSB_NET_HEARTBEAT" ]]; then - READSB_CMD+=("--net-heartbeat=$READSB_NET_HEARTBEAT") -fi - -# Handle "--net-only" -if [[ -n "$READSB_NET_ONLY" ]]; then - READSB_CMD+=("--net-only") -fi - -# Handle "--net-ri-port=" -if [[ -n "$READSB_NET_RAW_INPUT_PORT" ]]; then - READSB_CMD+=("--net-ri-port=$READSB_NET_RAW_INPUT_PORT") -fi - -# Handle "--net-ro-interval=" -if [[ -n "$READSB_NET_RAW_OUTPUT_INTERVAL" ]]; then - READSB_CMD+=("--net-ro-interval=$READSB_NET_RAW_OUTPUT_INTERVAL") -fi - -# Handle "--net-ri-port=" -if [[ -n "$READSB_NET_RAW_OUTPUT_PORT" ]]; then - READSB_CMD+=("--net-ro-port=$READSB_NET_RAW_OUTPUT_PORT") -fi - -# Handle "--net-ro-size=" -if [[ -n "$READSB_NET_RAW_OUTPUT_SIZE" ]]; then - READSB_CMD+=("--net-ro-size=$READSB_NET_RAW_OUTPUT_SIZE") -fi - -# Handle "--net-sbs-in-port=" -if [[ -n "$READSB_NET_SBS_INPUT_PORT" ]]; then - READSB_CMD+=("--net-sbs-in-port=$READSB_NET_SBS_INPUT_PORT") -fi - -# Handle "--net-sbs-port=" -if [[ -n "$READSB_NET_SBS_OUTPUT_PORT" ]]; then - READSB_CMD+=("--net-sbs-port=$READSB_NET_SBS_OUTPUT_PORT") -fi - -# Handle "--net-verbatim" -if [[ -n "$REASSB_NET_VERBATIM" ]]; then - READSB_CMD+=("--net-verbatim") -fi - -# Handle "--net-vrs-port=" -if [[ -n "$READSB_NET_VRS_PORT" ]]; then - READSB_CMD+=("--net-vrs-port=$READSB_NET_VRS_PORT") - -# Telegraf needs the JSON output from readsb, so if this hasn't been enabled by the user, enable it -elif [ -z "$INFLUXDB_SKIP_AIRCRAFT" ] && { [ -n "$INFLUXDBURL" ] || [ -n "$ENABLE_PROMETHEUS" ]; } then - READSB_NET_VRS_PORT="33333" - READSB_CMD+=("--net-vrs-port=$READSB_NET_VRS_PORT") -fi - -##### RTL-SDR OPTIONS ##### - -# Handle "--device=" -if [[ -n "$READSB_RTLSDR_DEVICE" ]]; then - READSB_CMD+=("--device=$READSB_RTLSDR_DEVICE") -fi - -# Handle "--enable-agc" -if [[ -n "$READSB_RTLSDR_ENABLE_AGC" ]]; then - READSB_CMD+=("--enable-agc") -fi - -# Handle "--ppm=" -if [[ -n "$READSB_RTLSDR_PPM" ]]; then - READSB_CMD+=("--ppm=$READSB_RTLSDR_PPM") -fi - -##### BLADERF OPTIONS ##### - -# Handle "--device=" -if [[ -n "$READSB_BLADERF_DEVICE" ]]; then - READSB_CMD+=("--device=$READSB_BLADERF_DEVICE") -fi - -# Handle "--bladerf-bandwidth=" -if [[ -n "$READSB_BLADERF_BANDWIDTH" ]]; then - READSB_CMD+=("--bladerf-bandwidth=$READSB_BLADERF_BANDWIDTH") -fi - -# Handle "--bladerf-decimation=" -if [[ -n "$READSB_BLADERF_DECIMATION" ]]; then - READSB_CMD+=("--bladerf-decimation=$READSB_BLADERF_DECIMATION") -fi - -# Handle "--bladerf-fpga=" -if [[ -n "$READSB_BLADERF_FPGA" ]]; then - READSB_CMD+=("--bladerf-fpga=\"$READSB_BLADERF_FPGA\"") -fi - -##### MODE-S BEAST OPTIONS ##### - -# Handle "--beast-crc-off" -if [[ -n "$READSB_BEAST_CRC_OFF" ]]; then - READSB_CMD+=("--beast-crc-off") -fi - -# Handle "--beast-df045-on" -if [[ -n "$READSB_BEAST_DF045_ON" ]]; then - READSB_CMD+=("--beast-df045-on") -fi - -# Handle "--beast-df1117-on" -if [[ -n "$READSB_BEAST_DF1117_ON" ]]; then - READSB_CMD+=("--beast-df1117-on") -fi - -# Handle "--beast-fec-off" -if [[ -n "$READSB_BEAST_FEC_OFF" ]]; then - READSB_CMD+=("--beast-fec-off") -fi - -# Handle "--beast-mlat-off" -if [[ -n "$READSB_BEAST_MLAT_OFF" ]]; then - READSB_CMD+=("--beast-mlat-off") -fi - -# Handle "--beast-modeac" -if [[ -n "$READSB_BEAST_MODEAC" ]]; then - READSB_CMD+=("--beast-modeac") -fi - -# Handle "--beast-serial=" -if [[ -n "$READSB_BEAST_SERIAL" ]]; then - READSB_CMD+=("--beast-serial=$READSB_BEAST_SERIAL") -fi - -##### ADALM-Pluto SDR OPTIONS ##### - -# Handle "--pluto-network=" -if [[ -n "$READSB_PLUTO_NETWORK" ]]; then - READSB_CMD+=("--pluto-network=$READSB_PLUTO_NETWORK") -fi - -# Handle "--pluto-uri=" -if [[ -n "$READSB_PLUTO_URI" ]]; then - READSB_CMD+=("--pluto-uri=$READSB_PLUTO_URI") -fi - -##### LAUNCH READSB ##### - -set -eo pipefail - -fdmove -c 2 1 \ - "${READSB_BIN}" \ - "${READSB_CMD[@]}" | - sed --unbuffered '/^$/d' | - awk -W Interactive '{print "[readsb] " strftime("%Y/%m/%d %H:%M:%S", systime()) " " $0}' - -sleep 5 diff --git a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/readsb/type b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/readsb/type deleted file mode 100644 index 1780f9f4..00000000 --- a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/readsb/type +++ /dev/null @@ -1 +0,0 @@ -longrun \ No newline at end of file diff --git a/pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/readsb b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/pw-ingest similarity index 100% rename from pw-feed-in/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/readsb rename to pw-mux/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/pw-ingest diff --git a/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/readsb b/pw-mux/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/readsb deleted file mode 100644 index e69de29b..00000000