diff --git a/Dockerfile.windows b/Dockerfile.windows index 822e2363a25..4f4d1006700 100644 --- a/Dockerfile.windows +++ b/Dockerfile.windows @@ -56,6 +56,7 @@ RUN mkdir -p charts # We use the containerd-shim-runhcs-v1.exe binary from upstream, as it apparently can't be cross-built on Linux COPY Dockerfile ./ +COPY windows/node-calico.ps1 rancher/ RUN CONTAINERD_VERSION=$(grep "rancher/hardened-containerd" Dockerfile | grep ':v' | cut -d '=' -f 2- | grep -oE "([0-9]+)\.([0-9]+)\.([0-9]+)") \ && curl -sLO https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-windows-amd64.tar.gz \ && curl -sLO https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-windows-amd64.tar.gz.sha256sum \ diff --git a/pkg/windows/calico.go b/pkg/windows/calico.go index 4892320fef8..15ee0f8eee8 100644 --- a/pkg/windows/calico.go +++ b/pkg/windows/calico.go @@ -302,7 +302,9 @@ 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 { + cmd := exec.Command("powershell.exe", "C:\\var\\lib\\rancher\\rke2\\bin\\node-calico.ps1") + if err := cmd.Run(); err != nil { + //if err := deleteAllNetworks(); 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..7721d9c3022 100644 --- a/pkg/windows/utils.go +++ b/pkg/windows/utils.go @@ -34,6 +34,12 @@ var ( // 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 { diff --git a/windows/node-calico.ps1 b/windows/node-calico.ps1 new file mode 100644 index 00000000000..cd1bd509c93 --- /dev/null +++ b/windows/node-calico.ps1 @@ -0,0 +1,96 @@ +$softwareRegistryKey = "HKLM:\Software\Tigera" +$calicoRegistryKey = $softwareRegistryKey + "\Calico" + +function Get-LastBootTime() +{ + $bootTime = (Get-CimInstance win32_operatingsystem | select @{LABEL='LastBootUpTime';EXPRESSION={$_.lastbootuptime}}).LastBootUpTime + if (($bootTime -EQ $null) -OR ($bootTime.length -EQ 0)) + { + throw "Failed to get last boot time" + } + + # This function is used in conjunction with Get-StoredLastBootTime, which + # returns a string, so convert the datetime value to a string using the "general" standard format. + return $bootTime.ToString("G") +} + +function Get-StoredLastBootTime() +{ + try + { + return (Get-ItemProperty $calicoRegistryKey -ErrorAction Ignore).LastBootTime + } + catch + { + $PSItem.Exception.Message + } +} + +function ensureRegistryKey() +{ + if (! (Test-Path $softwareRegistryKey)) + { + New-Item $softwareRegistryKey + } + if (! (Test-Path $calicoRegistryKey)) + { + New-Item $calicoRegistryKey + } +} + +function Set-StoredLastBootTime($lastBootTime) +{ + ensureRegistryKey + + return Set-ItemProperty $calicoRegistryKey -Name LastBootTime -Value $lastBootTime +} + +$lastBootTime = Get-LastBootTime + +# Check if the node has been rebooted. If so, the HNS networks will be in unknown state so we need to +# clean them up and recreate them. +$prevLastBootTime = Get-StoredLastBootTime +Write-Host "StoredLastBootTime $prevLastBootTime, CurrentLastBootTime $lastBootTime" +if ($prevLastBootTime -NE $lastBootTime) +{ + if ((Get-HNSNetwork | ? Type -NE nat)) + { + Write-Host "First time Calico has run since boot up, cleaning out any old network state." + Get-HNSNetwork | ? Type -NE nat | Remove-HNSNetwork + do + { + Write-Host "Waiting for network deletion to complete." + Start-Sleep 1 + } while ((Get-HNSNetwork | ? Type -NE nat)) + } + # After deletion of all hns networks, wait for an interface to have an IP that is not a 169.254.0.0/16 (or 127.0.0.0/8) address, + # before creation of External network. + $isValidIP = $false + $IPRegEx1='(^127\.0\.0\.)' + $IPRegEx2='(^169\.254\.)' + while(!($isValidIP) -AND ($timeout -gt 0)) + { + $IPAddress = (Get-NetIPAddress -AddressFamily IPv4).IPAddress + Write-Host "`nTimeout Remaining: $timeout sec" + Write-Host "List of IP Address before initialising Calico: $IPAddress" + Foreach ($ip in $IPAddress) + { + if (($ip -NotMatch $IPRegEx1) -AND ($ip -NotMatch $IPRegEx2)) + { + $isValidIP = $true + Write-Host "`nFound valid IP: $ip" + break + } + } + if (!($isValidIP)) + { + Start-Sleep -s 5 + $timeout = $timeout - 5 + } + } +} + +Set-StoredLastBootTime $lastBootTime +$Stored = Get-StoredLastBootTime +Write-Host "Stored new lastBootTime $Stored" +