]> ruderich.org/simon Gitweb - linux-network-namespace-labs/linux-network-namespace-labs.git/commitdiff
Add "down" command to remove an existing lab
authorSimon Ruderich <simon@ruderich.org>
Mon, 4 Nov 2024 08:03:55 +0000 (09:03 +0100)
committerSimon Ruderich <simon@ruderich.org>
Mon, 4 Nov 2024 08:03:55 +0000 (09:03 +0100)
main.go
setup.go

diff --git a/main.go b/main.go
index 9ca00ad9b67d901e6798e8c0a984f97b09f89307..700afd920b1e81a3ccdb1e31f034ad484e55d024 100644 (file)
--- a/main.go
+++ b/main.go
@@ -39,6 +39,13 @@ func main() {
                cfg := loadConfig()
                mustUp(cfg)
 
+       case "down":
+               if len(os.Args) != 3 {
+                       log.Fatalf("invalid arguments; expected: \"down\" <config>")
+               }
+               cfg := loadConfig()
+               mustDown(cfg)
+
        case "dot":
                // Write dot file showing the network architecture
                if len(os.Args) != 4 {
index 7d17520fabac52952a75aeb81613263eb0a6a85b..80b3276efabc2dc5b8d39800ba1971f3c7fe562e 100644 (file)
--- a/setup.go
+++ b/setup.go
@@ -26,15 +26,7 @@ func mustUp(cfg *Config) {
                ns := node.Name
                if netnsExists(ns) {
                        // Terminate processes in old namespaces
-                       for _, x := range netnsPids(ns) {
-                               log.Printf("  Killing old PID %d", x)
-                               err := syscall.Kill(x, syscall.SIGTERM)
-                               if err != nil {
-                                       log.Fatalf("failed to kill %d: %v", x, err)
-                               }
-                               // Also try SIGHUP to terminate shells which ignore SIGTERM
-                               _ = syscall.Kill(x, syscall.SIGHUP)
-                       }
+                       netnsKillPids(ns)
                        // Prevent any conflicts with existing data
                        ip("netns", "del", ns)
                        // Don't remove anything in /etc/netns/ as the user might store
@@ -43,10 +35,9 @@ func mustUp(cfg *Config) {
                ip("netns", "add", ns)
 
                // Write /etc/netns/$netns/hosts with all known hosts
-               nsCfgPath := filepath.Join("/etc/netns", ns)
-               nsHostsPath := filepath.Join(nsCfgPath, "hosts")
+               nsHostsPath := netnsHostsPath(ns)
                log.Printf("  Writing %q", nsHostsPath)
-               err := os.MkdirAll(nsCfgPath, 0755)
+               err := os.MkdirAll(netnsCfgPath(ns), 0755)
                if err != nil {
                        log.Fatal(err)
                }
@@ -117,6 +108,33 @@ func mustUp(cfg *Config) {
        }
 }
 
+func mustDown(cfg *Config) {
+       for _, node := range cfg.Nodes {
+               log.Printf("Removing node %q ...", node.Name)
+
+               ns := node.Name
+               if !netnsExists(ns) {
+                       log.Printf("  netns doesn't exist, skipping cleanup")
+                       continue
+               }
+
+               netnsKillPids(ns)
+               ip("netns", "del", ns)
+
+               // Delete files we created in /etc/netns/. Keep the rest as the user
+               // might store configuration there!
+               nsHostsPath := netnsHostsPath(ns)
+               log.Printf("  Removing %q (including parent directory if empty)",
+                       nsHostsPath)
+               err := os.Remove(nsHostsPath)
+               if err != nil && !os.IsNotExist(err) {
+                       log.Fatal(err)
+               }
+               // Ignore error as /etc/netns/<ns>/ might not be empty
+               _ = os.Remove(netnsCfgPath(ns))
+       }
+}
+
 func ip(args ...string) {
        xargs := append([]string{"ip"}, args...)
        log.Printf("  Running %q", xargs)
@@ -167,6 +185,26 @@ func netnsPids(netns string) []int {
        return res
 }
 
+func netnsKillPids(netns string) {
+       for _, x := range netnsPids(netns) {
+               log.Printf("  Killing old PID %d", x)
+               err := syscall.Kill(x, syscall.SIGTERM)
+               if err != nil {
+                       log.Fatalf("failed to kill %d: %v", x, err)
+               }
+               // Also try SIGHUP to terminate shells which ignore SIGTERM
+               _ = syscall.Kill(x, syscall.SIGHUP)
+       }
+}
+
+func netnsCfgPath(netns string) string {
+       return filepath.Join("/etc/netns", netns)
+}
+
+func netnsHostsPath(netns string) string {
+       return filepath.Join(netnsCfgPath(netns), "hosts")
+}
+
 func ifaceExists(netns, name string) bool {
        args := []string{"-n", netns, "-json", "link"}
        xargs := append([]string{"ip"}, args...)