github.com/jmitchell/nomad@v0.1.3-0.20151007230021-7ab84c2862d8/client/driver/driver.go (about)

     1  package driver
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"sync"
     7  
     8  	"github.com/hashicorp/nomad/client/allocdir"
     9  	"github.com/hashicorp/nomad/client/config"
    10  	"github.com/hashicorp/nomad/client/driver/environment"
    11  	"github.com/hashicorp/nomad/client/fingerprint"
    12  	"github.com/hashicorp/nomad/nomad/structs"
    13  )
    14  
    15  // BuiltinDrivers contains the built in registered drivers
    16  // which are available for allocation handling
    17  var BuiltinDrivers = map[string]Factory{
    18  	"docker": NewDockerDriver,
    19  	"exec":   NewExecDriver,
    20  	"java":   NewJavaDriver,
    21  	"qemu":   NewQemuDriver,
    22  	"rkt":    NewRktDriver,
    23  }
    24  
    25  // NewDriver is used to instantiate and return a new driver
    26  // given the name and a logger
    27  func NewDriver(name string, ctx *DriverContext) (Driver, error) {
    28  	// Lookup the factory function
    29  	factory, ok := BuiltinDrivers[name]
    30  	if !ok {
    31  		return nil, fmt.Errorf("unknown driver '%s'", name)
    32  	}
    33  
    34  	// Instantiate the driver
    35  	f := factory(ctx)
    36  	return f, nil
    37  }
    38  
    39  // Factory is used to instantiate a new Driver
    40  type Factory func(*DriverContext) Driver
    41  
    42  // Driver is used for execution of tasks. This allows Nomad
    43  // to support many pluggable implementations of task drivers.
    44  // Examples could include LXC, Docker, Qemu, etc.
    45  type Driver interface {
    46  	// Drivers must support the fingerprint interface for detection
    47  	fingerprint.Fingerprint
    48  
    49  	// Start is used to being task execution
    50  	Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error)
    51  
    52  	// Open is used to re-open a handle to a task
    53  	Open(ctx *ExecContext, handleID string) (DriverHandle, error)
    54  }
    55  
    56  // DriverContext is a means to inject dependencies such as loggers, configs, and
    57  // node attributes into a Driver without having to change the Driver interface
    58  // each time we do it. Used in conjection with Factory, above.
    59  type DriverContext struct {
    60  	taskName string
    61  	config   *config.Config
    62  	logger   *log.Logger
    63  	node     *structs.Node
    64  }
    65  
    66  // NewDriverContext initializes a new DriverContext with the specified fields.
    67  // This enables other packages to create DriverContexts but keeps the fields
    68  // private to the driver. If we want to change this later we can gorename all of
    69  // the fields in DriverContext.
    70  func NewDriverContext(taskName string, config *config.Config, node *structs.Node, logger *log.Logger) *DriverContext {
    71  	return &DriverContext{
    72  		taskName: taskName,
    73  		config:   config,
    74  		node:     node,
    75  		logger:   logger,
    76  	}
    77  }
    78  
    79  // DriverHandle is an opaque handle into a driver used for task
    80  // manipulation
    81  type DriverHandle interface {
    82  	// Returns an opaque handle that can be used to re-open the handle
    83  	ID() string
    84  
    85  	// WaitCh is used to return a channel used wait for task completion
    86  	WaitCh() chan error
    87  
    88  	// Update is used to update the task if possible
    89  	Update(task *structs.Task) error
    90  
    91  	// Kill is used to stop the task
    92  	Kill() error
    93  }
    94  
    95  // ExecContext is shared between drivers within an allocation
    96  type ExecContext struct {
    97  	sync.Mutex
    98  
    99  	// AllocDir contains information about the alloc directory structure.
   100  	AllocDir *allocdir.AllocDir
   101  }
   102  
   103  // NewExecContext is used to create a new execution context
   104  func NewExecContext(alloc *allocdir.AllocDir) *ExecContext {
   105  	return &ExecContext{AllocDir: alloc}
   106  }
   107  
   108  // TaskEnvironmentVariables converts exec context and task configuration into a
   109  // TaskEnvironment.
   110  func TaskEnvironmentVariables(ctx *ExecContext, task *structs.Task) environment.TaskEnvironment {
   111  	env := environment.NewTaskEnivornment()
   112  	env.SetMeta(task.Meta)
   113  
   114  	if ctx.AllocDir != nil {
   115  		env.SetAllocDir(ctx.AllocDir.AllocDir)
   116  	}
   117  
   118  	if task.Resources != nil {
   119  		env.SetMemLimit(task.Resources.MemoryMB)
   120  		env.SetCpuLimit(task.Resources.CPU)
   121  
   122  		if len(task.Resources.Networks) > 0 {
   123  			network := task.Resources.Networks[0]
   124  			env.SetTaskIp(network.IP)
   125  			env.SetPorts(network.MapDynamicPorts())
   126  		}
   127  	}
   128  
   129  	if task.Env != nil {
   130  		env.SetEnvvars(task.Env)
   131  	}
   132  
   133  	return env
   134  }