@@ -73,6 +73,20 @@ func (w *testEIPWatcher) assertNoChanges() error {
7373 return w .assertChanges ()
7474}
7575
76+ func (w * testEIPWatcher ) flushChanges () {
77+ w .changes = []string {}
78+ }
79+
80+ func (w * testEIPWatcher ) assertUpdateEgressCIDRsNotification () error {
81+ for _ , change := range w .changes {
82+ if change == "update egress CIDRs" {
83+ w .flushChanges ()
84+ return nil
85+ }
86+ }
87+ return fmt .Errorf ("expected change \" update egress CIDRs\" , got %#v" , w .changes )
88+ }
89+
7690func setupEgressIPTracker (t * testing.T ) (* EgressIPTracker , * testEIPWatcher ) {
7791 watcher := & testEIPWatcher {}
7892 return NewEgressIPTracker (watcher ), watcher
@@ -864,9 +878,6 @@ func TestEgressCIDRAllocation(t *testing.T) {
864878 t .Fatalf ("%v" , err )
865879 }
866880 allocation = eit .ReallocateEgressIPs ()
867- if len (allocation ) != 0 {
868- t .Fatalf ("Unexpected allocation: %#v" , allocation )
869- }
870881 updateAllocations (eit , allocation )
871882 err = w .assertNoChanges ()
872883 if err != nil {
@@ -947,31 +958,41 @@ func TestEgressCIDRAllocation(t *testing.T) {
947958 t .Fatalf ("%v" , err )
948959 }
949960
950- // Changing the EgressIPs of a namespace should drop the old allocation and create a new one
961+ // Changing/Removing the EgressIPs of a namespace should drop the old allocation and create a new one
951962 updateNetNamespaceEgress (eit , & networkapi.NetNamespace {
952963 NetID : 46 ,
953964 EgressIPs : []string {"172.17.0.202" }, // was 172.17.0.200
954965 })
966+ updateNetNamespaceEgress (eit , & networkapi.NetNamespace {
967+ NetID : 44 ,
968+ EgressIPs : []string {}, // was 172.17.1.1
969+ })
955970 err = w .assertChanges (
956971 "release 172.17.0.200 on 172.17.0.4" ,
957972 "namespace 46 dropped" ,
958973 "update egress CIDRs" ,
974+ "release 172.17.1.1 on 172.17.0.3" ,
975+ "namespace 44 normal" ,
976+ "update egress CIDRs" ,
959977 )
960978 if err != nil {
961979 t .Fatalf ("%v" , err )
962980 }
963981
964982 allocation = eit .ReallocateEgressIPs ()
965- for _ , ip := range allocation ["node-4" ] {
966- if ip == "172.17.0.200" {
967- t .Fatalf ("reallocation failed to drop unused egress IP 172.17.0.200: %#v" , allocation )
983+ for _ , nodeAllocation := range allocation {
984+ for _ , ip := range nodeAllocation {
985+ if ip == "172.17.1.1" || ip == "172.17.0.200" {
986+ t .Fatalf ("reallocation failed to drop unused egress IP %s: %#v" , ip , allocation )
987+ }
968988 }
969989 }
970990 updateAllocations (eit , allocation )
971991 err = w .assertChanges (
972992 "claim 172.17.0.202 on 172.17.0.4 for namespace 46" ,
973993 "namespace 46 via 172.17.0.202 on 172.17.0.4" ,
974994 "update egress CIDRs" ,
995+ "update egress CIDRs" ,
975996 )
976997 if err != nil {
977998 t .Fatalf ("%v" , err )
@@ -1031,3 +1052,132 @@ func TestEgressNodeRenumbering(t *testing.T) {
10311052 t .Fatalf ("%v" , err )
10321053 }
10331054}
1055+
1056+ func TestEgressCIDRAllocationOffline (t * testing.T ) {
1057+ eit , w := setupEgressIPTracker (t )
1058+
1059+ // Create nodes...
1060+ updateHostSubnetEgress (eit , & networkapi.HostSubnet {
1061+ HostIP : "172.17.0.3" ,
1062+ EgressIPs : []string {},
1063+ EgressCIDRs : []string {"172.17.0.0/24" , "172.17.1.0/24" },
1064+ })
1065+ updateHostSubnetEgress (eit , & networkapi.HostSubnet {
1066+ HostIP : "172.17.0.4" ,
1067+ EgressIPs : []string {},
1068+ EgressCIDRs : []string {"172.17.0.0/24" },
1069+ })
1070+ updateHostSubnetEgress (eit , & networkapi.HostSubnet {
1071+ HostIP : "172.17.0.5" ,
1072+ EgressIPs : []string {},
1073+ EgressCIDRs : []string {"172.17.1.0/24" },
1074+ })
1075+
1076+ // Create namespaces
1077+ updateNetNamespaceEgress (eit , & networkapi.NetNamespace {
1078+ NetID : 100 ,
1079+ EgressIPs : []string {"172.17.0.100" },
1080+ })
1081+ updateNetNamespaceEgress (eit , & networkapi.NetNamespace {
1082+ NetID : 101 ,
1083+ EgressIPs : []string {"172.17.0.101" },
1084+ })
1085+ updateNetNamespaceEgress (eit , & networkapi.NetNamespace {
1086+ NetID : 102 ,
1087+ EgressIPs : []string {"172.17.0.102" },
1088+ })
1089+ updateNetNamespaceEgress (eit , & networkapi.NetNamespace {
1090+ NetID : 200 ,
1091+ EgressIPs : []string {"172.17.1.200" },
1092+ })
1093+ updateNetNamespaceEgress (eit , & networkapi.NetNamespace {
1094+ NetID : 201 ,
1095+ EgressIPs : []string {"172.17.1.201" },
1096+ })
1097+ updateNetNamespaceEgress (eit , & networkapi.NetNamespace {
1098+ NetID : 202 ,
1099+ EgressIPs : []string {"172.17.1.202" },
1100+ })
1101+
1102+ // In a perfect world, we'd get 2 IPs on each node, but depending on processing
1103+ // order, this isn't guaranteed. Eg, if the three 172.17.0.x IPs get processed
1104+ // first, we could get two of them on node-3 and one on node-4. Then the first two
1105+ // 172.17.1.x IPs get assigned to node-5, and the last one could go to either
1106+ // node-3 or node-5. Regardless of order, node-3 is guaranteed to get at least
1107+ // two IPs since there's no way either node-4 or node-5 could be assigned a
1108+ // third IP if node-3 still only had one.
1109+ allocation := eit .ReallocateEgressIPs ()
1110+ node3ips := allocation ["node-3" ]
1111+ node4ips := allocation ["node-4" ]
1112+ node5ips := allocation ["node-5" ]
1113+ if len (node3ips ) < 2 || len (node4ips ) == 0 || len (node5ips ) == 0 ||
1114+ len (node3ips )+ len (node4ips )+ len (node5ips ) != 6 {
1115+ t .Fatalf ("Bad IP allocation: %#v" , allocation )
1116+ }
1117+ updateAllocations (eit , allocation )
1118+
1119+ w .flushChanges ()
1120+
1121+ // Now take node-3 offline
1122+ eit .SetNodeOffline ("172.17.0.3" , true )
1123+ err := w .assertUpdateEgressCIDRsNotification ()
1124+ if err != nil {
1125+ t .Fatalf ("%v" , err )
1126+ }
1127+
1128+ // First reallocation should empty out node-3
1129+ allocation = eit .ReallocateEgressIPs ()
1130+ if node3ips , ok := allocation ["node-3" ]; ! ok || len (node3ips ) != 0 {
1131+ t .Fatalf ("Bad IP allocation: %#v" , allocation )
1132+ }
1133+ updateAllocations (eit , allocation )
1134+
1135+ err = w .assertUpdateEgressCIDRsNotification ()
1136+ if err != nil {
1137+ t .Fatalf ("%v" , err )
1138+ }
1139+
1140+ // Next reallocation should reassign egress IPs to node-4 and node-5
1141+ allocation = eit .ReallocateEgressIPs ()
1142+ node3ips = allocation ["node-3" ]
1143+ node4ips = allocation ["node-4" ]
1144+ node5ips = allocation ["node-5" ]
1145+ if len (node3ips ) != 0 || len (node4ips ) != 3 || len (node5ips ) != 3 {
1146+ t .Fatalf ("Bad IP allocation: %#v" , allocation )
1147+ }
1148+ updateAllocations (eit , allocation )
1149+
1150+ // Bring node-3 back
1151+ eit .SetNodeOffline ("172.17.0.3" , false )
1152+ err = w .assertUpdateEgressCIDRsNotification ()
1153+ if err != nil {
1154+ t .Fatalf ("%v" , err )
1155+ }
1156+
1157+ // First reallocation should remove some IPs from node-4 and node-5 but not add
1158+ // them to node-3. As above, the "balanced" allocation we're aiming for may not
1159+ // be perfect, but it has to be planning to assign at least 2 IPs to node-3.
1160+ allocation = eit .ReallocateEgressIPs ()
1161+ node3ips = allocation ["node-3" ]
1162+ node4ips = allocation ["node-4" ]
1163+ node5ips = allocation ["node-5" ]
1164+ if len (node3ips ) != 0 || len (node4ips )+ len (node5ips ) > 4 {
1165+ t .Fatalf ("Bad IP allocation: %#v" , allocation )
1166+ }
1167+ updateAllocations (eit , allocation )
1168+
1169+ err = w .assertUpdateEgressCIDRsNotification ()
1170+ if err != nil {
1171+ t .Fatalf ("%v" , err )
1172+ }
1173+
1174+ // Next reallocation should reassign egress IPs to node-3
1175+ allocation = eit .ReallocateEgressIPs ()
1176+ node3ips = allocation ["node-3" ]
1177+ node4ips = allocation ["node-4" ]
1178+ node5ips = allocation ["node-5" ]
1179+ if len (node3ips ) < 2 || len (node4ips ) == 0 || len (node5ips ) == 0 {
1180+ t .Fatalf ("Bad IP allocation: %#v" , allocation )
1181+ }
1182+ updateAllocations (eit , allocation )
1183+ }
0 commit comments