// validate plugin registration for zk:// prefix is working func TestDectorFactoryNew_ZkPrefix(t *testing.T) { assert := assert.New(t) m, err := detector.New("zk://127.0.0.1:5050/mesos") assert.NoError(err) assert.IsType(&MasterDetector{}, m) md := m.(*MasterDetector) t.Logf("canceling detector") md.Cancel() }
func detectMasters(zk string, masters []string) <-chan []string { changed := make(chan []string, 1) if zk != "" { logging.Verbose.Println("Starting master detector for ZK ", zk) if md, err := detector.New(zk); err != nil { log.Fatalf("failed to create master detector: %v", err) } else if err := md.Detect(detect.NewMasters(masters, changed)); err != nil { log.Fatalf("failed to initialize master detector: %v", err) } } else { changed <- masters } return changed }
func newMesosCloud(configReader io.Reader) (*MesosCloud, error) { config, err := readConfig(configReader) if err != nil { return nil, err } log.V(1).Infof("new mesos cloud, master='%v'", config.MesosMaster) if d, err := detector.New(config.MesosMaster); err != nil { log.V(1).Infof("failed to create master detector: %v", err) return nil, err } else if cl, err := newMesosClient(d, config.MesosHttpClientTimeout.Duration, config.StateCacheTTL.Duration); err != nil { log.V(1).Infof("failed to create mesos cloud client: %v", err) return nil, err } else { return &MesosCloud{client: cl, config: config}, nil } }
func (m *Mesos) zkDetector(zkURI string) { if zkURI == "" { log.Fatal("Zookeeper address not provided") } md, err := detector.New(zkURI) if err != nil { log.Fatal(err.Error()) } m.startChan = make(chan struct{}) md.Detect(m) select { case <-m.startChan: log.Info("Done waiting for initial leader information from Zookeeper.") case <-time.After(2 * time.Minute): log.Fatal("Timed out waiting for initial ZK detection.") } }
func main() { masters := flag.String("masters", "zk://localhost:2181/mesos", "ZK Mesos masters URI") flag.Parse() log.Infof("creating ZK detector for %q", *masters) m, err := detector.New(*masters) if err != nil { log.Fatalf("failed to create ZK listener for Mesos masters: %v", err) } log.Info("created ZK detector") err = m.Detect(&zkListener{}) if err != nil { log.Fatalf("failed to register ZK listener: %v", err) } log.Info("registered ZK listener") select {} // never stop }
// Start a Zookeeper listener to track leading master, invokes callback function when // master changes are reported. func startDefaultZKdetector(zkurl string, leaderChanged func(string)) error { // start listener logging.Verbose.Println("Starting master detector for ZK ", zkurl) md, err := detector.New(zkurl) if err != nil { return fmt.Errorf("failed to create master detector: %v", err) } // and listen for master changes if err := md.Detect(detector.OnMasterChanged(func(info *mesos.MasterInfo) { leader := "" if leaderChanged != nil { defer func() { leaderChanged(leader) }() } logging.VeryVerbose.Println("Updated Zookeeper info: ", info) if info == nil { logging.Error.Println("No leader available in Zookeeper.") } else { if host := info.GetHostname(); host != "" { leader = host } else { // unpack IPv4 octets := make([]byte, 4, 4) binary.BigEndian.PutUint32(octets, info.GetIp()) ipv4 := net.IP(octets) leader = ipv4.String() } leader = fmt.Sprintf("%s:%d", leader, info.GetPort()) logging.Verbose.Println("new master in Zookeeper ", leader) } })); err != nil { return fmt.Errorf("failed to initialize master detector: %v", err) } return nil }
// Create a new mesos scheduler driver with the given // scheduler, framework info, // master address, and credential(optional) func NewMesosSchedulerDriver(config DriverConfig) (initializedDriver *MesosSchedulerDriver, err error) { if config.Scheduler == nil { err = fmt.Errorf("Scheduler callbacks required.") } else if config.Master == "" { err = fmt.Errorf("Missing master location URL.") } else if config.Framework == nil { err = fmt.Errorf("FrameworkInfo must be provided.") } else if config.Credential != nil && config.WithAuthContext == nil { err = fmt.Errorf("WithAuthContext must be provided when Credential != nil") } if err != nil { return } framework := proto.Clone(config.Framework).(*mesos.FrameworkInfo) // set default userid if framework.GetUser() == "" { user, err := user.Current() if err != nil || user == nil { if err != nil { log.Warningf("Failed to obtain username: %v\n", err) } else { log.Warningln("Failed to obtain username.") } framework.User = proto.String("") } else { framework.User = proto.String(user.Username) } } // default hostname hostname := util.GetHostname(config.HostnameOverride) if framework.GetHostname() == "" { framework.Hostname = proto.String(hostname) } driver := &MesosSchedulerDriver{ frameworkInfo: framework, stopCh: make(chan struct{}), status: mesos.Status_DRIVER_NOT_STARTED, cache: newSchedCache(), credential: config.Credential, failover: framework.Id != nil && len(framework.Id.GetValue()) > 0, withAuthContext: config.WithAuthContext, started: make(chan struct{}), done: make(chan struct{}), } driver.withScheduler = driver.makeWithScheduler(config.Scheduler) if framework.FailoverTimeout != nil && *framework.FailoverTimeout > 0 { driver.failoverTimeout = *framework.FailoverTimeout * float64(time.Second) log.V(1).Infof("found failover_timeout = %v", time.Duration(driver.failoverTimeout)) } newDetector := config.NewDetector if newDetector == nil { newDetector = func() (detector.Master, error) { return detector.New(config.Master) } } newMessenger := config.NewMessenger if newMessenger == nil { newMessenger = func() (messenger.Messenger, error) { process := process.New("scheduler") return messenger.ForHostname(process, hostname, config.BindingAddress, config.BindingPort, config.PublishedAddress) } } // initialize new detector. if driver.masterDetector, err = newDetector(); err != nil { return } else if driver.messenger, err = newMessenger(); err != nil { return } else if err = driver.init(); err != nil { return } else { initializedDriver = driver } return }
func main() { util.PanicHandlers = append(util.PanicHandlers, func(_ interface{}) { // by default the handler already logs the panic os.Exit(1) }) var versionFlag bool // parse flags cjson := flag.String("config", "config.json", "path to config file (json)") flag.BoolVar(&versionFlag, "version", false, "output the version") flag.Parse() // -version if versionFlag { fmt.Println(version) os.Exit(0) } // initialize logging logging.SetupLogs() // initialize resolver config := records.SetConfig(*cjson) res := resolver.New(version, config) errch := make(chan error) // launch DNS server if config.DNSOn { go func() { errch <- <-res.LaunchDNS() }() } // launch HTTP server if config.HTTPOn { go func() { errch <- <-res.LaunchHTTP() }() } changed := make(chan []string, 1) if config.Zk != "" { logging.Verbose.Println("Starting master detector for ZK ", config.Zk) if md, err := detector.New(config.Zk); err != nil { log.Fatalf("failed to create master detector: %v", err) } else if err := md.Detect(detect.NewMasters(config.Masters, changed)); err != nil { log.Fatalf("failed to initialize master detector: %v", err) } } else { changed <- config.Masters } reload := time.NewTicker(time.Second * time.Duration(config.RefreshSeconds)) timeout := time.AfterFunc(zkInitialDetectionTimeout, func() { errch <- fmt.Errorf("master detection timed out after %s", zkInitialDetectionTimeout) }) defer reload.Stop() defer util.HandleCrash() for { select { case <-reload.C: res.Reload() case masters := <-changed: timeout.Stop() logging.VeryVerbose.Printf("new masters detected: %v", masters) res.SetMasters(masters) res.Reload() case err := <-errch: logging.Error.Fatal(err) } } }
// Create a new mesos scheduler driver with the given // scheduler, framework info, // master address, and credential(optional) func NewMesosSchedulerDriver(config DriverConfig) (initializedDriver *MesosSchedulerDriver, err error) { if config.Scheduler == nil { err = fmt.Errorf("Scheduler callbacks required.") } else if config.Master == "" { err = fmt.Errorf("Missing master location URL.") } else if config.Framework == nil { err = fmt.Errorf("FrameworkInfo must be provided.") } else if config.Credential != nil && config.WithAuthContext == nil { err = fmt.Errorf("WithAuthContext must be provided when Credential != nil") } if err != nil { return } framework := proto.Clone(config.Framework).(*mesos.FrameworkInfo) // set default userid if framework.GetUser() == "" { user, err := user.Current() if err != nil || user == nil { if err != nil { log.Warningf("Failed to obtain username: %v\n", err) } else { log.Warningln("Failed to obtain username.") } framework.User = proto.String("") } else { framework.User = proto.String(user.Username) } } // default hostname hostname := util.GetHostname(config.HostnameOverride) if framework.GetHostname() == "" { framework.Hostname = proto.String(hostname) } driver := &MesosSchedulerDriver{ frameworkInfo: framework, stopCh: make(chan struct{}), status: mesos.Status_DRIVER_NOT_STARTED, cache: newSchedCache(), credential: config.Credential, failover: framework.Id != nil && len(framework.Id.GetValue()) > 0, withAuthContext: config.WithAuthContext, started: make(chan struct{}), } driver.eventCond = sync.NewCond(&driver.eventLock) // mechanism that allows us to asynchronously invoke scheduler callbacks, but in a manner // such that the callback invocations are serialized. useful because this will decouple the // goroutine executing a messenger callback from the goroutine executing a scheduler callback, // while preserving the serialization semantics for each type of callback handling. // we use a chan to maintain the order of callback invocations; this is important for maintaining // the order in which status updates are processed. schedQueue := make(chan func(s Scheduler)) go func() { for { select { case f := <-schedQueue: f(config.Scheduler) case <-driver.stopCh: // check for a tie: abort() may have sent a message that we need to pass up // to the user. select { case f := <-schedQueue: f(config.Scheduler) default: } return } } }() driver.withScheduler = func(f func(s Scheduler)) { select { case schedQueue <- f: case <-driver.stopCh: } } if framework.FailoverTimeout != nil && *framework.FailoverTimeout > 0 { driver.failoverTimeout = *framework.FailoverTimeout * float64(time.Second) log.V(1).Infof("found failover_timeout = %v", time.Duration(driver.failoverTimeout)) } newMessenger := config.NewMessenger if newMessenger == nil { newMessenger = func() (messenger.Messenger, error) { process := process.New("scheduler") return messenger.ForHostname(process, hostname, config.BindingAddress, config.BindingPort, config.PublishedAddress) } } // initialize new detector. if driver.masterDetector, err = detector.New(config.Master); err != nil { return } else if driver.messenger, err = newMessenger(); err != nil { return } else if err = driver.init(); err != nil { return } else { initializedDriver = driver } return }