Skip to content

Commit b4cfc0e

Browse files
committed
add CIFS/SMB based file sharing for windows
it allows users to mount the host's home folder at /mnt/c/users/$username directory in the crc vm to determine if folder sharing is supported/enabled it checks that a smb share named 'crc-dir0' exists which should've been created during msi installation since CIFS/SMB is a network file system and needs a username and password for getting access two new fields 'SharedDirUsername' and 'SharedDirPassword' is added to the MachineConfig and StartConfig structs
1 parent c502056 commit b4cfc0e

12 files changed

Lines changed: 136 additions & 23 deletions

File tree

pkg/crc/machine/config/config.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ type MachineConfig struct {
77
BundleName string
88

99
// Virtual machine configuration
10-
Name string
11-
Memory int
12-
CPUs int
13-
DiskSize int
14-
ImageSourcePath string
15-
ImageFormat string
16-
SSHKeyPath string
17-
KubeConfig string
18-
SharedDirs []string
10+
Name string
11+
Memory int
12+
CPUs int
13+
DiskSize int
14+
ImageSourcePath string
15+
ImageFormat string
16+
SSHKeyPath string
17+
KubeConfig string
18+
SharedDirs []string
19+
SharedDirPassword string
20+
SharedDirUsername string
1921

2022
// macOS specific configuration
2123
KernelCmdLine string

pkg/crc/machine/driver.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,19 @@ func setDiskSize(host *host.Host, diskSizeGiB int) error {
5757

5858
return updateDriverValue(host, diskSizeSetter)
5959
}
60+
61+
func setSharedDirPassword(host *host.Host, password string) error {
62+
driver, err := loadDriverConfig(host)
63+
if err != nil {
64+
return err
65+
}
66+
67+
if len(driver.SharedDirs) == 0 {
68+
return nil
69+
}
70+
71+
for i := range driver.SharedDirs {
72+
driver.SharedDirs[i].Password = password
73+
}
74+
return updateDriverStruct(host, driver)
75+
}

pkg/crc/machine/driver_darwin.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
machineVf "github.com/code-ready/crc/pkg/drivers/vfkit"
1212
"github.com/code-ready/crc/pkg/libmachine"
1313
"github.com/code-ready/crc/pkg/libmachine/host"
14+
"github.com/code-ready/machine/libmachine/drivers"
1415
)
1516

1617
func newHost(api libmachine.API, machineConfig config.MachineConfig) (*host.Host, error) {
@@ -64,3 +65,7 @@ func updateKernelArgs(vm *virtualMachine) error {
6465
}
6566
return vm.api.Save(vm.Host)
6667
}
68+
69+
func updateDriverStruct(host *host.Host, driver *machineVf.Driver) error {
70+
return drivers.ErrNotImplemented
71+
}

pkg/crc/machine/driver_linux.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/code-ready/crc/pkg/libmachine"
1111
"github.com/code-ready/crc/pkg/libmachine/host"
1212
machineLibvirt "github.com/code-ready/machine/drivers/libvirt"
13+
"github.com/code-ready/machine/libmachine/drivers"
1314
)
1415

