-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Drivers: Use go-getter #288
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,10 +2,15 @@ package driver | |
|
||
import ( | ||
"fmt" | ||
"log" | ||
"path" | ||
"path/filepath" | ||
"runtime" | ||
"syscall" | ||
"time" | ||
|
||
"github.com/hashicorp/go-getter" | ||
"github.com/hashicorp/nomad/client/allocdir" | ||
"github.com/hashicorp/nomad/client/config" | ||
"github.com/hashicorp/nomad/client/executor" | ||
"github.com/hashicorp/nomad/nomad/structs" | ||
|
@@ -41,12 +46,40 @@ func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, | |
} | ||
|
||
func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) { | ||
// Get the command | ||
// Get the command to be ran | ||
command, ok := task.Config["command"] | ||
if !ok || command == "" { | ||
return nil, fmt.Errorf("missing command for exec driver") | ||
} | ||
|
||
// Check if an artificat is specified and attempt to download it | ||
source, ok := task.Config["artifact_source"] | ||
if ok && source != "" { | ||
// Proceed to download an artifact to be executed. | ||
// We use go-getter to support a variety of protocols, but need to change | ||
// file permissions of the resulted download to be executable | ||
|
||
// Create a location to download the artifact. | ||
taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName] | ||
if !ok { | ||
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName) | ||
} | ||
destDir := filepath.Join(taskDir, allocdir.TaskLocal) | ||
|
||
artifactName := path.Base(source) | ||
artifactFile := filepath.Join(destDir, artifactName) | ||
if err := getter.GetFile(artifactFile, source); err != nil { | ||
return nil, fmt.Errorf("Error downloading artifact for Exec driver: %s", err) | ||
} | ||
|
||
// Add execution permissions to the newly downloaded artifact | ||
if runtime.GOOS != "windows" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We drop permissions for some of the drivers but not others. Could we move this into a shared "drop perms" function that can handle the various OSs and share between drivers? |
||
if err := syscall.Chmod(artifactFile, 0755); err != nil { | ||
log.Printf("[ERR] driver.Exec: Error making artifact executable: %s", err) | ||
} | ||
} | ||
} | ||
|
||
// Get the environment variables. | ||
envVars := TaskEnvironmentVariables(ctx, task) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,6 @@ import ( | |
"fmt" | ||
"io" | ||
"log" | ||
"net/http" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
|
@@ -19,6 +18,7 @@ import ( | |
"syscall" | ||
"time" | ||
|
||
"github.com/hashicorp/go-getter" | ||
"github.com/hashicorp/nomad/client/allocdir" | ||
"github.com/hashicorp/nomad/client/config" | ||
"github.com/hashicorp/nomad/nomad/structs" | ||
|
@@ -94,45 +94,25 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, | |
return nil, fmt.Errorf("Missing required Task Resource: Memory") | ||
} | ||
|
||
// Attempt to download the thing | ||
// Should be extracted to some kind of Http Fetcher | ||
// Right now, assume publicly accessible HTTP url | ||
resp, err := http.Get(source) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error downloading source for Qemu driver: %s", err) | ||
} | ||
|
||
// Get the tasks local directory. | ||
taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName] | ||
if !ok { | ||
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName) | ||
} | ||
taskLocal := filepath.Join(taskDir, allocdir.TaskLocal) | ||
|
||
// Create a location in the local directory to download and store the image. | ||
// TODO: Caching | ||
// Create a location to download the binary. | ||
destDir := filepath.Join(taskDir, allocdir.TaskLocal) | ||
vmID := fmt.Sprintf("qemu-vm-%s-%s", structs.GenerateUUID(), filepath.Base(source)) | ||
fPath := filepath.Join(taskLocal, vmID) | ||
vmPath, err := os.OpenFile(fPath, os.O_CREATE|os.O_WRONLY, 0666) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error opening file to download to: %s", err) | ||
} | ||
|
||
defer vmPath.Close() | ||
defer resp.Body.Close() | ||
|
||
// Copy remote file to local AllocDir for execution | ||
// TODO: a retry of sort if io.Copy fails, for large binaries | ||
_, ioErr := io.Copy(vmPath, resp.Body) | ||
if ioErr != nil { | ||
return nil, fmt.Errorf("Error copying Qemu image from source: %s", ioErr) | ||
vmPath := filepath.Join(destDir, vmID) | ||
if err := getter.GetFile(vmPath, source); err != nil { | ||
return nil, fmt.Errorf("Error downloading artifact for Qemu driver: %s", err) | ||
} | ||
|
||
// compute and check checksum | ||
if check, ok := task.Config["checksum"]; ok { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a nice feature, I wonder if we should make it a generic "artifact_checksum" so that all the drivers can use this? This could even do things like "md5:abcd" or "sha256:abc123" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can address that in a future pull request, I think. I'm (slowly) adding checksums into go-getter directly hashicorp/go-getter#1 |
||
d.logger.Printf("[DEBUG] Running checksum on (%s)", vmID) | ||
hasher := sha256.New() | ||
file, err := os.Open(vmPath.Name()) | ||
file, err := os.Open(vmPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("Failed to open file for checksum") | ||
} | ||
|
@@ -163,7 +143,7 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, | |
"-machine", "type=pc,accel=" + accelerator, | ||
"-name", vmID, | ||
"-m", mem, | ||
"-drive", "file=" + vmPath.Name(), | ||
"-drive", "file=" + vmPath, | ||
"-nodefconfig", | ||
"-nodefaults", | ||
"-nographic", | ||
|
@@ -240,7 +220,7 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, | |
// Create and Return Handle | ||
h := &qemuHandle{ | ||
proc: cmd.Process, | ||
vmID: vmPath.Name(), | ||
vmID: vmPath, | ||
doneCh: make(chan struct{}), | ||
waitCh: make(chan error, 1), | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should update this function to return an error and handle it in the drivers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opened #326 to track this