func doNetworkGet(d *Daemon, name string) (shared.NetworkConfig, error) { // Get some information osInfo, _ := net.InterfaceByName(name) _, dbInfo, _ := dbNetworkGet(d.db, name) // Sanity check if osInfo == nil && dbInfo == nil { return shared.NetworkConfig{}, os.ErrNotExist } // Prepare the response n := shared.NetworkConfig{} n.Name = name n.UsedBy = []string{} n.Config = map[string]string{} // Look for containers using the interface cts, err := dbContainersList(d.db, cTypeRegular) if err != nil { return shared.NetworkConfig{}, err } for _, ct := range cts { c, err := containerLoadByName(d, ct) if err != nil { return shared.NetworkConfig{}, err } if networkIsInUse(c, n.Name) { n.UsedBy = append(n.UsedBy, fmt.Sprintf("/%s/containers/%s", shared.APIVersion, ct)) } } // Set the device type as needed if osInfo != nil && shared.IsLoopback(osInfo) { n.Type = "loopback" } else if dbInfo != nil || shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", n.Name)) { if dbInfo != nil { n.Managed = true n.Config = dbInfo.Config } n.Type = "bridge" } else if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/device", n.Name)) { n.Type = "physical" } else if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bonding", n.Name)) { n.Type = "bond" } else { _, err := exec.Command("ovs-vsctl", "br-exists", n.Name).CombinedOutput() if err == nil { n.Type = "bridge" } else { n.Type = "unknown" } } return n, nil }
func networkPatch(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] // Get the existing network _, dbInfo, err := dbNetworkGet(d.db, name) if dbInfo != nil { return SmartError(err) } // Validate the ETag etag := []interface{}{dbInfo.Name, dbInfo.Managed, dbInfo.Type, dbInfo.Config} err = etagCheck(r, etag) if err != nil { return PreconditionFailed(err) } req := shared.NetworkConfig{} if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return BadRequest(err) } // Config stacking if req.Config == nil { req.Config = map[string]string{} } for k, v := range dbInfo.Config { _, ok := req.Config[k] if !ok { req.Config[k] = v } } return doNetworkUpdate(d, name, dbInfo.Config, req.Config) }
func networksPost(d *Daemon, r *http.Request) Response { req := shared.NetworkConfig{} // Parse the request err := json.NewDecoder(r.Body).Decode(&req) if err != nil { return BadRequest(err) } // Sanity checks if req.Name == "" { return BadRequest(fmt.Errorf("No name provided")) } err = networkValidName(req.Name) if err != nil { return BadRequest(err) } if req.Type != "" && req.Type != "bridge" { return BadRequest(fmt.Errorf("Only 'bridge' type networks can be created")) } networks, err := networkGetInterfaces(d) if err != nil { return InternalError(err) } if shared.StringInSlice(req.Name, networks) { return BadRequest(fmt.Errorf("The network already exists")) } if req.Config == nil { req.Config = map[string]string{} } err = networkValidateConfig(req.Name, req.Config) if err != nil { return BadRequest(err) } // Set some default values where needed if req.Config["bridge.mode"] == "fan" { if req.Config["fan.underlay_subnet"] == "" { req.Config["fan.underlay_subnet"] = "auto" } } else { if req.Config["ipv4.address"] == "" { req.Config["ipv4.address"] = "auto" } if req.Config["ipv4.address"] == "auto" && req.Config["ipv4.nat"] == "" { req.Config["ipv4.nat"] = "true" } if req.Config["ipv6.address"] == "" { content, err := ioutil.ReadFile("/proc/sys/net/ipv6/conf/default/disable_ipv6") if err == nil && string(content) == "0\n" { req.Config["ipv6.address"] = "auto" } } if req.Config["ipv6.address"] == "auto" && req.Config["ipv6.nat"] == "" { req.Config["ipv6.nat"] = "true" } } // Replace "auto" by actual values err = networkFillAuto(req.Config) if err != nil { return InternalError(err) } // Create the database entry _, err = dbNetworkCreate(d.db, req.Name, req.Config) if err != nil { return InternalError( fmt.Errorf("Error inserting %s into database: %s", req.Name, err)) } // Start the network n, err := networkLoadByName(d, req.Name) if err != nil { return InternalError(err) } err = n.Start() if err != nil { n.Delete() return InternalError(err) } return SyncResponseLocation(true, nil, fmt.Sprintf("/%s/networks/%s", shared.APIVersion, req.Name)) }