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 }