155 lines
5.3 KiB
Ruby
155 lines
5.3 KiB
Ruby
# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
require "log4r"
|
|
|
|
require 'vagrant/util/platform'
|
|
|
|
require_relative "mixin_synced_folders"
|
|
|
|
module Vagrant
|
|
module Action
|
|
module Builtin
|
|
# This middleware will setup the synced folders for the machine using
|
|
# the appropriate synced folder plugin.
|
|
class SyncedFolders
|
|
include MixinSyncedFolders
|
|
|
|
def initialize(app, env)
|
|
@app = app
|
|
@logger = Log4r::Logger.new("vagrant::action::builtin::synced_folders")
|
|
end
|
|
|
|
def call(env)
|
|
opts = {
|
|
cached: !!env[:synced_folders_cached],
|
|
config: env[:synced_folders_config],
|
|
}
|
|
|
|
@logger.info("SyncedFolders loading from cache: #{opts[:cached]}")
|
|
folders = synced_folders(env[:machine], **opts)
|
|
original_folders = folders
|
|
|
|
folders.each do |impl_name, fs|
|
|
@logger.info("Synced Folder Implementation: #{impl_name}")
|
|
|
|
fs.each do |id, data|
|
|
# Log every implementation and their paths
|
|
@logger.info(" - #{id}: #{data[:hostpath]} => #{data[:guestpath]}")
|
|
end
|
|
end
|
|
|
|
# Go through each folder and make sure to create it if
|
|
# it does not exist on host
|
|
folders.each do |_, fs|
|
|
fs.each do |id, data|
|
|
next if data[:hostpath_exact]
|
|
|
|
data[:hostpath] = File.expand_path(
|
|
data[:hostpath], env[:root_path])
|
|
|
|
# Expand the symlink if this is a path that exists
|
|
if File.file?(data[:hostpath])
|
|
data[:hostpath] = File.realpath(data[:hostpath])
|
|
end
|
|
|
|
# Create the hostpath if it doesn't exist and we've been told to
|
|
if !File.directory?(data[:hostpath]) && data[:create]
|
|
@logger.info("Creating shared folder host directory: #{data[:hostpath]}")
|
|
begin
|
|
Pathname.new(data[:hostpath]).mkpath
|
|
rescue Errno::EACCES
|
|
raise Vagrant::Errors::SharedFolderCreateFailed,
|
|
path: data[:hostpath]
|
|
end
|
|
end
|
|
|
|
if File.directory?(data[:hostpath])
|
|
data[:hostpath] = File.realpath(data[:hostpath])
|
|
data[:hostpath] = Util::Platform.fs_real_path(data[:hostpath]).to_s
|
|
end
|
|
end
|
|
end
|
|
|
|
# Build up the instances of the synced folders. We do this once
|
|
# so that they can store state.
|
|
folders = folders.map do |impl_name, fs|
|
|
instance = plugins[impl_name.to_sym][0].new
|
|
[instance, impl_name, fs]
|
|
end
|
|
|
|
# Go through each folder and prepare the folders
|
|
folders.each do |impl, impl_name, fs|
|
|
if !env[:synced_folders_disable]
|
|
@logger.info("Invoking synced folder prepare for: #{impl_name}")
|
|
impl.prepare(env[:machine], fs, impl_opts(impl_name, env))
|
|
end
|
|
end
|
|
|
|
# Continue, we need the VM to be booted.
|
|
@app.call(env)
|
|
|
|
# Once booted, setup the folder contents
|
|
folders.each do |impl, impl_name, fs|
|
|
if !env[:synced_folders_disable]
|
|
@logger.info("Invoking synced folder enable: #{impl_name}")
|
|
impl.enable(env[:machine], fs, impl_opts(impl_name, env))
|
|
next
|
|
end
|
|
|
|
# We're disabling synced folders
|
|
to_disable = {}
|
|
fs.each do |id, data|
|
|
next if !env[:synced_folders_disable].include?(id)
|
|
to_disable[id] = data
|
|
end
|
|
|
|
@logger.info("Invoking synced folder disable: #{impl_name}")
|
|
to_disable.each do |id, _|
|
|
@logger.info(" - Disabling: #{id}")
|
|
end
|
|
impl.disable(env[:machine], to_disable, impl_opts(impl_name, env))
|
|
end
|
|
|
|
# If we disabled folders, we have to delete some from the
|
|
# save, so we load the entire cached thing, and delete them.
|
|
if env[:synced_folders_disable]
|
|
all = synced_folders(env[:machine], cached: true)
|
|
all.each do |impl, fs|
|
|
fs.keys.each do |id|
|
|
if env[:synced_folders_disable].include?(id)
|
|
fs.delete(id)
|
|
end
|
|
end
|
|
end
|
|
|
|
save_synced_folders(env[:machine], all)
|
|
else
|
|
save_opts = { merge: true }
|
|
save_opts[:vagrantfile] = true if !opts[:config]
|
|
|
|
# Save the synced folders
|
|
save_synced_folders(env[:machine], original_folders, **save_opts)
|
|
end
|
|
|
|
# Persist the mounts by adding them to fstab (only if the guest is available)
|
|
begin
|
|
persist_mount = env[:machine].guest.capability?(:persist_mount_shared_folder)
|
|
rescue Errors::MachineGuestNotReady
|
|
persist_mount = false
|
|
end
|
|
if persist_mount
|
|
# Persist the mounts by adding them to fstab
|
|
if env[:machine].config.vm.allow_fstab_modification
|
|
fstab_folders = original_folders
|
|
else
|
|
fstab_folders = nil
|
|
end
|
|
env[:machine].guest.capability(:persist_mount_shared_folder, fstab_folders)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|