diff --git a/Makefile b/Makefile index 7e8af3773d..6c668f85f3 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,8 @@ build-local: @mkdir -p "bin" go build -tags experimental -o "bin/dnet" ./cmd/dnet go build -o "bin/docker-proxy" ./cmd/proxy - + go build -o "bin/cniserver" ./cmd/cni_server + go build -o "bin/cnictl" ./cmd/dnet_cni/ clean: @echo "🐳 $@" @if [ -d bin ]; then \ diff --git a/api/api.go b/api/api.go index 8befe63d23..d4c2467dd5 100644 --- a/api/api.go +++ b/api/api.go @@ -646,12 +646,17 @@ func procPublishService(c libnetwork.NetworkController, vars map[string]string, setFctList = append(setFctList, libnetwork.CreateOptionMyAlias(str)) } + if sp.DisableResolution { + setFctList = append(setFctList, libnetwork.CreateOptionDisableResolution()) + } + ep, err := n.CreateEndpoint(sp.Name, setFctList...) if err != nil { return "", endpointToService(convertNetworkError(err)) } + epResp := getEndpointInfo(ep) - return ep.ID(), &createdResponse + return epResp, &createdResponse } func procUnpublishService(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) { @@ -708,6 +713,13 @@ func procAttachBackend(c libnetwork.NetworkController, vars map[string]string, b return nil, convertNetworkError(err) } + if bk.SandboxKey != "" { + err = sb.SetKey(bk.SandboxKey) + if err != nil { + return nil, convertNetworkError(err) + } + } + return sb.Key(), &successResponse } @@ -727,7 +739,6 @@ func procDetachBackend(c libnetwork.NetworkController, vars map[string]string, b if err != nil { return nil, convertNetworkError(err) } - return nil, &successResponse } diff --git a/api/api_test.go b/api/api_test.go index bb86f4d9c3..8280d4006b 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -821,11 +821,15 @@ func TestProcPublishUnpublishService(t *testing.T) { if err != nil { t.Fatal(err) } - si, errRsp := procPublishService(c, vars, b) + sv, errRsp := procPublishService(c, vars, b) if errRsp != &createdResponse { t.Fatalf("Unexpected failure: %v", errRsp) } - sid := i2s(si) + ep, ok := sv.(endpointInfo) + if !ok { + panic(fmt.Sprintf("Failed for %v", sv)) + } + sid := ep.ID vars[urlEpID] = "" _, errRsp = procUnpublishService(c, vars, nil) diff --git a/api/types.go b/api/types.go index 640891b2c4..03202b773a 100644 --- a/api/types.go +++ b/api/types.go @@ -1,6 +1,11 @@ package api -import "github.com/docker/libnetwork/types" +import ( + "net" + + "github.com/docker/libnetwork" + "github.com/docker/libnetwork/types" +) /*********** Resources @@ -72,15 +77,17 @@ type sandboxCreate struct { // endpointJoin represents the expected body of the "join endpoint" or "leave endpoint" http request messages type endpointJoin struct { - SandboxID string `json:"sandbox_id"` - Aliases []string `json:"aliases"` + SandboxID string `json:"sandbox_id"` + Aliases []string `json:"aliases"` + SandboxKey string `json:"sandbox_key"` } // servicePublish represents the body of the "publish service" http request message type servicePublish struct { - Name string `json:"name"` - MyAliases []string `json:"my_aliases"` - Network string `json:"network_name"` + Name string `json:"name"` + MyAliases []string `json:"my_aliases"` + Network string `json:"network_name"` + DisableResolution bool `json:"disable_resolution"` } // serviceDelete represents the body of the "unpublish service" http request message @@ -89,8 +96,55 @@ type serviceDelete struct { Force bool `json:"force"` } +// endpointInfo represents the endpoint info for https response message on endpoint creation +type endpointInfo struct { + ID string `json:"id"` + Address net.IPNet `json:"address"` + AddressIPv6 net.IPNet `json:"address_ipv6"` + MacAddress net.HardwareAddr `json:"mac_address"` + Gateway net.IP `json:"gateway"` + GatewayIPv6 net.IP `json:"gateway_ipv6"` +} + // extraHost represents the extra host object type extraHost struct { Name string `json:"name"` Address string `json:"address"` } + +// SandboxMetadata holds the metadata related to sandox (config) +type SandboxMetadata struct { + ContainerID string `json:"container_id"` + HostName string `json:"host_name"` + DomainName string `json:"domain_name"` + HostsPath string `json:"hosts_path"` + ResolvConfPath string `json:"resolv_conf_path"` + DNS []string `json:"dns"` + ExtraHosts []extraHost `json:"extra_hosts"` + UseExternalKey bool `json:"use_external_key"` + UseDefaultSandbox bool `json:"use_default_sandbox"` + ExposedPorts []types.TransportPort `json:"exposed_ports"` + PortMapping []types.PortBinding `json:"port_mapping"` + ExternalKey string `json:"external_key"` +} + +func getEndpointInfo(ep libnetwork.Endpoint) endpointInfo { + epInfo := endpointInfo{ID: ep.ID()} + + if ipv4 := ep.Info().Iface().Address(); ipv4 != nil { + epInfo.Address = *ipv4 + } + if ipv6 := ep.Info().Iface().AddressIPv6(); ipv6 != nil { + epInfo.AddressIPv6 = *ipv6 + } + if mac := ep.Info().Iface().MacAddress(); mac != nil { + epInfo.MacAddress = mac + } + if gw := ep.Info().Gateway(); gw != nil { + epInfo.Gateway = gw + } + if gw6 := ep.Info().GatewayIPv6(); gw6 != nil { + epInfo.GatewayIPv6 = gw6 + } + return epInfo +} diff --git a/client/client_test.go b/client/client_test.go index ab15a3eef3..7d163f7147 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -35,8 +35,8 @@ var mockContainerID = "2a3456789" var mockSandboxID = "2b3456789" func setupMockHTTPCallback() { - var list []networkResource - nw := networkResource{Name: mockNwName, ID: mockNwID} + var list []NetworkResource + nw := NetworkResource{Name: mockNwName, ID: mockNwID} mockNwJSON, _ = json.Marshal(nw) list = append(list, nw) mockNwListJSON, _ = json.Marshal(list) diff --git a/client/network.go b/client/network.go index f080f62fe7..27ea1bd52c 100644 --- a/client/network.go +++ b/client/network.go @@ -71,9 +71,9 @@ func (cli *NetworkCli) CmdNetworkCreate(chain string, args ...string) error { } } - var icList []ipamConf + var icList []IPAMConf if *flSubnet != "" { - ic := ipamConf{ + ic := IPAMConf{ PreferredPool: *flSubnet, } @@ -85,7 +85,7 @@ func (cli *NetworkCli) CmdNetworkCreate(chain string, args ...string) error { } // Construct network create request body - nc := networkCreate{Name: cmd.Arg(0), NetworkType: *flDriver, ID: *flID, IPv4Conf: icList, DriverOpts: driverOpts, NetworkOpts: networkOpts} + nc := NetworkCreate{Name: cmd.Arg(0), NetworkType: *flDriver, ID: *flID, IPv4Conf: icList, DriverOpts: driverOpts, NetworkOpts: networkOpts} obj, _, err := readBody(cli.call("POST", "/networks", nc, nil)) if err != nil { return err @@ -137,7 +137,7 @@ func (cli *NetworkCli) CmdNetworkLs(chain string, args ...string) error { *last = 1 } - var networkResources []networkResource + var networkResources []NetworkResource err = json.Unmarshal(obj, &networkResources) if err != nil { return err @@ -189,7 +189,7 @@ func (cli *NetworkCli) CmdNetworkInfo(chain string, args ...string) error { if err != nil { return err } - networkResource := &networkResource{} + networkResource := &NetworkResource{} if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil { return err } @@ -222,7 +222,7 @@ func lookupNetworkID(cli *NetworkCli, nameID string) (string, error) { return "", fmt.Errorf("name query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj)) } - var list []*networkResource + var list []*NetworkResource err = json.Unmarshal(obj, &list) if err != nil { return "", err diff --git a/client/service.go b/client/service.go index 532afcff3b..9020c28acc 100644 --- a/client/service.go +++ b/client/service.go @@ -32,7 +32,7 @@ func lookupServiceID(cli *NetworkCli, nwName, svNameID string) (string, error) { if err != nil { return "", err } - var nwList []networkResource + var nwList []NetworkResource if err = json.Unmarshal(obj, &nwList); err != nil { return "", err } @@ -45,7 +45,7 @@ func lookupServiceID(cli *NetworkCli, nwName, svNameID string) (string, error) { if err != nil { return "", err } - networkResource := &networkResource{} + networkResource := &NetworkResource{} if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil { return "", err } @@ -173,19 +173,19 @@ func (cli *NetworkCli) CmdServicePublish(chain string, args ...string) error { } sn, nn := parseServiceName(cmd.Arg(0)) - sc := serviceCreate{Name: sn, Network: nn, MyAliases: flAlias.GetAll()} + sc := ServiceCreate{Name: sn, Network: nn, MyAliases: flAlias.GetAll()} obj, _, err := readBody(cli.call("POST", "/services", sc, nil)) if err != nil { return err } - var replyID string - err = json.Unmarshal(obj, &replyID) + var ep EndpointInfo + err = json.Unmarshal(obj, &ep) if err != nil { return err } - fmt.Fprintf(cli.out, "%s\n", replyID) + fmt.Fprintf(cli.out, "%s\n", ep.ID) return nil } @@ -205,7 +205,7 @@ func (cli *NetworkCli) CmdServiceUnpublish(chain string, args ...string) error { return err } - sd := serviceDelete{Name: sn, Force: *force} + sd := ServiceDelete{Name: sn, Force: *force} _, _, err = readBody(cli.call("DELETE", "/services/"+serviceID, sd, nil)) return err @@ -350,7 +350,7 @@ func (cli *NetworkCli) CmdServiceAttach(chain string, args ...string) error { return err } - nc := serviceAttach{SandboxID: sandboxID, Aliases: flAlias.GetAll()} + nc := ServiceAttach{SandboxID: sandboxID, Aliases: flAlias.GetAll()} _, _, err = readBody(cli.call("POST", "/services/"+serviceID+"/backend", nc, nil)) diff --git a/client/types.go b/client/types.go index c7b2c550a5..1b5c238b67 100644 --- a/client/types.go +++ b/client/types.go @@ -1,13 +1,17 @@ package client -import "github.com/docker/libnetwork/types" +import ( + "net" + + "github.com/docker/libnetwork/types" +) /*********** Resources ************/ -// networkResource is the body of the "get network" http response message -type networkResource struct { +// NetworkResource is the body of the "get network" http response message +type NetworkResource struct { Name string `json:"name"` ID string `json:"id"` Type string `json:"type"` @@ -31,40 +35,44 @@ type SandboxResource struct { /*********** Body types ************/ -type ipamConf struct { + +// IPAMConf is the ipam configution used during network create +type IPAMConf struct { PreferredPool string SubPool string Gateway string AuxAddresses map[string]string } -// networkCreate is the expected body of the "create network" http request message -type networkCreate struct { +// NetworkCreate is the expected body of the "create network" http request message +type NetworkCreate struct { Name string `json:"name"` ID string `json:"id"` NetworkType string `json:"network_type"` - IPv4Conf []ipamConf `json:"ipv4_configuration"` + IPv4Conf []IPAMConf `json:"ipv4_configuration"` DriverOpts map[string]string `json:"driver_opts"` NetworkOpts map[string]string `json:"network_opts"` } -// serviceCreate represents the body of the "publish service" http request message -type serviceCreate struct { - Name string `json:"name"` - MyAliases []string `json:"my_aliases"` - Network string `json:"network_name"` +// ServiceCreate represents the body of the "publish service" http request message +type ServiceCreate struct { + Name string `json:"name"` + MyAliases []string `json:"my_aliases"` + Network string `json:"network_name"` + DisableResolution bool `json:"disable_resolution"` } -// serviceDelete represents the body of the "unpublish service" http request message -type serviceDelete struct { +// ServiceDelete represents the body of the "unpublish service" http request message +type ServiceDelete struct { Name string `json:"name"` Force bool `json:"force"` } -// serviceAttach represents the expected body of the "attach/detach sandbox to/from service" http request messages -type serviceAttach struct { - SandboxID string `json:"sandbox_id"` - Aliases []string `json:"aliases"` +// ServiceAttach represents the expected body of the "attach/detach sandbox to/from service" http request messages +type ServiceAttach struct { + SandboxID string `json:"sandbox_id"` + Aliases []string `json:"aliases"` + SandboxKey string `json:"sandbox_key"` } // SandboxCreate is the body of the "post /sandboxes" http request message @@ -76,6 +84,7 @@ type SandboxCreate struct { ResolvConfPath string `json:"resolv_conf_path"` DNS []string `json:"dns"` ExtraHosts []extraHost `json:"extra_hosts"` + UseExternalKey bool `json:"use_external_key"` UseDefaultSandbox bool `json:"use_default_sandbox"` ExposedPorts []types.TransportPort `json:"exposed_ports"` PortMapping []types.PortBinding `json:"port_mapping"` @@ -94,3 +103,13 @@ type sandboxParentUpdate struct { Name string `json:"name"` Address string `json:"address"` } + +// EndpointInfo contants the endpoint info for http response message on endpoint creation +type EndpointInfo struct { + ID string `json:"id"` + Address net.IPNet `json:"address"` + AddressIPv6 net.IPNet `json:"address_ipv6"` + MacAddress net.HardwareAddr `json:"mac_address"` + Gateway net.IP `json:"gateway"` + GatewayIPv6 net.IP `json:"gateway_ipv6"` +} diff --git a/cmd/cni_server/cni_server.go b/cmd/cni_server/cni_server.go new file mode 100644 index 0000000000..56272ec7d2 --- /dev/null +++ b/cmd/cni_server/cni_server.go @@ -0,0 +1,36 @@ +package main + +import ( + "io" + "os" + + "github.com/codegangsta/cli" + "github.com/docker/docker/pkg/reexec" + "github.com/docker/docker/pkg/term" + "github.com/sirupsen/logrus" +) + +func main() { + if reexec.Init() { + return + } + _, stdout, stderr := term.StdStreams() + logrus.SetOutput(stderr) + err := cniApp(stdout, stderr) + if err != nil { + os.Exit(1) + } +} + +func cniApp(stdout, stderr io.Writer) error { + app := cli.NewApp() + + app.Name = "cniserver" + app.Usage = "A cni side car for libnetwork daemon." + app.Flags = cniserverFlags + app.Before = processFlags + //app.Commands = cniCommands // TODO: Add cni commands to improve debuggability + + app.Run(os.Args) + return nil +} diff --git a/cmd/cni_server/flags.go b/cmd/cni_server/flags.go new file mode 100644 index 0000000000..075cca1b4f --- /dev/null +++ b/cmd/cni_server/flags.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "os" + + "github.com/codegangsta/cli" + "github.com/sirupsen/logrus" + + cniserver "github.com/docker/libnetwork/provider/cni/server" +) + +var ( + cniserverFlags = []cli.Flag{ + cli.StringFlag{ + Name: "sock", + Value: "/var/run/cniserver.sock", + Usage: "path to the socket file on which cniserver listens. Default (/var/run/cni-libnetwork.sock)", + }, + cli.StringFlag{ + Name: "dnet-port", + Value: "2389", + Usage: "Daemon socket to connect to. Default(2389)", + }, + cli.StringFlag{ + Name: "dnet-address", + Value: "127.0.0.1", + Usage: "Daemon IP address to connect to", + }, + cli.BoolFlag{ + Name: "D, -debug", + Usage: "Enable debug mode", + }, + } +) + +func processFlags(c *cli.Context) error { + var err error + + if c.Bool("D") { + logrus.SetLevel(logrus.DebugLevel) + } + + cniService, err := cniserver.NewCniService(c.String("sock"), c.String("dnet-address"), c.String("dnet-port")) + if err != nil { + return fmt.Errorf("failed to create cni service: %v", err) + } + serverCloseChan := make(chan struct{}) + if err := cniService.Init(serverCloseChan); err != nil { + logrus.Errorf("Failed to initialize CNI server: %v", err) + os.Exit(1) + } + // Wait on till the server closes + <-serverCloseChan + return nil +} diff --git a/cmd/dnet/cmd.go b/cmd/dnet/cmd.go index 428b433bab..1c85cb788a 100644 --- a/cmd/dnet/cmd.go +++ b/cmd/dnet/cmd.go @@ -3,14 +3,12 @@ package main import ( "encoding/json" "fmt" - "io" - "io/ioutil" - "net/http" "os" "github.com/codegangsta/cli" "github.com/docker/docker/pkg/term" "github.com/docker/libnetwork/client" + "github.com/docker/libnetwork/netutils" ) var ( @@ -49,7 +47,7 @@ func runContainerCreate(c *cli.Context) { } sc := client.SandboxCreate{ContainerID: c.Args()[0]} - obj, _, err := readBody(epConn.httpCall("POST", "/sandboxes", sc, nil)) + obj, _, err := netutils.ReadBody(epConn.conn.HTTPCall("POST", "/sandboxes", sc, nil)) if err != nil { fmt.Printf("POST failed during create container: %v\n", err) os.Exit(1) @@ -74,7 +72,7 @@ func runContainerRm(c *cli.Context) { os.Exit(1) } - obj, _, err := readBody(epConn.httpCall("GET", "/sandboxes?partial-container-id="+c.Args()[0], nil, nil)) + obj, _, err := netutils.ReadBody(epConn.conn.HTTPCall("GET", "/sandboxes?partial-container-id="+c.Args()[0], nil, nil)) if err != nil { fmt.Printf("GET failed during container id lookup: %v\n", err) os.Exit(1) @@ -91,7 +89,7 @@ func runContainerRm(c *cli.Context) { os.Exit(1) } - _, _, err = readBody(epConn.httpCall("DELETE", "/sandboxes/"+sbList[0].ID, nil, nil)) + _, _, err = netutils.ReadBody(epConn.conn.HTTPCall("DELETE", "/sandboxes/"+sbList[0].ID, nil, nil)) if err != nil { fmt.Printf("DELETE of sandbox id %s failed: %v", sbList[0].ID, err) os.Exit(1) @@ -100,7 +98,7 @@ func runContainerRm(c *cli.Context) { func runDockerCommand(c *cli.Context, cmd string) { _, stdout, stderr := term.StdStreams() - oldcli := client.NewNetworkCli(stdout, stderr, epConn.httpCall) + oldcli := client.NewNetworkCli(stdout, stderr, epConn.conn.HTTPCall) var args []string args = append(args, cmd) if c.Bool("h") { @@ -130,17 +128,3 @@ func createDockerCommand(cmd string) cli.Command { }, } } - -func readBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) { - if stream != nil { - defer stream.Close() - } - if err != nil { - return nil, statusCode, err - } - body, err := ioutil.ReadAll(stream) - if err != nil { - return nil, -1, err - } - return body, statusCode, nil -} diff --git a/cmd/dnet/dnet.go b/cmd/dnet/dnet.go index ff5c9df5f3..d90351bd6c 100644 --- a/cmd/dnet/dnet.go +++ b/cmd/dnet/dnet.go @@ -1,8 +1,6 @@ package main import ( - "bytes" - "encoding/json" "errors" "fmt" "io" @@ -18,12 +16,15 @@ import ( "github.com/BurntSushi/toml" "github.com/codegangsta/cli" + "github.com/docker/docker/api/types/network" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/discovery" "github.com/docker/docker/pkg/reexec" - - "github.com/docker/docker/api/types/network" "github.com/docker/docker/pkg/term" + "github.com/gorilla/mux" + "github.com/sirupsen/logrus" + "golang.org/x/net/context" + "github.com/docker/libnetwork" "github.com/docker/libnetwork/api" "github.com/docker/libnetwork/cluster" @@ -33,23 +34,23 @@ import ( "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/netutils" "github.com/docker/libnetwork/options" + "github.com/docker/libnetwork/provider" + "github.com/docker/libnetwork/provider/cni/cniapi" "github.com/docker/libnetwork/types" - "github.com/gorilla/mux" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" ) const ( // DefaultHTTPHost is used if only port is provided to -H flag e.g. docker -d -H tcp://:8080 DefaultHTTPHost = "0.0.0.0" // DefaultHTTPPort is the default http port used by dnet - DefaultHTTPPort = 2385 + DefaultHTTPPort = 2389 // DefaultUnixSocket exported - DefaultUnixSocket = "/var/run/dnet.sock" - cfgFileEnv = "LIBNETWORK_CFG" - defaultCfgFile = "/etc/default/libnetwork.toml" - defaultHeartbeat = time.Duration(10) * time.Second - ttlFactor = 2 + DefaultUnixSocket = "/var/run/dnet.sock" + cfgFileEnv = "LIBNETWORK_CFG" + defaultCfgFile = "/etc/default/libnetwork.toml" + defaultHeartbeat = time.Duration(10) * time.Second + ttlFactor = 2 + defaultProviderTimeout = 120 // default time to fetch state from provider ) var epConn *dnetConnection @@ -96,10 +97,10 @@ func (d *dnetConnection) parseConfig(cfgFile string) (*config.Config, error) { return config.ParseConfig(cfgFile) } -func processConfig(cfg *config.Config) []config.Option { +func processConfig(cfg *config.Config) ([]config.Option, error) { options := []config.Option{} if cfg == nil { - return options + return options, nil } dn := "bridge" @@ -123,14 +124,30 @@ func processConfig(cfg *config.Config) []config.Option { options = append(options, config.OptionKVProviderURL(dcfg.Client.Address)) } - dOptions, err := startDiscovery(&cfg.Cluster) - if err != nil { - logrus.Infof("Skipping discovery : %s", err.Error()) - } else { - options = append(options, dOptions...) + if cfg.Daemon.DefaultGwNetwork != "" { + options = append(options, config.OptionDefaultGwNetwork(cfg.Daemon.DefaultGwNetwork)) + } + + if cfg.Daemon.DataDir != "" { + options = append(options, config.OptionDataDir(cfg.Daemon.DataDir)) } - return options + // Retry discovery for 2 minutes before exiting + if cfg.Cluster.Discovery != "" { + for { + select { + case <-time.After(2 * time.Minute): + return nil, fmt.Errorf("failed to initialize discovery") + default: + dOptions, err := startDiscovery(&cfg.Cluster) + if err == nil { + options = append(options, dOptions...) + return options, nil + } + } + } + } + return options, nil } func startDiscovery(cfg *config.ClusterCfg) ([]config.Option, error) { @@ -230,10 +247,7 @@ func createDefaultNetwork(c libnetwork.NetworkController) { } type dnetConnection struct { - // proto holds the client protocol i.e. unix. - proto string - // addr holds the client address. - addr string + conn *netutils.HTTPConnection Orchestration *NetworkOrchestration configEvent chan cluster.ConfigEventType } @@ -246,7 +260,8 @@ type NetworkOrchestration struct { Peer string } -func (d *dnetConnection) dnetDaemon(cfgFile string) error { +func (d *dnetConnection) dnetDaemon(cfgFile string, provider string) error { + logrus.Infof("Starting DnetDaemon") if err := startTestDriver(); err != nil { return fmt.Errorf("failed to start test driver: %v", err) } @@ -254,9 +269,16 @@ func (d *dnetConnection) dnetDaemon(cfgFile string) error { cfg, err := d.parseConfig(cfgFile) var cOptions []config.Option if err == nil { - cOptions = processConfig(cfg) + cOptions, err = processConfig(cfg) + if err != nil { + return fmt.Errorf("failed to process config: %v", err) + } } else { - logrus.Errorf("Error parsing config %v", err) + return fmt.Errorf("failed to parse config: %v", err) + } + + if provider != "" { + cfg.Daemon.Provider = attachDnetProvider(provider) } bridgeConfig := options.Generic{ @@ -268,9 +290,19 @@ func (d *dnetConnection) dnetDaemon(cfgFile string) error { cOptions = append(cOptions, config.OptionDriverConfig("bridge", bridgeOption)) + // If this is a restore ,then fetch active sandboxes from api server. + if cfg.Daemon.Provider != nil { + sbOptions, err := fetchActiveSandboxes(cfg.Daemon.Provider) + if err != nil { + return err + } + if sbOptions != nil { + cOptions = append(cOptions, sbOptions) + } + } controller, err := libnetwork.New(cOptions...) if err != nil { - fmt.Println("Error starting dnetDaemon :", err) + fmt.Println("Error starting DnetDaemon :", err) return err } controller.SetClusterProvider(d) @@ -298,7 +330,7 @@ func (d *dnetConnection) dnetDaemon(cfgFile string) error { handleSignals(controller) setupDumpStackTrap() - return http.ListenAndServe(d.addr, r) + return http.ListenAndServe(d.conn.Addr, r) } func (d *dnetConnection) IsManager() bool { @@ -428,76 +460,14 @@ func newDnetConnection(val string) (*dnetConnection, error) { return nil, errors.New("dnet currently only supports tcp transport") } - return &dnetConnection{protoAddrParts[0], protoAddrParts[1], &NetworkOrchestration{}, make(chan cluster.ConfigEventType, 10)}, nil -} - -func (d *dnetConnection) httpCall(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) { - var in io.Reader - in, err := encodeData(data) - if err != nil { - return nil, nil, -1, err - } - - req, err := http.NewRequest(method, fmt.Sprintf("%s", path), in) - if err != nil { - return nil, nil, -1, err - } - - setupRequestHeaders(method, data, req, headers) - - req.URL.Host = d.addr - req.URL.Scheme = "http" - - httpClient := &http.Client{} - resp, err := httpClient.Do(req) - statusCode := -1 - if resp != nil { - statusCode = resp.StatusCode - } - if err != nil { - return nil, nil, statusCode, fmt.Errorf("error when trying to connect: %v", err) - } - - if statusCode < 200 || statusCode >= 400 { - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, nil, statusCode, err - } - return nil, nil, statusCode, fmt.Errorf("error : %s", bytes.TrimSpace(body)) - } - - return resp.Body, resp.Header, statusCode, nil -} - -func setupRequestHeaders(method string, data interface{}, req *http.Request, headers map[string][]string) { - if data != nil { - if headers == nil { - headers = make(map[string][]string) - } - headers["Content-Type"] = []string{"application/json"} - } - - expectedPayload := (method == "POST" || method == "PUT") - - if expectedPayload && req.Header.Get("Content-Type") == "" { - req.Header.Set("Content-Type", "text/plain") - } - - if headers != nil { - for k, v := range headers { - req.Header[k] = v - } - } -} - -func encodeData(data interface{}) (*bytes.Buffer, error) { - params := bytes.NewBuffer(nil) - if data != nil { - if err := json.NewEncoder(params).Encode(data); err != nil { - return nil, err - } - } - return params, nil + return &dnetConnection{ + &netutils.HTTPConnection{ + Proto: protoAddrParts[0], + Addr: protoAddrParts[1], + }, + &NetworkOrchestration{}, + make(chan cluster.ConfigEventType, 10), + }, nil } func ipamOption(bridgeName string) libnetwork.NetworkOption { @@ -511,3 +481,34 @@ func ipamOption(bridgeName string) libnetwork.NetworkOption { } return nil } + +func attachDnetProvider(provider string) provider.DnetProvider { + switch provider { + case "cni": + return cniapi.NewDnetCniClient() + default: + return nil + } +} + +func fetchActiveSandboxes(provider provider.DnetProvider) (config.Option, error) { + x := time.Duration(2 * time.Second) + var err error + var sbOptions map[string]interface{} + for x < defaultProviderTimeout { + sbOptions, err = provider.FetchActiveSandboxes() + if err == nil { + goto success + } + logrus.Errorf("Retry:failed to fetch active sandbox: %b", err) + time.Sleep(x * time.Second) + x = x * 2 + } + return nil, fmt.Errorf("failed to fetch active sandbox: %b", err) +success: + logrus.Infof("Active sandboxes are: {%+v}", sbOptions) + if len(sbOptions) != 0 { + return config.OptionActiveSandboxes(sbOptions), nil + } + return nil, nil +} diff --git a/cmd/dnet/flags.go b/cmd/dnet/flags.go index a59bd9d1fd..dfb35806a3 100644 --- a/cmd/dnet/flags.go +++ b/cmd/dnet/flags.go @@ -33,6 +33,10 @@ var ( Value: "/etc/default/libnetwork.toml", Usage: "Configuration file", }, + cli.StringFlag{ + Name: "p, -provider-interface", + Usage: "Provider for Dnet. Accepted values cni", + }, } ) @@ -75,7 +79,9 @@ func processFlags(c *cli.Context) error { } if c.Bool("d") { - err = epConn.dnetDaemon(c.String("c")) + cfgFile := c.String("c") + provider := c.String("p") + err = epConn.dnetDaemon(cfgFile, provider) if err != nil { logrus.Errorf("dnet Daemon exited with an error : %v", err) os.Exit(1) diff --git a/cmd/dnet_cni/main.go b/cmd/dnet_cni/main.go new file mode 100644 index 0000000000..f90d59f0e0 --- /dev/null +++ b/cmd/dnet_cni/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" + log "github.com/sirupsen/logrus" + + "github.com/docker/libnetwork/provider/cni/cniapi" +) + +func cmdAdd(args *skel.CmdArgs) error { + c := cniapi.NewDnetCniClient() + result, err := c.AddWorkload(args) + if err != nil { + return fmt.Errorf("failed to add workload: %v", err) + } + return types.PrintResult(result, version.Current()) +} + +func cmdDel(args *skel.CmdArgs) error { + c := cniapi.NewDnetCniClient() + if err := c.DeleteWorkload(args); err != nil { + return fmt.Errorf("failed to delete workload: %v", err) + } + return nil +} + +func main() { + log.Infof("Dnet CNI plugin") + skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("", "0.1.0", "0.2.0", version.Current())) +} diff --git a/config/config.go b/config/config.go index 3e8473d255..7ce459500f 100644 --- a/config/config.go +++ b/config/config.go @@ -1,6 +1,7 @@ package config import ( + "os" "strings" "github.com/BurntSushi/toml" @@ -8,11 +9,13 @@ import ( "github.com/docker/docker/pkg/plugingetter" "github.com/docker/go-connections/tlsconfig" "github.com/docker/libkv/store" + "github.com/sirupsen/logrus" + "github.com/docker/libnetwork/cluster" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/osl" - "github.com/sirupsen/logrus" + "github.com/docker/libnetwork/provider" ) const ( @@ -33,8 +36,10 @@ type Config struct { type DaemonCfg struct { Debug bool Experimental bool + Provider provider.DnetProvider DataDir string DefaultNetwork string + DefaultGwNetwork string DefaultDriver string Labels []string DriverCfg map[string]interface{} @@ -69,7 +74,21 @@ func ParseConfig(tomlCfgFile string) (*Config, error) { if _, err := toml.DecodeFile(tomlCfgFile, cfg); err != nil { return nil, err } + if cfg.Cluster.Address == "" { + cfg.Cluster.Address = os.Getenv("DNET_ADDRESS") + } + if cfg.Cluster.Discovery == "" { + cfg.Cluster.Discovery = os.Getenv("DNET_DISCOVERY") + } + + if _, ok := cfg.Scopes[datastore.GlobalScope]; !ok { + kvParts := strings.SplitN(cfg.Cluster.Discovery, "://", 2) + if len(kvParts) == 2 { + gCfg := datastore.ScopeClientCfg{Provider: kvParts[0], Address: kvParts[1]} + cfg.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{gCfg} + } + } cfg.LoadDefaultScopes(cfg.Daemon.DataDir) return cfg, nil } @@ -97,11 +116,17 @@ type Option func(c *Config) // OptionDefaultNetwork function returns an option setter for a default network func OptionDefaultNetwork(dn string) Option { return func(c *Config) { - logrus.Debugf("Option DefaultNetwork: %s", dn) c.Daemon.DefaultNetwork = strings.TrimSpace(dn) } } +// OptionDefaultGwNetwork function returns an option setter for a default Gateway network +func OptionDefaultGwNetwork(dn string) Option { + return func(c *Config) { + c.Daemon.DefaultGwNetwork = strings.TrimSpace(dn) + } +} + // OptionDefaultDriver function returns an option setter for default driver func OptionDefaultDriver(dd string) Option { return func(c *Config) { diff --git a/config/libnetwork.toml b/config/libnetwork.toml index 93a2ff4756..9c0cba2b48 100644 --- a/config/libnetwork.toml +++ b/config/libnetwork.toml @@ -1,12 +1,20 @@ title = "LibNetwork Configuration file" [daemon] - debug = false + debug = true + labels = ["com.docker.network.driver.overlay.hostmode=true", "com.docker.network.driver.overlay.vxlan-port=4790", "com.docker.network.driver.overlay.gossip-port=8000"] + defaultGwNetwork = "dnet-gwbridge" + DataDir = "/var/run/libnetwork" [cluster] - discovery = "token://swarm-discovery-token" - Address = "Cluster-wide reachable Host IP" + discovery = "etcd://192.168.56.101:3379" + address = "192.168.56.101" [datastore] embedded = false [datastore.client] - provider = "consul" - Address = "localhost:8500" + provider = "etcd" + Address = "192.168.56.101:3379" +[scopes] + [scopes.global] + [scopes.global.client] + provider = "etcd" + address = "192.168.56.101:3379" diff --git a/controller.go b/controller.go index 801097ab99..74002abcff 100644 --- a/controller.go +++ b/controller.go @@ -190,12 +190,11 @@ func New(cfgOptions ...config.Option) (NetworkController, error) { if err := c.initStores(); err != nil { return nil, err } - + c.initDefaultGwNetwork() drvRegistry, err := drvregistry.New(c.getStore(datastore.LocalScope), c.getStore(datastore.GlobalScope), c.RegisterDriver, nil, c.cfg.PluginGetter) if err != nil { return nil, err } - for _, i := range getInitializers(c.cfg.Daemon.Experimental) { var dcfg map[string]interface{} @@ -235,7 +234,6 @@ func New(cfgOptions ...config.Option) (NetworkController, error) { c.sandboxCleanup(c.cfg.ActiveSandboxes) c.cleanupLocalEndpoints() c.networkCleanup() - if err := c.startExternalKeyListener(); err != nil { return nil, err } diff --git a/default_gateway.go b/default_gateway.go index 9a60fd6758..bee6ea73e5 100644 --- a/default_gateway.go +++ b/default_gateway.go @@ -29,6 +29,12 @@ var procGwNetwork = make(chan (bool), 1) - its deleted when an endpoint with GW joins the container */ +func (c *controller) initDefaultGwNetwork() { + if c.cfg.Daemon.DefaultGwNetwork == "" { + c.cfg.Daemon.DefaultGwNetwork = libnGWNetwork + } +} + func (sb *sandbox) setupDefaultGW() error { // check if the container already has a GW endpoint @@ -40,14 +46,14 @@ func (sb *sandbox) setupDefaultGW() error { // Look for default gw network. In case of error (includes not found), // retry and create it if needed in a serialized execution. - n, err := c.NetworkByName(libnGWNetwork) + n, err := c.NetworkByName(sb.controller.DefaultGwNetworkName()) if err != nil { if n, err = c.defaultGwNetwork(); err != nil { return err } } - createOptions := []EndpointOption{CreateOptionAnonymous()} + createOptions := []EndpointOption{CreateOptionAnonymous(), CreateOptionDisableResolution()} eplen := gwEPlen if len(sb.containerID) < gwEPlen { @@ -146,7 +152,7 @@ func (sb *sandbox) needDefaultGW() bool { func (sb *sandbox) getEndpointInGWNetwork() *endpoint { for _, ep := range sb.getConnectedEndpoints() { - if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") { + if ep.getNetwork().name == sb.controller.DefaultGwNetworkName() && strings.HasPrefix(ep.Name(), "gateway_") { return ep } } @@ -154,7 +160,7 @@ func (sb *sandbox) getEndpointInGWNetwork() *endpoint { } func (ep *endpoint) endpointInGWNetwork() bool { - if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") { + if ep.getNetwork().name == ep.getNetwork().ctrlr.DefaultGwNetworkName() && strings.HasPrefix(ep.Name(), "gateway_") { return true } return false @@ -178,7 +184,7 @@ func (c *controller) defaultGwNetwork() (Network, error) { procGwNetwork <- true defer func() { <-procGwNetwork }() - n, err := c.NetworkByName(libnGWNetwork) + n, err := c.NetworkByName(c.DefaultGwNetworkName()) if err != nil { if _, ok := err.(types.NotFoundError); ok { n, err = c.createGWNetwork() @@ -187,6 +193,10 @@ func (c *controller) defaultGwNetwork() (Network, error) { return n, err } +func (c *controller) DefaultGwNetworkName() string { + return c.cfg.Daemon.DefaultGwNetwork +} + // Returns the endpoint which is providing external connectivity to the sandbox func (sb *sandbox) getGatewayEndpoint() *endpoint { for _, ep := range sb.getConnectedEndpoints() { diff --git a/default_gateway_linux.go b/default_gateway_linux.go index 60df856722..5f946e8056 100644 --- a/default_gateway_linux.go +++ b/default_gateway_linux.go @@ -15,12 +15,12 @@ func getPlatformOption() EndpointOption { func (c *controller) createGWNetwork() (Network, error) { netOption := map[string]string{ - bridge.BridgeName: libnGWNetwork, + bridge.BridgeName: c.DefaultGwNetworkName(), bridge.EnableICC: strconv.FormatBool(false), bridge.EnableIPMasquerade: strconv.FormatBool(true), } - n, err := c.NewNetwork("bridge", libnGWNetwork, "", + n, err := c.NewNetwork("bridge", c.DefaultGwNetworkName(), "", NetworkOptionDriverOpts(netOption), NetworkOptionEnableIPv6(false), ) diff --git a/default_gateway_solaris.go b/default_gateway_solaris.go index 8d86a66c1d..7ffeb44715 100644 --- a/default_gateway_solaris.go +++ b/default_gateway_solaris.go @@ -15,12 +15,12 @@ func getPlatformOption() EndpointOption { func (c *controller) createGWNetwork() (Network, error) { netOption := map[string]string{ - bridge.BridgeName: libnGWNetwork, + bridge.BridgeName: c.DefaultGwNetworkName(), bridge.EnableICC: strconv.FormatBool(false), bridge.EnableIPMasquerade: strconv.FormatBool(true), } - n, err := c.NewNetwork("bridge", libnGWNetwork, "", + n, err := c.NewNetwork("bridge", c.DefaultGwNetworkName(), "", NetworkOptionDriverOpts(netOption), NetworkOptionEnableIPv6(false), ) diff --git a/driverapi/driverapi.go b/driverapi/driverapi.go index 48a14ae57a..22a19f9427 100644 --- a/driverapi/driverapi.go +++ b/driverapi/driverapi.go @@ -56,7 +56,7 @@ type Driver interface { Join(nid, eid string, sboxKey string, jinfo JoinInfo, options map[string]interface{}) error // Leave method is invoked when a Sandbox detaches from an endpoint. - Leave(nid, eid string) error + Leave(nid, eid string, linfo LeaveInfo) error // ProgramExternalConnectivity invokes the driver method which does the necessary // programming to allow the external connectivity dictated by the passed options @@ -136,6 +136,9 @@ type JoinInfo interface { // SetGateway sets the default IPv4 gateway when a container joins the endpoint. SetGateway(net.IP) error + // RequestAddress allocates an IP address as required by the driver + RequestAddress(*net.IPNet) (*net.IPNet, error) + // SetGatewayIPv6 sets the default IPv6 gateway when a container joins the endpoint. SetGatewayIPv6(net.IP) error @@ -151,6 +154,12 @@ type JoinInfo interface { AddTableEntry(tableName string, key string, value []byte) error } +// LeaveInfo interface for object release during sandbox detach +type LeaveInfo interface { + // ReleaseAddress frees up allocated IP + ReleaseAddress(net.IP) error +} + // DriverCallback provides a Callback interface for Drivers into LibNetwork type DriverCallback interface { // GetPluginGetter returns the pluginv2 getter. diff --git a/drivers/bridge/bridge.go b/drivers/bridge/bridge.go index 1742c8df31..44ee92f4c3 100644 --- a/drivers/bridge/bridge.go +++ b/drivers/bridge/bridge.go @@ -1244,7 +1244,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { defer osl.InitOSContext()() network, err := d.getNetwork(nid) diff --git a/drivers/bridge/bridge_test.go b/drivers/bridge/bridge_test.go index 3fbddc6e63..ef67f6747e 100644 --- a/drivers/bridge/bridge_test.go +++ b/drivers/bridge/bridge_test.go @@ -686,7 +686,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) { } // release host mapped ports - err = d.Leave("net1", "ep1") + err = d.Leave("net1", "ep1", nil) if err != nil { t.Fatal(err) } @@ -810,7 +810,7 @@ func TestLinkContainers(t *testing.T) { t.Fatalf("Failed to revoke external connectivity: %v", err) } - err = d.Leave("net1", "ep2") + err = d.Leave("net1", "ep2", nil) if err != nil { t.Fatal("Failed to unlink ep1 and ep2") } diff --git a/drivers/bridge/brmanager/brmanager.go b/drivers/bridge/brmanager/brmanager.go index 74bb95c001..7604c32279 100644 --- a/drivers/bridge/brmanager/brmanager.go +++ b/drivers/bridge/brmanager/brmanager.go @@ -59,7 +59,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return types.NotImplementedErrorf("not implemented") } -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { return types.NotImplementedErrorf("not implemented") } diff --git a/drivers/host/host.go b/drivers/host/host.go index a71d461380..7a245c4cee 100644 --- a/drivers/host/host.go +++ b/drivers/host/host.go @@ -75,7 +75,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { return nil } diff --git a/drivers/ipvlan/ipvlan_joinleave.go b/drivers/ipvlan/ipvlan_joinleave.go index 9d229a245e..e1de092c69 100644 --- a/drivers/ipvlan/ipvlan_joinleave.go +++ b/drivers/ipvlan/ipvlan_joinleave.go @@ -124,7 +124,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { defer osl.InitOSContext()() network, err := d.getNetwork(nid) if err != nil { diff --git a/drivers/ipvlan/ivmanager/ivmanager.go b/drivers/ipvlan/ivmanager/ivmanager.go index 519f1e8795..4efda8675e 100644 --- a/drivers/ipvlan/ivmanager/ivmanager.go +++ b/drivers/ipvlan/ivmanager/ivmanager.go @@ -59,7 +59,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return types.NotImplementedErrorf("not implemented") } -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { return types.NotImplementedErrorf("not implemented") } diff --git a/drivers/macvlan/macvlan_joinleave.go b/drivers/macvlan/macvlan_joinleave.go index 778613db77..fd5582836c 100644 --- a/drivers/macvlan/macvlan_joinleave.go +++ b/drivers/macvlan/macvlan_joinleave.go @@ -84,7 +84,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { defer osl.InitOSContext()() network, err := d.getNetwork(nid) if err != nil { diff --git a/drivers/macvlan/mvmanager/mvmanager.go b/drivers/macvlan/mvmanager/mvmanager.go index 0f811ac36f..7795c13ac2 100644 --- a/drivers/macvlan/mvmanager/mvmanager.go +++ b/drivers/macvlan/mvmanager/mvmanager.go @@ -59,7 +59,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return types.NotImplementedErrorf("not implemented") } -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { return types.NotImplementedErrorf("not implemented") } diff --git a/drivers/null/null.go b/drivers/null/null.go index 7f2a5e32f7..0b19ace129 100644 --- a/drivers/null/null.go +++ b/drivers/null/null.go @@ -74,7 +74,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { return nil } diff --git a/drivers/overlay/encryption.go b/drivers/overlay/encryption.go index 802d7bc36d..f07bc17c0a 100644 --- a/drivers/overlay/encryption.go +++ b/drivers/overlay/encryption.go @@ -113,13 +113,13 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal if add { for _, rIP := range nodes { - if err := setupEncryption(lIP, aIP, rIP, vxlanID, d.secMap, d.keys); err != nil { + if err := d.setupEncryption(lIP, aIP, rIP, vxlanID, d.secMap, d.keys); err != nil { logrus.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err) } } } else { if len(nodes) == 0 { - if err := removeEncryption(lIP, rIP, d.secMap); err != nil { + if err := d.removeEncryption(lIP, rIP, d.secMap); err != nil { logrus.Warnf("Failed to remove network encryption between %s and %s: %v", lIP, rIP, err) } } @@ -128,18 +128,18 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal return nil } -func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*key) error { +func (d *driver) setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*key) error { logrus.Debugf("Programming encryption for vxlan %d between %s and %s", vni, localIP, remoteIP) rIPs := remoteIP.String() indices := make([]*spi, 0, len(keys)) - err := programMangle(vni, true) + err := programMangle(vni, d.vxlanPort, true) if err != nil { logrus.Warn(err) } - err = programInput(vni, true) + err = programInput(vni, d.vxlanPort, true) if err != nil { logrus.Warn(err) } @@ -171,7 +171,7 @@ func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, k return nil } -func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error { +func (d *driver) removeEncryption(localIP, remoteIP net.IP, em *encrMap) error { em.Lock() indices, ok := em.nodes[remoteIP.String()] em.Unlock() @@ -198,7 +198,7 @@ func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error { return nil } -func programMangle(vni uint32, add bool) (err error) { +func programMangle(vni uint32, vxlanPort int, add bool) (err error) { var ( p = strconv.FormatUint(uint64(vxlanPort), 10) c = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8) @@ -225,7 +225,7 @@ func programMangle(vni uint32, add bool) (err error) { return } -func programInput(vni uint32, add bool) (err error) { +func programInput(vni uint32, vxlanPort int, add bool) (err error) { var ( port = strconv.FormatUint(uint64(vxlanPort), 10) vniMatch = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8) diff --git a/drivers/overlay/filter.go b/drivers/overlay/filter.go index 1601803aa0..f0f545ca1e 100644 --- a/drivers/overlay/filter.go +++ b/drivers/overlay/filter.go @@ -87,7 +87,7 @@ func removeNetworkChain(cname string) error { return setNetworkChain(cname, true) } -func setFilters(cname, brName string, remove bool) error { +func setFilters(cname, brName string, hostAccess bool, remove bool) error { opt := "-I" if remove { opt = "-D" @@ -117,26 +117,40 @@ func setFilters(cname, brName string, remove bool) error { } } - exists = iptables.Exists(iptables.Filter, cname, "-i", brName, "-j", "ACCEPT") + acceptRule := []string{"-i", brName, "-j", "ACCEPT"} + if hostAccess { + acceptRule = []string{"-j", "ACCEPT"} + + // Insert/Delete a rule to jump to per-bridge chain for bridge ingress case + exists = iptables.Exists(iptables.Filter, globalChain, "-i", brName, "!", "-o", brName, "-j", cname) + if (!remove && !exists) || (remove && exists) { + if err := iptables.RawCombinedOutput(opt, globalChain, "-i", brName, "!", "-o", brName, "-j", cname); err != nil { + return fmt.Errorf("failed to add per-bridge ingress filter rule for bridge %s, network chain %s: %v", brName, cname, err) + } + } + } + + exists = iptables.Exists(iptables.Filter, cname, acceptRule...) if (!remove && exists) || (remove && !exists) { return nil } - if err := iptables.RawCombinedOutput(opt, cname, "-i", brName, "-j", "ACCEPT"); err != nil { - return fmt.Errorf("failed to add overlay filter rile for network chain %s, bridge %s: %v", cname, brName, err) + combinedRule := []string{opt, cname} + if err := iptables.RawCombinedOutput(append(combinedRule, acceptRule...)...); err != nil { + return fmt.Errorf("failed to add overlay filter rile for network chain %s, bridge %s, hostAccess %v: %v", cname, brName, hostAccess, err) } return nil } -func addFilters(cname, brName string) error { +func addFilters(cname, brName string, hostAccess bool) error { defer filterWait()() - return setFilters(cname, brName, false) + return setFilters(cname, brName, hostAccess, false) } -func removeFilters(cname, brName string) error { +func removeFilters(cname, brName string, hostAccess bool) error { defer filterWait()() - return setFilters(cname, brName, true) + return setFilters(cname, brName, hostAccess, true) } diff --git a/drivers/overlay/joinleave.go b/drivers/overlay/joinleave.go index 0770513e7d..3a1384f843 100644 --- a/drivers/overlay/joinleave.go +++ b/drivers/overlay/joinleave.go @@ -6,6 +6,7 @@ import ( "syscall" "github.com/docker/libnetwork/driverapi" + "github.com/docker/libnetwork/netutils" "github.com/docker/libnetwork/ns" "github.com/docker/libnetwork/types" "github.com/gogo/protobuf/proto" @@ -43,6 +44,15 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return fmt.Errorf("could not find subnet for endpoint %s", eid) } + if s.gwIP == nil { + gwIP, err := jinfo.RequestAddress(s.subnetIP) + if err != nil { + logrus.Errorf("RequestAddress failed %s %v", s.subnetIP.String(), err) + return err + } + s.gwIP = gwIP + } + if err := n.obtainVxlanID(s); err != nil { return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err) } @@ -121,6 +131,9 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } d.peerAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), false, false, true) + if n.hostAccess { + d.peerAdd(nid, eid, s.gwIP.IP, s.gwIP.Mask, netutils.GenerateMACFromIP(s.gwIP.IP), net.ParseIP(d.advertiseAddress), false, false, true) + } if err = d.checkEncryption(nid, nil, n.vxlanID(s), true, true); err != nil { logrus.Warn(err) @@ -208,7 +221,7 @@ func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key stri } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { if err := validateID(nid, eid); err != nil { return err } @@ -233,8 +246,7 @@ func (d *driver) Leave(nid, eid string) error { } d.peerDelete(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), true) - - n.leaveSandbox() + n.leaveSandbox(linfo) return nil } diff --git a/drivers/overlay/ov_network.go b/drivers/overlay/ov_network.go index 3fbfccf007..3caa08dc2b 100644 --- a/drivers/overlay/ov_network.go +++ b/drivers/overlay/ov_network.go @@ -31,7 +31,6 @@ import ( ) var ( - hostMode bool networkOnce sync.Once networkMu sync.Mutex vniTbl = make(map[uint32]string) @@ -56,20 +55,21 @@ type subnetJSON struct { } type network struct { - id string - dbIndex uint64 - dbExists bool - sbox osl.Sandbox - nlSocket *nl.NetlinkSocket - endpoints endpointTable - driver *driver - joinCnt int - once *sync.Once - initEpoch int - initErr error - subnets []*subnet - secure bool - mtu int + id string + dbIndex uint64 + dbExists bool + sbox osl.Sandbox + nlSocket *nl.NetlinkSocket + endpoints endpointTable + driver *driver + joinCnt int + once *sync.Once + initEpoch int + initErr error + subnets []*subnet + secure bool + hostAccess bool + mtu int sync.Mutex } @@ -173,6 +173,9 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d if _, ok := optMap[secureOption]; ok { n.secure = true } + if _, ok := optMap[hostAccess]; ok { + n.hostAccess = true + } if val, ok := optMap[netlabel.DriverMTU]; ok { var err error if n.mtu, err = strconv.Atoi(val); err != nil { @@ -211,8 +214,8 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d // Make sure no rule is on the way from any stale secure network if !n.secure { for _, vni := range vnis { - programMangle(vni, false) - programInput(vni, false) + programMangle(vni, d.vxlanPort, false) + programInput(vni, d.vxlanPort, false) } } @@ -263,8 +266,8 @@ func (d *driver) DeleteNetwork(nid string) error { if n.secure { for _, vni := range vnis { - programMangle(vni, false) - programInput(vni, false) + programMangle(vni, d.vxlanPort, false) + programInput(vni, d.vxlanPort, false) } } @@ -304,7 +307,7 @@ func (n *network) joinSubnetSandbox(s *subnet, restore bool) error { return s.initErr } -func (n *network) leaveSandbox() { +func (n *network) leaveSandbox(linfo driverapi.LeaveInfo) { n.Lock() defer n.Unlock() n.joinCnt-- @@ -318,6 +321,13 @@ func (n *network) leaveSandbox() { n.once = &sync.Once{} for _, s := range n.subnets { s.once = &sync.Once{} + if n.hostAccess { + err := linfo.ReleaseAddress(s.gwIP.IP) + if err != nil { + logrus.Errorf("Releasing GW IP failed %v", err) + } + s.gwIP = nil + } } n.destroySandbox() @@ -334,7 +344,7 @@ func (n *network) destroySandbox() { for _, s := range n.subnets { if hostMode { - if err := removeFilters(n.id[:12], s.brName); err != nil { + if err := removeFilters(n.id[:12], s.brName, n.hostAccess); err != nil { logrus.Warnf("Could not remove overlay filters: %v", err) } } @@ -408,15 +418,13 @@ func populateVNITbl() { }) } -func networkOnceInit() { +func (d *driver) networkOnceInit() { populateVNITbl() - - if os.Getenv("_OVERLAY_HOST_MODE") != "" { - hostMode = true + if hostMode { return } - err := createVxlan("testvxlan", 1, 0) + err := createVxlan("testvxlan", 1, d.vxlanPort, 0) if err != nil { logrus.Errorf("Failed to create testvxlan interface: %v", err) return @@ -552,11 +560,12 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error if err := sbox.AddInterface(brName, "br", sbox.InterfaceOptions().Address(s.gwIP), + sbox.InterfaceOptions().MacAddress(netutils.GenerateMACFromIP(s.gwIP.IP)), sbox.InterfaceOptions().Bridge(true)); err != nil { return fmt.Errorf("bridge creation in sandbox failed for subnet %q: %v", s.subnetIP.String(), err) } - err := createVxlan(vxlanName, n.vxlanID(s), n.maxMTU()) + err := createVxlan(vxlanName, n.vxlanID(s), n.driver.vxlanPort, n.maxMTU()) if err != nil { return err } @@ -586,7 +595,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error } if hostMode { - if err := addFilters(n.id[:12], brName); err != nil { + if err := addFilters(n.id[:12], brName, n.hostAccess); err != nil { return err } } @@ -656,7 +665,7 @@ func (n *network) initSandbox(restore bool) error { n.initEpoch++ n.Unlock() - networkOnce.Do(networkOnceInit) + networkOnce.Do(n.driver.networkOnceInit) if !restore { if hostMode { @@ -811,6 +820,11 @@ func (d *driver) network(nid string) *network { n.driver = d n.endpoints = endpointTable{} n.once = &sync.Once{} + if n.hostAccess { + for _, s := range n.subnets { + s.gwIP = nil + } + } d.Lock() d.networks[nid] = n d.Unlock() @@ -888,6 +902,7 @@ func (n *network) Value() []byte { } m["secure"] = n.secure + m["hostAccess"] = n.hostAccess m["subnets"] = netJSON m["mtu"] = n.mtu b, err := json.Marshal(m) @@ -939,6 +954,9 @@ func (n *network) SetValue(value []byte) error { if val, ok := m["secure"]; ok { n.secure = val.(bool) } + if val, ok := m["hostAccess"]; ok { + n.hostAccess = val.(bool) + } if val, ok := m["mtu"]; ok { n.mtu = int(val.(float64)) } diff --git a/drivers/overlay/ov_serf.go b/drivers/overlay/ov_serf.go index f644799afd..b54ce09bdb 100644 --- a/drivers/overlay/ov_serf.go +++ b/drivers/overlay/ov_serf.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/docker/libnetwork/netutils" "github.com/hashicorp/serf/serf" "github.com/sirupsen/logrus" ) @@ -41,6 +42,8 @@ func (d *driver) serfInit() error { config := serf.DefaultConfig() config.Init() config.MemberlistConfig.BindAddr = d.advertiseAddress + config.MemberlistConfig.BindPort = d.gossipPort + config.MemberlistConfig.AdvertisePort = d.gossipPort d.eventCh = make(chan serf.Event, 4) config.EventCh = d.eventCh @@ -91,6 +94,33 @@ func (d *driver) notifyEvent(event ovNotify) { if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil { logrus.Errorf("Sending user event failed: %v\n", err) } + + // Following Serf Event of sending the unique gateway IP is applicable only + // to the network that requires hostAccess + + nw := event.nw + if !nw.hostAccess { + return + } + var snet *subnet + for _, s := range nw.subnets { + if s.subnetIP.Contains(ep.addr.IP) { + snet = s + } + } + if snet == nil || snet.gwIP == nil { + logrus.Errorf("GW IP reset is not sent in serf channel %v", snet) + return + } + + ePayload = fmt.Sprintf("%s %s %s %s", event.action, snet.gwIP.IP.String(), + net.IP(snet.gwIP.Mask).String(), netutils.GenerateMACFromIP(snet.gwIP.IP).String()) + eName = fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(), + event.nw.id, ep.id) + + if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil { + logrus.Errorf("Sending user event failed: %v\n", err) + } } func (d *driver) processEvent(u serf.UserEvent) { diff --git a/drivers/overlay/ov_utils.go b/drivers/overlay/ov_utils.go index 27f57c1fe2..84b9ce9244 100644 --- a/drivers/overlay/ov_utils.go +++ b/drivers/overlay/ov_utils.go @@ -54,14 +54,14 @@ func createVethPair() (string, string, error) { return name1, name2, nil } -func createVxlan(name string, vni uint32, mtu int) error { +func createVxlan(name string, vni uint32, port int, mtu int) error { defer osl.InitOSContext()() vxlan := &netlink.Vxlan{ LinkAttrs: netlink.LinkAttrs{Name: name, MTU: mtu}, VxlanId: int(vni), Learning: true, - Port: vxlanPort, + Port: int(port), Proxy: true, L3miss: true, L2miss: true, diff --git a/drivers/overlay/overlay.go b/drivers/overlay/overlay.go index f029c5cce4..220c4ff748 100644 --- a/drivers/overlay/overlay.go +++ b/drivers/overlay/overlay.go @@ -6,6 +6,8 @@ import ( "context" "fmt" "net" + "os" + "strconv" "sync" "github.com/docker/libnetwork/datastore" @@ -20,16 +22,20 @@ import ( ) const ( - networkType = "overlay" - vethPrefix = "veth" - vethLen = 7 - vxlanIDStart = 256 - vxlanIDEnd = (1 << 24) - 1 - vxlanPort = 4789 - vxlanEncap = 50 - secureOption = "encrypted" + networkType = "overlay" + vethPrefix = "veth" + vethLen = 7 + vxlanIDStart = 256 + vxlanIDEnd = (1 << 24) - 1 + vxlanEncap = 50 + secureOption = "encrypted" + hostAccess = "hostaccess" + hostModeLabel = netlabel.DriverPrefix + "." + networkType + ".hostmode" + vxlanPortLabel = netlabel.DriverPrefix + "." + networkType + ".vxlan-port" + gossipPortLabel = netlabel.DriverPrefix + "." + networkType + ".gossip-port" ) +var hostMode bool var initVxlanIdm = make(chan (bool), 1) type driver struct { @@ -53,6 +59,8 @@ type driver struct { keys []*key peerOpCh chan *peerOperation peerOpCancel context.CancelFunc + gossipPort int + vxlanPort int sync.Mutex } @@ -67,9 +75,11 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { peerDb: peerNetworkMap{ mp: map[string]*peerMap{}, }, - secMap: &encrMap{nodes: map[string][]*spi{}}, - config: config, - peerOpCh: make(chan *peerOperation), + secMap: &encrMap{nodes: map[string][]*spi{}}, + config: config, + peerOpCh: make(chan *peerOperation), + vxlanPort: 4789, + gossipPort: 7946, } // Launch the go routine for processing peer operations @@ -101,6 +111,46 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { } } + if os.Getenv("_OVERLAY_HOST_MODE") != "" { + hostMode = true + } + + if _, ok := config[hostModeLabel]; ok { + hostMode = true + } + + if port, ok := config[vxlanPortLabel]; ok { + switch p := port.(type) { + case string: + vp, err := strconv.Atoi(p) + if err == nil { + d.vxlanPort = vp + } else { + logrus.Errorf("Error parsing VXLANPORT : %s %v", p, err) + } + case int, int32, int64: + d.vxlanPort = p.(int) + default: + logrus.Errorf("Error parsing VXLANPORT : %v", port) + } + } + + if port, ok := config[gossipPortLabel]; ok { + switch p := port.(type) { + case string: + gp, err := strconv.Atoi(p) + if err == nil { + d.gossipPort = gp + } else { + logrus.Errorf("Error parsing GOSSIPPORT : %s %v", p, err) + } + case int, int32, int64: + d.gossipPort = p.(int) + default: + logrus.Errorf("Error parsing GOSSIPPORT : %v", port) + } + } + if err := d.restoreEndpoints(); err != nil { logrus.Warnf("Failure during overlay endpoints restore: %v", err) } diff --git a/drivers/overlay/ovmanager/ovmanager.go b/drivers/overlay/ovmanager/ovmanager.go index 58cc687d4f..49181b8153 100644 --- a/drivers/overlay/ovmanager/ovmanager.go +++ b/drivers/overlay/ovmanager/ovmanager.go @@ -226,7 +226,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { return types.NotImplementedErrorf("not implemented") } diff --git a/drivers/remote/driver.go b/drivers/remote/driver.go index b52163025a..7b086226ee 100644 --- a/drivers/remote/driver.go +++ b/drivers/remote/driver.go @@ -248,7 +248,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, ifaceName := res.InterfaceName if iface := jinfo.InterfaceName(); iface != nil && ifaceName != nil { if err := iface.SetNames(ifaceName.SrcName, ifaceName.DstPrefix); err != nil { - return errorWithRollback(fmt.Sprintf("failed to set interface name: %s", err), d.Leave(nid, eid)) + return errorWithRollback(fmt.Sprintf("failed to set interface name: %s", err), d.Leave(nid, eid, nil)) } } @@ -258,7 +258,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return fmt.Errorf(`unable to parse Gateway "%s"`, res.Gateway) } if jinfo.SetGateway(addr) != nil { - return errorWithRollback(fmt.Sprintf("failed to set gateway: %v", addr), d.Leave(nid, eid)) + return errorWithRollback(fmt.Sprintf("failed to set gateway: %v", addr), d.Leave(nid, eid, nil)) } } if res.GatewayIPv6 != "" { @@ -266,7 +266,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return fmt.Errorf(`unable to parse GatewayIPv6 "%s"`, res.GatewayIPv6) } if jinfo.SetGatewayIPv6(addr) != nil { - return errorWithRollback(fmt.Sprintf("failed to set gateway IPv6: %v", addr), d.Leave(nid, eid)) + return errorWithRollback(fmt.Sprintf("failed to set gateway IPv6: %v", addr), d.Leave(nid, eid, nil)) } } if len(res.StaticRoutes) > 0 { @@ -276,7 +276,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } for _, route := range routes { if jinfo.AddStaticRoute(route.Destination, route.RouteType, route.NextHop) != nil { - return errorWithRollback(fmt.Sprintf("failed to set static route: %v", route), d.Leave(nid, eid)) + return errorWithRollback(fmt.Sprintf("failed to set static route: %v", route), d.Leave(nid, eid, nil)) } } } @@ -287,7 +287,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { leave := &api.LeaveRequest{ NetworkID: nid, EndpointID: eid, diff --git a/drivers/remote/driver_test.go b/drivers/remote/driver_test.go index 8a97bacffd..85ead5d942 100644 --- a/drivers/remote/driver_test.go +++ b/drivers/remote/driver_test.go @@ -435,7 +435,7 @@ func TestRemoteDriver(t *testing.T) { if _, err = d.EndpointOperInfo(netID, endID); err != nil { t.Fatal(err) } - if err = d.Leave(netID, endID); err != nil { + if err = d.Leave(netID, endID, nil); err != nil { t.Fatal(err) } if err = d.DeleteEndpoint(netID, endID); err != nil { diff --git a/drivers/solaris/bridge/bridge.go b/drivers/solaris/bridge/bridge.go index 558157abe4..44f89d013c 100644 --- a/drivers/solaris/bridge/bridge.go +++ b/drivers/solaris/bridge/bridge.go @@ -843,7 +843,7 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, enable b } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { network, err := d.getNetwork(nid) if err != nil { return types.InternalMaskableErrorf("%s", err) diff --git a/drivers/solaris/bridge/bridge_test.go b/drivers/solaris/bridge/bridge_test.go index e27264a6e7..c46c2351e1 100644 --- a/drivers/solaris/bridge/bridge_test.go +++ b/drivers/solaris/bridge/bridge_test.go @@ -579,7 +579,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) { } // release host mapped ports - err = d.Leave("net1", "ep1") + err = d.Leave("net1", "ep1", nil) if err != nil { t.Fatal(err) } diff --git a/drivers/solaris/overlay/joinleave.go b/drivers/solaris/overlay/joinleave.go index ff03f3ccb6..ece17ac371 100644 --- a/drivers/solaris/overlay/joinleave.go +++ b/drivers/solaris/overlay/joinleave.go @@ -154,7 +154,7 @@ func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (s } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { if err := validateID(nid, eid); err != nil { return err } diff --git a/drivers/solaris/overlay/ovmanager/ovmanager.go b/drivers/solaris/overlay/ovmanager/ovmanager.go index 430e38a4a3..f51e8e7635 100644 --- a/drivers/solaris/overlay/ovmanager/ovmanager.go +++ b/drivers/solaris/overlay/ovmanager/ovmanager.go @@ -226,7 +226,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { return types.NotImplementedErrorf("not implemented") } diff --git a/drivers/windows/overlay/joinleave_windows.go b/drivers/windows/overlay/joinleave_windows.go index 83bee5ad93..a7b24fd64e 100644 --- a/drivers/windows/overlay/joinleave_windows.go +++ b/drivers/windows/overlay/joinleave_windows.go @@ -103,7 +103,7 @@ func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (s } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { if err := validateID(nid, eid); err != nil { return err } diff --git a/drivers/windows/windows.go b/drivers/windows/windows.go index 16d1ca2cb9..3c61d8c717 100644 --- a/drivers/windows/windows.go +++ b/drivers/windows/windows.go @@ -752,7 +752,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } // Leave method is invoked when a Sandbox detaches from an endpoint. -func (d *driver) Leave(nid, eid string) error { +func (d *driver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { network, err := d.getNetwork(nid) if err != nil { return types.InternalMaskableErrorf("%s", err) diff --git a/endpoint.go b/endpoint.go index a2d1dbc4c6..cbab33faef 100644 --- a/endpoint.go +++ b/endpoint.go @@ -478,7 +478,7 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) (err error) { } defer func() { if err != nil { - if e := d.Leave(nid, epid); e != nil { + if e := d.Leave(nid, epid, ep); e != nil { logrus.Warnf("driver leave failed while rolling back join: %v", e) } } @@ -587,7 +587,7 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) (err error) { } func doUpdateHostsFile(n *network, sb *sandbox) bool { - return !n.ingress && n.Name() != libnGWNetwork + return !n.ingress && n.Name() != n.ctrlr.DefaultGwNetworkName() } func (ep *endpoint) rename(name string) error { @@ -739,7 +739,7 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) } } - if err := d.Leave(n.id, ep.id); err != nil { + if err := d.Leave(n.id, ep.id, ep); err != nil { if _, ok := err.(types.MaskableError); !ok { logrus.Warnf("driver error disconnecting container %s : %v", ep.name, err) } diff --git a/endpoint_info.go b/endpoint_info.go index 68d3e8673d..5ff397b109 100644 --- a/endpoint_info.go +++ b/endpoint_info.go @@ -396,6 +396,75 @@ func (ep *endpoint) DisableGatewayService() { ep.joinInfo.disableGatewayService = true } +func (ep *endpoint) RequestAddress(subnet *net.IPNet) (*net.IPNet, error) { + if subnet == nil || subnet.IP.IsUnspecified() { + return nil, fmt.Errorf("Invalid RequestAddress request") + } + + n, err := ep.getNetworkFromStore() + if err != nil { + return nil, fmt.Errorf("failed to get network during RequestAddress: %v", err) + } + ipam, _, err := n.getController().getIPAMDriver(n.ipamType) + if err != nil { + return nil, err + } + + ipVer := 4 + if subnet.IP.To4() == nil { + ipVer = 6 + } + + ipInfo := n.getIPInfo(ipVer) + + // ipv6 address is not mandatory + if len(ipInfo) == 0 { + return nil, fmt.Errorf("error allocating IP with no IPInfo") + } + + for _, d := range ipInfo { + if !d.Pool.Contains(subnet.IP) { + continue + } + addr, _, err := ipam.RequestAddress(d.PoolID, nil, nil) + if err != nil { + return nil, err + } + return addr, err + } + return nil, fmt.Errorf("Unable to allocate address") +} + +func (ep *endpoint) ReleaseAddress(ip net.IP) error { + n, err := ep.getNetworkFromStore() + if err != nil { + return fmt.Errorf("failed to get network during RequestAddress: %v", err) + } + ipam, _, err := n.getController().getIPAMDriver(n.ipamType) + if err != nil { + return err + } + + ipVer := 4 + if ip.To4() == nil { + ipVer = 6 + } + + ipInfo := n.getIPInfo(ipVer) + + if len(ipInfo) == 0 { + return nil + } + + for _, d := range ipInfo { + if !d.Pool.Contains(ip) { + continue + } + return ipam.ReleaseAddress(d.PoolID, ip) + } + return fmt.Errorf("Unable to release address") +} + func (epj *endpointJoinInfo) MarshalJSON() ([]byte, error) { epMap := make(map[string]interface{}) if epj.gw != nil { diff --git a/install/Dockerfile.cniserver b/install/Dockerfile.cniserver new file mode 100644 index 0000000000..87f07fb2c4 --- /dev/null +++ b/install/Dockerfile.cniserver @@ -0,0 +1,13 @@ +FROM ubuntu:16.04 + +RUN apt-get update \ + && apt-get install -y\ + net-tools \ + iptables \ + && rm -rf /var/lib/apt/lists/* + +COPY bin/cniserver /var/libnetwork/bin/ +COPY cniserver.sh /var/libnetwork/ +COPY bin/cnictl /var/libnetwork/bin/ + +ENTRYPOINT ["/var/libnetwork/cniserver.sh"] diff --git a/install/Dockerfile.dnet b/install/Dockerfile.dnet new file mode 100644 index 0000000000..f0549cc69d --- /dev/null +++ b/install/Dockerfile.dnet @@ -0,0 +1,13 @@ +FROM ubuntu:16.04 + +RUN apt-get update \ + && apt-get install -y\ + net-tools \ + iptables \ + && rm -rf /var/lib/apt/lists/* + +COPY bin/dnet /var/libnetwork/bin/ +COPY dnet.sh /var/libnetwork/ +COPY config.toml /var/libnetwork/config/ + +ENTRYPOINT ["/var/libnetwork/dnet.sh"] diff --git a/install/cniserver.sh b/install/cniserver.sh new file mode 100755 index 0000000000..59f4447b25 --- /dev/null +++ b/install/cniserver.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -euo pipefail +cp /var/libnetwork/bin/cnictl /opt/cni/bin/dnet-cni +echo ${DNET_CNI_CONF} > /etc/cni/net.d/00-dnet-cni.conf + +/var/libnetwork/bin/cniserver &> /home/libnetwork/cniserver.log diff --git a/install/config.toml b/install/config.toml new file mode 100644 index 0000000000..c334c27827 --- /dev/null +++ b/install/config.toml @@ -0,0 +1,11 @@ +title = "LibNetwork Configuration file" + +[daemon] + debug = true + labels = ["com.docker.network.driver.overlay.hostmode=true", "com.docker.network.driver.overlay.vxlan-port=34789", "com.docker.network.driver.overlay.gossip-port=37946"] + defaultGwNetwork = "cni-gwbridge" + DataDir = "/var/run/libnetwork" +[cluster] + discovery = "" +[datastore] + embedded = false diff --git a/install/dnet.sh b/install/dnet.sh new file mode 100755 index 0000000000..b69d68d1a7 --- /dev/null +++ b/install/dnet.sh @@ -0,0 +1,3 @@ +#!/bin/bash +set -euo pipefail +/var/libnetwork/bin/dnet -d -p cni -c /var/libnetwork/config/config.toml &> /home/libnetwork/dnet.log diff --git a/libnetwork_internal_test.go b/libnetwork_internal_test.go index 58742cf5e1..fb61e4fd5b 100644 --- a/libnetwork_internal_test.go +++ b/libnetwork_internal_test.go @@ -653,7 +653,7 @@ func (b *badDriver) EndpointOperInfo(nid, eid string) (map[string]interface{}, e func (b *badDriver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { return fmt.Errorf("I will not allow any join") } -func (b *badDriver) Leave(nid, eid string) error { +func (b *badDriver) Leave(nid, eid string, linfo driverapi.LeaveInfo) error { return nil } func (b *badDriver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { diff --git a/netutils/httputils.go b/netutils/httputils.go new file mode 100644 index 0000000000..0243430ca4 --- /dev/null +++ b/netutils/httputils.go @@ -0,0 +1,102 @@ +package netutils + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" +) + +// HTTPConnection holds the protocol and address info for http connection +type HTTPConnection struct { + // Proto holds the client protocol i.e. unix. + Proto string + // Addr holds the client address. + Addr string +} + +// HTTPCall is used to make a http call using httpconnection information +func (h *HTTPConnection) HTTPCall(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) { + var in io.Reader + in, err := encodeData(data) + if err != nil { + return nil, nil, -1, err + } + + req, err := http.NewRequest(method, fmt.Sprintf("%s", path), in) + if err != nil { + return nil, nil, -1, err + } + + setupRequestHeaders(method, data, req, headers) + + req.URL.Host = h.Addr + req.URL.Scheme = "http" + httpClient := &http.Client{} + resp, err := httpClient.Do(req) + statusCode := -1 + if resp != nil { + statusCode = resp.StatusCode + } + if err != nil { + return nil, nil, statusCode, fmt.Errorf("error when trying to connect: %v", err) + } + + if statusCode < 200 || statusCode >= 400 { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, nil, statusCode, err + } + return nil, nil, statusCode, fmt.Errorf("error : %s", bytes.TrimSpace(body)) + } + + return resp.Body, resp.Header, statusCode, nil +} + +func setupRequestHeaders(method string, data interface{}, req *http.Request, headers map[string][]string) { + if data != nil { + if headers == nil { + headers = make(map[string][]string) + } + headers["Content-Type"] = []string{"application/json"} + } + + expectedPayload := (method == "POST" || method == "PUT") + + if expectedPayload && req.Header.Get("Content-Type") == "" { + req.Header.Set("Content-Type", "text/plain") + } + + if headers != nil { + for k, v := range headers { + req.Header[k] = v + } + } +} + +func encodeData(data interface{}) (*bytes.Buffer, error) { + params := bytes.NewBuffer(nil) + if data != nil { + if err := json.NewEncoder(params).Encode(data); err != nil { + return nil, err + } + } + return params, nil +} + +// ReadBody reads http body from stream +func ReadBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) { + if stream != nil { + defer stream.Close() + } + if err != nil { + return nil, statusCode, err + } + body, err := ioutil.ReadAll(stream) + if err != nil { + return nil, -1, err + } + return body, statusCode, nil +} diff --git a/provider/cni/cniapi/api.go b/provider/cni/cniapi/api.go new file mode 100644 index 0000000000..22950861e7 --- /dev/null +++ b/provider/cni/cniapi/api.go @@ -0,0 +1,239 @@ +package cniapi + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net" + "net/http" + "strings" + + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types/current" + "github.com/containernetworking/plugins/pkg/ns" + log "github.com/sirupsen/logrus" + + "github.com/docker/libnetwork" + "github.com/docker/libnetwork/api" +) + +const ( + // AddWorkloadURL url endpoint to add workload + AddWorkloadURL = "/AddWorkload" + // DelWorkloadURL url endpoint to delete workload + DelWorkloadURL = "/DelWorkload" + // GetActiveWorkloads url endpoint to fetch active workload sandboxes + GetActiveWorkloads = "/ActiveWorkloads" + // DnetCNISock is dnet cni sidecar sock file + DnetCNISock = "/var/run/cniserver.sock" +) + +// DnetCniClient is the cni client connection information +type DnetCniClient struct { + url string + httpClient *http.Client +} + +// NetworkConf is the cni network configuration information +type NetworkConf struct { + CNIVersion string `json:"cniVersion,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Capabilities map[string]bool `json:"capabilities,omitempty"` + IPAM *IPAMConf `json:"ipam,omitempty"` + DNS types.DNS `json:"dns"` +} + +// IPAMConf is the cni network IPAM configuration information +type IPAMConf struct { + Type string `json:"type,omitempty"` + PreferredPool string `json:"preferred-pool,omitempty"` + SubPool string `json:"sub-pool,omitempty"` + Gateway string `json:"gateway,omitempty"` +} + +// CniInfo represents the cni information for a cni transaction +type CniInfo struct { + ContainerID string + NetNS string + IfName string + NetConf NetworkConf + Metadata map[string]string +} + +func unixDial(proto, addr string) (conn net.Conn, err error) { + sock := DnetCNISock + return net.Dial("unix", sock) +} + +// NewDnetCniClient returns a well formed cni client +func NewDnetCniClient() *DnetCniClient { + c := new(DnetCniClient) + c.url = "http://localhost" + c.httpClient = &http.Client{ + Transport: &http.Transport{ + Dial: unixDial, + }, + } + return c +} + +// AddWorkload setups up the sandbox and endpoint for the infra container in a workload +func (l *DnetCniClient) AddWorkload(args *skel.CmdArgs) (*current.Result, error) { + var data current.Result + log.Infof("Sending add workload request %+v", args) + workloadNetInfo, err := validateWorkloadNetworkInfo(args, true) + if err != nil { + return nil, fmt.Errorf("failed to valid cni arguments, error: %v", err) + } + buf, err := json.Marshal(workloadNetInfo) + if err != nil { + return nil, err + } + body := bytes.NewBuffer(buf) + url := l.url + AddWorkloadURL + r, err := l.httpClient.Post(url, "application/json", body) + if err != nil { + return nil, err + } + defer r.Body.Close() + switch { + case r.StatusCode == int(404): + return nil, fmt.Errorf("page not found") + + case r.StatusCode == int(403): + return nil, fmt.Errorf("access denied") + + case r.StatusCode == int(500): + info, err := ioutil.ReadAll(r.Body) + if err != nil { + return nil, err + } + err = json.Unmarshal(info, &data) + if err != nil { + return nil, err + } + return &data, fmt.Errorf("Internal Server Error") + + case r.StatusCode != int(200): + log.Errorf("POST Status '%s' status code %d \n", r.Status, r.StatusCode) + return nil, fmt.Errorf("%s", r.Status) + } + + response, err := ioutil.ReadAll(r.Body) + if err != nil { + return nil, err + } + + err = json.Unmarshal(response, &data) + if err != nil { + return nil, err + } + return &data, nil +} + +// DeleteWorkload tears the sandbox and endpoint created for the workload. +func (l *DnetCniClient) DeleteWorkload(args *skel.CmdArgs) error { + log.Infof("Sending delete Workload request %+v", args) + workloadNetInfo, err := validateWorkloadNetworkInfo(args, false) + if err != nil { + return fmt.Errorf("failed to validate cni arguments, error: %v", err) + } + buf, err := json.Marshal(workloadNetInfo) + if err != nil { + return err + } + body := bytes.NewBuffer(buf) + url := l.url + DelWorkloadURL + r, err := l.httpClient.Post(url, "application/json", body) + if err != nil { + return err + } + defer r.Body.Close() + return nil +} + +// FetchActiveSandboxes returns a list of active workloads and their sandboxIDs +func (l *DnetCniClient) FetchActiveSandboxes() (map[string]interface{}, error) { + log.Infof("Requesting for for active sandboxes") + var sandboxes map[string]api.SandboxMetadata + url := l.url + GetActiveWorkloads + r, err := l.httpClient.Get(url) + if err != nil { + return nil, fmt.Errorf("failed during http get :%v", err) + } + defer r.Body.Close() + response, err := ioutil.ReadAll(r.Body) + if err != nil { + return nil, err + } + err = json.Unmarshal(response, &sandboxes) + if err != nil { + return nil, fmt.Errorf("failed to decode http response: %v", err) + } + result := make(map[string]interface{}) + for sb, meta := range sandboxes { + result[sb] = parseConfigOptions(meta) + } + return result, nil +} + +func parseConfigOptions(meta api.SandboxMetadata) []libnetwork.SandboxOption { + var sbOptions []libnetwork.SandboxOption + if meta.UseExternalKey { + sbOptions = append(sbOptions, libnetwork.OptionUseExternalKey()) + } + if meta.ExternalKey != "" { + sbOptions = append(sbOptions, libnetwork.OptionExternalKey(meta.ExternalKey)) + } + return sbOptions +} + +func validateWorkloadNetworkInfo(args *skel.CmdArgs, add bool) (*CniInfo, error) { + rt := new(CniInfo) + if args.ContainerID == "" { + return nil, fmt.Errorf("containerID empty") + } + rt.ContainerID = args.ContainerID + if add { + if args.Netns == "" { + return nil, fmt.Errorf("network namespace not present") + } + _, err := ns.GetNS(args.Netns) + if err != nil { + return nil, err + } + rt.NetNS = args.Netns + } + if args.IfName == "" { + rt.IfName = "eth1" + } else { + rt.IfName = args.IfName + } + var netConf struct { + NetworkConf + } + if err := json.Unmarshal(args.StdinData, &netConf); err != nil { + return nil, fmt.Errorf("failed to unmarshal network configuration :%v", err) + } + rt.NetConf = netConf.NetworkConf + if args.Args != "" { + rt.Metadata = getMetadataFromArgs(args.Args) + } + return rt, nil +} + +func getMetadataFromArgs(args string) map[string]string { + m := make(map[string]string) + for _, a := range strings.Split(args, ";") { + if strings.Contains(a, "=") { + kvPair := strings.Split(a, "=") + m[strings.TrimSpace(kvPair[0])] = strings.TrimSpace(kvPair[1]) + } else { + m[a] = "" + } + } + return m +} diff --git a/provider/cni/server/add_workload.go b/provider/cni/server/add_workload.go new file mode 100644 index 0000000000..de687d9f5c --- /dev/null +++ b/provider/cni/server/add_workload.go @@ -0,0 +1,56 @@ +package server + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net" + "net/http" + "reflect" + + "github.com/containernetworking/cni/pkg/types/current" + log "github.com/sirupsen/logrus" + + "github.com/docker/libnetwork/provider/cni" + "github.com/docker/libnetwork/provider/cni/cniapi" +) + +func addWorkload(w http.ResponseWriter, r *http.Request, c cni.Service, vars map[string]string) (_ interface{}, retErr error) { + cniInfo := cniapi.CniInfo{} + var result current.Result + + content, err := ioutil.ReadAll(r.Body) + if err != nil { + log.Errorf("Failed to read request: %v", err) + return cniInfo, err + } + + if err := json.Unmarshal(content, &cniInfo); err != nil { + return cniInfo, err + } + + log.Infof("Received add workload request %+v", cniInfo) + ep, err := c.SetupWorkload(cniInfo) + if err != nil { + return nil, fmt.Errorf("failed to setup workload: %v", err) + } + result.Interfaces = append(result.Interfaces, ¤t.Interface{Name: "eth1", Mac: ep.MacAddress.String()}) + if !reflect.DeepEqual(ep.Address, (net.IPNet{})) { + result.IPs = append(result.IPs, ¤t.IPConfig{ + Version: "4", + Address: ep.Address, + Gateway: ep.Gateway, + }) + } + if !reflect.DeepEqual(ep.AddressIPv6, (net.IPNet{})) { + result.IPs = append(result.IPs, ¤t.IPConfig{ + Version: "6", + Address: ep.AddressIPv6, + Gateway: ep.GatewayIPv6, + }) + } + //TODO : Point IPs to the interface index + + return result, err + +} diff --git a/provider/cni/server/cni_server.go b/provider/cni/server/cni_server.go new file mode 100644 index 0000000000..2692dcb954 --- /dev/null +++ b/provider/cni/server/cni_server.go @@ -0,0 +1,324 @@ +package server + +import ( + "encoding/json" + "fmt" + "net" + "net/http" + "strings" + "syscall" + "time" + + "github.com/docker/libkv/store" + "github.com/docker/libkv/store/boltdb" + "github.com/gorilla/mux" + log "github.com/sirupsen/logrus" + + "github.com/docker/libnetwork/client" + "github.com/docker/libnetwork/datastore" + "github.com/docker/libnetwork/netutils" + "github.com/docker/libnetwork/provider/cni/cniapi" + cnistore "github.com/docker/libnetwork/provider/cni/store" + "github.com/docker/libnetwork/types" +) + +// CniService hold the cni service information +type CniService struct { + listenPath string + dnetConn *netutils.HTTPConnection + store datastore.DataStore +} + +var dnetConn *netutils.HTTPConnection + +// NewCniService returns a new cni service instance +func NewCniService(sock string, dnetIP string, dnetPort string) (*CniService, error) { + dnetURL := dnetIP + ":" + dnetPort + c := new(CniService) + dnetConn = &netutils.HTTPConnection{Addr: dnetURL, Proto: "tcp"} + c.listenPath = sock + return c, nil +} + +// Init initializes the cni server +func (c *CniService) Init(serverCloseChan chan struct{}) error { + log.Infof("Starting CNI server") + router := mux.NewRouter() + t := router.Methods("POST").Subrouter() + t.HandleFunc(cniapi.AddWorkloadURL, MakeHTTPHandler(c, addWorkload)) + t.HandleFunc(cniapi.DelWorkloadURL, MakeHTTPHandler(c, deleteWorkload)) + + syscall.Unlink(c.listenPath) + boltdb.Register() + store, err := localStore() + if err != nil { + return fmt.Errorf("failed to initialize local store: %v", err) + } + c.store = store + go func() { + l, err := net.ListenUnix("unix", &net.UnixAddr{Name: c.listenPath, Net: "unix"}) + if err != nil { + panic(err) + } + log.Infof("Dnet CNI plugin listening on on %s", c.listenPath) + http.Serve(l, router) + l.Close() + close(serverCloseChan) + }() + return nil +} + +// SetupWorkload sets up the network for the workload +func (c *CniService) SetupWorkload(cniInfo cniapi.CniInfo) ( + ep client.EndpointInfo, + retErr error, +) { + // Create a Sandbox + sbConfig, sbID, err := createSandbox(cniInfo.ContainerID) + if err != nil { + return ep, fmt.Errorf("failed to create sandbox for %q: %v", cniInfo.ContainerID, err) + } + defer func() { + if retErr != nil { + if err := deleteSandbox(sbID); err != nil { + log.Warnf("failed to delete sandbox %v on setup pod failure , error:%v", sbID, err) + } + } + }() + + // Create an Endpoint + ep, err = createEndpoint(cniInfo.ContainerID, cniInfo.NetConf) + if err != nil { + return ep, fmt.Errorf("failed to create endpoint for %q: %v", cniInfo.ContainerID, err) + } + defer func() { + if retErr != nil { + if err := deleteEndpoint(ep.ID); err != nil { + log.Warnf("failed to delete endpoint %v on setup pod failure , error:%v", ep.ID, err) + } + } + }() + + // Attach endpoint to the sandbox + if err = endpointJoin(sbID, ep.ID, cniInfo.NetNS); err != nil { + return ep, fmt.Errorf("failed to attach endpoint to sandbox for container:%q,sandbox:%q,endpoint:%q, error:%v", cniInfo.ContainerID, sbID, ep.ID, err) + } + defer func() { + if retErr != nil { + if err = endpointLeave(sbID, ep.ID); err != nil { + log.Warnf("failed to detach endpoint %q from sandbox %q , err:%v", ep.ID, sbID, err) + } + } + }() + + if err := c.putMetadataToStore(cniInfo, sbID, ep.ID, sbConfig); err != nil { + return ep, fmt.Errorf("failed put metadata to store: %v", err) + } + return ep, nil +} + +// TearDownWorkload tears the networking of the workload +func (c *CniService) TearDownWorkload(cniInfo cniapi.CniInfo) error { + cniMetadata, err := c.getMetadataFromStore(cniInfo) + if err != nil { + log.Errorf("cni workload data not found in plugin store: %v", err) + // If its not found in store we do not have information regarding this workload. + // We just return nil. TODO : figure out an alternative if this causes unwanted + // issues + return nil + } + sbID := cniMetadata.SandboxID + epID := cniMetadata.EndpointID + + if err = endpointLeave(sbID, epID); err != nil { + return fmt.Errorf("failed to leave endpoint from sandbox for container:%q,sandbox:%q,endpoint:%q, error:%v", cniInfo.ContainerID, sbID, epID, err) + } + + if err = deleteEndpoint(epID); err != nil { + return fmt.Errorf("failed to delete endpoint %q for container %q,, error:%v", + epID, cniInfo.ContainerID, err) + } + + if err = deleteSandbox(sbID); err != nil { + return fmt.Errorf("failed to delete sandbox %q for container %q, error:%v", sbID, cniInfo.ContainerID, err) + } + + return c.deleteMetadataFromStore(cniMetadata) +} + +func (c *CniService) putMetadataToStore(cniInfo cniapi.CniInfo, + sbID, + epID string, + sbConfig client.SandboxCreate, +) error { + var err error + cs := &cnistore.CniMetadata{ + ContainerID: cniInfo.ContainerID, + SandboxID: sbID, + EndpointID: epID, + SandboxMeta: copySandboxMetadata(sbConfig, cniInfo.NetNS), + } + store := c.getstore() + if store == nil { + return nil + } + if err = store.PutObjectAtomic(cs); err == datastore.ErrKeyModified { + return types.RetryErrorf("failed to perform atomic write (%v). retry might fix the error", err) + } + + return err +} + +func (c *CniService) deleteMetadataFromStore(cs *cnistore.CniMetadata) error { + store := c.getstore() + if store == nil { + return nil + } + return store.DeleteObjectAtomic(cs) +} + +func (c *CniService) getMetadataFromStore(cniInfo cniapi.CniInfo) (*cnistore.CniMetadata, error) { + store := c.getstore() + if store == nil { + return nil, nil + } + cs := &cnistore.CniMetadata{ContainerID: cniInfo.ContainerID} + if err := store.GetObject(datastore.Key(cs.Key()...), cs); err != nil { + if err == datastore.ErrKeyNotFound { + return nil, fmt.Errorf("failed to find cni metadata from store for %s workload %s", + cniInfo.ContainerID, err) + } + return nil, types.InternalErrorf("could not get pools config from store: %v", err) + } + return cs, nil +} + +func localStore() (datastore.DataStore, error) { + return datastore.NewDataStore(datastore.LocalScope, &datastore.ScopeCfg{ + Client: datastore.ScopeClientCfg{ + Provider: string(store.BOLTDB), + Address: "/var/run/libnetwork/cnidb.db", + Config: &store.Config{ + Bucket: "cni-dnet", + ConnectionTimeout: 5 * time.Second, + }, + }, + }) +} + +// getstore returns store instance +func (c *CniService) getstore() datastore.DataStore { + return c.store +} + +func createSandbox(ContainerID string) (client.SandboxCreate, string, error) { + sc := client.SandboxCreate{ContainerID: ContainerID, UseExternalKey: true} + obj, _, err := netutils.ReadBody(dnetConn.HTTPCall("POST", "/sandboxes", sc, nil)) + if err != nil { + return client.SandboxCreate{}, "", err + } + + var replyID string + err = json.Unmarshal(obj, &replyID) + if err != nil { + return client.SandboxCreate{}, "", err + } + return sc, replyID, nil +} + +func createEndpoint(ContainerID string, netConfig cniapi.NetworkConf) (client.EndpointInfo, error) { + var ep client.EndpointInfo + // Create network if it doesnt exist. Need to handle refcount to delete + // network on last workload delete. + if !networkExists(netConfig.Name) { + if err := createNetwork(netConfig); err != nil && !strings.Contains(err.Error(), "already exists") { + return ep, err + } + } + + sc := client.ServiceCreate{Name: ContainerID, Network: netConfig.Name, DisableResolution: true} + obj, _, err := netutils.ReadBody(dnetConn.HTTPCall("POST", "/services", sc, nil)) + if err != nil { + return ep, err + } + err = json.Unmarshal(obj, &ep) + return ep, err +} + +func endpointJoin(sandboxID, endpointID, netns string) (retErr error) { + nc := client.ServiceAttach{SandboxID: sandboxID, SandboxKey: netns} + _, _, err := netutils.ReadBody(dnetConn.HTTPCall("POST", "/services/"+endpointID+"/backend", nc, nil)) + return err +} + +func networkExists(networkID string) bool { + obj, statusCode, err := netutils.ReadBody(dnetConn.HTTPCall("GET", "/networks?partial-id="+networkID, nil, nil)) + if err != nil { + log.Debugf("%s network does not exist:%v \n", networkID, err) + return false + } + if statusCode != http.StatusOK { + log.Debugf("%s network does not exist \n", networkID) + return false + } + var list []*client.NetworkResource + err = json.Unmarshal(obj, &list) + if err != nil { + return false + } + return (len(list) != 0) +} + +// createNetwork is a very simple utility to create a default network +// if not present. +//TODO: Need to watch out for parallel createnetwork calls on multiple nodes +func createNetwork(netConf cniapi.NetworkConf) error { + log.Infof("Creating network %+v \n", netConf) + driverOpts := make(map[string]string) + driverOpts["hostaccess"] = "" + nc := client.NetworkCreate{Name: netConf.Name, ID: netConf.Name, NetworkType: getNetworkType(netConf.Name), + DriverOpts: driverOpts} + if ipam := netConf.IPAM; ipam != nil { + cfg := client.IPAMConf{} + if ipam.PreferredPool != "" { + cfg.PreferredPool = ipam.PreferredPool + } + if ipam.SubPool != "" { + cfg.SubPool = ipam.SubPool + } + if ipam.Gateway != "" { + cfg.Gateway = ipam.Gateway + } + nc.IPv4Conf = []client.IPAMConf{cfg} + } + obj, _, err := netutils.ReadBody(dnetConn.HTTPCall("POST", "/networks", nc, nil)) + if err != nil { + return err + } + var replyID string + err = json.Unmarshal(obj, &replyID) + if err != nil { + return err + } + fmt.Printf("Network creation succeeded: %v", replyID) + return nil +} + +func endpointLeave(sandboxID, endpointID string) error { + log.Infof("Sending EndpointLeave for endpoint %s , sandbox:%s \n", endpointID, sandboxID) + _, _, err := netutils.ReadBody(dnetConn.HTTPCall("DELETE", "/services/"+endpointID+"/backend/"+sandboxID, nil, nil)) + return err +} + +func deleteSandbox(sandboxID string) error { + log.Infof("Sending deleteSandbox sandbox:%s \n", sandboxID) + _, _, err := netutils.ReadBody(dnetConn.HTTPCall("DELETE", "/sandboxes/"+sandboxID, nil, nil)) + return err +} + +func deleteEndpoint(endpointID string) error { + log.Infof("Sending deleteEndpoint for endpoint %s \n", endpointID) + sd := client.ServiceDelete{Name: endpointID, Force: true} + _, _, err := netutils.ReadBody(dnetConn.HTTPCall("DELETE", "/services/"+endpointID, sd, nil)) + return err +} diff --git a/provider/cni/server/cni_utils.go b/provider/cni/server/cni_utils.go new file mode 100644 index 0000000000..96e7cda9d7 --- /dev/null +++ b/provider/cni/server/cni_utils.go @@ -0,0 +1,91 @@ +package server + +import ( + "encoding/json" + "net/http" + + "github.com/gorilla/mux" + log "github.com/sirupsen/logrus" + + "github.com/docker/libnetwork/api" + "github.com/docker/libnetwork/client" + "github.com/docker/libnetwork/provider/cni" +) + +type httpAPIFunc func(w http.ResponseWriter, + r *http.Request, + c cni.Service, + vars map[string]string, +) (interface{}, error) + +// MakeHTTPHandler is a simple Wrapper for http handlers +func MakeHTTPHandler(c cni.Service, handlerFunc httpAPIFunc) http.HandlerFunc { + // Create a closure and return an anonymous function + return func(w http.ResponseWriter, r *http.Request) { + // Call the handler + resp, err := handlerFunc(w, r, c, mux.Vars(r)) + if err != nil { + // Log error + log.Errorf("Handler for %s %s returned error: %s", r.Method, r.URL, err) + if resp == nil { + // Send HTTP response + http.Error(w, err.Error(), http.StatusInternalServerError) + } else { + // Send HTTP response as Json + content, err := json.Marshal(resp) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusInternalServerError) + w.Write(content) + } + } else { + // Send HTTP response as Json + err = writeJSON(w, http.StatusOK, resp) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + } + } +} + +func writeJSON(w http.ResponseWriter, code int, v interface{}) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(code) + return json.NewEncoder(w).Encode(v) +} + +// CopySandboxMetadata creates a sandbox metadata +func copySandboxMetadata(sbConfig client.SandboxCreate, externalKey string) api.SandboxMetadata { + var meta api.SandboxMetadata + meta.ContainerID = sbConfig.ContainerID + meta.HostName = sbConfig.HostName + meta.DomainName = sbConfig.DomainName + meta.HostsPath = sbConfig.HostsPath + meta.ResolvConfPath = sbConfig.ResolvConfPath + meta.DNS = sbConfig.DNS + meta.UseExternalKey = sbConfig.UseExternalKey + meta.UseDefaultSandbox = sbConfig.UseDefaultSandbox + meta.ExposedPorts = sbConfig.ExposedPorts + meta.PortMapping = sbConfig.PortMapping + meta.ExternalKey = externalKey + //TODO: skipped extrahosts + return meta +} + +func getNetworkType(networkType string) string { + switch networkType { + case "dnet-overlay-net": + return "overlay" + case "dnet-bridge-net": + return "bridge" + case "dnet-ipvlan-net": + return "ipvlan" + case "dnet-macvlan-net": + return "macvlan" + default: + return "overlay" + } +} diff --git a/provider/cni/server/del_workload.go b/provider/cni/server/del_workload.go new file mode 100644 index 0000000000..cb386e518a --- /dev/null +++ b/provider/cni/server/del_workload.go @@ -0,0 +1,32 @@ +package server + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + "github.com/sirupsen/logrus" + + "github.com/docker/libnetwork/provider/cni" + "github.com/docker/libnetwork/provider/cni/cniapi" +) + +func deleteWorkload(w http.ResponseWriter, r *http.Request, c cni.Service, vars map[string]string) (interface{}, error) { + //TODO: need to explore force cleanup and test for parallel delete workloads + cniInfo := cniapi.CniInfo{} + + content, err := ioutil.ReadAll(r.Body) + if err != nil { + return nil, fmt.Errorf("failed to read request: %v", err) + } + + if err = json.Unmarshal(content, &cniInfo); err != nil { + return nil, err + } + logrus.Infof("Received delete workload request %+v", cniInfo) + if err := c.TearDownWorkload(cniInfo); err != nil { + return nil, err + } + return nil, nil +} diff --git a/provider/cni/service.go b/provider/cni/service.go new file mode 100644 index 0000000000..dd6b15218f --- /dev/null +++ b/provider/cni/service.go @@ -0,0 +1,16 @@ +package cni + +import ( + "github.com/docker/libnetwork/client" + "github.com/docker/libnetwork/provider/cni/cniapi" +) + +// Service interface for Cni service implementations +type Service interface { + // Init initializes the cni server + Init(serverCloseChan chan struct{}) error + // SetupWorkload setups the CNI workload networking + SetupWorkload(cniapi.CniInfo) (client.EndpointInfo, error) + // TearDownWorkload tears down the CNI workload networking + TearDownWorkload(cniapi.CniInfo) error +} diff --git a/provider/cni/store/cni_store.go b/provider/cni/store/cni_store.go new file mode 100644 index 0000000000..5f9df082a1 --- /dev/null +++ b/provider/cni/store/cni_store.go @@ -0,0 +1,91 @@ +package store + +import ( + "encoding/json" + + "github.com/docker/libnetwork/api" + "github.com/docker/libnetwork/datastore" + "github.com/sirupsen/logrus" +) + +const ( + cniPrefix = "cni" +) + +// CniMetadata holds the cni metadata information for a workload +type CniMetadata struct { + ContainerID string + SandboxID string + EndpointID string + SandboxMeta api.SandboxMetadata + dbIndex uint64 + dbExists bool +} + +// Key provides the Key to be used in KV Store +func (cs *CniMetadata) Key() []string { + return []string{cniPrefix, cs.ContainerID} +} + +// KeyPrefix returns the immediate parent key that can be used for tree walk +func (cs *CniMetadata) KeyPrefix() []string { + return []string{cniPrefix} +} + +// Value marshals the data to be stored in the KV store +func (cs *CniMetadata) Value() []byte { + b, err := json.Marshal(cs) + if err != nil { + logrus.Warnf("failed to marshal cni store: %v", err) + return nil + } + return b +} + +// SetValue unmarshalls the data from the KV store. +func (cs *CniMetadata) SetValue(value []byte) error { + return json.Unmarshal(value, cs) +} + +// Index returns the latest DB Index as seen by this object +func (cs *CniMetadata) Index() uint64 { + return cs.dbIndex +} + +// SetIndex method allows the datastore to store the latest DB Index into this object +func (cs *CniMetadata) SetIndex(index uint64) { + cs.dbIndex = index + cs.dbExists = true +} + +// Exists method is true if this object has been stored in the DB. +func (cs *CniMetadata) Exists() bool { + return cs.dbExists +} + +// Skip provides a way for a KV Object to avoid persisting it in the KV Store +func (cs *CniMetadata) Skip() bool { + return false +} + +// New returns a new cnimetada KVObjects +func (cs *CniMetadata) New() datastore.KVObject { + return &CniMetadata{} +} + +// CopyTo copy from source to destination KBObject +func (cs *CniMetadata) CopyTo(o datastore.KVObject) error { + dstCs := o.(*CniMetadata) + dstCs.ContainerID = cs.ContainerID + dstCs.SandboxID = cs.SandboxID + dstCs.EndpointID = cs.EndpointID + dstCs.SandboxMeta = cs.SandboxMeta + dstCs.dbIndex = cs.dbIndex + dstCs.dbExists = cs.dbExists + return nil +} + +// DataScope method returns the storage scope of the datastore +func (cs *CniMetadata) DataScope() string { + return datastore.LocalScope +} diff --git a/provider/provider.go b/provider/provider.go new file mode 100644 index 0000000000..8bf7f2291b --- /dev/null +++ b/provider/provider.go @@ -0,0 +1,10 @@ +package provider + +// DnetProvider is entity that runs on top of dnet. For eg cni +// TODO: This interface may be removed/expanded depending on the push/pull +// model we might adopt. +type DnetProvider interface { + // FetchActiveSandboxes fetches the active sandboxes as map + // of sandbox IDs and sandbox options + FetchActiveSandboxes() (map[string]interface{}, error) +} diff --git a/sandbox.go b/sandbox.go index 315195ebb8..db3e15532e 100644 --- a/sandbox.go +++ b/sandbox.go @@ -128,6 +128,7 @@ type containerConfig struct { generic map[string]interface{} useDefaultSandBox bool useExternalKey bool + externalKey string prio int // higher the value, more the priority exposedPorts []types.TransportPort } @@ -650,6 +651,7 @@ func (sb *sandbox) SetKey(basePath string) error { sb.Lock() sb.osSbox = osSbox + sb.config.externalKey = basePath sb.Unlock() // If the resolver was setup before stop it and set it up in the @@ -1096,6 +1098,14 @@ func OptionUseExternalKey() SandboxOption { } } +// OptionExternalKey function returns an option setter for using external key namespace +// instead of creating one. +func OptionExternalKey(key string) SandboxOption { + return func(sb *sandbox) { + sb.config.externalKey = key + } +} + // OptionGeneric function returns an option setter for Generic configuration // that is not managed by libNetwork but can be used by the Drivers during the call to // net container creation method. Container Labels are a good example. diff --git a/sandbox_store.go b/sandbox_store.go index a083644598..bf3b01d9f1 100644 --- a/sandbox_store.go +++ b/sandbox_store.go @@ -210,7 +210,6 @@ func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) { for _, kvo := range kvol { sbs := kvo.(*sbState) - sb := &sandbox{ id: sbs.ID, controller: sbs.c, @@ -244,10 +243,19 @@ func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) { create = !sb.config.useDefaultSandBox heap.Init(&sb.endpoints) } - sb.osSbox, err = osl.NewSandbox(sb.Key(), create, isRestore) - if err != nil { - logrus.Errorf("failed to create osl sandbox while trying to restore sandbox %s%s: %v", sb.ID()[0:7], msg, err) - continue + logrus.Debugf("Sandbox restore isRestore:%+v Key:%v,create:%v", isRestore, sb.Key(), create) + if sb.config.useExternalKey { + sb.osSbox, err = osl.GetSandboxForExternalKey(sb.config.externalKey, sb.Key()) + if err != nil { + logrus.Errorf("failed to get sandbox for external key: %v", err) + } + } else { + osSbox, err := osl.NewSandbox(sb.Key(), create, isRestore) + if err != nil { + logrus.Errorf("failed to create osl sandbox while trying to restore sandbox %s%s: %v", sb.ID()[0:7], msg, err) + continue + } + sb.osSbox = osSbox } c.Lock() diff --git a/test/integration/dnet/helpers.bash b/test/integration/dnet/helpers.bash index 8424cae7e2..24783a9682 100644 --- a/test/integration/dnet/helpers.bash +++ b/test/integration/dnet/helpers.bash @@ -127,7 +127,7 @@ function start_dnet() { name=$(dnet_container_name ${inst} ${store}) hport=$((41000+${inst}-1)) - cport=2385 + cport=2389 hopt="" while [ -n "$1" ] diff --git a/vendor.conf b/vendor.conf index c97f5517df..d531359cd4 100644 --- a/vendor.conf +++ b/vendor.conf @@ -9,7 +9,8 @@ github.com/codegangsta/cli a65b733b303f0055f8d324d805f393cd3e7a7904 github.com/coreos/etcd 925d1d74cec8c3b169c52fd4b2dc234a35934fce github.com/coreos/go-systemd b4a58d95188dd092ae20072bac14cece0e67c388 github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d - +github.com/containernetworking/cni v0.6.0 +github.com/containernetworking/plugins v0.6.0 github.com/docker/docker 2cac43e3573893cf8fd816e0ad5615426acb87f4 https://github.com/dmcgowan/docker.git github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 @@ -42,3 +43,4 @@ github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 golang.org/x/net c427ad74c6d7a814201695e9ffde0c5d400a7674 golang.org/x/sys 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9 github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 +github.com/davecgh/go-spew dce690a33ebe33040a7a2ffeb96dd200060f3fca diff --git a/vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go deleted file mode 100644 index 82393ca367..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/mksyscall_windows.go +++ /dev/null @@ -1,934 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -mksyscall_windows generates windows system call bodies - -It parses all files specified on command line containing function -prototypes (like syscall_windows.go) and prints system call bodies -to standard output. - -The prototypes are marked by lines beginning with "//sys" and read -like func declarations if //sys is replaced by func, but: - -* The parameter lists must give a name for each argument. This - includes return parameters. - -* The parameter lists must give a type for each argument: - the (x, y, z int) shorthand is not allowed. - -* If the return parameter is an error number, it must be named err. - -* If go func name needs to be different from it's winapi dll name, - the winapi name could be specified at the end, after "=" sign, like - //sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA - -* Each function that returns err needs to supply a condition, that - return value of winapi will be tested against to detect failure. - This would set err to windows "last-error", otherwise it will be nil. - The value can be provided at end of //sys declaration, like - //sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA - and is [failretval==0] by default. - -Usage: - mksyscall_windows [flags] [path ...] - -The flags are: - -output - Specify output file name (outputs to console if blank). - -trace - Generate print statement after every syscall. -*/ -package main - -import ( - "bufio" - "bytes" - "errors" - "flag" - "fmt" - "go/format" - "go/parser" - "go/token" - "io" - "io/ioutil" - "log" - "os" - "path/filepath" - "runtime" - "sort" - "strconv" - "strings" - "text/template" -) - -var ( - filename = flag.String("output", "", "output file name (standard output if omitted)") - printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall") - systemDLL = flag.Bool("systemdll", true, "whether all DLLs should be loaded from the Windows system directory") -) - -func trim(s string) string { - return strings.Trim(s, " \t") -} - -var packageName string - -func packagename() string { - return packageName -} - -func syscalldot() string { - if packageName == "syscall" { - return "" - } - return "syscall." -} - -// Param is function parameter -type Param struct { - Name string - Type string - fn *Fn - tmpVarIdx int -} - -// tmpVar returns temp variable name that will be used to represent p during syscall. -func (p *Param) tmpVar() string { - if p.tmpVarIdx < 0 { - p.tmpVarIdx = p.fn.curTmpVarIdx - p.fn.curTmpVarIdx++ - } - return fmt.Sprintf("_p%d", p.tmpVarIdx) -} - -// BoolTmpVarCode returns source code for bool temp variable. -func (p *Param) BoolTmpVarCode() string { - const code = `var %s uint32 - if %s { - %s = 1 - } else { - %s = 0 - }` - tmp := p.tmpVar() - return fmt.Sprintf(code, tmp, p.Name, tmp, tmp) -} - -// SliceTmpVarCode returns source code for slice temp variable. -func (p *Param) SliceTmpVarCode() string { - const code = `var %s *%s - if len(%s) > 0 { - %s = &%s[0] - }` - tmp := p.tmpVar() - return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name) -} - -// StringTmpVarCode returns source code for string temp variable. -func (p *Param) StringTmpVarCode() string { - errvar := p.fn.Rets.ErrorVarName() - if errvar == "" { - errvar = "_" - } - tmp := p.tmpVar() - const code = `var %s %s - %s, %s = %s(%s)` - s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name) - if errvar == "-" { - return s - } - const morecode = ` - if %s != nil { - return - }` - return s + fmt.Sprintf(morecode, errvar) -} - -// TmpVarCode returns source code for temp variable. -func (p *Param) TmpVarCode() string { - switch { - case p.Type == "bool": - return p.BoolTmpVarCode() - case strings.HasPrefix(p.Type, "[]"): - return p.SliceTmpVarCode() - default: - return "" - } -} - -// TmpVarHelperCode returns source code for helper's temp variable. -func (p *Param) TmpVarHelperCode() string { - if p.Type != "string" { - return "" - } - return p.StringTmpVarCode() -} - -// SyscallArgList returns source code fragments representing p parameter -// in syscall. Slices are translated into 2 syscall parameters: pointer to -// the first element and length. -func (p *Param) SyscallArgList() []string { - t := p.HelperType() - var s string - switch { - case t[0] == '*': - s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name) - case t == "bool": - s = p.tmpVar() - case strings.HasPrefix(t, "[]"): - return []string{ - fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()), - fmt.Sprintf("uintptr(len(%s))", p.Name), - } - default: - s = p.Name - } - return []string{fmt.Sprintf("uintptr(%s)", s)} -} - -// IsError determines if p parameter is used to return error. -func (p *Param) IsError() bool { - return p.Name == "err" && p.Type == "error" -} - -// HelperType returns type of parameter p used in helper function. -func (p *Param) HelperType() string { - if p.Type == "string" { - return p.fn.StrconvType() - } - return p.Type -} - -// join concatenates parameters ps into a string with sep separator. -// Each parameter is converted into string by applying fn to it -// before conversion. -func join(ps []*Param, fn func(*Param) string, sep string) string { - if len(ps) == 0 { - return "" - } - a := make([]string, 0) - for _, p := range ps { - a = append(a, fn(p)) - } - return strings.Join(a, sep) -} - -// Rets describes function return parameters. -type Rets struct { - Name string - Type string - ReturnsError bool - FailCond string -} - -// ErrorVarName returns error variable name for r. -func (r *Rets) ErrorVarName() string { - if r.ReturnsError { - return "err" - } - if r.Type == "error" { - return r.Name - } - return "" -} - -// ToParams converts r into slice of *Param. -func (r *Rets) ToParams() []*Param { - ps := make([]*Param, 0) - if len(r.Name) > 0 { - ps = append(ps, &Param{Name: r.Name, Type: r.Type}) - } - if r.ReturnsError { - ps = append(ps, &Param{Name: "err", Type: "error"}) - } - return ps -} - -// List returns source code of syscall return parameters. -func (r *Rets) List() string { - s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ") - if len(s) > 0 { - s = "(" + s + ")" - } - return s -} - -// PrintList returns source code of trace printing part correspondent -// to syscall return values. -func (r *Rets) PrintList() string { - return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `) -} - -// SetReturnValuesCode returns source code that accepts syscall return values. -func (r *Rets) SetReturnValuesCode() string { - if r.Name == "" && !r.ReturnsError { - return "" - } - retvar := "r0" - if r.Name == "" { - retvar = "r1" - } - errvar := "_" - if r.ReturnsError { - errvar = "e1" - } - return fmt.Sprintf("%s, _, %s := ", retvar, errvar) -} - -func (r *Rets) useLongHandleErrorCode(retvar string) string { - const code = `if %s { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = %sEINVAL - } - }` - cond := retvar + " == 0" - if r.FailCond != "" { - cond = strings.Replace(r.FailCond, "failretval", retvar, 1) - } - return fmt.Sprintf(code, cond, syscalldot()) -} - -// SetErrorCode returns source code that sets return parameters. -func (r *Rets) SetErrorCode() string { - const code = `if r0 != 0 { - %s = %sErrno(r0) - }` - const hrCode = `if int32(r0) < 0 { - %s = %sErrno(win32FromHresult(r0)) - }` - if r.Name == "" && !r.ReturnsError { - return "" - } - if r.Name == "" { - return r.useLongHandleErrorCode("r1") - } - if r.Type == "error" { - if r.Name == "hr" { - return fmt.Sprintf(hrCode, r.Name, syscalldot()) - } else { - return fmt.Sprintf(code, r.Name, syscalldot()) - } - } - s := "" - switch { - case r.Type[0] == '*': - s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type) - case r.Type == "bool": - s = fmt.Sprintf("%s = r0 != 0", r.Name) - default: - s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type) - } - if !r.ReturnsError { - return s - } - return s + "\n\t" + r.useLongHandleErrorCode(r.Name) -} - -// Fn describes syscall function. -type Fn struct { - Name string - Params []*Param - Rets *Rets - PrintTrace bool - confirmproc bool - dllname string - dllfuncname string - src string - // TODO: get rid of this field and just use parameter index instead - curTmpVarIdx int // insure tmp variables have uniq names -} - -// extractParams parses s to extract function parameters. -func extractParams(s string, f *Fn) ([]*Param, error) { - s = trim(s) - if s == "" { - return nil, nil - } - a := strings.Split(s, ",") - ps := make([]*Param, len(a)) - for i := range ps { - s2 := trim(a[i]) - b := strings.Split(s2, " ") - if len(b) != 2 { - b = strings.Split(s2, "\t") - if len(b) != 2 { - return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"") - } - } - ps[i] = &Param{ - Name: trim(b[0]), - Type: trim(b[1]), - fn: f, - tmpVarIdx: -1, - } - } - return ps, nil -} - -// extractSection extracts text out of string s starting after start -// and ending just before end. found return value will indicate success, -// and prefix, body and suffix will contain correspondent parts of string s. -func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) { - s = trim(s) - if strings.HasPrefix(s, string(start)) { - // no prefix - body = s[1:] - } else { - a := strings.SplitN(s, string(start), 2) - if len(a) != 2 { - return "", "", s, false - } - prefix = a[0] - body = a[1] - } - a := strings.SplitN(body, string(end), 2) - if len(a) != 2 { - return "", "", "", false - } - return prefix, a[0], a[1], true -} - -// newFn parses string s and return created function Fn. -func newFn(s string) (*Fn, error) { - s = trim(s) - f := &Fn{ - Rets: &Rets{}, - src: s, - PrintTrace: *printTraceFlag, - } - // function name and args - prefix, body, s, found := extractSection(s, '(', ')') - if !found || prefix == "" { - return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"") - } - f.Name = prefix - var err error - f.Params, err = extractParams(body, f) - if err != nil { - return nil, err - } - // return values - _, body, s, found = extractSection(s, '(', ')') - if found { - r, err := extractParams(body, f) - if err != nil { - return nil, err - } - switch len(r) { - case 0: - case 1: - if r[0].IsError() { - f.Rets.ReturnsError = true - } else { - f.Rets.Name = r[0].Name - f.Rets.Type = r[0].Type - } - case 2: - if !r[1].IsError() { - return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"") - } - f.Rets.ReturnsError = true - f.Rets.Name = r[0].Name - f.Rets.Type = r[0].Type - default: - return nil, errors.New("Too many return values in \"" + f.src + "\"") - } - } - // fail condition - _, body, s, found = extractSection(s, '[', ']') - if found { - f.Rets.FailCond = body - } - // dll and dll function names - s = trim(s) - if s == "" { - return f, nil - } - if !strings.HasPrefix(s, "=") { - return nil, errors.New("Could not extract dll name from \"" + f.src + "\"") - } - s = trim(s[1:]) - a := strings.Split(s, ".") - switch len(a) { - case 1: - f.dllfuncname = a[0] - case 2: - f.dllname = a[0] - f.dllfuncname = a[1] - default: - return nil, errors.New("Could not extract dll name from \"" + f.src + "\"") - } - if f.dllfuncname[len(f.dllfuncname)-1] == '?' { - f.confirmproc = true - f.dllfuncname = f.dllfuncname[0 : len(f.dllfuncname)-1] - } - return f, nil -} - -// DLLName returns DLL name for function f. -func (f *Fn) DLLName() string { - if f.dllname == "" { - return "kernel32" - } - return f.dllname -} - -// DLLName returns DLL function name for function f. -func (f *Fn) DLLFuncName() string { - if f.dllfuncname == "" { - return f.Name - } - return f.dllfuncname -} - -func (f *Fn) ConfirmProc() bool { - return f.confirmproc -} - -// ParamList returns source code for function f parameters. -func (f *Fn) ParamList() string { - return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ") -} - -// HelperParamList returns source code for helper function f parameters. -func (f *Fn) HelperParamList() string { - return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ") -} - -// ParamPrintList returns source code of trace printing part correspondent -// to syscall input parameters. -func (f *Fn) ParamPrintList() string { - return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `) -} - -// ParamCount return number of syscall parameters for function f. -func (f *Fn) ParamCount() int { - n := 0 - for _, p := range f.Params { - n += len(p.SyscallArgList()) - } - return n -} - -// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/... -// to use. It returns parameter count for correspondent SyscallX function. -func (f *Fn) SyscallParamCount() int { - n := f.ParamCount() - switch { - case n <= 3: - return 3 - case n <= 6: - return 6 - case n <= 9: - return 9 - case n <= 12: - return 12 - case n <= 15: - return 15 - default: - panic("too many arguments to system call") - } -} - -// Syscall determines which SyscallX function to use for function f. -func (f *Fn) Syscall() string { - c := f.SyscallParamCount() - if c == 3 { - return syscalldot() + "Syscall" - } - return syscalldot() + "Syscall" + strconv.Itoa(c) -} - -// SyscallParamList returns source code for SyscallX parameters for function f. -func (f *Fn) SyscallParamList() string { - a := make([]string, 0) - for _, p := range f.Params { - a = append(a, p.SyscallArgList()...) - } - for len(a) < f.SyscallParamCount() { - a = append(a, "0") - } - return strings.Join(a, ", ") -} - -// HelperCallParamList returns source code of call into function f helper. -func (f *Fn) HelperCallParamList() string { - a := make([]string, 0, len(f.Params)) - for _, p := range f.Params { - s := p.Name - if p.Type == "string" { - s = p.tmpVar() - } - a = append(a, s) - } - return strings.Join(a, ", ") -} - -// IsUTF16 is true, if f is W (utf16) function. It is false -// for all A (ascii) functions. -func (_ *Fn) IsUTF16() bool { - return true -} - -// StrconvFunc returns name of Go string to OS string function for f. -func (f *Fn) StrconvFunc() string { - if f.IsUTF16() { - return syscalldot() + "UTF16PtrFromString" - } - return syscalldot() + "BytePtrFromString" -} - -// StrconvType returns Go type name used for OS string for f. -func (f *Fn) StrconvType() string { - if f.IsUTF16() { - return "*uint16" - } - return "*byte" -} - -// HasStringParam is true, if f has at least one string parameter. -// Otherwise it is false. -func (f *Fn) HasStringParam() bool { - for _, p := range f.Params { - if p.Type == "string" { - return true - } - } - return false -} - -var uniqDllFuncName = make(map[string]bool) - -// IsNotDuplicate is true if f is not a duplicated function -func (f *Fn) IsNotDuplicate() bool { - funcName := f.DLLFuncName() - if uniqDllFuncName[funcName] == false { - uniqDllFuncName[funcName] = true - return true - } - return false -} - -// HelperName returns name of function f helper. -func (f *Fn) HelperName() string { - if !f.HasStringParam() { - return f.Name - } - return "_" + f.Name -} - -// Source files and functions. -type Source struct { - Funcs []*Fn - Files []string - StdLibImports []string - ExternalImports []string -} - -func (src *Source) Import(pkg string) { - src.StdLibImports = append(src.StdLibImports, pkg) - sort.Strings(src.StdLibImports) -} - -func (src *Source) ExternalImport(pkg string) { - src.ExternalImports = append(src.ExternalImports, pkg) - sort.Strings(src.ExternalImports) -} - -// ParseFiles parses files listed in fs and extracts all syscall -// functions listed in sys comments. It returns source files -// and functions collection *Source if successful. -func ParseFiles(fs []string) (*Source, error) { - src := &Source{ - Funcs: make([]*Fn, 0), - Files: make([]string, 0), - StdLibImports: []string{ - "unsafe", - }, - ExternalImports: make([]string, 0), - } - for _, file := range fs { - if err := src.ParseFile(file); err != nil { - return nil, err - } - } - return src, nil -} - -// DLLs return dll names for a source set src. -func (src *Source) DLLs() []string { - uniq := make(map[string]bool) - r := make([]string, 0) - for _, f := range src.Funcs { - name := f.DLLName() - if _, found := uniq[name]; !found { - uniq[name] = true - r = append(r, name) - } - } - return r -} - -// ParseFile adds additional file path to a source set src. -func (src *Source) ParseFile(path string) error { - file, err := os.Open(path) - if err != nil { - return err - } - defer file.Close() - - s := bufio.NewScanner(file) - for s.Scan() { - t := trim(s.Text()) - if len(t) < 7 { - continue - } - if !strings.HasPrefix(t, "//sys") { - continue - } - t = t[5:] - if !(t[0] == ' ' || t[0] == '\t') { - continue - } - f, err := newFn(t[1:]) - if err != nil { - return err - } - src.Funcs = append(src.Funcs, f) - } - if err := s.Err(); err != nil { - return err - } - src.Files = append(src.Files, path) - - // get package name - fset := token.NewFileSet() - _, err = file.Seek(0, 0) - if err != nil { - return err - } - pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly) - if err != nil { - return err - } - packageName = pkg.Name.Name - - return nil -} - -// IsStdRepo returns true if src is part of standard library. -func (src *Source) IsStdRepo() (bool, error) { - if len(src.Files) == 0 { - return false, errors.New("no input files provided") - } - abspath, err := filepath.Abs(src.Files[0]) - if err != nil { - return false, err - } - goroot := runtime.GOROOT() - if runtime.GOOS == "windows" { - abspath = strings.ToLower(abspath) - goroot = strings.ToLower(goroot) - } - sep := string(os.PathSeparator) - if !strings.HasSuffix(goroot, sep) { - goroot += sep - } - return strings.HasPrefix(abspath, goroot), nil -} - -// Generate output source file from a source set src. -func (src *Source) Generate(w io.Writer) error { - const ( - pkgStd = iota // any package in std library - pkgXSysWindows // x/sys/windows package - pkgOther - ) - isStdRepo, err := src.IsStdRepo() - if err != nil { - return err - } - var pkgtype int - switch { - case isStdRepo: - pkgtype = pkgStd - case packageName == "windows": - // TODO: this needs better logic than just using package name - pkgtype = pkgXSysWindows - default: - pkgtype = pkgOther - } - if *systemDLL { - switch pkgtype { - case pkgStd: - src.Import("internal/syscall/windows/sysdll") - case pkgXSysWindows: - default: - src.ExternalImport("golang.org/x/sys/windows") - } - } - src.ExternalImport("github.com/Microsoft/go-winio") - if packageName != "syscall" { - src.Import("syscall") - } - funcMap := template.FuncMap{ - "packagename": packagename, - "syscalldot": syscalldot, - "newlazydll": func(dll string) string { - arg := "\"" + dll + ".dll\"" - if !*systemDLL { - return syscalldot() + "NewLazyDLL(" + arg + ")" - } - switch pkgtype { - case pkgStd: - return syscalldot() + "NewLazyDLL(sysdll.Add(" + arg + "))" - case pkgXSysWindows: - return "NewLazySystemDLL(" + arg + ")" - default: - return "windows.NewLazySystemDLL(" + arg + ")" - } - }, - } - t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate)) - err = t.Execute(w, src) - if err != nil { - return errors.New("Failed to execute template: " + err.Error()) - } - return nil -} - -func usage() { - fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n") - flag.PrintDefaults() - os.Exit(1) -} - -func main() { - flag.Usage = usage - flag.Parse() - if len(flag.Args()) <= 0 { - fmt.Fprintf(os.Stderr, "no files to parse provided\n") - usage() - } - - src, err := ParseFiles(flag.Args()) - if err != nil { - log.Fatal(err) - } - - var buf bytes.Buffer - if err := src.Generate(&buf); err != nil { - log.Fatal(err) - } - - data, err := format.Source(buf.Bytes()) - if err != nil { - log.Fatal(err) - } - if *filename == "" { - _, err = os.Stdout.Write(data) - } else { - err = ioutil.WriteFile(*filename, data, 0644) - } - if err != nil { - log.Fatal(err) - } -} - -// TODO: use println instead to print in the following template -const srcTemplate = ` - -{{define "main"}}// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT - -package {{packagename}} - -import ( -{{range .StdLibImports}}"{{.}}" -{{end}} - -{{range .ExternalImports}}"{{.}}" -{{end}} -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = {{syscalldot}}Errno(errnoERROR_IO_PENDING) -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e {{syscalldot}}Errno) error { - switch e { - case 0: - return nil - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) - return e -} - -var ( -{{template "dlls" .}} -{{template "funcnames" .}}) -{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}} -{{end}} - -{{/* help functions */}} - -{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{newlazydll .}} -{{end}}{{end}} - -{{define "funcnames"}}{{range .Funcs}}{{if .IsNotDuplicate}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}"){{end}} -{{end}}{{end}} - -{{define "helperbody"}} -func {{.Name}}({{.ParamList}}) {{template "results" .}}{ -{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}}) -} -{{end}} - -{{define "funcbody"}} -func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{ -{{template "tmpvars" .}} {{template "syscallcheck" .}}{{template "syscall" .}} -{{template "seterror" .}}{{template "printtrace" .}} return -} -{{end}} - -{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}} -{{end}}{{end}}{{end}} - -{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}} -{{end}}{{end}}{{end}} - -{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}} - -{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}} - -{{define "syscallcheck"}}{{if .ConfirmProc}}if {{.Rets.ErrorVarName}} = proc{{.DLLFuncName}}.Find(); {{.Rets.ErrorVarName}} != nil { - return -} -{{end}}{{end}} - - -{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}} -{{end}}{{end}} - -{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n") -{{end}}{{end}} - -` diff --git a/vendor/github.com/containernetworking/cni/LICENSE b/vendor/github.com/containernetworking/cni/LICENSE new file mode 100644 index 0000000000..8f71f43fee --- /dev/null +++ b/vendor/github.com/containernetworking/cni/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/vendor/github.com/containernetworking/cni/README.md b/vendor/github.com/containernetworking/cni/README.md new file mode 100644 index 0000000000..793187c790 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/README.md @@ -0,0 +1,191 @@ +[![Build Status](https://travis-ci.org/containernetworking/cni.svg?branch=master)](https://travis-ci.org/containernetworking/cni) +[![Coverage Status](https://coveralls.io/repos/github/containernetworking/cni/badge.svg?branch=master)](https://coveralls.io/github/containernetworking/cni?branch=master) +[![Slack Status](https://cryptic-tundra-43194.herokuapp.com/badge.svg)](https://cryptic-tundra-43194.herokuapp.com/) + +![CNI Logo](logo.png) + +--- + +# Community Sync Meeting + +There is a community sync meeting for users and developers every 1-2 months. The next meeting will help on a Google Hangout and the link is in the [agenda](https://docs.google.com/document/d/10ECyT2mBGewsJUcmYmS8QNo1AcNgy2ZIe2xS7lShYhE/edit?usp=sharing) (Notes from previous meeting are also in this doc). The next meeting will be held on *Wednesday, June 21th* at *3:00pm UTC* [Add to Calendar]https://www.worldtimebuddy.com/?qm=1&lid=100,5,2643743,5391959&h=100&date=2017-6-21&sln=15-16). + +--- + +# CNI - the Container Network Interface + +## What is CNI? + +CNI (_Container Network Interface_), a [Cloud Native Computing Foundation](https://cncf.io) project, consists of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins. +CNI concerns itself only with network connectivity of containers and removing allocated resources when the container is deleted. +Because of this focus, CNI has a wide range of support and the specification is simple to implement. + +As well as the [specification](SPEC.md), this repository contains the Go source code of a [library for integrating CNI into applications](libcni) and an [example command-line tool](cnitool) for executing CNI plugins. A [separate repository contains reference plugins](https://github.com/containernetworking/plugins) and a template for making new plugins. + +The template code makes it straight-forward to create a CNI plugin for an existing container networking project. +CNI also makes a good framework for creating a new container networking project from scratch. + +## Why develop CNI? + +Application containers on Linux are a rapidly evolving area, and within this area networking is not well addressed as it is highly environment-specific. +We believe that many container runtimes and orchestrators will seek to solve the same problem of making the network layer pluggable. + +To avoid duplication, we think it is prudent to define a common interface between the network plugins and container execution: hence we put forward this specification, along with libraries for Go and a set of plugins. + +## Who is using CNI? +### Container runtimes +- [rkt - container engine](https://coreos.com/blog/rkt-cni-networking.html) +- [Kurma - container runtime](http://kurma.io/) +- [Kubernetes - a system to simplify container operations](http://kubernetes.io/docs/admin/network-plugins/) +- [OpenShift - Kubernetes with additional enterprise features](https://github.com/openshift/origin/blob/master/docs/openshift_networking_requirements.md) +- [Cloud Foundry - a platform for cloud applications](https://github.com/cloudfoundry-incubator/cf-networking-release) +- [Mesos - a distributed systems kernel](https://github.com/apache/mesos/blob/master/docs/cni.md) + +### 3rd party plugins +- [Project Calico - a layer 3 virtual network](https://github.com/projectcalico/calico-cni) +- [Weave - a multi-host Docker network](https://github.com/weaveworks/weave) +- [Contiv Networking - policy networking for various use cases](https://github.com/contiv/netplugin) +- [SR-IOV](https://github.com/hustcat/sriov-cni) +- [Cilium - BPF & XDP for containers](https://github.com/cilium/cilium) +- [Infoblox - enterprise IP address management for containers](https://github.com/infobloxopen/cni-infoblox) +- [Multus - a Multi plugin](https://github.com/Intel-Corp/multus-cni) +- [Romana - Layer 3 CNI plugin supporting network policy for Kubernetes](https://github.com/romana/kube) +- [CNI-Genie - generic CNI network plugin](https://github.com/Huawei-PaaS/CNI-Genie) +- [Nuage CNI - Nuage Networks SDN plugin for network policy kubernetes support ](https://github.com/nuagenetworks/nuage-cni) +- [Silk - a CNI plugin designed for Cloud Foundry](https://github.com/cloudfoundry-incubator/silk) +- [Linen - a CNI plugin designed for overlay networks with Open vSwitch and fit in SDN/OpenFlow network environment](https://github.com/John-Lin/linen-cni) + +The CNI team also maintains some [core plugins in a separate repository](https://github.com/containernetworking/plugins). + + +## Contributing to CNI + +We welcome contributions, including [bug reports](https://github.com/containernetworking/cni/issues), and code and documentation improvements. +If you intend to contribute to code or documentation, please read [CONTRIBUTING.md](CONTRIBUTING.md). Also see the [contact section](#contact) in this README. + +## How do I use CNI? + +### Requirements + +The CNI spec is language agnostic. To use the Go language libraries in this repository, you'll need a recent version of Go. Our [automated tests](https://travis-ci.org/containernetworking/cni/builds) cover Go versions 1.7 and 1.8. + +### Reference Plugins + +The CNI project maintains a set of [reference plugins](https://github.com/containernetworking/plugins) that implement the CNI specification. +NOTE: the reference plugins used to live in this repository but have been split out into a [separate repository](https://github.com/containernetworking/plugins) as of May 2017. + +### Running the plugins + +After building and installing the [reference plugins](https://github.com/containernetworking/plugins), you can use the `priv-net-run.sh` and `docker-run.sh` scripts in the `scripts/` directory to exercise the plugins. + +**note - priv-net-run.sh depends on `jq`** + +Start out by creating a netconf file to describe a network: + +```bash +$ mkdir -p /etc/cni/net.d +$ cat >/etc/cni/net.d/10-mynet.conf </etc/cni/net.d/99-loopback.conf < 0 && !isIgnoreUnknown { + return fmt.Errorf("ARGS: unknown args %q", unknownArgs) + } + return nil +} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go new file mode 100644 index 0000000000..caac92ba77 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go @@ -0,0 +1,300 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package current + +import ( + "encoding/json" + "fmt" + "net" + "os" + + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types/020" +) + +const ImplementedSpecVersion string = "0.3.1" + +var SupportedVersions = []string{"0.3.0", ImplementedSpecVersion} + +func NewResult(data []byte) (types.Result, error) { + result := &Result{} + if err := json.Unmarshal(data, result); err != nil { + return nil, err + } + return result, nil +} + +func GetResult(r types.Result) (*Result, error) { + resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion) + if err != nil { + return nil, err + } + result, ok := resultCurrent.(*Result) + if !ok { + return nil, fmt.Errorf("failed to convert result") + } + return result, nil +} + +var resultConverters = []struct { + versions []string + convert func(types.Result) (*Result, error) +}{ + {types020.SupportedVersions, convertFrom020}, + {SupportedVersions, convertFrom030}, +} + +func convertFrom020(result types.Result) (*Result, error) { + oldResult, err := types020.GetResult(result) + if err != nil { + return nil, err + } + + newResult := &Result{ + CNIVersion: ImplementedSpecVersion, + DNS: oldResult.DNS, + Routes: []*types.Route{}, + } + + if oldResult.IP4 != nil { + newResult.IPs = append(newResult.IPs, &IPConfig{ + Version: "4", + Address: oldResult.IP4.IP, + Gateway: oldResult.IP4.Gateway, + }) + for _, route := range oldResult.IP4.Routes { + gw := route.GW + if gw == nil { + gw = oldResult.IP4.Gateway + } + newResult.Routes = append(newResult.Routes, &types.Route{ + Dst: route.Dst, + GW: gw, + }) + } + } + + if oldResult.IP6 != nil { + newResult.IPs = append(newResult.IPs, &IPConfig{ + Version: "6", + Address: oldResult.IP6.IP, + Gateway: oldResult.IP6.Gateway, + }) + for _, route := range oldResult.IP6.Routes { + gw := route.GW + if gw == nil { + gw = oldResult.IP6.Gateway + } + newResult.Routes = append(newResult.Routes, &types.Route{ + Dst: route.Dst, + GW: gw, + }) + } + } + + if len(newResult.IPs) == 0 { + return nil, fmt.Errorf("cannot convert: no valid IP addresses") + } + + return newResult, nil +} + +func convertFrom030(result types.Result) (*Result, error) { + newResult, ok := result.(*Result) + if !ok { + return nil, fmt.Errorf("failed to convert result") + } + newResult.CNIVersion = ImplementedSpecVersion + return newResult, nil +} + +func NewResultFromResult(result types.Result) (*Result, error) { + version := result.Version() + for _, converter := range resultConverters { + for _, supportedVersion := range converter.versions { + if version == supportedVersion { + return converter.convert(result) + } + } + } + return nil, fmt.Errorf("unsupported CNI result22 version %q", version) +} + +// Result is what gets returned from the plugin (via stdout) to the caller +type Result struct { + CNIVersion string `json:"cniVersion,omitempty"` + Interfaces []*Interface `json:"interfaces,omitempty"` + IPs []*IPConfig `json:"ips,omitempty"` + Routes []*types.Route `json:"routes,omitempty"` + DNS types.DNS `json:"dns,omitempty"` +} + +// Convert to the older 0.2.0 CNI spec Result type +func (r *Result) convertTo020() (*types020.Result, error) { + oldResult := &types020.Result{ + CNIVersion: types020.ImplementedSpecVersion, + DNS: r.DNS, + } + + for _, ip := range r.IPs { + // Only convert the first IP address of each version as 0.2.0 + // and earlier cannot handle multiple IP addresses + if ip.Version == "4" && oldResult.IP4 == nil { + oldResult.IP4 = &types020.IPConfig{ + IP: ip.Address, + Gateway: ip.Gateway, + } + } else if ip.Version == "6" && oldResult.IP6 == nil { + oldResult.IP6 = &types020.IPConfig{ + IP: ip.Address, + Gateway: ip.Gateway, + } + } + + if oldResult.IP4 != nil && oldResult.IP6 != nil { + break + } + } + + for _, route := range r.Routes { + is4 := route.Dst.IP.To4() != nil + if is4 && oldResult.IP4 != nil { + oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{ + Dst: route.Dst, + GW: route.GW, + }) + } else if !is4 && oldResult.IP6 != nil { + oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{ + Dst: route.Dst, + GW: route.GW, + }) + } + } + + if oldResult.IP4 == nil && oldResult.IP6 == nil { + return nil, fmt.Errorf("cannot convert: no valid IP addresses") + } + + return oldResult, nil +} + +func (r *Result) Version() string { + return ImplementedSpecVersion +} + +func (r *Result) GetAsVersion(version string) (types.Result, error) { + switch version { + case "0.3.0", ImplementedSpecVersion: + r.CNIVersion = version + return r, nil + case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]: + return r.convertTo020() + } + return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version) +} + +func (r *Result) Print() error { + data, err := json.MarshalIndent(r, "", " ") + if err != nil { + return err + } + _, err = os.Stdout.Write(data) + return err +} + +// String returns a formatted string in the form of "[Interfaces: $1,][ IP: $2,] DNS: $3" where +// $1 represents the receiver's Interfaces, $2 represents the receiver's IP addresses and $3 the +// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string. +func (r *Result) String() string { + var str string + if len(r.Interfaces) > 0 { + str += fmt.Sprintf("Interfaces:%+v, ", r.Interfaces) + } + if len(r.IPs) > 0 { + str += fmt.Sprintf("IP:%+v, ", r.IPs) + } + if len(r.Routes) > 0 { + str += fmt.Sprintf("Routes:%+v, ", r.Routes) + } + return fmt.Sprintf("%sDNS:%+v", str, r.DNS) +} + +// Convert this old version result to the current CNI version result +func (r *Result) Convert() (*Result, error) { + return r, nil +} + +// Interface contains values about the created interfaces +type Interface struct { + Name string `json:"name"` + Mac string `json:"mac,omitempty"` + Sandbox string `json:"sandbox,omitempty"` +} + +func (i *Interface) String() string { + return fmt.Sprintf("%+v", *i) +} + +// Int returns a pointer to the int value passed in. Used to +// set the IPConfig.Interface field. +func Int(v int) *int { + return &v +} + +// IPConfig contains values necessary to configure an IP address on an interface +type IPConfig struct { + // IP version, either "4" or "6" + Version string + // Index into Result structs Interfaces list + Interface *int + Address net.IPNet + Gateway net.IP +} + +func (i *IPConfig) String() string { + return fmt.Sprintf("%+v", *i) +} + +// JSON (un)marshallable types +type ipConfig struct { + Version string `json:"version"` + Interface *int `json:"interface,omitempty"` + Address types.IPNet `json:"address"` + Gateway net.IP `json:"gateway,omitempty"` +} + +func (c *IPConfig) MarshalJSON() ([]byte, error) { + ipc := ipConfig{ + Version: c.Version, + Interface: c.Interface, + Address: types.IPNet(c.Address), + Gateway: c.Gateway, + } + + return json.Marshal(ipc) +} + +func (c *IPConfig) UnmarshalJSON(data []byte) error { + ipc := ipConfig{} + if err := json.Unmarshal(data, &ipc); err != nil { + return err + } + + c.Version = ipc.Version + c.Interface = ipc.Interface + c.Address = net.IPNet(ipc.Address) + c.Gateway = ipc.Gateway + return nil +} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/types.go b/vendor/github.com/containernetworking/cni/pkg/types/types.go new file mode 100644 index 0000000000..6412756007 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/types/types.go @@ -0,0 +1,189 @@ +// Copyright 2015 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "encoding/json" + "errors" + "fmt" + "net" + "os" +) + +// like net.IPNet but adds JSON marshalling and unmarshalling +type IPNet net.IPNet + +// ParseCIDR takes a string like "10.2.3.1/24" and +// return IPNet with "10.2.3.1" and /24 mask +func ParseCIDR(s string) (*net.IPNet, error) { + ip, ipn, err := net.ParseCIDR(s) + if err != nil { + return nil, err + } + + ipn.IP = ip + return ipn, nil +} + +func (n IPNet) MarshalJSON() ([]byte, error) { + return json.Marshal((*net.IPNet)(&n).String()) +} + +func (n *IPNet) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return err + } + + tmp, err := ParseCIDR(s) + if err != nil { + return err + } + + *n = IPNet(*tmp) + return nil +} + +// NetConf describes a network. +type NetConf struct { + CNIVersion string `json:"cniVersion,omitempty"` + + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Capabilities map[string]bool `json:"capabilities,omitempty"` + IPAM struct { + Type string `json:"type,omitempty"` + } `json:"ipam,omitempty"` + DNS DNS `json:"dns"` +} + +// NetConfList describes an ordered list of networks. +type NetConfList struct { + CNIVersion string `json:"cniVersion,omitempty"` + + Name string `json:"name,omitempty"` + Plugins []*NetConf `json:"plugins,omitempty"` +} + +type ResultFactoryFunc func([]byte) (Result, error) + +// Result is an interface that provides the result of plugin execution +type Result interface { + // The highest CNI specification result verison the result supports + // without having to convert + Version() string + + // Returns the result converted into the requested CNI specification + // result version, or an error if conversion failed + GetAsVersion(version string) (Result, error) + + // Prints the result in JSON format to stdout + Print() error + + // Returns a JSON string representation of the result + String() string +} + +func PrintResult(result Result, version string) error { + newResult, err := result.GetAsVersion(version) + if err != nil { + return err + } + return newResult.Print() +} + +// DNS contains values interesting for DNS resolvers +type DNS struct { + Nameservers []string `json:"nameservers,omitempty"` + Domain string `json:"domain,omitempty"` + Search []string `json:"search,omitempty"` + Options []string `json:"options,omitempty"` +} + +type Route struct { + Dst net.IPNet + GW net.IP +} + +func (r *Route) String() string { + return fmt.Sprintf("%+v", *r) +} + +// Well known error codes +// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes +const ( + ErrUnknown uint = iota // 0 + ErrIncompatibleCNIVersion // 1 + ErrUnsupportedField // 2 +) + +type Error struct { + Code uint `json:"code"` + Msg string `json:"msg"` + Details string `json:"details,omitempty"` +} + +func (e *Error) Error() string { + details := "" + if e.Details != "" { + details = fmt.Sprintf("; %v", e.Details) + } + return fmt.Sprintf("%v%v", e.Msg, details) +} + +func (e *Error) Print() error { + return prettyPrint(e) +} + +// net.IPNet is not JSON (un)marshallable so this duality is needed +// for our custom IPNet type + +// JSON (un)marshallable types +type route struct { + Dst IPNet `json:"dst"` + GW net.IP `json:"gw,omitempty"` +} + +func (r *Route) UnmarshalJSON(data []byte) error { + rt := route{} + if err := json.Unmarshal(data, &rt); err != nil { + return err + } + + r.Dst = net.IPNet(rt.Dst) + r.GW = rt.GW + return nil +} + +func (r *Route) MarshalJSON() ([]byte, error) { + rt := route{ + Dst: IPNet(r.Dst), + GW: r.GW, + } + + return json.Marshal(rt) +} + +func prettyPrint(obj interface{}) error { + data, err := json.MarshalIndent(obj, "", " ") + if err != nil { + return err + } + _, err = os.Stdout.Write(data) + return err +} + +// NotImplementedError is used to indicate that a method is not implemented for the given platform +var NotImplementedError = errors.New("Not Implemented") diff --git a/vendor/github.com/containernetworking/cni/pkg/version/conf.go b/vendor/github.com/containernetworking/cni/pkg/version/conf.go new file mode 100644 index 0000000000..3cca58bbeb --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/version/conf.go @@ -0,0 +1,37 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package version + +import ( + "encoding/json" + "fmt" +) + +// ConfigDecoder can decode the CNI version available in network config data +type ConfigDecoder struct{} + +func (*ConfigDecoder) Decode(jsonBytes []byte) (string, error) { + var conf struct { + CNIVersion string `json:"cniVersion"` + } + err := json.Unmarshal(jsonBytes, &conf) + if err != nil { + return "", fmt.Errorf("decoding version from network config: %s", err) + } + if conf.CNIVersion == "" { + return "0.1.0", nil + } + return conf.CNIVersion, nil +} diff --git a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go new file mode 100644 index 0000000000..8a46728105 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go @@ -0,0 +1,81 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package version + +import ( + "encoding/json" + "fmt" + "io" +) + +// PluginInfo reports information about CNI versioning +type PluginInfo interface { + // SupportedVersions returns one or more CNI spec versions that the plugin + // supports. If input is provided in one of these versions, then the plugin + // promises to use the same CNI version in its response + SupportedVersions() []string + + // Encode writes this CNI version information as JSON to the given Writer + Encode(io.Writer) error +} + +type pluginInfo struct { + CNIVersion_ string `json:"cniVersion"` + SupportedVersions_ []string `json:"supportedVersions,omitempty"` +} + +// pluginInfo implements the PluginInfo interface +var _ PluginInfo = &pluginInfo{} + +func (p *pluginInfo) Encode(w io.Writer) error { + return json.NewEncoder(w).Encode(p) +} + +func (p *pluginInfo) SupportedVersions() []string { + return p.SupportedVersions_ +} + +// PluginSupports returns a new PluginInfo that will report the given versions +// as supported +func PluginSupports(supportedVersions ...string) PluginInfo { + if len(supportedVersions) < 1 { + panic("programmer error: you must support at least one version") + } + return &pluginInfo{ + CNIVersion_: Current(), + SupportedVersions_: supportedVersions, + } +} + +// PluginDecoder can decode the response returned by a plugin's VERSION command +type PluginDecoder struct{} + +func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) { + var info pluginInfo + err := json.Unmarshal(jsonBytes, &info) + if err != nil { + return nil, fmt.Errorf("decoding version info: %s", err) + } + if info.CNIVersion_ == "" { + return nil, fmt.Errorf("decoding version info: missing field cniVersion") + } + if len(info.SupportedVersions_) == 0 { + if info.CNIVersion_ == "0.2.0" { + return PluginSupports("0.1.0", "0.2.0"), nil + } + return nil, fmt.Errorf("decoding version info: missing field supportedVersions") + } + return &info, nil +} diff --git a/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go b/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go new file mode 100644 index 0000000000..25c3810b2a --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go @@ -0,0 +1,49 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package version + +import "fmt" + +type ErrorIncompatible struct { + Config string + Supported []string +} + +func (e *ErrorIncompatible) Details() string { + return fmt.Sprintf("config is %q, plugin supports %q", e.Config, e.Supported) +} + +func (e *ErrorIncompatible) Error() string { + return fmt.Sprintf("incompatible CNI versions: %s", e.Details()) +} + +type Reconciler struct{} + +func (r *Reconciler) Check(configVersion string, pluginInfo PluginInfo) *ErrorIncompatible { + return r.CheckRaw(configVersion, pluginInfo.SupportedVersions()) +} + +func (*Reconciler) CheckRaw(configVersion string, supportedVersions []string) *ErrorIncompatible { + for _, supportedVersion := range supportedVersions { + if configVersion == supportedVersion { + return nil + } + } + + return &ErrorIncompatible{ + Config: configVersion, + Supported: supportedVersions, + } +} diff --git a/vendor/github.com/containernetworking/cni/pkg/version/version.go b/vendor/github.com/containernetworking/cni/pkg/version/version.go new file mode 100644 index 0000000000..efe8ea8716 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/version/version.go @@ -0,0 +1,61 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package version + +import ( + "fmt" + + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types/020" + "github.com/containernetworking/cni/pkg/types/current" +) + +// Current reports the version of the CNI spec implemented by this library +func Current() string { + return "0.3.1" +} + +// Legacy PluginInfo describes a plugin that is backwards compatible with the +// CNI spec version 0.1.0. In particular, a runtime compiled against the 0.1.0 +// library ought to work correctly with a plugin that reports support for +// Legacy versions. +// +// Any future CNI spec versions which meet this definition should be added to +// this list. +var Legacy = PluginSupports("0.1.0", "0.2.0") +var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1") + +var resultFactories = []struct { + supportedVersions []string + newResult types.ResultFactoryFunc +}{ + {current.SupportedVersions, current.NewResult}, + {types020.SupportedVersions, types020.NewResult}, +} + +// Finds a Result object matching the requested version (if any) and asks +// that object to parse the plugin result, returning an error if parsing failed. +func NewResult(version string, resultBytes []byte) (types.Result, error) { + reconciler := &Reconciler{} + for _, resultFactory := range resultFactories { + err := reconciler.CheckRaw(version, resultFactory.supportedVersions) + if err == nil { + // Result supports this version + return resultFactory.newResult(resultBytes) + } + } + + return nil, fmt.Errorf("unsupported CNI result version %q", version) +} diff --git a/vendor/github.com/containernetworking/plugins/LICENSE b/vendor/github.com/containernetworking/plugins/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/vendor/github.com/containernetworking/plugins/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/containernetworking/plugins/README.md b/vendor/github.com/containernetworking/plugins/README.md new file mode 100644 index 0000000000..458ebd682a --- /dev/null +++ b/vendor/github.com/containernetworking/plugins/README.md @@ -0,0 +1,25 @@ +[![Build Status](https://travis-ci.org/containernetworking/plugins.svg?branch=master)](https://travis-ci.org/containernetworking/plugins) + +# plugins +Some CNI network plugins, maintained by the containernetworking team. For more information, see the individual READMEs. + +## Plugins supplied: +### Main: interface-creating +* `bridge`: Creates a bridge, adds the host and the container to it. +* `ipvlan`: Adds an [ipvlan](https://www.kernel.org/doc/Documentation/networking/ipvlan.txt) interface in the container +* `loopback`: Creates a loopback interface +* `macvlan`: Creates a new MAC address, forwards all traffic to that to the container +* `ptp`: Creates a veth pair. +* `vlan`: Allocates a vlan device. + +### IPAM: IP address allocation +* `dhcp`: Runs a daemon on the host to make DHCP requests on behalf of the container +* `host-local`: maintains a local database of allocated IPs + +### Meta: other plugins +* `flannel`: generates an interface corresponding to a flannel config file +* `tuning`: Tweaks sysctl parameters of an existing interface +* `portmap`: An iptables-based portmapping plugin. Maps ports from the host's address space to the container. + +### Sample +The sample plugin provides an example for building your own plugin. diff --git a/vendor/github.com/containernetworking/plugins/pkg/ns/README.md b/vendor/github.com/containernetworking/plugins/pkg/ns/README.md new file mode 100644 index 0000000000..c0f5cf2e86 --- /dev/null +++ b/vendor/github.com/containernetworking/plugins/pkg/ns/README.md @@ -0,0 +1,40 @@ +### Namespaces, Threads, and Go +On Linux each OS thread can have a different network namespace. Go's thread scheduling model switches goroutines between OS threads based on OS thread load and whether the goroutine would block other goroutines. This can result in a goroutine switching network namespaces without notice and lead to errors in your code. + +### Namespace Switching +Switching namespaces with the `ns.Set()` method is not recommended without additional strategies to prevent unexpected namespace changes when your goroutines switch OS threads. + +Go provides the `runtime.LockOSThread()` function to ensure a specific goroutine executes on its current OS thread and prevents any other goroutine from running in that thread until the locked one exits. Careful usage of `LockOSThread()` and goroutines can provide good control over which network namespace a given goroutine executes in. + +For example, you cannot rely on the `ns.Set()` namespace being the current namespace after the `Set()` call unless you do two things. First, the goroutine calling `Set()` must have previously called `LockOSThread()`. Second, you must ensure `runtime.UnlockOSThread()` is not called somewhere in-between. You also cannot rely on the initial network namespace remaining the current network namespace if any other code in your program switches namespaces, unless you have already called `LockOSThread()` in that goroutine. Note that `LockOSThread()` prevents the Go scheduler from optimally scheduling goroutines for best performance, so `LockOSThread()` should only be used in small, isolated goroutines that release the lock quickly. + +### Do() The Recommended Thing +The `ns.Do()` method provides **partial** control over network namespaces for you by implementing these strategies. All code dependent on a particular network namespace (including the root namespace) should be wrapped in the `ns.Do()` method to ensure the correct namespace is selected for the duration of your code. For example: + +```go +targetNs, err := ns.NewNS() +if err != nil { + return err +} +err = targetNs.Do(func(hostNs ns.NetNS) error { + dummy := &netlink.Dummy{ + LinkAttrs: netlink.LinkAttrs{ + Name: "dummy0", + }, + } + return netlink.LinkAdd(dummy) +}) +``` + +Note this requirement to wrap every network call is very onerous - any libraries you call might call out to network services such as DNS, and all such calls need to be protected after you call `ns.Do()`. The CNI plugins all exit very soon after calling `ns.Do()` which helps to minimize the problem. + +Also: If the runtime spawns a new OS thread, it will inherit the network namespace of the parent thread, which may have been temporarily switched, and thus the new OS thread will be permanently "stuck in the wrong namespace". + +In short, **there is no safe way to change network namespaces from within a long-lived, multithreaded Go process**. If your daemon process needs to be namespace aware, consider spawning a separate process (like a CNI plugin) for each namespace. + +### Further Reading + - https://github.com/golang/go/wiki/LockOSThread + - http://morsmachine.dk/go-scheduler + - https://github.com/containernetworking/cni/issues/262 + - https://golang.org/pkg/runtime/ + - https://www.weave.works/blog/linux-namespaces-and-go-don-t-mix diff --git a/vendor/github.com/containernetworking/plugins/pkg/ns/ns.go b/vendor/github.com/containernetworking/plugins/pkg/ns/ns.go new file mode 100644 index 0000000000..c212f4893e --- /dev/null +++ b/vendor/github.com/containernetworking/plugins/pkg/ns/ns.go @@ -0,0 +1,178 @@ +// Copyright 2015 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ns + +import ( + "fmt" + "os" + "runtime" + "sync" + "syscall" +) + +type NetNS interface { + // Executes the passed closure in this object's network namespace, + // attempting to restore the original namespace before returning. + // However, since each OS thread can have a different network namespace, + // and Go's thread scheduling is highly variable, callers cannot + // guarantee any specific namespace is set unless operations that + // require that namespace are wrapped with Do(). Also, no code called + // from Do() should call runtime.UnlockOSThread(), or the risk + // of executing code in an incorrect namespace will be greater. See + // https://github.com/golang/go/wiki/LockOSThread for further details. + Do(toRun func(NetNS) error) error + + // Sets the current network namespace to this object's network namespace. + // Note that since Go's thread scheduling is highly variable, callers + // cannot guarantee the requested namespace will be the current namespace + // after this function is called; to ensure this wrap operations that + // require the namespace with Do() instead. + Set() error + + // Returns the filesystem path representing this object's network namespace + Path() string + + // Returns a file descriptor representing this object's network namespace + Fd() uintptr + + // Cleans up this instance of the network namespace; if this instance + // is the last user the namespace will be destroyed + Close() error +} + +type netNS struct { + file *os.File + mounted bool + closed bool +} + +// netNS implements the NetNS interface +var _ NetNS = &netNS{} + +const ( + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/magic.h + NSFS_MAGIC = 0x6e736673 + PROCFS_MAGIC = 0x9fa0 +) + +type NSPathNotExistErr struct{ msg string } + +func (e NSPathNotExistErr) Error() string { return e.msg } + +type NSPathNotNSErr struct{ msg string } + +func (e NSPathNotNSErr) Error() string { return e.msg } + +func IsNSorErr(nspath string) error { + stat := syscall.Statfs_t{} + if err := syscall.Statfs(nspath, &stat); err != nil { + if os.IsNotExist(err) { + err = NSPathNotExistErr{msg: fmt.Sprintf("failed to Statfs %q: %v", nspath, err)} + } else { + err = fmt.Errorf("failed to Statfs %q: %v", nspath, err) + } + return err + } + + switch stat.Type { + case PROCFS_MAGIC, NSFS_MAGIC: + return nil + default: + return NSPathNotNSErr{msg: fmt.Sprintf("unknown FS magic on %q: %x", nspath, stat.Type)} + } +} + +// Returns an object representing the namespace referred to by @path +func GetNS(nspath string) (NetNS, error) { + err := IsNSorErr(nspath) + if err != nil { + return nil, err + } + + fd, err := os.Open(nspath) + if err != nil { + return nil, err + } + + return &netNS{file: fd}, nil +} + +func (ns *netNS) Path() string { + return ns.file.Name() +} + +func (ns *netNS) Fd() uintptr { + return ns.file.Fd() +} + +func (ns *netNS) errorIfClosed() error { + if ns.closed { + return fmt.Errorf("%q has already been closed", ns.file.Name()) + } + return nil +} + +func (ns *netNS) Do(toRun func(NetNS) error) error { + if err := ns.errorIfClosed(); err != nil { + return err + } + + containedCall := func(hostNS NetNS) error { + threadNS, err := GetCurrentNS() + if err != nil { + return fmt.Errorf("failed to open current netns: %v", err) + } + defer threadNS.Close() + + // switch to target namespace + if err = ns.Set(); err != nil { + return fmt.Errorf("error switching to ns %v: %v", ns.file.Name(), err) + } + defer threadNS.Set() // switch back + + return toRun(hostNS) + } + + // save a handle to current network namespace + hostNS, err := GetCurrentNS() + if err != nil { + return fmt.Errorf("Failed to open current namespace: %v", err) + } + defer hostNS.Close() + + var wg sync.WaitGroup + wg.Add(1) + + var innerError error + go func() { + defer wg.Done() + runtime.LockOSThread() + innerError = containedCall(hostNS) + }() + wg.Wait() + + return innerError +} + +// WithNetNSPath executes the passed closure under the given network +// namespace, restoring the original namespace afterwards. +func WithNetNSPath(nspath string, toRun func(NetNS) error) error { + ns, err := GetNS(nspath) + if err != nil { + return err + } + defer ns.Close() + return ns.Do(toRun) +} diff --git a/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go b/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go new file mode 100644 index 0000000000..8949d21b50 --- /dev/null +++ b/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go @@ -0,0 +1,149 @@ +// Copyright 2015-2017 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ns + +import ( + "crypto/rand" + "fmt" + "os" + "path" + "runtime" + "sync" + + "golang.org/x/sys/unix" +) + +// Returns an object representing the current OS thread's network namespace +func GetCurrentNS() (NetNS, error) { + return GetNS(getCurrentThreadNetNSPath()) +} + +func getCurrentThreadNetNSPath() string { + // /proc/self/ns/net returns the namespace of the main thread, not + // of whatever thread this goroutine is running on. Make sure we + // use the thread's net namespace since the thread is switching around + return fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid()) +} + +// Creates a new persistent network namespace and returns an object +// representing that namespace, without switching to it +func NewNS() (NetNS, error) { + const nsRunDir = "/var/run/netns" + + b := make([]byte, 16) + _, err := rand.Reader.Read(b) + if err != nil { + return nil, fmt.Errorf("failed to generate random netns name: %v", err) + } + + err = os.MkdirAll(nsRunDir, 0755) + if err != nil { + return nil, err + } + + // create an empty file at the mount point + nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) + nsPath := path.Join(nsRunDir, nsName) + mountPointFd, err := os.Create(nsPath) + if err != nil { + return nil, err + } + mountPointFd.Close() + + // Ensure the mount point is cleaned up on errors; if the namespace + // was successfully mounted this will have no effect because the file + // is in-use + defer os.RemoveAll(nsPath) + + var wg sync.WaitGroup + wg.Add(1) + + // do namespace work in a dedicated goroutine, so that we can safely + // Lock/Unlock OSThread without upsetting the lock/unlock state of + // the caller of this function + var fd *os.File + go (func() { + defer wg.Done() + runtime.LockOSThread() + + var origNS NetNS + origNS, err = GetNS(getCurrentThreadNetNSPath()) + if err != nil { + return + } + defer origNS.Close() + + // create a new netns on the current thread + err = unix.Unshare(unix.CLONE_NEWNET) + if err != nil { + return + } + defer origNS.Set() + + // bind mount the new netns from the current thread onto the mount point + err = unix.Mount(getCurrentThreadNetNSPath(), nsPath, "none", unix.MS_BIND, "") + if err != nil { + return + } + + fd, err = os.Open(nsPath) + if err != nil { + return + } + })() + wg.Wait() + + if err != nil { + unix.Unmount(nsPath, unix.MNT_DETACH) + return nil, fmt.Errorf("failed to create namespace: %v", err) + } + + return &netNS{file: fd, mounted: true}, nil +} + +func (ns *netNS) Close() error { + if err := ns.errorIfClosed(); err != nil { + return err + } + + if err := ns.file.Close(); err != nil { + return fmt.Errorf("Failed to close %q: %v", ns.file.Name(), err) + } + ns.closed = true + + if ns.mounted { + if err := unix.Unmount(ns.file.Name(), unix.MNT_DETACH); err != nil { + return fmt.Errorf("Failed to unmount namespace %s: %v", ns.file.Name(), err) + } + if err := os.RemoveAll(ns.file.Name()); err != nil { + return fmt.Errorf("Failed to clean up namespace %s: %v", ns.file.Name(), err) + } + ns.mounted = false + } + + return nil +} + +func (ns *netNS) Set() error { + if err := ns.errorIfClosed(); err != nil { + return err + } + + if err := unix.Setns(int(ns.Fd()), unix.CLONE_NEWNET); err != nil { + return fmt.Errorf("Error switching to ns %v: %v", ns.file.Name(), err) + } + + return nil +} diff --git a/vendor/github.com/containernetworking/plugins/pkg/ns/ns_unspecified.go b/vendor/github.com/containernetworking/plugins/pkg/ns/ns_unspecified.go new file mode 100644 index 0000000000..41b446862f --- /dev/null +++ b/vendor/github.com/containernetworking/plugins/pkg/ns/ns_unspecified.go @@ -0,0 +1,36 @@ +// Copyright 2015-2017 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !linux + +package ns + +import "github.com/containernetworking/cni/pkg/types" + +// Returns an object representing the current OS thread's network namespace +func GetCurrentNS() (NetNS, error) { + return nil, types.NotImplementedError +} + +func NewNS() (NetNS, error) { + return nil, types.NotImplementedError +} + +func (ns *netNS) Close() error { + return types.NotImplementedError +} + +func (ns *netNS) Set() error { + return types.NotImplementedError +} diff --git a/vendor/github.com/miekg/dns/types_generate.go b/vendor/github.com/miekg/dns/types_generate.go deleted file mode 100644 index 53690141a1..0000000000 --- a/vendor/github.com/miekg/dns/types_generate.go +++ /dev/null @@ -1,266 +0,0 @@ -//+build ignore - -// types_generate.go is meant to run with go generate. It will use -// go/{importer,types} to track down all the RR struct types. Then for each type -// it will generate conversion tables (TypeToRR and TypeToString) and banal -// methods (len, Header, copy) based on the struct tags. The generated source is -// written to ztypes.go, and is meant to be checked into git. -package main - -import ( - "bytes" - "fmt" - "go/format" - "go/importer" - "go/types" - "log" - "os" - "strings" - "text/template" -) - -var skipLen = map[string]struct{}{ - "NSEC": struct{}{}, - "NSEC3": struct{}{}, - "OPT": struct{}{}, - "WKS": struct{}{}, - "IPSECKEY": struct{}{}, -} - -var packageHdr = ` -// *** DO NOT MODIFY *** -// AUTOGENERATED BY go generate - -package dns - -import ( - "encoding/base64" - "net" -) - -` - -var TypeToRR = template.Must(template.New("TypeToRR").Parse(` -// TypeToRR is a map of constructors for each RR type. -var TypeToRR = map[uint16]func() RR{ -{{range .}}{{if ne . "RFC3597"}} Type{{.}}: func() RR { return new({{.}}) }, -{{end}}{{end}} } - -`)) - -var typeToString = template.Must(template.New("typeToString").Parse(` -// TypeToString is a map of strings for each RR type. -var TypeToString = map[uint16]string{ -{{range .}}{{if ne . "NSAPPTR"}} Type{{.}}: "{{.}}", -{{end}}{{end}} TypeNSAPPTR: "NSAP-PTR", -} - -`)) - -var headerFunc = template.Must(template.New("headerFunc").Parse(` -// Header() functions -{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr } -{{end}} - -`)) - -// getTypeStruct will take a type and the package scope, and return the -// (innermost) struct if the type is considered a RR type (currently defined as -// those structs beginning with a RR_Header, could be redefined as implementing -// the RR interface). The bool return value indicates if embedded structs were -// resolved. -func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) { - st, ok := t.Underlying().(*types.Struct) - if !ok { - return nil, false - } - if st.Field(0).Type() == scope.Lookup("RR_Header").Type() { - return st, false - } - if st.Field(0).Anonymous() { - st, _ := getTypeStruct(st.Field(0).Type(), scope) - return st, true - } - return nil, false -} - -func main() { - // Import and type-check the package - pkg, err := importer.Default().Import("github.com/miekg/dns") - fatalIfErr(err) - scope := pkg.Scope() - - // Collect constants like TypeX - var numberedTypes []string - for _, name := range scope.Names() { - o := scope.Lookup(name) - if o == nil || !o.Exported() { - continue - } - b, ok := o.Type().(*types.Basic) - if !ok || b.Kind() != types.Uint16 { - continue - } - if !strings.HasPrefix(o.Name(), "Type") { - continue - } - name := strings.TrimPrefix(o.Name(), "Type") - if name == "PrivateRR" { - continue - } - numberedTypes = append(numberedTypes, name) - } - - // Collect actual types (*X) - var namedTypes []string - for _, name := range scope.Names() { - o := scope.Lookup(name) - if o == nil || !o.Exported() { - continue - } - if st, _ := getTypeStruct(o.Type(), scope); st == nil { - continue - } - if name == "PrivateRR" { - continue - } - - // Check if corresponding TypeX exists - if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" { - log.Fatalf("Constant Type%s does not exist.", o.Name()) - } - - namedTypes = append(namedTypes, o.Name()) - } - - b := &bytes.Buffer{} - b.WriteString(packageHdr) - - // Generate TypeToRR - fatalIfErr(TypeToRR.Execute(b, namedTypes)) - - // Generate typeToString - fatalIfErr(typeToString.Execute(b, numberedTypes)) - - // Generate headerFunc - fatalIfErr(headerFunc.Execute(b, namedTypes)) - - // Generate len() - fmt.Fprint(b, "// len() functions\n") - for _, name := range namedTypes { - if _, ok := skipLen[name]; ok { - continue - } - o := scope.Lookup(name) - st, isEmbedded := getTypeStruct(o.Type(), scope) - if isEmbedded { - continue - } - fmt.Fprintf(b, "func (rr *%s) len() int {\n", name) - fmt.Fprintf(b, "l := rr.Hdr.len()\n") - for i := 1; i < st.NumFields(); i++ { - o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) } - - if _, ok := st.Field(i).Type().(*types.Slice); ok { - switch st.Tag(i) { - case `dns:"-"`: - // ignored - case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`: - o("for _, x := range rr.%s { l += len(x) + 1 }\n") - default: - log.Fatalln(name, st.Field(i).Name(), st.Tag(i)) - } - continue - } - - switch st.Tag(i) { - case `dns:"-"`: - // ignored - case `dns:"cdomain-name"`, `dns:"domain-name"`: - o("l += len(rr.%s) + 1\n") - case `dns:"octet"`: - o("l += len(rr.%s)\n") - case `dns:"base64"`: - o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n") - case `dns:"size-hex"`, `dns:"hex"`: - o("l += len(rr.%s)/2 + 1\n") - case `dns:"a"`: - o("l += net.IPv4len // %s\n") - case `dns:"aaaa"`: - o("l += net.IPv6len // %s\n") - case `dns:"txt"`: - o("for _, t := range rr.%s { l += len(t) + 1 }\n") - case `dns:"uint48"`: - o("l += 6 // %s\n") - case "": - switch st.Field(i).Type().(*types.Basic).Kind() { - case types.Uint8: - o("l += 1 // %s\n") - case types.Uint16: - o("l += 2 // %s\n") - case types.Uint32: - o("l += 4 // %s\n") - case types.Uint64: - o("l += 8 // %s\n") - case types.String: - o("l += len(rr.%s) + 1\n") - default: - log.Fatalln(name, st.Field(i).Name()) - } - default: - log.Fatalln(name, st.Field(i).Name(), st.Tag(i)) - } - } - fmt.Fprintf(b, "return l }\n") - } - - // Generate copy() - fmt.Fprint(b, "// copy() functions\n") - for _, name := range namedTypes { - o := scope.Lookup(name) - st, isEmbedded := getTypeStruct(o.Type(), scope) - if isEmbedded { - continue - } - fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name) - fields := []string{"*rr.Hdr.copyHeader()"} - for i := 1; i < st.NumFields(); i++ { - f := st.Field(i).Name() - if sl, ok := st.Field(i).Type().(*types.Slice); ok { - t := sl.Underlying().String() - t = strings.TrimPrefix(t, "[]") - t = strings.TrimPrefix(t, "github.com/miekg/dns.") - fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n", - f, t, f, f, f) - fields = append(fields, f) - continue - } - if st.Field(i).Type().String() == "net.IP" { - fields = append(fields, "copyIP(rr."+f+")") - continue - } - fields = append(fields, "rr."+f) - } - fmt.Fprintf(b, "return &%s{%s}\n", name, strings.Join(fields, ",")) - fmt.Fprintf(b, "}\n") - } - - // gofmt - res, err := format.Source(b.Bytes()) - if err != nil { - b.WriteTo(os.Stderr) - log.Fatal(err) - } - - // write result - f, err := os.Create("ztypes.go") - fatalIfErr(err) - defer f.Close() - f.Write(res) -} - -func fatalIfErr(err error) { - if err != nil { - log.Fatal(err) - } -} diff --git a/vendor/golang.org/x/sys/unix/mkpost.go b/vendor/golang.org/x/sys/unix/mkpost.go deleted file mode 100644 index ed50d902af..0000000000 --- a/vendor/golang.org/x/sys/unix/mkpost.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -// mkpost processes the output of cgo -godefs to -// modify the generated types. It is used to clean up -// the sys API in an architecture specific manner. -// -// mkpost is run after cgo -godefs by mkall.sh. -package main - -import ( - "fmt" - "go/format" - "io/ioutil" - "log" - "os" - "regexp" -) - -func main() { - b, err := ioutil.ReadAll(os.Stdin) - if err != nil { - log.Fatal(err) - } - s := string(b) - - goarch := os.Getenv("GOARCH") - goos := os.Getenv("GOOS") - if goarch == "s390x" && goos == "linux" { - // Export the types of PtraceRegs fields. - re := regexp.MustCompile("ptrace(Psw|Fpregs|Per)") - s = re.ReplaceAllString(s, "Ptrace$1") - - // Replace padding fields inserted by cgo with blank identifiers. - re = regexp.MustCompile("Pad_cgo[A-Za-z0-9_]*") - s = re.ReplaceAllString(s, "_") - - // Replace other unwanted fields with blank identifiers. - re = regexp.MustCompile("X_[A-Za-z0-9_]*") - s = re.ReplaceAllString(s, "_") - - // Replace the control_regs union with a blank identifier for now. - re = regexp.MustCompile("(Control_regs)\\s+\\[0\\]uint64") - s = re.ReplaceAllString(s, "_ [0]uint64") - } - - // gofmt - b, err = format.Source([]byte(s)) - if err != nil { - log.Fatal(err) - } - - // Append this command to the header to show where the new file - // came from. - re := regexp.MustCompile("(cgo -godefs [a-zA-Z0-9_]+\\.go.*)") - b = re.ReplaceAll(b, []byte("$1 | go run mkpost.go")) - - fmt.Printf("%s", b) -} diff --git a/vendor/golang.org/x/sys/unix/types_darwin.go b/vendor/golang.org/x/sys/unix/types_darwin.go deleted file mode 100644 index 1153261822..0000000000 --- a/vendor/golang.org/x/sys/unix/types_darwin.go +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define __DARWIN_UNIX03 0 -#define KERNEL -#define _DARWIN_USE_64_BIT_INODE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics; for internal use. - -const ( - sizeofPtr = C.sizeofPtr - sizeofShort = C.sizeof_short - sizeofInt = C.sizeof_int - sizeofLong = C.sizeof_long - sizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timeval32 C.struct_timeval32 - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat64 - -type Statfs_t C.struct_statfs64 - -type Flock_t C.struct_flock - -type Fstore_t C.struct_fstore - -type Radvisory_t C.struct_radvisory - -type Fbootstraptransfer_t C.struct_fbootstraptransfer - -type Log2phys_t C.struct_log2phys - -type Fsid C.struct_fsid - -type Dirent C.struct_dirent - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet4Pktinfo C.struct_in_pktinfo - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2 - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfmaMsghdr2 C.struct_ifma_msghdr2 - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -// Terminal handling - -type Termios C.struct_termios - -// fchmodat-like syscalls. - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) diff --git a/vendor/golang.org/x/sys/unix/types_dragonfly.go b/vendor/golang.org/x/sys/unix/types_dragonfly.go deleted file mode 100644 index f3c971dffd..0000000000 --- a/vendor/golang.org/x/sys/unix/types_dragonfly.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics; for internal use. - -const ( - sizeofPtr = C.sizeofPtr - sizeofShort = C.sizeof_short - sizeofInt = C.sizeof_int - sizeofLong = C.sizeof_long - sizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -const ( // Directory mode bits - S_IFMT = C.S_IFMT - S_IFIFO = C.S_IFIFO - S_IFCHR = C.S_IFCHR - S_IFDIR = C.S_IFDIR - S_IFBLK = C.S_IFBLK - S_IFREG = C.S_IFREG - S_IFLNK = C.S_IFLNK - S_IFSOCK = C.S_IFSOCK - S_ISUID = C.S_ISUID - S_ISGID = C.S_ISGID - S_ISVTX = C.S_ISVTX - S_IRUSR = C.S_IRUSR - S_IWUSR = C.S_IWUSR - S_IXUSR = C.S_IXUSR -) - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.struct_fsid - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -// Terminal handling - -type Termios C.struct_termios diff --git a/vendor/golang.org/x/sys/unix/types_freebsd.go b/vendor/golang.org/x/sys/unix/types_freebsd.go deleted file mode 100644 index ae24557ad1..0000000000 --- a/vendor/golang.org/x/sys/unix/types_freebsd.go +++ /dev/null @@ -1,353 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -// This structure is a duplicate of stat on FreeBSD 8-STABLE. -// See /usr/include/sys/stat.h. -struct stat8 { -#undef st_atimespec st_atim -#undef st_mtimespec st_mtim -#undef st_ctimespec st_ctim -#undef st_birthtimespec st_birthtim - __dev_t st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - __dev_t st_rdev; -#if __BSD_VISIBLE - struct timespec st_atimespec; - struct timespec st_mtimespec; - struct timespec st_ctimespec; -#else - time_t st_atime; - long __st_atimensec; - time_t st_mtime; - long __st_mtimensec; - time_t st_ctime; - long __st_ctimensec; -#endif - off_t st_size; - blkcnt_t st_blocks; - blksize_t st_blksize; - fflags_t st_flags; - __uint32_t st_gen; - __int32_t st_lspare; -#if __BSD_VISIBLE - struct timespec st_birthtimespec; - unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec)); - unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec)); -#else - time_t st_birthtime; - long st_birthtimensec; - unsigned int :(8 / 2) * (16 - (int)sizeof(struct __timespec)); - unsigned int :(8 / 2) * (16 - (int)sizeof(struct __timespec)); -#endif -}; - -// This structure is a duplicate of if_data on FreeBSD 8-STABLE. -// See /usr/include/net/if.h. -struct if_data8 { - u_char ifi_type; - u_char ifi_physical; - u_char ifi_addrlen; - u_char ifi_hdrlen; - u_char ifi_link_state; - u_char ifi_spare_char1; - u_char ifi_spare_char2; - u_char ifi_datalen; - u_long ifi_mtu; - u_long ifi_metric; - u_long ifi_baudrate; - u_long ifi_ipackets; - u_long ifi_ierrors; - u_long ifi_opackets; - u_long ifi_oerrors; - u_long ifi_collisions; - u_long ifi_ibytes; - u_long ifi_obytes; - u_long ifi_imcasts; - u_long ifi_omcasts; - u_long ifi_iqdrops; - u_long ifi_noproto; - u_long ifi_hwassist; - time_t ifi_epoch; - struct timeval ifi_lastchange; -}; - -// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE. -// See /usr/include/net/if.h. -struct if_msghdr8 { - u_short ifm_msglen; - u_char ifm_version; - u_char ifm_type; - int ifm_addrs; - int ifm_flags; - u_short ifm_index; - struct if_data8 ifm_data; -}; -*/ -import "C" - -// Machine characteristics; for internal use. - -const ( - sizeofPtr = C.sizeofPtr - sizeofShort = C.sizeof_short - sizeofInt = C.sizeof_int - sizeofLong = C.sizeof_long - sizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -const ( // Directory mode bits - S_IFMT = C.S_IFMT - S_IFIFO = C.S_IFIFO - S_IFCHR = C.S_IFCHR - S_IFDIR = C.S_IFDIR - S_IFBLK = C.S_IFBLK - S_IFREG = C.S_IFREG - S_IFLNK = C.S_IFLNK - S_IFSOCK = C.S_IFSOCK - S_ISUID = C.S_ISUID - S_ISGID = C.S_ISGID - S_ISVTX = C.S_ISVTX - S_IRUSR = C.S_IRUSR - S_IWUSR = C.S_IWUSR - S_IXUSR = C.S_IXUSR -) - -type Stat_t C.struct_stat8 - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.struct_fsid - -// Advice to Fadvise - -const ( - FADV_NORMAL = C.POSIX_FADV_NORMAL - FADV_RANDOM = C.POSIX_FADV_RANDOM - FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL - FADV_WILLNEED = C.POSIX_FADV_WILLNEED - FADV_DONTNEED = C.POSIX_FADV_DONTNEED - FADV_NOREUSE = C.POSIX_FADV_NOREUSE -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPMreqn C.struct_ip_mreqn - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPMreqn = C.sizeof_struct_ip_mreqn - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - sizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfMsghdr = C.sizeof_struct_if_msghdr8 - sizeofIfData = C.sizeof_struct_if_data - SizeofIfData = C.sizeof_struct_if_data8 - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type ifMsghdr C.struct_if_msghdr - -type IfMsghdr C.struct_if_msghdr8 - -type ifData C.struct_if_data - -type IfData C.struct_if_data8 - -type IfaMsghdr C.struct_ifa_msghdr - -type IfmaMsghdr C.struct_ifma_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr - SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfZbuf C.struct_bpf_zbuf - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfZbufHeader C.struct_bpf_zbuf_header - -// Terminal handling - -type Termios C.struct_termios diff --git a/vendor/golang.org/x/sys/unix/types_linux.go b/vendor/golang.org/x/sys/unix/types_linux.go deleted file mode 100644 index 7dea79a8ef..0000000000 --- a/vendor/golang.org/x/sys/unix/types_linux.go +++ /dev/null @@ -1,450 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#define _FILE_OFFSET_BITS 64 -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef TCSETS2 -// On systems that have "struct termios2" use this as type Termios. -typedef struct termios2 termios_t; -#else -typedef struct termios termios_t; -#endif - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_ll s5; - struct sockaddr_nl s6; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -// copied from /usr/include/linux/un.h -struct my_sockaddr_un { - sa_family_t sun_family; -#if defined(__ARM_EABI__) || defined(__powerpc64__) - // on ARM char is by default unsigned - signed char sun_path[108]; -#else - char sun_path[108]; -#endif -}; - -#ifdef __ARM_EABI__ -typedef struct user_regs PtraceRegs; -#elif defined(__aarch64__) -typedef struct user_pt_regs PtraceRegs; -#elif defined(__powerpc64__) -typedef struct pt_regs PtraceRegs; -#elif defined(__mips__) -typedef struct user PtraceRegs; -#elif defined(__s390x__) -typedef struct _user_regs_struct PtraceRegs; -#else -typedef struct user_regs_struct PtraceRegs; -#endif - -#if defined(__s390x__) -typedef struct _user_psw_struct ptracePsw; -typedef struct _user_fpregs_struct ptraceFpregs; -typedef struct _user_per_struct ptracePer; -#else -typedef struct {} ptracePsw; -typedef struct {} ptraceFpregs; -typedef struct {} ptracePer; -#endif - -// The real epoll_event is a union, and godefs doesn't handle it well. -struct my_epoll_event { - uint32_t events; -#if defined(__ARM_EABI__) || defined(__aarch64__) - // padding is not specified in linux/eventpoll.h but added to conform to the - // alignment requirements of EABI - int32_t padFd; -#elif defined(__powerpc64__) || defined(__s390x__) - int32_t _padFd; -#endif - int32_t fd; - int32_t pad; -}; - -*/ -import "C" - -// Machine characteristics; for internal use. - -const ( - sizeofPtr = C.sizeofPtr - sizeofShort = C.sizeof_short - sizeofInt = C.sizeof_int - sizeofLong = C.sizeof_long - sizeofLongLong = C.sizeof_longlong - PathMax = C.PATH_MAX -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timex C.struct_timex - -type Time_t C.time_t - -type Tms C.struct_tms - -type Utimbuf C.struct_utimbuf - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Dirent C.struct_dirent - -type Fsid C.fsid_t - -type Flock_t C.struct_flock - -// Advice to Fadvise - -const ( - FADV_NORMAL = C.POSIX_FADV_NORMAL - FADV_RANDOM = C.POSIX_FADV_RANDOM - FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL - FADV_WILLNEED = C.POSIX_FADV_WILLNEED - FADV_DONTNEED = C.POSIX_FADV_DONTNEED - FADV_NOREUSE = C.POSIX_FADV_NOREUSE -) - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_my_sockaddr_un - -type RawSockaddrLinklayer C.struct_sockaddr_ll - -type RawSockaddrNetlink C.struct_sockaddr_nl - -type RawSockaddrHCI C.struct_sockaddr_hci - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPMreqn C.struct_ip_mreqn - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet4Pktinfo C.struct_in_pktinfo - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -type Ucred C.struct_ucred - -type TCPInfo C.struct_tcp_info - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrLinklayer = C.sizeof_struct_sockaddr_ll - SizeofSockaddrNetlink = C.sizeof_struct_sockaddr_nl - SizeofSockaddrHCI = C.sizeof_struct_sockaddr_hci - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPMreqn = C.sizeof_struct_ip_mreqn - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter - SizeofUcred = C.sizeof_struct_ucred - SizeofTCPInfo = C.sizeof_struct_tcp_info -) - -// Netlink routing and interface messages - -const ( - IFA_UNSPEC = C.IFA_UNSPEC - IFA_ADDRESS = C.IFA_ADDRESS - IFA_LOCAL = C.IFA_LOCAL - IFA_LABEL = C.IFA_LABEL - IFA_BROADCAST = C.IFA_BROADCAST - IFA_ANYCAST = C.IFA_ANYCAST - IFA_CACHEINFO = C.IFA_CACHEINFO - IFA_MULTICAST = C.IFA_MULTICAST - IFLA_UNSPEC = C.IFLA_UNSPEC - IFLA_ADDRESS = C.IFLA_ADDRESS - IFLA_BROADCAST = C.IFLA_BROADCAST - IFLA_IFNAME = C.IFLA_IFNAME - IFLA_MTU = C.IFLA_MTU - IFLA_LINK = C.IFLA_LINK - IFLA_QDISC = C.IFLA_QDISC - IFLA_STATS = C.IFLA_STATS - IFLA_COST = C.IFLA_COST - IFLA_PRIORITY = C.IFLA_PRIORITY - IFLA_MASTER = C.IFLA_MASTER - IFLA_WIRELESS = C.IFLA_WIRELESS - IFLA_PROTINFO = C.IFLA_PROTINFO - IFLA_TXQLEN = C.IFLA_TXQLEN - IFLA_MAP = C.IFLA_MAP - IFLA_WEIGHT = C.IFLA_WEIGHT - IFLA_OPERSTATE = C.IFLA_OPERSTATE - IFLA_LINKMODE = C.IFLA_LINKMODE - IFLA_LINKINFO = C.IFLA_LINKINFO - IFLA_NET_NS_PID = C.IFLA_NET_NS_PID - IFLA_IFALIAS = C.IFLA_IFALIAS - IFLA_MAX = C.IFLA_MAX - RT_SCOPE_UNIVERSE = C.RT_SCOPE_UNIVERSE - RT_SCOPE_SITE = C.RT_SCOPE_SITE - RT_SCOPE_LINK = C.RT_SCOPE_LINK - RT_SCOPE_HOST = C.RT_SCOPE_HOST - RT_SCOPE_NOWHERE = C.RT_SCOPE_NOWHERE - RT_TABLE_UNSPEC = C.RT_TABLE_UNSPEC - RT_TABLE_COMPAT = C.RT_TABLE_COMPAT - RT_TABLE_DEFAULT = C.RT_TABLE_DEFAULT - RT_TABLE_MAIN = C.RT_TABLE_MAIN - RT_TABLE_LOCAL = C.RT_TABLE_LOCAL - RT_TABLE_MAX = C.RT_TABLE_MAX - RTA_UNSPEC = C.RTA_UNSPEC - RTA_DST = C.RTA_DST - RTA_SRC = C.RTA_SRC - RTA_IIF = C.RTA_IIF - RTA_OIF = C.RTA_OIF - RTA_GATEWAY = C.RTA_GATEWAY - RTA_PRIORITY = C.RTA_PRIORITY - RTA_PREFSRC = C.RTA_PREFSRC - RTA_METRICS = C.RTA_METRICS - RTA_MULTIPATH = C.RTA_MULTIPATH - RTA_FLOW = C.RTA_FLOW - RTA_CACHEINFO = C.RTA_CACHEINFO - RTA_TABLE = C.RTA_TABLE - RTN_UNSPEC = C.RTN_UNSPEC - RTN_UNICAST = C.RTN_UNICAST - RTN_LOCAL = C.RTN_LOCAL - RTN_BROADCAST = C.RTN_BROADCAST - RTN_ANYCAST = C.RTN_ANYCAST - RTN_MULTICAST = C.RTN_MULTICAST - RTN_BLACKHOLE = C.RTN_BLACKHOLE - RTN_UNREACHABLE = C.RTN_UNREACHABLE - RTN_PROHIBIT = C.RTN_PROHIBIT - RTN_THROW = C.RTN_THROW - RTN_NAT = C.RTN_NAT - RTN_XRESOLVE = C.RTN_XRESOLVE - RTNLGRP_NONE = C.RTNLGRP_NONE - RTNLGRP_LINK = C.RTNLGRP_LINK - RTNLGRP_NOTIFY = C.RTNLGRP_NOTIFY - RTNLGRP_NEIGH = C.RTNLGRP_NEIGH - RTNLGRP_TC = C.RTNLGRP_TC - RTNLGRP_IPV4_IFADDR = C.RTNLGRP_IPV4_IFADDR - RTNLGRP_IPV4_MROUTE = C.RTNLGRP_IPV4_MROUTE - RTNLGRP_IPV4_ROUTE = C.RTNLGRP_IPV4_ROUTE - RTNLGRP_IPV4_RULE = C.RTNLGRP_IPV4_RULE - RTNLGRP_IPV6_IFADDR = C.RTNLGRP_IPV6_IFADDR - RTNLGRP_IPV6_MROUTE = C.RTNLGRP_IPV6_MROUTE - RTNLGRP_IPV6_ROUTE = C.RTNLGRP_IPV6_ROUTE - RTNLGRP_IPV6_IFINFO = C.RTNLGRP_IPV6_IFINFO - RTNLGRP_IPV6_PREFIX = C.RTNLGRP_IPV6_PREFIX - RTNLGRP_IPV6_RULE = C.RTNLGRP_IPV6_RULE - RTNLGRP_ND_USEROPT = C.RTNLGRP_ND_USEROPT - SizeofNlMsghdr = C.sizeof_struct_nlmsghdr - SizeofNlMsgerr = C.sizeof_struct_nlmsgerr - SizeofRtGenmsg = C.sizeof_struct_rtgenmsg - SizeofNlAttr = C.sizeof_struct_nlattr - SizeofRtAttr = C.sizeof_struct_rtattr - SizeofIfInfomsg = C.sizeof_struct_ifinfomsg - SizeofIfAddrmsg = C.sizeof_struct_ifaddrmsg - SizeofRtMsg = C.sizeof_struct_rtmsg - SizeofRtNexthop = C.sizeof_struct_rtnexthop -) - -type NlMsghdr C.struct_nlmsghdr - -type NlMsgerr C.struct_nlmsgerr - -type RtGenmsg C.struct_rtgenmsg - -type NlAttr C.struct_nlattr - -type RtAttr C.struct_rtattr - -type IfInfomsg C.struct_ifinfomsg - -type IfAddrmsg C.struct_ifaddrmsg - -type RtMsg C.struct_rtmsg - -type RtNexthop C.struct_rtnexthop - -// Linux socket filter - -const ( - SizeofSockFilter = C.sizeof_struct_sock_filter - SizeofSockFprog = C.sizeof_struct_sock_fprog -) - -type SockFilter C.struct_sock_filter - -type SockFprog C.struct_sock_fprog - -// Inotify - -type InotifyEvent C.struct_inotify_event - -const SizeofInotifyEvent = C.sizeof_struct_inotify_event - -// Ptrace - -// Register structures -type PtraceRegs C.PtraceRegs - -// Structures contained in PtraceRegs on s390x (exported by mkpost.go) -type ptracePsw C.ptracePsw - -type ptraceFpregs C.ptraceFpregs - -type ptracePer C.ptracePer - -// Misc - -type FdSet C.fd_set - -type Sysinfo_t C.struct_sysinfo - -type Utsname C.struct_utsname - -type Ustat_t C.struct_ustat - -type EpollEvent C.struct_my_epoll_event - -const ( - AT_FDCWD = C.AT_FDCWD - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW -) - -type PollFd C.struct_pollfd - -const ( - POLLIN = C.POLLIN - POLLPRI = C.POLLPRI - POLLOUT = C.POLLOUT - POLLRDHUP = C.POLLRDHUP - POLLERR = C.POLLERR - POLLHUP = C.POLLHUP - POLLNVAL = C.POLLNVAL -) - -type Sigset_t C.sigset_t - -// Terminal handling - -type Termios C.termios_t diff --git a/vendor/golang.org/x/sys/unix/types_netbsd.go b/vendor/golang.org/x/sys/unix/types_netbsd.go deleted file mode 100644 index d15f93d192..0000000000 --- a/vendor/golang.org/x/sys/unix/types_netbsd.go +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics; for internal use. - -const ( - sizeofPtr = C.sizeofPtr - sizeofShort = C.sizeof_short - sizeofInt = C.sizeof_int - sizeofLong = C.sizeof_long - sizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.fsid_t - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -type Mclpool C.struct_mclpool - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfTimeval C.struct_bpf_timeval - -// Terminal handling - -type Termios C.struct_termios - -// Sysctl - -type Sysctlnode C.struct_sysctlnode diff --git a/vendor/golang.org/x/sys/unix/types_openbsd.go b/vendor/golang.org/x/sys/unix/types_openbsd.go deleted file mode 100644 index b66fe25f73..0000000000 --- a/vendor/golang.org/x/sys/unix/types_openbsd.go +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics; for internal use. - -const ( - sizeofPtr = C.sizeofPtr - sizeofShort = C.sizeof_short - sizeofInt = C.sizeof_int - sizeofLong = C.sizeof_long - sizeofLongLong = C.sizeof_longlong -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -const ( // Directory mode bits - S_IFMT = C.S_IFMT - S_IFIFO = C.S_IFIFO - S_IFCHR = C.S_IFCHR - S_IFDIR = C.S_IFDIR - S_IFBLK = C.S_IFBLK - S_IFREG = C.S_IFREG - S_IFLNK = C.S_IFLNK - S_IFSOCK = C.S_IFSOCK - S_ISUID = C.S_ISUID - S_ISGID = C.S_ISGID - S_ISVTX = C.S_ISVTX - S_IRUSR = C.S_IRUSR - S_IWUSR = C.S_IWUSR - S_IXUSR = C.S_IXUSR -) - -type Stat_t C.struct_stat - -type Statfs_t C.struct_statfs - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -type Fsid C.fsid_t - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Ptrace requests - -const ( - PTRACE_TRACEME = C.PT_TRACE_ME - PTRACE_CONT = C.PT_CONTINUE - PTRACE_KILL = C.PT_KILL -) - -// Events (kqueue, kevent) - -type Kevent_t C.struct_kevent - -// Select - -type FdSet C.fd_set - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type IfAnnounceMsghdr C.struct_if_announcemsghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -type Mclpool C.struct_mclpool - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfHdr C.struct_bpf_hdr - -type BpfTimeval C.struct_bpf_timeval - -// Terminal handling - -type Termios C.struct_termios diff --git a/vendor/golang.org/x/sys/unix/types_solaris.go b/vendor/golang.org/x/sys/unix/types_solaris.go deleted file mode 100644 index c5d5c8f16a..0000000000 --- a/vendor/golang.org/x/sys/unix/types_solaris.go +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -/* -Input to cgo -godefs. See also mkerrors.sh and mkall.sh -*/ - -// +godefs map struct_in_addr [4]byte /* in_addr */ -// +godefs map struct_in6_addr [16]byte /* in6_addr */ - -package unix - -/* -#define KERNEL -// These defines ensure that builds done on newer versions of Solaris are -// backwards-compatible with older versions of Solaris and -// OpenSolaris-based derivatives. -#define __USE_SUNOS_SOCKETS__ // msghdr -#define __USE_LEGACY_PROTOTYPES__ // iovec -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - sizeofPtr = sizeof(void*), -}; - -union sockaddr_all { - struct sockaddr s1; // this one gets used for fields - struct sockaddr_in s2; // these pad it out - struct sockaddr_in6 s3; - struct sockaddr_un s4; - struct sockaddr_dl s5; -}; - -struct sockaddr_any { - struct sockaddr addr; - char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)]; -}; - -*/ -import "C" - -// Machine characteristics; for internal use. - -const ( - sizeofPtr = C.sizeofPtr - sizeofShort = C.sizeof_short - sizeofInt = C.sizeof_int - sizeofLong = C.sizeof_long - sizeofLongLong = C.sizeof_longlong - PathMax = C.PATH_MAX - MaxHostNameLen = C.MAXHOSTNAMELEN -) - -// Basic types - -type ( - _C_short C.short - _C_int C.int - _C_long C.long - _C_long_long C.longlong -) - -// Time - -type Timespec C.struct_timespec - -type Timeval C.struct_timeval - -type Timeval32 C.struct_timeval32 - -type Tms C.struct_tms - -type Utimbuf C.struct_utimbuf - -// Processes - -type Rusage C.struct_rusage - -type Rlimit C.struct_rlimit - -type _Gid_t C.gid_t - -// Files - -const ( // Directory mode bits - S_IFMT = C.S_IFMT - S_IFIFO = C.S_IFIFO - S_IFCHR = C.S_IFCHR - S_IFDIR = C.S_IFDIR - S_IFBLK = C.S_IFBLK - S_IFREG = C.S_IFREG - S_IFLNK = C.S_IFLNK - S_IFSOCK = C.S_IFSOCK - S_ISUID = C.S_ISUID - S_ISGID = C.S_ISGID - S_ISVTX = C.S_ISVTX - S_IRUSR = C.S_IRUSR - S_IWUSR = C.S_IWUSR - S_IXUSR = C.S_IXUSR -) - -type Stat_t C.struct_stat - -type Flock_t C.struct_flock - -type Dirent C.struct_dirent - -// Sockets - -type RawSockaddrInet4 C.struct_sockaddr_in - -type RawSockaddrInet6 C.struct_sockaddr_in6 - -type RawSockaddrUnix C.struct_sockaddr_un - -type RawSockaddrDatalink C.struct_sockaddr_dl - -type RawSockaddr C.struct_sockaddr - -type RawSockaddrAny C.struct_sockaddr_any - -type _Socklen C.socklen_t - -type Linger C.struct_linger - -type Iovec C.struct_iovec - -type IPMreq C.struct_ip_mreq - -type IPv6Mreq C.struct_ipv6_mreq - -type Msghdr C.struct_msghdr - -type Cmsghdr C.struct_cmsghdr - -type Inet6Pktinfo C.struct_in6_pktinfo - -type IPv6MTUInfo C.struct_ip6_mtuinfo - -type ICMPv6Filter C.struct_icmp6_filter - -const ( - SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in - SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6 - SizeofSockaddrAny = C.sizeof_struct_sockaddr_any - SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un - SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl - SizeofLinger = C.sizeof_struct_linger - SizeofIPMreq = C.sizeof_struct_ip_mreq - SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq - SizeofMsghdr = C.sizeof_struct_msghdr - SizeofCmsghdr = C.sizeof_struct_cmsghdr - SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo - SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo - SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter -) - -// Select - -type FdSet C.fd_set - -// Misc - -type Utsname C.struct_utsname - -type Ustat_t C.struct_ustat - -const ( - AT_FDCWD = C.AT_FDCWD - AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW - AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW - AT_REMOVEDIR = C.AT_REMOVEDIR - AT_EACCESS = C.AT_EACCESS -) - -// Routing and interface messages - -const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics -) - -type IfMsghdr C.struct_if_msghdr - -type IfData C.struct_if_data - -type IfaMsghdr C.struct_ifa_msghdr - -type RtMsghdr C.struct_rt_msghdr - -type RtMetrics C.struct_rt_metrics - -// Berkeley packet filter - -const ( - SizeofBpfVersion = C.sizeof_struct_bpf_version - SizeofBpfStat = C.sizeof_struct_bpf_stat - SizeofBpfProgram = C.sizeof_struct_bpf_program - SizeofBpfInsn = C.sizeof_struct_bpf_insn - SizeofBpfHdr = C.sizeof_struct_bpf_hdr -) - -type BpfVersion C.struct_bpf_version - -type BpfStat C.struct_bpf_stat - -type BpfProgram C.struct_bpf_program - -type BpfInsn C.struct_bpf_insn - -type BpfTimeval C.struct_bpf_timeval - -type BpfHdr C.struct_bpf_hdr - -// sysconf information - -const _SC_PAGESIZE = C._SC_PAGESIZE - -// Terminal handling - -type Termios C.struct_termios - -type Termio C.struct_termio - -type Winsize C.struct_winsize