Commit 99a98946 authored by Yann Garcia's avatar Yann Garcia
Browse files

Restore lost fixes

parent 0ef5c10c
Loading
Loading
Loading
Loading
+18 −3
Changes for go-apps/meep-simu5g-mobility-adapter/README.md: 18 added lines, 3 removed lines.
Original line number Diff line number Diff line
# meep-simu5g-mobility-adapter

Runs on **NativeEdge Connector**. Listens for UDP telemetry from **Network Emulation Stack (Simu5G/SimuLTE)** (`UeTelemetryUdpSender`, port 9100) and publishes UE locations to GIS (TODO).
Runs on **NativeEdge Connector**. Listens for UDP telemetry from **Network Emulation Stack (Simu5G/SimuLTE)** (`UeTelemetryUdpSender`, port 9100) and publishes UE locations to `meep-gis-engine` via `POST /gis/v1/geodata/{assetName}`.

GIS asset names are `ue-car-*` / `ue-ped-*` from the companion YAML. The adapter talks to the GIS **ClusterIP** (no ingress session cookie). `--dry-run` skips GIS writes.

monaco-harbor must be **active** in the sandbox UI. NEM running on host S is not enough: GIS returns `No active scenario` until the companion scenario is loaded.

## Run (live, two-host)

Rebuild after pulling code:

```bash
go run . --config /path/to/simu5g-config.json
go build -o bin/meep-simu5g-mobility-adapter ./go-apps/meep-simu5g-mobility-adapter
./bin/meep-simu5g-mobility-adapter --config /home/ubuntu-template/etsi-mec-sandbox/tools/simu5g/monaco-harbor-integration-config.json
```

Configure the Network Emulation Stack to send telemetry to `NativeEdgeConnectorNode:9100`.
Listens on **UDP 9100**. monaco-harbor INI must send to host B (`172.29.10.53:9100`). After each GIS write the adapter GETs `poaInRange` and logs `servingPoa` (wifi > 5g > 4g from monaco names) when the set changes. That is a **logical GIS** attachment, not Simu5G EN-DC / X2 handover (Story 3.4 on host S).

Optional: `--gis-url http://<gis-cluster-ip>/gis/v1` or `--sandbox <ns>` if `gis.sandboxName` in the JSON is wrong.

Parse-only (no GIS writes):

```bash
./bin/meep-simu5g-mobility-adapter --config .../monaco-harbor-integration-config.json --dry-run
```

## Run (offline replay)

