@@ -18,6 +18,7 @@ import (
18
18
"encoding/json"
19
19
"errors"
20
20
"fmt"
21
+ "log"
21
22
"net"
22
23
"os"
23
24
"runtime"
@@ -41,7 +42,10 @@ import (
41
42
)
42
43
43
44
// For testcases to force an error after IPAM has been performed
44
- var debugPostIPAMError error
45
+ var (
46
+ debugPostIPAMError error
47
+ logger = log .New (os .Stdout , "" , log .Ldate | log .Ltime )
48
+ )
45
49
46
50
const defaultBrName = "cni0"
47
51
@@ -774,10 +778,6 @@ func cmdDel(args *skel.CmdArgs) error {
774
778
return nil
775
779
}
776
780
777
- if args .Netns == "" {
778
- return ipamDel ()
779
- }
780
-
781
781
// There is a netns so try to clean up. Delete can be called multiple times
782
782
// so don't return an error if the device is already removed.
783
783
// If the device isn't there then don't try to clean up IP masq either.
@@ -791,28 +791,35 @@ func cmdDel(args *skel.CmdArgs) error {
791
791
return err
792
792
})
793
793
if err != nil {
794
- // if NetNs is passed down by the Cloud Orchestration Engine, or if it called multiple times
794
+ // if NetNs is passed down by the Cloud Orchestration Engine, or if it called multiple times
795
795
// so don't return an error if the device is already removed.
796
796
// https://github.com/kubernetes/kubernetes/issues/43014#issuecomment-287164444
797
797
_ , ok := err .(ns.NSPathNotExistErr )
798
- if ok {
799
- return ipamDel ()
798
+ if ! ok {
799
+ return err
800
800
}
801
- return err
802
801
}
803
802
804
- // call ipam.ExecDel after clean up device in netns
805
- if err := ipamDel (); err != nil {
806
- return err
807
- }
803
+ if len (ipnets ) == 0 {
804
+ // could not get ip address within netns, so try to get it from prevResult
805
+ prevResult , err := parsePrevResult (n )
806
+ if err != nil {
807
+ return err
808
+ }
808
809
809
- if n .MacSpoofChk {
810
- sc := link .NewSpoofChecker ("" , "" , uniqueID (args .ContainerID , args .IfName ))
811
- if err := sc .Teardown (); err != nil {
812
- fmt .Fprintf (os .Stderr , "%v" , err )
810
+ if prevResult != nil {
811
+ ipCfgs , err := getIPCfgs (args .IfName , prevResult )
812
+ if err != nil {
813
+ return err
814
+ }
815
+
816
+ for _ , ip := range ipCfgs {
817
+ ipnets = append (ipnets , & ip .Address )
818
+ }
813
819
}
814
820
}
815
821
822
+ // clean up IP masq first
816
823
if isLayer3 && n .IPMasq {
817
824
chain := utils .FormatChainName (n .Name , args .ContainerID )
818
825
comment := utils .FormatComment (n .Name , args .ContainerID )
@@ -823,6 +830,18 @@ func cmdDel(args *skel.CmdArgs) error {
823
830
}
824
831
}
825
832
833
+ // call ipam.ExecDel after clean up device in netns
834
+ if err := ipamDel (); err != nil {
835
+ return err
836
+ }
837
+
838
+ if n .MacSpoofChk {
839
+ sc := link .NewSpoofChecker ("" , "" , uniqueID (args .ContainerID , args .IfName ))
840
+ if err := sc .Teardown (); err != nil {
841
+ fmt .Fprintf (os .Stderr , "%v" , err )
842
+ }
843
+ }
844
+
826
845
return err
827
846
}
828
847
@@ -1088,3 +1107,60 @@ func cmdCheck(args *skel.CmdArgs) error {
1088
1107
func uniqueID (containerID , cniIface string ) string {
1089
1108
return containerID + "-" + cniIface
1090
1109
}
1110
+
1111
+ // parsePrevResult parse previous result
1112
+ func parsePrevResult (conf * NetConf ) (* current.Result , error ) {
1113
+ var prevResult * current.Result
1114
+ if conf .RawPrevResult != nil {
1115
+ resultBytes , err := json .Marshal (conf .RawPrevResult )
1116
+ if err != nil {
1117
+ return nil , fmt .Errorf ("could not serialize prevResult: %#v" , err )
1118
+ }
1119
+ res , err := version .NewResult (conf .CNIVersion , resultBytes )
1120
+ if err != nil {
1121
+ return nil , fmt .Errorf ("could not parse prevResult: %v" , err )
1122
+ }
1123
+ conf .RawPrevResult = nil
1124
+ prevResult , err = current .NewResultFromResult (res )
1125
+ if err != nil {
1126
+ return nil , fmt .Errorf ("could not convert result to current version: %v" , err )
1127
+ }
1128
+ }
1129
+ return prevResult , nil
1130
+ }
1131
+
1132
+ // getIPCfgs finds the IPs on the supplied interface, returning as IPConfig structures
1133
+ func getIPCfgs (iface string , prevResult * current.Result ) ([]* current.IPConfig , error ) {
1134
+ if len (prevResult .IPs ) == 0 {
1135
+ // No IP addresses; that makes no sense. Pack it in.
1136
+ return nil , fmt .Errorf ("No IP addresses supplied on interface: %s" , iface )
1137
+ }
1138
+
1139
+ // We do a single interface name, stored in args.IfName
1140
+ logger .Printf ("Checking for relevant interface: %s" , iface )
1141
+
1142
+ // ips contains the IPConfig structures that were passed, filtered somewhat
1143
+ ipCfgs := make ([]* current.IPConfig , 0 , len (prevResult .IPs ))
1144
+
1145
+ for _ , ipCfg := range prevResult .IPs {
1146
+ // IPs have an interface that is an index into the interfaces array.
1147
+ // We assume a match if this index is missing.
1148
+ if ipCfg .Interface == nil {
1149
+ logger .Printf ("No interface for IP address %s" , ipCfg .Address .IP )
1150
+ ipCfgs = append (ipCfgs , ipCfg )
1151
+ continue
1152
+ }
1153
+
1154
+ // Skip all IPs we know belong to an interface with the wrong name.
1155
+ intIdx := * ipCfg .Interface
1156
+ if intIdx >= 0 && intIdx < len (prevResult .Interfaces ) && prevResult .Interfaces [intIdx ].Name != iface {
1157
+ logger .Printf ("Incorrect interface for IP address %s" , ipCfg .Address .IP )
1158
+ continue
1159
+ }
1160
+
1161
+ logger .Printf ("Found IP address %s" , ipCfg .Address .IP .String ())
1162
+ ipCfgs = append (ipCfgs , ipCfg )
1163
+ }
1164
+
1165
+ return ipCfgs , nil
1166
+ }
0 commit comments