func (handler *ScopesHandlersImpl) listScopes(idName string) ([]*models.ScopeConfig, error) { _scopes, err := handler.netCtx.Scopes(&idName) if err != nil { return nil, err } cfgs := make([]*models.ScopeConfig, len(_scopes)) updated := make(map[uid.UID]*exec.Handle) for i, s := range _scopes { for _, e := range s.Endpoints() { // update the container config, if necessary // do not need do this for non-bridge scopes, since // IPAM is done by the port layer. For other // scopes types, like external, the network // may be using DHCP, in which case we need to // get the current IP address, and other network // info from the container VM. if s.Type() != network.BridgeScopeType { var h *exec.Handle c := e.Container().ID() if h = updated[c]; h == nil { h = exec.GetContainer(c) if _, err := h.Update(context.Background(), handler.handlerCtx.Session); err != nil { return nil, err } updated[c] = h } if err = handler.netCtx.UpdateContainer(h); err != nil { return nil, err } } } cfgs[i] = toScopeConfig(s) } for _, h := range updated { h.Close() } return cfgs, nil }
func (c *Context) RemoveContainer(h *exec.Handle, scope string) error { c.Lock() defer c.Unlock() if h == nil { return fmt.Errorf("handle is required") } if _, ok := c.containers[uid.Parse(h.ExecConfig.ID)]; ok { return fmt.Errorf("container is bound") } var err error s, err := c.resolveScope(scope) if err != nil { return err } var ne *executor.NetworkEndpoint ne, ok := h.ExecConfig.Networks[s.Name()] if !ok { return fmt.Errorf("container %s not part of network %s", h.ExecConfig.ID, s.Name()) } // figure out if any other networks are using the NIC removeNIC := true for _, ne2 := range h.ExecConfig.Networks { if ne2 == ne { continue } if ne2.ID == ne.ID { removeNIC = false break } } if removeNIC { // ensure spec is not nil h.SetSpec(nil) var devices object.VirtualDeviceList backing, err := s.network.EthernetCardBackingInfo(context.Background()) if err != nil { return err } d, err := devices.CreateEthernetCard("vmxnet3", backing) if err != nil { return err } devices = append(devices, d) spec, err := devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationRemove) if err != nil { return err } h.Spec.DeviceChange = append(h.Spec.DeviceChange, spec...) } delete(h.ExecConfig.Networks, s.Name()) return nil }
// AddContainer add a container to the specified scope, optionally specifying an ip address // for the container in the scope func (c *Context) AddContainer(h *exec.Handle, options *AddContainerOptions) error { c.Lock() defer c.Unlock() if h == nil { return fmt.Errorf("handle is required") } var err error s, err := c.resolveScope(options.Scope) if err != nil { return err } if h.ExecConfig.Networks != nil { if _, ok := h.ExecConfig.Networks[s.Name()]; ok { // already part of this scope return nil } // check if container is already part of an "external" scope; // only one "external" scope per container is allowed if s.Type() == ExternalScopeType { for name := range h.ExecConfig.Networks { sc, _ := c.resolveScope(name) if sc.Type() == ExternalScopeType { return fmt.Errorf("container can only be added to at most one mapped network") } } } } if err := h.SetSpec(nil); err != nil { return err } // figure out if we need to add a new NIC // if there is already a NIC connected to a // bridge network and we are adding the container // to a bridge network, we just reuse that // NIC var pciSlot int32 if s.Type() == BridgeScopeType { for _, ne := range h.ExecConfig.Networks { sc, err := c.resolveScope(ne.Network.Name) if err != nil { return err } if sc.Type() != BridgeScopeType { continue } if ne.ID != "" { pciSlot = atoiOrZero(ne.ID) if pciSlot != 0 { break } } } } if pciSlot == 0 { d, err := addEthernetCard(h, s) if err != nil { return err } pciSlot = spec.VirtualDeviceSlotNumber(d) } if h.ExecConfig.Networks == nil { h.ExecConfig.Networks = make(map[string]*executor.NetworkEndpoint) } ne := &executor.NetworkEndpoint{ Common: executor.Common{ ID: strconv.Itoa(int(pciSlot)), // Name: this would cause NIC renaming if uncommented }, Network: executor.ContainerNetwork{ Common: executor.Common{ Name: s.Name(), }, Aliases: options.Aliases, }, Ports: options.Ports, } if options.IP != nil && !options.IP.IsUnspecified() { ne.Static = &net.IPNet{ IP: *options.IP, Mask: s.Subnet().Mask, } } h.ExecConfig.Networks[s.Name()] = ne return nil }