+124 −0
Changes for go-apps/meep-simu5g-mobility-adapter/gis_url.go: 124 added lines, 0 removed lines.
Original line number Diff line number Diff line
/*
 * Copyright (c) 2026  The AdvantEDGE Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"bytes"
	"context"
	"fmt"
	"net"
	"os"
	"os/exec"
	"strings"
	"time"

	log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
	bridge "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-simu5g-bridge"
)

func resolveGISBaseURL(cfg *bridge.IntegrationConfig, flagURL, flagSandbox string) (string, error) {
	if u := strings.TrimRight(strings.TrimSpace(flagURL), "/"); u != "" {
		return u, nil
	}
	if u := cfg.GISBaseURL(); u != "" {
		return u, nil
	}
	if u := strings.TrimRight(strings.TrimSpace(os.Getenv("MEEP_GIS_BASE_URL")), "/"); u != "" {
		return u, nil
	}

	sandbox := strings.TrimSpace(flagSandbox)
	if sandbox == "" {
		sandbox = strings.TrimSpace(cfg.GIS.SandboxName)
	}
	if sandbox == "" {
		sandbox = strings.TrimSpace(os.Getenv("MEEP_SANDBOX_NAME"))
	}

	if sandbox != "" {
		if hostResolves("meep-gis-engine." + sandbox + ".svc.cluster.local") {
			return "http://meep-gis-engine." + sandbox + ".svc.cluster.local/gis/v1", nil
		}
		ip, err := kubectlGISClusterIP(sandbox)
		if err != nil {
			return "", fmt.Errorf("cannot reach meep-gis-engine in namespace %s (set gis.baseUrl to http://<clusterIP>/gis/v1): %v", sandbox, err)
		}
		log.Info("GIS ClusterIP for sandbox " + sandbox + " is " + ip)
		return "http://" + ip + "/gis/v1", nil
	}

	ns, ip, err := kubectlDiscoverSingleGIS()
	if err != nil {
		return "", fmt.Errorf("gis.baseUrl or gis.sandboxName required (or --gis-url / --sandbox): %v", err)
	}
	log.Info("discovered GIS Service in sandbox " + ns + " ClusterIP " + ip)
	return "http://" + ip + "/gis/v1", nil
}

func hostResolves(host string) bool {
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()
	var r net.Resolver
	_, err := r.LookupHost(ctx, host)
	return err == nil
}

func kubectlGISClusterIP(namespace string) (string, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)
	defer cancel()
	cmd := exec.CommandContext(ctx, "kubectl", "get", "svc", "meep-gis-engine", "-n", namespace, "-o", "jsonpath={.spec.clusterIP}")
	out, err := cmd.Output()
	if err != nil {
		return "", err
	}
	ip := strings.TrimSpace(string(out))
	if net.ParseIP(ip) == nil {
		return "", fmt.Errorf("invalid ClusterIP %q", ip)
	}
	return ip, nil
}

func kubectlDiscoverSingleGIS() (namespace, clusterIP string, err error) {
	ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)
	defer cancel()
	cmd := exec.CommandContext(ctx, "kubectl", "get", "svc", "-A",
		"--field-selector", "metadata.name=meep-gis-engine",
		"-o", `jsonpath={range .items[*]}{.metadata.namespace}{" "}{.spec.clusterIP}{"\n"}{end}`)
	out, err := cmd.Output()
	if err != nil {
		return "", "", err
	}
	lines := bytes.Split(bytes.TrimSpace(out), []byte("\n"))
	var found [][2]string
	for _, line := range lines {
		f := strings.Fields(string(line))
		if len(f) != 2 {
			continue
		}
		if net.ParseIP(f[1]) == nil {
			continue
		}
		found = append(found, [2]string{f[0], f[1]})
	}
	if len(found) == 0 {
		return "", "", fmt.Errorf("no meep-gis-engine Service found")
	}
	if len(found) > 1 {
		return "", "", fmt.Errorf("multiple GIS engines; set gis.sandboxName")
	}
	return found[0][0], found[0][1], nil
}
+20 −0
Changes for go-apps/meep-simu5g-mobility-adapter/gis_url_test.go: 20 added lines, 0 removed lines.
Original line number Diff line number Diff line
package main

import (
	"testing"

	bridge "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-simu5g-bridge"
)

func TestResolveGISBaseURLFlagOverridesConfig(t *testing.T) {
	cfg := &bridge.IntegrationConfig{
		GIS: bridge.GISOptions{BaseURL: "http://from-config/gis/v1"},
	}
	u, err := resolveGISBaseURL(cfg, "http://from-flag/gis/v1/", "")
	if err != nil {
		t.Fatal(err)
	}
	if u != "http://from-flag/gis/v1" {
		t.Fatalf("got %q", u)
	}
}
+2 −0
Changes for go-apps/meep-simu5g-mobility-adapter/go.mod: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -3,11 +3,13 @@ module github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-simu5g-mobility-adapte
go 1.12

require (
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-gis-engine-client v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger v0.0.0
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-simu5g-bridge v0.0.0
)

replace (
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-gis-engine-client => ../../go-packages/meep-gis-engine-client
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger => ../../go-packages/meep-logger
	github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-simu5g-bridge => ../../go-packages/meep-simu5g-bridge
)
+19 −0
Changes for go-apps/meep-simu5g-mobility-adapter/go.sum: 19 added lines, 0 removed lines.
Original line number Diff line number Diff line
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
Loading