Commit 11c53207 authored by Dawn Chen's avatar Dawn Chen Committed by GitHub

Merge pull request #33675 from mikedanese/fix-godeps

fix godeps
parents c0826a2e 589d70f4
...@@ -1504,31 +1504,6 @@ ...@@ -1504,31 +1504,6 @@
"Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" "Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a"
}, },
{ {
"ImportPath": "github.com/mesos/mesos-go/auth",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/auth/callback",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/auth/sasl",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/auth/sasl/mech",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/auth/sasl/mech/crammd5",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/detector", "ImportPath": "github.com/mesos/mesos-go/detector",
"Comment": "before-0.26-protos-33-g45c8b08", "Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0" "Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
...@@ -1539,46 +1514,16 @@ ...@@ -1539,46 +1514,16 @@
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0" "Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
}, },
{ {
"ImportPath": "github.com/mesos/mesos-go/executor",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/mesosproto", "ImportPath": "github.com/mesos/mesos-go/mesosproto",
"Comment": "before-0.26-protos-33-g45c8b08", "Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0" "Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
}, },
{ {
"ImportPath": "github.com/mesos/mesos-go/mesosproto/scheduler",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/mesosutil", "ImportPath": "github.com/mesos/mesos-go/mesosutil",
"Comment": "before-0.26-protos-33-g45c8b08", "Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0" "Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
}, },
{ {
"ImportPath": "github.com/mesos/mesos-go/mesosutil/process",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/messenger",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/messenger/sessionid",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/scheduler",
"Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
},
{
"ImportPath": "github.com/mesos/mesos-go/upid", "ImportPath": "github.com/mesos/mesos-go/upid",
"Comment": "before-0.26-protos-33-g45c8b08", "Comment": "before-0.26-protos-33-g45c8b08",
"Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0" "Rev": "45c8b08e9af666add36a6f93ff8c1c75812367b0"
......
package callback
import (
"fmt"
)
type Unsupported struct {
Callback Interface
}
func (uc *Unsupported) Error() string {
return fmt.Sprintf("Unsupported callback <%T>: %v", uc.Callback, uc.Callback)
}
type Interface interface {
// marker interface
}
type Handler interface {
// may return an Unsupported error on failure
Handle(callbacks ...Interface) error
}
type HandlerFunc func(callbacks ...Interface) error
func (f HandlerFunc) Handle(callbacks ...Interface) error {
return f(callbacks...)
}
package callback
import (
"github.com/mesos/mesos-go/upid"
)
type Interprocess struct {
client upid.UPID
server upid.UPID
}
func NewInterprocess() *Interprocess {
return &Interprocess{}
}
func (cb *Interprocess) Client() upid.UPID {
return cb.client
}
func (cb *Interprocess) Server() upid.UPID {
return cb.server
}
func (cb *Interprocess) Set(server, client upid.UPID) {
cb.server = server
cb.client = client
}
package callback
type Name struct {
name string
}
func NewName() *Name {
return &Name{}
}
func (cb *Name) Get() string {
return cb.name
}
func (cb *Name) Set(name string) {
cb.name = name
}
package callback
type Password struct {
password []byte
}
func NewPassword() *Password {
return &Password{}
}
func (cb *Password) Get() []byte {
clone := make([]byte, len(cb.password))
copy(clone, cb.password)
return clone
}
func (cb *Password) Set(password []byte) {
cb.password = make([]byte, len(password))
copy(cb.password, password)
}
package auth
import (
"errors"
"fmt"
"sync"
log "github.com/golang/glog"
"github.com/mesos/mesos-go/auth/callback"
"golang.org/x/net/context"
)
// SPI interface: login provider implementations support this interface, clients
// do not authenticate against this directly, instead they should use Login()
type Authenticatee interface {
// Returns no errors if successfully authenticated, otherwise a single
// error.
Authenticate(ctx context.Context, handler callback.Handler) error
}
// Func adapter for interface: allow func's to implement the Authenticatee interface
// as long as the func signature matches
type AuthenticateeFunc func(ctx context.Context, handler callback.Handler) error
func (f AuthenticateeFunc) Authenticate(ctx context.Context, handler callback.Handler) error {
return f(ctx, handler)
}
var (
// Authentication was attempted and failed (likely due to incorrect credentials, too
// many retries within a time window, etc). Distinctly different from authentication
// errors (e.g. network errors, configuration errors, etc).
AuthenticationFailed = errors.New("authentication failed")
authenticateeProviders = make(map[string]Authenticatee) // authentication providers dict
providerLock sync.Mutex
)
// Register an authentication provider (aka "login provider"). packages that
// provide Authenticatee implementations should invoke this func in their
// init() to register.
func RegisterAuthenticateeProvider(name string, auth Authenticatee) (err error) {
providerLock.Lock()
defer providerLock.Unlock()
if _, found := authenticateeProviders[name]; found {
err = fmt.Errorf("authentication provider already registered: %v", name)
} else {
authenticateeProviders[name] = auth
log.V(1).Infof("registered authentication provider: %v", name)
}
return
}
// Look up an authentication provider by name, returns non-nil and true if such
// a provider is found.
func getAuthenticateeProvider(name string) (provider Authenticatee, ok bool) {
providerLock.Lock()
defer providerLock.Unlock()
provider, ok = authenticateeProviders[name]
return
}
package auth
import (
"errors"
"fmt"
"time"
"github.com/mesos/mesos-go/auth/callback"
"github.com/mesos/mesos-go/upid"
"golang.org/x/net/context"
)
var (
// No login provider name has been specified in a context.Context
NoLoginProviderName = errors.New("missing login provider name in context")
)
// Main client entrypoint into the authentication APIs: clients are expected to
// invoke this func with a context containing a login provider name value.
// This may be written as:
// providerName := ... // the user has probably configured this via some flag
// handler := ... // handlers provide data like usernames and passwords
// ctx := ... // obtain some initial or timed context
// err := auth.Login(auth.WithLoginProvider(ctx, providerName), handler)
func Login(ctx context.Context, handler callback.Handler) error {
name, ok := LoginProviderFrom(ctx)
if !ok {
return NoLoginProviderName
}
provider, ok := getAuthenticateeProvider(name)
if !ok {
return fmt.Errorf("unrecognized login provider name in context: %s", name)
}
return provider.Authenticate(ctx, handler)
}
// Unexported key type, avoids conflicts with other context-using packages. All
// context items registered from this package should use keys of this type.
type loginKeyType int
const (
// name of login provider to use
loginProviderNameKey loginKeyType = iota
// upid.UPID of some parent process
parentUpidKey
// time.Duration that limits the overall duration of an auth attempt
timeoutKey
)
// Return a context that inherits all values from the parent ctx and specifies
// the login provider name given here. Intended to be invoked before calls to
// Login().
func WithLoginProvider(ctx context.Context, providerName string) context.Context {
return context.WithValue(ctx, loginProviderNameKey, providerName)
}
// Return the name of the login provider specified in this context.
func LoginProviderFrom(ctx context.Context) (name string, ok bool) {
name, ok = ctx.Value(loginProviderNameKey).(string)
return
}
// Return the name of the login provider specified in this context, or empty
// string if none.
func LoginProvider(ctx context.Context) string {
name, _ := LoginProviderFrom(ctx)
return name
}
func WithParentUPID(ctx context.Context, pid upid.UPID) context.Context {
return context.WithValue(ctx, parentUpidKey, pid)
}
func ParentUPIDFrom(ctx context.Context) (pid upid.UPID, ok bool) {
pid, ok = ctx.Value(parentUpidKey).(upid.UPID)
return
}
func ParentUPID(ctx context.Context) (upid *upid.UPID) {
if upid, ok := ParentUPIDFrom(ctx); ok {
return &upid
}
return nil
}
func TimeoutFrom(ctx context.Context) (d time.Duration, ok bool) {
d, ok = ctx.Value(timeoutKey).(time.Duration)
return
}
func Timeout(ctx context.Context) (d time.Duration) {
d, _ = TimeoutFrom(ctx)
return
}
func WithTimeout(ctx context.Context, d time.Duration) context.Context {
return context.WithValue(ctx, timeoutKey, d)
}
package sasl
import (
"net"
"golang.org/x/net/context"
)
// unexported to prevent collisions with context keys defined in
// other packages.
type _key int
// If this package defined other context keys, they would have
// different integer values.
const (
statusKey _key = iota
bindingAddressKey // bind address for login-related network ops
)
func withStatus(ctx context.Context, s statusType) context.Context {
return context.WithValue(ctx, statusKey, s)
}
func statusFrom(ctx context.Context) statusType {
s, ok := ctx.Value(statusKey).(statusType)
if !ok {
panic("missing status in context")
}
return s
}
func WithBindingAddress(ctx context.Context, address net.IP) context.Context {
return context.WithValue(ctx, bindingAddressKey, address)
}
func BindingAddressFrom(ctx context.Context) net.IP {
obj := ctx.Value(bindingAddressKey)
if addr, ok := obj.(net.IP); ok {
return addr
} else {
return nil
}
}
package crammd5
import (
"crypto/hmac"
"crypto/md5"
"encoding/hex"
"errors"
"io"
log "github.com/golang/glog"
"github.com/mesos/mesos-go/auth/callback"
"github.com/mesos/mesos-go/auth/sasl/mech"
)
var (
Name = "CRAM-MD5" // name this mechanism is registered with
//TODO(jdef) is this a generic SASL error? if so, move it up to mech
challengeDataRequired = errors.New("challenge data may not be empty")
)
func init() {
mech.Register(Name, newInstance)
}
type mechanism struct {
handler callback.Handler
}
func (m *mechanism) Handler() callback.Handler {
return m.handler
}
func (m *mechanism) Discard() {
// noop
}
func newInstance(h callback.Handler) (mech.Interface, mech.StepFunc, error) {
m := &mechanism{
handler: h,
}
fn := func(m mech.Interface, data []byte) (mech.StepFunc, []byte, error) {
// noop: no initialization needed
return challengeResponse, nil, nil
}
return m, fn, nil
}
// algorithm lifted from wikipedia: http://en.wikipedia.org/wiki/CRAM-MD5
// except that the SASL mechanism used by Mesos doesn't leverage base64 encoding
func challengeResponse(m mech.Interface, data []byte) (mech.StepFunc, []byte, error) {
if len(data) == 0 {
return mech.IllegalState, nil, challengeDataRequired
}
decoded := string(data)
log.V(4).Infof("challenge(decoded): %s", decoded) // for deep debugging only
username := callback.NewName()
secret := callback.NewPassword()
if err := m.Handler().Handle(username, secret); err != nil {
return mech.IllegalState, nil, err
}
hash := hmac.New(md5.New, secret.Get())
if _, err := io.WriteString(hash, decoded); err != nil {
return mech.IllegalState, nil, err
}
codes := hex.EncodeToString(hash.Sum(nil))
msg := username.Get() + " " + codes
return nil, []byte(msg), nil
}
package mech
import (
"errors"
"github.com/mesos/mesos-go/auth/callback"
)
var (
IllegalStateErr = errors.New("illegal mechanism state")
)
type Interface interface {
Handler() callback.Handler
Discard() // clean up resources or sensitive information; idempotent
}
// return a mechanism and it's initialization step (may be a noop that returns
// a nil data blob and handle to the first "real" challenge step).
type Factory func(h callback.Handler) (Interface, StepFunc, error)
// StepFunc implementations should never return a nil StepFunc result. This
// helps keep the logic in the SASL authticatee simpler: step functions are
// never nil. Mechanisms that end up an error state (for example, some decoding
// logic fails...) should return a StepFunc that represents an error state.
// Some mechanisms may be able to recover from such.
type StepFunc func(m Interface, data []byte) (StepFunc, []byte, error)
// reflects an unrecoverable, illegal mechanism state; always returns IllegalState
// as the next step along with an IllegalStateErr
func IllegalState(m Interface, data []byte) (StepFunc, []byte, error) {
return IllegalState, nil, IllegalStateErr
}
package mech
import (
"fmt"
"sync"
log "github.com/golang/glog"
)
var (
mechLock sync.Mutex
supportedMechs = make(map[string]Factory)
)
func Register(name string, f Factory) error {
mechLock.Lock()
defer mechLock.Unlock()
if _, found := supportedMechs[name]; found {
return fmt.Errorf("Mechanism registered twice: %s", name)
}
supportedMechs[name] = f
log.V(1).Infof("Registered mechanism %s", name)
return nil
}
func ListSupported() (list []string) {
mechLock.Lock()
defer mechLock.Unlock()
for mechname := range supportedMechs {
list = append(list, mechname)
}
return list
}
func SelectSupported(mechanisms []string) (selectedMech string, factory Factory) {
mechLock.Lock()
defer mechLock.Unlock()
for _, m := range mechanisms {
if f, ok := supportedMechs[m]; ok {
selectedMech = m
factory = f
break
}
}
return
}
/*
Package executor includes the interfaces of the mesos executor and
the mesos executor driver, as well as an implementation of the driver.
*/
package executor
package executor
import (
"github.com/mesos/mesos-go/mesosproto"
)
/**
* Executor callback interface to be implemented by frameworks' executors. Note
* that only one callback will be invoked at a time, so it is not
* recommended that you block within a callback because it may cause a
* deadlock.
*
* Each callback includes an instance to the executor driver that was
* used to run this executor. The driver will not change for the
* duration of an executor (i.e., from the point you do
* ExecutorDriver.Start() to the point that ExecutorDriver.Join()
* returns). This is intended for convenience so that an executor
* doesn't need to store a pointer to the driver itself.
*/
type Executor interface {
/**
* Invoked once the executor driver has been able to successfully
* connect with Mesos. In particular, a scheduler can pass some
* data to its executors through the FrameworkInfo.ExecutorInfo's
* data field.
*/
Registered(ExecutorDriver, *mesosproto.ExecutorInfo, *mesosproto.FrameworkInfo, *mesosproto.SlaveInfo)
/**
* Invoked when the executor re-registers with a restarted slave.
*/
Reregistered(ExecutorDriver, *mesosproto.SlaveInfo)
/**
* Invoked when the executor becomes "disconnected" from the slave
* (e.g., the slave is being restarted due to an upgrade).
*/
Disconnected(ExecutorDriver)
/**
* Invoked when a task has been launched on this executor (initiated
* via SchedulerDriver.LaunchTasks). Note that this task can be realized
* with a goroutine, an external process, or some simple computation, however,
* no other callbacks will be invoked on this executor until this
* callback has returned.
*/
LaunchTask(ExecutorDriver, *mesosproto.TaskInfo)
/**
* Invoked when a task running within this executor has been killed
* (via SchedulerDriver.KillTask). Note that no status update will
* be sent on behalf of the executor, the executor is responsible
* for creating a new TaskStatus (i.e., with TASK_KILLED) and
* invoking ExecutorDriver.SendStatusUpdate.
*/
KillTask(ExecutorDriver, *mesosproto.TaskID)
/**
* Invoked when a framework message has arrived for this
* executor. These messages are best effort; do not expect a
* framework message to be retransmitted in any reliable fashion.
*/
FrameworkMessage(ExecutorDriver, string)
/**
* Invoked when the executor should terminate all of its currently
* running tasks. Note that after Mesos has determined that an
* executor has terminated, any tasks that the executor did not send
* terminal status updates for (e.g., TASK_KILLED, TASK_FINISHED,
* TASK_FAILED, etc) a TASK_LOST status update will be created.
*/
Shutdown(ExecutorDriver)
/**
* Invoked when a fatal error has occured with the executor and/or
* executor driver. The driver will be aborted BEFORE invoking this
* callback.
*/
Error(ExecutorDriver, string)
}
/**
* ExecutorDriver interface for connecting an executor to Mesos. This
* interface is used both to manage the executor's lifecycle (start
* it, stop it, or wait for it to finish) and to interact with Mesos
* (e.g., send status updates, send framework messages, etc.).
* A driver method is expected to fail-fast and return an error when possible.
* Other internal errors (or remote error) that occur asynchronously are handled
* using the the Executor.Error() callback.
*/
type ExecutorDriver interface {
/**
* Starts the executor driver. This needs to be called before any
* other driver calls are made.
*/
Start() (mesosproto.Status, error)
/**
* Stops the executor driver.
*/
Stop() (mesosproto.Status, error)
/**
* Aborts the driver so that no more callbacks can be made to the
* executor. The semantics of abort and stop have deliberately been
* separated so that code can detect an aborted driver (i.e., via
* the return status of ExecutorDriver.Join, see below), and
* instantiate and start another driver if desired (from within the
* same process ... although this functionality is currently not
* supported for executors).
*/
Abort() (mesosproto.Status, error)
/**
* Waits for the driver to be stopped or aborted, possibly
* blocking the calling goroutine indefinitely. The return status of
* this function can be used to determine if the driver was aborted
* (see package mesosproto for a description of Status).
*/
Join() (mesosproto.Status, error)
/**
* Starts and immediately joins (i.e., blocks on) the driver.
*/
Run() (mesosproto.Status, error)
/**
* Sends a status update to the framework scheduler, retrying as
* necessary until an acknowledgement has been received or the
* executor is terminated (in which case, a TASK_LOST status update
* will be sent). See Scheduler.StatusUpdate for more information
* about status update acknowledgements.
*/
SendStatusUpdate(*mesosproto.TaskStatus) (mesosproto.Status, error)
/**
* Sends a message to the framework scheduler. These messages are
* best effort; do not expect a framework message to be
* retransmitted in any reliable fashion.
*/
SendFrameworkMessage(string) (mesosproto.Status, error)
}
package executor
import (
"github.com/gogo/protobuf/proto"
"github.com/mesos/mesos-go/messenger"
"github.com/mesos/mesos-go/upid"
"golang.org/x/net/context"
)
type TestDriver struct {
*MesosExecutorDriver
}
func (e *TestDriver) SetConnected(b bool) {
e.guarded(func() {
e.connected = b
})
}
func (e *TestDriver) SetMessenger(m messenger.Messenger) {
e.messenger = m
}
func (e *TestDriver) Started() <-chan struct{} {
return e.started
}
func (e *TestDriver) guarded(f func()) {
e.lock.Lock()
defer e.lock.Unlock()
f()
}
func (e *TestDriver) Context() context.Context {
return e.context()
}
func (e *TestDriver) StatusUpdateAcknowledgement(ctx context.Context, from *upid.UPID, msg proto.Message) {
e.guarded(func() {
e.statusUpdateAcknowledgement(ctx, from, msg)
})
}
This source diff could not be displayed because it is too large. You can view the blob instead.
package process
import (
"fmt"
"sync"
)
var (
pidLock sync.Mutex
pid uint64
)
func nextPid() uint64 {
pidLock.Lock()
defer pidLock.Unlock()
pid++
return pid
}
//TODO(jdef) add lifecycle funcs
//TODO(jdef) add messaging funcs
type Process struct {
label string
}
func New(kind string) *Process {
return &Process{
label: fmt.Sprintf("%s(%d)", kind, nextPid()),
}
}
func (p *Process) Label() string {
return p.label
}
####Benchmark of the messenger.
```shell
$ go test -v -run=Benckmark* -bench=.
PASS
BenchmarkMessengerSendSmallMessage 50000 70568 ns/op
BenchmarkMessengerSendMediumMessage 50000 70265 ns/op
BenchmarkMessengerSendBigMessage 50000 72693 ns/op
BenchmarkMessengerSendLargeMessage 50000 72896 ns/op
BenchmarkMessengerSendMixedMessage 50000 72631 ns/op
BenchmarkMessengerSendRecvSmallMessage 20000 78409 ns/op
BenchmarkMessengerSendRecvMediumMessage 20000 80471 ns/op
BenchmarkMessengerSendRecvBigMessage 20000 82629 ns/op
BenchmarkMessengerSendRecvLargeMessage 20000 85987 ns/op
BenchmarkMessengerSendRecvMixedMessage 20000 83678 ns/op
ok github.com/mesos/mesos-go/messenger 115.135s
$ go test -v -run=Benckmark* -bench=. -cpu=4 -send-routines=4 2>/dev/null
PASS
BenchmarkMessengerSendSmallMessage-4 50000 35529 ns/op
BenchmarkMessengerSendMediumMessage-4 50000 35997 ns/op
BenchmarkMessengerSendBigMessage-4 50000 36871 ns/op
BenchmarkMessengerSendLargeMessage-4 50000 37310 ns/op
BenchmarkMessengerSendMixedMessage-4 50000 37419 ns/op
BenchmarkMessengerSendRecvSmallMessage-4 50000 39320 ns/op
BenchmarkMessengerSendRecvMediumMessage-4 50000 41990 ns/op
BenchmarkMessengerSendRecvBigMessage-4 50000 42157 ns/op
BenchmarkMessengerSendRecvLargeMessage-4 50000 45472 ns/op
BenchmarkMessengerSendRecvMixedMessage-4 50000 47393 ns/op
ok github.com/mesos/mesos-go/messenger 105.173s
```
####environment:
```
OS: Linux yifan-laptop 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
CPU: Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
MEM: 4G DDR3 1600MHz
```
/*
Package messenger includes a messenger and a transporter.
The messenger provides interfaces to send a protobuf message
through the underlying transporter. It also dispatches messages
to installed handlers.
*/
package messenger
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package messenger
import (
"fmt"
"strings"
"github.com/gogo/protobuf/proto"
"github.com/mesos/mesos-go/upid"
)
// Message defines the type that passes in the Messenger.
type Message struct {
UPID *upid.UPID
Name string
ProtoMessage proto.Message
Bytes []byte
}
// RequestURI returns the request URI of the message.
func (m *Message) RequestURI() string {
if m.isV1API() {
return fmt.Sprintf("/api/v1/%s", m.Name)
}
return fmt.Sprintf("/%s/%s", m.UPID.ID, m.Name)
}
func (m *Message) isV1API() bool {
return !strings.HasPrefix(m.Name, "mesos.internal")
}
// NOTE: This should not fail or panic.
func extractNameFromRequestURI(requestURI string) string {
return strings.Split(requestURI, "/")[2]
}
package sessionid
import (
"golang.org/x/net/context"
)
type key int
const sessionIDKey = 0
func NewContext(ctx context.Context, sessionID string) context.Context {
return context.WithValue(ctx, sessionIDKey, sessionID)
}
func FromContext(ctx context.Context) (string, bool) {
sessionID, ok := ctx.Value(sessionIDKey).(string)
return sessionID, ok
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package messenger
import (
"github.com/mesos/mesos-go/upid"
"golang.org/x/net/context"
)
// Transporter defines methods for communicating with remote processes.
type Transporter interface {
//Send sends message to remote process. Must use context to determine
//cancelled requests. Will stop sending when transport is stopped.
Send(ctx context.Context, msg *Message) error
//Rcvd receives and delegate message handling to installed handlers.
//Will stop receiving when transport is stopped.
Recv() (*Message, error)
//Install mount an handler based on incoming message name.
Install(messageName string)
//Start starts the transporter and returns immediately. The error chan
//is never nil.
Start() (upid.UPID, <-chan error)
//Stop kills the transporter.
Stop(graceful bool) error
//UPID returns the PID for transporter.
UPID() upid.UPID
}
/*
Package scheduler includes the interfaces for the mesos scheduler and
the mesos executor driver. It also contains as well as an implementation
of the driver that you can use in your code.
*/
package scheduler
package scheduler
import (
"github.com/mesos/mesos-go/auth/callback"
mesos "github.com/mesos/mesos-go/mesosproto"
"github.com/mesos/mesos-go/upid"
)
type CredentialHandler struct {
pid *upid.UPID // the process to authenticate against (master)
client *upid.UPID // the process to be authenticated (slave / framework)
credential *mesos.Credential
}
func (h *CredentialHandler) Handle(callbacks ...callback.Interface) error {
for _, cb := range callbacks {
switch cb := cb.(type) {
case *callback.Name:
cb.Set(h.credential.GetPrincipal())
case *callback.Password:
cb.Set(([]byte)(h.credential.GetSecret()))
case *callback.Interprocess:
cb.Set(*(h.pid), *(h.client))
default:
return &callback.Unsupported{Callback: cb}
}
}
return nil
}
package scheduler
import (
_ "github.com/mesos/mesos-go/auth/sasl"
_ "github.com/mesos/mesos-go/auth/sasl/mech/crammd5"
_ "github.com/mesos/mesos-go/detector/zoo"
)
package scheduler
import (
log "github.com/golang/glog"
mesos "github.com/mesos/mesos-go/mesosproto"
"github.com/mesos/mesos-go/upid"
"sync"
)
type cachedOffer struct {
offer *mesos.Offer
slavePid *upid.UPID
}
func newCachedOffer(offer *mesos.Offer, slavePid *upid.UPID) *cachedOffer {
return &cachedOffer{offer: offer, slavePid: slavePid}
}
// schedCache a managed cache with backing maps to store offeres
// and tasked slaves.
type schedCache struct {
lock sync.RWMutex
savedOffers map[string]*cachedOffer // current offers key:OfferID
savedSlavePids map[string]*upid.UPID // Current saved slaves, key:slaveId
}
func newSchedCache() *schedCache {
return &schedCache{
savedOffers: make(map[string]*cachedOffer),
savedSlavePids: make(map[string]*upid.UPID),
}
}
// 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()
}
// getOffer returns cached offer
func (cache *schedCache) getOffer(offerId *mesos.OfferID) *cachedOffer {
if offerId == nil {
log.V(3).Infoln("WARN: OfferId == nil, returning nil")
return nil
}
cache.lock.RLock()
defer cache.lock.RUnlock()
return cache.savedOffers[offerId.GetValue()]
}
// containsOff test cache for offer(offerId)
func (cache *schedCache) containsOffer(offerId *mesos.OfferID) bool {
cache.lock.RLock()
defer cache.lock.RUnlock()
_, ok := cache.savedOffers[offerId.GetValue()]
return ok
}
func (cache *schedCache) removeOffer(offerId *mesos.OfferID) {
cache.lock.Lock()
delete(cache.savedOffers, offerId.GetValue())
cache.lock.Unlock()
}
func (cache *schedCache) putSlavePid(slaveId *mesos.SlaveID, pid *upid.UPID) {
cache.lock.Lock()
cache.savedSlavePids[slaveId.GetValue()] = pid
cache.lock.Unlock()
}
func (cache *schedCache) getSlavePid(slaveId *mesos.SlaveID) *upid.UPID {
if slaveId == nil {
log.V(3).Infoln("SlaveId == nil, returning empty UPID")
return nil
}
return cache.savedSlavePids[slaveId.GetValue()]
}
func (cache *schedCache) containsSlavePid(slaveId *mesos.SlaveID) bool {
cache.lock.RLock()
defer cache.lock.RUnlock()
_, ok := cache.savedSlavePids[slaveId.GetValue()]
return ok
}
func (cache *schedCache) removeSlavePid(slaveId *mesos.SlaveID) {
cache.lock.Lock()
delete(cache.savedSlavePids, slaveId.GetValue())
cache.lock.Unlock()
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package scheduler
import (
mesos "github.com/mesos/mesos-go/mesosproto"
)
// Interface for connecting a scheduler to Mesos. This
// interface is used both to manage the scheduler's lifecycle (start
// it, stop it, or wait for it to finish) and to interact with Mesos
// (e.g., launch tasks, kill tasks, etc.).
// See the MesosSchedulerDriver type for a concrete
// impl of a SchedulerDriver.
type SchedulerDriver interface {
// Starts the scheduler driver. This needs to be called before any
// other driver calls are made.
Start() (mesos.Status, error)
// Stops the scheduler driver. If the 'failover' flag is set to
// false then it is expected that this framework will never
// reconnect to Mesos and all of its executors and tasks can be
// terminated. Otherwise, all executors and tasks will remain
// running (for some framework specific failover timeout) allowing the
// scheduler to reconnect (possibly in the same process, or from a
// different process, for example, on a different machine).
Stop(failover bool) (mesos.Status, error)
// Aborts the driver so that no more callbacks can be made to the
// scheduler. The semantics of abort and stop have deliberately been
// separated so that code can detect an aborted driver (i.e., via
// the return status of SchedulerDriver::join, see below), and
// instantiate and start another driver if desired (from within the
// same process). Note that 'Stop()' is not automatically called
// inside 'Abort()'.
Abort() (mesos.Status, error)
// Waits for the driver to be stopped or aborted, possibly
// _blocking_ the current thread indefinitely. The return status of
// this function can be used to determine if the driver was aborted
// (see mesos.proto for a description of Status).
Join() (mesos.Status, error)
// Starts and immediately joins (i.e., blocks on) the driver.
Run() (mesos.Status, error)
// Requests resources from Mesos (see mesos.proto for a description
// of Request and how, for example, to request resources
// from specific slaves). Any resources available are offered to the
// framework via Scheduler.ResourceOffers callback, asynchronously.
RequestResources(requests []*mesos.Request) (mesos.Status, error)
// AcceptOffers utilizes the new HTTP API to send a Scheduler Call Message
// to the Mesos Master. Valid operation types are LAUNCH, RESERVE, UNRESERVE,
// CREATE, DESTROY, and more.
AcceptOffers(offerIDs []*mesos.OfferID, operations []*mesos.Offer_Operation, filters *mesos.Filters) (mesos.Status, error)
// Launches the given set of tasks. Any resources remaining (i.e.,
// not used by the tasks or their executors) will be considered
// declined. The specified filters are applied on all unused
// resources (see mesos.proto for a description of Filters).
// Available resources are aggregated when mutiple offers are
// provided. Note that all offers must belong to the same slave.
// Invoking this function with an empty collection of tasks declines
// offers in their entirety (see Scheduler::declineOffer).
LaunchTasks(offerIDs []*mesos.OfferID, tasks []*mesos.TaskInfo, filters *mesos.Filters) (mesos.Status, error)
// Kills the specified task. Note that attempting to kill a task is
// currently not reliable. If, for example, a scheduler fails over
// while it was attempting to kill a task it will need to retry in
// the future. Likewise, if unregistered / disconnected, the request
// will be dropped (these semantics may be changed in the future).
KillTask(taskID *mesos.TaskID) (mesos.Status, error)
// Declines an offer in its entirety and applies the specified
// filters on the resources (see mesos.proto for a description of
// Filters). Note that this can be done at any time, it is not
// necessary to do this within the Scheduler::resourceOffers
// callback.
DeclineOffer(offerID *mesos.OfferID, filters *mesos.Filters) (mesos.Status, error)
// Removes all filters previously set by the framework (via
// LaunchTasks()). This enables the framework to receive offers from
// those filtered slaves.
ReviveOffers() (mesos.Status, error)
// Sends a message from the framework to one of its executors. These
// messages are best effort; do not expect a framework message to be
// retransmitted in any reliable fashion.
SendFrameworkMessage(executorID *mesos.ExecutorID, slaveID *mesos.SlaveID, data string) (mesos.Status, error)
// Allows the framework to query the status for non-terminal tasks.
// This causes the master to send back the latest task status for
// each task in 'statuses', if possible. Tasks that are no longer
// known will result in a TASK_LOST update. If statuses is empty,
// then the master will send the latest status for each task
// currently known.
ReconcileTasks(statuses []*mesos.TaskStatus) (mesos.Status, error)
}
// Scheduler a type with callback attributes to be provided by frameworks
// schedulers.
//
// Each callback includes a reference to the scheduler driver that was
// used to run this scheduler. The pointer will not change for the
// duration of a scheduler (i.e., from the point you do
// SchedulerDriver.Start() to the point that SchedulerDriver.Stop()
// returns). This is intended for convenience so that a scheduler
// doesn't need to store a reference to the driver itself.
type Scheduler interface {
// Invoked when the scheduler successfully registers with a Mesos
// master. A unique ID (generated by the master) used for
// distinguishing this framework from others and MasterInfo
// with the ip and port of the current master are provided as arguments.
Registered(SchedulerDriver, *mesos.FrameworkID, *mesos.MasterInfo)
// Invoked when the scheduler re-registers with a newly elected Mesos master.
// This is only called when the scheduler has previously been registered.
// MasterInfo containing the updated information about the elected master
// is provided as an argument.
Reregistered(SchedulerDriver, *mesos.MasterInfo)
// Invoked when the scheduler becomes "disconnected" from the master
// (e.g., the master fails and another is taking over).
Disconnected(SchedulerDriver)
// Invoked when resources have been offered to this framework. A
// single offer will only contain resources from a single slave.
// Resources associated with an offer will not be re-offered to
// _this_ framework until either (a) this framework has rejected
// those resources (see SchedulerDriver::launchTasks) or (b) those
// resources have been rescinded (see Scheduler::offerRescinded).
// Note that resources may be concurrently offered to more than one
// framework at a time (depending on the allocator being used). In
// that case, the first framework to launch tasks using those
// resources will be able to use them while the other frameworks
// will have those resources rescinded (or if a framework has
// already launched tasks with those resources then those tasks will
// fail with a TASK_LOST status and a message saying as much).
ResourceOffers(SchedulerDriver, []*mesos.Offer)
// Invoked when an offer is no longer valid (e.g., the slave was
// lost or another framework used resources in the offer). If for
// whatever reason an offer is never rescinded (e.g., dropped
// message, failing over framework, etc.), a framwork that attempts
// to launch tasks using an invalid offer will receive TASK_LOST
// status updates for those tasks (see Scheduler::resourceOffers).
OfferRescinded(SchedulerDriver, *mesos.OfferID)
// Invoked when the status of a task has changed (e.g., a slave is
// lost and so the task is lost, a task finishes and an executor
// sends a status update saying so, etc). Note that returning from
// this callback _acknowledges_ receipt of this status update! If
// for whatever reason the scheduler aborts during this callback (or
// the process exits) another status update will be delivered (note,
// however, that this is currently not true if the slave sending the
// status update is lost/fails during that time).
StatusUpdate(SchedulerDriver, *mesos.TaskStatus)
// Invoked when an executor sends a message. These messages are best
// effort; do not expect a framework message to be retransmitted in
// any reliable fashion.
FrameworkMessage(SchedulerDriver, *mesos.ExecutorID, *mesos.SlaveID, string)
// Invoked when a slave has been determined unreachable (e.g.,
// machine failure, network partition). Most frameworks will need to
// reschedule any tasks launched on this slave on a new slave.
SlaveLost(SchedulerDriver, *mesos.SlaveID)
// Invoked when an executor has exited/terminated. Note that any
// tasks running will have TASK_LOST status updates automagically
// generated.
ExecutorLost(SchedulerDriver, *mesos.ExecutorID, *mesos.SlaveID, int)
// Invoked when there is an unrecoverable error in the scheduler or
// scheduler driver. The driver will be aborted BEFORE invoking this
// callback.
Error(SchedulerDriver, string)
}
package scheduler
import (
"github.com/gogo/protobuf/proto"
mesos "github.com/mesos/mesos-go/mesosproto"
"github.com/mesos/mesos-go/upid"
"golang.org/x/net/context"
)
type TestDriver struct {
*MesosSchedulerDriver
}
func (t *TestDriver) SetConnected(b bool) {
t.eventLock.Lock()
defer t.eventLock.Unlock()
t.connected = b
}
func (t *TestDriver) Started() <-chan struct{} {
return t.started
}
func (t *TestDriver) Stopped() <-chan struct{} {
return t.stopCh
}
func (t *TestDriver) Done() <-chan struct{} {
return t.done
}
func (t *TestDriver) Framework() *mesos.FrameworkInfo {
return t.frameworkInfo
}
func (t *TestDriver) UPID() *upid.UPID {
return t.self
}
func (t *TestDriver) MasterPID() *upid.UPID {
return t.masterPid
}
func (t *TestDriver) Fatal(ctx context.Context, msg string) {
t.eventLock.Lock()
defer t.eventLock.Unlock()
t.fatal(ctx, msg)
}
func (t *TestDriver) OnDispatch(f func(ctx context.Context, upid *upid.UPID, msg proto.Message) error) {
t.dispatch = f
}
func (t *TestDriver) HandleMasterChanged(ctx context.Context, from *upid.UPID, msg proto.Message) {
t.eventLock.Lock()
defer t.eventLock.Unlock()
t.handleMasterChanged(ctx, from, msg)
}
func (t *TestDriver) CacheOffer(offer *mesos.Offer, pid *upid.UPID) {
t.cache.putOffer(offer, pid)
}
func (t *TestDriver) Context() context.Context {
return t.context()
}
func (t *TestDriver) FrameworkRegistered(ctx context.Context, from *upid.UPID, msg proto.Message) {
t.eventLock.Lock()
defer t.eventLock.Unlock()
t.frameworkRegistered(ctx, from, msg)
}
func (t *TestDriver) FrameworkReregistered(ctx context.Context, from *upid.UPID, msg proto.Message) {
t.eventLock.Lock()
defer t.eventLock.Unlock()
t.frameworkReregistered(ctx, from, msg)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment