From fe3baf678a6cc5ef63a18958d093520a72687ace Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Wed, 21 Jun 2023 21:45:40 -0400 Subject: [PATCH 1/9] add Linux test cases for connectivity --- .../datapath/datapath_linux_test.go | 238 ++++++++++++++++++ .../manifests/datapath/linux-deployment.yaml | 74 ++++++ test/internal/datapath/datapath_linux.go | 167 ++++++++++++ test/internal/k8sutils/utils.go | 1 - 4 files changed, 479 insertions(+), 1 deletion(-) create mode 100644 test/integration/datapath/datapath_linux_test.go create mode 100644 test/integration/manifests/datapath/linux-deployment.yaml create mode 100644 test/internal/datapath/datapath_linux.go diff --git a/test/integration/datapath/datapath_linux_test.go b/test/integration/datapath/datapath_linux_test.go new file mode 100644 index 0000000000..acf9cea2f1 --- /dev/null +++ b/test/integration/datapath/datapath_linux_test.go @@ -0,0 +1,238 @@ +//go:build connection + +package connection + +import ( + "context" + "flag" + "fmt" + "testing" + "time" + + "github.com/Azure/azure-container-networking/test/integration" + "github.com/Azure/azure-container-networking/test/integration/goldpinger" + k8sutils "github.com/Azure/azure-container-networking/test/internal/k8sutils" + "github.com/Azure/azure-container-networking/test/internal/retry" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + apiv1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + LinuxDeployYamlPath = "../manifests/datapath/linux-deployment.yaml" + podLabelKey = "app" + podCount = 2 + nodepoolKey = "agentpool" + maxRetryDelaySeconds = 10 + defaultTimeoutSeconds = 120 + defaultRetryDelaySeconds = 1 + goldpingerRetryCount = 24 + goldpingerDelayTimeSeconds = 5 +) + +var ( + podPrefix = flag.String("podName", "goldpinger", "Prefix for test pods") + podNamespace = flag.String("namespace", "datapath-linux", "Namespace for test pods") + nodepoolSelector = flag.String("nodepoolSelector", "nodepool1", "Provides nodepool as a Node-Selector for pods") + defaultRetrier = retry.Retrier{ + Attempts: 10, + Delay: defaultRetryDelaySeconds * time.Second, + } +) + +/* +This test assumes that you have the current credentials loaded in your default kubeconfig for a +k8s cluster with a Linux nodepool consisting of at least 2 Linux nodes. +*** The expected nodepool name is npwin, if the nodepool has a diferent name ensure that you change nodepoolSelector with: + -nodepoolSelector="yournodepoolname" + +To run the test use one of the following commands: +go test -count=1 test/integration/datapath/datapath_linux_test.go -timeout 3m -tags connection -run ^TestDatapathLinux$ -tags=connection + or +go test -count=1 test/integration/datapath/datapath_linux_test.go -timeout 3m -tags connection -run ^TestDatapathLinux$ -podName=acnpod -nodepoolSelector=npwina -tags=connection + + +This test checks pod to pod, pod to node, and pod to internet for datapath connectivity. + +Timeout context is controled by the -timeout flag. + +*/ + +func TestDatapathLinux(t *testing.T) { + ctx := context.Background() + + t.Log("Create Clientset") + clientset, err := k8sutils.MustGetClientset() + if err != nil { + require.NoError(t, err, "could not get k8s clientset: %v", err) + } + t.Log("Get REST config") + restConfig := k8sutils.MustGetRestConfig(t) + + t.Log("Create Label Selectors") + + podLabelSelector := fmt.Sprintf("%s=%s", podLabelKey, *podPrefix) + nodeLabelSelector := fmt.Sprintf("%s=%s", nodepoolKey, *nodepoolSelector) + + t.Log("Get Nodes") + nodes, err := k8sutils.GetNodeListByLabelSelector(ctx, clientset, nodeLabelSelector) + if err != nil { + require.NoError(t, err, "could not get k8s node list: %v", err) + } + + // Test Namespace + t.Log("Create Namespace") + err = k8sutils.MustCreateNamespace(ctx, clientset, *podNamespace) + createPodFlag := !(apierrors.IsAlreadyExists(err)) + t.Logf("%v", createPodFlag) + + if createPodFlag { + t.Log("Creating Linux pods through deployment") + deployment, err := k8sutils.MustParseDeployment(LinuxDeployYamlPath) + if err != nil { + require.NoError(t, err) + } + + // Fields for overwritting existing deployment yaml. + // Defaults from flags will not change anything + deployment.Spec.Selector.MatchLabels[podLabelKey] = *podPrefix + deployment.Spec.Template.ObjectMeta.Labels[podLabelKey] = *podPrefix + deployment.Spec.Template.Spec.NodeSelector[nodepoolKey] = *nodepoolSelector + deployment.Name = *podPrefix + deployment.Namespace = *podNamespace + + t.Logf("deployment Spec Template is %+v", deployment.Spec.Template) + deploymentsClient := clientset.AppsV1().Deployments(*podNamespace) + err = k8sutils.MustCreateDeployment(ctx, deploymentsClient, deployment) + if err != nil { + require.NoError(t, err) + } + t.Logf("podNamespace is %s", *podNamespace) + t.Logf("podLabelSelector is %s", podLabelSelector) + + t.Log("Waiting for pods to be running state") + err = k8sutils.WaitForPodsRunning(ctx, clientset, *podNamespace, podLabelSelector) + if err != nil { + require.NoError(t, err) + } + t.Log("Successfully created customer linux pods") + } else { + // Checks namespace already exists from previous attempt + t.Log("Namespace already exists") + + t.Log("Checking for pods to be running state") + err = k8sutils.WaitForPodsRunning(ctx, clientset, *podNamespace, podLabelSelector) + if err != nil { + require.NoError(t, err) + } + } + t.Log("Checking Linux test environment") + for _, node := range nodes.Items { + + pods, err := k8sutils.GetPodsByNode(ctx, clientset, *podNamespace, podLabelSelector, node.Name) + if err != nil { + require.NoError(t, err, "could not get k8s clientset: %v", err) + } + if len(pods.Items) <= 1 { + t.Logf("%s", node.Name) + require.NoError(t, errors.New("Less than 2 pods on node")) + } + } + t.Log("Linux test environment ready") + + t.Run("Linux ping tests", func(t *testing.T) { + // Check goldpinger health + t.Run("all pods have IPs assigned", func(t *testing.T) { + podsClient := clientset.CoreV1().Pods(*podNamespace) + + checkPodIPsFn := func() error { + podList, err := podsClient.List(ctx, metav1.ListOptions{LabelSelector: "app=goldpinger"}) + t.Logf("podList is %+v", podList) + if err != nil { + return err + } + + if len(podList.Items) == 0 { + return errors.New("no pods scheduled") + } + + for _, pod := range podList.Items { + if pod.Status.Phase == apiv1.PodPending { + return errors.New("some pods still pending") + } + } + + for _, pod := range podList.Items { + if pod.Status.PodIP == "" { + return errors.New("a pod has not been allocated an IP") + } + } + + return nil + } + err := defaultRetrier.Do(ctx, checkPodIPsFn) + if err != nil { + t.Fatalf("not all pods were allocated IPs: %v", err) + } + t.Log("all pods have been allocated IPs") + }) + + t.Run("all linux pods can ping each other", func(t *testing.T) { + pfOpts := k8s.PortForwardingOpts{ + Namespace: "default", + LabelSelector: "type=goldpinger-pod", + LocalPort: 9090, + DestPort: 8080, + } + + pf, err := k8s.NewPortForwarder(restConfig, t, pfOpts) + if err != nil { + t.Fatal(err) + } + + portForwardCtx, cancel := context.WithTimeout(ctx, defaultTimeoutSeconds*time.Second) + defer cancel() + + portForwardFn := func() error { + err := pf.Forward(portForwardCtx) + if err != nil { + t.Logf("unable to start port forward: %v", err) + return err + } + return nil + } + if err := defaultRetrier.Do(portForwardCtx, portForwardFn); err != nil { + t.Fatalf("could not start port forward within %ds: %v", defaultTimeoutSeconds, err) + } + defer pf.Stop() + + gpClient := goldpinger.Client{Host: pf.Address()} + + clusterCheckCtx, cancel := context.WithTimeout(ctx, 3*time.Minute) + defer cancel() + clusterCheckFn := func() error { + clusterState, err := gpClient.CheckAll(clusterCheckCtx) + if err != nil { + return err + } + + stats := goldpinger.ClusterStats(clusterState) + stats.PrintStats() + if stats.AllPingsHealthy() { + return nil + } + + return errors.New("not all pings are healthy") + } + retrier := retry.Retrier{Attempts: goldpingerRetryCount, Delay: goldpingerDelayTimeSeconds * time.Second} + if err := retrier.Do(clusterCheckCtx, clusterCheckFn); err != nil { + t.Fatalf("goldpinger pods network health could not reach healthy state after %d seconds: %v", goldpingerRetryCount*goldpingerDelayTimeSeconds, err) + } + + t.Log("all pings successful!") + }) + }) +} diff --git a/test/integration/manifests/datapath/linux-deployment.yaml b/test/integration/manifests/datapath/linux-deployment.yaml new file mode 100644 index 0000000000..4b029c28c3 --- /dev/null +++ b/test/integration/manifests/datapath/linux-deployment.yaml @@ -0,0 +1,74 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: goldpinger-deploy + namespace: datapath-linux +spec: + replicas: 4 + selector: + matchLabels: + app: goldpinger + template: + metadata: + labels: + app: goldpinger + spec: + serviceAccount: "goldpinger-serviceaccount" + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 2000 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: "app" + operator: In + values: + - goldpinger + topologyKey: "kubernetes.io/hostname" + containers: + - name: goldpinger + env: + - name: HOST + value: "0.0.0.0" + - name: PORT + value: "8080" + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + image: "docker.io/bloomberg/goldpinger:v3.0.0" + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + resources: + limits: + memory: 80Mi + requests: + cpu: 1m + memory: 40Mi + ports: + - containerPort: 8080 + name: http + readinessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + nodeSelector: + kubernetes.io/os: linux diff --git a/test/internal/datapath/datapath_linux.go b/test/internal/datapath/datapath_linux.go new file mode 100644 index 0000000000..f32d4cda3f --- /dev/null +++ b/test/internal/datapath/datapath_linux.go @@ -0,0 +1,167 @@ +package datapath + +import ( + "context" + "fmt" + + "github.com/Azure/azure-container-networking/test/internal/k8sutils" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" +) + +func LinuxPodToPodPingTestSameNode(ctx context.Context, clientset *kubernetes.Clientset, nodeName, podNamespace, labelSelector string, rc *restclient.Config) error { + logrus.Infof("Get Pods for Linux Node: %s", nodeName) + pods, err := k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName) + if err != nil { + logrus.Error(err) + return errors.Wrap(err, "k8s api call") + } + if len(pods.Items) <= 1 { + return errors.New("Less than 2 pods on node") + } + + // Get first pod on this node + firstPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", firstPod.Name, err)) + } + logrus.Infof("First pod: %v %v", firstPod.Name, firstPod.Status.PodIP) + + // Get the second pod on this node + secondPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[1].Name, metav1.GetOptions{}) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", secondPod.Name, err)) + } + logrus.Infof("Second pod: %v %v", secondPod.Name, secondPod.Status.PodIP) + + // Ping the second pod from the first pod + return podTest(ctx, clientset, firstPod, []string{"ping", secondPod.Status.PodIP}, rc, pingPassedWindows) +} + +// func WindowsPodToPodPingTestDiffNode(ctx context.Context, clientset *kubernetes.Clientset, nodeName1, nodeName2, podNamespace, labelSelector string, rc *restclient.Config) error { +// logrus.Infof("Get Pods for Node 1: %s", nodeName1) +// // Node 1 +// pods, err := k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName1) +// if err != nil { +// logrus.Error(err) +// return errors.Wrap(err, "k8s api call") +// } +// firstPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) +// if err != nil { +// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", firstPod.Name, err)) +// } +// logrus.Infof("First pod: %v %v", firstPod.Name, firstPod.Status.PodIP) + +// logrus.Infof("Get Pods for Node 2: %s", nodeName2) +// // Node 2 +// pods, err = k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName2) +// if err != nil { +// logrus.Error(err) +// return errors.Wrap(err, "k8s api call") +// } +// secondPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) +// if err != nil { +// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", secondPod.Name, err)) +// } +// logrus.Infof("Second pod: %v %v", secondPod.Name, secondPod.Status.PodIP) + +// // Ping the second pod from the first pod located on different nodes +// return podTest(ctx, clientset, firstPod, []string{"ping", secondPod.Status.PodIP}, rc, pingPassedWindows) +// } + +// func WindowsPodToNode(ctx context.Context, clientset *kubernetes.Clientset, nodeName, nodeIP, podNamespace, labelSelector string, rc *restclient.Config) error { +// logrus.Infof("Get Pods by Node: %s %s", nodeName, nodeIP) +// pods, err := k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName) +// if err != nil { +// logrus.Error(err) +// return errors.Wrap(err, "k8s api call") +// } +// if len(pods.Items) <= 1 { +// return errors.New("Less than 2 pods on node") +// } +// // Get first pod on this node +// firstPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) +// if err != nil { +// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", firstPod.Name, err)) +// } +// logrus.Infof("First pod: %v", firstPod.Name) + +// // Get the second pod on this node +// secondPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[1].Name, metav1.GetOptions{}) +// if err != nil { +// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", secondPod.Name, err)) +// } +// logrus.Infof("Second pod: %v", secondPod.Name) + +// // Ping from pod to node +// resultOne := podTest(ctx, clientset, firstPod, []string{"ping", nodeIP}, rc, pingPassedWindows) +// resultTwo := podTest(ctx, clientset, secondPod, []string{"ping", nodeIP}, rc, pingPassedWindows) + +// if resultOne != nil { +// return resultOne +// } + +// if resultTwo != nil { +// return resultTwo +// } + +// return nil +// } + +// func WindowsPodToInternet(ctx context.Context, clientset *kubernetes.Clientset, nodeName, podNamespace, labelSelector string, rc *restclient.Config) error { +// logrus.Infof("Get Pods by Node: %s", nodeName) +// pods, err := k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName) +// if err != nil { +// logrus.Error(err) +// return errors.Wrap(err, "k8s api call") +// } +// if len(pods.Items) <= 1 { +// return errors.New("Less than 2 pods on node") +// } + +// // Get first pod on this node +// firstPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) +// if err != nil { +// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", firstPod.Name, err)) +// } +// logrus.Infof("First pod: %v", firstPod.Name) + +// // Get the second pod on this node +// secondPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[1].Name, metav1.GetOptions{}) +// if err != nil { +// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", secondPod.Name, err)) +// } +// logrus.Infof("Second pod: %v", secondPod.Name) + +// resultOne := podTest(ctx, clientset, firstPod, []string{"powershell", "Invoke-WebRequest", "www.bing.com", "-UseBasicParsing"}, rc, webRequestPassedWindows) +// resultTwo := podTest(ctx, clientset, secondPod, []string{"powershell", "Invoke-WebRequest", "www.bing.com", "-UseBasicParsing"}, rc, webRequestPassedWindows) + +// if resultOne != nil { +// return resultOne +// } + +// if resultTwo != nil { +// return resultTwo +// } + +// return nil +// } + +// func webRequestPassedWindows(output string) error { +// const searchString = "200 OK" +// if strings.Contains(output, searchString) { +// return nil +// } +// return errors.Wrapf(errors.New("Output did not contain \"200 OK\""), "output was: %s", output) +// } + +// func pingPassedWindows(output string) error { +// const searchString = "0% loss" +// if strings.Contains(output, searchString) { +// return nil +// } +// return errors.Wrapf(errors.New("Ping did not contain\"0% loss\""), "output was: %s", output) +// } diff --git a/test/internal/k8sutils/utils.go b/test/internal/k8sutils/utils.go index 4174595751..21873da72a 100644 --- a/test/internal/k8sutils/utils.go +++ b/test/internal/k8sutils/utils.go @@ -71,7 +71,6 @@ func mustParseResource(path string, out interface{}) error { if err := yaml.NewYAMLOrJSONDecoder(f, 0).Decode(out); err != nil { return err } - return err } From 121c072368a9fd218455d0ee276f78e8f080470b Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Thu, 20 Jul 2023 13:13:58 -0400 Subject: [PATCH 2/9] add ovs scripts to cleanup bridges and remove leaked rules --- hack/scripts/remove_ovs_bridges.py | 85 +++++++++++++++++++++++++ hack/scripts/remove_ovs_leaked_rules.py | 43 +++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 hack/scripts/remove_ovs_bridges.py create mode 100644 hack/scripts/remove_ovs_leaked_rules.py diff --git a/hack/scripts/remove_ovs_bridges.py b/hack/scripts/remove_ovs_bridges.py new file mode 100644 index 0000000000..fef1097ad6 --- /dev/null +++ b/hack/scripts/remove_ovs_bridges.py @@ -0,0 +1,85 @@ +import subprocess +import os +import re +import requests + +# step 1: get all ovs bridges: +try: + ovsBridgeShow = subprocess.Popen(['ovs-vsctl', 'list-br'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) +except subprocess.CalledProcessError: + print("failed to execute ovs-vsctl show command") + os.Exit(1) + +stdout = ovsBridgeShow.communicate() +ovsBridgeList = stdout[0].decode("utf-8".strip()).split('\n') + +# step 2: remove all ovs bridges +for bridge in ovsBridgeList: + if bridge != "": + deleteCommand = "ovs-vsctl del-br %s"%bridge + try: + print("deleting ovs bridge by: ", deleteCommand) + os.system(deleteCommand) + except: + print("failed to delete all ovs bridges") + +# step 3: reset vSwitch configuration to clean state and delete manager +try: + os.system("ovs-vsctl del-manager") + os.system("ovs-vsctl emer-reset") +except: + print("failed to reset vSwitch configuration and delete manager") + +# step 4: check if ovs flows exist anymore +try: + ovsDPCtlShow = subprocess.Popen(['ovs-dpctl', 'show'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) +except subprocess.CalledProcessError: + print("failed to execute ovs-dpctl show command") + os.Exit(1) + +stdout = ovsDPCtlShow.communicate() +if stdout[0].decode("utf-8") != "": + print("ovs flows still exist, please check if all ovs bridges are removed from system") + os.Exit(1) + +# step 5: delete cni state file: +cniStatePath = "/var/run/azure-vnet.json" +if os.path.exists(cniStatePath): + try: + os.system("rm /var/run/azure-vnet.json") + except: + print("failed to delete cni state file") + os.Exit(1) + +# step 6: delete az* interfaces as supporting for apipa connectivity +try: + ovsBridgeShow = subprocess.Popen(['ls', '/sys/class/net'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) +except subprocess.CalledProcessError: + print("failed to execute get all interfaces command") + os.Exit(1) + +stdout = ovsBridgeShow.communicate() +for interface in stdout[0].decode("utf-8").split('\n'): + if interface.startswith("az"): + try: + ovsBridgeShow = subprocess.Popen(['ip', 'link', 'delete', interface], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + print("failed to delete interface: ", interface) + os.Exit(1) + +# step 7: check internet connectivity after ovs bridges are removed +url = "http://www.bing.com" +timeout = 5 +try: + request = requests.get(url, timeout=timeout) + print("Connected to the Internet") +except (requests.ConnectionError, requests.Timeout) as exception: + print("No internet connection.") \ No newline at end of file diff --git a/hack/scripts/remove_ovs_leaked_rules.py b/hack/scripts/remove_ovs_leaked_rules.py new file mode 100644 index 0000000000..6a6e57d801 --- /dev/null +++ b/hack/scripts/remove_ovs_leaked_rules.py @@ -0,0 +1,43 @@ +import subprocess +import re +import os + +# step 1: get ovs-dpctl show out to make sure which ports are being used +try: + ovsDPCtlShow = subprocess.Popen(['ovs-dpctl', 'show'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) +except subprocess.CalledProcessError: + print("failed to execute ovs-dpctl show command") + os.Exit(1) + +stdout = ovsDPCtlShow.communicate() + +usedPortList = re.findall("port (\d+)", str(stdout)) + +# Step 2: Check ovs flows dumps +try: + ovsDumpFlows = subprocess.Popen(['ovs-ofctl', 'dump-flows', 'azure0'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) +except subprocess.CalledProcessError: + print("failed to execute ovs-ofctl dump-flows command") + os.Exit(1) + +stdout = ovsDumpFlows.communicate() +allPortList = re.findall("in_port=(\d+)", str(stdout)) + +unUsedPortList = [] +for port in allPortList: + if port not in usedPortList: + unUsedPortList.append(port) + +# Step 3: delete leaked rules +# only use unused ports +for port in unUsedPortList: + deleteCommand = "ovs-ofctl del-flows azure0 ip,in_port=%s"%port + try: + os.system(deleteCommand) + except: + print("delete command %s does not work"%deleteCommand) + os.Exit(1) \ No newline at end of file From 949de9efd42af5e6df20819f8daf032a898a50d5 Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Thu, 20 Jul 2023 13:17:15 -0400 Subject: [PATCH 3/9] remove conflicted files --- .../datapath/datapath_linux_test.go | 238 ------------------ .../manifests/datapath/linux-deployment.yaml | 74 ------ test/internal/datapath/datapath_linux.go | 167 ------------ test/internal/k8sutils/utils.go | 1 + 4 files changed, 1 insertion(+), 479 deletions(-) delete mode 100644 test/integration/datapath/datapath_linux_test.go delete mode 100644 test/integration/manifests/datapath/linux-deployment.yaml delete mode 100644 test/internal/datapath/datapath_linux.go diff --git a/test/integration/datapath/datapath_linux_test.go b/test/integration/datapath/datapath_linux_test.go deleted file mode 100644 index acf9cea2f1..0000000000 --- a/test/integration/datapath/datapath_linux_test.go +++ /dev/null @@ -1,238 +0,0 @@ -//go:build connection - -package connection - -import ( - "context" - "flag" - "fmt" - "testing" - "time" - - "github.com/Azure/azure-container-networking/test/integration" - "github.com/Azure/azure-container-networking/test/integration/goldpinger" - k8sutils "github.com/Azure/azure-container-networking/test/internal/k8sutils" - "github.com/Azure/azure-container-networking/test/internal/retry" - "github.com/pkg/errors" - "github.com/stretchr/testify/require" - - apiv1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - LinuxDeployYamlPath = "../manifests/datapath/linux-deployment.yaml" - podLabelKey = "app" - podCount = 2 - nodepoolKey = "agentpool" - maxRetryDelaySeconds = 10 - defaultTimeoutSeconds = 120 - defaultRetryDelaySeconds = 1 - goldpingerRetryCount = 24 - goldpingerDelayTimeSeconds = 5 -) - -var ( - podPrefix = flag.String("podName", "goldpinger", "Prefix for test pods") - podNamespace = flag.String("namespace", "datapath-linux", "Namespace for test pods") - nodepoolSelector = flag.String("nodepoolSelector", "nodepool1", "Provides nodepool as a Node-Selector for pods") - defaultRetrier = retry.Retrier{ - Attempts: 10, - Delay: defaultRetryDelaySeconds * time.Second, - } -) - -/* -This test assumes that you have the current credentials loaded in your default kubeconfig for a -k8s cluster with a Linux nodepool consisting of at least 2 Linux nodes. -*** The expected nodepool name is npwin, if the nodepool has a diferent name ensure that you change nodepoolSelector with: - -nodepoolSelector="yournodepoolname" - -To run the test use one of the following commands: -go test -count=1 test/integration/datapath/datapath_linux_test.go -timeout 3m -tags connection -run ^TestDatapathLinux$ -tags=connection - or -go test -count=1 test/integration/datapath/datapath_linux_test.go -timeout 3m -tags connection -run ^TestDatapathLinux$ -podName=acnpod -nodepoolSelector=npwina -tags=connection - - -This test checks pod to pod, pod to node, and pod to internet for datapath connectivity. - -Timeout context is controled by the -timeout flag. - -*/ - -func TestDatapathLinux(t *testing.T) { - ctx := context.Background() - - t.Log("Create Clientset") - clientset, err := k8sutils.MustGetClientset() - if err != nil { - require.NoError(t, err, "could not get k8s clientset: %v", err) - } - t.Log("Get REST config") - restConfig := k8sutils.MustGetRestConfig(t) - - t.Log("Create Label Selectors") - - podLabelSelector := fmt.Sprintf("%s=%s", podLabelKey, *podPrefix) - nodeLabelSelector := fmt.Sprintf("%s=%s", nodepoolKey, *nodepoolSelector) - - t.Log("Get Nodes") - nodes, err := k8sutils.GetNodeListByLabelSelector(ctx, clientset, nodeLabelSelector) - if err != nil { - require.NoError(t, err, "could not get k8s node list: %v", err) - } - - // Test Namespace - t.Log("Create Namespace") - err = k8sutils.MustCreateNamespace(ctx, clientset, *podNamespace) - createPodFlag := !(apierrors.IsAlreadyExists(err)) - t.Logf("%v", createPodFlag) - - if createPodFlag { - t.Log("Creating Linux pods through deployment") - deployment, err := k8sutils.MustParseDeployment(LinuxDeployYamlPath) - if err != nil { - require.NoError(t, err) - } - - // Fields for overwritting existing deployment yaml. - // Defaults from flags will not change anything - deployment.Spec.Selector.MatchLabels[podLabelKey] = *podPrefix - deployment.Spec.Template.ObjectMeta.Labels[podLabelKey] = *podPrefix - deployment.Spec.Template.Spec.NodeSelector[nodepoolKey] = *nodepoolSelector - deployment.Name = *podPrefix - deployment.Namespace = *podNamespace - - t.Logf("deployment Spec Template is %+v", deployment.Spec.Template) - deploymentsClient := clientset.AppsV1().Deployments(*podNamespace) - err = k8sutils.MustCreateDeployment(ctx, deploymentsClient, deployment) - if err != nil { - require.NoError(t, err) - } - t.Logf("podNamespace is %s", *podNamespace) - t.Logf("podLabelSelector is %s", podLabelSelector) - - t.Log("Waiting for pods to be running state") - err = k8sutils.WaitForPodsRunning(ctx, clientset, *podNamespace, podLabelSelector) - if err != nil { - require.NoError(t, err) - } - t.Log("Successfully created customer linux pods") - } else { - // Checks namespace already exists from previous attempt - t.Log("Namespace already exists") - - t.Log("Checking for pods to be running state") - err = k8sutils.WaitForPodsRunning(ctx, clientset, *podNamespace, podLabelSelector) - if err != nil { - require.NoError(t, err) - } - } - t.Log("Checking Linux test environment") - for _, node := range nodes.Items { - - pods, err := k8sutils.GetPodsByNode(ctx, clientset, *podNamespace, podLabelSelector, node.Name) - if err != nil { - require.NoError(t, err, "could not get k8s clientset: %v", err) - } - if len(pods.Items) <= 1 { - t.Logf("%s", node.Name) - require.NoError(t, errors.New("Less than 2 pods on node")) - } - } - t.Log("Linux test environment ready") - - t.Run("Linux ping tests", func(t *testing.T) { - // Check goldpinger health - t.Run("all pods have IPs assigned", func(t *testing.T) { - podsClient := clientset.CoreV1().Pods(*podNamespace) - - checkPodIPsFn := func() error { - podList, err := podsClient.List(ctx, metav1.ListOptions{LabelSelector: "app=goldpinger"}) - t.Logf("podList is %+v", podList) - if err != nil { - return err - } - - if len(podList.Items) == 0 { - return errors.New("no pods scheduled") - } - - for _, pod := range podList.Items { - if pod.Status.Phase == apiv1.PodPending { - return errors.New("some pods still pending") - } - } - - for _, pod := range podList.Items { - if pod.Status.PodIP == "" { - return errors.New("a pod has not been allocated an IP") - } - } - - return nil - } - err := defaultRetrier.Do(ctx, checkPodIPsFn) - if err != nil { - t.Fatalf("not all pods were allocated IPs: %v", err) - } - t.Log("all pods have been allocated IPs") - }) - - t.Run("all linux pods can ping each other", func(t *testing.T) { - pfOpts := k8s.PortForwardingOpts{ - Namespace: "default", - LabelSelector: "type=goldpinger-pod", - LocalPort: 9090, - DestPort: 8080, - } - - pf, err := k8s.NewPortForwarder(restConfig, t, pfOpts) - if err != nil { - t.Fatal(err) - } - - portForwardCtx, cancel := context.WithTimeout(ctx, defaultTimeoutSeconds*time.Second) - defer cancel() - - portForwardFn := func() error { - err := pf.Forward(portForwardCtx) - if err != nil { - t.Logf("unable to start port forward: %v", err) - return err - } - return nil - } - if err := defaultRetrier.Do(portForwardCtx, portForwardFn); err != nil { - t.Fatalf("could not start port forward within %ds: %v", defaultTimeoutSeconds, err) - } - defer pf.Stop() - - gpClient := goldpinger.Client{Host: pf.Address()} - - clusterCheckCtx, cancel := context.WithTimeout(ctx, 3*time.Minute) - defer cancel() - clusterCheckFn := func() error { - clusterState, err := gpClient.CheckAll(clusterCheckCtx) - if err != nil { - return err - } - - stats := goldpinger.ClusterStats(clusterState) - stats.PrintStats() - if stats.AllPingsHealthy() { - return nil - } - - return errors.New("not all pings are healthy") - } - retrier := retry.Retrier{Attempts: goldpingerRetryCount, Delay: goldpingerDelayTimeSeconds * time.Second} - if err := retrier.Do(clusterCheckCtx, clusterCheckFn); err != nil { - t.Fatalf("goldpinger pods network health could not reach healthy state after %d seconds: %v", goldpingerRetryCount*goldpingerDelayTimeSeconds, err) - } - - t.Log("all pings successful!") - }) - }) -} diff --git a/test/integration/manifests/datapath/linux-deployment.yaml b/test/integration/manifests/datapath/linux-deployment.yaml deleted file mode 100644 index 4b029c28c3..0000000000 --- a/test/integration/manifests/datapath/linux-deployment.yaml +++ /dev/null @@ -1,74 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: goldpinger-deploy - namespace: datapath-linux -spec: - replicas: 4 - selector: - matchLabels: - app: goldpinger - template: - metadata: - labels: - app: goldpinger - spec: - serviceAccount: "goldpinger-serviceaccount" - securityContext: - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 2000 - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: "app" - operator: In - values: - - goldpinger - topologyKey: "kubernetes.io/hostname" - containers: - - name: goldpinger - env: - - name: HOST - value: "0.0.0.0" - - name: PORT - value: "8080" - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - image: "docker.io/bloomberg/goldpinger:v3.0.0" - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - resources: - limits: - memory: 80Mi - requests: - cpu: 1m - memory: 40Mi - ports: - - containerPort: 8080 - name: http - readinessProbe: - httpGet: - path: /healthz - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - livenessProbe: - httpGet: - path: /healthz - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - nodeSelector: - kubernetes.io/os: linux diff --git a/test/internal/datapath/datapath_linux.go b/test/internal/datapath/datapath_linux.go deleted file mode 100644 index f32d4cda3f..0000000000 --- a/test/internal/datapath/datapath_linux.go +++ /dev/null @@ -1,167 +0,0 @@ -package datapath - -import ( - "context" - "fmt" - - "github.com/Azure/azure-container-networking/test/internal/k8sutils" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - restclient "k8s.io/client-go/rest" -) - -func LinuxPodToPodPingTestSameNode(ctx context.Context, clientset *kubernetes.Clientset, nodeName, podNamespace, labelSelector string, rc *restclient.Config) error { - logrus.Infof("Get Pods for Linux Node: %s", nodeName) - pods, err := k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName) - if err != nil { - logrus.Error(err) - return errors.Wrap(err, "k8s api call") - } - if len(pods.Items) <= 1 { - return errors.New("Less than 2 pods on node") - } - - // Get first pod on this node - firstPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) - if err != nil { - return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", firstPod.Name, err)) - } - logrus.Infof("First pod: %v %v", firstPod.Name, firstPod.Status.PodIP) - - // Get the second pod on this node - secondPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[1].Name, metav1.GetOptions{}) - if err != nil { - return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", secondPod.Name, err)) - } - logrus.Infof("Second pod: %v %v", secondPod.Name, secondPod.Status.PodIP) - - // Ping the second pod from the first pod - return podTest(ctx, clientset, firstPod, []string{"ping", secondPod.Status.PodIP}, rc, pingPassedWindows) -} - -// func WindowsPodToPodPingTestDiffNode(ctx context.Context, clientset *kubernetes.Clientset, nodeName1, nodeName2, podNamespace, labelSelector string, rc *restclient.Config) error { -// logrus.Infof("Get Pods for Node 1: %s", nodeName1) -// // Node 1 -// pods, err := k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName1) -// if err != nil { -// logrus.Error(err) -// return errors.Wrap(err, "k8s api call") -// } -// firstPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) -// if err != nil { -// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", firstPod.Name, err)) -// } -// logrus.Infof("First pod: %v %v", firstPod.Name, firstPod.Status.PodIP) - -// logrus.Infof("Get Pods for Node 2: %s", nodeName2) -// // Node 2 -// pods, err = k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName2) -// if err != nil { -// logrus.Error(err) -// return errors.Wrap(err, "k8s api call") -// } -// secondPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) -// if err != nil { -// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", secondPod.Name, err)) -// } -// logrus.Infof("Second pod: %v %v", secondPod.Name, secondPod.Status.PodIP) - -// // Ping the second pod from the first pod located on different nodes -// return podTest(ctx, clientset, firstPod, []string{"ping", secondPod.Status.PodIP}, rc, pingPassedWindows) -// } - -// func WindowsPodToNode(ctx context.Context, clientset *kubernetes.Clientset, nodeName, nodeIP, podNamespace, labelSelector string, rc *restclient.Config) error { -// logrus.Infof("Get Pods by Node: %s %s", nodeName, nodeIP) -// pods, err := k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName) -// if err != nil { -// logrus.Error(err) -// return errors.Wrap(err, "k8s api call") -// } -// if len(pods.Items) <= 1 { -// return errors.New("Less than 2 pods on node") -// } -// // Get first pod on this node -// firstPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) -// if err != nil { -// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", firstPod.Name, err)) -// } -// logrus.Infof("First pod: %v", firstPod.Name) - -// // Get the second pod on this node -// secondPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[1].Name, metav1.GetOptions{}) -// if err != nil { -// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", secondPod.Name, err)) -// } -// logrus.Infof("Second pod: %v", secondPod.Name) - -// // Ping from pod to node -// resultOne := podTest(ctx, clientset, firstPod, []string{"ping", nodeIP}, rc, pingPassedWindows) -// resultTwo := podTest(ctx, clientset, secondPod, []string{"ping", nodeIP}, rc, pingPassedWindows) - -// if resultOne != nil { -// return resultOne -// } - -// if resultTwo != nil { -// return resultTwo -// } - -// return nil -// } - -// func WindowsPodToInternet(ctx context.Context, clientset *kubernetes.Clientset, nodeName, podNamespace, labelSelector string, rc *restclient.Config) error { -// logrus.Infof("Get Pods by Node: %s", nodeName) -// pods, err := k8sutils.GetPodsByNode(ctx, clientset, podNamespace, labelSelector, nodeName) -// if err != nil { -// logrus.Error(err) -// return errors.Wrap(err, "k8s api call") -// } -// if len(pods.Items) <= 1 { -// return errors.New("Less than 2 pods on node") -// } - -// // Get first pod on this node -// firstPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[0].Name, metav1.GetOptions{}) -// if err != nil { -// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", firstPod.Name, err)) -// } -// logrus.Infof("First pod: %v", firstPod.Name) - -// // Get the second pod on this node -// secondPod, err := clientset.CoreV1().Pods(podNamespace).Get(ctx, pods.Items[1].Name, metav1.GetOptions{}) -// if err != nil { -// return errors.Wrap(err, fmt.Sprintf("Getting pod %s failed with %v", secondPod.Name, err)) -// } -// logrus.Infof("Second pod: %v", secondPod.Name) - -// resultOne := podTest(ctx, clientset, firstPod, []string{"powershell", "Invoke-WebRequest", "www.bing.com", "-UseBasicParsing"}, rc, webRequestPassedWindows) -// resultTwo := podTest(ctx, clientset, secondPod, []string{"powershell", "Invoke-WebRequest", "www.bing.com", "-UseBasicParsing"}, rc, webRequestPassedWindows) - -// if resultOne != nil { -// return resultOne -// } - -// if resultTwo != nil { -// return resultTwo -// } - -// return nil -// } - -// func webRequestPassedWindows(output string) error { -// const searchString = "200 OK" -// if strings.Contains(output, searchString) { -// return nil -// } -// return errors.Wrapf(errors.New("Output did not contain \"200 OK\""), "output was: %s", output) -// } - -// func pingPassedWindows(output string) error { -// const searchString = "0% loss" -// if strings.Contains(output, searchString) { -// return nil -// } -// return errors.Wrapf(errors.New("Ping did not contain\"0% loss\""), "output was: %s", output) -// } diff --git a/test/internal/k8sutils/utils.go b/test/internal/k8sutils/utils.go index 21873da72a..4174595751 100644 --- a/test/internal/k8sutils/utils.go +++ b/test/internal/k8sutils/utils.go @@ -71,6 +71,7 @@ func mustParseResource(path string, out interface{}) error { if err := yaml.NewYAMLOrJSONDecoder(f, 0).Decode(out); err != nil { return err } + return err } From 068fa79043ed3eb3bf96bdce5777477a5fd523de Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Sat, 22 Jul 2023 10:40:38 -0400 Subject: [PATCH 4/9] add ReadMe --- hack/scripts/ovs_scripts/README.md | 18 ++++++++++++++++++ .../{ => ovs_scripts}/remove_ovs_bridges.py | 0 .../remove_ovs_leaked_rules.py | 0 3 files changed, 18 insertions(+) create mode 100644 hack/scripts/ovs_scripts/README.md rename hack/scripts/{ => ovs_scripts}/remove_ovs_bridges.py (100%) rename hack/scripts/{ => ovs_scripts}/remove_ovs_leaked_rules.py (100%) diff --git a/hack/scripts/ovs_scripts/README.md b/hack/scripts/ovs_scripts/README.md new file mode 100644 index 0000000000..cac85f86bf --- /dev/null +++ b/hack/scripts/ovs_scripts/README.md @@ -0,0 +1,18 @@ +# remove_ovs_bridges.py + +`remove_ovs_bridges.py` script is for removing all ovs bridges +It will get all existing ovs bridges and delete them and then delete CNI state file +and all interfaces starting with `az` that are used for supporting apipa connectivity. After that, +it will check if Linux VM internet connectivity is still working. + +`remove_ovs_bridges` script is for removeing all leaked ovs rules +It will check ovs flow dumps and filter which ports are being used. Then delete these ovs rules that +are not associated with used ports. + +To run these script, clone scripts to Linux VM with ovs and have Python3 environment ready: +paulyu@paul-microsoft:~$ which python3 +/usr/bin/python3 + +Run script: +python3 remove_ovs_bridges.py +python3 remove_ovs_leaked_rules.py diff --git a/hack/scripts/remove_ovs_bridges.py b/hack/scripts/ovs_scripts/remove_ovs_bridges.py similarity index 100% rename from hack/scripts/remove_ovs_bridges.py rename to hack/scripts/ovs_scripts/remove_ovs_bridges.py diff --git a/hack/scripts/remove_ovs_leaked_rules.py b/hack/scripts/ovs_scripts/remove_ovs_leaked_rules.py similarity index 100% rename from hack/scripts/remove_ovs_leaked_rules.py rename to hack/scripts/ovs_scripts/remove_ovs_leaked_rules.py From 3ff1b2c632bc1281d05b145b4ad9d464d8f513c8 Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Sat, 22 Jul 2023 10:41:12 -0400 Subject: [PATCH 5/9] add ReadMe --- hack/scripts/ovs_scripts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/scripts/ovs_scripts/README.md b/hack/scripts/ovs_scripts/README.md index cac85f86bf..29ad0b7c7d 100644 --- a/hack/scripts/ovs_scripts/README.md +++ b/hack/scripts/ovs_scripts/README.md @@ -1,4 +1,4 @@ -# remove_ovs_bridges.py +# ovs_scripts `remove_ovs_bridges.py` script is for removing all ovs bridges It will get all existing ovs bridges and delete them and then delete CNI state file From 5536290fbc4ed53c8c9046ed8db51f0a980a63dc Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Mon, 24 Jul 2023 12:34:49 -0400 Subject: [PATCH 6/9] add one readme --- hack/scripts/ovs_scripts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/scripts/ovs_scripts/README.md b/hack/scripts/ovs_scripts/README.md index 29ad0b7c7d..39cba0f591 100644 --- a/hack/scripts/ovs_scripts/README.md +++ b/hack/scripts/ovs_scripts/README.md @@ -1,6 +1,6 @@ # ovs_scripts -`remove_ovs_bridges.py` script is for removing all ovs bridges +`remove_ovs_bridges.py` script is for removing all ovs bridges and ssh connection will not be lost It will get all existing ovs bridges and delete them and then delete CNI state file and all interfaces starting with `az` that are used for supporting apipa connectivity. After that, it will check if Linux VM internet connectivity is still working. From 23f6d5ffdc52afcbfc7285a82b219826b49a82b7 Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Mon, 24 Jul 2023 12:47:54 -0400 Subject: [PATCH 7/9] fix comment --- hack/scripts/ovs_scripts/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hack/scripts/ovs_scripts/README.md b/hack/scripts/ovs_scripts/README.md index 39cba0f591..8eb513faaa 100644 --- a/hack/scripts/ovs_scripts/README.md +++ b/hack/scripts/ovs_scripts/README.md @@ -1,6 +1,7 @@ # ovs_scripts -`remove_ovs_bridges.py` script is for removing all ovs bridges and ssh connection will not be lost +`remove_ovs_bridges.py` script is for removing ovs switch(azure0) and the and openflow rules configured with it +ssh connection will not be lost when running script It will get all existing ovs bridges and delete them and then delete CNI state file and all interfaces starting with `az` that are used for supporting apipa connectivity. After that, it will check if Linux VM internet connectivity is still working. From 7ed468d237eb2bcb211c64b36b8d908215c848c0 Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Mon, 24 Jul 2023 13:23:31 -0400 Subject: [PATCH 8/9] correct file name --- hack/scripts/ovs_scripts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/scripts/ovs_scripts/README.md b/hack/scripts/ovs_scripts/README.md index 8eb513faaa..c6642c5642 100644 --- a/hack/scripts/ovs_scripts/README.md +++ b/hack/scripts/ovs_scripts/README.md @@ -6,7 +6,7 @@ It will get all existing ovs bridges and delete them and then delete CNI state f and all interfaces starting with `az` that are used for supporting apipa connectivity. After that, it will check if Linux VM internet connectivity is still working. -`remove_ovs_bridges` script is for removeing all leaked ovs rules +`remove_ovs_leaked_rules.py` script is for removeing all leaked ovs rules It will check ovs flow dumps and filter which ports are being used. Then delete these ovs rules that are not associated with used ports. From 64de6e75f8e9ad0b27951e158aa9f749b81b8b2b Mon Sep 17 00:00:00 2001 From: paulyufan2 Date: Mon, 24 Jul 2023 13:24:49 -0400 Subject: [PATCH 9/9] add a new line of readme --- hack/scripts/ovs_scripts/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hack/scripts/ovs_scripts/README.md b/hack/scripts/ovs_scripts/README.md index c6642c5642..89f6632e80 100644 --- a/hack/scripts/ovs_scripts/README.md +++ b/hack/scripts/ovs_scripts/README.md @@ -4,7 +4,8 @@ ssh connection will not be lost when running script It will get all existing ovs bridges and delete them and then delete CNI state file and all interfaces starting with `az` that are used for supporting apipa connectivity. After that, -it will check if Linux VM internet connectivity is still working. +it will bring back VM to original state with eth0 as primary interface and +check if Linux VM internet connectivity is still working. `remove_ovs_leaked_rules.py` script is for removeing all leaked ovs rules It will check ovs flow dumps and filter which ports are being used. Then delete these ovs rules that