...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package recover
17
18 import (
19 "context"
20 "fmt"
21 "regexp"
22 "strconv"
23 "strings"
24
25 "github.com/pingcap/errors"
26
27 ctrlclient "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/client"
28 )
29
30
31
32
33
34
35
36 var tcRegexp = regexp.MustCompile(`([0-9]+): dev (\w+)`)
37
38 type tcsRecoverer struct {
39 client *ctrlclient.CtrlClient
40 }
41
42 func newTcsRecoverer(client *ctrlclient.CtrlClient) Recoverer {
43 return &tcsRecoverer{
44 client: client,
45 }
46 }
47
48
49 func (r *tcsRecoverer) Recover(ctx context.Context, pod *PartialPod) error {
50 deviceSet := map[string]bool{}
51 for _, rule := range pod.TcQdisc {
52 matches := tcRegexp.FindStringSubmatch(rule)
53 if len(matches) != 3 {
54 continue
55 }
56 handle, err := strconv.Atoi(matches[1])
57 if err != nil {
58 return errors.Wrapf(err, "parse tc qdisc handle: `%s`", matches[1])
59 }
60 if handle > 0 {
61
62 deviceSet[matches[2]] = true
63 }
64 }
65
66 var devices []string
67 for dev := range deviceSet {
68 devices = append(devices, dev)
69 }
70
71 if len(devices) == 0 {
72 printStep("all tc rules are cleaned up")
73 return nil
74 }
75 printStep(fmt.Sprintf("cleaning tc rules for device %v", devices))
76
77 cleanedTcs, err := r.client.CleanTcs(ctx, pod.Namespace, pod.Name, devices)
78 if err != nil {
79 return err
80 }
81
82 if len(cleanedTcs) != 0 {
83 printStep(fmt.Sprintf("tc rules on device %s are cleaned up", strings.Join(cleanedTcs, ",")))
84 }
85
86 return nil
87 }
88
89 type iptablesRecoverer struct {
90 client *ctrlclient.CtrlClient
91 }
92
93 func newIptablesRecoverer(client *ctrlclient.CtrlClient) Recoverer {
94 return &iptablesRecoverer{
95 client: client,
96 }
97 }
98
99
100 func (r *iptablesRecoverer) Recover(ctx context.Context, pod *PartialPod) error {
101 chainSet := map[string]bool{
102 "CHAOS-INPUT": false,
103 "CHAOS-OUTPUT": false,
104 }
105 for _, rule := range pod.Iptables {
106 for chain := range chainSet {
107 if strings.HasPrefix(rule, fmt.Sprintf("Chain %s", chain)) {
108 chainSet[chain] = true
109 }
110 }
111 }
112
113 var chains []string
114 for chain, ok := range chainSet {
115 if ok {
116 chains = append(chains, chain)
117 }
118 }
119
120 if len(chains) == 0 {
121 printStep("all iptables rules are cleaned up")
122 return nil
123 }
124 printStep(fmt.Sprintf("cleaning iptables rules for chains %v", chains))
125
126 cleanedChains, err := r.client.CleanIptables(ctx, pod.Namespace, pod.Name, chains)
127 if err != nil {
128 return err
129 }
130
131 if len(cleanedChains) != 0 {
132 printStep(fmt.Sprintf("iptables rules in chains %s are cleaned up", strings.Join(cleanedChains, ",")))
133 }
134
135 return nil
136 }
137
138 type networkRecoverer struct {
139 tcsRecoverer Recoverer
140 iptablesRecoverer Recoverer
141 }
142
143 func NetworkRecoverer(client *ctrlclient.CtrlClient) Recoverer {
144 return &networkRecoverer{
145 tcsRecoverer: newTcsRecoverer(client),
146 iptablesRecoverer: newIptablesRecoverer(client),
147 }
148 }
149
150 func (r *networkRecoverer) Recover(ctx context.Context, pod *PartialPod) error {
151 err := r.tcsRecoverer.Recover(ctx, pod)
152 if err != nil {
153 return errors.Wrap(err, "recover tcs rules")
154 }
155 err = r.iptablesRecoverer.Recover(ctx, pod)
156 if err != nil {
157 return errors.Wrap(err, "recover iptables rules")
158 }
159 return nil
160 }
161