From 7af5676929eb2ff24c673e42d9e250f7b961ca43 Mon Sep 17 00:00:00 2001 From: Roberto Bonafiglia Date: Wed, 31 Jul 2024 17:59:21 +0200 Subject: [PATCH] Fixed hns clean only in case of reboot Signed-off-by: Roberto Bonafiglia --- pkg/windows/calico.go | 6 +-- pkg/windows/utils.go | 106 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/pkg/windows/calico.go b/pkg/windows/calico.go index 4892320fef8..005176ebc90 100644 --- a/pkg/windows/calico.go +++ b/pkg/windows/calico.go @@ -150,7 +150,7 @@ func (c *Calico) Setup(ctx context.Context, nodeConfig *daemonconfig.Node, restC } logrus.Info("Generating HNS networks, please wait") - return c.generateCalicoNetworks() + return c.generateCalicoNetworks(ctx) } // initializeConfig sets the default configuration in CNIConfig @@ -301,8 +301,8 @@ func (c *Calico) Start(ctx context.Context) error { } // generateCalicoNetworks creates the overlay networks for internode networking -func (c *Calico) generateCalicoNetworks() error { - if err := deleteAllNetworks(); err != nil { +func (c *Calico) generateCalicoNetworks(ctx context.Context) error { + if err := deleteAllNetworks(ctx); err != nil { return errors.Wrapf(err, "failed to delete all networks before bootstrapping calico") } diff --git a/pkg/windows/utils.go b/pkg/windows/utils.go index 772de9f3f10..91bc282a7a7 100644 --- a/pkg/windows/utils.go +++ b/pkg/windows/utils.go @@ -4,11 +4,13 @@ package windows import ( + "context" "encoding/json" "fmt" "net" "net/http" "net/url" + "os/exec" "regexp" "strings" "text/template" @@ -20,6 +22,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" opv1 "github.com/tigera/operator/api/v1" + "golang.org/x/sys/windows/registry" "k8s.io/apimachinery/pkg/util/wait" ) @@ -31,9 +34,103 @@ var ( } ) +var softwareRegistryKey = "Software\\Rancher" +var softwareCalicoRegistryKey = softwareRegistryKey+"\\Calico" + + +func ensureRegistryKey() error { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, "Software", registry.QUERY_VALUE) + if err != nil { + return err + } + defer k.Close() + + softwareK, _, err := registry.CreateKey(k, "Rancher", registry.CREATE_SUB_KEY) + if err != nil { + return err + } + defer softwareK.Close() + + calicoK, exist, err := registry.CreateKey(softwareK, "Calico", registry.CREATE_SUB_KEY) + if err != nil { + return err + } + calicoK.Close() + if !exist { + err = setStoredLastBootTime("") + if err != nil { + return err + } + } + + return nil +} + +//Get latest stored reboot +func getStoredLastBootTime() (string, error) { + calicoK, err := registry.OpenKey(registry.LOCAL_MACHINE, softwareCalicoRegistryKey, registry.QUERY_VALUE) + if err != nil { + return "", err + } + defer calicoK.Close() + + lastStoredBoot, _, err := calicoK.GetStringValue("LastBootTime") + if err != nil { + return "", err + } + return lastStoredBoot, nil +} + +//Set last boot time on the registry +func setStoredLastBootTime(lastBootTime string) error { + calicoK, err := registry.OpenKey(registry.LOCAL_MACHINE, softwareCalicoRegistryKey, registry.SET_VALUE) + if err != nil { + return err + } + defer calicoK.Close() + + err = calicoK.SetStringValue("LastBootTime", lastBootTime) + if err != nil { + return err + } + + return nil +} + +// Check if the node was rebooted +func isNodeRebooted(ctx context.Context) (bool, error) { + path, err := exec.LookPath("powershell") + if err == nil { + cmd := exec.CommandContext(ctx, path, "-NoProfile", "-NonInteractive", "@(Get-CimInstance Win32_OperatingSystem).LastBootUpTime.ToString(\"G\")") + out, err := cmd.CombinedOutput() + if err == nil { + lastReboot := strings.Replace(string(out), "\r\n", "", -1) + err := ensureRegistryKey() + if err != nil { + return true, err + } + prevLastReboot, err := getStoredLastBootTime() + if err != nil { + return true, err + } + if lastReboot == prevLastReboot { + return false, nil + } + err = setStoredLastBootTime(lastReboot) + } + } + return true, err +} + // createHnsNetwork creates the network that will connect nodes and returns its managementIP func createHnsNetwork(backend string, networkAdapter string) (string, error) { var network hcsshim.HNSNetwork + // Check if the interface already exists + hcsnetwork, err := hcsshim.GetHNSNetworkByName(CalicoHnsNetworkName) + if err == nil { + return hcsnetwork.ManagementIP, nil + } + if backend == "vxlan" { // Ignoring the return because both true and false without an error represent that the firewall rule was created or already exists if _, err := wapi.FirewallRuleAdd("OverlayTraffic4789UDP", "Overlay network traffic UDP", "", "4789", wapi.NET_FW_IP_PROTOCOL_UDP, wapi.NET_FW_PROFILE2_ALL); err != nil { @@ -105,7 +202,14 @@ func nodeAddressAutodetection(autoDetect opv1.NodeAddressAutodetection) (string, } // deleteAllNetworks deletes all hns networks -func deleteAllNetworks() error { +func deleteAllNetworks(ctx context.Context) error { + nodeRebooted, err := isNodeRebooted(ctx) + if err != nil { + return err + } + if !nodeRebooted { + return nil + } networks, err := hcsshim.HNSListNetworkRequest("GET", "", "") if err != nil { return err