From ed3393746cdb7f5d8b88457f34625d936c9f1b3f Mon Sep 17 00:00:00 2001 From: Charles CAPORALI Date: Thu, 16 Jan 2025 09:43:24 +0100 Subject: [PATCH] adding the --bridgeNetwork option to change the default configuration for bridge setup by passing a JSON file --- README.md | 5 ++ bridgeNetwork.json | 4 ++ cmd/k8s-netperf/k8s-netperf.go | 87 +++++++++++++++++++++++++--------- pkg/config/config.go | 56 ++++++++++++---------- pkg/k8s/kubernetes.go | 4 +- pkg/k8s/kubevirt.go | 12 ++--- 6 files changed, 113 insertions(+), 55 deletions(-) create mode 100644 bridgeNetwork.json diff --git a/README.md b/README.md index 446196f..cec8e97 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,11 @@ spec: Then you can launch a test using the bridge interface: ``` ./bin/amd64/k8s-netperf --vm --bridge br0 +``` +By default, it will read the `bridgeNetwork.json` file from the git repository. If the default IP addresses (10.10.10.12/24 and 10.10.10.14/24) are not available for your setup, it is possible to change it by passing a JSON file as a parameter with `--bridgeNetwork`, like follow: +``` +k8s-netperf --vm --bridge br0 --bridgeNetwork /path/to/my/bridgeConfig.json + ``` ### Config file diff --git a/bridgeNetwork.json b/bridgeNetwork.json new file mode 100644 index 0000000..6f27bc7 --- /dev/null +++ b/bridgeNetwork.json @@ -0,0 +1,4 @@ +{ + "bridgeServerNetwork": "10.10.10.12/24", + "bridgeClientNetwork": "10.10.10.14/24" +} diff --git a/cmd/k8s-netperf/k8s-netperf.go b/cmd/k8s-netperf/k8s-netperf.go index f0fc994..4eaced5 100644 --- a/cmd/k8s-netperf/k8s-netperf.go +++ b/cmd/k8s-netperf/k8s-netperf.go @@ -2,7 +2,9 @@ package main import ( "context" + encodeJson "encoding/json" "fmt" + "io/ioutil" "os" "regexp" "strings" @@ -33,28 +35,29 @@ const index = "k8s-netperf" const retry = 3 var ( - cfgfile string - nl bool - clean bool - netperf bool - iperf3 bool - uperf bool - udn bool - acrossAZ bool - full bool - vm bool - vmimage string - debug bool - bridge string - promURL string - id string - searchURL string - showMetrics bool - tcpt float64 - json bool - version bool - csvArchive bool - searchIndex string + cfgfile string + nl bool + clean bool + netperf bool + iperf3 bool + uperf bool + udn bool + acrossAZ bool + full bool + vm bool + vmimage string + debug bool + bridge string + bridgeNetwork string + promURL string + id string + searchURL string + showMetrics bool + tcpt float64 + json bool + version bool + csvArchive bool + searchIndex string ) var rootCmd = &cobra.Command{ @@ -191,6 +194,10 @@ var rootCmd = &cobra.Command{ log.Error(err) } s.Bridge = true + s.BridgeServerNetwork, s.BridgeClientNetwork, err = parseNetworkConfig(bridgeNetwork) + if err != nil { + log.Error(err) + } } } @@ -403,6 +410,39 @@ func cleanup(client *kubernetes.Clientset) { } } +// Function to parse the JSON from a file and return the IP parts (before '/') +func parseNetworkConfig(jsonFile string) (string, string, error) { + + // Open the JSON file + file, err := os.Open(jsonFile) + if err != nil { + return "", "", fmt.Errorf("error opening file: %v", err) + } + defer file.Close() + + // Read the file contents + content, err := ioutil.ReadAll(file) + if err != nil { + return "", "", fmt.Errorf("error reading file: %v", err) + } + + // Create an instance of the struct + var netConfig config.BridgeNetworkConfig + + // Unmarshal the JSON string into the struct + err = encodeJson.Unmarshal(content, &netConfig) + if err != nil { + return "", "", fmt.Errorf("error parsing JSON: %v", err) + } + + // Extract the IP parts (before '/') + serverIP := netConfig.BridgeServerNetwork + clientIP := netConfig.BridgeClientNetwork + + // Return the extracted IPs + return serverIP, clientIP, nil +} + // executeWorkload executes the workload and returns the result data. func executeWorkload(nc config.Config, s config.PerfScenarios, @@ -427,7 +467,7 @@ func executeWorkload(nc config.Config, } //when using a bridge, ip is static } else if s.Bridge { - serverIP = "10.10.10.14" + serverIP = strings.Split(s.BridgeServerNetwork, "/")[0] } else { if hostNet { serverIP = s.ServerHost.Items[0].Status.PodIP @@ -528,6 +568,7 @@ func main() { rootCmd.Flags().BoolVar(&debug, "debug", false, "Enable debug log") rootCmd.Flags().BoolVar(&udn, "udn", false, "Create and use a UDN called 'udn-l2-primary' as primary network.") rootCmd.Flags().StringVar(&bridge, "bridge", "", "Name of the NNCP to be used for creating bridge interface - VM only.") + rootCmd.Flags().StringVar(&bridgeNetwork, "bridgeNetwork", "bridgeNetwork.json", "Json file for the network defined by the bridge interface - bridge should be enabled") rootCmd.Flags().StringVar(&promURL, "prom", "", "Prometheus URL") rootCmd.Flags().StringVar(&id, "uuid", "", "User provided UUID") rootCmd.Flags().StringVar(&searchURL, "search", "", "OpenSearch URL, if you have auth, pass in the format of https://user:pass@url:port") diff --git a/pkg/config/config.go b/pkg/config/config.go index 1910005..9058ce7 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -32,30 +32,38 @@ type Config struct { // PerfScenarios describes the different scenarios type PerfScenarios struct { - NodeLocal bool - AcrossAZ bool - HostNetwork bool - Configs []Config - VM bool - VMImage string - VMHost string - Udn bool - Bridge bool - ServerNodeInfo metrics.NodeInfo - ClientNodeInfo metrics.NodeInfo - Client apiv1.PodList - Server apiv1.PodList - ClientAcross apiv1.PodList - ClientHost apiv1.PodList - ServerHost apiv1.PodList - NetperfService *apiv1.Service - IperfService *apiv1.Service - UperfService *apiv1.Service - RestConfig rest.Config - ClientSet *kubernetes.Clientset - KClient *kubevirtv1.KubevirtV1Client - DClient *dynamic.DynamicClient - SSHClient *goph.Client + NodeLocal bool + AcrossAZ bool + HostNetwork bool + Configs []Config + VM bool + VMImage string + VMHost string + Udn bool + Bridge bool + BridgeServerNetwork string + BridgeClientNetwork string + ServerNodeInfo metrics.NodeInfo + ClientNodeInfo metrics.NodeInfo + Client apiv1.PodList + Server apiv1.PodList + ClientAcross apiv1.PodList + ClientHost apiv1.PodList + ServerHost apiv1.PodList + NetperfService *apiv1.Service + IperfService *apiv1.Service + UperfService *apiv1.Service + RestConfig rest.Config + ClientSet *kubernetes.Clientset + KClient *kubevirtv1.KubevirtV1Client + DClient *dynamic.DynamicClient + SSHClient *goph.Client +} + +// struct for bridge options +type BridgeNetworkConfig struct { + BridgeServerNetwork string `json:"bridgeServerNetwork"` + BridgeClientNetwork string `json:"bridgeClientNetwork"` } // Tests we will support in k8s-netperf diff --git a/pkg/k8s/kubernetes.go b/pkg/k8s/kubernetes.go index 397e354..ec10166 100644 --- a/pkg/k8s/kubernetes.go +++ b/pkg/k8s/kubernetes.go @@ -587,7 +587,7 @@ func ExtractUdnIp(s config.PerfScenarios) (string, error) { // launchServerVM will create the ServerVM with the specific node and pod affinity. func launchServerVM(perf *config.PerfScenarios, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity) error { - _, err := CreateVMServer(perf.KClient, serverRole, serverRole, *podAff, *nodeAff, perf.VMImage, perf.Bridge) + _, err := CreateVMServer(perf.KClient, serverRole, serverRole, *podAff, *nodeAff, perf.VMImage, perf.Bridge, perf.BridgeServerNetwork) if err != nil { return err } @@ -612,7 +612,7 @@ func launchServerVM(perf *config.PerfScenarios, name string, podAff *corev1.PodA // launchClientVM will create the ClientVM with the specific node and pod affinity. func launchClientVM(perf *config.PerfScenarios, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity) error { - host, err := CreateVMClient(perf.KClient, perf.ClientSet, perf.DClient, name, podAff, nodeAff, perf.VMImage, perf.Bridge) + host, err := CreateVMClient(perf.KClient, perf.ClientSet, perf.DClient, name, podAff, nodeAff, perf.VMImage, perf.Bridge, perf.BridgeClientNetwork) if err != nil { return err } diff --git a/pkg/k8s/kubevirt.go b/pkg/k8s/kubevirt.go index 77c9df0..1b8cdba 100644 --- a/pkg/k8s/kubevirt.go +++ b/pkg/k8s/kubevirt.go @@ -158,7 +158,7 @@ func exposeService(client *kubernetes.Clientset, dynamicClient *dynamic.DynamicC // CreateVMClient takes in the affinity rules and deploys the VMI func CreateVMClient(kclient *kubevirtv1.KubevirtV1Client, client *kubernetes.Clientset, - dyn *dynamic.DynamicClient, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity, vmimage string, bridge bool) (string, error) { + dyn *dynamic.DynamicClient, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity, vmimage string, bridge bool, bridgeNetwork string) (string, error) { label := map[string]string{ "app": name, "role": name, @@ -228,10 +228,10 @@ runcmd: }, }, }) - netData = `version: 2 + netData = fmt.Sprintf(`version: 2 ethernets: eth1: - addresses: [ 10.10.10.12/24 ]` + addresses: [ %s ]`, bridgeNetwork) } _, err = CreateVMI(kclient, name, label, b64.StdEncoding.EncodeToString([]byte(data)), *podAff, *nodeAff, vmimage, interfaces, networks, b64.StdEncoding.EncodeToString([]byte(netData))) if err != nil { @@ -250,7 +250,7 @@ ethernets: // CreateVMServer will take the pod and node affinity and deploy the VMI func CreateVMServer(client *kubevirtv1.KubevirtV1Client, name string, role string, podAff corev1.PodAntiAffinity, - nodeAff corev1.NodeAffinity, vmimage string, bridge bool) (*v1.VirtualMachineInstance, error) { + nodeAff corev1.NodeAffinity, vmimage string, bridge bool, bridgeNetwork string) (*v1.VirtualMachineInstance, error) { label := map[string]string{ "app": name, "role": role, @@ -321,10 +321,10 @@ runcmd: }, }, }) - netData = `version: 2 + netData = fmt.Sprintf(`version: 2 ethernets: eth1: - addresses: [ 10.10.10.14/24 ]` + addresses: [ %s ]`, bridgeNetwork) } return CreateVMI(client, name, label, b64.StdEncoding.EncodeToString([]byte(data)), podAff, nodeAff, vmimage, interfaces, networks, b64.StdEncoding.EncodeToString([]byte(netData))) }