Repository: code-ready/crc
Pull request #2234 (2021-04-16 20:01:49)

Fix 'crc podman-env' command
It enables the user to use rootless podman. 

This is very early stage and tbh, it doesn't work well.
With bundle 4.7.5, podman 2.2.1, a simple 'podman ps' hangs half of the time. It also freezes the VM (cannot ssh during the podman hang). 

With podman rootless, I have this error when it hangs:
```
$ systemctl --user status podman.service
● podman.service - Podman API Service
   Loaded: loaded (/usr/lib/systemd/user/podman.service; static; vendor preset: enabled)
   Active: activating (start) since Fri 2021-04-16 20:00:56 UTC; 735ms ago
     Docs: man:podman-system-service(1)
 Main PID: 3990 (podman)
   CGroup: /user.slice/user-1000.slice/user@1000.service/podman.service
           ├─3990 /usr/bin/podman --log-level=info system service
           └─4000 /usr/bin/podman --log-level=info system service

Apr 16 20:00:56 crc-xl2km-master-0 systemd[3830]: Starting Podman API Service...
Apr 16 20:00:56 crc-xl2km-master-0 podman[3990]: time="2021-04-16T20:00:56Z" level=info msg="/usr/bin/podman filtering at log level info"
Apr 16 20:00:56 crc-xl2km-master-0 podman[3990]: time="2021-04-16T20:00:56Z" level=warning msg="Error initializing configured OCI runtime kata: no valid executable found for OCI runtime kata: invalid a>
Apr 16 20:00:56 crc-xl2km-master-0 podman[3990]: time="2021-04-16T20:00:56Z" level=info msg="Setting parallel job count to 13"
Apr 16 20:00:56 crc-xl2km-master-0 podman[3990]: time="2021-04-16T20:00:56Z" level=info msg="/usr/bin/podman filtering at log level info"
Apr 16 20:00:56 crc-xl2km-master-0 podman[3990]: time="2021-04-16T20:00:56Z" level=warning msg="Error initializing configured OCI runtime kata: no valid executable found for OCI runtime kata: invalid a>
Apr 16 20:00:56 crc-xl2km-master-0 podman[3990]: time="2021-04-16T20:00:56Z" level=info msg="Setting parallel job count to 13"
Apr 16 20:00:56 crc-xl2km-master-0 podman[3990]: time="2021-04-16T20:00:56Z" level=info msg="using API endpoint: 'unix:/run/user/1000/podman/podman.sock'"
Apr 16 20:00:56 crc-xl2km-master-0 podman[3990]: time="2021-04-16T20:00:56Z" level=info msg="API server listening on \"/run/user/1000/podman/podman.sock\""
Apr 16 20:00:56 crc-xl2km-master-0 systemd[3830]: podman.service: Got notification message from PID 4000, but reception only permitted for main PID 3990
```

With podman root, I have this error when it hangs:
```
Apr 16 19:53:04 crc-xl2km-master-0 systemd[3830]: Failed to connect to API bus: Connection refused
```

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

This pull-request has been approved by: *<a href="https://github.com/code-ready/crc/pull/2234#" title="Author self-approved">guillaumerose</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:

