@@ -2,6 +2,7 @@ package network
22
33import (
44 "fmt"
5+ "os"
56 "os/exec"
67 "strings"
78
@@ -47,3 +48,63 @@ func hasNoCarrier(interfaceName string) bool {
4748func isOrphanVMTap (interfaceName string ) bool {
4849 return len (interfaceName ) == 15 && strings .HasPrefix (interfaceName , "t-" )
4950}
51+
52+ // CleanupOrphanedNamespaces removes network namespaces that start with "n-"
53+ // but don't have corresponding files in /var/run/cache/networkd/networks/
54+ func CleanupOrphanedNamespaces () error {
55+ const networksDir = "/var/run/cache/networkd/networks/"
56+
57+ // Get list of files in the networks directory
58+ validNetworkIDs := make (map [string ]bool )
59+ entries , err := os .ReadDir (networksDir )
60+ if err != nil {
61+ return fmt .Errorf ("failed to read networks directory %s: %w" , networksDir , err )
62+ }
63+
64+ for _ , entry := range entries {
65+ if ! entry .IsDir () {
66+ validNetworkIDs [entry .Name ()] = true
67+ }
68+ }
69+
70+ // Get list of network namespaces
71+ cmd := exec .Command ("ip" , "netns" , "list" )
72+ output , err := cmd .CombinedOutput ()
73+ if err != nil {
74+ return fmt .Errorf ("failed to list network namespaces: %w" , err )
75+ }
76+
77+ lines := strings .Split (strings .TrimSpace (string (output )), "\n " )
78+ for _ , line := range lines {
79+ if line == "" {
80+ continue
81+ }
82+
83+ // Parse namespace name (format: "n-EB2AJhw1cGbYf (id: 15)" or just "n-EB2AJhw1cGbYf")
84+ parts := strings .Fields (line )
85+ if len (parts ) == 0 {
86+ continue
87+ }
88+
89+ nsName := parts [0 ]
90+
91+ // Only process namespaces that start with "n-"
92+ if ! strings .HasPrefix (nsName , "n-" ) {
93+ continue
94+ }
95+
96+ // Extract the ID part after "n-"
97+ networkID := strings .TrimPrefix (nsName , "n-" )
98+
99+ // Check if corresponding file exists in networks directory
100+ if ! validNetworkIDs [networkID ] {
101+ // Remove the orphaned namespace
102+ delCmd := exec .Command ("ip" , "netns" , "del" , nsName )
103+ if err := delCmd .Run (); err != nil {
104+ return fmt .Errorf ("failed to delete namespace %s: %w" , nsName , err )
105+ }
106+ }
107+ }
108+
109+ return nil
110+ }
0 commit comments