Skip to content

Commit

Permalink
Run Linux Images (LCOW) and Windows Containers side by side (#7850)
Browse files Browse the repository at this point in the history
Makes it possible to run Linux Containers On Windows with Nomad alongside Windows Containers. Fingerprint prevents only to run Nomad in Windows 10 with Linux Containers
  • Loading branch information
jlarriba committed May 4, 2020
1 parent b3d43b8 commit 65f09ed
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
2 changes: 1 addition & 1 deletion client/allocdir/fs_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var (
// directory shared across tasks in a task group.
SharedAllocContainerPath = filepath.Join("c:\\", SharedAllocName)

// TaskLocalContainer is the path inside a container for mounted directory
// TaskLocalContainerPath is the path inside a container for mounted directory
// for local storage.
TaskLocalContainerPath = filepath.Join("c:\\", TaskLocal)

Expand Down
27 changes: 25 additions & 2 deletions drivers/docker/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,13 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
return nil, nil, err
}

if runtime.GOOS == "windows" {
err = d.convertAllocPathsForWindowsLCOW(cfg, driverConfig.Image)
if err != nil {
return nil, nil, err
}
}

containerCfg, err := d.createContainerConfig(cfg, &driverConfig, driverConfig.Image)
if err != nil {
d.logger.Error("failed to create container configuration", "image_name", driverConfig.Image,
Expand Down Expand Up @@ -616,8 +623,24 @@ func (d *Driver) loadImage(task *drivers.TaskConfig, driverConfig *TaskConfig, c
return dockerImage.ID, nil
}

func (d *Driver) containerBinds(task *drivers.TaskConfig, driverConfig *TaskConfig) ([]string, error) {
func (d *Driver) convertAllocPathsForWindowsLCOW(task *drivers.TaskConfig, image string) error {
imageConfig, err := client.InspectImage(image)
if err != nil {
return fmt.Errorf("the image does not exist: %v", err)
}
// LCOW If we are running a Linux Container on Windows, we need to mount it correctly, as c:\ does not exist on unix
if imageConfig.OS == "linux" {
a := []rune(task.Env[taskenv.AllocDir])
task.Env[taskenv.AllocDir] = strings.ReplaceAll(string(a[2:]), "\\", "/")
l := []rune(task.Env[taskenv.TaskLocalDir])
task.Env[taskenv.TaskLocalDir] = strings.ReplaceAll(string(l[2:]), "\\", "/")
s := []rune(task.Env[taskenv.SecretsDir])
task.Env[taskenv.SecretsDir] = strings.ReplaceAll(string(s[2:]), "\\", "/")
}
return nil
}

func (d *Driver) containerBinds(task *drivers.TaskConfig, driverConfig *TaskConfig) ([]string, error) {
allocDirBind := fmt.Sprintf("%s:%s", task.TaskDir().SharedAllocDir, task.Env[taskenv.AllocDir])
taskLocalBind := fmt.Sprintf("%s:%s", task.TaskDir().LocalDir, task.Env[taskenv.TaskLocalDir])
secretDirBind := fmt.Sprintf("%s:%s", task.TaskDir().SecretsDir, task.Env[taskenv.SecretsDir])
Expand Down Expand Up @@ -723,7 +746,6 @@ func (d *Driver) createContainerConfig(task *drivers.TaskConfig, driverConfig *T
logger.Error("task.Resources is empty")
return c, fmt.Errorf("task.Resources is empty")
}

binds, err := d.containerBinds(task, driverConfig)
if err != nil {
return c, err
Expand Down Expand Up @@ -817,6 +839,7 @@ func (d *Driver) createContainerConfig(task *drivers.TaskConfig, driverConfig *T
logger.Debug("configured resources", "memory", hostConfig.Memory,
"cpu_shares", hostConfig.CPUShares, "cpu_quota", hostConfig.CPUQuota,
"cpu_period", hostConfig.CPUPeriod)

logger.Debug("binding directories", "binds", hclog.Fmt("%#v", hostConfig.Binds))

// set privileged mode
Expand Down
5 changes: 3 additions & 2 deletions drivers/docker/fingerprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,16 @@ func (d *Driver) buildFingerprint() *drivers.Fingerprint {
strings.Join(runtimeNames, ","))
fp.Attributes["driver.docker.os_type"] = pstructs.NewStringAttribute(dockerInfo.OSType)

// If this situations arises, we are running in Windows 10 with Linux Containers enabled via VM
if runtime.GOOS == "windows" && dockerInfo.OSType == "linux" {
if d.fingerprintSuccessful() {
d.logger.Warn("detected Linux docker containers on Windows; only Windows containers are supported")
d.logger.Warn("Docker is configured with Linux containers; switch to Windows Containers")
}

d.setFingerprintFailure()
return &drivers.Fingerprint{
Health: drivers.HealthStateUnhealthy,
HealthDescription: "Docker is configured with Linux containers; only Windows containers are supported",
HealthDescription: "Docker is configured with Linux containers; switch to Windows Containers",
}
}
}
Expand Down

0 comments on commit 65f09ed

Please sign in to comment.