// Run blocks implementing the scheduler module. func Run(conn db.Conn) { var sched scheduler for range conn.TriggerTick(30, db.MinionTable, db.EtcdTable, db.ContainerTable, db.PlacementTable).C { minion, err := conn.MinionSelf() if err != nil || !conn.EtcdLeader() || minion.Role != db.Master || minion.PrivateIP == "" { sched = nil continue } if sched == nil { ip := minion.PrivateIP sched = newSwarm(docker.New(fmt.Sprintf("tcp://%s:2377", ip))) time.Sleep(60 * time.Second) } placements := conn.SelectFromPlacement(nil) connections := conn.SelectFromConnection(nil) // Each time we run through this loop, we may boot or terminate // containers. These modification should, in turn, be reflected in the // database themselves. For this reason, we attempt to sync until no // database modifications happen (up to an arbitrary limit of three // tries). for i := 0; i < 3; i++ { dkc, err := sched.list() if err != nil { log.WithError(err).Warning("Failed to get containers.") break } var boot []db.Container var term []string conn.Transact(func(view db.Database) error { term, boot = syncDB(view, dkc) return nil }) if len(term) == 0 && len(boot) == 0 { break } sched.terminate(term) sched.boot(boot, placements, connections) } } }