mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	ipvs: check for existence of scheduler module and fail if not found
Signed-off-by: Christopher M. Luciano <cmluciano@us.ibm.com>
This commit is contained in:
		@@ -111,6 +111,7 @@ func Test_getProxyMode(t *testing.T) {
 | 
			
		||||
			kernelVersion: "4.18",
 | 
			
		||||
			ipsetVersion:  ipvs.MinIPSetCheckVersion,
 | 
			
		||||
			expected:      proxyModeIPVS,
 | 
			
		||||
			scheduler:     "rr",
 | 
			
		||||
		},
 | 
			
		||||
		{ // flag says ipvs, ipset version ok, kernel modules installed for linux kernel 4.19
 | 
			
		||||
			flag:          "ipvs",
 | 
			
		||||
@@ -118,6 +119,7 @@ func Test_getProxyMode(t *testing.T) {
 | 
			
		||||
			kernelVersion: "4.19",
 | 
			
		||||
			ipsetVersion:  ipvs.MinIPSetCheckVersion,
 | 
			
		||||
			expected:      proxyModeIPVS,
 | 
			
		||||
			scheduler:     "rr",
 | 
			
		||||
		},
 | 
			
		||||
		{ // flag says ipvs, ipset version too low, fallback on iptables mode
 | 
			
		||||
			flag:          "ipvs",
 | 
			
		||||
@@ -151,13 +153,14 @@ func Test_getProxyMode(t *testing.T) {
 | 
			
		||||
			expected:      proxyModeIPVS,
 | 
			
		||||
			scheduler:     "sed",
 | 
			
		||||
		},
 | 
			
		||||
		{ // flag says ipvs, ipset version ok, non-existent scheduler
 | 
			
		||||
		{ // flag says ipvs, kernel modules not installed for sed scheduler, fallback to iptables
 | 
			
		||||
			flag:          "ipvs",
 | 
			
		||||
			kmods:         []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack", "ip_vs_sed"},
 | 
			
		||||
			kmods:         []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack"},
 | 
			
		||||
			kernelVersion: "4.19",
 | 
			
		||||
			ipsetVersion:  ipvs.MinIPSetCheckVersion,
 | 
			
		||||
			expected:      proxyModeIPVS,
 | 
			
		||||
			scheduler:     "foobar",
 | 
			
		||||
			expected:      proxyModeIPTables,
 | 
			
		||||
			kernelCompat:  true,
 | 
			
		||||
			scheduler:     "sed",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for i, c := range cases {
 | 
			
		||||
@@ -167,11 +170,7 @@ func Test_getProxyMode(t *testing.T) {
 | 
			
		||||
			modules:       c.kmods,
 | 
			
		||||
			kernelVersion: c.kernelVersion,
 | 
			
		||||
		}
 | 
			
		||||
		scheduler := cases[i].scheduler
 | 
			
		||||
		if scheduler == "" {
 | 
			
		||||
			scheduler = "rr"
 | 
			
		||||
		}
 | 
			
		||||
		canUseIPVS, _ := ipvs.CanUseIPVSProxier(khandler, ipsetver, scheduler)
 | 
			
		||||
		canUseIPVS, _ := ipvs.CanUseIPVSProxier(khandler, ipsetver, cases[i].scheduler)
 | 
			
		||||
		r := getProxyMode(c.flag, canUseIPVS, kcompater)
 | 
			
		||||
		if r != c.expected {
 | 
			
		||||
			t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
 | 
			
		||||
 
 | 
			
		||||
@@ -711,10 +711,11 @@ func CanUseIPVSProxier(handle KernelHandler, ipsetver IPSetVersioner, scheduler
 | 
			
		||||
	}
 | 
			
		||||
	mods = utilipvs.GetRequiredIPVSModules(kernelVersion)
 | 
			
		||||
	wantModules := sets.NewString()
 | 
			
		||||
	schedulerMod, modNotFound := utilipvs.GetRequiredSchedulerModules(scheduler)
 | 
			
		||||
	if modNotFound != nil {
 | 
			
		||||
		klog.Error(modNotFound)
 | 
			
		||||
	// We check for the existence of the scheduler mod and will trigger a missingMods error if not found
 | 
			
		||||
	if scheduler == "" {
 | 
			
		||||
		scheduler = DefaultScheduler
 | 
			
		||||
	}
 | 
			
		||||
	schedulerMod := "ip_vs_" + scheduler
 | 
			
		||||
	mods = append(mods, schedulerMod)
 | 
			
		||||
	wantModules.Insert(mods...)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -348,13 +348,13 @@ func TestCanUseIPVSProxier(t *testing.T) {
 | 
			
		||||
			ipsetVersion:  MinIPSetCheckVersion,
 | 
			
		||||
			ok:            true,
 | 
			
		||||
		},
 | 
			
		||||
		// case 10, non-existent scheduler, fallback to rr
 | 
			
		||||
		// case 10, non-existent scheduler, error due to modules not existing
 | 
			
		||||
		{
 | 
			
		||||
			mods:          []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack", "ip_vs_dh"},
 | 
			
		||||
			scheduler:     "foobar",
 | 
			
		||||
			kernelVersion: "4.19",
 | 
			
		||||
			ipsetVersion:  MinIPSetCheckVersion,
 | 
			
		||||
			ok:            true,
 | 
			
		||||
			ok:            false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@ limitations under the License.
 | 
			
		||||
package ipvs
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
@@ -84,14 +83,6 @@ const (
 | 
			
		||||
	KernelModuleIPVSWRR string = "ip_vs_wrr"
 | 
			
		||||
	// KernelModuleIPVSSH is the kernel module "ip_vs_sh"
 | 
			
		||||
	KernelModuleIPVSSH string = "ip_vs_sh"
 | 
			
		||||
	// KernelModuleIPVSLC is the kernel module "ip_vs_lc"
 | 
			
		||||
	KernelModuleIPVSLC string = "ip_vs_lc"
 | 
			
		||||
	// KernelModuleIPVSNQ is the kernel module "ip_vs_nq"
 | 
			
		||||
	KernelModuleIPVSNQ string = "ip_vs_nq"
 | 
			
		||||
	// KernelModuleIPVSDH is the kernel module "ip_vs_dh"
 | 
			
		||||
	KernelModuleIPVSDH string = "ip_vs_dh"
 | 
			
		||||
	// KernelModuleIPVSSED is the kernel module "ip_vs_sed"
 | 
			
		||||
	KernelModuleIPVSSED string = "ip_vs_sed"
 | 
			
		||||
	// KernelModuleNfConntrackIPV4 is the module "nf_conntrack_ipv4"
 | 
			
		||||
	KernelModuleNfConntrackIPV4 string = "nf_conntrack_ipv4"
 | 
			
		||||
	// KernelModuleNfConntrack is the kernel module "nf_conntrack"
 | 
			
		||||
@@ -148,26 +139,3 @@ func GetRequiredIPVSModules(kernelVersion *version.Version) []string {
 | 
			
		||||
func IsRsGracefulTerminationNeeded(proto string) bool {
 | 
			
		||||
	return !strings.EqualFold(proto, "UDP") && !strings.EqualFold(proto, "SCTP")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRequiredSchedulerModules returns the required ipvs scheduler module for configured scheduler
 | 
			
		||||
func GetRequiredSchedulerModules(scheduler string) (string, error) {
 | 
			
		||||
	switch s := scheduler; s {
 | 
			
		||||
	case "rr":
 | 
			
		||||
		return KernelModuleIPVSRR, nil
 | 
			
		||||
	case "lc":
 | 
			
		||||
		return KernelModuleIPVSLC, nil
 | 
			
		||||
	case "nq":
 | 
			
		||||
		return KernelModuleIPVSNQ, nil
 | 
			
		||||
	case "dh":
 | 
			
		||||
		return KernelModuleIPVSDH, nil
 | 
			
		||||
	case "sh":
 | 
			
		||||
		return KernelModuleIPVSSH, nil
 | 
			
		||||
	case "sed":
 | 
			
		||||
		return KernelModuleIPVSSED, nil
 | 
			
		||||
	case "":
 | 
			
		||||
		return KernelModuleIPVSRR, nil
 | 
			
		||||
	default:
 | 
			
		||||
		notFound := fmt.Errorf("ip_vs_%s is not a supported IPVS scheduler algorithm, falling back to round-robin", scheduler)
 | 
			
		||||
		return KernelModuleIPVSRR, notFound
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@ limitations under the License.
 | 
			
		||||
package ipvs
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
@@ -414,51 +413,3 @@ func TestGetRequiredIPVSModules(t *testing.T) {
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetRequiredSchedulerModules(t *testing.T) {
 | 
			
		||||
	Tests := []struct {
 | 
			
		||||
		name         string
 | 
			
		||||
		scheduler    string
 | 
			
		||||
		want         string
 | 
			
		||||
		expectedErrs error
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:         "scheduler explicitly set to  rr",
 | 
			
		||||
			scheduler:    "rr",
 | 
			
		||||
			want:         "ip_vs_rr",
 | 
			
		||||
			expectedErrs: nil,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "scheduler set to  nq",
 | 
			
		||||
			scheduler:    "nq",
 | 
			
		||||
			want:         "ip_vs_nq",
 | 
			
		||||
			expectedErrs: nil,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "unset scheduler",
 | 
			
		||||
			scheduler:    "",
 | 
			
		||||
			want:         "ip_vs_rr",
 | 
			
		||||
			expectedErrs: nil,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "invalid scheduler algorithm",
 | 
			
		||||
			scheduler:    "foobar",
 | 
			
		||||
			want:         "ip_vs_rr",
 | 
			
		||||
			expectedErrs: fmt.Errorf("ip_vs_%s is not a supported IPVS scheduler algorithm, falling back to round-robin", "foobar"),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range Tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			got, err := GetRequiredSchedulerModules(test.scheduler)
 | 
			
		||||
			if !reflect.DeepEqual(got, test.want) {
 | 
			
		||||
				t.Fatalf("GetRequiredSchedulerModules() = testCase %v failed- expected: %s scheduler, but got: %s", test.name, test.want, got)
 | 
			
		||||
			}
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				if err.Error() != test.expectedErrs.Error() {
 | 
			
		||||
					t.Fatalf("Expected error: %v, got: %v", test.expectedErrs, err.Error())
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user