Browse Source

Rolling back the port configs if failed to programIngress()

Signed-off-by: fanjiyun <fan.jiyun@zte.com.cn>
fanjiyun 7 years ago
parent
commit
03ba96c5cf
2 changed files with 40 additions and 18 deletions
  1. 1 1
      libnetwork/resolver_unix.go
  2. 39 17
      libnetwork/service_linux.go

+ 1 - 1
libnetwork/resolver_unix.go

@@ -76,7 +76,7 @@ func reexecSetupResolver() {
 
 	for _, rule := range rules {
 		if iptables.RawCombinedOutputNative(rule...) != nil {
-			logrus.Errorf("setting up rule failed, %v", rule)
+			logrus.Errorf("set up rule failed, %v", rule)
 		}
 	}
 }

+ 39 - 17
libnetwork/service_linux.go

@@ -135,8 +135,7 @@ func (n *network) addLBBackend(ip net.IP, lb *loadBalancer) {
 			if ep := sb.getGatewayEndpoint(); ep != nil {
 				gwIP = ep.Iface().Address().IP
 			}
-			filteredPorts := filterPortConfigs(lb.service.ingressPorts, false)
-			if err := programIngress(gwIP, filteredPorts, false); err != nil {
+			if err := programIngress(gwIP, lb.service.ingressPorts, false); err != nil {
 				logrus.Errorf("Failed to add ingress: %v", err)
 				return
 			}
@@ -227,8 +226,7 @@ func (n *network) rmLBBackend(ip net.IP, lb *loadBalancer, rmService bool, fullR
 			if ep := sb.getGatewayEndpoint(); ep != nil {
 				gwIP = ep.Iface().Address().IP
 			}
-			filteredPorts := filterPortConfigs(lb.service.ingressPorts, true)
-			if err := programIngress(gwIP, filteredPorts, true); err != nil {
+			if err := programIngress(gwIP, lb.service.ingressPorts, true); err != nil {
 				logrus.Errorf("Failed to delete ingress: %v", err)
 			}
 		}
@@ -299,8 +297,10 @@ func filterPortConfigs(ingressPorts []*PortConfig, isDelete bool) []*PortConfig
 
 func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) error {
 	addDelOpt := "-I"
+	rollbackAddDelOpt := "-D"
 	if isDelete {
 		addDelOpt = "-D"
+		rollbackAddDelOpt = "-I"
 	}
 
 	ingressMu.Lock()
@@ -381,18 +381,35 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro
 		}
 	}
 
-	for _, iPort := range ingressPorts {
+	//Filter the ingress ports until port rules start to be added/deleted
+	filteredPorts := filterPortConfigs(ingressPorts, isDelete)
+	rollbackRules := make([][]string, 0, len(filteredPorts)*3)
+	var portErr error
+	defer func() {
+		if portErr != nil && !isDelete {
+			filterPortConfigs(filteredPorts, !isDelete)
+			for _, rule := range rollbackRules {
+				if err := iptables.RawCombinedOutput(rule...); err != nil {
+					logrus.Warnf("roll back rule failed, %v: %v", rule, err)
+				}
+			}
+		}
+	}()
+
+	for _, iPort := range filteredPorts {
 		if iptables.ExistChain(ingressChain, iptables.Nat) {
 			rule := strings.Fields(fmt.Sprintf("-t nat %s %s -p %s --dport %d -j DNAT --to-destination %s:%d",
 				addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, gwIP, iPort.PublishedPort))
-			if err := iptables.RawCombinedOutput(rule...); err != nil {
-				errStr := fmt.Sprintf("setting up rule failed, %v: %v", rule, err)
+			if portErr = iptables.RawCombinedOutput(rule...); portErr != nil {
+				errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr)
 				if !isDelete {
 					return fmt.Errorf("%s", errStr)
 				}
-
 				logrus.Infof("%s", errStr)
 			}
+			rollbackRule := strings.Fields(fmt.Sprintf("-t nat %s %s -p %s --dport %d -j DNAT --to-destination %s:%d", rollbackAddDelOpt,
+				ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, gwIP, iPort.PublishedPort))
+			rollbackRules = append(rollbackRules, rollbackRule)
 		}
 
 		// Filter table rules to allow a published service to be accessible in the local node from..
@@ -400,24 +417,29 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro
 		// 2) unmanaged containers on bridge networks
 		rule := strings.Fields(fmt.Sprintf("%s %s -m state -p %s --sport %d --state ESTABLISHED,RELATED -j ACCEPT",
 			addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort))
-		if err := iptables.RawCombinedOutput(rule...); err != nil {
-			errStr := fmt.Sprintf("setting up rule failed, %v: %v", rule, err)
+		if portErr = iptables.RawCombinedOutput(rule...); portErr != nil {
+			errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr)
 			if !isDelete {
 				return fmt.Errorf("%s", errStr)
 			}
 			logrus.Warnf("%s", errStr)
 		}
+		rollbackRule := strings.Fields(fmt.Sprintf("%s %s -m state -p %s --sport %d --state ESTABLISHED,RELATED -j ACCEPT", rollbackAddDelOpt,
+			ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort))
+		rollbackRules = append(rollbackRules, rollbackRule)
 
 		rule = strings.Fields(fmt.Sprintf("%s %s -p %s --dport %d -j ACCEPT",
 			addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort))
-		if err := iptables.RawCombinedOutput(rule...); err != nil {
-			errStr := fmt.Sprintf("setting up rule failed, %v: %v", rule, err)
+		if portErr = iptables.RawCombinedOutput(rule...); portErr != nil {
+			errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr)
 			if !isDelete {
 				return fmt.Errorf("%s", errStr)
 			}
-
 			logrus.Warnf("%s", errStr)
 		}
+		rollbackRule = strings.Fields(fmt.Sprintf("%s %s -p %s --dport %d -j ACCEPT", rollbackAddDelOpt,
+			ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort))
+		rollbackRules = append(rollbackRules, rollbackRule)
 
 		if err := plumbProxy(iPort, isDelete); err != nil {
 			logrus.Warnf("failed to create proxy for port %d: %v", iPort.PublishedPort, err)
@@ -648,7 +670,7 @@ func fwMarker() {
 
 	for _, rule := range rules {
 		if err := iptables.RawCombinedOutputNative(rule...); err != nil {
-			logrus.Errorf("setting up rule failed, %v: %v", rule, err)
+			logrus.Errorf("set up rule failed, %v: %v", rule, err)
 			os.Exit(8)
 		}
 	}
@@ -735,7 +757,7 @@ func redirector() {
 
 	for _, rule := range rules {
 		if err := iptables.RawCombinedOutputNative(rule...); err != nil {
-			logrus.Errorf("setting up rule failed, %v: %v", rule, err)
+			logrus.Errorf("set up rule failed, %v: %v", rule, err)
 			os.Exit(6)
 		}
 	}
@@ -752,14 +774,14 @@ func redirector() {
 	} {
 		if !iptables.ExistsNative(iptables.Filter, "INPUT", rule...) {
 			if err := iptables.RawCombinedOutputNative(append([]string{"-A", "INPUT"}, rule...)...); err != nil {
-				logrus.Errorf("setting up rule failed, %v: %v", rule, err)
+				logrus.Errorf("set up rule failed, %v: %v", rule, err)
 				os.Exit(7)
 			}
 		}
 		rule[0] = "-s"
 		if !iptables.ExistsNative(iptables.Filter, "OUTPUT", rule...) {
 			if err := iptables.RawCombinedOutputNative(append([]string{"-A", "OUTPUT"}, rule...)...); err != nil {
-				logrus.Errorf("setting up rule failed, %v: %v", rule, err)
+				logrus.Errorf("set up rule failed, %v: %v", rule, err)
 				os.Exit(8)
 			}
 		}