func TestConsistencyStaleInterface(t *testing.T) { client := createTestClient() podStore := new(mocks.Store) serviceStore := new(mocks.Store) checker := NewConsistencyChecker(client, NewConfig(), podStore, serviceStore, nil) kube := mocks.NewKubeClient() controller := NewTestController(kube, client, nil, nil) netnsProject := new(types.Project) netnsProject.SetFQName("domain", []string{"default-domain", "testns"}) client.Create(netnsProject) installPods(controller, &kube.PodInterface.Mock, &podStore.Mock, "testns", 3) shutdown := make(chan struct{}) go controller.Run(shutdown) time.Sleep(100 * time.Millisecond) type shutdownMsg struct { } shutdown <- shutdownMsg{} time.Sleep(100 * time.Millisecond) serviceStore.On("List").Return([]interface{}{}) assert.True(t, checker.Check()) vmi := new(types.VirtualMachineInterface) vmi.SetFQName("project", []string{"default-domain", "testns", "pod03"}) assert.NoError(t, client.Create(vmi)) assert.False(t, checker.Check()) }
func TestReadChildren(t *testing.T) { client := new(ApiClient) client.Init() project := new(types.Project) project.SetFQName("domain", []string{"default-domain", "p1"}) assert.NoError(t, client.Create(project)) net := new(types.VirtualNetwork) net.SetFQName("project", []string{"default-domain", "p1", "n1"}) assert.NoError(t, client.Create(net)) vmi1 := new(types.VirtualMachineInterface) vmi1.SetFQName("project", []string{"default-domain", "p1", "port1"}) vmi1.AddVirtualNetwork(net) assert.NoError(t, client.Create(vmi1)) vmi2 := new(types.VirtualMachineInterface) vmi2.SetFQName("project", []string{"default-domain", "p1", "port2"}) vmi2.AddVirtualNetwork(net) assert.NoError(t, client.Create(vmi2)) refs, err := project.GetVirtualMachineInterfaces() assert.NoError(t, err) assert.Len(t, refs, 2) }
func (m *InstanceManager) LocateInstanceIp( network *types.VirtualNetwork, instanceUID string, nic *types.VirtualMachineInterface) *types.InstanceIp { tenant := nic.GetFQName()[len(nic.GetFQName())-2] name := makeInstanceIpName(tenant, nic.GetName()) obj, err := m.client.FindByName("instance-ip", name) if err == nil { // TODO(prm): ensure that attributes are as expected return obj.(*types.InstanceIp) } address, err := m.allocator.LocateIpAddress(instanceUID) if err != nil { return nil } // Create InstanceIp ipObj := new(types.InstanceIp) ipObj.SetName(name) ipObj.AddVirtualNetwork(network) ipObj.AddVirtualMachineInterface(nic) ipObj.SetInstanceIpAddress(address) ipObj.SetInstanceIpMode("active-active") err = m.client.Create(ipObj) if err != nil { glog.Errorf("Create instance-ip %s for %s: %v", address, nic.GetName(), err) return nil } obj, err = m.client.FindByUuid(ipObj.GetType(), ipObj.GetUuid()) if err != nil { glog.Errorf("Get instance-ip %s for %s: %v", address, ipObj.GetUuid(), err) return nil } return ipObj }
func TestConsistencyStaleInterface(t *testing.T) { env := new(TestFramework) env.SetUp("192.0.2.0/24") client := env.client netnsProject := new(types.Project) netnsProject.SetFQName("domain", []string{"default-domain", "testns"}) client.Create(netnsProject) env.Start() installPods(env, "testns", 3) env.SyncBarrier() env.Shutdown() assert.True(t, env.checker.Check()) vmi := new(types.VirtualMachineInterface) vmi.SetFQName("project", []string{"default-domain", "testns", "pod03"}) assert.NoError(t, client.Create(vmi)) assert.False(t, env.checker.Check()) }
func TestUpdateClearVM(t *testing.T) { client := new(ApiClient) client.Init() project := new(types.Project) project.SetFQName("domain", []string{"default-domain", "tenant"}) assert.NoError(t, client.Create(project)) vm := new(types.VirtualMachine) vm.SetFQName("project", []string{"default-domain", "tenant", "instance"}) assert.NoError(t, client.Create(vm)) vmi := new(types.VirtualMachineInterface) vmi.SetFQName("project", []string{"default-domain", "tenant", "instance"}) vmi.AddVirtualMachine(vm) assert.NoError(t, client.Create(vmi)) vmi.ClearVirtualMachine() assert.NoError(t, client.Update(vmi)) assert.NoError(t, client.Delete(vm)) }
func TestReadRefs(t *testing.T) { client := new(ApiClient) client.Init() project := new(types.Project) project.SetFQName("domain", []string{"default-domain", "p1"}) assert.NoError(t, client.Create(project)) net := new(types.VirtualNetwork) net.SetFQName("project", []string{"default-domain", "p1", "n1"}) assert.NoError(t, client.Create(net)) vmi1 := new(types.VirtualMachineInterface) vmi1.SetFQName("project", []string{"default-domain", "p1", "port1"}) vmi1.AddVirtualNetwork(net) assert.NoError(t, client.Create(vmi1)) refs, err := vmi1.GetVirtualNetworkRefs() assert.NoError(t, err) assert.Len(t, refs, 1) assert.Equal(t, net.GetUuid(), refs[0].Uuid) }
func (c *Controller) updateInstanceMetadata( pod *api.Pod, nic *types.VirtualMachineInterface, address, gateway string) { doUpdate := false if pod.Annotations == nil { pod.Annotations = make(map[string]string) doUpdate = true } var newValue, oldValue InstanceMetadata if data, ok := pod.Annotations[MetadataAnnotationTag]; ok { json.Unmarshal([]byte(data), &oldValue) } newValue.Uuid = nic.GetUuid() var mac_address string addressArr := nic.GetVirtualMachineInterfaceMacAddresses() if len(addressArr.MacAddress) > 0 { mac_address = addressArr.MacAddress[0] } else { glog.Errorf("interface %s: no mac-addresses", nic.GetName()) } newValue.MacAddress = mac_address newValue.IpAddress = address newValue.Gateway = gateway if !doUpdate && reflect.DeepEqual(newValue, oldValue) { return } encoded, err := json.Marshal(&newValue) if err != nil { glog.Errorf("JSON encode: %v", err) return } pod.Annotations[MetadataAnnotationTag] = string(encoded) _, err = c.kube.Pods(pod.Namespace).Update(pod) if err != nil { // Update will return an error if the pod object that we are // working with is stale. glog.Infof("Pod Update %s: %v", pod.Name, err) } }
func (c *Controller) updateInstanceMetadata( pod *api.Pod, nic *types.VirtualMachineInterface, address, gateway string) { doUpdate := false if pod.Annotations == nil { pod.Annotations = make(map[string]string) doUpdate = true } if updateElement(pod.Annotations, "nic_uuid", nic.GetUuid()) { doUpdate = true } var mac_address string addressArr := nic.GetVirtualMachineInterfaceMacAddresses() if len(addressArr.MacAddress) > 0 { mac_address = addressArr.MacAddress[0] } else { glog.Errorf("interface %s: no mac-addresses", nic.GetName()) } if updateElement(pod.Annotations, "mac_address", mac_address) { doUpdate = true } if updateElement(pod.Annotations, "ip_address", address) { doUpdate = true } if updateElement(pod.Annotations, "gateway", gateway) { doUpdate = true } if !doUpdate { return } _, err := c.kube.Pods(pod.Namespace).Update(pod) if err != nil { // Update will return an error if the pod object that we are // working with is stale. glog.Infof("Pod Update %s: %v", pod.Name, err) } }
func (m *InstanceManager) LocateInterface( network *types.VirtualNetwork, instance *types.VirtualMachine) *types.VirtualMachineInterface { tenant := network.GetFQName()[len(network.GetFQName())-2] fqn := interfaceFQName(m.config.DefaultDomain, tenant, instance.GetName()) obj, err := m.client.FindByName( "virtual-machine-interface", strings.Join(fqn, ":")) if err == nil { nic := obj.(*types.VirtualMachineInterface) // TODO(prm): ensure network is as expected, else update. return nic } nic := new(types.VirtualMachineInterface) nic.SetFQName("project", fqn) nic.AddVirtualMachine(instance) if network != nil { nic.AddVirtualNetwork(network) } err = m.client.Create(nic) if err != nil { glog.Errorf("Create interface %s: %v", instance.GetName(), err) return nil } obj, err = m.client.FindByUuid(nic.GetType(), nic.GetUuid()) if err != nil { glog.Errorf("Get vmi %s: %v", nic.GetUuid(), err) return nil } return obj.(*types.VirtualMachineInterface) }
func TestReadBackRefs(t *testing.T) { client := new(ApiClient) client.Init() project := new(types.Project) project.SetFQName("domain", []string{"default-domain", "p1"}) assert.NoError(t, client.Create(project)) net := new(types.VirtualNetwork) net.SetFQName("project", []string{"default-domain", "p1", "n1"}) props := new(types.VirtualNetworkType) props.ForwardingMode = "turbo" net.SetVirtualNetworkProperties(props) assert.NoError(t, client.Create(net)) vmi1 := new(types.VirtualMachineInterface) vmi1.SetFQName("project", []string{"default-domain", "p1", "port1"}) vmi1.AddVirtualNetwork(net) assert.NoError(t, client.Create(vmi1)) vmi2 := new(types.VirtualMachineInterface) vmi2.SetFQName("project", []string{"default-domain", "p1", "port2"}) vmi2.AddVirtualNetwork(net) assert.NoError(t, client.Create(vmi2)) refs, err := net.GetVirtualMachineInterfaceBackRefs() assert.NoError(t, err) assert.Len(t, refs, 2) idList := make([]string, len(refs)) for i, ref := range refs { idList[i] = ref.Uuid } assert.Contains(t, idList, vmi1.GetUuid()) assert.Contains(t, idList, vmi2.GetUuid()) rProps := net.GetVirtualNetworkProperties() assert.Equal(t, "turbo", rProps.ForwardingMode) }
func TestUpdateRefs(t *testing.T) { db := NewInMemDatabase() var instances [8]*types.VirtualMachine for i := 0; i < 8; i++ { instance := new(types.VirtualMachine) instance.SetUuid(uuid.New()) instance.SetName(fmt.Sprintf("instance-%d", i)) assert.NoError(t, db.Put(instance, nil, UIDList{})) instances[i] = instance } vmi1 := new(types.VirtualMachineInterface) vmi1.SetUuid(uuid.New()) vmi1.SetName("port1") vmi1.AddVirtualMachine(instances[0]) vmi1.AddVirtualMachine(instances[1]) vmi1.AddVirtualMachine(instances[2]) assert.NoError(t, db.Put(vmi1, nil, GetReferenceList(vmi1))) vmi2 := new(types.VirtualMachineInterface) vmi2.SetUuid(uuid.New()) vmi2.SetName("port2") vmi2.AddVirtualMachine(instances[2]) vmi2.AddVirtualMachine(instances[4]) vmi2.AddVirtualMachine(instances[3]) assert.NoError(t, db.Put(vmi2, nil, GetReferenceList(vmi2))) r2, err := db.GetBackReferences(parseUID(instances[2].GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Len(t, r2, 2) assert.Contains(t, r2, parseUID(vmi1.GetUuid())) assert.Contains(t, r2, parseUID(vmi2.GetUuid())) r3, err := db.GetBackReferences(parseUID(instances[3].GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Len(t, r3, 1) vmi2.ClearVirtualMachine() vmi2.AddVirtualMachine(instances[4]) vmi2.AddVirtualMachine(instances[6]) assert.NoError(t, db.Update(vmi2, GetReferenceList(vmi2))) r2, err = db.GetBackReferences(parseUID(instances[2].GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Len(t, r2, 1) assert.Contains(t, r2, parseUID(vmi1.GetUuid())) r3, err = db.GetBackReferences(parseUID(instances[3].GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Len(t, r3, 0) r4, err := db.GetBackReferences(parseUID(instances[4].GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Len(t, r4, 1) assert.Contains(t, r4, parseUID(vmi2.GetUuid())) vmi1.ClearVirtualMachine() vmi1.AddVirtualMachine(instances[0]) vmi1.AddVirtualMachine(instances[1]) vmi1.AddVirtualMachine(instances[5]) vmi1.AddVirtualMachine(instances[4]) assert.NoError(t, db.Update(vmi1, GetReferenceList(vmi1))) r4, err = db.GetBackReferences(parseUID(instances[4].GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Len(t, r4, 2) assert.Contains(t, r4, parseUID(vmi1.GetUuid())) assert.Contains(t, r4, parseUID(vmi2.GetUuid())) }
func TestChildrenRefs(t *testing.T) { db := NewInMemDatabase() project := new(types.Project) project.SetUuid(uuid.New()) project.SetName("p1") assert.NoError(t, db.Put(project, nil, GetReferenceList(project))) net := new(types.VirtualNetwork) net.SetUuid(uuid.New()) net.SetFQName("project", []string{"p1", "n1"}) assert.NoError(t, db.Put(net, project, UIDList{})) vmi1 := new(types.VirtualMachineInterface) vmi1.SetUuid(uuid.New()) vmi1.SetName("port1") vmi1.AddVirtualNetwork(net) assert.NoError(t, db.Put(vmi1, project, GetReferenceList(vmi1))) vmi2 := new(types.VirtualMachineInterface) vmi2.SetUuid(uuid.New()) vmi2.SetName("port2") vmi2.AddVirtualNetwork(net) assert.NoError(t, db.Put(vmi2, project, GetReferenceList(vmi2))) result, err := db.GetChildren(parseUID(project.GetUuid()), "virtual_network") assert.NoError(t, err) assert.Len(t, result, 1) result, err = db.GetChildren(parseUID(project.GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Len(t, result, 2) assert.Contains(t, result, parseUID(vmi1.GetUuid())) assert.Contains(t, result, parseUID(vmi2.GetUuid())) assert.Error(t, db.Delete(project)) assert.NoError(t, db.Delete(vmi1)) assert.Error(t, db.Delete(net)) assert.NoError(t, db.Delete(vmi2)) assert.NoError(t, db.Delete(net)) assert.NoError(t, db.Delete(project)) }
// Create floating-ip with 2 vmi references, delete it and verify that // the back_refs are updated as expected. func TestDeleteRefs(t *testing.T) { db := NewInMemDatabase() vmi1 := new(types.VirtualMachineInterface) vmi1.SetUuid(uuid.New()) vmi1.SetName("port1") assert.NoError(t, db.Put(vmi1, nil, GetReferenceList(vmi1))) vmi2 := new(types.VirtualMachineInterface) vmi2.SetUuid(uuid.New()) vmi2.SetName("port2") assert.NoError(t, db.Put(vmi2, nil, GetReferenceList(vmi2))) fip := new(types.FloatingIp) fip.SetUuid(uuid.New()) fip.SetName("fip") fip.AddVirtualMachineInterface(vmi1) fip.AddVirtualMachineInterface(vmi2) assert.NoError(t, db.Put(fip, nil, GetReferenceList(fip))) assert.Error(t, db.Delete(vmi1)) result, err := db.GetBackReferences(parseUID(vmi2.GetUuid()), "floating_ip") assert.NoError(t, err) assert.Len(t, result, 1) assert.NoError(t, db.Delete(fip)) result, err = db.GetBackReferences(parseUID(vmi2.GetUuid()), "floating_ip") assert.NoError(t, err) assert.Len(t, result, 0) assert.NoError(t, db.Delete(vmi1)) assert.NoError(t, db.Delete(vmi2)) }
func TestUpdateOne(t *testing.T) { db := NewInMemDatabase() instance := new(types.VirtualMachine) instance.SetUuid(uuid.New()) instance.SetName("instance") assert.NoError(t, db.Put(instance, nil, UIDList{})) vmi1 := new(types.VirtualMachineInterface) vmi1.SetUuid(uuid.New()) vmi1.SetName("port1") assert.NoError(t, db.Put(vmi1, nil, GetReferenceList(vmi1))) vmi1.AddVirtualMachine(instance) assert.NoError(t, db.Update(vmi1, GetReferenceList(vmi1))) result, err := db.GetBackReferences(parseUID(instance.GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Contains(t, result, parseUID(vmi1.GetUuid())) vmi1.ClearVirtualMachine() assert.NoError(t, db.Update(vmi1, GetReferenceList(vmi1))) result, err = db.GetBackReferences(parseUID(instance.GetUuid()), "virtual_machine_interface") assert.NoError(t, err) assert.Len(t, result, 0) }
func TestPodDelete(t *testing.T) { client := new(contrail_mocks.ApiClient) client.Init() allocator := new(mocks.AddressAllocator) networkMgr := new(mocks.NetworkManager) controller := NewTestController(nil, client, allocator, networkMgr) pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "test", Namespace: "testns", UID: kubetypes.UID(uuid.New()), Labels: map[string]string{ "name": "testnet", }, }, } netnsProject := new(types.Project) netnsProject.SetUuid(uuid.New()) netnsProject.SetFQName("", []string{"default-domain", "testns"}) assert.NoError(t, client.Create(netnsProject)) instance := new(types.VirtualMachine) fqn := []string{"default-domain", "testns", "test"} instance.SetFQName("project", fqn) instance.SetUuid(string(pod.ObjectMeta.UID)) assert.NoError(t, client.Create(instance)) vmi := new(types.VirtualMachineInterface) vmi.SetFQName("project", fqn) vmi.AddVirtualMachine(instance) assert.NoError(t, client.Create(vmi)) ipObj := new(types.InstanceIp) ipObj.SetName("testns_test") assert.NoError(t, client.Create(ipObj)) allocator.On("ReleaseIpAddress", string(pod.ObjectMeta.UID)).Return() networkMgr.On("ReleaseNetworkIfEmpty", "testns", "testnet").Return(true, nil) shutdown := make(chan struct{}) go controller.Run(shutdown) controller.DeletePod(pod) time.Sleep(100 * time.Millisecond) type shutdownMsg struct { } shutdown <- shutdownMsg{} if obj, err := client.FindByName("virtual-machine", strings.Join(fqn, ":")); err == nil { t.Errorf("virtual-machine object still present %s", obj.GetUuid()) } if obj, err := client.FindByUuid("virtual-machine-interface", vmi.GetUuid()); err == nil { t.Errorf("virtual-machine-interface object still present %s", obj.GetUuid()) } if obj, err := client.FindByUuid("instance-ip", ipObj.GetUuid()); err == nil { t.Errorf("instance-ip object still present %s", obj.GetUuid()) } allocator.AssertExpectations(t) }