Example #1
0
// putOffer stores an offer and the slavePID associated with offer.
func (cache *schedCache) putOffer(offer *mesos.Offer, pid *upid.UPID) {
	if offer == nil || pid == nil {
		log.V(3).Infoln("WARN: Offer not cached. The offer or pid cannot be nil")
		return
	}
	log.V(3).Infoln("Caching offer ", offer.Id.GetValue(), " with slavePID ", pid.String())
	cache.lock.Lock()
	cache.savedOffers[offer.Id.GetValue()] = &cachedOffer{offer: offer, slavePid: pid}
	cache.lock.Unlock()
}
Example #2
0
// Super-useful utility func that attempts to build a mesos.MasterInfo from a
// upid.UPID specification. An attempt is made to determine the IP address of
// the UPID's Host and any errors during such resolution will result in a nil
// returned result. A nil result is also returned upon errors parsing the Port
// specification of the UPID.
//
// TODO(jdef) make this a func of upid.UPID so that callers can invoke somePid.MasterInfo()?
//
func CreateMasterInfo(pid *upid.UPID) *mesos.MasterInfo {
	if pid == nil {
		return nil
	}
	port, err := strconv.Atoi(pid.Port)
	if err != nil {
		log.Errorf("failed to parse port: %v", err)
		return nil
	}
	//TODO(jdef) what about (future) ipv6 support?
	var ipv4 net.IP
	if ipv4 = net.ParseIP(pid.Host); ipv4 != nil {
		// This is needed for the people cross-compiling from macos to linux.
		// The cross-compiled version of net.LookupIP() fails to handle plain IPs.
		// See https://github.com/basho-labs/mesos-go/pull/117
	} else if addrs, err := net.LookupIP(pid.Host); err == nil {
		for _, ip := range addrs {
			if ip = ip.To4(); ip != nil {
				ipv4 = ip
				break
			}
		}
		if ipv4 == nil {
			log.Errorf("host does not resolve to an IPv4 address: %v", pid.Host)
			return nil
		}
	} else {
		log.Errorf("failed to lookup IPs for host '%v': %v", pid.Host, err)
		return nil
	}
	packedip := binary.BigEndian.Uint32(ipv4) // network byte order is big-endian
	mi := util.NewMasterInfo(pid.ID, packedip, uint32(port))
	mi.Pid = proto.String(pid.String())
	if pid.Host != "" {
		mi.Hostname = proto.String(pid.Host)
	}
	return mi
}
Example #3
0
func (driver *MesosSchedulerDriver) handleAuthenticationResult(from *upid.UPID, pbMsg proto.Message) {
	if driver.status != mesos.Status_DRIVER_RUNNING {
		log.V(1).Info("ignoring authenticate because driver is not running")
		return
	}
	if !from.Equal(driver.self) {
		log.Errorf("ignoring authentication result message received from upid '%v'", from)
		return
	}
	if driver.authenticated {
		// programming error
		panic("already authenticated")
	}
	if driver.masterPid == nil {
		log.Infoln("ignoring authentication result because master is lost")
		driver.authenticating.cancel() // cancel any in-progress background attempt

		// disable future retries until we get a new master
		driver.reauthenticate = false
		return
	}
	msg := pbMsg.(*mesos.InternalAuthenticationResult)
	if driver.reauthenticate || !msg.GetCompleted() || driver.masterPid.String() != msg.GetPid() {
		log.Infof("failed to authenticate with master %v: master changed", driver.masterPid)
		driver.authenticating.cancel() // cancel any in-progress background authentication
		driver.reauthenticate = false
		driver.tryAuthentication()
		return
	}
	if !msg.GetSuccess() {
		log.Errorf("master %v refused authentication", driver.masterPid)
		return
	}
	driver.authenticated = true
	go driver.doReliableRegistration(float64(registrationBackoffFactor))
}
Example #4
0
// lead master detection callback.
func (driver *MesosSchedulerDriver) handleMasterChanged(from *upid.UPID, pbMsg proto.Message) {
	if driver.status == mesos.Status_DRIVER_ABORTED {
		log.Info("Ignoring master change because the driver is aborted.")
		return
	} else if !from.Equal(driver.self) {
		log.Errorf("ignoring master changed message received from upid '%v'", from)
		return
	}

	// Reconnect every time a master is detected.
	if driver.connected {
		log.V(3).Info("Disconnecting scheduler.")
		driver.masterPid = nil
		driver.withScheduler(func(s Scheduler) { s.Disconnected(driver) })
	}

	msg := pbMsg.(*mesos.InternalMasterChangeDetected)
	master := msg.Master

	driver.connected = false
	driver.authenticated = false

	if master != nil {
		log.Infof("New master %s detected\n", master.GetPid())

		pid, err := upid.Parse(master.GetPid())
		if err != nil {
			panic("Unable to parse Master's PID value.") // this should not happen.
		}

		driver.masterPid = pid // save for downstream ops.
		driver.tryAuthentication()
	} else {
		log.Infoln("No master detected.")
	}
}
Example #5
0
// statusUpdated expects to be guarded by eventLock
func (driver *MesosSchedulerDriver) statusUpdated(from *upid.UPID, pbMsg proto.Message) {
	msg := pbMsg.(*mesos.StatusUpdateMessage)

	if driver.status != mesos.Status_DRIVER_RUNNING {
		log.V(1).Infoln("Ignoring StatusUpdate message, the driver is not running!")
		return
	}
	if !from.Equal(driver.self) {
		if !driver.connected {
			log.V(1).Infoln("Ignoring StatusUpdate message, the driver is not connected!")
			return
		}
		if !driver.masterPid.Equal(from) {
			log.Warningf("ignoring status message because it was sent from '%v' instead of leading master '%v'", from, driver.masterPid)
			return
		}
	}

	log.V(2).Infof("Received status update from %q status source %q", from.String(), msg.GetPid())

	status := msg.Update.GetStatus()

	// see https://github.com/apache/mesos/blob/master/src/sched/sched.cpp#L887
	// If the update does not have a 'uuid', it does not need
	// acknowledging. However, prior to 0.23.0, the update uuid
	// was required and always set. We also don't want to ACK updates
	// that were internally generated. In 0.24.0, we can rely on the
	// update uuid check here, until then we must still check for
	// this being sent from the driver (from == UPID()) or from
	// the master (pid == UPID()).
	// TODO(vinod): Get rid of this logic in 0.25.0 because master
	// and slave correctly set task status in 0.24.0.
	if clearUUID := len(msg.Update.Uuid) == 0 || from.Equal(driver.self) || msg.GetPid() == driver.self.String(); clearUUID {
		status.Uuid = nil
	} else {
		status.Uuid = msg.Update.Uuid
	}

	driver.withScheduler(func(s Scheduler) { s.StatusUpdate(driver, status) })

	if driver.status == mesos.Status_DRIVER_ABORTED {
		log.V(1).Infoln("Not sending StatusUpdate ACK, the driver is aborted!")
		return
	}

	// Send StatusUpdate Acknowledgement; see above for the rules.
	// Only send ACK if udpate was not from this driver and spec'd a UUID; this is compat w/ 0.23+
	ackRequired := len(msg.Update.Uuid) > 0 && !from.Equal(driver.self) && msg.GetPid() != driver.self.String()
	if ackRequired {
		ackMsg := &mesos.StatusUpdateAcknowledgementMessage{
			SlaveId:     msg.Update.SlaveId,
			FrameworkId: driver.frameworkInfo.Id,
			TaskId:      msg.Update.Status.TaskId,
			Uuid:        msg.Update.Uuid,
		}

		log.V(2).Infof("Sending ACK for status update %+v to %q", *msg.Update, from.String())
		if err := driver.send(driver.masterPid, ackMsg); err != nil {
			log.Errorf("Failed to send StatusUpdate ACK message: %v", err)
			return
		}
	} else {
		log.V(2).Infof("Not sending ACK, update is not from slave %q", from.String())
	}
}
func TestAuthticatee_validLogin(t *testing.T) {
	assert := assert.New(t)
	ctx := context.TODO()
	client := upid.UPID{
		ID:   "someFramework",
		Host: "b.net",
		Port: "789",
	}
	server := upid.UPID{
		ID:   "serv",
		Host: "a.com",
		Port: "123",
	}
	tpid := upid.UPID{
		ID:   "sasl_transport",
		Host: "g.org",
		Port: "456",
	}
	handler := callback.HandlerFunc(func(cb ...callback.Interface) error {
		for _, c := range cb {
			switch c := c.(type) {
			case *callback.Name:
				c.Set("foo")
			case *callback.Password:
				c.Set([]byte("bar"))
			case *callback.Interprocess:
				c.Set(server, client)
			default:
				return &callback.Unsupported{Callback: c}
			}
		}
		return nil
	})
	var transport *MockTransport
	factory := transportFactoryFunc(func() messenger.Messenger {
		transport = &MockTransport{messenger.NewMockedMessenger()}
		transport.On("Install").Return(nil)
		transport.On("UPID").Return(tpid)
		transport.On("Start").Return(nil)
		transport.On("Stop").Return(nil)

		mechMsg := make(chan struct{})
		stepMsg := make(chan struct{})

		transport.On("Send", mock.Anything, &server, &mesos.AuthenticateMessage{
			Pid: proto.String(client.String()),
		}).Return(nil).Run(func(_ mock.Arguments) {
			defer close(mechMsg)
			transport.Recv(&server, &mesos.AuthenticationMechanismsMessage{
				Mechanisms: []string{crammd5.Name},
			})
		}).Once()

		transport.On("Send", mock.Anything, &server, &mesos.AuthenticationStartMessage{
			Mechanism: proto.String(crammd5.Name),
		}).Return(nil).Run(func(_ mock.Arguments) {
			defer close(stepMsg)
			<-mechMsg
			transport.Recv(&server, &mesos.AuthenticationStepMessage{
				Data: []byte(`lsd;lfkgjs;dlfkgjs;dfklg`),
			})
		}).Once()

		transport.On("Send", mock.Anything, &server, &mesos.AuthenticationStepMessage{
			Data: []byte(`foo cc7fd96cd80123ea844a7dba29a594ed`),
		}).Return(nil).Run(func(_ mock.Arguments) {
			<-stepMsg
			transport.Recv(&server, &mesos.AuthenticationCompletedMessage{})
		}).Once()

		return transport
	})
	login, err := makeAuthenticatee(handler, factory)
	assert.Nil(err)

	err = login.Authenticate(ctx, handler)
	assert.Nil(err)
	assert.NotNil(transport)
	time.Sleep(1 * time.Second) // wait for the authenticator to shut down
	transport.AssertExpectations(t)
}