func waitStart(pChan <-chan netfilter.NFPacket, chanId uint16, waitChan chan<- uint16, hostIp string) { for true { p := <-pChan port, err := portForPacket(p) if err != nil { fmt.Println(err) p.SetVerdict(netfilter.NF_ACCEPT) waitChan <- chanId continue } id, err := port.IdentifierFor() if err != nil { fmt.Println(err) p.SetVerdict(netfilter.NF_ACCEPT) waitChan <- chanId continue } cInfo, err := systemd.Connection().GetUnitProperties(id.UnitNameFor()) if err != nil || cInfo["ActiveState"] != "active" { //TODO: Placeholder for container start detection fmt.Printf("[%v] Waiting for container %v to start\n", time.Now().Format(time.RFC3339), id) time.Sleep(time.Second * 5) fmt.Printf("[%v] Container %v started\n", time.Now().Format(time.RFC3339), id) iptables.UnidleContainer(id, hostIp) } p.SetVerdict(netfilter.NF_ACCEPT) waitChan <- chanId } }
func (idler *Idler) Run() { for i := range idler.qh { if i >= 1 { go waitStart(idler.qh[i].GetPackets(), uint16(i), idler.waitChan, idler.hostIp) } } packets := idler.qh[0].GetPackets() ticker := time.NewTicker(idler.idleTimeout) events, errors := idler.eventListener.Run() for true { select { case e := <-events: fmt.Printf("[%v] Event: %v\n", time.Now().Format(time.RFC3339), e) switch { case e.Type == containers.Stopped || e.Type == containers.Deleted || e.Type == containers.Errored: iptables.DeleteContainer(e.Id, idler.hostIp) case e.Type == containers.Started: iptables.UnidleContainer(e.Id, idler.hostIp) case e.Type == containers.Idled: //No-op } case e := <-errors: fmt.Printf("Error: %v\n", e) case chanId := <-idler.waitChan: idler.openChannels[chanId] = "" case p := <-packets: port, err := portForPacket(p) if err != nil { fmt.Println(err) p.SetVerdict(netfilter.NF_ACCEPT) continue } id, err := port.IdentifierFor() if err != nil { fmt.Println(err) iptables.CleanupRulesForPort(port) p.SetVerdict(netfilter.NF_ACCEPT) continue } idler.unidleContainer(id, p) case <-ticker.C: cpkt, err := iptables.GetDockerContainerPacketCounts(idler.d) if err != nil { fmt.Printf("Error retrieving packet counts for containers: %v\n", err) } var packetData bytes.Buffer w := new(tabwriter.Writer) w.Init(&packetData, 0, 8, 0, '\t', 0) fmt.Fprintf(w, "[%v] Packet counts:\n\tContainer\tActive?\tIdled?\tPackets\n", time.Now().Format(time.RFC3339)) iptables.ResetPacketCount() for id, pkts := range cpkt { started, err := id.UnitStartOnBoot() if err != nil { fmt.Printf("Error reading container state for %v: %v\n", id, err) } var idleFlag bool _, err = os.Stat(id.IdleUnitPathFor()) if err == nil { idleFlag = true } fmt.Fprintf(w, "\t%v\t%v\t%v\t%v", id, started, idleFlag, pkts) if started && pkts == 0 { if idler.idleContainer(id) { fmt.Fprintf(w, "\tidling...") } } fmt.Fprintf(w, "\n") } w.Flush() packetData.WriteTo(os.Stdout) fmt.Println("\n") } } }