From d07984e6f1ab100d641c0965a8e54cd67c2054bd Mon Sep 17 00:00:00 2001 From: Kumar Atish Date: Wed, 19 Jul 2023 18:15:05 +0530 Subject: [PATCH] Add support to run Windows OVS in container For #4952 Signed-off-by: Shuyang Xin Signed-off-by: Naman Agarwal Signed-off-by: Kumar Atish --- Makefile | 4 + build/images/Dockerfile.build.windows | 8 + .../antrea-windows-containerd-with-ovs.yml | 374 ++++++++++++++++++ build/yamls/antrea-windows-containerd.yml | 7 +- .../conf/PostStart-AntreaAgent-Containerd.ps1 | 12 + .../conf/PreStop-AntreaAgent-Containerd.ps1 | 12 + .../conf/Run-AntreaOVS-Containerd.ps1 | 31 ++ .../containerd-with-ovs.yml | 40 ++ .../containerd-with-ovs/kustomization.yml | 16 + .../windows/containerd/agent-containerd.yml | 2 +- .../conf/Run-AntreaAgent-Containerd.ps1 | 1 + ci/jenkins/test.sh | 18 +- docs/windows.md | 33 +- hack/generate-manifest-windows.sh | 20 +- hack/release/prepare-assets.sh | 1 + hack/windows/Clean-AntreaNetwork.ps1 | 51 ++- hack/windows/Install-OVS.ps1 | 15 +- hack/windows/Prepare-Node.ps1 | 9 +- hack/windows/Uninstall-OVS.ps1 | 25 +- 19 files changed, 631 insertions(+), 48 deletions(-) create mode 100644 build/yamls/antrea-windows-containerd-with-ovs.yml create mode 100644 build/yamls/windows/containerd-with-ovs/conf/PostStart-AntreaAgent-Containerd.ps1 create mode 100644 build/yamls/windows/containerd-with-ovs/conf/PreStop-AntreaAgent-Containerd.ps1 create mode 100644 build/yamls/windows/containerd-with-ovs/conf/Run-AntreaOVS-Containerd.ps1 create mode 100644 build/yamls/windows/containerd-with-ovs/containerd-with-ovs.yml create mode 100644 build/yamls/windows/containerd-with-ovs/kustomization.yml diff --git a/Makefile b/Makefile index f0a8bcfe12a..93fc4439129 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,8 @@ CNI_BINARIES_VERSION := $(shell head -n 1 build/images/deps/cni-binaries-version NANOSERVER_VERSION := $(shell head -n 1 build/images/deps/nanoserver-version) BUILD_TAG := $(shell build/images/build-tag.sh) WIN_BUILD_TAG := $(shell echo $(GO_VERSION) $(CNI_BINARIES_VERSION) $(NANOSERVER_VERSION)|md5sum|head -c 10) +WIN_OVS_VERSION := $(shell head -n 1 build/images/deps/ovs-version-windows) +WIN_BUILD_OVS_TAG := $(NANOSERVER_VERSION)-$(WIN_OVS_VERSION) GIT_HOOKS := $(shell find hack/git_client_side_hooks -type f -print) DOCKER_NETWORK ?= default TRIVY_TARGET_IMAGE ?= @@ -29,6 +31,7 @@ WIN_BUILD_ARGS := --build-arg GO_VERSION=$(GO_VERSION) WIN_BUILD_ARGS += --build-arg CNI_BINARIES_VERSION=$(CNI_BINARIES_VERSION) WIN_BUILD_ARGS += --build-arg NANOSERVER_VERSION=$(NANOSERVER_VERSION) WIN_BUILD_ARGS += --build-arg WIN_BUILD_TAG=$(WIN_BUILD_TAG) +WIN_BUILD_ARGS += --build-arg WIN_BUILD_OVS_TAG=$(WIN_BUILD_OVS_TAG) .PHONY: all all: build @@ -383,6 +386,7 @@ manifest: $(CURDIR)/hack/generate-standard-manifests.sh --mode dev --out build/yamls $(CURDIR)/hack/generate-manifest-windows.sh --mode dev > build/yamls/antrea-windows.yml $(CURDIR)/hack/generate-manifest-windows.sh --mode dev --containerd > build/yamls/antrea-windows-containerd.yml + $(CURDIR)/hack/generate-manifest-windows.sh --mode dev --containerd --include-ovs > build/yamls/antrea-windows-containerd-with-ovs.yml $(CURDIR)/hack/generate-manifest-flow-aggregator.sh --mode dev > build/yamls/flow-aggregator.yml .PHONY: manifest-scale diff --git a/build/images/Dockerfile.build.windows b/build/images/Dockerfile.build.windows index fbd2e94bfd9..0fdc2735c76 100644 --- a/build/images/Dockerfile.build.windows +++ b/build/images/Dockerfile.build.windows @@ -14,6 +14,7 @@ ARG WIN_BUILD_TAG ARG NANOSERVER_VERSION +ARG WIN_BUILD_OVS_TAG FROM antrea/base-windows:${WIN_BUILD_TAG} as antrea-build-windows @@ -27,6 +28,8 @@ COPY . /antrea RUN sh -c 'make windows-bin' +FROM antrea/windows-ovs:${WIN_BUILD_OVS_TAG} as windows-ovs + FROM mcr.microsoft.com/powershell:lts-nanoserver-${NANOSERVER_VERSION} SHELL ["pwsh", "-NoLogo", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] @@ -44,3 +47,8 @@ COPY --from=antrea-build-windows /antrea/bin/antrea-cni.exe /k/antrea/cni/antre RUN mkdir C:\k\antrea\utils COPY --from=antrea-build-windows /wins/wins.exe /k/antrea/utils/wins.exe + +COPY --from=windows-ovs /Windows/System32/vcruntime140.dll /Windows/System32/ +COPY --from=windows-ovs /Windows/System32/libeay32.dll /Windows/System32/ +COPY --from=windows-ovs /Windows/System32/ssleay32.dll /Windows/System32/ +COPY --from=windows-ovs /openvswitch/usr/bin /k/antrea/bin/ diff --git a/build/yamls/antrea-windows-containerd-with-ovs.yml b/build/yamls/antrea-windows-containerd-with-ovs.yml new file mode 100644 index 00000000000..50e36d99b86 --- /dev/null +++ b/build/yamls/antrea-windows-containerd-with-ovs.yml @@ -0,0 +1,374 @@ +apiVersion: v1 +data: + Install-WindowsCNI-Containerd.ps1: | + $ErrorActionPreference = "Stop"; + mkdir -force c:/var/log/antrea + $mountPath = $env:CONTAINER_SANDBOX_MOUNT_POINT + $mountPath = ($mountPath.Replace('\', '/')).TrimEnd('/') + mkdir -force C:/var/run/secrets/kubernetes.io/serviceaccount + cp $mountPath/var/run/secrets/kubernetes.io/serviceaccount/ca.crt C:/var/run/secrets/kubernetes.io/serviceaccount + cp $mountPath/var/run/secrets/kubernetes.io/serviceaccount/token C:/var/run/secrets/kubernetes.io/serviceaccount + mkdir -force c:/opt/cni/bin/ + mkdir -force c:/etc/cni/net.d/ + cp $mountPath/k/antrea/cni/* c:/opt/cni/bin/ + cp $mountPath/etc/antrea/antrea-cni.conflist c:/etc/cni/net.d/10-antrea.conflist + mkdir -force c:/k/antrea/bin + cp $mountPath/k/antrea/bin/antctl.exe c:/k/antrea/bin/antctl.exe + PostStart-AntreaAgent-Containerd.ps1: | + $networkName = "antrea-hnsnetwork" + $networks = Get-HnsNetwork + $networkExists = $false + foreach ($network in $networks) { + if ($network.Name -eq $networkName) { + $networkExists = $true + break + } + } + if ($networkExists) { + Enable-VMSwitchExtension -Name "Open vSwitch Extension" -VMSwitchName "antrea-hnsnetwork" + } + PreStop-AntreaAgent-Containerd.ps1: | + $networkName = "antrea-hnsnetwork" + $networks = Get-HnsNetwork + $networkExists = $false + foreach ($network in $networks) { + if ($network.Name -eq $networkName) { + $networkExists = $true + break + } + } + if ($networkExists) { + Disable-VMSwitchExtension -Name "Open vSwitch Extension" -VMSwitchName "antrea-hnsnetwork" + } + Run-AntreaAgent-Containerd.ps1: | + $ErrorActionPreference = "Stop" + $mountPath = $env:CONTAINER_SANDBOX_MOUNT_POINT + $mountPath = ($mountPath.Replace('\', '/')).TrimEnd('/') + $env:PATH = $env:PATH + ";$mountPath/Windows/System32;$mountPath/k/antrea/bin" + & "$mountPath/k/antrea/bin/antrea-agent.exe" --config=$mountPath/etc/antrea/antrea-agent.conf --logtostderr=false --log_dir=c:/var/log/antrea --alsologtostderr --log_file_max_size=100 --log_file_max_num=4 --v=0 + Run-AntreaOVS-Containerd.ps1: | + $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" + $OVS_DB_SCHEMA_PATH = "$mountPath/openvswitch/usr/share/openvswitch/vswitch.ovsschema" + $OVS_DB_PATH = "C:\openvswitch\etc\openvswitch\conf.db" + if ($(Test-Path $OVS_DB_SCHEMA_PATH) -and !$(Test-Path $OVS_DB_PATH)) { + ovsdb-tool create "$OVS_DB_PATH" "$OVS_DB_SCHEMA_PATH" + } + ovsdb-server $OVS_DB_PATH -vfile:info --remote=punix:db.sock --log-file=/var/log/antrea/openvswitch/ovsdb-server.log --pidfile --detach + ovs-vsctl --no-wait init + + # Set OVS version. + $OVS_VERSION=$(Get-Item $mountPath\openvswitch\driver\OVSExt.sys).VersionInfo.ProductVersion + ovs-vsctl --no-wait set Open_vSwitch . ovs_version=$OVS_VERSION + + ovs-vswitchd --log-file=/var/log/antrea/openvswitch/ovs-vswitchd.log --pidfile -vfile:info --detach + + $SleepInterval = 30 + Write-Host "Started the loop that checks OVS status every $SleepInterval seconds" + while ($true) { + if ( !( Get-Process ovsdb-server ) ) { + Write-Host "ovsdb-server is not running, starting it again..." + ovsdb-server $OVS_DB_PATH -vfile:info --remote=punix:db.sock --log-file=/var/log/antrea/openvswitch/ovsdb-server.log --pidfile --detach + } + if ( !( Get-Process ovs-vswitchd ) ) { + Write-Host "ovs-vswitchd is not running, starting it again..." + ovs-vswitchd --log-file=/var/log/antrea/openvswitch/ovs-vswitchd.log --pidfile -vfile:info --detach + } + Start-Sleep -Seconds $SleepInterval + } +kind: ConfigMap +metadata: + labels: + app: antrea + name: antrea-agent-windows-fb66k86gdm + namespace: kube-system +--- +apiVersion: v1 +data: + antrea-agent.conf: | + # FeatureGates is a map of feature names to bools that enable or disable experimental features. + featureGates: + # Enable antrea proxy which provides ServiceLB for in-cluster services in antrea agent. + # It should be enabled on Windows, otherwise NetworkPolicy will not take effect on + # Service traffic. + # AntreaProxy: true + + # Enable EndpointSlice support in AntreaProxy. Don't enable this feature unless that EndpointSlice + # API version v1beta1 is supported and set as enabled in Kubernetes. If AntreaProxy is not enabled, + # this flag will not take effect. + # EndpointSlice: true + + # Enable NodePortLocal feature to make the Pods reachable externally through NodePort + # NodePortLocal: true + + # Enable flowexporter which exports polled conntrack connections as IPFIX flow records from each agent to a configured collector. + # FlowExporter: false + + # Name of the OpenVSwitch bridge antrea-agent will create and use. + # Make sure it doesn't conflict with your existing OpenVSwitch bridges. + #ovsBridge: br-int + + # Name of the interface antrea-agent will create and use for host <--> pod communication. + # Make sure it doesn't conflict with your existing interfaces. + #hostGateway: antrea-gw0 + + # Encapsulation mode for communication between Pods across Nodes, supported values: + # - geneve (default) + # - vxlan + # - stt + #tunnelType: geneve + + # TunnelPort is the destination port for UDP and TCP based tunnel protocols + # (Geneve, VXLAN, and STT). If zero, it will use the assigned IANA port for the + # protocol, i.e. 6081 for Geneve, 4789 for VXLAN, and 7471 for STT. + #tunnelPort: 0 + + # Default MTU to use for the host gateway interface and the network interface of each Pod. + # If omitted, antrea-agent will discover the MTU of the Node's primary interface and + # also adjust MTU to accommodate for tunnel encapsulation overhead. + #defaultMTU: 1450 + + # ClusterIP CIDR range for Services. It's required when AntreaProxy is not enabled, and should be + # set to the same value as the one specified by --service-cluster-ip-range for kube-apiserver. When + # AntreaProxy is enabled, this parameter is not needed and will be ignored if provided. + #serviceCIDR: 10.96.0.0/12 + + # The port for the antrea-agent APIServer to serve on. + #apiPort: 10350 + + # Enable metrics exposure via Prometheus. Initializes Prometheus metrics listener. + #enablePrometheusMetrics: true + + # Provide the IPFIX collector address as a string with format :[][:]. + # HOST can either be the DNS name, IP, or Service name of the Flow Collector. If + # using an IP, it can be either IPv4 or IPv6. However, IPv6 address should be + # wrapped with []. When the collector is running in-cluster as a Service, set + # to /. For example, + # "flow-aggregator/flow-aggregator" can be provided to connect to the Antrea + # Flow Aggregator Service. + # If PORT is empty, we default to 4739, the standard IPFIX port. + # If no PROTO is given, we consider "tls" as default. We support "tls", "tcp" and + # "udp" protocols. "tls" is used for securing communication between flow exporter and + # flow aggregator. + #flowCollectorAddr: "flow-aggregator/flow-aggregator:4739:tls" + + # Provide flow poll interval as a duration string. This determines how often the + # flow exporter dumps connections from the conntrack module. Flow poll interval + # should be greater than or equal to 1s (one second). + # Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". + #flowPollInterval: "5s" + + # Provide the active flow export timeout, which is the timeout after which a flow + # record is sent to the collector for active flows. Thus, for flows with a continuous + # stream of packets, a flow record will be exported to the collector once the elapsed + # time since the last export event is equal to the value of this timeout. + # Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". + #activeFlowExportTimeout: "30s" + + # Provide the idle flow export timeout, which is the timeout after which a flow + # record is sent to the collector for idle flows. A flow is considered idle if no + # packet matching this flow has been observed since the last export event. + # Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". + #idleFlowExportTimeout: "15s" + + # Enable TLS communication from flow exporter to flow aggregator. + #enableTLSToFlowAggregator: true + + # Determines how traffic is encapsulated. It has the following options: + # encap(default): Inter-node Pod traffic is always encapsulated and Pod to external network + # traffic is SNAT'd. + # noEncap: Inter-node Pod traffic is not encapsulated; Pod to external network traffic is + # SNAT'd if noSNAT is not set to true. Underlying network must be capable of + # supporting Pod traffic across IP subnets. + # hybrid: noEncap if source and destination Nodes are on the same subnet, otherwise encap. + # + #trafficEncapMode: encap + + # The name of the interface on Node which is used for tunneling or routing the traffic across Nodes. + # If there are multiple IP addresses configured on the interface, the first one is used. The IP + # address used for tunneling or routing traffic to remote Nodes is decided in the following order of + # preference (from highest to lowest): + # 1. transportInterface + # 2. transportInterfaceCIDRs + # 3. The Node IP + #transportInterface: + + # The network CIDRs of the interface on Node which is used for tunneling or routing the traffic across + # Nodes. If there are multiple interfaces configured the same network CIDR, the first one is used. The + # IP address used for tunneling or routing traffic to remote Nodes is decided in the following order of + # preference (from highest to lowest): + # 1. transportInterface + # 2. transportInterfaceCIDRs + # 3. The Node IP + #transportInterfaceCIDRs: [,] + + # Provide the address of Kubernetes apiserver, to override any value provided in kubeconfig or InClusterConfig. + # Defaults to "". It must be a host string, a host:port pair, or a URL to the base of the apiserver. + #kubeAPIServerOverride: "" + + # Option antreaProxy contains AntreaProxy related configuration options. + antreaProxy: + # ProxyAll tells antrea-agent to proxy ClusterIP Service traffic, regardless of where they come from. + # Therefore, running kube-proxy is no longer required. This requires the AntreaProxy feature to be enabled. + # Note that this option is experimental. If kube-proxy is removed, option kubeAPIServerOverride must be used to access + # apiserver directly. + proxyAll: true + # The value of the "service.kubernetes.io/service-proxy-name" label for AntreaProxy to match. If it is set, + # then AntreaProxy will only handle Services with the label that equals the provided value. If it is not set, + # then AntreaProxy will only handle Services without the "service.kubernetes.io/service-proxy-name" label, + # but ignore Services with the label no matter what is the value. + serviceProxyName: "" + + nodePortLocal: + # Enable NodePortLocal, a feature used to make Pods reachable using port forwarding on the host. To + # enable this feature, you need to set "enable" to true, and ensure that the NodePortLocal feature + # gate is also enabled (which is the default). + # enable: false + # Provide the port range used by NodePortLocal. When the NodePortLocal feature is enabled, a port + # from that range will be assigned whenever a Pod's container defines a specific port to be exposed + # (each container can define a list of ports as pod.spec.containers[].ports), and all Node traffic + # directed to that port will be forwarded to the Pod. + # portRange: 40000-41000 + antrea-cni.conflist: | + { + "cniVersion":"0.3.0", + "name": "antrea", + "plugins": [ + { + "type": "antrea", + "ipam": { + "type": "host-local" + }, + "capabilities": {"dns": true} + } + ] + } +kind: ConfigMap +metadata: + labels: + app: antrea + name: antrea-windows-config-cb2hmgg648 + namespace: kube-system +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + app: antrea + component: antrea-agent + name: antrea-agent-windows + namespace: kube-system +spec: + selector: + matchLabels: + app: antrea + component: antrea-agent + template: + metadata: + annotations: + microsoft.com/hostprocess-inherit-user: "true" + labels: + app: antrea + component: antrea-agent + spec: + containers: + - args: + - -file + - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/Run-AntreaAgent-Containerd.ps1 + command: + - powershell + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + image: antrea/antrea-windows:latest + imagePullPolicy: IfNotPresent + lifecycle: + postStart: + exec: + command: + - powershell + - -file + - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/PostStart-AntreaAgent-Containerd.ps1 + preStop: + exec: + command: + - powershell + - -file + - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/PreStop-AntreaAgent-Containerd.ps1 + name: antrea-agent + volumeMounts: + - mountPath: /etc/antrea + name: antrea-windows-config + - mountPath: /var/lib/antrea-windows + name: antrea-agent-windows + - mountPath: /var/log/antrea/ + name: var-log-antrea + - args: + - -file + - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/Run-AntreaOVS-Containerd.ps1 + command: + - powershell + image: antrea/windows-ovs:1809-3.0.5 + imagePullPolicy: IfNotPresent + name: antrea-ovs + volumeMounts: + - mountPath: /var/lib/antrea-windows + name: antrea-agent-windows + - mountPath: /var/log/openvswitch + name: var-log-antrea + subPath: openvswitch + hostNetwork: true + initContainers: + - args: + - -file + - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/Install-WindowsCNI-Containerd.ps1 + command: + - powershell + image: antrea/antrea-windows:latest + imagePullPolicy: IfNotPresent + name: install-cni + volumeMounts: + - mountPath: /etc/antrea + name: antrea-windows-config + readOnly: true + - mountPath: /var/lib/antrea-windows + name: antrea-agent-windows + nodeSelector: + kubernetes.io/os: windows + priorityClassName: system-node-critical + securityContext: + windowsOptions: + hostProcess: true + runAsUserName: NT AUTHORITY\SYSTEM + serviceAccountName: antrea-agent + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - effect: NoSchedule + operator: Exists + volumes: + - configMap: + name: antrea-windows-config-cb2hmgg648 + name: antrea-windows-config + - configMap: + defaultMode: 420 + name: antrea-agent-windows-fb66k86gdm + name: antrea-agent-windows + - hostPath: + path: /var/log/antrea/ + type: DirectoryOrCreate + name: var-log-antrea + updateStrategy: + type: RollingUpdate diff --git a/build/yamls/antrea-windows-containerd.yml b/build/yamls/antrea-windows-containerd.yml index 185ad930fac..bb509643512 100644 --- a/build/yamls/antrea-windows-containerd.yml +++ b/build/yamls/antrea-windows-containerd.yml @@ -18,12 +18,13 @@ data: $ErrorActionPreference = "Stop" $mountPath = $env:CONTAINER_SANDBOX_MOUNT_POINT $mountPath = ($mountPath.Replace('\', '/')).TrimEnd('/') + $env:PATH = $env:PATH + ";$mountPath/Windows/System32;$mountPath/k/antrea/bin" & "$mountPath/k/antrea/bin/antrea-agent.exe" --config=$mountPath/etc/antrea/antrea-agent.conf --logtostderr=false --log_dir=c:/var/log/antrea --alsologtostderr --log_file_max_size=100 --log_file_max_num=4 --v=0 kind: ConfigMap metadata: labels: app: antrea - name: antrea-agent-windows-4d6m7hf65f + name: antrea-agent-windows-h2b282tk2b namespace: kube-system --- apiVersion: v1 @@ -246,7 +247,7 @@ spec: hostNetwork: true initContainers: - args: - - -File + - -file - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/Install-WindowsCNI-Containerd.ps1 command: - powershell @@ -278,7 +279,7 @@ spec: name: antrea-windows-config - configMap: defaultMode: 420 - name: antrea-agent-windows-4d6m7hf65f + name: antrea-agent-windows-h2b282tk2b name: antrea-agent-windows - hostPath: path: /var/log/antrea/ diff --git a/build/yamls/windows/containerd-with-ovs/conf/PostStart-AntreaAgent-Containerd.ps1 b/build/yamls/windows/containerd-with-ovs/conf/PostStart-AntreaAgent-Containerd.ps1 new file mode 100644 index 00000000000..9c67a16f39d --- /dev/null +++ b/build/yamls/windows/containerd-with-ovs/conf/PostStart-AntreaAgent-Containerd.ps1 @@ -0,0 +1,12 @@ +$networkName = "antrea-hnsnetwork" +$networks = Get-HnsNetwork +$networkExists = $false +foreach ($network in $networks) { + if ($network.Name -eq $networkName) { + $networkExists = $true + break + } +} +if ($networkExists) { + Enable-VMSwitchExtension -Name "Open vSwitch Extension" -VMSwitchName "antrea-hnsnetwork" +} diff --git a/build/yamls/windows/containerd-with-ovs/conf/PreStop-AntreaAgent-Containerd.ps1 b/build/yamls/windows/containerd-with-ovs/conf/PreStop-AntreaAgent-Containerd.ps1 new file mode 100644 index 00000000000..3959ed5c57f --- /dev/null +++ b/build/yamls/windows/containerd-with-ovs/conf/PreStop-AntreaAgent-Containerd.ps1 @@ -0,0 +1,12 @@ +$networkName = "antrea-hnsnetwork" +$networks = Get-HnsNetwork +$networkExists = $false +foreach ($network in $networks) { + if ($network.Name -eq $networkName) { + $networkExists = $true + break + } +} +if ($networkExists) { + Disable-VMSwitchExtension -Name "Open vSwitch Extension" -VMSwitchName "antrea-hnsnetwork" +} diff --git a/build/yamls/windows/containerd-with-ovs/conf/Run-AntreaOVS-Containerd.ps1 b/build/yamls/windows/containerd-with-ovs/conf/Run-AntreaOVS-Containerd.ps1 new file mode 100644 index 00000000000..4f8012b58f1 --- /dev/null +++ b/build/yamls/windows/containerd-with-ovs/conf/Run-AntreaOVS-Containerd.ps1 @@ -0,0 +1,31 @@ +$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" +$OVS_DB_SCHEMA_PATH = "$mountPath/openvswitch/usr/share/openvswitch/vswitch.ovsschema" +$OVS_DB_PATH = "C:\openvswitch\etc\openvswitch\conf.db" +if ($(Test-Path $OVS_DB_SCHEMA_PATH) -and !$(Test-Path $OVS_DB_PATH)) { + ovsdb-tool create "$OVS_DB_PATH" "$OVS_DB_SCHEMA_PATH" +} +ovsdb-server $OVS_DB_PATH -vfile:info --remote=punix:db.sock --log-file=/var/log/antrea/openvswitch/ovsdb-server.log --pidfile --detach +ovs-vsctl --no-wait init + +# Set OVS version. +$OVS_VERSION=$(Get-Item $mountPath\openvswitch\driver\OVSExt.sys).VersionInfo.ProductVersion +ovs-vsctl --no-wait set Open_vSwitch . ovs_version=$OVS_VERSION + +ovs-vswitchd --log-file=/var/log/antrea/openvswitch/ovs-vswitchd.log --pidfile -vfile:info --detach + +$SleepInterval = 30 +Write-Host "Started the loop that checks OVS status every $SleepInterval seconds" +while ($true) { + if ( !( Get-Process ovsdb-server ) ) { + Write-Host "ovsdb-server is not running, starting it again..." + ovsdb-server $OVS_DB_PATH -vfile:info --remote=punix:db.sock --log-file=/var/log/antrea/openvswitch/ovsdb-server.log --pidfile --detach + } + if ( !( Get-Process ovs-vswitchd ) ) { + Write-Host "ovs-vswitchd is not running, starting it again..." + ovs-vswitchd --log-file=/var/log/antrea/openvswitch/ovs-vswitchd.log --pidfile -vfile:info --detach + } + Start-Sleep -Seconds $SleepInterval +} diff --git a/build/yamls/windows/containerd-with-ovs/containerd-with-ovs.yml b/build/yamls/windows/containerd-with-ovs/containerd-with-ovs.yml new file mode 100644 index 00000000000..b6f6f7f23ef --- /dev/null +++ b/build/yamls/windows/containerd-with-ovs/containerd-with-ovs.yml @@ -0,0 +1,40 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + component: antrea-agent + name: antrea-agent-windows +spec: + selector: + matchLabels: + component: antrea-agent + template: + metadata: + annotations: + "microsoft.com/hostprocess-inherit-user": "true" + labels: + component: antrea-agent + spec: + containers: + - name: antrea-agent + lifecycle: + preStop: + exec: + command: ["powershell", "-file", "$env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/PreStop-AntreaAgent-Containerd.ps1"] + postStart: + exec: + command: ["powershell", "-file", "$env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/PostStart-AntreaAgent-Containerd.ps1"] + - name: antrea-ovs + image: antrea/windows-ovs:1809-3.0.5 + imagePullPolicy: IfNotPresent + args: + - -file + - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/Run-AntreaOVS-Containerd.ps1 + command: + - powershell + volumeMounts: + - mountPath: /var/lib/antrea-windows + name: antrea-agent-windows + - mountPath: /var/log/openvswitch + name: var-log-antrea + subPath: openvswitch diff --git a/build/yamls/windows/containerd-with-ovs/kustomization.yml b/build/yamls/windows/containerd-with-ovs/kustomization.yml new file mode 100644 index 00000000000..ca2a8a97cec --- /dev/null +++ b/build/yamls/windows/containerd-with-ovs/kustomization.yml @@ -0,0 +1,16 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../containerd +patchesStrategicMerge: +- containerd-with-ovs.yml +commonLabels: + app: antrea +configMapGenerator: +- files: + - conf/Run-AntreaOVS-Containerd.ps1 + - conf/PostStart-AntreaAgent-Containerd.ps1 + - conf/PreStop-AntreaAgent-Containerd.ps1 + name: antrea-agent-windows + namespace: kube-system + behavior: merge diff --git a/build/yamls/windows/containerd/agent-containerd.yml b/build/yamls/windows/containerd/agent-containerd.yml index 2ac379c78e6..f54ae8c8f92 100644 --- a/build/yamls/windows/containerd/agent-containerd.yml +++ b/build/yamls/windows/containerd/agent-containerd.yml @@ -50,7 +50,7 @@ spec: hostNetwork: true initContainers: - args: - - -File + - -file - $env:CONTAINER_SANDBOX_MOUNT_POINT/var/lib/antrea-windows/Install-WindowsCNI-Containerd.ps1 command: - powershell diff --git a/build/yamls/windows/containerd/conf/Run-AntreaAgent-Containerd.ps1 b/build/yamls/windows/containerd/conf/Run-AntreaAgent-Containerd.ps1 index 7ca32e33094..357a42f8497 100644 --- a/build/yamls/windows/containerd/conf/Run-AntreaAgent-Containerd.ps1 +++ b/build/yamls/windows/containerd/conf/Run-AntreaAgent-Containerd.ps1 @@ -1,4 +1,5 @@ $ErrorActionPreference = "Stop" $mountPath = $env:CONTAINER_SANDBOX_MOUNT_POINT $mountPath = ($mountPath.Replace('\', '/')).TrimEnd('/') +$env:PATH = $env:PATH + ";$mountPath/Windows/System32;$mountPath/k/antrea/bin" & "$mountPath/k/antrea/bin/antrea-agent.exe" --config=$mountPath/etc/antrea/antrea-agent.conf --logtostderr=false --log_dir=c:/var/log/antrea --alsologtostderr --log_file_max_size=100 --log_file_max_num=4 --v=0 diff --git a/ci/jenkins/test.sh b/ci/jenkins/test.sh index 3ac7785d501..097f9132815 100755 --- a/ci/jenkins/test.sh +++ b/ci/jenkins/test.sh @@ -321,8 +321,9 @@ function prepare_env { function revert_snapshot_windows { WIN_NAME=$1 - echo "==== Reverting Windows VM ${WIN_NAME} =====" - govc snapshot.revert -vm ${WIN_NAME} win-initial + SNAPSHOT_NAME=$2 + echo "==== Reverting Windows VM ${WIN_NAME} to ${SNAPSHOT_NAME} =====" + govc snapshot.revert -vm ${WIN_NAME} ${SNAPSHOT_NAME} # If Windows VM fails to power on correctly in time, retry several times. winVMIPs="" for i in `seq 10`; do @@ -411,7 +412,7 @@ function deliver_antrea_windows { rm -f antrea-windows.tar.gz sed -i 's/if (!(Test-Path $AntreaAgentConfigPath))/if ($true)/' hack/windows/Helper.psm1 kubectl get nodes -o wide --no-headers=true | awk -v role="$CONTROL_PLANE_NODE_ROLE" '$3 !~ role && $1 ~ /win/ {print $1}' | while read WORKER_NAME; do - revert_snapshot_windows ${WORKER_NAME} + revert_snapshot_windows ${WORKER_NAME} win-initial # Use a script to run antrea agent in windows Network Policy cases if [ "$TESTCASE" == "windows-networkpolicy-process" ]; then @@ -474,6 +475,7 @@ function deliver_antrea_windows_containerd { echo "====== Cleanup Antrea Installation Before Delivering Antrea Windows Containerd ======" clean_antrea kubectl delete -f ${WORKDIR}/antrea-windows-containerd.yml --ignore-not-found=true || true + kubectl delete -f ${WORKDIR}/antrea-windows-containerd-with-ovs.yml --ignore-not-found=true || true kubectl delete -f ${WORKDIR}/kube-proxy-windows-containerd.yml --ignore-not-found=true || true kubectl delete daemonset antrea-agent -n kube-system --ignore-not-found=true || true kubectl delete -f ${WORKDIR}/antrea.yml --ignore-not-found=true || true @@ -496,7 +498,7 @@ function deliver_antrea_windows_containerd { echo "====== Updating yaml files to enable proxyAll ======" KUBE_API_SERVER=$(kubectl --kubeconfig=$KubeConfigFile config view -o jsonpath='{.clusters[0].cluster.server}') - sed -i "s|.*kubeAPIServerOverride: \"\"| kubeAPIServerOverride: \"${KUBE_API_SERVER}\"|g" build/yamls/antrea.yml build/yamls/antrea-windows-containerd.yml + sed -i "s|.*kubeAPIServerOverride: \"\"| kubeAPIServerOverride: \"${KUBE_API_SERVER}\"|g" build/yamls/antrea.yml build/yamls/antrea-windows-containerd.yml build/yamls/antrea-windows-containerd-with-ovs.yml cp -f build/yamls/*.yml $WORKDIR docker save -o antrea-ubuntu.tar antrea/antrea-ubuntu:latest @@ -533,8 +535,7 @@ function deliver_antrea_windows_containerd { done echo "===== Build Antrea Windows on Windows Jumper Node =====" - echo "==== Reverting Windows VM ${WIN_IMAGE_NODE} =====" - revert_snapshot_windows ${WIN_IMAGE_NODE} + revert_snapshot_windows ${WIN_IMAGE_NODE} win-initial rm -f antrea-windows.tar.gz # Compress antrea repo and copy it to a Windows node mkdir -p jenkins @@ -551,7 +552,7 @@ function deliver_antrea_windows_containerd { echo "===== Deliver Antrea Windows to Windows worker nodes and pull necessary images on Windows worker nodes =====" sed -i 's/if (!(Test-Path $AntreaAgentConfigPath))/if ($true)/' hack/windows/Helper.psm1 kubectl get nodes -o wide --no-headers=true | awk -v role="$CONTROL_PLANE_NODE_ROLE" '$3 !~ role && $1 ~ /win/ {print $1}' | while read WORKER_NAME; do - revert_snapshot_windows ${WORKER_NAME} + revert_snapshot_windows ${WORKER_NAME} win-initial-userspaceovs # Some tests need us.gcr.io/k8s-artifacts-prod/e2e-test-images/agnhost:2.13 image but it is not for windows/amd64 10.0.17763 # Use e2eteam/agnhost:2.13 instead harbor_images=("sigwindowstools-kube-proxy:v1.18.0" "agnhost:2.13" "agnhost:2.13" "agnhost:2.29" "e2eteam-jessie-dnsutils:1.0" "e2eteam-pause:3.2") @@ -1086,7 +1087,8 @@ fi trap clean_antrea EXIT if [[ ${TESTCASE} =~ "windows" ]]; then if [[ ${TESTCASE} =~ "containerd" ]]; then - WINDOWS_YAML_SUFFIX="windows-containerd" + # WINDOWS_YAML_SUFFIX="windows-containerd" + WINDOWS_YAML_SUFFIX="windows-containerd-with-ovs" deliver_antrea_windows_containerd if [[ ${TESTCASE} =~ "e2e" ]]; then run_e2e_windows diff --git a/docs/windows.md b/docs/windows.md index bc36e0d2667..ac419f3f348 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -47,9 +47,10 @@ The following components should be configured and run on the Windows Node. antrea-agent and kube-proxy run as processes on host and are managed by management Pods. It is recommended to run OVS daemons as Windows services. -If you don't want to run antrea-agent and kube-proxy from the management Pods -Antrea also provides scripts which help install and run these two components -directly without Pod, please see [Manually run kube-proxy and antrea-agent on Windows worker Nodes](#Manually-run-kube-proxy-and-antrea-agent-on-Windows-worker-Nodes) +We also support running OVS processes inside a container. If you don't want to +run antrea-agent and kube-proxy from the management Pods Antrea also provides +scripts which help to install and run these two components directly without Pod. +Please see [Manually run kube-proxy and antrea-agent on Windows worker Nodes](#Manually-run-kube-proxy-and-antrea-agent-on-Windows-worker-Nodes) section for details. ### Antrea Windows demo @@ -205,6 +206,18 @@ sed "s|.*kubeAPIServerOverride: \"\"| kubeAPIServerOverride: \"${KUBE_APISERV kubectl apply -f - ``` +Since Antrea 1.13, you can deploy both antrea-agent and antrea-ovs Windows DaemonSets +with containerd runtime by applying file `antrea-windows-containerd-with-ovs.yml`. The +following commands downloads the manifest, sets kubeAPIServerOverride, and deploys +the antrea-agent and antrea-ovs Windows DaemonSets with containerd runtime: + +```bash +KUBE_APISERVER=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}') && \ +curl -sL https://github.com/antrea-io/antrea/releases/download//antrea-windows-containerd-with-ovs.yml | \ +sed "s|.*kubeAPIServerOverride: \"\"| kubeAPIServerOverride: \"${KUBE_APISERVER}\"|g" | \ +kubectl apply -f - +``` + #### Join Windows worker Nodes ##### 1. (Optional) Install OVS (provided by Antrea or your own) @@ -243,6 +256,13 @@ get-service ovsdb-server get-service ovs-vswitchd ``` +If you want to containerize OVS for containerd runtime, OVS userspace processes are +not run on the host and hence you can set the `InstallUserspace` parameter to false. + +```powershell +.\Install-OVS.ps1 -InstallUserspace $false +``` + ##### 2. Disable Windows Firewall ```powershell @@ -525,6 +545,13 @@ Extension is disabled by default. In this case, the stale OVS bridge and ports should be removed. A help script [Clean-AntreaNetwork.ps1](https://raw.githubusercontent.com/antrea-io/antrea/main/hack/windows/Clean-AntreaNetwork.ps1) can be used to clean the OVS bridge. + ```powershell + # If OVS userspace processes were running as a Service on Windows host + ./Clean-AntreaNetwork.ps1 -OVSRunMode "service" + # If OVS userspace processes were running inside container in antrea-agent Pod + ./Clean-AntreaNetwork.ps1 -OVSRunMode "container" + ``` + 2. Hyper-V feature cannot be installed on Windows Node due to the processor not having the required virtualization capabilities. diff --git a/hack/generate-manifest-windows.sh b/hack/generate-manifest-windows.sh index 03c5dd63533..7444affbdc8 100755 --- a/hack/generate-manifest-windows.sh +++ b/hack/generate-manifest-windows.sh @@ -22,9 +22,12 @@ function echoerr { _usage="Usage: $0 [--mode (dev|release)] [--keep] [--help|-h] Generate a YAML manifest to run Antrea on Windows Nodes, using Kustomize, and print it to stdout. - --mode (dev|release) Choose the configuration variant that you need (default is 'dev') - --keep Debug flag which will preserve the generated kustomization.yml - --help, -h Print this message and exit + --mode (dev|release) Choose the configuration variant that you need (default is 'dev') + --keep Debug flag which will preserve the generated kustomization.yml + --help, -h Print this message and exit + --containerd Support for containerd runtime. + --include-ovs Run Windows OVS processes inside antrea-ovs container in antrea-agent pod + on Windows host with containerd runtime. In 'release' mode, environment variables IMG_NAME and IMG_TAG must be set. @@ -44,6 +47,7 @@ function print_help { RUNTIME="" MODE="dev" KEEP=false +OVSRunMode="service" while [[ $# -gt 0 ]] do @@ -62,6 +66,10 @@ case $key in RUNTIME="containerd" shift ;; + --include-ovs) + OVSRunMode="container" + shift + ;; -h|--help) print_usage exit 0 @@ -111,7 +119,11 @@ pushd $TMP_DIR > /dev/null BASE=../../default if [ "$RUNTIME" == "containerd" ]; then - BASE=../../containerd + if [ "$OVSRunMode" == "container" ]; then + BASE=../../containerd-with-ovs + elif [ "$OVSRunMode" == "service" ]; then + BASE=../../containerd + fi fi mkdir $MODE && cd $MODE diff --git a/hack/release/prepare-assets.sh b/hack/release/prepare-assets.sh index 771904772ac..c59b8c1f9be 100755 --- a/hack/release/prepare-assets.sh +++ b/hack/release/prepare-assets.sh @@ -110,6 +110,7 @@ export IMG_NAME=projects.registry.vmware.com/antrea/antrea-ubuntu export IMG_NAME=projects.registry.vmware.com/antrea/antrea-windows ./hack/generate-manifest-windows.sh --mode release > "$OUTPUT_DIR"/antrea-windows.yml ./hack/generate-manifest-windows.sh --mode release --containerd > "$OUTPUT_DIR"/antrea-windows-containerd.yml +./hack/generate-manifest-windows.sh --mode release --containerd --include-ovs > "$OUTPUT_DIR"/antrea-windows-containerd-with-ovs.yml export IMG_NAME=projects.registry.vmware.com/antrea/flow-aggregator ./hack/generate-manifest-flow-aggregator.sh --mode release > "$OUTPUT_DIR"/flow-aggregator.yml diff --git a/hack/windows/Clean-AntreaNetwork.ps1 b/hack/windows/Clean-AntreaNetwork.ps1 index 5fd5dee1ae5..eb9ec25d981 100644 --- a/hack/windows/Clean-AntreaNetwork.ps1 +++ b/hack/windows/Clean-AntreaNetwork.ps1 @@ -11,11 +11,15 @@ as true, this script would remove the two Windows services from the host. Otherwise, we consider that these services are supposed to be running on the host, so the script would try to recover them if their statuses are not as expected. + .PARAMETER OVSRunMode + OVS run mode can be if OVS userspace processes were running inside a container in antrea-agent Pod + or if OVS userspace processes were running as a Service on host. Default mode is . #> Param( [parameter(Mandatory = $false)] [string] $OVSInstallDir = "C:\openvswitch", [parameter(Mandatory = $false)] [bool] $RenewIPConfig = $false, - [parameter(Mandatory = $false)] [bool] $RemoveOVS = $false + [parameter(Mandatory = $false)] [bool] $RemoveOVS = $false, + [parameter(Mandatory = $false)] [ValidateSet("service", "container")] [string] $OVSRunMode = "service" ) # Replace the path using the actual path where ovs-vswitchd.pid locates. It is always under path $OVSInstallDir\var\run\openvswitch. @@ -28,10 +32,16 @@ $OVS_BR_ADAPTER = "br-int" $AntreaHnsNetworkName = "antrea-hnsnetwork" function RemoveOVSService() { - stop-service ovs-vswitchd - sc.exe delete ovs-vswitchd - stop-service ovsdb-server - sc.exe delete ovsdb-server + $ovsSvc = Get-Service ovs-vswitchd -ErrorAction SilentlyContinue + if ($ovsSvc -ne $null ) { + stop-service ovs-vswitchd + sc.exe delete ovs-vswitchd + } + $ovsdbSvc = Get-Service ovsdb-server -ErrorAction SilentlyContinue + if ($ovsdbSvc -ne $null ) { + stop-service ovsdb-server + sc.exe delete ovsdb-server + } } function ResetOVSService() { @@ -103,15 +113,30 @@ function ClearHnsNetwork() { clearOVSBridge ClearHnsNetwork -if ($RemoveOVS) { - RemoveOVSService -} else { - # ResetOVSService is called to recover Windows Services "ovsdb-server" and "ovs-vswitchd" if they are removed - # unexpectedly or their status is not correct, e.g., ovs-vswitchd fails to go into Running. - # This might happen after the Windows host is restarted abnormally, in which case some stale configurations - # can prevent ovs-vswitchd from running, like a stale pid file or misconfigurations in OVSDB. - ResetOVSService +switch ($OVSRunMode) +{ + "service" { + if ($RemoveOVS) { + RemoveOVSService + } else { + # ResetOVSService is called to recover Windows Services "ovsdb-server" and "ovs-vswitchd" if they are removed + # unexpectedly or their status is not correct, e.g., ovs-vswitchd fails to go into Running. + # This might happen after the Windows host is restarted abnormally, in which case some stale configurations + # can prevent ovs-vswitchd from running, like a stale pid file or misconfigurations in OVSDB. + ResetOVSService + } + } + "container" { + if (Test-Path -Path $OVS_DB_PATH) { + Remove-Item -Path $OVS_DB_PATH -Force + if (Test-Path -Path $OVS_DB_PATH) { + Write-Host "Failed to delete file: $OVS_DB_PATH" + exit 1 + } + } + } } + if ($RenewIPConfig) { ipconfig /renew } diff --git a/hack/windows/Install-OVS.ps1 b/hack/windows/Install-OVS.ps1 index 32d6349dbb0..9500a294dca 100644 --- a/hack/windows/Install-OVS.ps1 +++ b/hack/windows/Install-OVS.ps1 @@ -21,6 +21,10 @@ .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. + + .PARAMETER InstallUserspace + Specifies whether OVS userspace processes are included in the installation. If false, these processes will not + be installed as a Windows service on the host. #> Param( [parameter(Mandatory = $false)] [string] $DownloadDir, @@ -28,7 +32,8 @@ Param( [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] $ImportCertificate = $true, + [parameter(Mandatory = $false)] [bool] $InstallUserspace = $true ) $ErrorActionPreference = "Stop" @@ -259,8 +264,10 @@ DownloadOVS InstallOVS -InstallDependency - -ConfigOVS +if ($InstallUserspace -eq $true) { + InstallDependency + ConfigOVS +} +icacls $OVSInstallDir /grant "NT AUTHORITY\SYSTEM:(OI)(CI)F" /T Log "OVS Installation Complete!" diff --git a/hack/windows/Prepare-Node.ps1 b/hack/windows/Prepare-Node.ps1 index 92ffcb07bd4..89857d251b9 100644 --- a/hack/windows/Prepare-Node.ps1 +++ b/hack/windows/Prepare-Node.ps1 @@ -22,6 +22,10 @@ Install OVS .PARAMETER NodeIP The node ip used by kubelet +.PARAMETER InstallOVSUserspace +Specifies whether OVS userspace processes are included in the installation. If false, these processes will not +be installed as a Windows service on the host. + .EXAMPLE PS> .\Prepare-Node.ps1 -KubernetesVersion v1.18.0 -InstallOVS -NodeIP 192.168.1.10 @@ -31,7 +35,8 @@ Param( [parameter(Mandatory = $false, HelpMessage="Kubernetes version to use")] [string] $KubernetesVersion="v1.18.0", [parameter(Mandatory = $true, HelpMessage="Node IP")] [string] $NodeIP, [parameter(Mandatory = $false)] [switch] $InstallOVS = $false, - [parameter(Mandatory = $false, HelpMessage="Kubernetes download")] [string] $KubernetesURL="dl.k8s.io" + [parameter(Mandatory = $false, HelpMessage="Kubernetes download")] [string] $KubernetesURL="dl.k8s.io", + [parameter(Mandatory = $false)] [bool] $InstallOVSUserspace = $true ) $ErrorActionPreference = 'Stop' @@ -127,5 +132,5 @@ New-NetFirewallRule -Name kubelet -DisplayName 'kubelet' -Enabled True -Directio if ($InstallOVS) { Write-Host "Installing OVS" - & .\Install-OVS.ps1 + & .\Install-OVS.ps1 -InstallUserspace $InstallOVSUserspace } diff --git a/hack/windows/Uninstall-OVS.ps1 b/hack/windows/Uninstall-OVS.ps1 index 962f0a79e0e..b52f477bd51 100644 --- a/hack/windows/Uninstall-OVS.ps1 +++ b/hack/windows/Uninstall-OVS.ps1 @@ -17,19 +17,24 @@ if ($DeleteBridges) { } } -# Stop and delete ovs-vswitchd service -stop-service ovs-vswitchd -sc.exe delete ovs-vswitchd +# Stop and delete ovs-vswitchd service if it exists if (Get-Service ovs-vswitchd -ErrorAction SilentlyContinue) { - Write-Host "Failed to delete ovs-vswitchd service, exit." - exit 1 + stop-service ovs-vswitchd + sc.exe delete ovs-vswitchd + if (Get-Service ovs-vswitchd -ErrorAction SilentlyContinue) { + Write-Host "Failed to delete ovs-vswitchd service, exit." + exit 1 + } } -# Stop and delete ovsdb-service service -stop-service ovsdb-server -sc.exe delete ovsdb-server + +# Stop and delete ovsdb-service service if it exists if (Get-Service ovsdb-server -ErrorAction SilentlyContinue) { - Write-Host "Failed to delete ovs-vswitchd service, exit." - exit 1 + stop-service ovsdb-server + sc.exe delete ovsdb-server + if (Get-Service ovsdb-server -ErrorAction SilentlyContinue) { + Write-Host "Failed to delete ovs-vswitchd service, exit." + exit 1 + } } # Uninstall OVS kernel driver cmd /c "cd $OVSDriverDir && uninstall.cmd"