@@ -18,6 +18,7 @@ package multus
1818import (
1919 "context"
2020 "encoding/json"
21+ stderrors "errors"
2122 "fmt"
2223 "net"
2324 "os"
@@ -30,6 +31,7 @@ import (
3031 "github.com/containernetworking/cni/pkg/skel"
3132 cnitypes "github.com/containernetworking/cni/pkg/types"
3233 cni100 "github.com/containernetworking/cni/pkg/types/100"
34+ cniversion "github.com/containernetworking/cni/pkg/version"
3335 "github.com/containernetworking/plugins/pkg/ns"
3436 nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
3537 nadutils "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils"
@@ -258,6 +260,42 @@ func confDel(rt *libcni.RuntimeConf, rawNetconf []byte, multusNetconf *types.Net
258260 return err
259261}
260262
263+ func confStatus (rt * libcni.RuntimeConf , rawNetconf []byte , multusNetconf * types.NetConf , exec invoke.Exec ) error {
264+ logging .Debugf ("confStatus: %v, %s" , rt , string (rawNetconf ))
265+
266+ binDirs := filepath .SplitList (os .Getenv ("CNI_PATH" ))
267+ binDirs = append ([]string {multusNetconf .BinDir }, binDirs ... )
268+ cniNet := libcni .NewCNIConfigWithCacheDir (binDirs , multusNetconf .CNIDir , exec )
269+
270+ conf , err := libcni .ConfFromBytes (rawNetconf )
271+ if err != nil {
272+ return logging .Errorf ("error in converting the raw bytes to conf: %v" , err )
273+ }
274+
275+ if gt , _ := cniversion .GreaterThanOrEqualTo (conf .Network .CNIVersion , "1.1.0" ); ! gt {
276+ logging .Debugf ("confStatus: skipping STATUS for network %q type %q cniVersion %q (< 1.1.0)" ,
277+ conf .Network .Name , conf .Network .Type , conf .Network .CNIVersion )
278+ return nil
279+ }
280+
281+ confList := & libcni.NetworkConfigList {
282+ Name : conf .Network .Name ,
283+ CNIVersion : conf .Network .CNIVersion ,
284+ Plugins : []* libcni.PluginConfig {conf },
285+ }
286+
287+ err = cniNet .GetStatusNetworkList (context .Background (), confList )
288+ if err != nil {
289+ var cniErr * cnitypes.Error
290+ if stderrors .As (err , & cniErr ) {
291+ return err
292+ }
293+ return logging .Errorf ("error in getting result from StatusNetworkList: %v" , err )
294+ }
295+
296+ return err
297+ }
298+
261299func conflistAdd (rt * libcni.RuntimeConf , rawnetconflist []byte , cniConfList * libcni.NetworkConfigList , multusNetconf * types.NetConf , exec invoke.Exec ) (cnitypes.Result , error ) {
262300 logging .Debugf ("conflistAdd: %v, %s" , rt , string (rawnetconflist ))
263301 // In part, adapted from K8s pkg/kubelet/dockershim/network/cni/cni.go
@@ -327,6 +365,34 @@ func conflistDel(rt *libcni.RuntimeConf, rawnetconflist []byte, multusNetconf *t
327365 return err
328366}
329367
368+ func conflistStatus (rt * libcni.RuntimeConf , rawnetconflist []byte , multusNetconf * types.NetConf , exec invoke.Exec ) error {
369+ logging .Debugf ("conflistStatus: %v, %s" , rt , string (rawnetconflist ))
370+
371+ binDirs := filepath .SplitList (os .Getenv ("CNI_PATH" ))
372+ binDirs = append ([]string {multusNetconf .BinDir }, binDirs ... )
373+ cniNet := libcni .NewCNIConfigWithCacheDir (binDirs , multusNetconf .CNIDir , exec )
374+
375+ confList , err := libcni .ConfListFromBytes (rawnetconflist )
376+ if err != nil {
377+ return logging .Errorf ("conflistStatus: error converting the raw bytes into a conflist: %v" , err )
378+ }
379+ if gt , _ := cniversion .GreaterThanOrEqualTo (confList .CNIVersion , "1.1.0" ); ! gt {
380+ logging .Debugf ("conflistStatus: skipping STATUS for network list %q cniVersion %q (< 1.1.0)" , confList .Name , confList .CNIVersion )
381+ return nil
382+ }
383+
384+ err = cniNet .GetStatusNetworkList (context .Background (), confList )
385+ if err != nil {
386+ var cniErr * cnitypes.Error
387+ if stderrors .As (err , & cniErr ) {
388+ return err
389+ }
390+ return logging .Errorf ("conflistStatus: error in getting result from StatusNetworkList: %v" , err )
391+ }
392+
393+ return err
394+ }
395+
330396// DelegateAdd ...
331397func DelegateAdd (exec invoke.Exec , kubeClient * k8s.ClientInfo , pod * v1.Pod , delegate * types.DelegateNetConf , rt * libcni.RuntimeConf , multusNetconf * types.NetConf ) (cnitypes.Result , error ) {
332398 logging .Debugf ("DelegateAdd: %v, %v, %v" , exec , delegate , rt )
@@ -456,6 +522,46 @@ func DelegateCheck(exec invoke.Exec, delegateConf *types.DelegateNetConf, rt *li
456522 return err
457523}
458524
525+ // DelegateStatus ...
526+ func DelegateStatus (exec invoke.Exec , delegateConf * types.DelegateNetConf , rt * libcni.RuntimeConf , multusNetconf * types.NetConf ) error {
527+ logging .Debugf ("DelegateStatus: %v, %v, %v" , exec , delegateConf , rt )
528+
529+ isConfList := delegateConf .ConfListPlugin
530+ if ! isConfList && delegateConf .Conf .Type == "" && delegateConf .ConfList .Name != "" {
531+ isConfList = true
532+ }
533+
534+ if logging .GetLoggingLevel () >= logging .VerboseLevel {
535+ var cniConfName string
536+ if isConfList {
537+ cniConfName = delegateConf .ConfList .Name
538+ } else {
539+ cniConfName = delegateConf .Conf .Name
540+ }
541+ logging .Verbosef ("Status: %s:%s:%s(%s):%s %s" , rt .Args [1 ][1 ], rt .Args [2 ][1 ], delegateConf .Name , cniConfName , rt .IfName , string (delegateConf .Bytes ))
542+ }
543+
544+ var err error
545+ if isConfList {
546+ err = conflistStatus (rt , delegateConf .Bytes , multusNetconf , exec )
547+ } else {
548+ err = confStatus (rt , delegateConf .Bytes , multusNetconf , exec )
549+ }
550+
551+ if err != nil {
552+ var cniErr * cnitypes.Error
553+ if stderrors .As (err , & cniErr ) {
554+ return err
555+ }
556+ if isConfList {
557+ return logging .Errorf ("DelegateStatus: error invoking ConflistStatus - %q: %v" , delegateConf .ConfList .Name , err )
558+ }
559+ return logging .Errorf ("DelegateStatus: error invoking ConfStatus - %q: %v" , delegateConf .Conf .Type , err )
560+ }
561+
562+ return err
563+ }
564+
459565// DelegateDel ...
460566func DelegateDel (exec invoke.Exec , pod * v1.Pod , delegateConf * types.DelegateNetConf , rt * libcni.RuntimeConf , multusNetconf * types.NetConf ) error {
461567 logging .Debugf ("DelegateDel: %v, %v, %v, %v" , exec , pod , delegateConf , rt )
@@ -659,10 +765,10 @@ func CmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo) (c
659765
660766 pod , err := GetPod (kubeClient , k8sArgs , false )
661767 if err != nil {
662- if err == errPodNotFound {
663- emptyresult := emptyCNIResult (args , "1.0.0" )
664- logging .Verbosef ("CmdAdd: Warning: pod [%s/%s] not found, exiting with empty CNI result: %v" , k8sArgs .K8S_POD_NAMESPACE , k8sArgs .K8S_POD_NAME , emptyresult )
665- return emptyresult , nil
768+ if stderrors . Is ( err , errPodNotFound ) {
769+ emptyResult := emptyCNIResult (args , n . CNIVersion )
770+ logging .Verbosef ("CmdAdd: Warning: pod [%s/%s] not found, exiting with empty CNI result: %v" , k8sArgs .K8S_POD_NAMESPACE , k8sArgs .K8S_POD_NAME , emptyResult )
771+ return emptyResult , nil
666772 }
667773 return nil , err
668774 }
@@ -1050,17 +1156,26 @@ func CmdStatus(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo)
10501156
10511157 // invoke delegate's STATUS command
10521158 // we only need to check cluster network status
1159+ delegate := n .Delegates [0 ]
1160+ if ! delegate .ConfListPlugin {
1161+ return confStatus (& libcni.RuntimeConf {}, delegate .Bytes , n , exec )
1162+ }
1163+
10531164 binDirs := filepath .SplitList (os .Getenv ("CNI_PATH" ))
10541165 binDirs = append ([]string {n .BinDir }, binDirs ... )
10551166 cniNet := libcni .NewCNIConfigWithCacheDir (binDirs , n .CNIDir , exec )
10561167
1057- conf , err := libcni .ConfListFromBytes (n . Delegates [ 0 ] .Bytes )
1168+ conf , err := libcni .ConfListFromBytes (delegate .Bytes )
10581169 if err != nil {
10591170 return logging .Errorf ("error in converting the raw bytes to conf: %v" , err )
10601171 }
10611172
1062- err = cniNet .GetStatusNetworkList (context .TODO (), conf )
1173+ err = cniNet .GetStatusNetworkList (context .Background (), conf )
10631174 if err != nil {
1175+ var cniErr * cnitypes.Error
1176+ if stderrors .As (err , & cniErr ) {
1177+ return err
1178+ }
10641179 return logging .Errorf ("error in STATUS command: %v" , err )
10651180 }
10661181
@@ -1101,17 +1216,36 @@ func CmdGC(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo) err
11011216 binDirs = append ([]string {n .BinDir }, binDirs ... )
11021217 cniNet := libcni .NewCNIConfigWithCacheDir (binDirs , n .CNIDir , exec )
11031218
1104- conf , err := libcni .ConfListFromBytes (n .Delegates [0 ].Bytes )
1105- if err != nil {
1106- return logging .Errorf ("error in converting the raw bytes to conf: %v" , err )
1219+ delegate := n .Delegates [0 ]
1220+ isConfList := delegate .ConfListPlugin
1221+ if ! isConfList && delegate .Conf .Type == "" && delegate .ConfList .Name != "" {
1222+ isConfList = true
1223+ }
1224+
1225+ var confList * libcni.NetworkConfigList
1226+ if isConfList {
1227+ confList , err = libcni .ConfListFromBytes (delegate .Bytes )
1228+ if err != nil {
1229+ return logging .Errorf ("error in converting the raw bytes to conf: %v" , err )
1230+ }
1231+ } else {
1232+ conf , err := libcni .ConfFromBytes (delegate .Bytes )
1233+ if err != nil {
1234+ return logging .Errorf ("error in converting the raw bytes to conf: %v" , err )
1235+ }
1236+ confList = & libcni.NetworkConfigList {
1237+ Name : conf .Network .Name ,
1238+ CNIVersion : conf .Network .CNIVersion ,
1239+ Plugins : []* libcni.PluginConfig {conf },
1240+ }
11071241 }
11081242
11091243 validAttachments , err := gatherValidAttachmentsFromCache (n .CNIDir )
11101244 if err != nil {
11111245 return logging .Errorf ("error in gather valid attachments: %v" , err )
11121246 }
11131247
1114- err = cniNet .GCNetworkList (context .TODO (), conf , & libcni.GCArgs {
1248+ err = cniNet .GCNetworkList (context .TODO (), confList , & libcni.GCArgs {
11151249 ValidAttachments : validAttachments ,
11161250 })
11171251 if err != nil {
0 commit comments