1package state 2 3import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 8 "github.com/hashicorp/nomad/client/allocrunner/taskrunner/state" 9 "github.com/hashicorp/nomad/helper/uuid" 10 "github.com/hashicorp/nomad/nomad/structs" 11 "github.com/hashicorp/nomad/plugins/drivers" 12 pstructs "github.com/hashicorp/nomad/plugins/shared/structs" 13) 14 15// allocRunnerMutableState08 is state that had to be written on each save as it 16// changed over the life-cycle of the alloc_runner in Nomad 0.8. 17// 18// https://github.com/hashicorp/nomad/blob/v0.8.6/client/alloc_runner.go#L146-L153 19// 20type allocRunnerMutableState08 struct { 21 // AllocClientStatus does not need to be upgraded as it is computed 22 // from task states. 23 AllocClientStatus string 24 25 // AllocClientDescription does not need to be upgraded as it is computed 26 // from task states. 27 AllocClientDescription string 28 29 TaskStates map[string]*structs.TaskState 30 DeploymentStatus *structs.AllocDeploymentStatus 31} 32 33// taskRunnerState08 was used to snapshot the state of the task runner in Nomad 34// 0.8. 35// 36// https://github.com/hashicorp/nomad/blob/v0.8.6/client/task_runner.go#L188-L197 37// COMPAT(0.10): Allows upgrading from 0.8.X to 0.9.0. 38type taskRunnerState08 struct { 39 Version string 40 HandleID string 41 ArtifactDownloaded bool 42 TaskDirBuilt bool 43 PayloadRendered bool 44 DriverNetwork *drivers.DriverNetwork 45 // Created Resources are no longer used. 46 //CreatedResources *driver.CreatedResources 47} 48 49type TaskRunnerHandle08 struct { 50 // Docker specific handle info 51 ContainerID string `json:"ContainerID"` 52 Image string `json:"Image"` 53 54 // LXC specific handle info 55 ContainerName string `json:"ContainerName"` 56 LxcPath string `json:"LxcPath"` 57 58 // Executor reattach config 59 PluginConfig struct { 60 Pid int `json:"Pid"` 61 AddrNet string `json:"AddrNet"` 62 AddrName string `json:"AddrName"` 63 } `json:"PluginConfig"` 64} 65 66func (t *TaskRunnerHandle08) ReattachConfig() *pstructs.ReattachConfig { 67 return &pstructs.ReattachConfig{ 68 Network: t.PluginConfig.AddrNet, 69 Addr: t.PluginConfig.AddrName, 70 Pid: t.PluginConfig.Pid, 71 } 72} 73 74func (t *taskRunnerState08) Upgrade(allocID, taskName string) (*state.LocalState, error) { 75 ls := state.NewLocalState() 76 77 // Reuse DriverNetwork 78 ls.DriverNetwork = t.DriverNetwork 79 80 // Upgrade artifact state 81 ls.Hooks["artifacts"] = &state.HookState{ 82 PrestartDone: t.ArtifactDownloaded, 83 } 84 85 // Upgrade task dir state 86 ls.Hooks["task_dir"] = &state.HookState{ 87 Data: map[string]string{ 88 // "is_done" is equivalent to task_dir_hook.TaskDirHookIsDoneKey 89 // Does not import to avoid import cycle 90 "is_done": fmt.Sprintf("%v", t.TaskDirBuilt), 91 }, 92 } 93 94 // Upgrade dispatch payload state 95 ls.Hooks["dispatch_payload"] = &state.HookState{ 96 PrestartDone: t.PayloadRendered, 97 } 98 99 // Add necessary fields to TaskConfig 100 ls.TaskHandle = drivers.NewTaskHandle(drivers.Pre09TaskHandleVersion) 101 ls.TaskHandle.Config = &drivers.TaskConfig{ 102 ID: fmt.Sprintf("pre09-%s", uuid.Generate()), 103 Name: taskName, 104 AllocID: allocID, 105 } 106 107 ls.TaskHandle.State = drivers.TaskStateUnknown 108 109 // The docker driver prefixed the handle with 'DOCKER:' 110 // Strip so that it can be unmarshalled 111 data := strings.TrimPrefix(t.HandleID, "DOCKER:") 112 113 // The pre09 driver handle ID is given to the driver. It is unmarshalled 114 // here to check for errors 115 if _, err := UnmarshalPre09HandleID([]byte(data)); err != nil { 116 return nil, err 117 } 118 119 ls.TaskHandle.DriverState = []byte(data) 120 121 return ls, nil 122} 123 124// UnmarshalPre09HandleID decodes the pre09 json encoded handle ID 125func UnmarshalPre09HandleID(raw []byte) (*TaskRunnerHandle08, error) { 126 var handle TaskRunnerHandle08 127 if err := json.Unmarshal(raw, &handle); err != nil { 128 return nil, fmt.Errorf("failed to decode 0.8 driver state: %v", err) 129 } 130 131 return &handle, nil 132} 133