Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit c98129e

Browse files
committed
rules fix for pod level portmapping
1. fix the iptables rules 2. improve the rollback mechanisms 3. don't merge continuous port mapping rules in spec 4. fix the API server Signed-off-by: Wang Xu <[email protected]>
1 parent c0737de commit c98129e

File tree

5 files changed

+62
-37
lines changed

5 files changed

+62
-37
lines changed

Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ if ON_DARWIN
2626
SUBDIRS=mac_installer
2727
endif
2828

29-
VERSION_PARAM=-ldflags "-X github.com/hyperhq/hyperd/utils.VERSION=$(VERSION) -X github.com/hyperhq/hyperd/utils.GITCOMMIT=`git describe`"
29+
VERSION_PARAM=-ldflags "-X github.com/hyperhq/hyperd/utils.VERSION=$(VERSION) -X github.com/hyperhq/hyperd/utils.GITCOMMIT=`git describe --dirty --always --tags 2> /dev/null || true`"
3030

3131
all-local: build-hyperd build-hyperctl build-vmlogd
3232
clean-local:

networking/portmapping/host_portmapping_linux.go

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ func generateIptablesArgs(containerip string, m *PortMapping) ([]string, []strin
7878
proto string
7979
from string
8080
to string
81+
dport string
8182
)
8283

8384
if strings.EqualFold(m.Protocol, "udp") {
@@ -90,16 +91,18 @@ func generateIptablesArgs(containerip string, m *PortMapping) ([]string, []strin
9091
from = strconv.Itoa(m.FromPorts.Begin)
9192
m.FromPorts.End = m.FromPorts.Begin
9293
} else if m.FromPorts.End > m.FromPorts.Begin {
93-
from = fmt.Sprintf("%d:%d", m.FromPorts, m.FromPorts.End)
94+
from = fmt.Sprintf("%d:%d", m.FromPorts.Begin, m.FromPorts.End)
9495
} else {
9596
return []string{}, []string{}, fmt.Errorf("invalid from port range %d-%d", m.FromPorts.Begin, m.FromPorts.End)
9697
}
9798

9899
if m.ToPorts.End == 0 || m.ToPorts.End == m.ToPorts.Begin {
99-
to = net.JoinHostPort(containerip, strconv.Itoa(m.ToPorts.Begin))
100+
dport = strconv.Itoa(m.ToPorts.Begin)
101+
to = net.JoinHostPort(containerip, dport)
100102
m.ToPorts.End = m.ToPorts.Begin
101103
} else if m.ToPorts.End > m.ToPorts.Begin {
102-
to = net.JoinHostPort(containerip, fmt.Sprintf("%d-%d", m.ToPorts, m.ToPorts.End))
104+
dport = fmt.Sprintf("%d:%d", m.ToPorts.Begin, m.ToPorts.End)
105+
to = net.JoinHostPort(containerip, fmt.Sprintf("%d-%d", m.ToPorts.Begin, m.ToPorts.End))
103106
} else {
104107
return []string{}, []string{}, fmt.Errorf("invalid to port range %d-%d", m.ToPorts.Begin, m.ToPorts.End)
105108
}
@@ -112,42 +115,74 @@ func generateIptablesArgs(containerip string, m *PortMapping) ([]string, []strin
112115
}
113116

114117
natArgs := []string{"-p", proto, "-m", proto, "--dport", from, "-j", "DNAT", "--to-destination", to}
115-
filterArgs := []string{"-d", containerip, "-p", proto, "-m", proto, "--dport", to, "-j", "ACCEPT"}
118+
filterArgs := []string{"-d", containerip, "-p", proto, "-m", proto, "--dport", dport, "-j", "ACCEPT"}
116119

117120
return natArgs, filterArgs, nil
118121
}
119122

123+
func parseRawResultOnHyper(output []byte, err error) error {
124+
if err != nil {
125+
return err
126+
} else if len(output) != 0 {
127+
return &iptables.ChainError{Chain: "HYPER", Output: output}
128+
129+
}
130+
return nil
131+
}
132+
120133
func SetupPortMaps(containerip string, maps []*PortMapping) error {
121134
if disableIptables || len(maps) == 0 {
122135
return nil
123136
}
124137

138+
var (
139+
revert bool
140+
revertRules = [][]string{}
141+
)
142+
defer func() {
143+
if revert {
144+
hlog.Log(hlog.WARNING, "revert portmapping rules...")
145+
for _, r := range revertRules {
146+
hlog.Log(hlog.INFO, "revert rule: %v", r)
147+
err := parseRawResultOnHyper(iptables.Raw(r...))
148+
if err != nil {
149+
hlog.Log(hlog.ERROR, "failed to revert rule: %v", err)
150+
err = nil //just ignore
151+
}
152+
}
153+
}
154+
}()
155+
125156
for _, m := range maps {
126157

127158
natArgs, filterArgs, err := generateIptablesArgs(containerip, m)
128159
if err != nil {
160+
revert = true
129161
return err
130162
}
131163

132164
//check if this rule has already existed
133165
if iptables.PortMapExists("HYPER", natArgs) {
134-
return nil
166+
continue
135167
}
136168

137169
if iptables.PortMapUsed("HYPER", m.Protocol, m.FromPorts.Begin, m.FromPorts.End) {
170+
revert = true
138171
return fmt.Errorf("Host port %v has aleady been used", m.FromPorts)
139172
}
140173

141-
err = iptables.OperatePortMap(iptables.Insert, "HYPER", natArgs)
174+
err = parseRawResultOnHyper(iptables.Raw(append([]string{"-t", "nat", "-I", "HYPER"}, natArgs...)...))
142175
if err != nil {
143-
return err
176+
revert = true
177+
return fmt.Errorf("Unable to setup NAT rule in HYPER chain: %s", err)
144178
}
179+
revertRules = append(revertRules, append([]string{"-t", "nat", "-D", "HYPER"}, natArgs...))
145180

146-
if output, err := iptables.Raw(append([]string{"-I", "HYPER"}, filterArgs...)...); err != nil {
147-
return fmt.Errorf("Unable to setup forward rule in HYPER chain: %s", err)
148-
} else if len(output) != 0 {
149-
return &iptables.ChainError{Chain: "HYPER", Output: output}
181+
if err = parseRawResultOnHyper(iptables.Raw(append([]string{"-I", "HYPER"}, filterArgs...)...)); err != nil {
182+
revert = true
183+
return fmt.Errorf("Unable to setup FILTER rule in HYPER chain: %s", err)
150184
}
185+
revertRules = append(revertRules, append([]string{"-D", "HYPER"}, filterArgs...))
151186

152187
i := m.FromPorts.Begin
153188
j := m.ToPorts.Begin
@@ -163,6 +198,7 @@ func SetupPortMaps(containerip string, maps []*PortMapping) error {
163198

164199
for i <= m.FromPorts.End {
165200
if err = PortMapper.AllocateMap(m.Protocol, i, containerip, j); err != nil {
201+
revert = true
166202
return err
167203
}
168204
i++
@@ -178,6 +214,7 @@ func ReleasePortMaps(containerip string, maps []*PortMapping) error {
178214
return nil
179215
}
180216

217+
release_loop:
181218
for _, m := range maps {
182219
if !strings.EqualFold(m.Protocol, "udp") {
183220
m.Protocol = "tcp"
@@ -191,7 +228,7 @@ func ReleasePortMaps(containerip string, maps []*PortMapping) error {
191228
for i := m.FromPorts.Begin; i <= m.FromPorts.End; i++ {
192229
err := PortMapper.ReleaseMap(m.Protocol, i)
193230
if err != nil {
194-
continue
231+
continue release_loop
195232
}
196233
}
197234

server/router/pod/pod.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func NewRouter(b Backend) router.Router {
3232
local.NewPostRoute("/pod/pause", r.postPodPause),
3333
local.NewPostRoute("/pod/unpause", r.postPodUnpause),
3434
// PUT
35-
local.NewPostRoute("/pod/{id}/portmappings/{action}", r.putPortMappings),
35+
local.NewPutRoute("/pod/{id}/portmappings/{action}", r.putPortMappings),
3636
// DELETE
3737
local.NewDeleteRoute("/pod", r.deletePod),
3838
}

types/spec_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ func TestMergePorts(t *testing.T) {
217217

218218
t.Log("> testing empty port mapping list")
219219
pms = []*_PortMapping{}
220-
res, err = mergePorts(pms)
220+
res, err = mergeContinuousPorts(pms)
221221
if err != nil {
222222
t.Fatalf("failed with emport pm list: %v", err)
223223
}
@@ -241,7 +241,7 @@ func TestMergePorts(t *testing.T) {
241241
},
242242
}
243243
t.Logf("---[debug] input items %v", pms)
244-
res, err = mergePorts(pms)
244+
res, err = mergeContinuousPorts(pms)
245245
if err != nil {
246246
t.Fatalf("error with normal pm list: %v", err)
247247
}
@@ -266,7 +266,7 @@ func TestMergePorts(t *testing.T) {
266266
},
267267
}
268268
t.Logf("---[debug] input items %v", pms)
269-
res, err = mergePorts(pms)
269+
res, err = mergeContinuousPorts(pms)
270270
if err != nil {
271271
t.Fatalf("error with normal pm list: %v", err)
272272
}
@@ -290,7 +290,7 @@ func TestMergePorts(t *testing.T) {
290290
},
291291
}
292292
t.Logf("---[debug] input items %v", pms)
293-
res, err = mergePorts(pms)
293+
res, err = mergeContinuousPorts(pms)
294294
if err != nil {
295295
t.Fatalf("error with normal pm list: %v", err)
296296
}
@@ -315,7 +315,7 @@ func TestMergePorts(t *testing.T) {
315315
},
316316
}
317317
t.Logf("---[debug] input items %v", pms)
318-
res, err = mergePorts(pms)
318+
res, err = mergeContinuousPorts(pms)
319319
if err == nil {
320320
t.Fatalf("failed with overlapped pm list: %v", res)
321321
}
@@ -336,7 +336,7 @@ func TestMergePorts(t *testing.T) {
336336
},
337337
}
338338
t.Logf("---[debug] input items %v", pms)
339-
res, err = mergePorts(pms)
339+
res, err = mergeContinuousPorts(pms)
340340
if err == nil {
341341
t.Fatalf("failed with overlapped pm list: %v", res)
342342
}
@@ -357,7 +357,7 @@ func TestMergePorts(t *testing.T) {
357357
},
358358
}
359359
t.Logf("---[debug] input items %v", pms)
360-
res, err = mergePorts(pms)
360+
res, err = mergeContinuousPorts(pms)
361361
if err == nil {
362362
t.Fatalf("failed with overlapped pm list: %v", res)
363363
}
@@ -379,7 +379,7 @@ func TestMergePorts(t *testing.T) {
379379
},
380380
}
381381
t.Logf("---[debug] input items %v", pms)
382-
res, err = mergePorts(pms)
382+
res, err = mergeContinuousPorts(pms)
383383
if err != nil {
384384
t.Fatalf("error with random pm list: %v", err)
385385
}
@@ -403,7 +403,7 @@ func TestMergePorts(t *testing.T) {
403403
},
404404
}
405405
t.Logf("---[debug] input items %v", pms)
406-
res, err = mergePorts(pms)
406+
res, err = mergeContinuousPorts(pms)
407407
if err == nil {
408408
t.Fatalf("didn't found collision in random pm list: %v", res)
409409
}
@@ -428,7 +428,7 @@ func TestMergePorts(t *testing.T) {
428428
},
429429
}
430430
t.Logf("---[debug] input items %v", pms)
431-
res, err = mergePorts(pms)
431+
res, err = mergeContinuousPorts(pms)
432432
if err != nil {
433433
t.Logf("got an error with random pm list: %v", err)
434434
t.Log("it's acceptable to fail in this case")

types/utils.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ func (pm *_PortMapping) notDetermined() bool {
250250
return !pm.container.isRange() && pm.host.isRange()
251251
}
252252

253-
func mergePorts(pms []*_PortMapping) ([]*_PortMapping, error) {
253+
func mergeContinuousPorts(pms []*_PortMapping) ([]*_PortMapping, error) {
254254
var (
255255
results = []*_PortMapping{}
256256
occupy = map[int]bool{}
@@ -364,18 +364,6 @@ func (p *UserPod) MergePortmappings() error {
364364
}
365365
}
366366

367-
hlog.Log(hlog.TRACE, "TCP ports to be merged: %v", tcpPorts)
368-
tcpPorts, err = mergePorts(tcpPorts)
369-
if err != nil {
370-
return err
371-
}
372-
373-
hlog.Log(hlog.TRACE, "UDP ports to be merged: %v", udpPorts)
374-
udpPorts, err = mergePorts(udpPorts)
375-
if err != nil {
376-
return err
377-
}
378-
379367
pms := []*PortMapping{}
380368
for _, pm := range tcpPorts {
381369
pms = append(pms, pm.toSpec())

0 commit comments

Comments
 (0)