func handleContainerStop(netPlugin *plugin.NetPlugin, crt *crt.CRT, opts *cliOpts, contID string) error { // If CONTIV_DIND_HOST_GOPATH env variable is set we can assume we are in docker in docker testbed // Here we need to set the network namespace of the ports created by netplugin back to NS of the docker host hostGoPath := os.Getenv("CONTIV_DIND_HOST_GOPATH") if hostGoPath != "" { osCmd := exec.Command("github.com/contiv/netplugin/scripts/dockerhost/setlocalns.sh") osCmd.Dir = os.Getenv("GOSRC") output, err := osCmd.Output() if err != nil { log.Errorf("setlocalns failed. Error: %s Output: \n%s\n", err, output) return err } return err } if opts.forceDeleteEp { log.Infof("deleting operEp for container with uuid %s \n", contID) epIDs, err := getEpIDByContainerUUID(netPlugin, contID) if err != nil { log.Errorf("error obtaining container's epid for uuid %s: %v \n", contID, err) return err } for _, epID := range epIDs { err = netPlugin.DeleteEndpoint(epID) if err != nil { log.Errorf("error deleting an endpoint upon container stop: %v \n", err) return err } } } return nil }
// delete master node func deleteMaster(netplugin *plugin.NetPlugin, srvInfo core.ServiceInfo) error { // delete from the db delete(masterDB, masterKey(srvInfo)) // tel plugin about it return netplugin.DeleteMaster(srvInfo) }
func createContainerEpOper(netPlugin *plugin.NetPlugin, contUUID, contName string) error { epIDs, err := getEpIDByContainerName(netPlugin, contName) if err != nil { log.Debugf("unable to find ep for container %s, error %v\n", contName, err) return err } for _, epID := range epIDs { operEp := &drivers.OvsOperEndpointState{} operEp.StateDriver = netPlugin.StateDriver err = operEp.Read(epID) if core.ErrIfKeyExists(err) != nil { return err } if err == nil { operEp.ContUUID = contUUID err = operEp.Write() if err != nil { log.Errorf("error updating oper state for ep %s \n", contName) return err } log.Infof("updating container '%s' with id '%s' \n", contName, contUUID) } else { err = netPlugin.CreateEndpoint(epID) if err != nil { log.Errorf("Endpoint creation failed. Error: %s", err) return err } log.Infof("Endpoint operation create succeeded") } } return err }
// Add a master node func addMaster(netplugin *plugin.NetPlugin, srvInfo core.ServiceInfo) error { // save it in db masterDB[masterKey(srvInfo)] = &srvInfo // tell the plugin about the master return netplugin.AddMaster(srvInfo) }
func processPeerEvent(netPlugin *plugin.NetPlugin, opts cliOpts, peerID string, isDelete bool) (err error) { // if this is our own peer info coming back to us, ignore it if peerID == opts.hostLabel { return nil } // take a lock to ensure we are programming one event at a time. netPlugin.Lock() defer func() { netPlugin.Unlock() }() operStr := "" if isDelete { err = netPlugin.DeletePeerHost(peerID) operStr = "delete" } else { err = netPlugin.CreatePeerHost(peerID) operStr = "create" } if err != nil { log.Errorf("PeerHost operation %s failed. Error: %s", operStr, err) } else { log.Infof("PeerHost operation %s succeeded", operStr) } return }
func processNetEvent(netPlugin *plugin.NetPlugin, netID string, isDelete bool) (err error) { // take a lock to ensure we are programming one event at a time. // Also network create events need to be processed before endpoint creates // and reverse shall happen for deletes. That order is ensured by netmaster, // so we don't need to worry about that here netPlugin.Lock() defer func() { netPlugin.Unlock() }() operStr := "" if isDelete { err = netPlugin.DeleteNetwork(netID) operStr = "delete" } else { err = netPlugin.CreateNetwork(netID) operStr = "create" } if err != nil { log.Errorf("Network operation %s failed. Error: %s", operStr, err) } else { log.Infof("Network operation %s succeeded", operStr) } return }
func processPeerEvent(netPlugin *plugin.NetPlugin, opts cliOpts, peerInfo *drivers.PeerHostState, isDelete bool) (err error) { // if this is our own peer info coming back to us, ignore it if peerInfo.ID == opts.hostLabel { return nil } nodeInfo := core.ServiceInfo{ HostAddr: peerInfo.HostAddr, Port: 0, } // take a lock to ensure we are programming one event at a time. netPlugin.Lock() defer func() { netPlugin.Unlock() }() operStr := "" if isDelete { err = netPlugin.DeletePeerHost(nodeInfo) operStr = "delete" } else { err = netPlugin.AddPeerHost(nodeInfo) operStr = "create" } if err != nil { log.Errorf("PeerHost operation %s failed. Error: %s", operStr, err) } else { log.Infof("PeerHost operation %s succeeded", operStr) } return }
// Main loop to discover peer hosts and masters func peerDiscoveryLoop(netplugin *plugin.NetPlugin, objdbClient objdb.ObjdbApi) { // Create channels for watch thread nodeEventCh := make(chan objdb.WatchServiceEvent, 1) watchStopCh := make(chan bool, 1) masterEventCh := make(chan objdb.WatchServiceEvent, 1) masterWatchStopCh := make(chan bool, 1) // Get the local address localIP, err := objdbClient.GetLocalAddr() if err != nil { log.Fatalf("Error getting locla IP address. Err: %v", err) } // Start a watch on netplugin service so that we dont miss any err = objdbClient.WatchService("netplugin", nodeEventCh, watchStopCh) if err != nil { log.Fatalf("Could not start a watch on netplugin service. Err: %v", err) } // Start a watch on netmaster too err = objdbClient.WatchService("netmaster", masterEventCh, masterWatchStopCh) if err != nil { log.Fatalf("Could not start a watch on netmaster service. Err: %v", err) } // Get a list of all existing netplugin nodes nodeList, err := objdbClient.GetService("netplugin") if err != nil { log.Errorf("Error getting node list from objdb. Err: %v", err) } log.Infof("Got netplugin service list: %+v", nodeList) // walk each node and add it as a PeerHost for _, node := range nodeList { // Ignore if its our own info if node.HostAddr == localIP { continue } // add the node err := netplugin.AddPeerHost(core.ServiceInfo{ HostAddr: node.HostAddr, Port: ofnet.OFNET_AGENT_PORT, }) if err != nil { log.Errorf("Error adding node {%+v}. Err: %v", node, err) } } // Get a list of all existing netmasters masterList, err := objdbClient.GetService("netmaster") if err != nil { log.Errorf("Error getting master list from objdb. Err: %v", err) } log.Infof("Got netmaster service list: %+v", masterList) // Walk each master and add it for _, master := range masterList { // Add the master err := netplugin.AddMaster(core.ServiceInfo{ HostAddr: master.HostAddr, Port: ofnet.OFNET_MASTER_PORT, }) if err != nil { log.Errorf("Error adding master {%+v}. Err: %v", master, err) } } for { select { case srvEvent := <-nodeEventCh: log.Infof("Received netplugin service watch event: %+v", srvEvent) // collect the info about the node nodeInfo := srvEvent.ServiceInfo // check if its our on info coming back to us if nodeInfo.HostAddr == localIP { break } // Handle based on event type if srvEvent.EventType == objdb.WatchServiceEventAdd { log.Infof("Node add event for {%+v}", nodeInfo) // add the node err := netplugin.AddPeerHost(core.ServiceInfo{ HostAddr: nodeInfo.HostAddr, Port: ofnet.OFNET_AGENT_PORT, }) if err != nil { log.Errorf("Error adding node {%+v}. Err: %v", nodeInfo, err) } } else if srvEvent.EventType == objdb.WatchServiceEventDel { log.Infof("Node delete event for {%+v}", nodeInfo) // remove the node err := netplugin.DeletePeerHost(core.ServiceInfo{ HostAddr: nodeInfo.HostAddr, Port: ofnet.OFNET_AGENT_PORT, }) if err != nil { log.Errorf("Error adding node {%+v}. Err: %v", nodeInfo, err) } } case srvEvent := <-masterEventCh: log.Infof("Received netmaster service watch event: %+v", srvEvent) // collect the info about the node nodeInfo := srvEvent.ServiceInfo // Handle based on event type if srvEvent.EventType == objdb.WatchServiceEventAdd { log.Infof("Master add event for {%+v}", nodeInfo) // Add the master err := netplugin.AddMaster(core.ServiceInfo{ HostAddr: nodeInfo.HostAddr, Port: ofnet.OFNET_MASTER_PORT, }) if err != nil { log.Errorf("Error adding master {%+v}. Err: %v", nodeInfo, err) } } else if srvEvent.EventType == objdb.WatchServiceEventDel { log.Infof("Master delete event for {%+v}", nodeInfo) // Delete the master err := netplugin.DeleteMaster(core.ServiceInfo{ HostAddr: nodeInfo.HostAddr, Port: nodeInfo.Port, }) if err != nil { log.Errorf("Error deletin master {%+v}. Err: %v", nodeInfo, err) } } } } }
func processEpEvent(netPlugin *plugin.NetPlugin, crt *crt.CRT, opts cliOpts, epID string, isDelete bool) (err error) { // take a lock to ensure we are programming one event at a time. // Also network create events need to be processed before endpoint creates // and reverse shall happen for deletes. That order is ensured by netmaster, // so we don't need to worry about that here netPlugin.Lock() defer func() { netPlugin.Unlock() }() homingHost := "" vtepIP := "" if !isDelete { epCfg := &drivers.OvsCfgEndpointState{} epCfg.StateDriver = netPlugin.StateDriver err = epCfg.Read(epID) if err != nil { log.Errorf("Failed to read config for ep '%s' \n", epID) return } homingHost = epCfg.HomingHost vtepIP = epCfg.VtepIP } else { epOper := &drivers.OvsOperEndpointState{} epOper.StateDriver = netPlugin.StateDriver err = epOper.Read(epID) if err != nil { log.Errorf("Failed to read oper for ep %s, err '%s' \n", epID, err) return } homingHost = epOper.HomingHost vtepIP = epOper.VtepIP } if skipHost(vtepIP, homingHost, opts.hostLabel) { log.Infof("skipping mismatching host for ep %s. EP's host %s (my host: %s)", epID, homingHost, opts.hostLabel) return } // read the context before to be compared with what changed after contEpContext, err := getEndpointContainerContext( netPlugin.StateDriver, epID) if err != nil { log.Errorf("Failed to obtain the container context for ep '%s' \n", epID) return } log.Debugf("read endpoint context: %s \n", contEpContext) operStr := "" if isDelete { err = netPlugin.DeleteEndpoint(epID) operStr = "delete" } else { err = netPlugin.CreateEndpoint(epID) operStr = "create" } if err != nil { log.Errorf("Endpoint operation %s failed. Error: %s", operStr, err) return } log.Infof("Endpoint operation %s succeeded", operStr) // attach or detach an endpoint to a container if isDelete || contAttachPointDeleted(contEpContext) { err = crt.ContainerIf.DetachEndpoint(contEpContext) if err != nil { log.Errorf("Endpoint detach container '%s' from ep '%s' failed . "+ "Error: %s", contEpContext.CurrContName, epID, err) } else { log.Infof("Endpoint detach container '%s' from ep '%s' succeeded", contEpContext.CurrContName, epID) } } if !isDelete && contAttachPointAdded(contEpContext) { // re-read post ep updated state newContEpContext, err1 := getEndpointContainerContext( netPlugin.StateDriver, epID) if err1 != nil { log.Errorf("Failed to obtain the container context for ep '%s' \n", epID) return } contEpContext.InterfaceID = newContEpContext.InterfaceID contEpContext.IPAddress = newContEpContext.IPAddress contEpContext.SubnetLen = newContEpContext.SubnetLen err = crt.ContainerIf.AttachEndpoint(contEpContext) if err != nil { log.Errorf("Endpoint attach container '%s' to ep '%s' failed . "+ "Error: %s", contEpContext.NewContName, epID, err) } else { log.Infof("Endpoint attach container '%s' to ep '%s' succeeded", contEpContext.NewContName, epID) } contID := crt.ContainerIf.GetContainerID(contEpContext.NewContName) if contID != "" { } } return }