Class: HashiCorp::VagrantVMwareDesktop::GuestCap::Linux::MountVMwareSharedFolder
- Inherits:
-
Object
- Object
- HashiCorp::VagrantVMwareDesktop::GuestCap::Linux::MountVMwareSharedFolder
- Defined in:
- lib/vagrant-vmware-desktop/guest_cap/linux/mount_vmware_shared_folder.rb
Constant Summary collapse
- VAGRANT_ROOT_MOUNT_POINT =
Root location for vagrant generated vmhgfs mounts
"/mnt/vagrant-mounts".freeze
Class Method Summary collapse
Class Method Details
.mount_vmware_shared_folder(machine, name, guestpath, options) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/vagrant-vmware-desktop/guest_cap/linux/mount_vmware_shared_folder.rb', line 12 def self.mount_vmware_shared_folder(machine, name, guestpath, ) = machine.guest.capability( :shell_expand_guest_path, guestpath) # Determine if we're using the HGFS kernel module or open-vm-tools. # We prefer to use the kernel module so we test for that. kernel_mod = machine.communicate.test("PATH=\"/sbin:$PATH\" lsmod | grep -i '^vmhgfs'") # The user can also override the mount strategy used by specifying a # vmware__mount_strategy option (the prefix is removed by Vagrant core). kernel_mod = [:mount_strategy].to_s == "kernel" if [:mount_strategy] # NOTE: This is pulled directly from the linux cap within vagrant proper. Once it is properly # extracted in vagrant, this should just be a method call for consistency. if [:owner].to_i.to_s == [:owner].to_s mount_uid = [:owner] else output = "" uid_command = "id -u #{[:owner]}" machine.communicate.execute(uid_command, error_check: false) { |type, data| output << data if type == :stdout } mount_uid = output.strip if mount_uid.to_i.to_s != mount_uid raise Errors::LinuxMountUIDFailed, folder_name: name end end if [:group].to_i.to_s == [:group].to_s mount_gid = [:group] else output = "" gid_command = "getent group #{[:group]}" machine.communicate.execute(gid_command, error_check: false) { |type, data| output << data if type == :stdout } mount_gid = output.strip.split(':').at(2) if mount_gid.to_i.to_s != mount_gid && [:owner] == [:group] output = "" result = machine.communicate.execute("id -g #{[:owner]}", error_check: false) { |type, data| output << data if type == :stdout } mount_gid = output.strip end if mount_gid.to_i.to_s != mount_gid raise Errors::LinuxMountGIDFailed, folder_name: name end end uid = mount_uid gid = mount_gid # Create the guest path if it doesn't exist machine.communicate.sudo( "test -L #{} && rm -rf #{}", error_check: false) machine.communicate.sudo("mkdir -p #{}") # If the kernel module is in use, continue using existing mount strategy. If the # kernel module is not in use, then we can assume the open-vm-tools are in use # which will automatically mount the share into the /mnt/hgfs directory if kernel_mod # Expand the name to the proper VMware name name = ".host:/#{name}" # Start building the mount options starting with the basic UID/GID = "-o uid=#{uid},gid=#{gid}" # Options += ",#{[:extra]}" if [:extra] += ",#{[:mount_options].join(",")}" if [:mount_options] # Build the full command mount_command = "mount -t vmhgfs" mount_command = "#{mount_command} #{} '#{name}' '#{}'" # Attempt to mount the folder. We retry here a few times because # it can fail early on. attempts = 0 while true success = true machine.communicate.sudo(mount_command) do |type, data| success = false if type == :stderr && data =~ /No such device/i # Sometimes it takes extra time for the `vmhgfs` filesystem # type to become available for use. success = false if type == :stderr && data =~ /unknown filesystem type/i end break if success attempts += 1 if attempts > 5 raise Vagrant::Errors::LinuxMountFailed, command: mount_command end sleep 3 end else # If using vmhgfs-fuse mounting the shared folder directly results in invalid # symlink generation. To resolve this we can bind mount the shared folder from # the full host shared mount. The open-vm-tools will automatically mount in # /mnt/hgfs, but the biggest issue with this mount is that it is fully accessible # to all users. Instead, we unmount that point if it is found, and we remount the # entire shared host (not just an individual folder) with uid and gid applied. The # container directory is only accessible via root, and the bind mounts result in the # expected behavior. current_mount_point = "#{VAGRANT_ROOT_MOUNT_POINT}/#{uid}-#{gid}" = "allow_other,default_permissions,uid=#{uid},gid=#{gid}" << ",#{[:extra]}" if [:extra] << ",#{[:mount_options].join(',')}" if [:mount_options] hgfs_mount = "vmhgfs-fuse -o #{} .host:/ '#{current_mount_point}'" # Allow user to disable unmounting of default vmhgfs-fuse mount point at /mnt/hgfs # by setting: `unmount_default_hgfs = false` in the provider config if machine.provider_config.unmount_default_hgfs machine.communicate.sudo <<-EOH.gsub(/^ */, '') if mount | grep /mnt/hgfs; then umount /mnt/hgfs fi EOH end # Unique mount point based on uid/gid pair machine.communicate.sudo <<-EOH.gsub(/^ */, '') mount | grep " #{current_mount_point} " if test $? -ne 0; then mkdir -p '#{current_mount_point}' chmod 700 '#{VAGRANT_ROOT_MOUNT_POINT}' #{hgfs_mount} fi EOH # Finally bind mount to the expected guest location mount_command = "mount --bind '#{current_mount_point}/#{name}' '#{}'" machine.communicate.sudo(mount_command) end # Emit an upstart event if we can machine.communicate.sudo <<-EOH.gsub(/^ {14}/, '') if command -v /sbin/init && /sbin/init --version | grep upstart; then /sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{}' fi EOH end |