Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/configurer/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"github.com/k0sproject/rig/os"
)

type rebootable interface {
Reboot() error
}

type DockerConfigurer struct{}

// GetDockerInfo gets docker info from the host.
Expand Down
4 changes: 0 additions & 4 deletions pkg/configurer/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ func GetInstaller(source string) (string, error) {
return path, nil
}

if path == "" {
return "", fmt.Errorf("%w; skipping failed installer download", ErrInstallerDownloadFailed)
}

path, getErr := downloadInstaller(source)
if getErr != nil {
return "", fmt.Errorf("%w, installer download failed; %s", ErrInstallerDownloadFailed, getErr.Error())
Expand Down
43 changes: 31 additions & 12 deletions pkg/configurer/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ func (c WindowsConfigurer) MCRConfigPath() string {
return `C:\ProgramData\Docker\config\daemon.json`
}

type rebootable interface {
Reboot() error
}

var errRebootRequired = fmt.Errorf("reboot required")

// InstallMCRLicense for license install..
Expand Down Expand Up @@ -88,23 +84,46 @@ func (c WindowsConfigurer) InstallMCR(h os.Host, engineConfig commonconfig.MCRCo
log.Infof("%s: running installer", h)

output, err := h.ExecOutput(installCommand)

needsReboot := false
if err != nil {
return fmt.Errorf("failed to run MCR installer: %w", err)
if isExitCode3010(err) {
needsReboot = true
} else {
return fmt.Errorf("failed to run MCR installer: %w", err)
}
}

if strings.Contains(output, "Your machine needs to be rebooted") {
log.Warnf("%s: host needs to be rebooted", h)
if rh, ok := h.(rebootable); ok {
if err := rh.Reboot(); err != nil {
return fmt.Errorf("%s: failed to reboot host: %w", h, err)
}
if !needsReboot && strings.Contains(output, "Your machine needs to be rebooted") {
needsReboot = true
}

if needsReboot {
log.Warnf("%s: host needs to be rebooted after MCR install", h)
rh, ok := h.(rebootable)
if !ok {
return fmt.Errorf("%s: %w: host does not support reboot", h, errRebootRequired)
}
if err := rh.Reboot(); err != nil {
return fmt.Errorf("%s: failed to reboot host: %w", h, err)
}
// Machine is back up. Delete the ONSTART scheduled task so it does not
// trigger another reboot on subsequent startups.
if err := h.Exec(`schtasks /delete /tn "RigReboot" /f`); err != nil {
log.Warnf("%s: failed to clean up RigReboot task: %s", h, err)
}
return fmt.Errorf("%s: %w: host isn't rebootable", h, errRebootRequired)
return nil
}

return nil
}

// isExitCode3010 checks if the error is a command failure with Windows exit
// code 3010 (ERROR_SUCCESS_REBOOT_REQUIRED).
func isExitCode3010(err error) bool {
return err != nil && strings.Contains(err.Error(), "non-zero exit code: 3010")
}

// UninstallMCR uninstalls docker-ee engine
// This relies on using the http://get.mirantis.com/install.ps1 script with the '-Uninstall' option, and some cleanup as per
// https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-docker/configure-docker-daemon#how-to-uninstall-docker
Expand Down
19 changes: 9 additions & 10 deletions pkg/docker/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,28 +95,27 @@ func (i *Image) Exist(h *mkeconfig.Host) bool {
// PullImages pulls multiple images parallelly by using a worker pool.
func PullImages(h *mkeconfig.Host, images []*Image) error {
wp := workerpool.New(5)
defer wp.StopWait()

var mutex sync.Mutex
var lastError error

for _, image := range images {
i := image // So we can safely pass i forward to pool without it getting mutated
wp.Submit(func() {
mutex.Lock()
defer mutex.Unlock()
if lastError != nil {
return
}

err := i.Pull(h)
if err != nil {
if err := i.Pull(h); err != nil {
mutex.Lock()
lastError = err
if lastError == nil {
lastError = err
}
mutex.Unlock()
}
})
}

// Wait for all workers to complete before reading lastError.
// A deferred StopWait() would let the return expression evaluate
// before workers finish, potentially returning nil on a real error.
wp.StopWait()
return lastError
}

Expand Down
Loading