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 }