func (v *Validator) network(ctx context.Context, input *data.Data, conf *config.VirtualContainerHostConfigSpec) { defer trace.End(trace.Begin("")) var e *executor.NetworkEndpoint var err error // set default portgroup if user input not provided if input.ClientNetwork.Name == "" { input.ClientNetwork.Name = input.ExternalNetwork.Name } if input.ManagementNetwork.Name == "" { input.ManagementNetwork.Name = input.ClientNetwork.Name } c := make(map[string]int) // number of VCH networks using portgroup i := make(map[string][]data.NetworkConfig) // user configured IPs for portgroup v.portGroupConfig(input, c, i) err = v.checkPortGroups(c, i) v.NoteIssue(err) err = v.configureSharedPortGroups(input, c, i) v.NoteIssue(err) // External net // external network is default for appliance e, err = v.getEndpoint(ctx, conf, input.ExternalNetwork, "external", "external", true, input.DNS) 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.ExternalNetwork.Name, "external") conf.AddNetwork(e) // Client net - defaults to connect to same portgroup as external e, err = v.getEndpoint(ctx, conf, input.ClientNetwork, "client", "client", false, input.DNS) 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.ClientNetwork.Name, "client") conf.AddNetwork(e) // Management net - defaults to connect to the same portgroup as client e, err = v.getEndpoint(ctx, conf, input.ManagementNetwork, "", "management", false, input.DNS) 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.ManagementNetwork.Name, "management") conf.AddNetwork(e) log.Debug("Network configuration:") for net, val := range conf.ExecutorConfig.Networks { log.Debugf("\tNetwork: %s NetworkEndpoint: %v", net, val) } // 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: true, IP: &net.IPNet{IP: net.IPv4zero}, // static but managed externally Network: executor.ContainerNetwork{ Common: executor.Common{ Name: "bridge", ID: netMoid, }, Type: "bridge", }, } // 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) conf.BridgeIPRange = input.BridgeIPRange 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(), }, Type: "external", 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) } v.nicNumbers(conf) }