Repository: code-ready/crc
Pull request #3090 (2022-03-29 12:45:01)

docs: Add OpenShift preset as a prerequisite to applicable procedures
This is a simple PR to add use of the `openshift` preset as a prerequisite to certain procedures which depend on the use of an OpenShift cluster.

openshift-ci[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/code-ready/crc/pull/3090#" title="Author self-approved">robin-owen</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=code-ready%2Fcrc).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[docs/OWNERS](https://github.com/code-ready/crc/blob/main/docs/OWNERS)~~ [robin-owen]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
openshift-ci[bot]: @robin-owen: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
ci/prow/e2e-crc | 5a8cef6d32a7a200b96e0a93085a544594ad2244 | [link](https://prow.ci.openshift.org/view/gs/origin-ci-test/pr-logs/pull/code-ready_crc/3090/pull-ci-code-ready-crc-main-e2e-crc/1508787323284754432) | true | `/test e2e-crc`

[Full PR test history](https://prow.ci.openshift.org/pr-history?org=code-ready&repo=crc&pr=3090). [Your PR dashboard](https://prow.ci.openshift.org/pr?query=is:pr+state:open+author:robin-owen).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/Makefile b/Makefile
index fac74896b..b710d3d9d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 SHELL := /bin/bash
 
-OPENSHIFT_VERSION ?= 4.10.4
+OPENSHIFT_VERSION ?= 4.10.6
 PODMAN_VERSION ?= 3.4.4
 BUNDLE_EXTENSION = crcbundle
 CRC_VERSION = 2.0.1
diff --git a/centos_ci.sh b/centos_ci.sh
index 0d7851244..01834fd35 100644
--- a/centos_ci.sh
+++ b/centos_ci.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # bundle location
-BUNDLE_VERSION=4.10.4
+BUNDLE_VERSION=4.10.6
 BUNDLE=crc_libvirt_$BUNDLE_VERSION_amd64.crcbundle
 GO_VERSION=1.16.10
 
diff --git a/cmd/crc/cmd/daemon.go b/cmd/crc/cmd/daemon.go
index 4bf5e79d0..0afb2cc7a 100644
--- a/cmd/crc/cmd/daemon.go
+++ b/cmd/crc/cmd/daemon.go
@@ -19,7 +19,6 @@ import (
 	"github.com/code-ready/crc/pkg/crc/constants"
 	"github.com/code-ready/crc/pkg/crc/daemonclient"
 	"github.com/code-ready/crc/pkg/crc/logging"
-	"github.com/code-ready/crc/pkg/crc/preflight"
 	"github.com/containers/gvisor-tap-vsock/pkg/types"
 	"github.com/containers/gvisor-tap-vsock/pkg/virtualnetwork"
 	"github.com/docker/go-units"
@@ -27,7 +26,6 @@ import (
 	"github.com/pkg/errors"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
-	"k8s.io/client-go/util/exec"
 )
 
 var watchdog bool
@@ -56,13 +54,6 @@ var daemonCmd = &cobra.Command{
 			return errors.New("daemon is already running")
 		}
 
-		if err := preflight.StartPreflightChecks(config); err != nil {
-			return exec.CodeExitError{
-				Err:  err,
-				Code: preflightFailedExitCode,
-			}
-		}
-
 		virtualNetworkConfig := types.Configuration{
 			Debug:             false, // never log packets
 			CaptureFile:       os.Getenv("CRC_DAEMON_PCAP_FILE"),
diff --git a/cmd/crc/cmd/daemon_darwin.go b/cmd/crc/cmd/daemon_darwin.go
index 4d02af8bf..e91c7a933 100644
--- a/cmd/crc/cmd/daemon_darwin.go
+++ b/cmd/crc/cmd/daemon_darwin.go
@@ -6,7 +6,6 @@ import (
 
 	"github.com/code-ready/crc/pkg/crc/constants"
 	"github.com/code-ready/crc/pkg/crc/logging"
-	crcversion "github.com/code-ready/crc/pkg/crc/version"
 )
 
 func vsockListener() (net.Listener, error) {
@@ -34,9 +33,6 @@ func checkIfDaemonIsRunning() (bool, error) {
 }
 
 func daemonNotRunningMessage() string {
-	if crcversion.IsInstaller() {
-		return "Is '/Applications/CodeReady Containers.app' running? Cannot reach daemon API"
-	}
 	return genericDaemonNotRunningMessage
 }
 
diff --git a/cmd/crc/cmd/podman_env.go b/cmd/crc/cmd/podman_env.go
index 26d308228..1a9a1c04d 100644
--- a/cmd/crc/cmd/podman_env.go
+++ b/cmd/crc/cmd/podman_env.go
@@ -38,9 +38,9 @@ func runPodmanEnv() error {
 		return err
 	}
 
-	socket := "/run/user/1000/podman/podman.sock"
+	socket := constants.RootlessPodmanSocket
 	if root {
-		socket = "/run/podman/podman.sock"
+		socket = constants.RootfulPodmanSocket
 	}
 	fmt.Println(shell.GetPathEnvString(userShell, constants.CrcOcBinDir))
 	fmt.Println(shell.GetEnvString(userShell, "CONTAINER_SSHKEY", connectionDetails.SSHKeys[0]))
diff --git a/docs/source/topics/proc_accessing-the-internal-openshift-registry.adoc b/docs/source/topics/proc_accessing-the-internal-openshift-registry.adoc
index efab2174b..2c5c1c99f 100644
--- a/docs/source/topics/proc_accessing-the-internal-openshift-registry.adoc
+++ b/docs/source/topics/proc_accessing-the-internal-openshift-registry.adoc
@@ -7,6 +7,8 @@ To access the internal OpenShift registry, follow these steps.
 
 .Prerequisites
 
+* {prod} is configured to use the {openshift} preset.
+For more information, see link:{crc-gsg-url}#changing-the-selected-preset_gsg[Changing the selected preset].
 * A running {prod} instance.
 For more information, see link:{crc-gsg-url}#starting-the-instance_gsg[Starting the instance].
 * A working OpenShift CLI ([command]`oc`) command.
diff --git a/docs/source/topics/proc_accessing-the-openshift-cluster-with-oc.adoc b/docs/source/topics/proc_accessing-the-openshift-cluster-with-oc.adoc
index bb9ba4bd0..2e28c4458 100644
--- a/docs/source/topics/proc_accessing-the-openshift-cluster-with-oc.adoc
+++ b/docs/source/topics/proc_accessing-the-openshift-cluster-with-oc.adoc
@@ -5,6 +5,8 @@ Access the OpenShift cluster by using the OpenShift CLI ([command]`oc`).
 
 .Prerequisites
 
+* {prod} is configured to use the {openshift} preset.
+For more information, see link:{crc-gsg-url}#changing-the-selected-preset_gsg[Changing the selected preset].
 * A running {prod} instance.
 For more information, see link:{crc-gsg-url}#starting-the-instance_gsg[Starting the instance].
 
diff --git a/docs/source/topics/proc_accessing-the-openshift-web-console.adoc b/docs/source/topics/proc_accessing-the-openshift-web-console.adoc
index 1f1c9ebeb..ee13da2e1 100644
--- a/docs/source/topics/proc_accessing-the-openshift-web-console.adoc
+++ b/docs/source/topics/proc_accessing-the-openshift-web-console.adoc
@@ -9,6 +9,8 @@ Use the `kubeadmin` user only for administrative tasks such as creating new user
 
 .Prerequisites
 
+* {prod} is configured to use the {openshift} preset.
+For more information, see link:{crc-gsg-url}#changing-the-selected-preset_gsg[Changing the selected preset].
 * A running {prod} instance.
 For more information, see link:{crc-gsg-url}#starting-the-instance_gsg[Starting the instance].
 
diff --git a/docs/source/topics/proc_changing-the-selected-preset.adoc b/docs/source/topics/proc_changing-the-selected-preset.adoc
index 9c9d2013f..fc9617ff9 100644
--- a/docs/source/topics/proc_changing-the-selected-preset.adoc
+++ b/docs/source/topics/proc_changing-the-selected-preset.adoc
@@ -20,7 +20,7 @@ To enable preset changes, you must delete the existing instance and start a new
 +
 [subs="+quotes,attributes"]
 ----
-$ {bin} config preset __<name>__
+$ {bin} config set preset __<name>__
 ----
 +
 Valid preset names are `openshift` for {ocp} and `podman` for the Podman container runtime.
diff --git a/docs/source/topics/proc_deploying-sample-application-with-odo.adoc b/docs/source/topics/proc_deploying-sample-application-with-odo.adoc
index 962c30629..0d88ade39 100644
--- a/docs/source/topics/proc_deploying-sample-application-with-odo.adoc
+++ b/docs/source/topics/proc_deploying-sample-application-with-odo.adoc
@@ -8,6 +8,8 @@ This procedure deploys a sample application to the OpenShift cluster running in
 
 * You have installed [command]`odo`.
 For more information, see link:{odo-docs-url-installing}[Installing `odo`] in the [command]`odo` documentation.
+* {prod} is configured to use the {openshift} preset.
+For more information, see link:{crc-gsg-url}#changing-the-selected-preset_gsg[Changing the selected preset].
 * The {prod} instance is running.
 For more information, see link:{crc-gsg-url}#starting-the-instance_gsg[Starting the instance].
 
diff --git a/docs/source/topics/proc_setting-up-remote-server.adoc b/docs/source/topics/proc_setting-up-remote-server.adoc
index 7e8cde23f..57521d72c 100644
--- a/docs/source/topics/proc_setting-up-remote-server.adoc
+++ b/docs/source/topics/proc_setting-up-remote-server.adoc
@@ -16,6 +16,8 @@ Exposing an insecure server on the internet has many security implications.
 
 * {prod} is installed and set up on the remote server.
 For more information, see link:{crc-gsg-url}#installing-codeready-containers_gsg[Installing {prod}] and link:{crc-gsg-url}#setting-up-codeready-containers_gsg[Setting up {prod}].
+* {prod} is configured to use the {openshift} preset on the remote server.
+For more information, see link:{crc-gsg-url}#changing-the-selected-preset_gsg[Changing the selected preset].
 * Your user account has `sudo` permissions on the remote server.
 
 .Procedure
diff --git a/packaging/windows/product.wxs.template b/packaging/windows/product.wxs.template
index 1171d6409..d082e174e 100755
--- a/packaging/windows/product.wxs.template
+++ b/packaging/windows/product.wxs.template
@@ -83,6 +83,8 @@
         <CustomAction Id="RemoveCrcGroup" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Impersonate="no" Return="ignore" />
         <SetProperty Action="CARemoveCrcUsersGroupRollback" Id="RemoveCrcGroupRollback" Value='"[System64Folder]cmd.exe" /c net localgroup crc-users /del' Before="RemoveCrcGroup" Sequence="execute"/>
         <CustomAction Id="RemoveCrcGroupRollback" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="rollback" Impersonate="no" Return="ignore" />
+        <SetProperty Action="CARemoveCrcDaemonTask" Id="RemoveCrcDaemonTask" Value='"[System64Folder]cmd.exe" /c schtasks /delete /TN crcDaemon /F' Before='RemoveFiles' Sequence="execute"/>
+        <CustomAction Id="RemoveCrcDaemonTask" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Impersonate="no" Return="ignore" />
 
         <SetProperty Action="CAInstallHyperv" Id="InstallHyperv" Value='"[System64Folder]dism.exe" /online /enable-feature /featureName:microsoft-hyper-v-all /NoRestart /quiet' Before="InstallHyperv" Sequence="execute"/>
         <CustomAction Id="InstallHyperv" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="deferred" Impersonate="no" Return="ignore" />
@@ -98,6 +100,7 @@
             <Custom Action="RemoveCrcGroup" After="RemoveFolders"> Installed AND NOT PATCH AND REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE</Custom>
             <Custom Action="InstallHyperv" Before="CreateCrcGroup"> NOT Installed AND NOT REMOVE~="ALL" AND NOT WIX_UPGRADE_DETECTED</Custom>
             <Custom Action="RemoveCrcGroupRollback" After="CreateCrcGroup"> NOT Installed AND NOT REMOVE~="ALL" AND NOT WIX_UPGRADE_DETECTED</Custom>
+            <Custom Action="RemoveCrcDaemonTask" Before='RemoveFiles'>Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
             <ScheduleReboot After="InstallFinalize"> NOT Installed AND NOT REMOVE~="ALL" AND NOT WIX_UPGRADE_DETECTED</ScheduleReboot>
         </InstallExecuteSequence>
         <Feature Id="DefaultFeature" Level="1">
@@ -117,6 +120,7 @@
             <ProgressText Action="RemoveCrcGroup">Removing crc-users group</ProgressText>
             <ProgressText Action="InstallHyperv">Installing Hyper-V</ProgressText>
             <ProgressText Action="AddUserToHypervAdminGroup">Adding user: [LogonUser] to Hyper-V Administrators group</ProgressText>
+            <ProgressText Action="RemoveCrcDaemonTask">Removing crcDaemon task</ProgressText>
         </UI>
         <Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
         <!-- this should help to propagate env var changes -->
diff --git a/pkg/crc/constants/constants.go b/pkg/crc/constants/constants.go
index b24023edd..46d0e447b 100644
--- a/pkg/crc/constants/constants.go
+++ b/pkg/crc/constants/constants.go
@@ -30,6 +30,8 @@ const (
 	DefaultContext            = "admin"
 	DaemonHTTPEndpoint        = "http://unix/api"
 	DefaultPodmanNamedPipe    = `\\.\pipe\crc-podman`
+	RootlessPodmanSocket      = "/run/user/1000/podman/podman.sock"
+	RootfulPodmanSocket       = "/run/podman/podman.sock"
 
 	VSockGateway = "192.168.127.1"
 	VsockSSHPort = 2222
diff --git a/pkg/crc/constants/constants_darwin.go b/pkg/crc/constants/constants_darwin.go
index 7a0a21d07..48e8990a5 100644
--- a/pkg/crc/constants/constants_darwin.go
+++ b/pkg/crc/constants/constants_darwin.go
@@ -10,6 +10,7 @@ const (
 	OcExecutableName           = "oc"
 	PodmanRemoteExecutableName = "podman"
 	TrayExecutableName         = "CodeReady Containers.app"
+	DaemonAgentLabel           = "com.redhat.crc.daemon"
 )
 
 var (
diff --git a/pkg/crc/constants/constants_windows.go b/pkg/crc/constants/constants_windows.go
index b213c2eb3..5c7742993 100644
--- a/pkg/crc/constants/constants_windows.go
+++ b/pkg/crc/constants/constants_windows.go
@@ -5,4 +5,6 @@ const (
 	PodmanRemoteExecutableName = "podman.exe"
 	TapSocketPath              = ""
 	DaemonHTTPNamedPipe        = `\\.\pipe\crc-http`
+	DaemonTaskName             = "crcDaemon"
+	AdminHelperServiceName     = "CodeReadyContainersAdminHelper"
 )
diff --git a/pkg/crc/machine/delete.go b/pkg/crc/machine/delete.go
index c78c319c9..7e2f095bb 100644
--- a/pkg/crc/machine/delete.go
+++ b/pkg/crc/machine/delete.go
@@ -4,6 +4,7 @@ import (
 	"os"
 
 	"github.com/code-ready/crc/pkg/crc/logging"
+	"github.com/code-ready/crc/pkg/crc/podman"
 	"github.com/pkg/errors"
 )
 
@@ -25,6 +26,14 @@ func (client *client) Delete() error {
 		}
 	}
 
+	// Remove the podman system connection for crc
+	if err := podman.RemoveRootlessSystemConnection(); err != nil {
+		return err
+	}
+	if err := podman.RemoveRootfulSystemConnection(); err != nil {
+		return err
+	}
+
 	if err := cleanKubeconfig(getGlobalKubeConfigPath(), getGlobalKubeConfigPath()); err != nil {
 		if !errors.Is(err, os.ErrNotExist) {
 			logging.Warnf("Failed to remove crc contexts from kubeconfig: %v", err)
diff --git a/pkg/crc/machine/start.go b/pkg/crc/machine/start.go
index f87980108..91c0616d4 100644
--- a/pkg/crc/machine/start.go
+++ b/pkg/crc/machine/start.go
@@ -23,6 +23,7 @@ import (
 	"github.com/code-ready/crc/pkg/crc/machine/types"
 	"github.com/code-ready/crc/pkg/crc/network"
 	"github.com/code-ready/crc/pkg/crc/oc"
+	"github.com/code-ready/crc/pkg/crc/podman"
 	crcPreset "github.com/code-ready/crc/pkg/crc/preset"
 	"github.com/code-ready/crc/pkg/crc/services"
 	"github.com/code-ready/crc/pkg/crc/services/dns"
@@ -331,6 +332,14 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
 			return nil, fmt.Errorf("Failed to rotate bearer token for cockpit webconsole: %w", err)
 		}
 
+		c, err := client.ConnectionDetails()
+		if err != nil {
+			return nil, err
+		}
+		if err := addPodmanSystemConnections(c); err != nil {
+			return nil, err
+		}
+
 		return &types.StartResult{
 			Status: vmState,
 		}, nil
@@ -757,3 +766,18 @@ func updateCockpitConsoleBearerToken(sshRunner *crcssh.Runner) error {
 
 	return nil
 }
+
+func addPodmanSystemConnections(c *types.ConnectionDetails) error {
+	rootlessURI := fmt.Sprintf("ssh://%s@%s:%d%s", c.SSHUsername, c.IP, c.SSHPort, constants.RootlessPodmanSocket)
+	rootfulURI := fmt.Sprintf("ssh://%s@%s:%d%s", c.SSHUsername, c.IP, c.SSHPort, constants.RootfulPodmanSocket)
+	if err := podman.AddRootlessSystemConnection(c.SSHKeys[0], rootlessURI); err != nil {
+		return err
+	}
+	if err := podman.MakeRootlessSystemConnectionDefault(); err != nil {
+		return err
+	}
+	if err := podman.AddRootfulSystemConnection(c.SSHKeys[0], rootfulURI); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/pkg/crc/podman/podman.go b/pkg/crc/podman/podman.go
new file mode 100644
index 000000000..427aa918a
--- /dev/null
+++ b/pkg/crc/podman/podman.go
@@ -0,0 +1,65 @@
+package podman
+
+import (
+	"fmt"
+	"path/filepath"
+
+	"github.com/code-ready/crc/pkg/crc/constants"
+	crcos "github.com/code-ready/crc/pkg/os"
+)
+
+const (
+	rootlessConn = "crc"
+	rootfulConn  = "crc-root"
+)
+
+var podmanExecutablePath = filepath.Join(constants.CrcOcBinDir, constants.PodmanRemoteExecutableName)
+
+func run(args ...string) (string, string, error) {
+	return crcos.RunWithDefaultLocale(podmanExecutablePath, args...)
+}
+
+func addSystemConnection(name, identity, uri string) error {
+	if _, stderr, err := run("system", "connection", "add", "--identity", identity, name, uri); err != nil {
+		return fmt.Errorf("failed to add podman system connection %v: %s", err, stderr)
+	}
+	return nil
+}
+
+func AddRootlessSystemConnection(sshIdentity, uri string) error {
+	return addSystemConnection(rootlessConn, sshIdentity, uri)
+}
+
+func AddRootfulSystemConnection(sshIdentity, uri string) error {
+	return addSystemConnection(rootfulConn, sshIdentity, uri)
+}
+
+func removeSystemConnection(name string) error {
+	if _, stderr, err := run("system", "connection", "remove", name); err != nil {
+		return fmt.Errorf("failed to remove podman system connection %v: %s", err, stderr)
+	}
+	return nil
+}
+
+func RemoveRootlessSystemConnection() error {
+	return removeSystemConnection(rootlessConn)
+}
+
+func RemoveRootfulSystemConnection() error {
+	return removeSystemConnection(rootfulConn)
+}
+
+func makeSystemConnectionDefault(name string) error {
+	if _, stderr, err := run("system", "connection", "default", name); err != nil {
+		return fmt.Errorf("failed to make %s podman system connection as default %v: %s", name, err, stderr)
+	}
+	return nil
+}
+
+func MakeRootlessSystemConnectionDefault() error {
+	return makeSystemConnectionDefault(rootlessConn)
+}
+
+func MakeRootfulSystemConnectionDefault() error {
+	return makeSystemConnectionDefault(rootfulConn)
+}
diff --git a/pkg/crc/preflight/preflight_checks_darwin.go b/pkg/crc/preflight/preflight_checks_darwin.go
index 0d9e6cbd9..c8ecbb670 100644
--- a/pkg/crc/preflight/preflight_checks_darwin.go
+++ b/pkg/crc/preflight/preflight_checks_darwin.go
@@ -15,6 +15,7 @@ import (
 	"github.com/code-ready/crc/pkg/crc/network"
 	"github.com/code-ready/crc/pkg/crc/version"
 	crcos "github.com/code-ready/crc/pkg/os"
+	"github.com/code-ready/crc/pkg/os/launchd"
 	"github.com/klauspost/cpuid/v2"
 	"golang.org/x/sys/unix"
 )
@@ -242,3 +243,65 @@ func stopCRCHyperkitProcess() error {
 	}
 	return nil
 }
+
+func getDaemonConfig() (*launchd.AgentConfig, error) {
+	logFilePath := filepath.Join(constants.CrcBaseDir, ".launchd-crcd.log")
+
+	env := map[string]string{"Version": version.GetCRCVersion()}
+	daemonConfig := launchd.AgentConfig{
+		Label:          constants.DaemonAgentLabel,
+		ExecutablePath: constants.CrcSymlinkPath,
+		StdOutFilePath: logFilePath,
+		StdErrFilePath: logFilePath,
+		Args:           []string{"daemon", "--log-level=debug"},
+		Env:            env,
+	}
+
+	return &daemonConfig, nil
+}
+
+func checkIfDaemonPlistFileExists() error {
+	daemonConfig, err := getDaemonConfig()
+	if err != nil {
+		return err
+	}
+	if err := launchd.CheckPlist(*daemonConfig); err != nil {
+		return err
+	}
+	if !launchd.AgentRunning(daemonConfig.Label) {
+		return fmt.Errorf("launchd agent '%s' is not running", daemonConfig.Label)
+	}
+	return nil
+}
+
+func fixDaemonPlistFileExists() error {
+	daemonConfig, err := getDaemonConfig()
+	if err != nil {
+		return err
+	}
+	return fixPlistFileExists(*daemonConfig)
+}
+
+func removeDaemonPlistFile() error {
+	if err := launchd.UnloadPlist(constants.DaemonAgentLabel); err != nil {
+		return err
+	}
+	return launchd.RemovePlist(constants.DaemonAgentLabel)
+}
+
+func fixPlistFileExists(agentConfig launchd.AgentConfig) error {
+	logging.Debugf("Creating plist for %s", agentConfig.Label)
+	err := launchd.CreatePlist(agentConfig)
+	if err != nil {
+		return err
+	}
+	if err := launchd.LoadPlist(agentConfig.Label); err != nil {
+		logging.Debugf("failed to load launchd agent '%s': %v", agentConfig.Label, err.Error())
+		return err
+	}
+	if err := launchd.RestartAgent(agentConfig.Label); err != nil {
+		logging.Debugf("failed to restart launchd agent '%s': %v", agentConfig.Label, err.Error())
+		return err
+	}
+	return nil
+}
diff --git a/pkg/crc/preflight/preflight_checks_linux.go b/pkg/crc/preflight/preflight_checks_linux.go
index 75e6120ff..0c55b8386 100644
--- a/pkg/crc/preflight/preflight_checks_linux.go
+++ b/pkg/crc/preflight/preflight_checks_linux.go
@@ -700,50 +700,3 @@ func getCPUFlags() (string, error) {
 	}
 	return flags, nil
 }
-
-func runtimeExecutablePath() (string, error) {
-	path, err := exec.LookPath(os.Args[0])
-	if err != nil {
-		// os.Args[0] is not in $PATH, crc must have been started by specifying the path to its binary
-		path = os.Args[0]
-	}
-	path, err = filepath.Abs(path)
-	if err != nil {
-		return "", err
-	}
-	return filepath.EvalSymlinks(path)
-}
-
-func checkCrcSymlink() error {
-	runtimePath, err := runtimeExecutablePath()
-	if err != nil {
-		return err
-	}
-	symlinkPath, err := filepath.EvalSymlinks(constants.CrcSymlinkPath)
-	if err != nil {
-		return err
-	}
-	if symlinkPath != runtimePath {
-		return fmt.Errorf("%s points to %s, not to %s", constants.CrcSymlinkPath, symlinkPath, runtimePath)
-	}
-
-	return nil
-}
-
-func fixCrcSymlink() error {
-	_ = os.Remove(constants.CrcSymlinkPath)
-
-	runtimePath, err := runtimeExecutablePath()
-	if err != nil {
-		return err
-	}
-	logging.Debugf("symlinking %s to %s", runtimePath, constants.CrcSymlinkPath)
-	return os.Symlink(runtimePath, constants.CrcSymlinkPath)
-}
-
-func removeCrcSymlink() error {
-	if crcos.FileExists(constants.CrcSymlinkPath) {
-		return os.Remove(constants.CrcSymlinkPath)
-	}
-	return nil
-}
diff --git a/pkg/crc/preflight/preflight_checks_nonwin.go b/pkg/crc/preflight/preflight_checks_nonwin.go
index 5ca8f3f2e..f99ed4b72 100644
--- a/pkg/crc/preflight/preflight_checks_nonwin.go
+++ b/pkg/crc/preflight/preflight_checks_nonwin.go
@@ -6,6 +6,7 @@ package preflight
 import (
 	"fmt"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"runtime"
 	"syscall"
@@ -70,6 +71,17 @@ func genericPreflightChecks(preset crcpreset.Preset) []Check {
 			fixDescription: fmt.Sprintf("crc requires at least %s to run", units.HumanSize(float64(constants.GetDefaultMemory(preset)*1024*1024))),
 			flags:          NoFix,
 
+			labels: None,
+		},
+		{
+			configKeySuffix:    "check-crc-symlink",
+			checkDescription:   "Checking if crc executable symlink exists",
+			check:              checkCrcSymlink,
+			fixDescription:     "Creating symlink for crc executable",
+			fix:                fixCrcSymlink,
+			cleanupDescription: "Removing crc executable symlink",
+			cleanup:            removeCrcSymlink,
+
 			labels: None,
 		},
 	}
@@ -186,3 +198,50 @@ func checkSupportedCPUArch() error {
 	}
 	return nil
 }
+
+func runtimeExecutablePath() (string, error) {
+	path, err := exec.LookPath(os.Args[0])
+	if err != nil {
+		// os.Args[0] is not in $PATH, crc must have been started by specifying the path to its binary
+		path = os.Args[0]
+	}
+	path, err = filepath.Abs(path)
+	if err != nil {
+		return "", err
+	}
+	return filepath.EvalSymlinks(path)
+}
+
+func checkCrcSymlink() error {
+	runtimePath, err := runtimeExecutablePath()
+	if err != nil {
+		return err
+	}
+	symlinkPath, err := filepath.EvalSymlinks(constants.CrcSymlinkPath)
+	if err != nil {
+		return err
+	}
+	if symlinkPath != runtimePath {
+		return fmt.Errorf("%s points to %s, not to %s", constants.CrcSymlinkPath, symlinkPath, runtimePath)
+	}
+
+	return nil
+}
+
+func fixCrcSymlink() error {
+	_ = os.Remove(constants.CrcSymlinkPath)
+
+	runtimePath, err := runtimeExecutablePath()
+	if err != nil {
+		return err
+	}
+	logging.Debugf("symlinking %s to %s", runtimePath, constants.CrcSymlinkPath)
+	return os.Symlink(runtimePath, constants.CrcSymlinkPath)
+}
+
+func removeCrcSymlink() error {
+	if crcos.FileExists(constants.CrcSymlinkPath) {
+		return os.Remove(constants.CrcSymlinkPath)
+	}
+	return nil
+}
diff --git a/pkg/crc/preflight/preflight_checks_windows.go b/pkg/crc/preflight/preflight_checks_windows.go
index b2f0d59e4..de9f52d04 100644
--- a/pkg/crc/preflight/preflight_checks_windows.go
+++ b/pkg/crc/preflight/preflight_checks_windows.go
@@ -183,3 +183,14 @@ func removeCrcVM() (err error) {
 	logging.Debug("'crc' VM is removed")
 	return nil
 }
+
+func checkIfAdminHelperServiceRunning() error {
+	stdout, stderr, err := powershell.Execute(fmt.Sprintf("(Get-Service %s).Status", constants.AdminHelperServiceName))
+	if err != nil {
+		return fmt.Errorf("%s service is not present %v: %s", constants.AdminHelperServiceName, err, stderr)
+	}
+	if strings.TrimSpace(stdout) != "Running" {
+		return fmt.Errorf("%s service is not running", constants.AdminHelperServiceName)
+	}
+	return nil
+}
diff --git a/pkg/crc/preflight/preflight_daemon_task_check_windows.go b/pkg/crc/preflight/preflight_daemon_task_check_windows.go
new file mode 100644
index 000000000..0c5a76833
--- /dev/null
+++ b/pkg/crc/preflight/preflight_daemon_task_check_windows.go
@@ -0,0 +1,159 @@
+package preflight
+
+import (
+	"bytes"
+	"encoding/xml"
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/code-ready/crc/pkg/crc/constants"
+	"github.com/code-ready/crc/pkg/crc/daemonclient"
+	"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, daemonCommand string) (string, error) {
+	var escapedName bytes.Buffer
+	if err := xml.EscapeText(&escapedName, []byte(daemonCommand)); err != nil {
+		return "", err
+	}
+
+	return fmt.Sprintf(daemonTaskTemplate,
+		crcVersion,
+		escapedName.String(),
+	), nil
+}
+
+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, err := genDaemonTaskInstallTemplate(
+		version.GetCRCVersion(),
+		binPathWithArgs,
+	)
+	if err != nil {
+		return err
+	}
+
+	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 {
+	if isDaemonRunningWithReleasedVersion() {
+		return nil
+	}
+	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
+}
+
+func isDaemonRunningWithReleasedVersion() bool {
+	ver, err := daemonclient.New().APIClient.Version()
+	if err != nil {
+		return false
+	}
+	if ver.CrcVersion != version.GetCRCVersion() {
+		logging.Debugf("Daemon is running with %s version but binary version is %s", ver.CrcVersion, version.GetCRCVersion())
+		return false
+	}
+	return true
+}
diff --git a/pkg/crc/preflight/preflight_darwin.go b/pkg/crc/preflight/preflight_darwin.go
index 3a60eed97..d94b7e1c0 100644
--- a/pkg/crc/preflight/preflight_darwin.go
+++ b/pkg/crc/preflight/preflight_darwin.go
@@ -99,6 +99,18 @@ var resolverPreflightChecks = []Check{
 	},
 }
 
+var daemonLaunchdChecks = []Check{
+	{
+		configKeySuffix:    "check-daemon-launchd-plist",
+		checkDescription:   "Checking if crc daemon plist file is present and loaded",
+		check:              checkIfDaemonPlistFileExists,
+		fixDescription:     "Adding crc daemon plist file and loading it",
+		fix:                fixDaemonPlistFileExists,
+		cleanupDescription: "Unloading and removing the daemon plist file",
+		cleanup:            removeDaemonPlistFile,
+	},
+}
+
 // We want all preflight checks including
 // - experimental checks
 // - tray checks when using an installer, regardless of tray enabled or not
@@ -120,6 +132,7 @@ func getChecks(mode network.Mode, bundlePath string, preset crcpreset.Preset) []
 	checks = append(checks, resolverPreflightChecks...)
 	checks = append(checks, bundleCheck(bundlePath, preset))
 	checks = append(checks, trayLaunchdCleanupChecks...)
+	checks = append(checks, daemonLaunchdChecks...)
 
 	return checks
 }
diff --git a/pkg/crc/preflight/preflight_linux.go b/pkg/crc/preflight/preflight_linux.go
index e238e65d7..80d8f40f3 100644
--- a/pkg/crc/preflight/preflight_linux.go
+++ b/pkg/crc/preflight/preflight_linux.go
@@ -20,17 +20,6 @@ import (
 
 func libvirtPreflightChecks(distro *linux.OsRelease) []Check {
 	checks := []Check{
-		{
-			configKeySuffix:    "check-crc-symlink",
-			checkDescription:   "Checking if crc executable symlink exists",
-			check:              checkCrcSymlink,
-			fixDescription:     "Creating symlink for crc executable",
-			fix:                fixCrcSymlink,
-			cleanupDescription: "Removing crc executable symlink",
-			cleanup:            removeCrcSymlink,
-
-			labels: labels{Os: Linux},
-		},
 		{
 			configKeySuffix:  "check-virt-enabled",
 			checkDescription: "Checking if Virtualization is enabled",
diff --git a/pkg/crc/preflight/preflight_windows.go b/pkg/crc/preflight/preflight_windows.go
index f3a01a121..2bf47b4d7 100644
--- a/pkg/crc/preflight/preflight_windows.go
+++ b/pkg/crc/preflight/preflight_windows.go
@@ -83,14 +83,14 @@ var hypervPreflightChecks = []Check{
 		check:            checkIfHyperVVirtualSwitchExists,
 		flags:            StartUpOnly,
 
-		labels: labels{Os: Windows},
+		labels: labels{Os: Windows, NetworkMode: System},
 	},
 	{
 		cleanupDescription: "Removing dns server from interface",
 		cleanup:            removeDNSServerAddress,
 		flags:              CleanUpOnly,
 
-		labels: labels{Os: Windows},
+		labels: labels{Os: Windows, NetworkMode: System},
 	},
 	{
 		cleanupDescription: "Removing crc's virtual machine",
@@ -112,6 +112,41 @@ var vsockChecks = []Check{
 	},
 }
 
+var daemonTaskChecks = []Check{
+	{
+		configKeySuffix:    "check-daemon-task-install",
+		checkDescription:   "Checking if daemon task is installed",
+		check:              checkIfDaemonTaskInstalled,
+		fixDescription:     "Installing the daemon task",
+		fix:                fixDaemonTaskInstalled,
+		cleanupDescription: "Removing daemon task",
+		cleanup:            removeDaemonTask,
+
+		labels: labels{Os: Windows},
+	},
+	{
+		configKeySuffix:  "check-daemon-task-running",
+		checkDescription: "Checking if daemon task is running",
+		check:            checkIfDaemonTaskRunning,
+		fixDescription:   "Running the daemon task",
+		fix:              fixDaemonTaskRunning,
+
+		labels: labels{Os: Windows},
+	},
+}
+
+var adminHelperServiceCheks = []Check{
+	{
+		configKeySuffix:  "check-admin-helper-service-running",
+		checkDescription: "Checking admin helper service is running",
+		check:            checkIfAdminHelperServiceRunning,
+		fixDescription:   "Make sure you installed the crc using installer",
+		flags:            NoFix,
+
+		labels: labels{Os: Windows},
+	},
+}
+
 var errReboot = errors.New("Please reboot your system and run 'crc setup' to complete the setup process")
 
 func username() string {
@@ -157,6 +192,8 @@ func getChecks(bundlePath string, preset crcpreset.Preset) []Check {
 	checks = append(checks, vsockChecks...)
 	checks = append(checks, bundleCheck(bundlePath, preset))
 	checks = append(checks, genericCleanupChecks...)
+	checks = append(checks, daemonTaskChecks...)
+	checks = append(checks, adminHelperServiceCheks...)
 	return checks
 }
 
diff --git a/pkg/os/launchd/launchd_darwin.go b/pkg/os/launchd/launchd_darwin.go
index 96370fc70..6f05a8861 100644
--- a/pkg/os/launchd/launchd_darwin.go
+++ b/pkg/os/launchd/launchd_darwin.go
@@ -18,28 +18,34 @@ import (
 
 const (
 	plistTemplate = `<?xml version='1.0' encoding='UTF-8'?>
-	<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-	<plist version='1.0'>
-		<dict>
-			<key>Label</key>
-			<string>{{ .Label }}</string>
-			<key>ProgramArguments</key>
-			<array>
-				<string>{{ .ExecutablePath }}</string>
-			{{ range .Args }}
-				<string>{{ . }}</string>
-			{{ end }}
-			</array>
-			<key>StandardOutPath</key>
-			<string>{{ .StdOutFilePath }}</string>
-			<key>Disabled</key>
-			<false/>
-			<key>RunAtLoad</key>
-			<true/>
-			<key>ProcessType</key>
-			<string>Interactive</string>
-		</dict>
-	</plist>`
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version='1.0'>
+<dict>
+	<key>Label</key>
+	<string>{{ .Label }}</string>
+	<key>ProgramArguments</key>
+	<array>
+		<string>{{ .ExecutablePath }}</string>
+	{{ range .Args }}
+		<string>{{ . }}</string>
+	{{ end }}
+	</array>
+	<key>StandardOutPath</key>
+	<string>{{ .StdOutFilePath }}</string>
+	<key>StandardErrorPath</key>
+	<string>{{ .StdErrFilePath }}</string>
+	<key>EnvironmentVariables</key>
+	<dict>
+		{{ range $key, $value := .Env }}
+		<key>{{ $key }}</key>
+		<string>{{ $value }}</string>
+		{{ end }}
+	</dict>
+	<key>RunAtLoad</key>
+	<true/>
+</dict>
+</plist>
+`
 )
 
 // AgentConfig is struct to contain configuration for agent plist file
@@ -47,7 +53,9 @@ type AgentConfig struct {
 	Label          string
 	ExecutablePath string
 	StdOutFilePath string
+	StdErrFilePath string
 	Args           []string
+	Env            map[string]string
 }
 
 var (
@@ -106,12 +114,12 @@ func CheckPlist(config AgentConfig) error {
 
 // LoadPlist loads a launchd agents' plist file
 func LoadPlist(label string) error {
-	return runLaunchCtl("load", getPlistPath(label))
+	return runLaunchCtl("load", "-w", getPlistPath(label))
 }
 
 // UnloadPlist Unloads a launchd agent's service
 func UnloadPlist(label string) error {
-	return runLaunchCtl("unload", getPlistPath(label))
+	return runLaunchCtl("unload", "-w", getPlistPath(label))
 }
 
 // RemovePlist removes a launchd agent plist config file


Test patch:
diff --git a/pkg/crc/preflight/preflight_darwin_test.go b/pkg/crc/preflight/preflight_darwin_test.go
index 9563fc66e..e53920684 100644
--- a/pkg/crc/preflight/preflight_darwin_test.go
+++ b/pkg/crc/preflight/preflight_darwin_test.go
@@ -13,13 +13,13 @@ import (
 func TestCountConfigurationOptions(t *testing.T) {
 	cfg := config.New(config.NewEmptyInMemoryStorage())
 	RegisterSettings(cfg)
-	assert.Len(t, cfg.AllConfigs(), 12)
+	assert.Len(t, cfg.AllConfigs(), 14)
 }
 
 func TestCountPreflights(t *testing.T) {
-	assert.Len(t, getPreflightChecks(true, network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 17)
-	assert.Len(t, getPreflightChecks(true, network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 17)
+	assert.Len(t, getPreflightChecks(true, network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 19)
+	assert.Len(t, getPreflightChecks(true, network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 19)
 
-	assert.Len(t, getPreflightChecks(true, network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 16)
-	assert.Len(t, getPreflightChecks(true, network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 16)
+	assert.Len(t, getPreflightChecks(true, network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 18)
+	assert.Len(t, getPreflightChecks(true, network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 18)
 }
diff --git a/pkg/crc/preflight/preflight_linux_test.go b/pkg/crc/preflight/preflight_linux_test.go
index f2e95011e..7c312a910 100644
--- a/pkg/crc/preflight/preflight_linux_test.go
+++ b/pkg/crc/preflight/preflight_linux_test.go
@@ -70,11 +70,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -109,11 +109,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -147,11 +147,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -179,11 +179,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -218,11 +218,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -256,11 +256,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -288,11 +288,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -327,11 +327,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -365,11 +365,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -397,11 +397,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -437,11 +437,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
@@ -476,11 +476,11 @@ var checkListForDistros = []checkListForDistro{
 			{check: checkOldAdminHelperExecutableCached},
 			{check: checkSupportedCPUArch},
 			{configKeySuffix: "check-ram"},
+			{check: checkCrcSymlink},
 			{cleanup: removeCRCMachinesDir},
 			{cleanup: removeOldLogs},
 			{cleanup: cluster.ForgetPullSecret},
 			{cleanup: removeHostsFileEntry},
-			{check: checkCrcSymlink},
 			{check: checkVirtualizationEnabled},
 			{check: checkKvmEnabled},
 			{check: checkLibvirtInstalled},
diff --git a/pkg/crc/preflight/preflight_windows_test.go b/pkg/crc/preflight/preflight_windows_test.go
index b4c745aae..34413b368 100644
--- a/pkg/crc/preflight/preflight_windows_test.go
+++ b/pkg/crc/preflight/preflight_windows_test.go
@@ -13,13 +13,13 @@ import (
 func TestCountConfigurationOptions(t *testing.T) {
 	cfg := config.New(config.NewEmptyInMemoryStorage())
 	RegisterSettings(cfg)
-	assert.Len(t, cfg.AllConfigs(), 10)
+	assert.Len(t, cfg.AllConfigs(), 12)
 }
 
 func TestCountPreflights(t *testing.T) {
-	assert.Len(t, getPreflightChecks(false, network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 15)
-	assert.Len(t, getPreflightChecks(true, network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 15)
+	assert.Len(t, getPreflightChecks(false, network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 18)
+	assert.Len(t, getPreflightChecks(true, network.SystemNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 18)
 
-	assert.Len(t, getPreflightChecks(false, network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 16)
-	assert.Len(t, getPreflightChecks(true, network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 16)
+	assert.Len(t, getPreflightChecks(false, network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 17)
+	assert.Len(t, getPreflightChecks(true, network.UserNetworkingMode, constants.GetDefaultBundlePath(preset.OpenShift), preset.OpenShift), 17)
 }