Loading charts/platform-core/meep-virt-engine/values.yaml +1 −0 Changes for charts/platform-core/meep-virt-engine/values.yaml: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ image: MEEP_NEM_URL: "" MEEP_NEM_TIMEOUT_MS: "3000" MEEP_NEM_ACTIVATE_TIMEOUT_MS: "180000" MEEP_SIMU5G_HOST_AGENT_URL: "" envSecret: service: Loading go-apps/meepctl/cmd/delete.go +1 −0 Changes for go-apps/meepctl/cmd/delete.go: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -107,6 +107,7 @@ func deleteRun(cmd *cobra.Command, args []string) { } else { deleteApps(deleteData.coreApps, cmd) } deleteNwSimulatorSidecars(cmd) case "dep": if targetApp != "" { deleteSingleDepApp(targetApp, cmd) Loading go-apps/meepctl/cmd/deploy.go +157 −32 Changes for go-apps/meepctl/cmd/deploy.go: 157 added lines, 32 removed lines. Original line number Diff line number Diff line Loading @@ -267,6 +267,7 @@ func deployCoreRun(cmd *cobra.Command, args []string) { start := time.Now() deploySetup(cmd) syncNwSimulatorSidecars(cmd) for _, target := range targets { if target == "all" { Loading Loading @@ -1198,17 +1199,94 @@ func getItemList(target string) string { } const nemProxyListenPort = "18787" const hostAgentListenPort = "8790" const nwSimHostAgentName = "meep-nw-sim-host-agent" func nwSimulatorType() string { t := strings.ToLower(strings.TrimSpace(utils.RepoCfg.GetString("repo.nw_simulator.type"))) if t == "" { return "internal" } return t } func nwSimulatorExternal() bool { t := nwSimulatorType() return t == "simu5g" || t == "oai" } func hostAgentURL() string { u := strings.TrimRight(utils.RepoCfg.GetString("repo.nw_simulator.host-agent-url"), "/") if u != "" { return u } if nodeIP := viper.GetString("node.ip"); nodeIP != "" { return "http://" + nodeIP + ":" + hostAgentListenPort } return "" } func operatorHomeDir() string { if h, err := homedir.Dir(); err == nil && strings.TrimSpace(h) != "" { return h } return "/home/ubuntu-template" } // syncNwSimulatorSidecars applies or removes hostNetwork sidecars for // simu5g/oai even when Helm core apps are skipped (already deployed). func syncNwSimulatorSidecars(cobraCmd *cobra.Command) { if !nwSimulatorExternal() { deleteNwSimulatorSidecars(cobraCmd) return } nemUrl := utils.RepoCfg.GetString("repo.nw_simulator.nem-url") if nemUrl != "" { if err := deployNemHostProxy(nemUrl, cobraCmd); err != nil { fmt.Println(utils.FormatWarning("NEM host proxy: " + err.Error())) } } if err := deployNwSimHostAgent(cobraCmd); err != nil { fmt.Println(utils.FormatWarning("nw-sim host agent: " + err.Error())) return } fmt.Println(utils.FormatStep("Deployed " + nwSimHostAgentName + " (simu5g/oai host TUN + adapters)")) } func deleteNwSimulatorSidecars(cobraCmd *cobra.Command) { for _, name := range []string{nwSimHostAgentName, "meep-nem-proxy"} { cmd := exec.Command("kubectl", "delete", "deploy", name, "-n", "default", "--ignore-not-found=true") _, _ = utils.ExecuteCmd(cmd, cobraCmd) } } func applyK8sManifest(prefix, manifest string, cobraCmd *cobra.Command) error { tmp, err := os.CreateTemp("", prefix+"-*.yaml") if err != nil { return err } path := tmp.Name() defer func() { _ = os.Remove(path) }() if _, err := tmp.WriteString(manifest); err != nil { _ = tmp.Close() return err } if err := tmp.Close(); err != nil { return err } cmd := exec.Command("kubectl", "apply", "-f", path) _, err = utils.ExecuteCmd(cmd, cobraCmd) return err } // setNwSimulatorHelmFlags copies repo.nw_simulator from .meepctl-repocfg.yaml // into core app env (MEEP_NW_SIMULATOR_TYPE, MEEP_NEM_URL, MEEP_NEM_TIMEOUT_MS, // MEEP_NEM_ACTIVATE_TIMEOUT_MS). Overlay pods cannot reach the radio-host NEM // on the node LAN, so simu5g/oai listing and instance lifecycle go through a // hostNetwork proxy on node.ip:18787 (same pattern as meep-auth-svc). // MEEP_NEM_ACTIVATE_TIMEOUT_MS, MEEP_SIMU5G_HOST_AGENT_URL). Overlay pods cannot // reach the radio-host NEM on the node LAN, so simu5g/oai listing and instance // lifecycle go through a hostNetwork proxy on node.ip:18787. func setNwSimulatorHelmFlags(flags [][]string, cobraCmd *cobra.Command) [][]string { nwSimType := utils.RepoCfg.GetString("repo.nw_simulator.type") if nwSimType == "" { nwSimType = "internal" } _ = cobraCmd nwSimType := nwSimulatorType() nemUrl := utils.RepoCfg.GetString("repo.nw_simulator.nem-url") timeoutMs := utils.RepoCfg.GetInt("repo.nw_simulator.timeout-ms") if timeoutMs <= 0 { Loading @@ -1218,22 +1296,17 @@ func setNwSimulatorHelmFlags(flags [][]string, cobraCmd *cobra.Command) [][]stri if activateTimeoutMs <= 0 { activateTimeoutMs = 180000 } if (nwSimType == "simu5g" || nwSimType == "oai") && nemUrl != "" { if nwSimulatorExternal() && nemUrl != "" { if nodeIP := viper.GetString("node.ip"); nodeIP != "" { if err := deployNemHostProxy(nemUrl, cobraCmd); err != nil { fmt.Println(utils.FormatWarning("NEM host proxy: " + err.Error())) } else { nemUrl = "http://" + nodeIP + ":" + nemProxyListenPort } } } flags = utils.HelmFlags(flags, "--set", "image.env.MEEP_NW_SIMULATOR_TYPE="+nwSimType) // --set-string keeps http://host:port from being parsed as a Helm nested map. flags = utils.HelmFlags(flags, "--set-string", "image.env.MEEP_NEM_URL="+nemUrl) flags = utils.HelmFlags(flags, "--set", "image.env.MEEP_NEM_TIMEOUT_MS="+strconv.Itoa(timeoutMs)) flags = utils.HelmFlags(flags, "--set", "image.env.MEEP_NEM_ACTIVATE_TIMEOUT_MS="+strconv.Itoa(activateTimeoutMs)) hostAgent := strings.TrimRight(utils.RepoCfg.GetString("repo.nw_simulator.host-agent-url"), "/") if hostAgent != "" { if hostAgent := hostAgentURL(); hostAgent != "" { flags = utils.HelmFlags(flags, "--set-string", "image.env.MEEP_SIMU5G_HOST_AGENT_URL="+hostAgent) } return flags Loading Loading @@ -1280,27 +1353,79 @@ spec: - operator: Exists `, nemProxyListenPort, backend, nemProxyListenPort, nemProxyListenPort) tmp, err := os.CreateTemp("", "meep-nem-proxy-*.yaml") if err != nil { return err } path := tmp.Name() defer func() { _ = os.Remove(path) }() if _, err := tmp.WriteString(manifest); err != nil { _ = tmp.Close() return err } if err := tmp.Close(); err != nil { return err } // Replace a previous one-off Pod of the same name, if present. del := exec.Command("kubectl", "delete", "pod", "meep-nem-proxy", "--ignore-not-found") _, _ = utils.ExecuteCmd(del, cobraCmd) return applyK8sManifest("meep-nem-proxy", manifest, cobraCmd) } cmd := exec.Command("kubectl", "apply", "-f", path) _, err = utils.ExecuteCmd(cmd, cobraCmd) return err func deployNwSimHostAgent(cobraCmd *cobra.Command) error { gitdir := strings.TrimSuffix(deployData.gitdir, "/") if gitdir == "" { gitdir = strings.TrimSuffix(viper.GetString("meep.gitdir"), "/") } if gitdir == "" { return fmt.Errorf("meep.gitdir is empty") } script := gitdir + "/tools/simu5g/simu5g_runner.py" registry := deployData.registry if registry == "" { registry = strings.TrimSuffix(viper.GetString("meep.registry"), "/") } if registry == "" { registry = "meep-docker-registry:30001" } tag := deployData.tag if tag == "" { tag = "latest" } image := registry + "/meep-sandbox-ctrl:" + tag home := operatorHomeDir() kubeconfig := home + "/.kube/config" nemUrl := strings.TrimRight(utils.RepoCfg.GetString("repo.nw_simulator.nem-url"), "/") if nemUrl == "" { nemUrl = "http://172.29.10.20:8787" } manifest := fmt.Sprintf(`apiVersion: apps/v1 kind: Deployment metadata: name: %s namespace: default labels: app: %s spec: replicas: 1 selector: matchLabels: app: %s template: metadata: labels: app: %s spec: hostNetwork: true hostPID: true dnsPolicy: ClusterFirstWithHostNet containers: - name: host-agent image: %s imagePullPolicy: IfNotPresent securityContext: privileged: true env: - name: HOME value: %q - name: KUBECONFIG value: %q - name: PYTHONUNBUFFERED value: "1" command: ["nsenter", "-t", "1", "-m", "-u", "-i", "-n", "-p", "-C", "--", "python3", %q, "serve", "--watch", "-n", "*", "--nem-url", %q] tolerations: - operator: Exists `, nwSimHostAgentName, nwSimHostAgentName, nwSimHostAgentName, nwSimHostAgentName, image, home, kubeconfig, script, nemUrl) return applyK8sManifest("meep-nw-sim-host-agent", manifest, cobraCmd) } func getProgressBar(current, total int) string { Loading tools/simu5g/simu5g_activate.py +47 −13 Changes for tools/simu5g/simu5g_activate.py: 47 added lines, 13 removed lines. Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ one-shot privileged hostNetwork Job that nsenter's into the host. from __future__ import annotations import copy import json import os import subprocess Loading Loading @@ -471,28 +472,60 @@ def deactivate(args): run_via_kubectl_job(args.namespace, "deactivate", config_file=cfg_path) def watching_all(namespace): return str(namespace or "").strip().lower() in ("*", "all") def list_sandbox_ids(): """Sandbox namespaces from meep-sandbox-ctrl Deployments, plus sbx* NS.""" ids = [] r = kubectl( "get", "deploy", "-A", "-l", "app=meep-sandbox-ctrl", "-o", r'jsonpath={range .items[*]}{.metadata.namespace}{"\n"}{end}', ) for line in (r.stdout or "").splitlines(): ns = line.strip() if ns and ns not in ids: ids.append(ns) r = kubectl("get", "ns", "-o", "jsonpath={.items[*].metadata.name}") for ns in (r.stdout or "").split(): if ns.startswith("sbx") and ns not in ids: ids.append(ns) return ids def watch_loop(args): started = set() if watching_all(args.namespace): _log(f"watching NEM {args.nem_url} for all sandboxes") else: _log(f"watching NEM {args.nem_url} for sandbox {args.namespace}") while True: inst = fetch_nem_instance(args.nem_url, args.namespace) ids = list_sandbox_ids() if watching_all(args.namespace) else [args.namespace] for sid in list(started): if sid not in ids: ids.append(sid) for sid in ids: one = copy.copy(args) one.namespace = sid one.force = False inst = fetch_nem_instance(args.nem_url, sid) ready = instance_ready(inst) if ready and args.namespace not in started: _log("NEM READY — starting TUN + mobility + RNIS") if ready and sid not in started: _log(f"NEM READY sandbox={sid} — starting TUN + mobility + RNIS") try: activate(args) started.add(args.namespace) activate(one) started.add(sid) except SystemExit as exc: _log(f"activate failed: {exc}") _log(f"activate failed sandbox={sid}: {exc}") time.sleep(max(args.interval, 15.0)) continue elif not ready and args.namespace in started: _log(f"NEM {inst.get('state')} — stopping host adapters") elif not ready and sid in started: _log(f"NEM {inst.get('state')} sandbox={sid} — stopping host adapters") try: deactivate(args) deactivate(one) except SystemExit as exc: _log(f"deactivate failed: {exc}") started.discard(args.namespace) _log(f"deactivate failed sandbox={sid}: {exc}") started.discard(sid) time.sleep(args.interval) Loading Loading @@ -563,7 +596,8 @@ def add_activate_parsers(subparsers): p.add_argument( "-n", "--namespace", default=os.environ.get("SANDBOX_NS", "sbx4lesbpo"), help="Sandbox / NEM instance id (Kubernetes namespace).", help="Sandbox / NEM instance id (Kubernetes namespace). " "Use '*' with serve --watch to cover every sandbox.", ) p.add_argument( "--config-file", Loading tools/simu5g/test_simu5g_runner.py +8 −0 Changes for tools/simu5g/test_simu5g_runner.py: 8 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -118,6 +118,14 @@ class TestMergeNem(unittest.TestCase): self.assertEqual(tun, "s5gbr2") self.assertTrue(path.endswith(".json")) def test_watching_all(self): import simu5g_activate as act self.assertTrue(act.watching_all("*")) self.assertTrue(act.watching_all("all")) self.assertTrue(act.watching_all("ALL")) self.assertFalse(act.watching_all("sbxnsptfga")) self.assertFalse(act.watching_all("")) if __name__ == "__main__": unittest.main() Loading
charts/platform-core/meep-virt-engine/values.yaml +1 −0 Changes for charts/platform-core/meep-virt-engine/values.yaml: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ image: MEEP_NEM_URL: "" MEEP_NEM_TIMEOUT_MS: "3000" MEEP_NEM_ACTIVATE_TIMEOUT_MS: "180000" MEEP_SIMU5G_HOST_AGENT_URL: "" envSecret: service: Loading
go-apps/meepctl/cmd/delete.go +1 −0 Changes for go-apps/meepctl/cmd/delete.go: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -107,6 +107,7 @@ func deleteRun(cmd *cobra.Command, args []string) { } else { deleteApps(deleteData.coreApps, cmd) } deleteNwSimulatorSidecars(cmd) case "dep": if targetApp != "" { deleteSingleDepApp(targetApp, cmd) Loading
go-apps/meepctl/cmd/deploy.go +157 −32 Changes for go-apps/meepctl/cmd/deploy.go: 157 added lines, 32 removed lines. Original line number Diff line number Diff line Loading @@ -267,6 +267,7 @@ func deployCoreRun(cmd *cobra.Command, args []string) { start := time.Now() deploySetup(cmd) syncNwSimulatorSidecars(cmd) for _, target := range targets { if target == "all" { Loading Loading @@ -1198,17 +1199,94 @@ func getItemList(target string) string { } const nemProxyListenPort = "18787" const hostAgentListenPort = "8790" const nwSimHostAgentName = "meep-nw-sim-host-agent" func nwSimulatorType() string { t := strings.ToLower(strings.TrimSpace(utils.RepoCfg.GetString("repo.nw_simulator.type"))) if t == "" { return "internal" } return t } func nwSimulatorExternal() bool { t := nwSimulatorType() return t == "simu5g" || t == "oai" } func hostAgentURL() string { u := strings.TrimRight(utils.RepoCfg.GetString("repo.nw_simulator.host-agent-url"), "/") if u != "" { return u } if nodeIP := viper.GetString("node.ip"); nodeIP != "" { return "http://" + nodeIP + ":" + hostAgentListenPort } return "" } func operatorHomeDir() string { if h, err := homedir.Dir(); err == nil && strings.TrimSpace(h) != "" { return h } return "/home/ubuntu-template" } // syncNwSimulatorSidecars applies or removes hostNetwork sidecars for // simu5g/oai even when Helm core apps are skipped (already deployed). func syncNwSimulatorSidecars(cobraCmd *cobra.Command) { if !nwSimulatorExternal() { deleteNwSimulatorSidecars(cobraCmd) return } nemUrl := utils.RepoCfg.GetString("repo.nw_simulator.nem-url") if nemUrl != "" { if err := deployNemHostProxy(nemUrl, cobraCmd); err != nil { fmt.Println(utils.FormatWarning("NEM host proxy: " + err.Error())) } } if err := deployNwSimHostAgent(cobraCmd); err != nil { fmt.Println(utils.FormatWarning("nw-sim host agent: " + err.Error())) return } fmt.Println(utils.FormatStep("Deployed " + nwSimHostAgentName + " (simu5g/oai host TUN + adapters)")) } func deleteNwSimulatorSidecars(cobraCmd *cobra.Command) { for _, name := range []string{nwSimHostAgentName, "meep-nem-proxy"} { cmd := exec.Command("kubectl", "delete", "deploy", name, "-n", "default", "--ignore-not-found=true") _, _ = utils.ExecuteCmd(cmd, cobraCmd) } } func applyK8sManifest(prefix, manifest string, cobraCmd *cobra.Command) error { tmp, err := os.CreateTemp("", prefix+"-*.yaml") if err != nil { return err } path := tmp.Name() defer func() { _ = os.Remove(path) }() if _, err := tmp.WriteString(manifest); err != nil { _ = tmp.Close() return err } if err := tmp.Close(); err != nil { return err } cmd := exec.Command("kubectl", "apply", "-f", path) _, err = utils.ExecuteCmd(cmd, cobraCmd) return err } // setNwSimulatorHelmFlags copies repo.nw_simulator from .meepctl-repocfg.yaml // into core app env (MEEP_NW_SIMULATOR_TYPE, MEEP_NEM_URL, MEEP_NEM_TIMEOUT_MS, // MEEP_NEM_ACTIVATE_TIMEOUT_MS). Overlay pods cannot reach the radio-host NEM // on the node LAN, so simu5g/oai listing and instance lifecycle go through a // hostNetwork proxy on node.ip:18787 (same pattern as meep-auth-svc). // MEEP_NEM_ACTIVATE_TIMEOUT_MS, MEEP_SIMU5G_HOST_AGENT_URL). Overlay pods cannot // reach the radio-host NEM on the node LAN, so simu5g/oai listing and instance // lifecycle go through a hostNetwork proxy on node.ip:18787. func setNwSimulatorHelmFlags(flags [][]string, cobraCmd *cobra.Command) [][]string { nwSimType := utils.RepoCfg.GetString("repo.nw_simulator.type") if nwSimType == "" { nwSimType = "internal" } _ = cobraCmd nwSimType := nwSimulatorType() nemUrl := utils.RepoCfg.GetString("repo.nw_simulator.nem-url") timeoutMs := utils.RepoCfg.GetInt("repo.nw_simulator.timeout-ms") if timeoutMs <= 0 { Loading @@ -1218,22 +1296,17 @@ func setNwSimulatorHelmFlags(flags [][]string, cobraCmd *cobra.Command) [][]stri if activateTimeoutMs <= 0 { activateTimeoutMs = 180000 } if (nwSimType == "simu5g" || nwSimType == "oai") && nemUrl != "" { if nwSimulatorExternal() && nemUrl != "" { if nodeIP := viper.GetString("node.ip"); nodeIP != "" { if err := deployNemHostProxy(nemUrl, cobraCmd); err != nil { fmt.Println(utils.FormatWarning("NEM host proxy: " + err.Error())) } else { nemUrl = "http://" + nodeIP + ":" + nemProxyListenPort } } } flags = utils.HelmFlags(flags, "--set", "image.env.MEEP_NW_SIMULATOR_TYPE="+nwSimType) // --set-string keeps http://host:port from being parsed as a Helm nested map. flags = utils.HelmFlags(flags, "--set-string", "image.env.MEEP_NEM_URL="+nemUrl) flags = utils.HelmFlags(flags, "--set", "image.env.MEEP_NEM_TIMEOUT_MS="+strconv.Itoa(timeoutMs)) flags = utils.HelmFlags(flags, "--set", "image.env.MEEP_NEM_ACTIVATE_TIMEOUT_MS="+strconv.Itoa(activateTimeoutMs)) hostAgent := strings.TrimRight(utils.RepoCfg.GetString("repo.nw_simulator.host-agent-url"), "/") if hostAgent != "" { if hostAgent := hostAgentURL(); hostAgent != "" { flags = utils.HelmFlags(flags, "--set-string", "image.env.MEEP_SIMU5G_HOST_AGENT_URL="+hostAgent) } return flags Loading Loading @@ -1280,27 +1353,79 @@ spec: - operator: Exists `, nemProxyListenPort, backend, nemProxyListenPort, nemProxyListenPort) tmp, err := os.CreateTemp("", "meep-nem-proxy-*.yaml") if err != nil { return err } path := tmp.Name() defer func() { _ = os.Remove(path) }() if _, err := tmp.WriteString(manifest); err != nil { _ = tmp.Close() return err } if err := tmp.Close(); err != nil { return err } // Replace a previous one-off Pod of the same name, if present. del := exec.Command("kubectl", "delete", "pod", "meep-nem-proxy", "--ignore-not-found") _, _ = utils.ExecuteCmd(del, cobraCmd) return applyK8sManifest("meep-nem-proxy", manifest, cobraCmd) } cmd := exec.Command("kubectl", "apply", "-f", path) _, err = utils.ExecuteCmd(cmd, cobraCmd) return err func deployNwSimHostAgent(cobraCmd *cobra.Command) error { gitdir := strings.TrimSuffix(deployData.gitdir, "/") if gitdir == "" { gitdir = strings.TrimSuffix(viper.GetString("meep.gitdir"), "/") } if gitdir == "" { return fmt.Errorf("meep.gitdir is empty") } script := gitdir + "/tools/simu5g/simu5g_runner.py" registry := deployData.registry if registry == "" { registry = strings.TrimSuffix(viper.GetString("meep.registry"), "/") } if registry == "" { registry = "meep-docker-registry:30001" } tag := deployData.tag if tag == "" { tag = "latest" } image := registry + "/meep-sandbox-ctrl:" + tag home := operatorHomeDir() kubeconfig := home + "/.kube/config" nemUrl := strings.TrimRight(utils.RepoCfg.GetString("repo.nw_simulator.nem-url"), "/") if nemUrl == "" { nemUrl = "http://172.29.10.20:8787" } manifest := fmt.Sprintf(`apiVersion: apps/v1 kind: Deployment metadata: name: %s namespace: default labels: app: %s spec: replicas: 1 selector: matchLabels: app: %s template: metadata: labels: app: %s spec: hostNetwork: true hostPID: true dnsPolicy: ClusterFirstWithHostNet containers: - name: host-agent image: %s imagePullPolicy: IfNotPresent securityContext: privileged: true env: - name: HOME value: %q - name: KUBECONFIG value: %q - name: PYTHONUNBUFFERED value: "1" command: ["nsenter", "-t", "1", "-m", "-u", "-i", "-n", "-p", "-C", "--", "python3", %q, "serve", "--watch", "-n", "*", "--nem-url", %q] tolerations: - operator: Exists `, nwSimHostAgentName, nwSimHostAgentName, nwSimHostAgentName, nwSimHostAgentName, image, home, kubeconfig, script, nemUrl) return applyK8sManifest("meep-nw-sim-host-agent", manifest, cobraCmd) } func getProgressBar(current, total int) string { Loading
tools/simu5g/simu5g_activate.py +47 −13 Changes for tools/simu5g/simu5g_activate.py: 47 added lines, 13 removed lines. Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ one-shot privileged hostNetwork Job that nsenter's into the host. from __future__ import annotations import copy import json import os import subprocess Loading Loading @@ -471,28 +472,60 @@ def deactivate(args): run_via_kubectl_job(args.namespace, "deactivate", config_file=cfg_path) def watching_all(namespace): return str(namespace or "").strip().lower() in ("*", "all") def list_sandbox_ids(): """Sandbox namespaces from meep-sandbox-ctrl Deployments, plus sbx* NS.""" ids = [] r = kubectl( "get", "deploy", "-A", "-l", "app=meep-sandbox-ctrl", "-o", r'jsonpath={range .items[*]}{.metadata.namespace}{"\n"}{end}', ) for line in (r.stdout or "").splitlines(): ns = line.strip() if ns and ns not in ids: ids.append(ns) r = kubectl("get", "ns", "-o", "jsonpath={.items[*].metadata.name}") for ns in (r.stdout or "").split(): if ns.startswith("sbx") and ns not in ids: ids.append(ns) return ids def watch_loop(args): started = set() if watching_all(args.namespace): _log(f"watching NEM {args.nem_url} for all sandboxes") else: _log(f"watching NEM {args.nem_url} for sandbox {args.namespace}") while True: inst = fetch_nem_instance(args.nem_url, args.namespace) ids = list_sandbox_ids() if watching_all(args.namespace) else [args.namespace] for sid in list(started): if sid not in ids: ids.append(sid) for sid in ids: one = copy.copy(args) one.namespace = sid one.force = False inst = fetch_nem_instance(args.nem_url, sid) ready = instance_ready(inst) if ready and args.namespace not in started: _log("NEM READY — starting TUN + mobility + RNIS") if ready and sid not in started: _log(f"NEM READY sandbox={sid} — starting TUN + mobility + RNIS") try: activate(args) started.add(args.namespace) activate(one) started.add(sid) except SystemExit as exc: _log(f"activate failed: {exc}") _log(f"activate failed sandbox={sid}: {exc}") time.sleep(max(args.interval, 15.0)) continue elif not ready and args.namespace in started: _log(f"NEM {inst.get('state')} — stopping host adapters") elif not ready and sid in started: _log(f"NEM {inst.get('state')} sandbox={sid} — stopping host adapters") try: deactivate(args) deactivate(one) except SystemExit as exc: _log(f"deactivate failed: {exc}") started.discard(args.namespace) _log(f"deactivate failed sandbox={sid}: {exc}") started.discard(sid) time.sleep(args.interval) Loading Loading @@ -563,7 +596,8 @@ def add_activate_parsers(subparsers): p.add_argument( "-n", "--namespace", default=os.environ.get("SANDBOX_NS", "sbx4lesbpo"), help="Sandbox / NEM instance id (Kubernetes namespace).", help="Sandbox / NEM instance id (Kubernetes namespace). " "Use '*' with serve --watch to cover every sandbox.", ) p.add_argument( "--config-file", Loading
tools/simu5g/test_simu5g_runner.py +8 −0 Changes for tools/simu5g/test_simu5g_runner.py: 8 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -118,6 +118,14 @@ class TestMergeNem(unittest.TestCase): self.assertEqual(tun, "s5gbr2") self.assertTrue(path.endswith(".json")) def test_watching_all(self): import simu5g_activate as act self.assertTrue(act.watching_all("*")) self.assertTrue(act.watching_all("all")) self.assertTrue(act.watching_all("ALL")) self.assertFalse(act.watching_all("sbxnsptfga")) self.assertFalse(act.watching_all("")) if __name__ == "__main__": unittest.main()