From ea3228523e98bc393a4b516624222e3baf3e54d5 Mon Sep 17 00:00:00 2001 From: Wenying Dong Date: Thu, 30 May 2024 18:32:08 +0800 Subject: [PATCH] [Windows] Optimize the containerized OVS installation steps 1. Add logic to check the installed OVSext drivers, if only the desired version of driver is already installed, skip the installation; otherwise, remove the existing the drivers and re-install. 2. Add logic to check the installed VC redistributable files, if the existing installd vc_redist version is equal to or higher than the lowest requirement, skip the installation; otherwise re-install the files provided in the image. 3. Optimize the logic of maintaining the system paths by removing the duplicated path. 4. Optimize Uninstall-OVS script by removing OVS bin paths from the system path after it is deleted. Signed-off-by: Wenying Dong --- build/images/Dockerfile.build.windows | 3 +- build/yamls/antrea-windows-with-ovs.yml | 43 +- .../conf/Install-OVSDriver.ps1 | 39 +- .../conf/Run-AntreaOVS.ps1 | 2 +- .../containerd-with-ovs.yml | 2 +- docs/windows.md | 14 +- hack/windows/Install-OVS.ps1 | 465 +++++++++++++----- hack/windows/Uninstall-OVS.ps1 | 22 +- 8 files changed, 385 insertions(+), 205 deletions(-) diff --git a/build/images/Dockerfile.build.windows b/build/images/Dockerfile.build.windows index 24cab356715..730cfdc4aef 100644 --- a/build/images/Dockerfile.build.windows +++ b/build/images/Dockerfile.build.windows @@ -40,7 +40,8 @@ RUN --mount=type=cache,target=/go/pkg/mod/ \ RUN mkdir -p /go/k/antrea/bin && \ cp /antrea/bin/antrea-agent.exe /go/k/antrea/bin/ && \ cp /antrea/bin/antctl.exe /go/k/antrea/bin/ && \ - cp /antrea/bin/antrea-cni.exe /go/k/antrea/cni/antrea.exe + cp /antrea/bin/antrea-cni.exe /go/k/antrea/cni/antrea.exe && \ + cp /antrea/hack/windows/Install-OVS.ps1 /go/k/antrea/ FROM antrea/windows-ovs:${OVS_VERSION} as antrea-ovs diff --git a/build/yamls/antrea-windows-with-ovs.yml b/build/yamls/antrea-windows-with-ovs.yml index fe444f28c64..91e0245c67d 100644 --- a/build/yamls/antrea-windows-with-ovs.yml +++ b/build/yamls/antrea-windows-with-ovs.yml @@ -4,39 +4,12 @@ data: $ErrorActionPreference = "Stop" $mountPath = $env:CONTAINER_SANDBOX_MOUNT_POINT $mountPath = ($mountPath.Replace('\', '/')).TrimEnd('/') - $OVSDriverDir = "$mountPath\openvswitch\driver" - - # Check if OVSExt driver is already installed - $driverStatus = netcfg -q ovsext - if ($driverStatus -like '*not installed*') { - # Install OVS Driver - $result = netcfg -l $OVSDriverDir/ovsext.inf -c s -i OVSExt - if ($result -like '*failed*') { - Write-Host "Failed to install OVSExt driver: $result" - exit 1 - } - Write-Host "OVSExt driver has been installed" - } - - # Check if the VC redistributable is already installed. - $OVSRedistDir="$mountPath\openvswitch\redist" - if (Test-Path $OVSRedistDir) { - $dllFound = $false - $paths = $env:PATH -split ';' - foreach ($path in $paths) { - $dllFiles = Get-ChildItem -Path $path -Filter "vcruntime*.dll" -File -ErrorAction SilentlyContinue - if ($dllFiles.Count -gt 0) { - $dllFound = $true - break - } - } - - # vcruntime dlls are not installed on the host, then install the binaries. - if (-not $dllFound) { - Get-ChildItem $OVSRedistDir -Filter *.exe | ForEach-Object { - Start-Process -FilePath $_.FullName -Args '/install /passive /norestart' -Verb RunAs -Wait - } - } + $OVSInstallScript = "$mountPath\k\antrea\Install-OVS.ps1" + if (Test-Path $OVSInstallScript) { + & $OVSInstallScript -InstallUserspace $false -LocalFile $mountPath\openvswitch + } else { + Write-Host "Installation script not found: $OVSInstallScript, please manually install OVS drivers" + exit 1 } Install-WindowsCNI.ps1: | $ErrorActionPreference = "Stop"; @@ -82,7 +55,7 @@ data: $ErrorActionPreference = "Stop" $mountPath = $env:CONTAINER_SANDBOX_MOUNT_POINT $mountPath = ($mountPath.Replace('\', '/')).TrimEnd('/') - $env:PATH = $env:PATH + ";$mountPath/Windows/System32;$mountPath/openvswitch/usr/bin;$mountPath/openvswitch/usr/sbin" + $env:PATH = $env:PATH + ";$mountPath/openvswitch/usr/bin;$mountPath/openvswitch/usr/sbin" $OVSDriverDir = "$mountPath\openvswitch\driver" # Configure OVS processes @@ -324,7 +297,7 @@ spec: template: metadata: annotations: - checksum/agent-windows: da4b49898e3181dfcb6359f2b2acba452c2ff9a17af8342b6cccb73e8857aad6 + checksum/agent-windows: 9aed7ded773dbf746f8373f2c7557c74568f7c9df9ce4b4fe8fcad97038ca637 checksum/windows-config: 6ff4f8bd0b310ebe4d4612bdd9697ffb3d79e0e0eab3936420417dd5a8fc128d microsoft.com/hostprocess-inherit-user: "true" labels: diff --git a/build/yamls/windows/containerd-with-ovs/conf/Install-OVSDriver.ps1 b/build/yamls/windows/containerd-with-ovs/conf/Install-OVSDriver.ps1 index 63dd1089e9b..5e2dc635718 100644 --- a/build/yamls/windows/containerd-with-ovs/conf/Install-OVSDriver.ps1 +++ b/build/yamls/windows/containerd-with-ovs/conf/Install-OVSDriver.ps1 @@ -1,37 +1,10 @@ $ErrorActionPreference = "Stop" $mountPath = $env:CONTAINER_SANDBOX_MOUNT_POINT $mountPath = ($mountPath.Replace('\', '/')).TrimEnd('/') -$OVSDriverDir = "$mountPath\openvswitch\driver" - -# Check if OVSExt driver is already installed -$driverStatus = netcfg -q ovsext -if ($driverStatus -like '*not installed*') { - # Install OVS Driver - $result = netcfg -l $OVSDriverDir/ovsext.inf -c s -i OVSExt - if ($result -like '*failed*') { - Write-Host "Failed to install OVSExt driver: $result" - exit 1 - } - Write-Host "OVSExt driver has been installed" -} - -# Check if the VC redistributable is already installed. -$OVSRedistDir="$mountPath\openvswitch\redist" -if (Test-Path $OVSRedistDir) { - $dllFound = $false - $paths = $env:PATH -split ';' - foreach ($path in $paths) { - $dllFiles = Get-ChildItem -Path $path -Filter "vcruntime*.dll" -File -ErrorAction SilentlyContinue - if ($dllFiles.Count -gt 0) { - $dllFound = $true - break - } - } - - # vcruntime dlls are not installed on the host, then install the binaries. - if (-not $dllFound) { - Get-ChildItem $OVSRedistDir -Filter *.exe | ForEach-Object { - Start-Process -FilePath $_.FullName -Args '/install /passive /norestart' -Verb RunAs -Wait - } - } +$OVSInstallScript = "$mountPath\k\antrea\Install-OVS.ps1" +if (Test-Path $OVSInstallScript) { + & $OVSInstallScript -InstallUserspace $false -LocalFile $mountPath\openvswitch +} else { + Write-Host "Installation script not found: $OVSInstallScript, please manually install OVS drivers" + exit 1 } diff --git a/build/yamls/windows/containerd-with-ovs/conf/Run-AntreaOVS.ps1 b/build/yamls/windows/containerd-with-ovs/conf/Run-AntreaOVS.ps1 index ee0747ada51..50032c29604 100644 --- a/build/yamls/windows/containerd-with-ovs/conf/Run-AntreaOVS.ps1 +++ b/build/yamls/windows/containerd-with-ovs/conf/Run-AntreaOVS.ps1 @@ -1,7 +1,7 @@ $ErrorActionPreference = "Stop" $mountPath = $env:CONTAINER_SANDBOX_MOUNT_POINT $mountPath = ($mountPath.Replace('\', '/')).TrimEnd('/') -$env:PATH = $env:PATH + ";$mountPath/Windows/System32;$mountPath/openvswitch/usr/bin;$mountPath/openvswitch/usr/sbin" +$env:PATH = $env:PATH + ";$mountPath/openvswitch/usr/bin;$mountPath/openvswitch/usr/sbin" $OVSDriverDir = "$mountPath\openvswitch\driver" # Configure OVS processes diff --git a/build/yamls/windows/containerd-with-ovs/containerd-with-ovs.yml b/build/yamls/windows/containerd-with-ovs/containerd-with-ovs.yml index f5d69ca280c..cf76175a1f9 100644 --- a/build/yamls/windows/containerd-with-ovs/containerd-with-ovs.yml +++ b/build/yamls/windows/containerd-with-ovs/containerd-with-ovs.yml @@ -34,7 +34,7 @@ spec: - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/Install-OVSDriver.ps1 command: - powershell - image: antrea/antrea-windows:latest + image: antrea-windows imagePullPolicy: IfNotPresent name: install-ovs-driver volumeMounts: diff --git a/docs/windows.md b/docs/windows.md index 810903d2c66..326bb08f57b 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -170,12 +170,12 @@ depending on whether you are using your own [signed](https://docs.microsoft.com/ OVS kernel driver or you want to use the test-signed driver provided by Antrea, you will need to invoke the `Install-OVS.ps1` script differently (or not at all). -| Containerized OVS daemons? | Test-signed OVS driver? | Run this command | -| -------------------------- | ----------------------- | ---------------- | -| Yes | Yes | `.\Install-OVS.ps1 -InstallUserspace $false` | -| Yes | No | N/A | -| No | Yes | `.\Install-OVS.ps1` | -| No | No | `.\Install-OVS.ps1 -ImportCertificate $false -Local -LocalFile ` | +| Containerized OVS daemons? | Test-signed OVS driver? | Run this command | +| -------------------------- | ----------------------- |---------------------------------------------------------------------------| +| Yes | Yes | `.\Install-OVS.ps1 -InstallUserspace $false` | +| Yes | No | N/A | +| No | Yes | `.\Install-OVS.ps1 -InstallUserspace $true` | +| No | No | `.\Install-OVS.ps1 -InstallUserspace $true -LocalFile ` | If you used `antrea-windows-with-ovs.yml` to create the antrea-agent Windows DaemonSet, then you are using "Containerized OVS daemons". For all other @@ -208,7 +208,7 @@ your own OVS package with a signed OVS kernel driver, you would run: ```powershell curl.exe -LO https://raw.githubusercontent.com/antrea-io/antrea/main/hack/windows/Install-OVS.ps1 -.\Install-OVS.ps1 -ImportCertificate $false -Local -LocalFile +.\Install-OVS.ps1 -InstallUserspace $true -LocalFile # verify that the OVS services are installed get-service ovsdb-server diff --git a/hack/windows/Install-OVS.ps1 b/hack/windows/Install-OVS.ps1 index 1086fc22d81..42edecbfa4d 100644 --- a/hack/windows/Install-OVS.ps1 +++ b/hack/windows/Install-OVS.ps1 @@ -5,22 +5,12 @@ .PARAMETER DownloadURL The URL of the OpenvSwitch package to be downloaded. - .PARAMETER DownloadDir - The path of the directory to be used to download OpenvSwitch package. The default path is the working directory. - .PARAMETER OVSInstallDir The target installation directory. The default path is "C:\openvswitch". - .PARAMETER CheckFileHash - Skips checking file hash. The default value is true. - .PARAMETER LocalFile Specifies the path of a local OpenvSwitch package to be used for installation. - When the param is used, "DownloadURL" and "DownloadDir" params will be ignored. - - .PARAMETER ImportCertificate - Specifies if a certificate file is needed for OVS package. If true, certificate - will be retrieved from OVSExt.sys and a package.cer file will be generated. + When the param is used, "DownloadURL" is ignored. .PARAMETER InstallUserspace Specifies whether OVS userspace processes are included in the installation. If false, these processes will not @@ -30,12 +20,9 @@ Specifies the path of a local SSL package to be used for installation. #> Param( - [parameter(Mandatory = $false)] [string] $DownloadDir, [parameter(Mandatory = $false)] [string] $DownloadURL, [parameter(Mandatory = $false)] [string] $OVSInstallDir = "C:\openvswitch", - [parameter(Mandatory = $false)] [bool] $CheckFileHash = $true, [parameter(Mandatory = $false)] [string] $LocalFile, - [parameter(Mandatory = $false)] [bool] $ImportCertificate = $true, [parameter(Mandatory = $false)] [bool] $InstallUserspace = $true, [parameter(Mandatory = $false)] [string] $LocalSSLFile ) @@ -44,27 +31,73 @@ $ErrorActionPreference = "Stop" $OVSDownloadURL = "https://downloads.antrea.io/ovs/ovs-3.0.5-antrea.1-win64.zip" # Use a SHA256 hash to ensure that the downloaded archive is correct. $OVSPublishedHash = '813a0c32067f40ce4aca9ceb7cd745a120e26906e9266d13cc8bf75b147bb6a5' +# $MininalVCRedistVersion is the minimal version required by the provided Windows OVS binary. If a higher +# version of VC redistributable file exists on the Windows host, we can skip the installation. +$MininalVCRedistVersion="14.12.25810" + $WorkDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition) -$OVSDownloadDir = $WorkDir +$InstallLog = "$WorkDir\install_ovs.log" $PowerShellModuleBase = "C:\Windows\System32\WindowsPowerShell\v1.0\Modules" +$OVSZip="" -if (!$LocalFile) { - $OVSZip = "$OVSDownloadDir\ovs-win64.zip" -} else { - $OVSZip = $LocalFile - $DownloadDir = Split-Path -Path $LocalFile -} +function PrepareOVSLocalFiles() { + if ($LocalFile -ne "") { + validateLocalOVSFiles + $OVSDownloadURL = "" + $OVSPublishedHash = "" + } else { + $OVSZip = "$WorkDir\ovs-win64.zip" + if ($DownloadURL -ne "" -and $DownloadURL -ne "$OVSDownloadURL") { + $OVSDownloadURL = $DownloadURL + $OVSPublishedHash = "" + } + } -if ($DownloadDir -ne "") { - $OVSDownloadDir = $DownloadDir + if (($OVSZip -ne "")) { + if (Test-Path -Path $OVSInstallDir) { + Log "$OVSInstallDir already exists, exit OVS installation." + exit 1 + } + $removeZipFile = $false + if ($OVSDownloadURL -ne "") { + DownloadOVS + $removeZipFile = $true + } + $ovsInstallParentPath = Split-Path -Path $OVSInstallDir -Parent + Expand-Archive -Path $OVSZip -DestinationPath $ovsInstallParentPath | Out-Null + if ($removeZipFile) { + rm $OVSZip + } + } } -$InstallLog = "$OVSDownloadDir\install_ovs.log" +function validateLocalOVSFiles() { + if (-not (Test-Path $LocalFile)){ + Log "Path $LocalFile doesn't exist, exit" + exit 1 + } + + $ovsFile = Get-Item $LocalFile + $attributes = $ovsFile.Attributes + if ($ovsFile -is [System.IO.FileInfo]) { + if (("$attributes" -eq "Archive") -and ($ovsFile.Extension -eq ".zip" )) { + $OVSZip = $LocalFile + return + } + Log "The OVS local package must be in ZIP format, exit" + exit 1 + } -if ($DownloadURL -ne "") { - $OVSDownloadURL = $DownloadURL - # For user-provided URLs, do not verify the hash for the archive. - $OVSPublishedHash = "" + if ($ovsFile -is [System.IO.DirectoryInfo]) { + if ($ovsFile.BaseName -eq "openvswitch") { + $OVSInstallDir = $ovsFile.FullName + return + } + Log "Unsupported local directory: $LocalFile. Only directories with a base name 'openvswitch' are supported" + exit 1 + } + Log "Unsupported local file $LocalFile with attributes '$attributes'" + exit 1 } function Log($Info) { @@ -72,22 +105,6 @@ function Log($Info) { "$time $Info `n`r" | Tee-Object $InstallLog -Append | Write-Host } -function CreatePath($Path){ - if ($(Test-Path $Path)) { - mv $Path $($Path + "_bak") - } - mkdir -p $Path | Out-Null -} - -function SetEnvVar($key, $value) { - [Environment]::SetEnvironmentVariable($key, $value, [EnvironmentVariableTarget]::Machine) -} - -function WaitExpandFiles($Src, $Dest) { - Log "Extract $Src to $Dest" - Expand-Archive -Path $Src -DestinationPath $Dest | Out-Null -} - function ServiceExists($ServiceName) { If (Get-Service $ServiceName -ErrorAction SilentlyContinue) { return $true @@ -107,14 +124,6 @@ function CheckIfOVSInstalled() { } function DownloadOVS() { - if ($LocalFile -ne "") { - Log "Skipping OVS download, using local file: $LocalFile" - return - } - - If (!(Test-Path $OVSDownloadDir)) { - mkdir -p $OVSDownloadDir - } Log "Downloading OVS package from $OVSDownloadURL to $OVSZip" curl.exe -sLo $OVSZip $OVSDownloadURL If (!$?) { @@ -122,9 +131,9 @@ function DownloadOVS() { exit 1 } - if ($CheckFileHash) { + if ($OVSPublishedHash -ne "") { $FileHash = Get-FileHash $OVSZip - If ($OVSPublishedHash -ne "" -And $FileHash.Hash -ne $OVSPublishedHash) { + If ($FileHash.Hash -ne $OVSPublishedHash) { Log "SHA256 mismatch for OVS download" exit 1 } @@ -134,50 +143,74 @@ function DownloadOVS() { } function InstallOVS() { - # unzip OVS. - WaitExpandFiles $OVSZip $OVSDownloadDir - # Copy OVS package to target dir. - Log "Copying OVS package from $OVSDownloadDir\openvswitch to $OVSInstallDir" - mv "$OVSDownloadDir\openvswitch" $OVSInstallDir - if (!$LocalFile) { - rm $OVSZip + # Install powershell modules + $OVSScriptsPath = "${OVSInstallDir}\scripts" + CheckAndInstallScripts -OVSScriptsPath $OVSScriptsPath + + # Install VC redistributables. + $OVSRedistDir="$mountPath\openvswitch\redist" + # Check if the VC redistributable is already installed. If not installed, or the installed version + # is lower than $MininalVCRedistVersion, install VC redistributable files provided in the container. + CheckAndInstallVCRedists -VCRedistPath $OVSRedistDir -VCRedistsVersion $MininalVCRedistVersion + + # Install OVS driver. + $OVSDriverDir = "${OVSInstallDir}\driver" + Log "Installing OVS kernel driver" + CheckAndInstallOVSDriver -OVSDriverPath $OVSDriverDir + + if ($InstallUserspace -eq $true) { + InstallOVSServices + } +} + +function InstallOVSServices() { + # Remove the existing OVS Services to avoid issues. + If (ServiceExists("ovs-vswitchd")) { + stop-service ovs-vswitchd + sc.exe delete ovs-vswitchd + } + if (ServiceExists("ovsdb-server")) { + stop-service ovsdb-server + sc.exe delete ovsdb-server } + + $usrBinPath="${OVSInstallDir}\usr\bin" + $usrSbinPath="${OVSInstallDir}\usr\sbin" + $OVSBinPaths="${usrBinPath};${usrSbinPath}" + InstallOpenSSLFiles "$OVSBinPaths" + # Create log and run dir. - $OVS_LOG_PATH = $OVSInstallDir + "\var\log\openvswitch" - CreatePath $OVS_LOG_PATH - $OVSRunDir = $OVSInstallDir + "\var\run\openvswitch" - CreatePath $OVSRunDir - $OVSDriverDir = "$OVSInstallDir\driver" - - # Install OVS driver certificate. - $DriverFile="$OVSDriverDir\OVSExt.sys" - if ($ImportCertificate) { - $CertificateFile = "$OVSDriverDir\package.cer" - if (!(Test-Path $CertificateFile)) { - Log "No existing OVS driver certificate found, generating a new one." - $ExportType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert; - $Cert = (Get-AuthenticodeSignature $DriverFile).SignerCertificate; - [System.IO.File]::WriteAllBytes($CertificateFile, $Cert.Export($ExportType)); - } - Log "Installing OVS driver certificate." - Import-Certificate -FilePath "$CertificateFile" -CertStoreLocation cert:\LocalMachine\TrustedPublisher - Import-Certificate -FilePath "$CertificateFile" -CertStoreLocation cert:\LocalMachine\Root - } - - # Install Microsoft Visual C++ Redistributable Package. - if (Test-Path $OVSInstallDir\redist) { - Log "Installing Microsoft Visual C++ Redistributable Package." - $RedistFiles = Get-ChildItem "$OVSInstallDir\redist" -Filter *.exe - $RedistFiles | ForEach-Object { - Log "Installing $_" - Start-Process -FilePath $_.FullName -Args '/install /passive /norestart' -Verb RunAs -Wait - } + $OVSLogDir = "${OVSInstallDir}\var\log\openvswitch" + if (-not (Test-Path $OVSLogDir)) { + mkdir -p $OVSLogDir | Out-Null + } + $OVSRunDir = "${OVSInstallDir}\var\run\openvswitch" + if (-not (Test-Path $OVSRunDir)) { + mkdir -p $OVSRunDir | Out-Null } - # Install powershell modules - if (Test-Path $OVSInstallDir\scripts) { + # Install OVS Services and configure OVSDB. + ConfigOVS + + # Add OVS usr/bin and usr/sbin to System path. + $envPaths = $env:Path -split ";" | Select-Object -Unique + if (-not $envPaths.Contains($usrBinPath)) { + $envPaths += $usrBinPath + } + if (-not $envPaths.Contains($usrSbinPath)) { + $envPaths += $usrSbinPath + } + $env:Path = [system.String]::Join(";", $envPaths) + [Environment]::SetEnvironmentVariable("Path", $env:Path, [EnvironmentVariableTarget]::Machine) +} + +function CheckAndInstallScripts { + param ( + [Parameter(Mandatory = $true)] [String]$OVSScriptsPath + ) + if (Test-Path $OVSScriptsPath) { Log "Installing powershell modules." - $PSModuleFiles = Get-ChildItem "$OVSInstallDir\scripts" -Filter *.psm1 + $PSModuleFiles = Get-ChildItem "$OVSScriptsPath" -Filter *.psm1 $PSModuleFiles | ForEach-Object { $PSModulePath = Join-Path -Path $PowerShellModuleBase -ChildPath $_.BaseName if (!(Test-Path $PSModulePath)) { @@ -187,29 +220,217 @@ function InstallOVS() { } } } +} - # Install OVS kernel driver. - Log "Installing OVS kernel driver" - $VMMSStatus = $(Get-Service vmms -ErrorAction SilentlyContinue).Status - if (!$VMMSStatus) { - $VMMSStatus = "not exist" +function CheckAndInstallVCRedists { + param ( + [Parameter(Mandatory = $true)] [String]$VCRedistPath, + [Parameter(Mandatory = $true)] [String]$VCRedistsVersion + ) + $mininalVersion = [version]$VCRedistsVersion + $existingVCRedists = getInstalledVcRedists + foreach ($redist in $existingVCRedists) { + $installedVersion = [version]$redist.Version + # VC redists files with a higher version are installed, return. + if ($installedVersion -ge $mininalVersion) { + return + } } - Log "Hyper-V Virtual Machine Management service status: $VMMSStatus" - if ($VMMSStatus -eq "Running") { - cmd /c "cd $OVSDriverDir && install.cmd" - } else { - cd $OVSDriverDir ; netcfg -l .\ovsext.inf -c s -i OVSExt; cd $WorkDir + # Install the provided VC redistributable files. + Get-ChildItem $VCRedistPath -Filter *.exe | ForEach-Object { + Start-Process -FilePath $_.FullName -Args '/install /passive /norestart' -Verb RunAs -Wait } - if (!$?) { - Log "Install OVS kernel driver failed, exit" +} + +function CheckAndInstallOVSDriver { + param ( + [Parameter(Mandatory = $true)] + [String]$OVSDriverPath + ) + + $expVersion = [version]$(Get-Item $OVSDriverPath\ovsext.sys).VersionInfo.ProductVersion + $ovsInstalled = $(netcfg -q ovsext) -like "*is installed*" + $installedDrivers = getInstalledOVSDrivers + + # OVSext driver with the desired version is already installed, return + if ($ovsInstalled -and ($installedDrivers.Length -eq 1) -and ($installedDrivers[0].DriverVersion -eq $expVersion)){ + return + } + + # Uninstall the existing driver which is with a different version. + if ($ovsInstalled) { + netcfg -u ovsext + } + + # Clean up the installed ovsext drivers packages. + foreach ($driver in $installedDrivers) { + $publishdName = $driver.PublishedName + pnputil.exe -d $publishdName + } + + # Import OVSext driver certificate to TrustedPublisher and Root. + $DriverFile="$OVSDriverPath\ovsext.sys" + $CertificateFile = "$OVSDriverPath\package.cer" + $ExportType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert + $Cert = (Get-AuthenticodeSignature $DriverFile).SignerCertificate + [System.IO.File]::WriteAllBytes($CertificateFile, $Cert.Export($ExportType)) + Import-Certificate -FilePath "$CertificateFile" -CertStoreLocation cert:\LocalMachine\TrustedPublisher + Import-Certificate -FilePath "$CertificateFile" -CertStoreLocation cert:\LocalMachine\Root + + # Install the OVSext driver with the desired version + $result = netcfg -l $OVSDriverPath/ovsext.inf -c s -i OVSExt + if ($result -like '*failed*') { + Write-Host "Failed to install OVSExt driver: $result" exit 1 } - $OVS_BIN_PATH="$OVSInstallDir\usr\bin;$OVSInstallDir\usr\sbin" - $env:Path += ";$OVS_BIN_PATH" - SetEnvVar "Path" $env:Path + Log "OVSExt driver has been installed" } -function InstallDependency() { +function getInstalledVcRedists { + # Get all installed Visual C++ Redistributables installed components + $VcRedists = listInstalledSoftware -SoftwareLike 'Microsoft Visual C++' + + # Add Architecture property to each entry + $VcRedists | ForEach-Object { If ( $_.Name.ToLower().Contains("x64") ) ` + { $_ | Add-Member -NotePropertyName "Architecture" -NotePropertyValue "x64" } } + + return $vcRedists +} + +function listInstalledSoftware { + param ( + [parameter(Mandatory = $false)] [string] $SoftwareLike + ) + Begin { + $SoftwareOutput = @() + $InstalledSoftware = (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*) + } + Process { + Try + { + if ($SoftwareLike -ne "") { + $nameFilter = "${SoftwareLike}*" + $InstalledSoftware = $InstalledSoftware | + Where-Object {$_.DisplayName -like "$nameFilter"} + } + + $SoftwareOutput = $InstalledSoftware | + Select-Object -Property @{ + Name = 'Date Installed' + Exp = { + $_.Installdate + } + }, @{ + Name = 'Version' + Exp = { + $_.DisplayVersion + } + }, @{ + Name = 'Name' + Exp = { + $_.DisplayName + } + }, UninstallString + } + Catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = New-Object -TypeName PSObject -Property @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info + } + } + + End{ + $SoftwareOutput | Sort-Object -Property Name + } +} + +function getInstalledOVSDrivers { + $pnputilOutput = pnputil.exe /enum-drivers + $drivers = @() + $lines = $pnputilOutput -split "`r`n" + $driverlines = @() + foreach ($line in $lines) { + if ($line -like "*Microsoft PnP Utility*") { + continue + } + if ($line.Trim() -eq "") { + if ($driverlines.Count -gt 0) { + $driver = $(parseDriver $driverlines) + $drivers += $driver + $driverlines = @() + } + continue + } + $driverlines += $line + } + if ($driverlines.Count -gt 0) { + $driver = parseDriver $driverlines + $drivers += $driver + } + $drivers = $drivers | Where-Object { $_.OriginalName -like "ovsext*"} + return $drivers +} + +function parseDriver { + param ( + [String[]]$driverlines + ) + $driver = [PSCustomObject]@{ + PublishedName = $null + ProviderName = $null + ClassName = $null + DriverVersion = $null + InstalledDate = $null + SignerName = $null + ClassGUID = $null + OriginalName = $null + } + $driverlines | ForEach-Object { + if ($_ -match "Published Name\s*:\s*(.+)") { + $driver.PublishedName = $matches[1].Trim() + } + elseif ($_ -match "Provider Name\s*:\s*(.+)") { + $driver.ProviderName = $matches[1].Trim() + } + elseif ($_ -match "Class Name\s*:\s*(.+)") { + $driver.ClassName = $matches[1].Trim() + } + elseif ($_ -match "Driver Version\s*:\s*(.+)") { + $dateAndVersion = $matches[1].Trim() -split " " + $driver.DriverVersion = [version]$dateAndVersion[1] + $driver.InstalledDate = $dateAndVersion[0] + } + elseif ($_ -match "Signer Name\s*:\s*(.+)") { + $driver.SignerName = $matches[1].Trim() + } + elseif ($_ -match "Class GUID\s*:\s*(.+)") { + $driver.ClassGUID = $matches[1].Trim() + } + elseif ($_ -match "Original Name\s*:\s*(.+)") { + $driver.OriginalName = $matches[1].Trim() + } + } + return $driver +} + +function InstallOpenSSLFiles { + param ( + [parameter(Mandatory = $true)] [string] $destinationPaths + ) + # Check if SSL library has been installed $paths = $env:Path.Split(";") foreach($path in $paths) { @@ -244,11 +465,17 @@ function InstallDependency() { Expand-Archive $SSLZip -DestinationPath openssl rm $SSLZip } - cp -Force openssl/*.dll $OVSInstallDir\usr\sbin\ + $destinationPaths -Split ";" | Foreach-Object { + cp -Force openssl/*.dll $_\ + } rm -Recurse -Force openssl } function ConfigOVS() { + # Antrea Pod runs as NT AUTHORITY\SYSTEM user on Windows, antrea-ovs container writes + # PID and conf.db files to $OVSInstallDir on Windows Node when it is running. + icacls $OVSInstallDir /grant "NT AUTHORITY\SYSTEM:(OI)(CI)F" /T + # Create ovsdb config file $OVS_DB_SCHEMA_PATH = "$OVSInstallDir\usr\share\openvswitch\vswitch.ovsschema" $OVS_DB_PATH = "$OVSInstallDir\etc\openvswitch\conf.db" @@ -272,21 +499,13 @@ function ConfigOVS() { ovs-vsctl --no-wait set Open_vSwitch . ovs_version=$OVS_VERSION } +if (($LocalFile -ne "") -and ($DownloadURL -ne "")) { + Log "LocalFile and DownloadURL are mutually exclusive, exit" + exit 1 +} Log "Installation log location: $InstallLog" -CheckIfOVSInstalled - -DownloadOVS - +PrepareOVSLocalFiles InstallOVS -if ($InstallUserspace -eq $true) { - InstallDependency - - ConfigOVS -} - -# Antrea Pod runs as NT AUTHORITY\SYSTEM user on Windows, antrea-ovs container writes -# pid and conf.db files to $OVSInstallDir on Windows host Node during runtime. -icacls $OVSInstallDir /grant "NT AUTHORITY\SYSTEM:(OI)(CI)F" /T Log "OVS Installation Complete!" diff --git a/hack/windows/Uninstall-OVS.ps1 b/hack/windows/Uninstall-OVS.ps1 index b52f477bd51..e3d597c3064 100644 --- a/hack/windows/Uninstall-OVS.ps1 +++ b/hack/windows/Uninstall-OVS.ps1 @@ -6,9 +6,8 @@ Param( $ErrorActionPreference = "Continue" $OVSBinDir = "$OVSInstallDir\usr\bin" -$OVSDriverDir = "$OVSInstallDir\driver\" -if ($DeleteBridges) { +if ((Test-Path $OVSBinDir) -and $DeleteBridges) { $brList = ovs-vsctl.exe list-br foreach ($br in $brList) { Write-Host "Delete OVS Bridge: %s $br" @@ -37,14 +36,17 @@ if (Get-Service ovsdb-server -ErrorAction SilentlyContinue) { } } # Uninstall OVS kernel driver -cmd /c "cd $OVSDriverDir && uninstall.cmd" +$ovsInstalled = $(netcfg -q ovsext) -like "*is installed*" +if ($ovsInstalled) { + netcfg -u ovsext +} if (!$?) { Write-Host "Failed to uninstall OVS kernel driver." exit 1 } # Remove OVS installation dir -if ($RemoveDir) { +if ($RemoveDir -and (Test-Path $OVSInstallDir)) { Remove-Item -Recurse $OVSInstallDir if (!$?) { Write-Host "Failed to remove OVS dir: $OVSInstallDir." @@ -52,4 +54,16 @@ if ($RemoveDir) { } } +# Remove OVS bin paths from environment variables. +$envPaths = @() +$usrBinPath="$OVSInstallDir\usr\bin" +$usrSbinPath="$OVSInstallDir\usr\sbin" +foreach ($item in $($env:Path -split ";" | Select-Object -Unique)) { + if (($item -ne "$usrBinPath") -and ($item -ne "$usrSbinPath")) { + $envPaths += $item + } +} +$env:Path = $envPaths -join ";" +[Environment]::SetEnvironmentVariable("Path", $env:Path, [EnvironmentVariableTarget]::Machine) + Write-Host "Uninstall OVS success."