func reserveGateway(gateway net.IP, subnet *net.IPNet, spaces []*AddressSpace) (net.IP, error) { defer trace.End(trace.Begin("")) if ip.IsUnspecifiedSubnet(subnet) { return nil, fmt.Errorf("cannot reserve gateway for nil subnet") } if !ip.IsUnspecifiedIP(gateway) { // verify gateway is routable address if !ip.IsRoutableIP(gateway, subnet) { return nil, fmt.Errorf("gateway address %s is not routable on network %s", gateway, subnet) } // optionally reserve it in one of the pools for _, p := range spaces { if err := p.ReserveIP4(gateway); err == nil { break } } return gateway, nil } // gateway is not specified, pick one from the available pools if len(spaces) > 0 { var err error if gateway, err = spaces[0].ReserveNextIP4(); err != nil { return nil, err } if !ip.IsRoutableIP(gateway, subnet) { return nil, fmt.Errorf("gateway address %s is not routable on network %s", gateway, subnet) } return gateway, nil } return nil, fmt.Errorf("could not reserve gateway address for network %s", subnet) }
func (v *Validator) network(ctx context.Context, input *data.Data, conf *config.VirtualContainerHostConfigSpec) { defer trace.End(trace.Begin("")) // External net // external network is default for appliance err := v.addNetworkHelper(ctx, conf, input.ExternalNetworkName, "external", "external", true) if err != nil { v.NoteIssue(fmt.Errorf("Error checking network for --external-network: %s", err)) v.suggestNetwork("--external-network", true) } // Bridge network should be different than all other networks v.checkNetworkConflict(input.BridgeNetworkName, input.ExternalNetworkName, "external") // Client net if input.ClientNetworkName == "" { input.ClientNetworkName = input.ExternalNetworkName } err = v.addNetworkHelper(ctx, conf, input.ClientNetworkName, "client", "client", false) if err != nil { v.NoteIssue(fmt.Errorf("Error checking network for --client-network: %s", err)) v.suggestNetwork("--client-network", true) } v.checkNetworkConflict(input.BridgeNetworkName, input.ClientNetworkName, "client") // Management net if input.ManagementNetworkName == "" { input.ManagementNetworkName = input.ClientNetworkName } err = v.addNetworkHelper(ctx, conf, input.ManagementNetworkName, "", "management", false) if err != nil { v.NoteIssue(fmt.Errorf("Error checking network for --management-network: %s", err)) v.suggestNetwork("--management-network", true) } v.checkNetworkConflict(input.BridgeNetworkName, input.ManagementNetworkName, "management") // Bridge net - // vCenter: must exist and must be a DPG // ESX: doesn't need to exist - we will create with default value // // for now we're hardcoded to "bridge" for the container host name conf.BridgeNetwork = "bridge" endpointMoref, err := v.dpgHelper(ctx, input.BridgeNetworkName) var bridgeID, netMoid string if err != nil { bridgeID = "" netMoid = "" } else { bridgeID = endpointMoref.String() netMoid = endpointMoref.String() } checkBridgeVDS := true if err != nil { if _, ok := err.(*find.NotFoundError); !ok || v.IsVC() { v.NoteIssue(fmt.Errorf("An existing distributed port group must be specified for bridge network on vCenter: %s", err)) v.suggestNetwork("--bridge-network", false) checkBridgeVDS = false // prevent duplicate error output } // this allows the dispatcher to create the network with corresponding name // if BridgeNetworkName doesn't already exist then we set the ContainerNetwork // ID to the name, but leaving the NetworkEndpoint moref as "" netMoid = input.BridgeNetworkName } bridgeNet := &executor.NetworkEndpoint{ Common: executor.Common{ Name: "bridge", ID: bridgeID, }, Static: &net.IPNet{IP: net.IPv4zero}, // static but managed externally Network: executor.ContainerNetwork{ Common: executor.Common{ Name: "bridge", ID: netMoid, }, }, } // we need to have the bridge network identified as an available container network conf.AddContainerNetwork(&bridgeNet.Network) // we also need to have the appliance attached to the bridge network to allow // port forwarding conf.AddNetwork(bridgeNet) err = v.checkVDSMembership(ctx, endpointMoref, input.BridgeNetworkName) if err != nil && checkBridgeVDS { v.NoteIssue(fmt.Errorf("Unable to check hosts in vDS for %q: %s", input.BridgeNetworkName, err)) } // add mapped networks (from --container-network) // these should be a distributed port groups in vCenter suggestedMapped := false // only suggest mapped nets once for name, net := range input.MappedNetworks { checkMappedVDS := true // "bridge" is reserved if name == "bridge" { v.NoteIssue(fmt.Errorf("Cannot use reserved name \"bridge\" for container network")) continue } gw := input.MappedNetworksGateways[name] pools := input.MappedNetworksIPRanges[name] dns := input.MappedNetworksDNS[name] if len(pools) != 0 && ip.IsUnspecifiedSubnet(&gw) { v.NoteIssue(fmt.Errorf("IP range specified without gateway for container network %q", name)) continue } if !ip.IsUnspecifiedSubnet(&gw) && !ip.IsRoutableIP(gw.IP, &gw) { v.NoteIssue(fmt.Errorf("Gateway %s is not a routable address", gw.IP)) continue } err = nil // verify ip ranges are within subnet, // and don't overlap with each other for i, r := range pools { if !gw.Contains(r.FirstIP) || !gw.Contains(r.LastIP) { err = fmt.Errorf("IP range %q is not in subnet %q", r, gw) break } for _, r2 := range pools[i+1:] { if r2.Overlaps(r) { err = fmt.Errorf("Overlapping ip ranges: %q %q", r2, r) break } } if err != nil { break } } if err != nil { v.NoteIssue(err) continue } moref, err := v.dpgHelper(ctx, net) if err != nil { v.NoteIssue(fmt.Errorf("Error adding container network %q: %s", name, err)) checkMappedVDS = false if !suggestedMapped { v.suggestNetwork("--container-network", true) suggestedMapped = true } } mappedNet := &executor.ContainerNetwork{ Common: executor.Common{ Name: name, ID: moref.String(), }, Gateway: gw, Nameservers: dns, Pools: pools, } if input.BridgeNetworkName == net { v.NoteIssue(errors.Errorf("the bridge network must not be shared with another network role - %q also mapped as container network %q", input.BridgeNetworkName, name)) } err = v.checkVDSMembership(ctx, moref, net) if err != nil && checkMappedVDS { v.NoteIssue(fmt.Errorf("Unable to check hosts in vDS for %q: %s", net, err)) } conf.AddContainerNetwork(mappedNet) } }