github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/cmd/dnet/dnet.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"net"
    11  	"net/http"
    12  	"net/http/httptest"
    13  	"os"
    14  	"os/signal"
    15  	"strings"
    16  	"syscall"
    17  	"time"
    18  
    19  	"github.com/BurntSushi/toml"
    20  	"github.com/codegangsta/cli"
    21  	"github.com/docker/docker/opts"
    22  	"github.com/docker/docker/pkg/discovery"
    23  	"github.com/docker/docker/pkg/reexec"
    24  
    25  	"github.com/Sirupsen/logrus"
    26  	"github.com/docker/docker/api/types/network"
    27  	"github.com/docker/docker/pkg/term"
    28  	"github.com/docker/libnetwork"
    29  	"github.com/docker/libnetwork/api"
    30  	"github.com/docker/libnetwork/config"
    31  	"github.com/docker/libnetwork/datastore"
    32  	"github.com/docker/libnetwork/driverapi"
    33  	"github.com/docker/libnetwork/netlabel"
    34  	"github.com/docker/libnetwork/netutils"
    35  	"github.com/docker/libnetwork/options"
    36  	"github.com/docker/libnetwork/types"
    37  	"github.com/gorilla/mux"
    38  	"golang.org/x/net/context"
    39  )
    40  
    41  const (
    42  	// DefaultHTTPHost is used if only port is provided to -H flag e.g. docker -d -H tcp://:8080
    43  	DefaultHTTPHost = "0.0.0.0"
    44  	// DefaultHTTPPort is the default http port used by dnet
    45  	DefaultHTTPPort = 2385
    46  	// DefaultUnixSocket exported
    47  	DefaultUnixSocket = "/var/run/dnet.sock"
    48  	cfgFileEnv        = "LIBNETWORK_CFG"
    49  	defaultCfgFile    = "/etc/default/libnetwork.toml"
    50  	defaultHeartbeat  = time.Duration(10) * time.Second
    51  	ttlFactor         = 2
    52  )
    53  
    54  var epConn *dnetConnection
    55  
    56  func main() {
    57  	if reexec.Init() {
    58  		return
    59  	}
    60  
    61  	_, stdout, stderr := term.StdStreams()
    62  	logrus.SetOutput(stderr)
    63  
    64  	err := dnetApp(stdout, stderr)
    65  	if err != nil {
    66  		os.Exit(1)
    67  	}
    68  }
    69  
    70  // ParseConfig parses the libnetwork configuration file
    71  func (d *dnetConnection) parseOrchestrationConfig(tomlCfgFile string) error {
    72  	dummy := &dnetConnection{}
    73  
    74  	if _, err := toml.DecodeFile(tomlCfgFile, dummy); err != nil {
    75  		return err
    76  	}
    77  
    78  	if dummy.Orchestration != nil {
    79  		d.Orchestration = dummy.Orchestration
    80  	}
    81  	return nil
    82  }
    83  
    84  func (d *dnetConnection) parseConfig(cfgFile string) (*config.Config, error) {
    85  	if strings.Trim(cfgFile, " ") == "" {
    86  		cfgFile = os.Getenv(cfgFileEnv)
    87  		if strings.Trim(cfgFile, " ") == "" {
    88  			cfgFile = defaultCfgFile
    89  		}
    90  	}
    91  
    92  	if err := d.parseOrchestrationConfig(cfgFile); err != nil {
    93  		return nil, err
    94  	}
    95  	return config.ParseConfig(cfgFile)
    96  }
    97  
    98  func processConfig(cfg *config.Config) []config.Option {
    99  	options := []config.Option{}
   100  	if cfg == nil {
   101  		return options
   102  	}
   103  
   104  	dn := "bridge"
   105  	if strings.TrimSpace(cfg.Daemon.DefaultNetwork) != "" {
   106  		dn = cfg.Daemon.DefaultNetwork
   107  	}
   108  	options = append(options, config.OptionDefaultNetwork(dn))
   109  
   110  	dd := "bridge"
   111  	if strings.TrimSpace(cfg.Daemon.DefaultDriver) != "" {
   112  		dd = cfg.Daemon.DefaultDriver
   113  	}
   114  	options = append(options, config.OptionDefaultDriver(dd))
   115  
   116  	if cfg.Daemon.Labels != nil {
   117  		options = append(options, config.OptionLabels(cfg.Daemon.Labels))
   118  	}
   119  
   120  	if dcfg, ok := cfg.Scopes[datastore.GlobalScope]; ok && dcfg.IsValid() {
   121  		options = append(options, config.OptionKVProvider(dcfg.Client.Provider))
   122  		options = append(options, config.OptionKVProviderURL(dcfg.Client.Address))
   123  	}
   124  
   125  	dOptions, err := startDiscovery(&cfg.Cluster)
   126  	if err != nil {
   127  		logrus.Infof("Skipping discovery : %s", err.Error())
   128  	} else {
   129  		options = append(options, dOptions...)
   130  	}
   131  
   132  	return options
   133  }
   134  
   135  func startDiscovery(cfg *config.ClusterCfg) ([]config.Option, error) {
   136  	if cfg == nil {
   137  		return nil, fmt.Errorf("discovery requires a valid configuration")
   138  	}
   139  
   140  	hb := time.Duration(cfg.Heartbeat) * time.Second
   141  	if hb == 0 {
   142  		hb = defaultHeartbeat
   143  	}
   144  	logrus.Infof("discovery : %s $s", cfg.Discovery, hb.String())
   145  	d, err := discovery.New(cfg.Discovery, hb, ttlFactor*hb, map[string]string{})
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  
   150  	if cfg.Address == "" {
   151  		iface, err := net.InterfaceByName("eth0")
   152  		if err != nil {
   153  			return nil, err
   154  		}
   155  		addrs, err := iface.Addrs()
   156  		if err != nil || len(addrs) == 0 {
   157  			return nil, err
   158  		}
   159  		ip, _, _ := net.ParseCIDR(addrs[0].String())
   160  		cfg.Address = ip.String()
   161  	}
   162  
   163  	if ip := net.ParseIP(cfg.Address); ip == nil {
   164  		return nil, errors.New("address config should be either ipv4 or ipv6 address")
   165  	}
   166  
   167  	if err := d.Register(cfg.Address + ":0"); err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	options := []config.Option{config.OptionDiscoveryWatcher(d), config.OptionDiscoveryAddress(cfg.Address)}
   172  	go func() {
   173  		for {
   174  			select {
   175  			case <-time.After(hb):
   176  				if err := d.Register(cfg.Address + ":0"); err != nil {
   177  					logrus.Warn(err)
   178  				}
   179  			}
   180  		}
   181  	}()
   182  	return options, nil
   183  }
   184  
   185  func dnetApp(stdout, stderr io.Writer) error {
   186  	app := cli.NewApp()
   187  
   188  	app.Name = "dnet"
   189  	app.Usage = "A self-sufficient runtime for container networking."
   190  	app.Flags = dnetFlags
   191  	app.Before = processFlags
   192  	app.Commands = dnetCommands
   193  
   194  	app.Run(os.Args)
   195  	return nil
   196  }
   197  
   198  func createDefaultNetwork(c libnetwork.NetworkController) {
   199  	nw := c.Config().Daemon.DefaultNetwork
   200  	d := c.Config().Daemon.DefaultDriver
   201  	createOptions := []libnetwork.NetworkOption{}
   202  	genericOption := options.Generic{}
   203  
   204  	if nw != "" && d != "" {
   205  		// Bridge driver is special due to legacy reasons
   206  		if d == "bridge" {
   207  			genericOption[netlabel.GenericData] = map[string]string{
   208  				"BridgeName":    "docker0",
   209  				"DefaultBridge": "true",
   210  			}
   211  			createOptions = append(createOptions,
   212  				libnetwork.NetworkOptionGeneric(genericOption),
   213  				ipamOption(nw))
   214  		}
   215  
   216  		if n, err := c.NetworkByName(nw); err == nil {
   217  			logrus.Debugf("Default network %s already present. Deleting it", nw)
   218  			if err = n.Delete(); err != nil {
   219  				logrus.Debugf("Network could not be deleted: %v", err)
   220  				return
   221  			}
   222  		}
   223  
   224  		_, err := c.NewNetwork(d, nw, "", createOptions...)
   225  		if err != nil {
   226  			logrus.Errorf("Error creating default network : %s : %v", nw, err)
   227  		}
   228  	}
   229  }
   230  
   231  type dnetConnection struct {
   232  	// proto holds the client protocol i.e. unix.
   233  	proto string
   234  	// addr holds the client address.
   235  	addr          string
   236  	Orchestration *NetworkOrchestration
   237  	configEvent   chan struct{}
   238  }
   239  
   240  // NetworkOrchestration exported
   241  type NetworkOrchestration struct {
   242  	Agent   bool
   243  	Manager bool
   244  	Bind    string
   245  	Peer    string
   246  }
   247  
   248  func (d *dnetConnection) dnetDaemon(cfgFile string) error {
   249  	if err := startTestDriver(); err != nil {
   250  		return fmt.Errorf("failed to start test driver: %v\n", err)
   251  	}
   252  
   253  	cfg, err := d.parseConfig(cfgFile)
   254  	var cOptions []config.Option
   255  	if err == nil {
   256  		cOptions = processConfig(cfg)
   257  	} else {
   258  		logrus.Errorf("Error parsing config %v", err)
   259  	}
   260  
   261  	bridgeConfig := options.Generic{
   262  		"EnableIPForwarding": true,
   263  		"EnableIPTables":     true,
   264  	}
   265  
   266  	bridgeOption := options.Generic{netlabel.GenericData: bridgeConfig}
   267  
   268  	cOptions = append(cOptions, config.OptionDriverConfig("bridge", bridgeOption))
   269  
   270  	controller, err := libnetwork.New(cOptions...)
   271  	if err != nil {
   272  		fmt.Println("Error starting dnetDaemon :", err)
   273  		return err
   274  	}
   275  	controller.SetClusterProvider(d)
   276  
   277  	if d.Orchestration.Agent || d.Orchestration.Manager {
   278  		d.configEvent <- struct{}{}
   279  	}
   280  
   281  	createDefaultNetwork(controller)
   282  	httpHandler := api.NewHTTPHandler(controller)
   283  	r := mux.NewRouter().StrictSlash(false)
   284  	post := r.PathPrefix("/{.*}/networks").Subrouter()
   285  	post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
   286  	post = r.PathPrefix("/networks").Subrouter()
   287  	post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
   288  	post = r.PathPrefix("/{.*}/services").Subrouter()
   289  	post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
   290  	post = r.PathPrefix("/services").Subrouter()
   291  	post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
   292  	post = r.PathPrefix("/{.*}/sandboxes").Subrouter()
   293  	post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
   294  	post = r.PathPrefix("/sandboxes").Subrouter()
   295  	post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
   296  
   297  	handleSignals(controller)
   298  	setupDumpStackTrap()
   299  
   300  	return http.ListenAndServe(d.addr, r)
   301  }
   302  
   303  func (d *dnetConnection) IsManager() bool {
   304  	return d.Orchestration.Manager
   305  }
   306  
   307  func (d *dnetConnection) IsAgent() bool {
   308  	return d.Orchestration.Agent
   309  }
   310  
   311  func (d *dnetConnection) GetAdvertiseAddress() string {
   312  	return d.Orchestration.Bind
   313  }
   314  
   315  func (d *dnetConnection) GetLocalAddress() string {
   316  	return d.Orchestration.Bind
   317  }
   318  
   319  func (d *dnetConnection) GetListenAddress() string {
   320  	return d.Orchestration.Bind
   321  }
   322  
   323  func (d *dnetConnection) GetRemoteAddress() string {
   324  	return d.Orchestration.Peer
   325  }
   326  
   327  func (d *dnetConnection) GetNetworkKeys() []*types.EncryptionKey {
   328  	return nil
   329  }
   330  
   331  func (d *dnetConnection) SetNetworkKeys([]*types.EncryptionKey) {
   332  }
   333  
   334  func (d *dnetConnection) ListenClusterEvents() <-chan struct{} {
   335  	return d.configEvent
   336  }
   337  
   338  func (d *dnetConnection) AttachNetwork(string, string, []string) (*network.NetworkingConfig, error) {
   339  	return nil, nil
   340  }
   341  
   342  func (d *dnetConnection) DetachNetwork(string, string) error {
   343  	return nil
   344  }
   345  
   346  func (d *dnetConnection) UpdateAttachment(string, string, *network.NetworkingConfig) error {
   347  	return nil
   348  }
   349  
   350  func (d *dnetConnection) WaitForDetachment(context.Context, string, string, string, string) error {
   351  	return nil
   352  }
   353  
   354  func handleSignals(controller libnetwork.NetworkController) {
   355  	c := make(chan os.Signal, 1)
   356  	signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}
   357  	signal.Notify(c, signals...)
   358  	go func() {
   359  		for range c {
   360  			controller.Stop()
   361  			os.Exit(0)
   362  		}
   363  	}()
   364  }
   365  
   366  func startTestDriver() error {
   367  	mux := http.NewServeMux()
   368  	server := httptest.NewServer(mux)
   369  	if server == nil {
   370  		return fmt.Errorf("Failed to start an HTTP Server")
   371  	}
   372  
   373  	mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
   374  		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
   375  		fmt.Fprintf(w, `{"Implements": ["%s"]}`, driverapi.NetworkPluginEndpointType)
   376  	})
   377  
   378  	mux.HandleFunc(fmt.Sprintf("/%s.GetCapabilities", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
   379  		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
   380  		fmt.Fprintf(w, `{"Scope":"global"}`)
   381  	})
   382  
   383  	mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
   384  		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
   385  		fmt.Fprintf(w, "null")
   386  	})
   387  
   388  	mux.HandleFunc(fmt.Sprintf("/%s.DeleteNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
   389  		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
   390  		fmt.Fprintf(w, "null")
   391  	})
   392  
   393  	mux.HandleFunc(fmt.Sprintf("/%s.CreateEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
   394  		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
   395  		fmt.Fprintf(w, "null")
   396  	})
   397  
   398  	mux.HandleFunc(fmt.Sprintf("/%s.DeleteEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
   399  		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
   400  		fmt.Fprintf(w, "null")
   401  	})
   402  
   403  	mux.HandleFunc(fmt.Sprintf("/%s.Join", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
   404  		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
   405  		fmt.Fprintf(w, "null")
   406  	})
   407  
   408  	mux.HandleFunc(fmt.Sprintf("/%s.Leave", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
   409  		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
   410  		fmt.Fprintf(w, "null")
   411  	})
   412  
   413  	if err := os.MkdirAll("/etc/docker/plugins", 0755); err != nil {
   414  		return err
   415  	}
   416  
   417  	if err := ioutil.WriteFile("/etc/docker/plugins/test.spec", []byte(server.URL), 0644); err != nil {
   418  		return err
   419  	}
   420  
   421  	return nil
   422  }
   423  
   424  func newDnetConnection(val string) (*dnetConnection, error) {
   425  	url, err := opts.ParseHost(false, val)
   426  	if err != nil {
   427  		return nil, err
   428  	}
   429  	protoAddrParts := strings.SplitN(url, "://", 2)
   430  	if len(protoAddrParts) != 2 {
   431  		return nil, fmt.Errorf("bad format, expected tcp://ADDR")
   432  	}
   433  	if strings.ToLower(protoAddrParts[0]) != "tcp" {
   434  		return nil, fmt.Errorf("dnet currently only supports tcp transport")
   435  	}
   436  
   437  	return &dnetConnection{protoAddrParts[0], protoAddrParts[1], &NetworkOrchestration{}, make(chan struct{}, 10)}, nil
   438  }
   439  
   440  func (d *dnetConnection) httpCall(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) {
   441  	var in io.Reader
   442  	in, err := encodeData(data)
   443  	if err != nil {
   444  		return nil, nil, -1, err
   445  	}
   446  
   447  	req, err := http.NewRequest(method, fmt.Sprintf("%s", path), in)
   448  	if err != nil {
   449  		return nil, nil, -1, err
   450  	}
   451  
   452  	setupRequestHeaders(method, data, req, headers)
   453  
   454  	req.URL.Host = d.addr
   455  	req.URL.Scheme = "http"
   456  
   457  	httpClient := &http.Client{}
   458  	resp, err := httpClient.Do(req)
   459  	statusCode := -1
   460  	if resp != nil {
   461  		statusCode = resp.StatusCode
   462  	}
   463  	if err != nil {
   464  		return nil, nil, statusCode, fmt.Errorf("error when trying to connect: %v", err)
   465  	}
   466  
   467  	if statusCode < 200 || statusCode >= 400 {
   468  		body, err := ioutil.ReadAll(resp.Body)
   469  		if err != nil {
   470  			return nil, nil, statusCode, err
   471  		}
   472  		return nil, nil, statusCode, fmt.Errorf("error : %s", bytes.TrimSpace(body))
   473  	}
   474  
   475  	return resp.Body, resp.Header, statusCode, nil
   476  }
   477  
   478  func setupRequestHeaders(method string, data interface{}, req *http.Request, headers map[string][]string) {
   479  	if data != nil {
   480  		if headers == nil {
   481  			headers = make(map[string][]string)
   482  		}
   483  		headers["Content-Type"] = []string{"application/json"}
   484  	}
   485  
   486  	expectedPayload := (method == "POST" || method == "PUT")
   487  
   488  	if expectedPayload && req.Header.Get("Content-Type") == "" {
   489  		req.Header.Set("Content-Type", "text/plain")
   490  	}
   491  
   492  	if headers != nil {
   493  		for k, v := range headers {
   494  			req.Header[k] = v
   495  		}
   496  	}
   497  }
   498  
   499  func encodeData(data interface{}) (*bytes.Buffer, error) {
   500  	params := bytes.NewBuffer(nil)
   501  	if data != nil {
   502  		if err := json.NewEncoder(params).Encode(data); err != nil {
   503  			return nil, err
   504  		}
   505  	}
   506  	return params, nil
   507  }
   508  
   509  func ipamOption(bridgeName string) libnetwork.NetworkOption {
   510  	if nw, _, err := netutils.ElectInterfaceAddresses(bridgeName); err == nil {
   511  		ipamV4Conf := &libnetwork.IpamConf{PreferredPool: nw.String()}
   512  		hip, _ := types.GetHostPartIP(nw.IP, nw.Mask)
   513  		if hip.IsGlobalUnicast() {
   514  			ipamV4Conf.Gateway = nw.IP.String()
   515  		}
   516  		return libnetwork.NetworkOptionIpam("default", "", []*libnetwork.IpamConf{ipamV4Conf}, nil, nil)
   517  	}
   518  	return nil
   519  }