1516
func newHost(api libmachine.API, machineConfig config.MachineConfig) (*host.Host, error) {
@@ -47,3 +48,7 @@ func (r *RPCServerDriver) SetConfigRaw(data []byte, _ *struct{}) error {
4748
return json.Unmarshal(data, &r.ActualDriver)
4849
}
4950
*/
51+
52+
func updateDriverStruct(host *host.Host, driver *machineLibvirt.Driver) error {
53+
return drivers.ErrNotImplemented
54+
}

pkg/crc/machine/driver_windows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,8 @@ func updateDriverConfig(host *host.Host, driver *machineHyperv.Driver) error {
3737
func updateKernelArgs(vm *virtualMachine) error {
3838
return nil
3939
}
40+
41+
func updateDriverStruct(host *host.Host, driver *machineHyperv.Driver) error {
42+
host.Driver = driver
43+
return nil
44+
}

pkg/crc/machine/hyperv/driver_windows.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package hyperv
22

33
import (
4+
"path/filepath"
5+
"strings"
6+
47
"github.com/code-ready/crc/pkg/crc/constants"
58
"github.com/code-ready/crc/pkg/crc/machine/config"
69
"github.com/code-ready/crc/pkg/crc/network"
710
"github.com/code-ready/crc/pkg/drivers/hyperv"
811
winnet "github.com/code-ready/crc/pkg/os/windows/network"
12+
"github.com/code-ready/machine/libmachine/drivers"
913
)
1014

1115
func CreateHost(machineConfig config.MachineConfig) *hyperv.Driver {
@@ -23,5 +27,35 @@ func CreateHost(machineConfig config.MachineConfig) *hyperv.Driver {
2327
hypervDriver.VirtualSwitch = switchName
2428
}
2529

30+
hypervDriver.SharedDirs = configureShareDirs(machineConfig)
2631
return hypervDriver
2732
}
33+
34+
// converts a path like c:\users\crc to /mnt/c/users/crc
35+
func convertToUnixPath(path string) string {
36+
/* podman internally converts windows style paths like C:\Users\crc to
37+
* /mnt/c/Users/crc so it expects the shared folder to be mounted under
38+
* '/mnt' instead of '/' like in the case of macOS and linux
39+
* see: https://github.com/containers/podman/blob/468aa6478c73e4acd8708ce8bb0bb5a056f329c2/pkg/specgen/winpath.go#L24-L59
40+
*/
41+
path = filepath.ToSlash(path)
42+
if len(path) > 1 && path[1] == ':' {
43+
return ("/mnt/" + strings.ToLower(path[0:1]) + path[2:])
44+
}
45+
return path
46+
}
47+
48+
func configureShareDirs(machineConfig config.MachineConfig) []drivers.SharedDir {
49+
var sharedDirs []drivers.SharedDir
50+
for _, dir := range machineConfig.SharedDirs {
51+
sharedDir := drivers.SharedDir{
52+
Source: dir,
53+
Target: convertToUnixPath(dir),
54+
Tag: "crc-dir0", // smb share 'crc-dir0' is created in the msi
55+
Type: "cifs",
56+
Username: machineConfig.SharedDirUsername,
57+
}
58+
sharedDirs = append(sharedDirs, sharedDir)
59+
}
60+
return sharedDirs
61+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package hyperv
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestConvertToUnixPath(t *testing.T) {
10+
assert.Equal(t, "/mnt/c/Users/crc", convertToUnixPath("C:\\Users\\crc"))
11+
assert.Equal(t, "/mnt/d/Users/crc", convertToUnixPath("d:\\Users\\crc"))
12+
}

pkg/crc/machine/start.go

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ func (client *client) updateVMConfig(startConfig types.StartConfig, vm *virtualM
9999
}
100100
}
101101

102+
// we want to set the shared dir password on-the-fly to be used
103+
// we do not want this value to be persisted to disk
104+
if startConfig.SharedDirPassword != "" {
105+
if err := setSharedDirPassword(vm.Host, startConfig.SharedDirPassword); err != nil {
106+
return fmt.Errorf("Failed to set shared dir password: %w", err)
107+
}
108+
}
109+
102110
return nil
103111
}
104112

@@ -178,6 +186,11 @@ func configureSharedDirs(vm *virtualMachine, sshRunner *crcssh.Runner) error {
178186
if _, _, err := sshRunner.RunPrivileged(fmt.Sprintf("Mounting %s", mount.Target), "mount", "-o", "context=\"system_u:object_r:container_file_t:s0\"", "-t", mount.Type, mount.Tag, mount.Target); err != nil {
179187
return err
180188
}
189+
case "cifs":
190+
smbUncPath := fmt.Sprintf("//%s/%s", hostVirtualIP, mount.Tag)
191+
if _, _, err := sshRunner.RunPrivate("sudo", "mount", "-o", fmt.Sprintf("rw,uid=core,gid=core,username='%s',password='%s'", mount.Username, mount.Password), "-t", mount.Type, smbUncPath, mount.Target); err != nil {
192+
return fmt.Errorf("Failed to mount CIFS/SMB share '%s' please make sure configured password is correct: %w", mount.Tag, err)
193+
}
181194
default:
182195
return fmt.Errorf("Unknown Shared dir type requested: %s", mount.Type)
183196
}
@@ -233,19 +246,21 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
233246
}
234247

235248
machineConfig := config.MachineConfig{
236-
Name: client.name,
237-
BundleName: bundleName,
238-
CPUs: startConfig.CPUs,
239-
Memory: startConfig.Memory,
240-
DiskSize: startConfig.DiskSize,
241-
NetworkMode: client.networkMode(),
242-
ImageSourcePath: crcBundleMetadata.GetDiskImagePath(),
243-
ImageFormat: crcBundleMetadata.GetDiskImageFormat(),
244-
SSHKeyPath: crcBundleMetadata.GetSSHKeyPath(),
245-
KernelCmdLine: crcBundleMetadata.GetKernelCommandLine(),
246-
Initramfs: crcBundleMetadata.GetInitramfsPath(),
247-
Kernel: crcBundleMetadata.GetKernelPath(),
248-
SharedDirs: sharedDirs,
249+
Name: client.name,
250+
BundleName: bundleName,
251+
CPUs: startConfig.CPUs,
252+
Memory: startConfig.Memory,
253+
DiskSize: startConfig.DiskSize,
254+
NetworkMode: client.networkMode(),
255+
ImageSourcePath: crcBundleMetadata.GetDiskImagePath(),
256+
ImageFormat: crcBundleMetadata.GetDiskImageFormat(),
257+
SSHKeyPath: crcBundleMetadata.GetSSHKeyPath(),
258+
KernelCmdLine: crcBundleMetadata.GetKernelCommandLine(),
259+
Initramfs: crcBundleMetadata.GetInitramfsPath(),
260+
Kernel: crcBundleMetadata.GetKernelPath(),
261+
SharedDirs: sharedDirs,
262+
SharedDirPassword: startConfig.SharedDirPassword,
263+
SharedDirUsername: startConfig.SharedDirUsername,
249264
}
250265
if crcBundleMetadata.IsOpenShift() {
251266
machineConfig.KubeConfig = crcBundleMetadata.GetKubeConfigPath()

pkg/crc/machine/types/types.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ type StartConfig struct {
3030
Preset crcpreset.Preset
3131

3232
// Shared dirs
33-
EnableSharedDirs bool
33+
EnableSharedDirs bool
34+
SharedDirPassword string
35+
SharedDirUsername string
3436

3537
// Ports to access openshift routes
3638
IngressHTTPPort uint

pkg/crc/machine/vsock.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func listOpenPorts(daemonClient *daemonclient.Client) ([]types.ExposeRequest, er
7676

7777
const (
7878
virtualMachineIP = "192.168.127.2"
79+
hostVirtualIP = "192.168.127.254"
7980
internalSSHPort = "22"
8081
localIP = "127.0.0.1"
8182
remoteHTTPPort = "80"

0 commit comments

Comments
 (0)