Skip to content

Commit

Permalink
Fix webhook for virtual workers
Browse files Browse the repository at this point in the history
this commit fix the validation webhook to support virtual workers using
PCI passthrough

Signed-off-by: Sebastian Sch <[email protected]>
  • Loading branch information
SchSeba committed Oct 31, 2021
1 parent 3dfb500 commit 8f4d42f
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 15 deletions.
10 changes: 10 additions & 0 deletions api/v1/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ func IsSupportedModel(vendorId, deviceId string) bool {
return false
}

func IsVfSupportedModel(vendorId, deviceId string) bool {
for _, n := range NicIdMap {
ids := strings.Split(n, " ")
if vendorId == ids[0] && deviceId == ids[2] {
return true
}
}
return false
}

func IsEnabledUnsupportedVendor(vendorId string, unsupportedNicIdMap map[string]string) bool {
for _, n := range unsupportedNicIdMap {
if IsValidPciString(n) {
Expand Down
7 changes: 1 addition & 6 deletions cmd/sriov-network-config-daemon/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ var (
kubeconfig string
nodeName string
}

// PlatformMap contains supported platforms for virtual VF
platformMap = map[string]utils.PlatformType{
"openstack": utils.VirtualOpenStack,
}
)

func init() {
Expand Down Expand Up @@ -147,7 +142,7 @@ func runStartCmd(cmd *cobra.Command, args []string) {

nodeInfo, err := kubeclient.CoreV1().Nodes().Get(context.Background(), startOpts.nodeName, v1.GetOptions{})
if err == nil {
for key, pType := range platformMap {
for key, pType := range utils.PlatformMap {
if strings.Contains(strings.ToLower(nodeInfo.Spec.ProviderID), strings.ToLower(key)) {
platformType = pType
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/utils/utils_virtual.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ func (e PlatformType) String() string {
}
}

var (
// PlatformMap contains supported platforms for virtual VF
PlatformMap = map[string]PlatformType{
"openstack": VirtualOpenStack,
}
)

const (
ospMetaDataDir = "/host/var/config/openstack/latest/"
ospNetworkData = ospMetaDataDir + "/network_data.json"
Expand Down
17 changes: 13 additions & 4 deletions pkg/webhook/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package webhook
import (
"context"
"fmt"
"github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils"
"os"
"regexp"
"strconv"
"strings"

"github.com/golang/glog"
"k8s.io/api/admission/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"

Expand Down Expand Up @@ -169,7 +171,7 @@ func dynamicValidateSriovNetworkNodePolicy(cr *sriovnetworkv1.SriovNetworkNodePo
nodesSelected = true
for _, ns := range nsList.Items {
if ns.GetName() == node.GetName() {
if ok, err := validatePolicyForNodeState(cr, &ns); err != nil || !ok {
if ok, err := validatePolicyForNodeState(cr, &ns, &node); err != nil || !ok {
return false, err
}
}
Expand All @@ -195,10 +197,10 @@ func dynamicValidateSriovNetworkNodePolicy(cr *sriovnetworkv1.SriovNetworkNodePo
return true, nil
}

func validatePolicyForNodeState(policy *sriovnetworkv1.SriovNetworkNodePolicy, state *sriovnetworkv1.SriovNetworkNodeState) (bool, error) {
func validatePolicyForNodeState(policy *sriovnetworkv1.SriovNetworkNodePolicy, state *sriovnetworkv1.SriovNetworkNodeState, node *corev1.Node) (bool, error) {
glog.V(2).Infof("validatePolicyForNodeState(): validate policy %s for node %s.", policy.GetName(), state.GetName())
for _, iface := range state.Status.Interfaces {
if validateNicModel(&policy.Spec.NicSelector, &iface, state.GetName()) {
if validateNicModel(&policy.Spec.NicSelector, &iface, node) {
interfaceSelected = true
if policy.GetName() != "default" && policy.Spec.NumVfs == 0 {
return false, fmt.Errorf("numVfs(%d) in CR %s is not allowed", policy.Spec.NumVfs, policy.GetName())
Expand Down Expand Up @@ -256,7 +258,7 @@ func keys(m map[string]([]string)) []string {
return keys
}

func validateNicModel(selector *sriovnetworkv1.SriovNetworkNicSelector, iface *sriovnetworkv1.InterfaceExt, nodeName string) bool {
func validateNicModel(selector *sriovnetworkv1.SriovNetworkNicSelector, iface *sriovnetworkv1.InterfaceExt, node *corev1.Node) bool {
if selector.Vendor != "" && selector.Vendor != iface.Vendor {
return false
}
Expand Down Expand Up @@ -285,5 +287,12 @@ func validateNicModel(selector *sriovnetworkv1.SriovNetworkNicSelector, iface *s
if sriovnetworkv1.IsSupportedModel(iface.Vendor, iface.DeviceID) {
return true
}

for key := range utils.PlatformMap {
if strings.Contains(strings.ToLower(node.Spec.ProviderID), strings.ToLower(key)) && sriovnetworkv1.IsVfSupportedModel(iface.Vendor, iface.DeviceID) {
return true
}
}

return false
}
80 changes: 75 additions & 5 deletions pkg/webhook/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package webhook

import (
"fmt"
corev1 "k8s.io/api/core/v1"
"os"
"testing"

Expand Down Expand Up @@ -121,6 +122,10 @@ func newNodePolicy() *SriovNetworkNodePolicy {
}
}

func NewNode() *corev1.Node {
return &corev1.Node{Spec: corev1.NodeSpec{ProviderID: "openstack"}}
}

func TestValidateSriovOperatorConfigWithDefaultOperatorConfig(t *testing.T) {
var err error
var ok bool
Expand Down Expand Up @@ -205,7 +210,7 @@ func TestValidatePolicyForNodeStateWithValidPolicy(t *testing.T) {
},
}
g := NewGomegaWithT(t)
ok, err := validatePolicyForNodeState(policy, state)
ok, err := validatePolicyForNodeState(policy, state, NewNode())
g.Expect(err).NotTo(HaveOccurred())
g.Expect(ok).To(Equal(true))
}
Expand All @@ -232,7 +237,7 @@ func TestValidatePolicyForNodeStateWithInvalidNumVfsPolicy(t *testing.T) {
},
}
g := NewGomegaWithT(t)
ok, err := validatePolicyForNodeState(policy, state)
ok, err := validatePolicyForNodeState(policy, state, NewNode())
g.Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("numVfs(%d) in CR %s exceed the maximum allowed value(%d)", policy.Spec.NumVfs, policy.GetName(), state.Status.Interfaces[0].TotalVfs))))
g.Expect(ok).To(Equal(false))
}
Expand Down Expand Up @@ -423,7 +428,7 @@ func TestValidatePolicyForNodeStateWithInvalidDevice(t *testing.T) {
g.Expect(err).ToNot(HaveOccurred())
g.Expect(cfg).ToNot(BeNil())
kubeclient = kubernetes.NewForConfigOrDie(cfg)
ok, err := validatePolicyForNodeState(policy, state)
ok, err := validatePolicyForNodeState(policy, state, NewNode())
g.Expect(err).NotTo(HaveOccurred())
g.Expect(ok).To(Equal(true))
}
Expand All @@ -446,7 +451,7 @@ func TestValidatePolicyForNodeStateWithInvalidPfName(t *testing.T) {
},
}
g := NewGomegaWithT(t)
ok, err := validatePolicyForNodeState(policy, state)
ok, err := validatePolicyForNodeState(policy, state, NewNode())
g.Expect(err).NotTo(HaveOccurred())
g.Expect(ok).To(Equal(true))
g.Expect(interfaceSelected).To(Equal(false))
Expand All @@ -470,7 +475,7 @@ func TestValidatePolicyForNodeStateWithValidPfName(t *testing.T) {
},
}
g := NewGomegaWithT(t)
ok, err := validatePolicyForNodeState(policy, state)
ok, err := validatePolicyForNodeState(policy, state, NewNode())
g.Expect(err).NotTo(HaveOccurred())
g.Expect(ok).To(Equal(true))
g.Expect(interfaceSelected).To(Equal(true))
Expand All @@ -492,3 +497,68 @@ func TestStaticValidateSriovNetworkNodePolicyWithInvalidNicSelector(t *testing.T
g.Expect(err).To(HaveOccurred())
g.Expect(ok).To(Equal(false))
}

func TestValidatePolicyForNodeStateWithValidVFAndNetFilter(t *testing.T) {
interfaceSelected = false
state := &SriovNetworkNodeState{
Spec: SriovNetworkNodeStateSpec{
Interfaces: []Interface{
{
Name: "ens803f1",
NumVfs: 1,
PciAddress: "0000:86:00.1",
VfGroups: []VfGroup{
{
DeviceType: "netdevice",
ResourceName: "nic1",
},
},
},
},
},
Status: SriovNetworkNodeStateStatus{
Interfaces: []InterfaceExt{
{
VFs: []VirtualFunction{
{
DeviceID: "154c",
Driver: "iavf",
PciAddress: "0000:86:00.1",
Mtu: 1500,
VfID: 0,
},
},
DeviceID: "154c",
Driver: "iavf",
Mtu: 1500,
Name: "ens803f0",
PciAddress: "0000:86:00.0",
Vendor: "8086",
NumVfs: 1,
TotalVfs: 64,
NetFilter: "openstack/NetworkID:e48c7670-bcb4-4f9c-8038-012b6571501d",
},
},
},
}
policy := &SriovNetworkNodePolicy{
Spec: SriovNetworkNodePolicySpec{
DeviceType: "netdevice",
NicSelector: SriovNetworkNicSelector{
PfNames: []string{"ens803f0"},
NetFilter: "openstack/NetworkID:e48c7670-bcb4-4f9c-8038-012b6571501d",
},
NodeSelector: map[string]string{
"feature.node.kubernetes.io/network-sriov.capable": "true",
},
NumVfs: 1,
Priority: 99,
ResourceName: "p0",
},
}
g := NewGomegaWithT(t)
ok, err := validatePolicyForNodeState(policy, state, NewNode())
g.Expect(err).NotTo(HaveOccurred())
g.Expect(ok).To(Equal(true))
g.Expect(interfaceSelected).To(Equal(true))
}

0 comments on commit 8f4d42f

Please sign in to comment.