Beispiel #1
0
// 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()
}
Beispiel #2
0
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
}
Beispiel #3
0
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
	}
}
Beispiel #4
0
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.")
	}
}
Beispiel #5
0
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
}
Beispiel #6
0
// 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
}
Beispiel #7
0
// 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
}
Beispiel #8
0
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)
		}
	}
}
Beispiel #9
0
// 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
}