- ~~[OWNERS](https://github.com/code-ready/crc/blob/master/OWNERS)~~ [guillaumerose]

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":[]} -->
guillaumerose: Success rate is much higher with https://gist.github.com/guillaumerose/596cd7d99cbe0ad03ca7b0c9a6b20376 🤔 
I don't understand why.. Less SSH connections ?
guillaumerose: I added a proxy in the middle. It deals with ssh for podman. It's far more reliable for root mode.
For rootless mode, it is still flaky: first call fail, then it "works".
openshift-ci[bot]: @guillaumerose: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e-crc | 1d60259ad7bc3809f28fdf48398f3f362599bbc5 | [link](https://prow.ci.openshift.org/view/gs/origin-ci-test/pr-logs/pull/code-ready_crc/2234/pull-ci-code-ready-crc-master-e2e-crc/1384131693014683648) | `/test e2e-crc`

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

<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 -->
cfergeau: > I added a proxy in the middle. It deals with ssh for podman. It's far more reliable for root mode.
> For rootless mode, it is still flaky: first call fail, then it "works".

Not so sure we should be adding workarounds for bugs which should be fixed in podman, or some place else, but not in crc.
cfergeau: > With podman rootless, I have this error when it hangs:
```
Apr 16 20:00:56 crc-xl2km-master-0 systemd[3830]: podman.service: Got notification message from PID 4000, but reception only permitted for main PID 3990
```

Could be a bug in podman socket activation, `systemctl status` shows
```
 Main PID: 3990 (podman)
   CGroup: /user.slice/user-1000.slice/user@1000.service/podman.service
           ├─3990 /usr/bin/podman --log-level=info system service
           └─4000 /usr/bin/podman --log-level=info system service
```

The PIDs match the error message, but I'm not sure it's intentional 2 podman binaries were spawned.
The corresponding unit file is
```
[Unit]
Description=Podman API Service
Requires=podman.socket
After=podman.socket
Documentation=man:podman-system-service(1)
StartLimitIntervalSec=0

[Service]
Type=notify
KillMode=process
Environment=LOGGING="--log-level=info"
ExecStart=/usr/bin/podman $LOGGING system service
```
guillaumerose: I kept only necessary commits. I tested it fine on the 3 platforms. 
It kind of works, it could be better. I see this PR as a first step before getting something really good when OpenShift 4.8 will ship also Podman 3.

Patch:
diff --git a/Makefile b/Makefile
index d6105dd18..526458a8c 100644
--- a/Makefile
+++ b/Makefile
@@ -124,10 +124,6 @@ test-rpmbuild: spec
 build_docs:
 	${CONTAINER_RUNTIME} run -v $(CURDIR)/docs:/docs:Z --rm $(DOCS_BUILD_CONTAINER) build_docs -b html5 -D /$(DOCS_BUILD_DIR) -o index.html $(DOCS_BUILD_TARGET)
 
-.PHONY: build_docs_pdf
-build_docs_pdf:
-	${CONTAINER_RUNTIME} run -v $(CURDIR)/docs:/docs:Z --rm $(DOCS_BUILD_CONTAINER) build_docs_pdf -D /$(DOCS_BUILD_DIR) -o doc.pdf $(DOCS_BUILD_TARGET)
-
 .PHONY: docs_serve
 docs_serve: build_docs
 	${CONTAINER_RUNTIME} run -it -v $(CURDIR)/docs:/docs:Z --rm -p 8088:8088/tcp $(DOCS_BUILD_CONTAINER) docs_serve 
@@ -214,19 +210,19 @@ gen_release_info:
 
 .PHONY: release
 release: LDFLAGS += $(RELEASE_VERSION_VARIABLES)
-release: cross-lint embed_bundle build_docs_pdf gen_release_info
+release: cross-lint embed_bundle gen_release_info
 	mkdir $(RELEASE_DIR)
 	
 	@mkdir -p $(BUILD_DIR)/crc-macos-$(CRC_VERSION)-amd64
-	@cp LICENSE $(DOCS_BUILD_DIR)/doc.pdf $(BUILD_DIR)/macos-amd64/crc $(BUILD_DIR)/crc-macos-$(CRC_VERSION)-amd64
+	@cp LICENSE $(BUILD_DIR)/macos-amd64/crc $(BUILD_DIR)/crc-macos-$(CRC_VERSION)-amd64
 	tar cJSf $(RELEASE_DIR)/crc-macos-amd64.tar.xz -C $(BUILD_DIR) crc-macos-$(CRC_VERSION)-amd64 --owner=0 --group=0
 
 	@mkdir -p $(BUILD_DIR)/crc-linux-$(CRC_VERSION)-amd64
-	@cp LICENSE $(DOCS_BUILD_DIR)/doc.pdf $(BUILD_DIR)/linux-amd64/crc $(BUILD_DIR)/crc-linux-$(CRC_VERSION)-amd64
+	@cp LICENSE $(BUILD_DIR)/linux-amd64/crc $(BUILD_DIR)/crc-linux-$(CRC_VERSION)-amd64
 	tar cJSf $(RELEASE_DIR)/crc-linux-amd64.tar.xz -C $(BUILD_DIR) crc-linux-$(CRC_VERSION)-amd64 --owner=0 --group=0
 	
 	@mkdir -p $(BUILD_DIR)/crc-windows-$(CRC_VERSION)-amd64
-	@cp LICENSE $(DOCS_BUILD_DIR)/doc.pdf $(BUILD_DIR)/windows-amd64/crc.exe $(BUILD_DIR)/crc-windows-$(CRC_VERSION)-amd64
+	@cp LICENSE $(BUILD_DIR)/windows-amd64/crc.exe $(BUILD_DIR)/crc-windows-$(CRC_VERSION)-amd64
 	cd $(BUILD_DIR) && zip -r $(CURDIR)/$(RELEASE_DIR)/crc-windows-amd64.zip crc-windows-$(CRC_VERSION)-amd64
 
 	@mv $(RELEASE_INFO) $(RELEASE_DIR)/$(RELEASE_INFO)
diff --git a/cmd/crc/cmd/ip.go b/cmd/crc/cmd/ip.go
index 477040f60..315652c83 100644
--- a/cmd/crc/cmd/ip.go
+++ b/cmd/crc/cmd/ip.go
@@ -25,10 +25,10 @@ func runIP(arguments []string) error {
 		return err
 	}
 
-	ip, err := client.IP()
+	connectionDetails, err := client.ConnectionDetails()
 	if err != nil {
 		return err
 	}
-	fmt.Println(ip)
+	fmt.Println(connectionDetails.IP)
 	return nil
 }
diff --git a/cmd/crc/cmd/podman_env.go b/cmd/crc/cmd/podman_env.go
index 06ca12138..bb7d3ebdd 100644
--- a/cmd/crc/cmd/podman_env.go
+++ b/cmd/crc/cmd/podman_env.go
@@ -1,7 +1,6 @@
 package cmd
 
 import (
-	"errors"
 	"fmt"
 
 	"github.com/code-ready/crc/pkg/crc/constants"
@@ -14,12 +13,11 @@ var podmanEnvCmd = &cobra.Command{
 	Short: "Setup podman environment",
 	Long:  `Setup environment for 'podman' executable to access podman on CRC VM`,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		// See issue #961; Currently does not work on Windows in combination with the CRC vm.
-		return errors.New("currently not supported")
+		return runPodmanEnv()
 	},
 }
 
-func RunPodmanEnv(args []string) error {
+func runPodmanEnv() error {
 	userShell, err := shell.GetShell(forceShell)
 	if err != nil {
 		return fmt.Errorf("Error running the podman-env command: %s", err.Error())
@@ -30,16 +28,18 @@ func RunPodmanEnv(args []string) error {
 		return err
 	}
 
-	ip, err := client.IP()
+	connectionDetails, err := client.ConnectionDetails()
 	if err != nil {
 		return err
 	}
 
-	fmt.Println(shell.GetPathEnvString(userShell, constants.CrcBinDir))
-	fmt.Println(shell.GetEnvString(userShell, "PODMAN_USER", constants.DefaultSSHUser))
-	fmt.Println(shell.GetEnvString(userShell, "PODMAN_HOST", ip))
-	fmt.Println(shell.GetEnvString(userShell, "PODMAN_IDENTITY_FILE", constants.GetPrivateKeyPath()))
-	fmt.Println(shell.GetEnvString(userShell, "PODMAN_IGNORE_HOSTS", "1"))
+	fmt.Println(shell.GetPathEnvString(userShell, constants.CrcOcBinDir))
+	fmt.Println(shell.GetEnvString(userShell, "CONTAINER_SSHKEY", connectionDetails.SSHKeys[0]))
+	fmt.Println(shell.GetEnvString(userShell, "CONTAINER_HOST",
+		fmt.Sprintf("ssh://%s@%s:%d/run/user/1000/podman/podman.sock",
+			connectionDetails.SSHUsername,
+			connectionDetails.IP,
+			connectionDetails.SSHPort)))
 	fmt.Println(shell.GenerateUsageHintWithComment(userShell, "crc podman-env"))
 	return nil
 }
diff --git a/images/docs-builder/Dockerfile b/images/docs-builder/Dockerfile
index e55bd0be5..33b3e12fa 100644
--- a/images/docs-builder/Dockerfile
+++ b/images/docs-builder/Dockerfile
@@ -7,7 +7,7 @@ RUN yum update -y && \
     yum module install nodejs:14 -y && \
     yum clean all && rm -rf /var/cache/yum/*
 
-RUN gem install asciidoctor asciidoctor-pdf --pre && \
+RUN gem install asciidoctor && \
     npm install -g asciidoc-link-check
 
 COPY entrypoint.sh /sbin/entrypoint.sh
diff --git a/images/docs-builder/entrypoint.sh b/images/docs-builder/entrypoint.sh
index b84a7a38d..a100c266c 100644
--- a/images/docs-builder/entrypoint.sh
+++ b/images/docs-builder/entrypoint.sh
@@ -2,7 +2,7 @@
 set -e
 
 if [ $# -lt 1 ]; then
-	echo "You need to provide an argument [build_docs, build_docs_pdf, docs_check_links, docs_serve]"
+	echo "You need to provide an argument [build_docs, docs_check_links, docs_serve]"
 fi
 
 case $1 in
@@ -11,11 +11,6 @@ case $1 in
 		shift 
 		asciidoctor $@
 		;;
-	build_docs_pdf)
-		echo "Generating pdf from docs source"
-		shift 
-		asciidoctor-pdf $@
-		;;
 	docs_check_links)
 		echo "Checking if all links are alive in docs source"
 		find . -name \*.adoc | xargs -n1 asciidoc-link-check -c /links_ignorelist.json -q
@@ -25,7 +20,7 @@ case $1 in
 		python3 -m http.server 8088
 		;;
 	*)
-		echo "Need to provide one of: build_docs, build_docs_pdf, docs_check_links, docs_serve"
+		echo "Need to provide one of: build_docs, docs_check_links, docs_serve"
 		exit 1
 		;;
 esac
diff --git a/packaging/package.sh b/packaging/package.sh
index 065d2dfdd..ac5296045 100755
--- a/packaging/package.sh
+++ b/packaging/package.sh
@@ -31,6 +31,8 @@ sign "${BASEDIR}/root/Applications/CodeReady Containers.app"
 
 codesign --verify --verbose "${binDir}/hyperkit"
 
+sudo chmod +sx "${binDir}/hyperkit" "${binDir}/admin-helper-darwin" "${binDir}/crc-driver-hyperkit"
+
 pkgbuild --identifier com.redhat.crc --version ${version} \
   --scripts "${BASEDIR}/darwin/scripts" \
   --root "${BASEDIR}/root" \
diff --git a/pkg/crc/adminhelper/hosts.go b/pkg/crc/adminhelper/hosts.go
index a88d9f177..1b338a881 100644
--- a/pkg/crc/adminhelper/hosts.go
+++ b/pkg/crc/adminhelper/hosts.go
@@ -8,7 +8,7 @@ import (
 )
 
 var (
-	adminHelperPath = filepath.Join(constants.CrcBinDir, constants.AdminHelperExecutableName)
+	adminHelperPath = filepath.Join(constants.BinDir(), constants.AdminHelperExecutableName)
 )
 
 // UpdateHostsFile updates the host's /etc/hosts file with Instance IP.
diff --git a/pkg/crc/constants/constants.go b/pkg/crc/constants/constants.go
index 29b377659..01c8e8479 100644
--- a/pkg/crc/constants/constants.go
+++ b/pkg/crc/constants/constants.go
@@ -114,6 +114,13 @@ func defaultBundlePath() string {
 	return filepath.Join(MachineCacheDir, GetDefaultBundle())
 }
 
+func BinDir() string {
+	if runtime.GOOS == "darwin" && version.IsMacosInstallPathSet() {
+		return version.GetMacosInstallPath()
+	}
+	return CrcBinDir
+}
+
 // GetHomeDir returns the home directory for the current user
 func GetHomeDir() string {
 	if runtime.GOOS == "windows" {
diff --git a/pkg/crc/machine/bundle/metadata.go b/pkg/crc/machine/bundle/metadata.go
index 0a05e0f1e..73bcef7b8 100644
--- a/pkg/crc/machine/bundle/metadata.go
+++ b/pkg/crc/machine/bundle/metadata.go
@@ -67,9 +67,16 @@ type DiskImage struct {
 	Format string `json:"format"`
 }
 
+type FileType string
+
+const (
+	OcExecutable     FileType = "oc-executable"
+	PodmanExecutable FileType = "podman-executable"
+)
+
 type FileListItem struct {
 	File
-	Type string `json:"type"`
+	Type FileType `json:"type"`
 }
 
 type DriverInfo struct {
@@ -102,7 +109,17 @@ func (bundle *CrcBundleInfo) GetKubeConfigPath() string {
 
 func (bundle *CrcBundleInfo) GetOcPath() string {
 	for _, file := range bundle.Storage.Files {
-		if file.Type == "oc-executable" {
+		if file.Type == OcExecutable {
+			return bundle.resolvePath(file.Name)
+		}
+	}
+
+	return ""
+}
+
+func (bundle *CrcBundleInfo) GetPodmanPath() string {
+	for _, file := range bundle.Storage.Files {
+		if file.Type == PodmanExecutable {
 			return bundle.resolvePath(file.Name)
 		}
 	}
diff --git a/pkg/crc/machine/bundle/repository.go b/pkg/crc/machine/bundle/repository.go
index db688f000..532d7ffb1 100644
--- a/pkg/crc/machine/bundle/repository.go
+++ b/pkg/crc/machine/bundle/repository.go
@@ -84,6 +84,9 @@ func (repo *Repository) Use(bundleName string) (*CrcBundleInfo, error) {
 	if err := bundleInfo.createSymlinkOrCopyOpenShiftClient(repo.OcBinDir); err != nil {
 		return nil, err
 	}
+	if err := bundleInfo.createSymlinkOrCopyPodmanClient(repo.OcBinDir); err != nil {
+		return nil, err
+	}
 	return bundleInfo, nil
 }
 
@@ -117,6 +120,23 @@ func (bundle *CrcBundleInfo) createSymlinkOrCopyOpenShiftClient(ocBinDir string)
 	return os.Symlink(ocInBundle, ocInBinDir)
 }
 
+func (bundle *CrcBundleInfo) createSymlinkOrCopyPodmanClient(ocBinDir string) error {
+	podmanInBundle := bundle.GetPodmanPath()
+	if podmanInBundle == "" {
+		return nil
+	}
+	podmanInBinDir := filepath.Join(ocBinDir, filepath.Base(podmanInBundle))
+
+	if err := os.MkdirAll(ocBinDir, 0750); err != nil {
+		return err
+	}
+	_ = os.Remove(podmanInBinDir)
+	if runtime.GOOS == "windows" {
+		return crcos.CopyFileContents(podmanInBundle, podmanInBinDir, 0750)
+	}
+	return os.Symlink(podmanInBundle, podmanInBinDir)
+}
+
 func (repo *Repository) Extract(path string) error {
 	bundleName := filepath.Base(path)
 
diff --git a/pkg/crc/machine/client.go b/pkg/crc/machine/client.go
index 58101cd2e..a9c07a81c 100644
--- a/pkg/crc/machine/client.go
+++ b/pkg/crc/machine/client.go
@@ -12,11 +12,11 @@ import (
 
 type Client interface {
 	GetName() string
+	GetConsoleURL() (*types.ConsoleResult, error)
+	ConnectionDetails() (*types.ConnectionDetails, error)
 
 	Delete() error
 	Exists() (bool, error)
-	GetConsoleURL() (*types.ConsoleResult, error)
-	IP() (string, error)
 	PowerOff() error
 	Start(ctx context.Context, startConfig types.StartConfig) (*types.StartResult, error)
 	Status() (*types.ClusterStatusResult, error)
diff --git a/pkg/crc/machine/driver_darwin.go b/pkg/crc/machine/driver_darwin.go
index 2c1387a6d..a35f6f4c8 100644
--- a/pkg/crc/machine/driver_darwin.go
+++ b/pkg/crc/machine/driver_darwin.go
@@ -17,7 +17,7 @@ func newHost(api libmachine.API, machineConfig config.MachineConfig) (*host.Host
 	if err != nil {
 		return nil, errors.New("Failed to marshal driver options")
 	}
-	return api.NewHost("hyperkit", constants.CrcBinDir, json)
+	return api.NewHost("hyperkit", constants.BinDir(), json)
 }
 
 func loadDriverConfig(host *host.Host) (*machineHyperkit.Driver, error) {
diff --git a/pkg/crc/machine/fakemachine/client.go b/pkg/crc/machine/fakemachine/client.go
index 0e9ecb9ec..fb53392e1 100644
--- a/pkg/crc/machine/fakemachine/client.go
+++ b/pkg/crc/machine/fakemachine/client.go
@@ -57,8 +57,8 @@ func (c *Client) GetProxyConfig(machineName string) (*network.ProxyConfig, error
 	return nil, errors.New("not implemented")
 }
 
-func (c *Client) IP() (string, error) {
-	return "", errors.New("not implemented")
+func (c *Client) ConnectionDetails() (*types.ConnectionDetails, error) {
+	return nil, errors.New("not implemented")
 }
 
 func (c *Client) PowerOff() error {
diff --git a/pkg/crc/machine/hyperkit/driver_darwin.go b/pkg/crc/machine/hyperkit/driver_darwin.go
index f48cde9e5..4419a51f1 100644
--- a/pkg/crc/machine/hyperkit/driver_darwin.go
+++ b/pkg/crc/machine/hyperkit/driver_darwin.go
@@ -18,7 +18,7 @@ func CreateHost(machineConfig config.MachineConfig) *hyperkit.Driver {
 	hyperkitDriver.Cmdline = machineConfig.KernelCmdLine
 	hyperkitDriver.VmlinuzPath = machineConfig.Kernel
 	hyperkitDriver.InitrdPath = machineConfig.Initramfs
-	hyperkitDriver.HyperKitPath = filepath.Join(constants.CrcBinDir, HyperKitCommand)
+	hyperkitDriver.HyperKitPath = filepath.Join(constants.BinDir(), HyperKitCommand)
 
 	hyperkitDriver.VMNet = machineConfig.NetworkMode == network.DefaultMode
 
diff --git a/pkg/crc/machine/ip.go b/pkg/crc/machine/ip.go
index 9cff84da3..9e847b03c 100644
--- a/pkg/crc/machine/ip.go
+++ b/pkg/crc/machine/ip.go
@@ -1,18 +1,32 @@
 package machine
 
-import "github.com/pkg/errors"
+import (
+	"github.com/code-ready/crc/pkg/crc/constants"
+	"github.com/code-ready/crc/pkg/crc/machine/types"
+	"github.com/pkg/errors"
+)
 
-func (client *client) IP() (string, error) {
+func (client *client) ConnectionDetails() (*types.ConnectionDetails, error) {
 	libMachineAPIClient, cleanup := createLibMachineClient()
 	defer cleanup()
 	host, err := libMachineAPIClient.Load(client.name)
+	if err != nil {
+		return nil, errors.Wrap(err, "Cannot load machine")
+	}
 
+	bundle, err := getBundleMetadataFromDriver(host.Driver)
 	if err != nil {
-		return "", errors.Wrap(err, "Cannot load machine")
+		return nil, errors.Wrap(err, "Error loading bundle metadata")
 	}
+
 	ip, err := getIP(host, client.useVSock())
 	if err != nil {
-		return "", errors.Wrap(err, "Cannot get IP")
+		return nil, errors.Wrap(err, "Cannot get IP")
 	}
-	return ip, nil
+	return &types.ConnectionDetails{
+		IP:          ip,
+		SSHPort:     getSSHPort(client.useVSock()),
+		SSHUsername: constants.DefaultSSHUser,
+		SSHKeys:     []string{constants.GetPrivateKeyPath(), constants.GetRsaPrivateKeyPath(), bundle.GetSSHKeyPath()},
+	}, nil
 }
diff --git a/pkg/crc/machine/start.go b/pkg/crc/machine/start.go
index e80e884bf..54004ef97 100644
--- a/pkg/crc/machine/start.go
+++ b/pkg/crc/machine/start.go
@@ -350,7 +350,6 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
 		if !client.useVSock() {
 			return nil, errors.Wrapf(err, "Failed internal DNS query: %s", queryOutput)
 		}
-		logging.Warn(fmt.Sprintf("Failed internal DNS query: %s: %v", queryOutput, err))
 	}
 	logging.Info("Check internal and public DNS query ...")
 
diff --git a/pkg/crc/machine/sync.go b/pkg/crc/machine/sync.go
index 5099e5781..4fe952967 100644
--- a/pkg/crc/machine/sync.go
+++ b/pkg/crc/machine/sync.go
@@ -154,8 +154,8 @@ func (s *Synchronized) GetConsoleURL() (*types.ConsoleResult, error) {
 	return s.underlying.GetConsoleURL()
 }
 
-func (s *Synchronized) IP() (string, error) {
-	return s.underlying.IP()
+func (s *Synchronized) ConnectionDetails() (*types.ConnectionDetails, error) {
+	return s.underlying.ConnectionDetails()
 }
 
 func (s *Synchronized) PowerOff() error {
diff --git a/pkg/crc/machine/types/types.go b/pkg/crc/machine/types/types.go
index 6bb212e75..87e8feac5 100644
--- a/pkg/crc/machine/types/types.go
+++ b/pkg/crc/machine/types/types.go
@@ -56,3 +56,10 @@ type ConsoleResult struct {
 	ClusterConfig ClusterConfig
 	State         state.State
 }
+
+type ConnectionDetails struct {
+	IP          string
+	SSHPort     int
+	SSHUsername string
+	SSHKeys     []string
+}
diff --git a/pkg/crc/preflight/preflight_checks_common.go b/pkg/crc/preflight/preflight_checks_common.go
index f9608ff78..e0e10cb61 100644
--- a/pkg/crc/preflight/preflight_checks_common.go
+++ b/pkg/crc/preflight/preflight_checks_common.go
@@ -12,6 +12,7 @@ import (
 	"github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/code-ready/crc/pkg/crc/machine/bundle"
 	"github.com/code-ready/crc/pkg/crc/validation"
+	"github.com/code-ready/crc/pkg/crc/version"
 	"github.com/code-ready/crc/pkg/embed"
 	crcos "github.com/code-ready/crc/pkg/os"
 	"github.com/docker/go-units"
@@ -140,6 +141,10 @@ func fixPodmanExecutableCached() error {
 
 // Check if helper executable is cached or not
 func checkAdminHelperExecutableCached() error {
+	if version.IsMacosInstallPathSet() {
+		return nil
+	}
+
 	helper := cache.NewAdminHelperCache()
 	if !helper.IsCached() {
 		return errors.New("admin-helper executable is not cached")
@@ -152,6 +157,10 @@ func checkAdminHelperExecutableCached() error {
 }
 
 func fixAdminHelperExecutableCached() error {
+	if version.IsMacosInstallPathSet() {
+		return nil
+	}
+
 	helper := cache.NewAdminHelperCache()
 	if err := helper.EnsureIsCached(); err != nil {
 		return errors.Wrap(err, "Unable to download admin-helper executable")
diff --git a/pkg/crc/preflight/preflight_checks_darwin.go b/pkg/crc/preflight/preflight_checks_darwin.go
index f7f2e0cd7..8f01b2410 100644
--- a/pkg/crc/preflight/preflight_checks_darwin.go
+++ b/pkg/crc/preflight/preflight_checks_darwin.go
@@ -12,6 +12,7 @@ import (
 	"github.com/code-ready/crc/pkg/crc/constants"
 	"github.com/code-ready/crc/pkg/crc/logging"
 	"github.com/code-ready/crc/pkg/crc/network"
+	"github.com/code-ready/crc/pkg/crc/version"
 	crcos "github.com/code-ready/crc/pkg/os"
 	"golang.org/x/sys/unix"
 )
@@ -24,6 +25,10 @@ const (
 
 func checkHyperKitInstalled(networkMode network.Mode) func() error {
 	return func() error {
+		if version.IsMacosInstallPathSet() {
+			return nil
+		}
+
 		h := cache.NewHyperKitCache()
 		if !h.IsCached() {
 			return fmt.Errorf("%s executable is not cached", h.GetExecutableName())
@@ -45,6 +50,10 @@ func checkHyperKitInstalled(networkMode network.Mode) func() error {
 
 func fixHyperKitInstallation(networkMode network.Mode) func() error {
 	return func() error {
+		if version.IsMacosInstallPathSet() {
+			return nil
+		}
+
 		h := cache.NewHyperKitCache()
 
 		logging.Debugf("Installing %s", h.GetExecutableName())
@@ -61,6 +70,10 @@ func fixHyperKitInstallation(networkMode network.Mode) func() error {
 
 func checkMachineDriverHyperKitInstalled(networkMode network.Mode) func() error {
 	return func() error {
+		if version.IsMacosInstallPathSet() {
+			return nil
+		}
+
 		hyperkitDriver := cache.NewMachineDriverHyperKitCache()
 
 		logging.Debugf("Checking if %s is installed", hyperkitDriver.GetExecutableName())
@@ -80,6 +93,10 @@ func checkMachineDriverHyperKitInstalled(networkMode network.Mode) func() error
 
 func fixMachineDriverHyperKitInstalled(networkMode network.Mode) func() error {
 	return func() error {
+		if version.IsMacosInstallPathSet() {
+			return nil
+		}
+
 		hyperkitDriver := cache.NewMachineDriverHyperKitCache()
 
 		logging.Debugf("Installing %s", hyperkitDriver.GetExecutableName())
@@ -192,7 +209,7 @@ func stopCRCHyperkitProcess() error {
 	if err != nil {
 		return fmt.Errorf("Could not find 'pgrep'. %w", err)
 	}
-	if _, _, err := crcos.RunWithDefaultLocale(pgrepPath, "-f", filepath.Join(constants.CrcBinDir, "hyperkit")); err != nil {
+	if _, _, err := crcos.RunWithDefaultLocale(pgrepPath, "-f", filepath.Join(constants.BinDir(), "hyperkit")); err != nil {
 		var exitErr *exec.ExitError
 		if errors.As(err, &exitErr) {
 			/* 1: no processes matched */
@@ -209,7 +226,7 @@ func stopCRCHyperkitProcess() error {
 	if err != nil {
 		return fmt.Errorf("Could not find 'pkill'. %w", err)
 	}
-	if _, _, err := crcos.RunWithDefaultLocale(pkillPath, "-SIGKILL", "-f", filepath.Join(constants.CrcBinDir, "hyperkit")); err != nil {
+	if _, _, err := crcos.RunWithDefaultLocale(pkillPath, "-SIGKILL", "-f", filepath.Join(constants.BinDir(), "hyperkit")); err != nil {
 		return fmt.Errorf("Failed to kill 'hyperkit' process. %w", err)
 	}
 	return nil


Test patch:
diff --git a/pkg/crc/machine/sync_test.go b/pkg/crc/machine/sync_test.go
index 7214a78d6..e29e0e9e8 100644
--- a/pkg/crc/machine/sync_test.go
+++ b/pkg/crc/machine/sync_test.go
@@ -135,8 +135,8 @@ func (m *waitingMachine) GetConsoleURL() (*types.ConsoleResult, error) {
 	return nil, errors.New("not implemented")
 }
 
-func (m *waitingMachine) IP() (string, error) {
-	return "", errors.New("not implemented")
+func (m *waitingMachine) ConnectionDetails() (*types.ConnectionDetails, error) {
+	return nil, errors.New("not implemented")
 }
 
 func (m *waitingMachine) PowerOff() error {
diff --git a/test/e2e/crcsuite/collect.go b/test/e2e/crcsuite/collect.go
index 5822abcde..d78e47253 100644
--- a/test/e2e/crcsuite/collect.go
+++ b/test/e2e/crcsuite/collect.go
@@ -177,12 +177,7 @@ type VMCommandCollector struct {
 }
 
 func (collector *VMCommandCollector) Collect(w Writer) error {
-	client := machine.NewClient(constants.DefaultName, true, crcConfig.New(crcConfig.NewEmptyInMemoryStorage()))
-	ip, err := client.IP()
-	if err != nil {
-		return err
-	}
-	ssh, err := ssh.NewClient(constants.DefaultSSHUser, ip, 22, constants.GetPrivateKeyPath())
+	ssh, err := sshClient()
 	if err != nil {
 		return err
 	}
@@ -198,12 +193,7 @@ type ContainerLogCollector struct {
 }
 
 func (collector *ContainerLogCollector) Collect(w Writer) error {
-	client := machine.NewClient(constants.DefaultName, true, crcConfig.New(crcConfig.NewEmptyInMemoryStorage()))
-	ip, err := client.IP()
-	if err != nil {
-		return err
-	}
-	ssh, err := ssh.NewClient(constants.DefaultSSHUser, ip, 22, constants.GetPrivateKeyPath())
+	ssh, err := sshClient()
 	if err != nil {
 		return err
 	}
@@ -234,6 +224,15 @@ func (collector *ContainerLogCollector) Collect(w Writer) error {
 	return nil
 }
 
+func sshClient() (ssh.Client, error) {
+	client := machine.NewClient(constants.DefaultName, true, crcConfig.New(crcConfig.NewEmptyInMemoryStorage()))
+	connectionDetails, err := client.ConnectionDetails()
+	if err != nil {
+		return nil, err
+	}
+	return ssh.NewClient(connectionDetails.SSHUsername, connectionDetails.IP, connectionDetails.SSHPort, connectionDetails.SSHKeys...)
+}
+
 func command(command, target string) *CommandCollector {
 	return &CommandCollector{
 		Command: command,
diff --git a/test/integration/utilities_test.go b/test/integration/utilities_test.go
index d40972e97..0233111f1 100644
--- a/test/integration/utilities_test.go
+++ b/test/integration/utilities_test.go
@@ -136,12 +136,11 @@ func RunCRCExpectFail(args ...string) (string, error) {
 // Send command to CRC VM via SSH
 func SendCommandToVM(cmd string) (string, error) {
 	client := machine.NewClient(constants.DefaultName, false, crcConfig.New(crcConfig.NewEmptyInMemoryStorage()))
-	ip, err := client.IP()
+	connectionDetails, err := client.ConnectionDetails()
 	if err != nil {
 		return "", err
 	}
-
-	ssh, err := ssh.NewClient(constants.DefaultSSHUser, ip, 22, constants.GetPrivateKeyPath())
+	ssh, err := ssh.NewClient(connectionDetails.SSHUsername, connectionDetails.IP, connectionDetails.SSHPort, connectionDetails.SSHKeys...)
 	if err != nil {
 		return "", err
 	}