Skip to content

Commit 5fa7fd9

Browse files
committed
IPAM config through cni network config
This commit introduces configurable IPAM setting for cni configs. This would allow used to configure the network level ipam configs in the cni config Signed-off-by: Abhinandan Prativadi <abhi@docker.com>
1 parent 312cda7 commit 5fa7fd9

13 files changed

Lines changed: 412 additions & 378 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ build-local:
3636
@mkdir -p "bin"
3737
go build -tags experimental -o "bin/dnet" ./cmd/dnet
3838
go build -o "bin/docker-proxy" ./cmd/proxy
39-
go build -o "bin/cniserver" ./pkg/server
39+
go build -o "bin/cniserver" ./cmd/cni_
4040
go build -o "bin/cnictl" ./cni/
4141
clean:
4242
@echo "🐳 $@"

cmd/cni_/cni_.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package main
2+
3+
import (
4+
"io"
5+
"os"
6+
7+
"github.com/codegangsta/cli"
8+
"github.com/docker/docker/pkg/reexec"
9+
"github.com/docker/docker/pkg/term"
10+
"github.com/sirupsen/logrus"
11+
)
12+
13+
func main() {
14+
if reexec.Init() {
15+
return
16+
}
17+
_, stdout, stderr := term.StdStreams()
18+
logrus.SetOutput(stderr)
19+
err := cniApp(stdout, stderr)
20+
if err != nil {
21+
os.Exit(1)
22+
}
23+
}
24+
25+
func cniApp(stdout, stderr io.Writer) error {
26+
app := cli.NewApp()
27+
28+
app.Name = "cniserver"
29+
app.Usage = "A cni side car for libnetwork daemon."
30+
app.Flags = cniserverFlags
31+
app.Before = processFlags
32+
//app.Commands = cniCommands
33+
34+
app.Run(os.Args)
35+
return nil
36+
}

cmd/cni_/flags_.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/codegangsta/cli"
8+
cniserver "github.com/docker/libnetwork/pkg/server/cniserver"
9+
"github.com/sirupsen/logrus"
10+
)
11+
12+
var (
13+
cniserverFlags = []cli.Flag{
14+
cli.StringFlag{
15+
Name: "sock",
16+
Value: "/var/run/cniserver.sock",
17+
Usage: "path to the socket file on which cniserver listens. Default (/var/run/cni-libnetwork.sock)",
18+
},
19+
cli.StringFlag{
20+
Name: "dnet-port",
21+
Value: "2389",
22+
Usage: "Daemon socket to connect to. Default(2389)",
23+
},
24+
cli.StringFlag{
25+
Name: "dnet-address",
26+
Value: "127.0.0.1",
27+
Usage: "Daemon IP address to connect to",
28+
},
29+
cli.BoolFlag{
30+
Name: "D, -debug",
31+
Usage: "Enable debug mode",
32+
},
33+
}
34+
)
35+
36+
func processFlags(c *cli.Context) error {
37+
var err error
38+
39+
if c.Bool("D") {
40+
logrus.SetLevel(logrus.DebugLevel)
41+
}
42+
43+
cniService, err := cniserver.NewCniService(c.String("sock"), c.String("dnet-address"), c.String("dnet-port"))
44+
if err != nil {
45+
return fmt.Errorf("faile to create cni service: %v", err)
46+
}
47+
serverCloseChan := make(chan struct{})
48+
if err := cniService.InitCniService(serverCloseChan); err != nil {
49+
fmt.Printf("Failed to initialize CNI server: \n", err)
50+
os.Exit(1)
51+
}
52+
<-serverCloseChan
53+
return nil
54+
}

cmd/dnet/cmd.go

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ package main
33
import (
44
"encoding/json"
55
"fmt"
6-
"io"
7-
"io/ioutil"
8-
"net/http"
96
"os"
107

118
"github.com/codegangsta/cli"
129
"github.com/docker/docker/pkg/term"
1310
"github.com/docker/libnetwork/client"
11+
"github.com/docker/libnetwork/netutils"
1412
)
1513

