func (d *Dispatcher) addNetworkDevices(conf *metadata.VirtualContainerHostConfigSpec, cspec *spec.VirtualMachineConfigSpec, devices object.VirtualDeviceList) (object.VirtualDeviceList, error) { defer trace.End(trace.Begin("")) // network name:alias, to avoid create multiple devices for same network slots := make(map[int32]bool) nets := make(map[string]*metadata.NetworkEndpoint) for name, endpoint := range conf.ExecutorConfig.Networks { if pnic, ok := nets[endpoint.Network.Common.ID]; ok { // there's already a NIC on this network endpoint.Common.ID = pnic.Common.ID log.Infof("Network role %s is sharing NIC with %s", name, pnic.Network.Common.Name) continue } moref := new(types.ManagedObjectReference) if ok := moref.FromString(endpoint.Network.ID); !ok { return nil, fmt.Errorf("serialized managed object reference in unexpected format: %s", endpoint.Network.ID) } obj, err := d.session.Finder.ObjectReference(d.ctx, *moref) if err != nil { return nil, fmt.Errorf("unable to reacquire reference for network %s from serialized form: %s", endpoint.Network.Name, endpoint.Network.ID) } network, ok := obj.(object.NetworkReference) if !ok { return nil, fmt.Errorf("reacquired reference for network %s, from serialized form %s, was not a network: %T", endpoint.Network.Name, endpoint.Network.ID, obj) } backing, err := network.EthernetCardBackingInfo(d.ctx) if err != nil { err = errors.Errorf("Failed to get network backing info for %s: %s", network, err) return nil, err } nic, err := devices.CreateEthernetCard("vmxnet3", backing) if err != nil { err = errors.Errorf("Failed to create Ethernet Card spec for %s", err) return nil, err } slot := cspec.AssignSlotNumber(nic, slots) if slot == spec.NilSlot { err = errors.Errorf("Failed to assign stable PCI slot for %s network card", name) } endpoint.Common.ID = strconv.Itoa(int(slot)) slots[slot] = true log.Debugf("Setting %s to slot %d", name, slot) devices = append(devices, nic) nets[endpoint.Network.Common.ID] = endpoint } return devices, nil }
for _, ds := range dcs { if ds.GetVirtualDeviceConfigSpec().Operation == types.VirtualDeviceConfigSpecOperationAdd { d = ds.GetVirtualDeviceConfigSpec().Device dc = ds break } } if d == nil { backing, err := s.Network().EthernetCardBackingInfo(ctx) if err != nil { return nil, err } if d, err = devices.CreateEthernetCard("vmxnet3", backing); err != nil { return nil, err } d.GetVirtualDevice().DeviceInfo = &types.Description{ Label: s.name, } } if spec.VirtualDeviceSlotNumber(d) == spec.NilSlot { slots := make(map[int32]bool) for _, e := range h.ExecConfig.Networks { if e.Common.ID != "" { slot, err := strconv.Atoi(e.Common.ID) if err == nil { slots[int32(slot)] = true
func (c *Context) RemoveContainer(h *exec.Handle, scope string) error { defer trace.End(trace.Begin("")) c.Lock() defer c.Unlock() if h == nil { return fmt.Errorf("handle is required") } if con, _ := c.container(h); con != nil { 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 { 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 }
func TestContextAddContainer(t *testing.T) { ctx, err := NewContext(net.IPNet{IP: net.IPv4(172, 16, 0, 0), Mask: net.CIDRMask(12, 32)}, net.CIDRMask(16, 32)) if err != nil { t.Fatalf("NewContext() => (nil, %s), want (ctx, nil)", err) return } h := exec.NewContainer("foo") var devices object.VirtualDeviceList backing, _ := ctx.DefaultScope().Network().EthernetCardBackingInfo(context.TODO()) specWithEthCard := &spec.VirtualMachineConfigSpec{ VirtualMachineConfigSpec: &types.VirtualMachineConfigSpec{}, } var d types.BaseVirtualDevice if d, err = devices.CreateEthernetCard("vmxnet3", backing); err == nil { d.GetVirtualDevice().SlotInfo = &types.VirtualDevicePciBusSlotInfo{ PciSlotNumber: 1111, } devices = append(devices, d) var cs []types.BaseVirtualDeviceConfigSpec if cs, err = devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd); err == nil { specWithEthCard.DeviceChange = cs } } if err != nil { t.Fatalf(err.Error()) } aecErr := func(_ *exec.Handle, _ *Scope) (types.BaseVirtualDevice, error) { return nil, fmt.Errorf("error") } otherScope, err := ctx.NewScope(BridgeScopeType, "other", nil, net.IPv4(0, 0, 0, 0), nil, nil) if err != nil { t.Fatalf("failed to add scope") } hBar := exec.NewContainer(uid.New()) var tests = []struct { aec func(h *exec.Handle, s *Scope) (types.BaseVirtualDevice, error) h *exec.Handle s *spec.VirtualMachineConfigSpec scope string ip *net.IP err error }{ // nil handle {nil, nil, nil, "", nil, fmt.Errorf("")}, // scope not found {nil, h, nil, "foo", nil, ResourceNotFoundError{}}, // addEthernetCard returns error {aecErr, h, nil, "default", nil, fmt.Errorf("")}, // add a container {nil, h, nil, "default", nil, nil}, // container already added {nil, h, nil, "default", nil, nil}, {nil, hBar, specWithEthCard, "default", nil, nil}, {nil, hBar, nil, otherScope.Name(), nil, nil}, } origAEC := addEthernetCard defer func() { addEthernetCard = origAEC }() for i, te := range tests { // setup addEthernetCard = origAEC scopy := &spec.VirtualMachineConfigSpec{} if te.h != nil { te.h.SetSpec(te.s) if te.h.Spec != nil { *scopy = *te.h.Spec } } if te.aec != nil { addEthernetCard = te.aec } options := &AddContainerOptions{ Scope: te.scope, IP: te.ip, } err := ctx.AddContainer(te.h, options) if te.err != nil { // expect an error if err == nil { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) => nil want err", i, te.h, te.scope, te.ip) } if reflect.TypeOf(err) != reflect.TypeOf(te.err) { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) => (%v, %v) want (%v, %v)", i, te.h, te.scope, te.ip, err, te.err, err, te.err) } if _, ok := te.err.(DuplicateResourceError); ok { continue } // verify no device changes in the spec if te.s != nil { if len(scopy.DeviceChange) != len(h.Spec.DeviceChange) { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) added device", i, te.h, te.scope, te.ip) } } continue } if err != nil { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) => %s want nil", i, te.h, te.scope, te.ip, err) } // verify the container was not added to the scope s, _ := ctx.resolveScope(te.scope) if s != nil && te.h != nil { c := s.Container(uid.Parse(te.h.Container.ExecConfig.ID)) if c != nil { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) added container", i, te.h, te.scope, te.ip) } } // spec should have a nic attached to the scope's network var dev types.BaseVirtualDevice dcs, err := te.h.Spec.FindNICs(context.TODO(), s.Network()) if len(dcs) != 1 { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) more than one NIC added for scope %s", i, te.h, te.scope, te.ip, s.Network()) } dev = dcs[0].GetVirtualDeviceConfigSpec().Device if spec.VirtualDeviceSlotNumber(dev) == spec.NilSlot { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) NIC added has nil pci slot", i, te.h, te.scope, te.ip) } // spec metadata should be updated with endpoint info ne, ok := te.h.ExecConfig.Networks[s.Name()] if !ok { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) no network endpoint info added", i, te.h, te.scope, te.ip) } if spec.VirtualDeviceSlotNumber(dev) != atoiOrZero(ne.ID) { t.Fatalf("case %d; ctx.AddContainer(%v, %s, %s) => ne.ID == %d, want %d", i, te.h, te.scope, te.ip, atoiOrZero(ne.ID), spec.VirtualDeviceSlotNumber(dev)) } if ne.Network.Name != s.Name() { t.Fatalf("case %d; ctx.AddContainer(%v, %s, %s) => ne.NetworkName == %s, want %s", i, te.h, te.scope, te.ip, ne.Network.Name, s.Name()) } if te.ip != nil && !te.ip.Equal(ne.Static.IP) { t.Fatalf("case %d; ctx.AddContainer(%v, %s, %s) => ne.Static.IP == %s, want %s", i, te.h, te.scope, te.ip, ne.Static.IP, te.ip) } if te.ip == nil && ne.Static != nil { t.Fatalf("case %d; ctx.AddContainer(%v, %s, %s) => ne.Static.IP == %s, want %s", i, te.h, te.scope, te.ip, ne.Static.IP, net.IPv4zero) } } }