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