1614
var (
@@ -49,7 +47,7 @@ func runContainerCreate(c *cli.Context) {
4947
}
5048

5149
sc := client.SandboxCreate{ContainerID: c.Args()[0]}
52-
obj, _, err := readBody(epConn.httpCall("POST", "/sandboxes", sc, nil))
50+
obj, _, err := netutils.ReadBody(epConn.conn.HttpCall("POST", "/sandboxes", sc, nil))
5351
if err != nil {
5452
fmt.Printf("POST failed during create container: %v\n", err)
5553
os.Exit(1)
@@ -74,7 +72,7 @@ func runContainerRm(c *cli.Context) {
7472
os.Exit(1)
7573
}
7674

77-
obj, _, err := readBody(epConn.httpCall("GET", "/sandboxes?partial-container-id="+c.Args()[0], nil, nil))
75+
obj, _, err := netutils.ReadBody(epConn.conn.HttpCall("GET", "/sandboxes?partial-container-id="+c.Args()[0], nil, nil))
7876
if err != nil {
7977
fmt.Printf("GET failed during container id lookup: %v\n", err)
8078
os.Exit(1)
@@ -91,7 +89,7 @@ func runContainerRm(c *cli.Context) {
9189
os.Exit(1)
9290
}
9391

94-
_, _, err = readBody(epConn.httpCall("DELETE", "/sandboxes/"+sbList[0].ID, nil, nil))
92+
_, _, err = netutils.ReadBody(epConn.conn.HttpCall("DELETE", "/sandboxes/"+sbList[0].ID, nil, nil))
9593
if err != nil {
9694
fmt.Printf("DELETE of sandbox id %s failed: %v", sbList[0].ID, err)
9795
os.Exit(1)
@@ -100,7 +98,7 @@ func runContainerRm(c *cli.Context) {
10098

10199
func runDockerCommand(c *cli.Context, cmd string) {
102100
_, stdout, stderr := term.StdStreams()
103-
oldcli := client.NewNetworkCli(stdout, stderr, epConn.httpCall)
101+
oldcli := client.NewNetworkCli(stdout, stderr, epConn.conn.HttpCall)
104102
var args []string
105103
args = append(args, cmd)
106104
if c.Bool("h") {
@@ -130,17 +128,3 @@ func createDockerCommand(cmd string) cli.Command {
130128
},
131129
}
132130
}
133-
134-
func readBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) {
135-
if stream != nil {
136-
defer stream.Close()
137-
}
138-
if err != nil {
139-
return nil, statusCode, err
140-
}
141-
body, err := ioutil.ReadAll(stream)
142-
if err != nil {
143-
return nil, -1, err
144-
}
145-
return body, statusCode, nil
146-
}

cmd/dnet/dnet.go

Lines changed: 29 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package main
22

33
import (
4-
"bytes"
5-
"encoding/json"
64
"errors"
75
"fmt"
86
"io"
@@ -96,10 +94,10 @@ func (d *dnetConnection) parseConfig(cfgFile string) (*config.Config, error) {
9694
return config.ParseConfig(cfgFile)
9795
}
9896

99-
func processConfig(cfg *config.Config) []config.Option {
97+
func processConfig(cfg *config.Config) ([]config.Option, error) {
10098
options := []config.Option{}
10199
if cfg == nil {
102-
return options
100+
return options, nil
103101
}
104102

105103
dn := "bridge"
@@ -131,14 +129,19 @@ func processConfig(cfg *config.Config) []config.Option {
131129
options = append(options, config.OptionDataDir(cfg.Daemon.DataDir))
132130
}
133131

134-
dOptions, err := startDiscovery(&cfg.Cluster)
135-
if err != nil {
136-
logrus.Infof("Skipping discovery : %s", err.Error())
137-
} else {
138-
options = append(options, dOptions...)
132+
// Retry discovery for 2 minutes before exiting
133+
for {
134+
select {
135+
case <-time.After(2 * time.Minute):
136+
return nil, fmt.Errorf("failed to initialize discovery")
137+
default:
138+
dOptions, err := startDiscovery(&cfg.Cluster)
139+
if err == nil {
140+
options = append(options, dOptions...)
141+
return options, nil
142+
}
143+
}
139144
}
140-
141-
return options
142145
}
143146

144147
func startDiscovery(cfg *config.ClusterCfg) ([]config.Option, error) {
@@ -238,10 +241,7 @@ func createDefaultNetwork(c libnetwork.NetworkController) {
238241
}
239242

240243
type dnetConnection struct {
241-
// proto holds the client protocol i.e. unix.
242-
proto string
243-
// addr holds the client address.
244-
addr string
244+
conn *netutils.HttpConnection
245245
Orchestration *NetworkOrchestration
246246
configEvent chan cluster.ConfigEventType
247247
}
@@ -262,9 +262,12 @@ func (d *dnetConnection) dnetDaemon(cfgFile string) error {
262262
cfg, err := d.parseConfig(cfgFile)
263263
var cOptions []config.Option
264264
if err == nil {
265-
cOptions = processConfig(cfg)
265+
cOptions, err = processConfig(cfg)
266+
if err != nil {
267+
fmt.Errorf("failed to process config: %v", err)
268+
}
266269
} else {
267-
logrus.Errorf("Error parsing config %v", err)
270+
logrus.Errorf("failed to parse config: %v", err)
268271
}
269272

270273
bridgeConfig := options.Generic{
@@ -306,7 +309,7 @@ func (d *dnetConnection) dnetDaemon(cfgFile string) error {
306309
handleSignals(controller)
307310
setupDumpStackTrap()
308311

309-
return http.ListenAndServe(d.addr, r)
312+
return http.ListenAndServe(d.conn.Addr, r)
310313
}
311314

312315
func (d *dnetConnection) IsManager() bool {
@@ -436,76 +439,14 @@ func newDnetConnection(val string) (*dnetConnection, error) {
436439
return nil, errors.New("dnet currently only supports tcp transport")
437440
}
438441

439-
return &dnetConnection{protoAddrParts[0], protoAddrParts[1], &NetworkOrchestration{}, make(chan cluster.ConfigEventType, 10)}, nil
440-
}
441-
442-
func (d *dnetConnection) httpCall(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) {
443-
var in io.Reader
444-
in, err := encodeData(data)
445-
if err != nil {
446-
return nil, nil, -1, err
447-
}
448-
449-
req, err := http.NewRequest(method, fmt.Sprintf("%s", path), in)
450-
if err != nil {
451-
return nil, nil, -1, err
452-
}
453-
454-
setupRequestHeaders(method, data, req, headers)
455-
456-
req.URL.Host = d.addr
457-
req.URL.Scheme = "http"
458-
fmt.Printf("Requesting http: %+v", req)
459-
httpClient := &http.Client{}
460-
resp, err := httpClient.Do(req)
461-
statusCode := -1
462-
if resp != nil {
463-
statusCode = resp.StatusCode
464-
}
465-
if err != nil {
466-
return nil, nil, statusCode, fmt.Errorf("error when trying to connect: %v", err)
467-
}
468-
469-
if statusCode < 200 || statusCode >= 400 {
470-
body, err := ioutil.ReadAll(resp.Body)
471-
if err != nil {
472-
return nil, nil, statusCode, err
473-
}
474-
return nil, nil, statusCode, fmt.Errorf("error : %s", bytes.TrimSpace(body))
475-
}
476-
477-
return resp.Body, resp.Header, statusCode, nil
478-
}
479-
480-
func setupRequestHeaders(method string, data interface{}, req *http.Request, headers map[string][]string) {
481-
if data != nil {
482-
if headers == nil {
483-
headers = make(map[string][]string)
484-
}
485-
headers["Content-Type"] = []string{"application/json"}
486-
}
487-
488-
expectedPayload := (method == "POST" || method == "PUT")
489-
490-
if expectedPayload && req.Header.Get("Content-Type") == "" {
491-
req.Header.Set("Content-Type", "text/plain")
492-
}
493-
494-
if headers != nil {
495-
for k, v := range headers {
496-
req.Header[k] = v
497-
}
498-
}
499-
}
500-
501-
func encodeData(data interface{}) (*bytes.Buffer, error) {
502-
params := bytes.NewBuffer(nil)
503-
if data != nil {
504-
if err := json.NewEncoder(params).Encode(data); err != nil {
505-
return nil, err
506-
}
507-
}
508-
return params, nil
442+
return &dnetConnection{
443+
&netutils.HttpConnection{
444+
Proto: protoAddrParts[0],
445+
Addr: protoAddrParts[1],
446+
},
447+
&NetworkOrchestration{},
448+
make(chan cluster.ConfigEventType, 10),
449+
}, nil
509450
}
510451

511452
func ipamOption(bridgeName string) libnetwork.NetworkOption {

cni/main.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,23 @@ import (
1111
)
1212

1313
func cmdAdd(args *skel.CmdArgs) error {
14-
libClient := cniapi.NewLibNetCniClient()
15-
result, err := libClient.SetupPod(args)
14+
c := cniapi.NewDnetCniClient()
15+
result, err := c.SetupPod(args)
1616
if err != nil {
17-
return fmt.Errorf("Failed to setup Pod , %v", err)
17+
return fmt.Errorf("failed to setup Pod: %v", err)
1818
}
1919
return types.PrintResult(result, version.Current())
2020
}
2121

2222
func cmdDel(args *skel.CmdArgs) error {
23-
libClient := cniapi.NewLibNetCniClient()
24-
if err := libClient.TearDownPod(args); err != nil {
25-
return fmt.Errorf("Failed to tear down pod, %v", err)
23+
c := cniapi.NewDnetCniClient()
24+
if err := c.TearDownPod(args); err != nil {
25+
return fmt.Errorf("failed to tear down pod: %v", err)
2626
}
2727
return nil
2828
}
2929

3030
func main() {
31-
log.Infof("Starting Libnetwork CNI plugin")
31+
log.Infof("Dnet CNI plugin")
3232
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("", "0.1.0", "0.2.0", version.Current()))
3333
}

0 commit comments

Comments
 (0)