Skip to content

Commit d5a3220

Browse files
committed
IPAM config through cni network config
Signed-off-by: Abhinandan Prativadi <abhi@docker.com>
1 parent cb395b0 commit d5a3220

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)