forked from crc-org/crc
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Windows: Run 'crc daemon' as task for 'crc setup'
This PR is uses windows powershell to create `crc daemon` as task and start it on demand for the current user. This doesn't need any elevated privillages to run `crc daemon` for user context. It try to perform following tasks - Check if there is already crcDaemon task + If present does it the latest one using version info - Install the task using predefined xml definition - Start the task which run the `crc daemon` in background. There is a known issue with windows powershell when you start a task in background using `powershell.exe` then for a second the windows pops up and disappear, PowerShell/PowerShell#3028 have more details around it but as of now this is only the way for interactive user context otherwise the task will need the admin privillages which we want to avoid.
- Loading branch information
1 parent
aa7e94f
commit c4f1dfe
Showing
4 changed files
with
163 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
pkg/crc/preflight/preflight_daemon_task_check_windows.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package preflight | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/code-ready/crc/pkg/crc/constants" | ||
"github.com/code-ready/crc/pkg/crc/logging" | ||
"github.com/code-ready/crc/pkg/crc/version" | ||
"github.com/code-ready/crc/pkg/os/windows/powershell" | ||
) | ||
|
||
var ( | ||
// https://docs.microsoft.com/en-us/windows/win32/taskschd/daily-trigger-example--xml- | ||
daemonTaskTemplate = `<?xml version="1.0" encoding="UTF-16"?> | ||
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> | ||
<RegistrationInfo> | ||
<Description>Run crc daemon as a task</Description> | ||
<Version>%s</Version> | ||
</RegistrationInfo> | ||
<Settings> | ||
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> | ||
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries> | ||
<Hidden>true</Hidden> | ||
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> | ||
<IdleSettings> | ||
<Duration>PT10M</Duration> | ||
<WaitTimeout>PT1H</WaitTimeout> | ||
<StopOnIdleEnd>true</StopOnIdleEnd> | ||
<RestartOnIdle>false</RestartOnIdle> | ||
</IdleSettings> | ||
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine> | ||
</Settings> | ||
<Triggers /> | ||
<Actions Context="Author"> | ||
<Exec> | ||
<Command>powershell.exe</Command> | ||
<Arguments>-WindowStyle Hidden -Command %s</Arguments> | ||
</Exec> | ||
</Actions> | ||
</Task> | ||
` | ||
) | ||
|
||
func genDaemonTaskInstallTemplate(crcVersion, daemonServiceName string) string { | ||
return fmt.Sprintf(daemonTaskTemplate, | ||
crcVersion, | ||
daemonServiceName, | ||
) | ||
} | ||
|
||
func checkIfDaemonTaskInstalled() error { | ||
_, stderr, err := powershell.Execute("Get-ScheduledTask", "-TaskName", constants.DaemonTaskName) | ||
if err != nil { | ||
logging.Debugf("%s task is not installed: %v : %s", constants.DaemonTaskName, err, stderr) | ||
return err | ||
} | ||
if err := checkIfOlderTask(); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func fixDaemonTaskInstalled() error { | ||
// prepare the task script | ||
binPath, err := os.Executable() | ||
if err != nil { | ||
return fmt.Errorf("unable to find the current executable location: %v", err) | ||
} | ||
binPathWithArgs := fmt.Sprintf("%s daemon", binPath) | ||
|
||
taskContent := genDaemonTaskInstallTemplate( | ||
version.GetCRCVersion(), | ||
binPathWithArgs, | ||
) | ||
|
||
if _, stderr, err := powershell.Execute("Register-ScheduledTask", "-Xml", fmt.Sprintf(`'%s'`, taskContent), "-TaskName", constants.DaemonTaskName); err != nil { | ||
return fmt.Errorf("failed to register %s task, %v: %s", constants.DaemonTaskName, err, stderr) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func removeDaemonTask() error { | ||
if err := checkIfDaemonTaskRunning(); err == nil { | ||
_, stderr, err := powershell.Execute("Stop-ScheduledTask", "-TaskName", constants.DaemonTaskName) | ||
if err != nil { | ||
logging.Debugf("unable to stop the %s task: %v : %s", constants.DaemonTaskName, err, stderr) | ||
return err | ||
} | ||
} | ||
if err := checkIfDaemonTaskInstalled(); err == nil { | ||
_, stderr, err := powershell.Execute("Unregister-ScheduledTask", "-TaskName", constants.DaemonTaskName, "-Confirm:$false") | ||
if err != nil { | ||
logging.Debugf("unable to unregister the %s task: %v : %s", constants.DaemonTaskName, err, stderr) | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func checkIfDaemonTaskRunning() error { | ||
stdout, stderr, err := powershell.Execute(fmt.Sprintf(`(Get-ScheduledTask -TaskName "%s").State`, constants.DaemonTaskName)) | ||
if err != nil { | ||
logging.Debugf("%s task is not running: %v : %s", constants.DaemonTaskName, err, stderr) | ||
return err | ||
} | ||
if strings.TrimSpace(stdout) != "Running" { | ||
return fmt.Errorf("expected %s task to be in 'Running' but got '%s'", constants.DaemonTaskName, stdout) | ||
} | ||
return nil | ||
} | ||
|
||
func fixDaemonTaskRunning() error { | ||
_, stderr, err := powershell.Execute("Start-ScheduledTask", "-TaskName", constants.DaemonTaskName) | ||
if err != nil { | ||
logging.Debugf("unable to run the %s task: %v : %s", constants.DaemonTaskName, err, stderr) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func checkIfOlderTask() error { | ||
stdout, stderr, err := powershell.Execute(fmt.Sprintf(`(Get-ScheduledTask -TaskName "%s").Version`, constants.DaemonTaskName)) | ||
if err != nil { | ||
return fmt.Errorf("%s task is not running: %v : %s", constants.DaemonTaskName, err, stderr) | ||
} | ||
if strings.TrimSpace(stdout) != version.GetCRCVersion() { | ||
return fmt.Errorf("expected %s task to be on version '%s' but got '%s'", constants.DaemonTaskName, version.GetCRCVersion(), stdout) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters