synced_folders/nfs: begin implementation (not functional)
This commit is contained in:
parent
9d3818a380
commit
52fe93cc41
|
@ -1,128 +0,0 @@
|
||||||
require 'fileutils'
|
|
||||||
require 'pathname'
|
|
||||||
require 'zlib'
|
|
||||||
|
|
||||||
require "log4r"
|
|
||||||
|
|
||||||
require 'vagrant/util/platform'
|
|
||||||
|
|
||||||
module Vagrant
|
|
||||||
module Action
|
|
||||||
module Builtin
|
|
||||||
# This built-in middleware exports and mounts NFS shared folders.
|
|
||||||
#
|
|
||||||
# To use this middleware, two configuration parameters must be given
|
|
||||||
# via the environment hash:
|
|
||||||
#
|
|
||||||
# - `:nfs_host_ip` - The IP of where to mount the NFS folder from.
|
|
||||||
# - `:nfs_machine_ip` - The IP of the machine where the NFS folder
|
|
||||||
# will be mounted.
|
|
||||||
#
|
|
||||||
class NFS
|
|
||||||
def initialize(app, env)
|
|
||||||
@app = app
|
|
||||||
@logger = Log4r::Logger.new("vagrant::action::builtin::nfs")
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(env)
|
|
||||||
# We forward things along first. We do everything on the tail
|
|
||||||
# end of the middleware call.
|
|
||||||
@app.call(env)
|
|
||||||
|
|
||||||
# Used by prepare_permission, so we need to save it
|
|
||||||
@env = env
|
|
||||||
|
|
||||||
folders = {}
|
|
||||||
env[:machine].config.vm.synced_folders.each do |id, opts|
|
|
||||||
# If this synced folder doesn't enable NFS, ignore it.
|
|
||||||
next if !opts[:nfs]
|
|
||||||
|
|
||||||
# Expand the host path, create it if we have to and
|
|
||||||
# store away the folder.
|
|
||||||
hostpath = Pathname.new(opts[:hostpath]).
|
|
||||||
expand_path(env[:root_path])
|
|
||||||
|
|
||||||
if !hostpath.directory? && opts[:create]
|
|
||||||
# Host path doesn't exist, so let's create it.
|
|
||||||
@logger.debug("Host path doesn't exist, creating: #{hostpath}")
|
|
||||||
|
|
||||||
begin
|
|
||||||
FileUtils.mkpath(hostpath)
|
|
||||||
rescue Errno::EACCES
|
|
||||||
raise Vagrant::Errors::SharedFolderCreateFailed,
|
|
||||||
:path => hostpath.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Determine the real path by expanding symlinks and getting
|
|
||||||
# proper casing. We have to do this after creating it
|
|
||||||
# if it doesn't exist.
|
|
||||||
hostpath = hostpath.realpath
|
|
||||||
hostpath = Util::Platform.fs_real_path(hostpath)
|
|
||||||
|
|
||||||
# Set the hostpath back on the options and save it
|
|
||||||
opts[:hostpath] = hostpath.to_s
|
|
||||||
folders[id] = opts
|
|
||||||
end
|
|
||||||
|
|
||||||
if !folders.empty?
|
|
||||||
raise Errors::NFSNoHostIP if !env[:nfs_host_ip]
|
|
||||||
raise Errors::NFSNoGuestIP if !env[:nfs_machine_ip]
|
|
||||||
|
|
||||||
machine_ip = env[:nfs_machine_ip]
|
|
||||||
machine_ip = [machine_ip] if !machine_ip.is_a?(Array)
|
|
||||||
|
|
||||||
# Prepare the folder, this means setting up various options
|
|
||||||
# and such on the folder itself.
|
|
||||||
folders.each { |id, opts| prepare_folder(opts) }
|
|
||||||
|
|
||||||
# Export the folders
|
|
||||||
env[:ui].info I18n.t("vagrant.actions.vm.nfs.exporting")
|
|
||||||
env[:host].nfs_export(env[:machine].id, machine_ip, folders)
|
|
||||||
|
|
||||||
# Mount
|
|
||||||
env[:ui].info I18n.t("vagrant.actions.vm.nfs.mounting")
|
|
||||||
|
|
||||||
# Only mount folders that have a guest path specified.
|
|
||||||
mount_folders = {}
|
|
||||||
folders.each do |id, opts|
|
|
||||||
mount_folders[id] = opts.dup if opts[:guestpath]
|
|
||||||
end
|
|
||||||
|
|
||||||
# Mount them!
|
|
||||||
env[:machine].guest.capability(
|
|
||||||
:mount_nfs_folder, env[:nfs_host_ip], mount_folders)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def prepare_folder(opts)
|
|
||||||
opts[:map_uid] = prepare_permission(:uid, opts)
|
|
||||||
opts[:map_gid] = prepare_permission(:gid, opts)
|
|
||||||
opts[:nfs_version] ||= 3
|
|
||||||
|
|
||||||
# We use a CRC32 to generate a 32-bit checksum so that the
|
|
||||||
# fsid is compatible with both old and new kernels.
|
|
||||||
opts[:uuid] = Zlib.crc32(opts[:hostpath]).to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
# Prepares the UID/GID settings for a single folder.
|
|
||||||
def prepare_permission(perm, opts)
|
|
||||||
key = "map_#{perm}".to_sym
|
|
||||||
return nil if opts.has_key?(key) && opts[key].nil?
|
|
||||||
|
|
||||||
# The options on the hash get priority, then the default
|
|
||||||
# values
|
|
||||||
value = opts.has_key?(key) ? opts[key] : @env[:machine].config.nfs.send(key)
|
|
||||||
return value if value != :auto
|
|
||||||
|
|
||||||
# Get UID/GID from folder if we've made it this far
|
|
||||||
# (value == :auto)
|
|
||||||
stat = File.stat(opts[:hostpath])
|
|
||||||
return stat.send(perm)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,5 +1,7 @@
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
|
||||||
|
require 'vagrant/util/platform'
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Action
|
module Action
|
||||||
module Builtin
|
module Builtin
|
||||||
|
@ -29,15 +31,20 @@ module Vagrant
|
||||||
fs.each do |id, data|
|
fs.each do |id, data|
|
||||||
data[:hostpath] = File.expand_path(data[:hostpath], env[:root_path])
|
data[:hostpath] = File.expand_path(data[:hostpath], env[:root_path])
|
||||||
|
|
||||||
# Don't do anything else if this directory exists or its
|
# Create the hostpath if it doesn't exist and we've been told to
|
||||||
# not flagged to auto-create
|
if !File.directory?(data[:hostpath]) && data[:create]
|
||||||
next if File.directory?(data[:hostpath]) || !data[:create]
|
@logger.info("Creating shared folder host directory: #{data[:hostpath]}")
|
||||||
@logger.info("Creating shared folder host directory: #{data[:hostpath]}")
|
begin
|
||||||
begin
|
Pathname.new(data[:hostpath]).mkpath
|
||||||
Pathname.new(data[:hostpath]).mkpath
|
rescue Errno::EACCES
|
||||||
rescue Errno::EACCES
|
raise Vagrant::Errors::SharedFolderCreateFailed,
|
||||||
raise Vagrant::Errors::SharedFolderCreateFailed,
|
path: data[:hostpath]
|
||||||
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])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,10 +6,10 @@ module Vagrant
|
||||||
def usable?(machine)
|
def usable?(machine)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepare(machine, folders)
|
def prepare(machine, folders, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable(machine, folders)
|
def enable(machine, folders, opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ module VagrantPlugins
|
||||||
machine.provider_name == :virtualbox
|
machine.provider_name == :virtualbox
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepare(machine, folders)
|
def prepare(machine, folders, _opts)
|
||||||
defs = []
|
defs = []
|
||||||
folders.each do |id, data|
|
folders.each do |id, data|
|
||||||
hostpath = Vagrant::Util::Platform.cygwin_windows_path(data[:hostpath])
|
hostpath = Vagrant::Util::Platform.cygwin_windows_path(data[:hostpath])
|
||||||
|
@ -23,7 +23,7 @@ module VagrantPlugins
|
||||||
driver(machine).share_folders(defs)
|
driver(machine).share_folders(defs)
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable(machine, folders)
|
def enable(machine, folders, _opts)
|
||||||
# short guestpaths first, so we don't step on ourselves
|
# short guestpaths first, so we don't step on ourselves
|
||||||
folders = folders.sort_by do |id, data|
|
folders = folders.sort_by do |id, data|
|
||||||
if data[:guestpath]
|
if data[:guestpath]
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
require "vagrant"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module SyncedFolderNFS
|
||||||
|
class Plugin < Vagrant.plugin("2")
|
||||||
|
name "NFS synced folders"
|
||||||
|
description <<-EOF
|
||||||
|
The NFS synced folders plugin enables you to use NFS as a synced folder
|
||||||
|
implementation.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
synced_folder(:nfs, 5) do
|
||||||
|
require File.expand_path("../synced_folder", __FILE__)
|
||||||
|
SyncedFolder
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,83 @@
|
||||||
|
require 'fileutils'
|
||||||
|
require 'zlib'
|
||||||
|
|
||||||
|
require "vagrant/util/platform"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module SyncedFolderNFS
|
||||||
|
# This synced folder requires that two keys be set on the environment
|
||||||
|
# within the middleware sequence:
|
||||||
|
#
|
||||||
|
# - `:nfs_host_ip` - The IP of where to mount the NFS folder from.
|
||||||
|
# - `:nfs_machine_ip` - The IP of the machine where the NFS folder
|
||||||
|
# will be mounted.
|
||||||
|
#
|
||||||
|
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
||||||
|
def usable?(machine)
|
||||||
|
# NFS is always available
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare(machine, folders, opts)
|
||||||
|
# Nothing is necessary to do before VM boot.
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable(machine, folders, nfsopts)
|
||||||
|
raise Errors::NFSNoHostIP if !nfsopts[:nfs_host_ip]
|
||||||
|
raise Errors::NFSNoGuestIP if !nfsopts[:nfs_machine_ip]
|
||||||
|
|
||||||
|
machine_ip = nfsopts[:nfs_machine_ip]
|
||||||
|
machine_ip = [machine_ip] if !machine_ip.is_a?(Array)
|
||||||
|
|
||||||
|
# Prepare the folder, this means setting up various options
|
||||||
|
# and such on the folder itself.
|
||||||
|
folders.each { |id, opts| prepare_folder(machine, opts) }
|
||||||
|
|
||||||
|
# Export the folders
|
||||||
|
machine.ui.info I18n.t("vagrant.actions.vm.nfs.exporting")
|
||||||
|
machine.env.host.nfs_export(machine.id, machine_ip, folders)
|
||||||
|
|
||||||
|
# Mount
|
||||||
|
machine.ui.info I18n.t("vagrant.actions.vm.nfs.mounting")
|
||||||
|
|
||||||
|
# Only mount folders that have a guest path specified.
|
||||||
|
mount_folders = {}
|
||||||
|
folders.each do |id, opts|
|
||||||
|
mount_folders[id] = opts.dup if opts[:guestpath]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mount them!
|
||||||
|
machine.guest.capability(
|
||||||
|
:mount_nfs_folder, nfsopts[:nfs_host_ip], mount_folders)
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def prepare_folder(machine, opts)
|
||||||
|
opts[:map_uid] = prepare_permission(machine, :uid, opts)
|
||||||
|
opts[:map_gid] = prepare_permission(machine, :gid, opts)
|
||||||
|
opts[:nfs_version] ||= 3
|
||||||
|
|
||||||
|
# We use a CRC32 to generate a 32-bit checksum so that the
|
||||||
|
# fsid is compatible with both old and new kernels.
|
||||||
|
opts[:uuid] = Zlib.crc32(opts[:hostpath]).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
# Prepares the UID/GID settings for a single folder.
|
||||||
|
def prepare_permission(machine, perm, opts)
|
||||||
|
key = "map_#{perm}".to_sym
|
||||||
|
return nil if opts.has_key?(key) && opts[key].nil?
|
||||||
|
|
||||||
|
# The options on the hash get priority, then the default
|
||||||
|
# values
|
||||||
|
value = opts.has_key?(key) ? opts[key] : machine.config.nfs.send(key)
|
||||||
|
return value if value != :auto
|
||||||
|
|
||||||
|
# Get UID/GID from folder if we've made it this far
|
||||||
|
# (value == :auto)
|
||||||
|
stat = File.stat(opts[:hostpath])
|
||||||
|
return stat.send(perm)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue