Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d385030
chore: Remove --pod-ip option
booxter Sep 30, 2025
a9d76d6
fix: --logfile-maxsize is in megabytes, not bytes
booxter Sep 30, 2025
d4136cc
fix: list allowed values for --platform-type option
booxter Sep 30, 2025
317bdd6
Enable ovn-ci workflow on release branches
npinaeva Oct 9, 2025
65e44a7
unskip cases as bug is verified
zhaozhanqi Oct 11, 2025
cde88f2
The expect expectedEndpointsNum should be 2 times endpoints for duals…
zhaozhanqi Oct 13, 2025
0651593
Fix named port handling in externalTrafficPolicy Local services
andreaskaris Sep 23, 2025
282b01e
Extends unit test coverage for named port handling in ETP local
andreaskaris Sep 23, 2025
651759c
E2E service: Move checkNumberOf.. to util.go
andreaskaris Sep 26, 2025
2fff366
E2E service: Fix potential flake in conn to an ext IP using src port
andreaskaris Sep 26, 2025
1ed9749
chore: Remove SetTaintOnNode
dave-tucker Oct 14, 2025
b39031c
Increase single target attempts
trozet Oct 14, 2025
0311aa3
Merge pull request #5647 from zhaozhanqi/remove-skip
trozet Oct 14, 2025
2871cda
RunOVSAppctl() doesn't work when ovs is run on host and hostPID is false
Oct 13, 2025
628c3c4
Fixes BFD timeout for external gateway E2E
trozet Oct 14, 2025
8e7b2c6
traffic-flow-tests: update to latest version of k8s-tft
thom311 Mar 20, 2025
cd70830
E2E service: Add test for named port handling with ETP=Local services
andreaskaris Sep 23, 2025
2de612a
Merge pull request #5131 from thom311/th/tft-update
tssurya Oct 15, 2025
a23f664
Merge pull request #5652 from l8huang/ovs-appctl
trozet Oct 15, 2025
9bb2f6f
Merge pull request #5656 from trozet/fix_exgw_tests
trozet Oct 15, 2025
9cfeb54
Merge pull request #5615 from booxter/logfile-maxsize-mb
trozet Oct 15, 2025
14d8e50
Merge pull request #5655 from dave-tucker/remove-taint
trozet Oct 15, 2025
04a98b6
Merge pull request #5613 from booxter/remove-pod-ip
trozet Oct 15, 2025
76f6439
Reintroduce completed pod check in shouldReleaseDeletedPod
jcaamano Oct 14, 2025
1bb538c
Merge pull request #5637 from npinaeva/release-ci
trozet Oct 16, 2025
36078b7
Merge pull request #5583 from andreaskaris/port-0-issue
trozet Oct 16, 2025
384408a
Merge pull request #5621 from booxter/construct-platform-types
trozet Oct 16, 2025
2afbaf6
Skip Pending pods in EgressIP status updates
pperiyasamy Sep 25, 2025
c74e67e
[okep: layer2 router topology] Add clarification for joinIP routes.
npinaeva Oct 17, 2025
f077fdd
Merge pull request #5665 from npinaeva/l2-okep-upd
trozet Oct 17, 2025
81ec1e0
Merge upstream/master into master with conflicts (10-19-2025)
Oct 19, 2025
fed1225
Resolve merge conflicts
pperiyasamy Oct 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 46 additions & 46 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: ovn-ci
on:
merge_group:
pull_request:
branches: [ master ]
branches: [ master,release-* ]
# Only run jobs if at least one non-doc file is changed
paths-ignore:
- '**/*.md'
Expand All @@ -30,7 +30,7 @@ env:

# This must be a directory
CI_IMAGE_CACHE: tmp/image_cache/
CI_IMAGE_MASTER_TAR: image-master.tar
CI_IMAGE_BASE_TAR: image-base.tar
CI_IMAGE_PR_TAR: image-pr.tar
CI_DIST_IMAGES_OUTPUT: dist/images/_output/

Expand Down Expand Up @@ -65,49 +65,49 @@ jobs:
working-directory: go-controller
args: --modules-download-mode=vendor --timeout=15m0s --verbose

build-master:
name: Build-master
build-base:
name: Build-base
runs-on: ubuntu-24.04
steps:
# Create a cache for the built master image
- name: Restore master image cache
id: image_cache_master
# Create a cache for the built base image
- name: Restore base image cache
id: image_cache_base
uses: actions/cache@v4
with:
path: |
${{ env.CI_IMAGE_CACHE }}
key: ${{ github.run_id }}-image-cache-master
# if CI_IMAGE_MASTER_TAR isn't in cache, try pulling it and saving to the cache rather
key: ${{ github.run_id }}-image-cache-base
# if CI_IMAGE_BASE_TAR isn't in cache, try pulling it and saving to the cache rather
# than building, resort back to building if the cache isn't populated and
# pulling the image fails.
- name: Check if master image build is needed
id: is_master_image_build_needed
- name: Check if base image build is needed
id: is_base_image_build_needed
continue-on-error: false
run: |
set -x
if [ -f ${CI_IMAGE_CACHE}${CI_IMAGE_MASTER_TAR}.gz ]; then
cp ${CI_IMAGE_CACHE}/${CI_IMAGE_MASTER_TAR}.gz ${CI_IMAGE_MASTER_TAR}.gz
gunzip ${CI_IMAGE_MASTER_TAR}.gz
echo "MASTER_IMAGE_RESTORED_FROM_CACHE=true" >> "$GITHUB_OUTPUT"
echo "MASTER_IMAGE_RESTORED=true" >> "$GITHUB_OUTPUT"
if [ -f ${CI_IMAGE_CACHE}${CI_IMAGE_BASE_TAR}.gz ]; then
cp ${CI_IMAGE_CACHE}/${CI_IMAGE_BASE_TAR}.gz ${CI_IMAGE_BASE_TAR}.gz
gunzip ${CI_IMAGE_BASE_TAR}.gz
echo "BASE_IMAGE_RESTORED_FROM_CACHE=true" >> "$GITHUB_OUTPUT"
echo "BASE_IMAGE_RESTORED=true" >> "$GITHUB_OUTPUT"
exit 0
fi

if docker pull ghcr.io/ovn-kubernetes/ovn-kubernetes/ovn-kube-fedora:master; then
docker tag ghcr.io/ovn-kubernetes/ovn-kubernetes/ovn-kube-fedora:master ovn-daemonset-fedora:dev
if docker pull ghcr.io/ovn-kubernetes/ovn-kubernetes/ovn-kube-fedora:${{ github.base_ref || github.ref_name }}; then
docker tag ghcr.io/ovn-kubernetes/ovn-kubernetes/ovn-kube-fedora:${{ github.base_ref || github.ref_name }} ovn-daemonset-fedora:dev

echo "MASTER_IMAGE_RESTORED=true" >> "$GITHUB_OUTPUT"
echo "BASE_IMAGE_RESTORED=true" >> "$GITHUB_OUTPUT"
exit 0
fi
# only run the following steps if the master image was not found in the cache
- name: Check out code into the Go module directory - from master branch
if: steps.is_master_image_build_needed.outputs.MASTER_IMAGE_RESTORED != 'true' && success()
# only run the following steps if the base image was not found in the cache
- name: Check out code into the Go module directory - from base branch
if: steps.is_base_image_build_needed.outputs.BASE_IMAGE_RESTORED != 'true' && success()
uses: actions/checkout@v4
with:
ref: master
ref: ${{ github.base_ref || github.ref_name }}

- name: Set up Go
if: steps.is_master_image_build_needed.outputs.MASTER_IMAGE_RESTORED != 'true' && success()
if: steps.is_base_image_build_needed.outputs.BASE_IMAGE_RESTORED != 'true' && success()
uses: actions/setup-go@v5
with:
go-version-file: 'go-controller/go.mod'
Expand All @@ -118,45 +118,45 @@ jobs:
cache: false
id: go

- name: Build - from master branch
if: steps.is_master_image_build_needed.outputs.MASTER_IMAGE_RESTORED != 'true' && success()
- name: Build - from base branch
if: steps.is_base_image_build_needed.outputs.BASE_IMAGE_RESTORED != 'true' && success()
run: |
set -x
pushd go-controller
make
make windows
popd

- name: Build docker image - from master branch
if: steps.is_master_image_build_needed.outputs.MASTER_IMAGE_RESTORED != 'true' && success()
- name: Build docker image - from base branch
if: steps.is_base_image_build_needed.outputs.BASE_IMAGE_RESTORED != 'true' && success()
run: |
make -C dist/images \
IMAGE=ovn-daemonset-fedora:dev \
OVN_REPO=${{ env.OVN_REPO }} \
OVN_GITREF=${{ env.OVN_GITREF }} \
fedora-image

- name: Cache master image
if: steps.is_master_image_build_needed.outputs.MASTER_IMAGE_RESTORED_FROM_CACHE != 'true' && success()
- name: Cache base image
if: steps.is_base_image_build_needed.outputs.BASE_IMAGE_RESTORED_FROM_CACHE != 'true' && success()
continue-on-error: false
run: |
set -x
if [ -f ${CI_IMAGE_CACHE}${CI_IMAGE_MASTER_TAR} ]; then
rm -f ${CI_IMAGE_CACHE}${CI_IMAGE_MASTER_TAR}
if [ -f ${CI_IMAGE_CACHE}${CI_IMAGE_BASE_TAR} ]; then
rm -f ${CI_IMAGE_CACHE}${CI_IMAGE_BASE_TAR}
fi
if [ -f ${CI_IMAGE_CACHE}${CI_IMAGE_MASTER_TAR}.gz ]; then
rm -f ${CI_IMAGE_CACHE}${CI_IMAGE_MASTER_TAR}.gz
if [ -f ${CI_IMAGE_CACHE}${CI_IMAGE_BASE_TAR}.gz ]; then
rm -f ${CI_IMAGE_CACHE}${CI_IMAGE_BASE_TAR}.gz
fi
docker save ovn-daemonset-fedora:dev -o ${CI_IMAGE_MASTER_TAR}
docker save ovn-daemonset-fedora:dev -o ${CI_IMAGE_BASE_TAR}
mkdir -p ${CI_IMAGE_CACHE}
cp ${CI_IMAGE_MASTER_TAR} ${CI_IMAGE_CACHE}${CI_IMAGE_MASTER_TAR}
gzip ${CI_IMAGE_CACHE}${CI_IMAGE_MASTER_TAR}
cp ${CI_IMAGE_BASE_TAR} ${CI_IMAGE_CACHE}${CI_IMAGE_BASE_TAR}
gzip ${CI_IMAGE_CACHE}${CI_IMAGE_BASE_TAR}

# run the following always if none of the steps before failed
- uses: actions/upload-artifact@v4
with:
name: test-image-master
path: ${{ env.CI_IMAGE_MASTER_TAR }}
name: test-image-base
path: ${{ env.CI_IMAGE_BASE_TAR }}

build-pr:
name: Build-PR
Expand Down Expand Up @@ -273,12 +273,12 @@ jobs:
path: ${{ env.CI_DIST_IMAGES_OUTPUT }}/${{ env.CI_IMAGE_PR_TAR }}

ovn-upgrade-e2e:
name: Upgrade OVN from Master to PR branch based image
name: Upgrade OVN from Base to PR branch based image
if: github.event_name != 'schedule'
runs-on: ubuntu-24.04
timeout-minutes: 120
needs:
- build-master
- build-base
- build-pr
strategy:
fail-fast: false
Expand All @@ -296,10 +296,10 @@ jobs:
OVN_MULTICAST_ENABLE: "false"
steps:

- name: Check out code into the Go module directory - from Master branch
- name: Check out code into the Go module directory - from Base branch
uses: actions/checkout@v4
with:
ref: master
ref: ${{ github.base_ref || github.ref_name }}

- name: Set up Go
uses: actions/setup-go@v5
Expand All @@ -324,10 +324,10 @@ jobs:
- name: Free up disk space
uses: ./.github/actions/free-disk-space

- name: Download test-image-master
- name: Download test-image-base
uses: actions/download-artifact@v4
with:
name: test-image-master
name: test-image-base

- name: Disable ufw
# For IPv6 and Dualstack, ufw (Uncomplicated Firewall) should be disabled.
Expand All @@ -337,7 +337,7 @@ jobs:

- name: Load docker image
run: |
docker load --input ${CI_IMAGE_MASTER_TAR} && rm -rf ${CI_IMAGE_MASTER_TAR}
docker load --input ${CI_IMAGE_BASE_TAR} && rm -rf ${CI_IMAGE_BASE_TAR}

- name: kind setup
run: |
Expand Down
9 changes: 8 additions & 1 deletion docs/okeps/okep-5094-layer2-transit-router.md
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,14 @@ Nodes using the new topology must perform the following actions:
- Create a tmp transit router port `trtos-layer2-switch-upgrade` with the GR MAC address
- Add a dummy IP from the join subnet to the `trtos-layer2-switch-upgrade` port to enable pod on node1 -> remote GR traffic.
- Add `trasit_router` routes to steer joinIP traffic for the ole nodes to the `trtos-layer2-switch-upgrade` port.
These routes look silly, but they work, like `100.65.0.3 100.65.0.3 dst-ip` for every joinIP of the old nodes.
These routes look weird, but they work, like `100.65.0.3 100.65.0.3 dst-ip` for every joinIP of the old nodes. We need this because
in OVN routes with dst-ip and src-ip policies are evaluated at the same time and selected based on longest-prefix-match,
and we have the following route for pod network `10.10.0.0/24`:
`10.10.0.0/24 10.10.0.2 src-ip`
Connected route for the join IP is based on the joinSubnet, which is always `/16`.
That means, that for traffic with src IP from the podSubnet dst IP from joinSubnet,
the winning route is joinIP if podSubnet mask is <= 16 and podSubnet otherwise.
That is not the desired behavior, that is why we add always-winning routes (aka /32 or /128) for joinIPs.

We need to make sure joinSubnet works between upgraded and non-upgraded nodes, as this is the only network that both topologies
understand:
Expand Down
28 changes: 25 additions & 3 deletions go-controller/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strings"
"time"

"github.com/openshift/api/config/v1"
"github.com/urfave/cli/v2"
gcfg "gopkg.in/gcfg.v1"
lumberjack "gopkg.in/natefinch/lumberjack.v2"
Expand All @@ -28,6 +29,28 @@ import (
"github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types"
)

// getSupportedPlatformTypes returns a list of all supported platform types
func getSupportedPlatformTypes() []string {
return []string{
string(v1.AWSPlatformType), // "AWS"
string(v1.AzurePlatformType), // "Azure"
string(v1.BareMetalPlatformType), // "BareMetal"
string(v1.GCPPlatformType), // "GCP"
string(v1.LibvirtPlatformType), // "Libvirt"
string(v1.OpenStackPlatformType), // "OpenStack"
string(v1.NonePlatformType), // "None"
string(v1.VSpherePlatformType), // "VSphere"
string(v1.OvirtPlatformType), // "oVirt"
string(v1.IBMCloudPlatformType), // "IBMCloud"
string(v1.KubevirtPlatformType), // "KubeVirt"
string(v1.EquinixMetalPlatformType), // "EquinixMetal"
string(v1.PowerVSPlatformType), // "PowerVS"
string(v1.AlibabaCloudPlatformType), // "AlibabaCloud"
string(v1.NutanixPlatformType), // "Nutanix"
string(v1.ExternalPlatformType), // "External"
}
}

// DefaultEncapPort number used if not supplied
const DefaultEncapPort = 6081

Expand Down Expand Up @@ -377,7 +400,6 @@ type KubernetesConfig struct {
ServiceCIDRs []*net.IPNet
OVNConfigNamespace string `gcfg:"ovn-config-namespace"`
OVNEmptyLbEvents bool `gcfg:"ovn-empty-lb-events"`
PodIP string `gcfg:"pod-ip"` // UNUSED
RawNoHostSubnetNodes string `gcfg:"no-hostsubnet-nodes"`
NoHostSubnetNodes labels.Selector
HostNetworkNamespace string `gcfg:"host-network-namespace"`
Expand Down Expand Up @@ -945,7 +967,7 @@ var CommonFlags = []cli.Flag{
// Logfile rotation parameters
&cli.IntFlag{
Name: "logfile-maxsize",
Usage: "Maximum size in bytes of the log file before it gets rolled",
Usage: "Maximum size in megabytes of the log file before it gets rolled",
Destination: &cliConfig.Logging.LogFileMaxSize,
Value: Logging.LogFileMaxSize,
},
Expand Down Expand Up @@ -1277,7 +1299,7 @@ var K8sFlags = []cli.Flag{
&cli.StringFlag{
Name: "platform-type",
Usage: "The cloud provider platform type ovn-kubernetes is deployed on. " +
"Valid values can be found in: https://github.com/ovn-org/ovn-kubernetes/blob/master/go-controller/vendor/github.com/openshift/api/config/v1/types_infrastructure.go#L130-L172",
"Valid values: " + strings.Join(getSupportedPlatformTypes(), ", "),
Destination: &cliConfig.Kubernetes.PlatformType,
Value: Kubernetes.PlatformType,
},
Expand Down
64 changes: 0 additions & 64 deletions go-controller/pkg/kube/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ type Interface interface {
SetAnnotationsOnService(namespace, serviceName string, annotations map[string]interface{}) error
SetAnnotationsOnNode(nodeName string, annotations map[string]interface{}) error
SetAnnotationsOnNamespace(namespaceName string, annotations map[string]interface{}) error
SetTaintOnNode(nodeName string, taint *corev1.Taint) error
RemoveTaintFromNode(nodeName string, taint *corev1.Taint) error
SetLabelsOnNode(nodeName string, labels map[string]interface{}) error
PatchNode(old, new *corev1.Node) error
UpdateNodeStatus(node *corev1.Node) error
Expand Down Expand Up @@ -197,68 +195,6 @@ func (k *Kube) SetAnnotationsOnService(namespace, name string, annotations map[s
return err
}

// SetTaintOnNode tries to add a new taint to the node. If the taint already exists, it doesn't do anything.
func (k *Kube) SetTaintOnNode(nodeName string, taint *corev1.Taint) error {
node, err := k.GetNodeForWindows(nodeName)
if err != nil {
klog.Errorf("Unable to retrieve node %s for tainting %s: %v", nodeName, taint.ToString(), err)
return err
}
newNode := node.DeepCopy()
nodeTaints := newNode.Spec.Taints

var newTaints []corev1.Taint
for i := range nodeTaints {
if taint.MatchTaint(&nodeTaints[i]) {
klog.Infof("Taint %s already exists on Node %s", taint.ToString(), node.Name)
return nil
}
newTaints = append(newTaints, nodeTaints[i])
}

klog.Infof("Setting taint %s on Node %s", taint.ToString(), node.Name)
newTaints = append(newTaints, *taint)
newNode.Spec.Taints = newTaints
err = k.PatchNode(node, newNode)
if err != nil {
klog.Errorf("Unable to add taint %s on node %s: %v", taint.ToString(), node.Name, err)
return err
}

klog.Infof("Added taint %s on node %s", taint.ToString(), node.Name)
return nil
}

// RemoveTaintFromNode removes all the taints that have the same key and effect from the node.
// If the taint doesn't exist, it doesn't do anything.
func (k *Kube) RemoveTaintFromNode(nodeName string, taint *corev1.Taint) error {
node, err := k.GetNodeForWindows(nodeName)
if err != nil {
klog.Errorf("Unable to retrieve node %s for tainting %s: %v", nodeName, taint.ToString(), err)
return err
}
newNode := node.DeepCopy()
nodeTaints := newNode.Spec.Taints

var newTaints []corev1.Taint
for i := range nodeTaints {
if taint.MatchTaint(&nodeTaints[i]) {
klog.Infof("Removing taint %s from Node %s", taint.ToString(), node.Name)
continue
}
newTaints = append(newTaints, nodeTaints[i])
}

newNode.Spec.Taints = newTaints
err = k.PatchNode(node, newNode)
if err != nil {
klog.Errorf("Unable to remove taint %s on node %s: %v", taint.ToString(), node.Name, err)
return err
}
klog.Infof("Removed taint %s on node %s", taint.ToString(), node.Name)
return nil
}

// SetLabelsOnNode takes the node name and map of key/value string pairs to set as labels
func (k *Kube) SetLabelsOnNode(nodeName string, labels map[string]interface{}) error {
patch := struct {
Expand Down
Loading