mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
Merge pull request #170 from teto/virtfs
Add 9p (virtfs) support to vagrant-libvirt.
This commit is contained in:
commit
489e096227
4
Gemfile
4
Gemfile
@ -10,3 +10,7 @@ group :development do
|
|||||||
gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
|
gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
group :plugins do
|
||||||
|
gem "vagrant-libvirt", :path => '.'
|
||||||
|
end
|
||||||
|
|
||||||
|
@ -27,19 +27,26 @@ module VagrantPlugins
|
|||||||
b2.use CreateNetworks
|
b2.use CreateNetworks
|
||||||
b2.use CreateNetworkInterfaces
|
b2.use CreateNetworkInterfaces
|
||||||
|
|
||||||
b2.use StartDomain
|
|
||||||
b2.use WaitTillUp
|
|
||||||
|
|
||||||
b2.use PrepareNFSValidIds
|
b2.use PrepareNFSValidIds
|
||||||
b2.use SyncedFolderCleanup
|
b2.use SyncedFolderCleanup
|
||||||
b2.use SyncedFolders
|
b2.use SyncedFolders
|
||||||
|
|
||||||
|
b2.use StartDomain
|
||||||
|
b2.use WaitTillUp
|
||||||
|
|
||||||
|
b2.use StartDomain
|
||||||
|
b2.use WaitTillUp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
b2.use ForwardPorts
|
b2.use ForwardPorts
|
||||||
|
|
||||||
b2.use PrepareNFSSettings
|
# b2.use PrepareNFSSettings
|
||||||
b2.use ShareFolders
|
b2.use ShareFolders
|
||||||
b2.use SetHostname
|
b2.use SetHostname
|
||||||
b2.use SyncFolders
|
# b2.use SyncFolders
|
||||||
else
|
else
|
||||||
b2.use action_start
|
b2.use action_start
|
||||||
end
|
end
|
||||||
@ -70,6 +77,11 @@ module VagrantPlugins
|
|||||||
# Ensure networks are created and active
|
# Ensure networks are created and active
|
||||||
b3.use CreateNetworks
|
b3.use CreateNetworks
|
||||||
|
|
||||||
|
b3.use PrepareNFSValidIds
|
||||||
|
b3.use SyncedFolderCleanup
|
||||||
|
b3.use SyncedFolders
|
||||||
|
|
||||||
|
|
||||||
# Start it..
|
# Start it..
|
||||||
b3.use StartDomain
|
b3.use StartDomain
|
||||||
|
|
||||||
@ -77,12 +89,9 @@ module VagrantPlugins
|
|||||||
# so wait for dhcp lease and store IP into machines data_dir.
|
# so wait for dhcp lease and store IP into machines data_dir.
|
||||||
b3.use WaitTillUp
|
b3.use WaitTillUp
|
||||||
|
|
||||||
b3.use PrepareNFSValidIds
|
|
||||||
b3.use SyncedFolderCleanup
|
|
||||||
b3.use SyncedFolders
|
|
||||||
|
|
||||||
b3.use ForwardPorts
|
b3.use ForwardPorts
|
||||||
b3.use PrepareNFSSettings
|
# b3.use PrepareNFSSettings
|
||||||
b3.use ShareFolders
|
b3.use ShareFolders
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -147,7 +156,7 @@ module VagrantPlugins
|
|||||||
|
|
||||||
b2.use ConnectLibvirt
|
b2.use ConnectLibvirt
|
||||||
b2.use ClearForwardedPorts
|
b2.use ClearForwardedPorts
|
||||||
b2.use PruneNFSExports
|
# b2.use PruneNFSExports
|
||||||
b2.use DestroyDomain
|
b2.use DestroyDomain
|
||||||
b2.use DestroyNetworks
|
b2.use DestroyNetworks
|
||||||
end
|
end
|
||||||
@ -195,7 +204,7 @@ module VagrantPlugins
|
|||||||
end
|
end
|
||||||
|
|
||||||
b3.use Provision
|
b3.use Provision
|
||||||
b3.use SyncFolders
|
# b3.use SyncFolders
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -312,18 +321,25 @@ module VagrantPlugins
|
|||||||
autoload :MessageNotCreated, action_root.join('message_not_created')
|
autoload :MessageNotCreated, action_root.join('message_not_created')
|
||||||
autoload :MessageNotRunning, action_root.join('message_not_running')
|
autoload :MessageNotRunning, action_root.join('message_not_running')
|
||||||
autoload :MessageNotSuspended, action_root.join('message_not_suspended')
|
autoload :MessageNotSuspended, action_root.join('message_not_suspended')
|
||||||
|
|
||||||
autoload :PrepareNFSSettings, action_root.join('prepare_nfs_settings')
|
autoload :PrepareNFSSettings, action_root.join('prepare_nfs_settings')
|
||||||
autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
|
autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
|
||||||
autoload :PruneNFSExports, action_root.join('prune_nfs_exports')
|
autoload :PruneNFSExports, action_root.join('prune_nfs_exports')
|
||||||
|
|
||||||
autoload :ReadSSHInfo, action_root.join('read_ssh_info')
|
autoload :ReadSSHInfo, action_root.join('read_ssh_info')
|
||||||
autoload :ReadState, action_root.join('read_state')
|
autoload :ReadState, action_root.join('read_state')
|
||||||
autoload :ResumeDomain, action_root.join('resume_domain')
|
autoload :ResumeDomain, action_root.join('resume_domain')
|
||||||
autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
|
autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
|
||||||
|
|
||||||
|
# I don't think we need it anymore
|
||||||
autoload :ShareFolders, action_root.join('share_folders')
|
autoload :ShareFolders, action_root.join('share_folders')
|
||||||
autoload :StartDomain, action_root.join('start_domain')
|
autoload :StartDomain, action_root.join('start_domain')
|
||||||
autoload :SuspendDomain, action_root.join('suspend_domain')
|
autoload :SuspendDomain, action_root.join('suspend_domain')
|
||||||
autoload :SyncFolders, action_root.join('sync_folders')
|
autoload :TimedProvision, action_root.join('timed_provision')
|
||||||
|
|
||||||
autoload :WaitTillUp, action_root.join('wait_till_up')
|
autoload :WaitTillUp, action_root.join('wait_till_up')
|
||||||
|
autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
|
||||||
|
|
||||||
autoload :SSHRun, 'vagrant/action/builtin/ssh_run'
|
autoload :SSHRun, 'vagrant/action/builtin/ssh_run'
|
||||||
autoload :HandleBoxUrl, 'vagrant/action/builtin/handle_box_url'
|
autoload :HandleBoxUrl, 'vagrant/action/builtin/handle_box_url'
|
||||||
autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
|
autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
require "log4r"
|
|
||||||
require "vagrant/util/subprocess"
|
|
||||||
|
|
||||||
module VagrantPlugins
|
|
||||||
module ProviderLibvirt
|
|
||||||
module Action
|
|
||||||
# This middleware uses `rsync` to sync the folders over to the
|
|
||||||
# libvirt domain.
|
|
||||||
class SyncFolders
|
|
||||||
def initialize(app, env)
|
|
||||||
@app = app
|
|
||||||
@logger = Log4r::Logger.new("vagrant_libvirt::action::sync_folders")
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(env)
|
|
||||||
@app.call(env)
|
|
||||||
|
|
||||||
ssh_info = env[:machine].ssh_info
|
|
||||||
|
|
||||||
env[:machine].config.vm.synced_folders.each do |id, data|
|
|
||||||
next unless data[:type] == :rsync
|
|
||||||
proxycommand = "-o ProxyCommand='#{ssh_info[:proxy_command]}'" if ssh_info[:proxy_command]
|
|
||||||
hostpath = File.expand_path(data[:hostpath], env[:root_path])
|
|
||||||
guestpath = data[:guestpath]
|
|
||||||
|
|
||||||
# Make sure there is a trailing slash on the host path to
|
|
||||||
# avoid creating an additional directory with rsync
|
|
||||||
hostpath = "#{hostpath}/" if hostpath !~ /\/$/
|
|
||||||
|
|
||||||
env[:ui].info(I18n.t('vagrant_libvirt.rsync_folder',
|
|
||||||
:hostpath => hostpath,
|
|
||||||
:guestpath => guestpath))
|
|
||||||
|
|
||||||
# Create the guest path
|
|
||||||
env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
|
|
||||||
env[:machine].communicate.sudo(
|
|
||||||
"chown #{ssh_info[:username]} '#{guestpath}'")
|
|
||||||
|
|
||||||
# Rsync over to the guest path using the SSH info
|
|
||||||
command = [
|
|
||||||
'rsync', '--del', '--verbose', '--archive', '-z',
|
|
||||||
'--exclude', '.vagrant/',
|
|
||||||
'-e', "ssh -p #{ssh_info[:port]} #{proxycommand} -o StrictHostKeyChecking=no #{ssh_key_options(ssh_info)}",
|
|
||||||
hostpath,
|
|
||||||
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
|
|
||||||
|
|
||||||
r = Vagrant::Util::Subprocess.execute(*command)
|
|
||||||
if r.exit_code != 0
|
|
||||||
raise Errors::RsyncError,
|
|
||||||
:guestpath => guestpath,
|
|
||||||
:hostpath => hostpath,
|
|
||||||
:stderr => r.stderr
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
private
|
|
||||||
|
|
||||||
def ssh_key_options(ssh_info)
|
|
||||||
# Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
|
|
||||||
Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
38
lib/vagrant-libvirt/cap/mount_p9.rb
Normal file
38
lib/vagrant-libvirt/cap/mount_p9.rb
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
require "vagrant/util/retryable"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module ProviderLibvirt
|
||||||
|
module Cap
|
||||||
|
class MountP9
|
||||||
|
extend Vagrant::Util::Retryable
|
||||||
|
|
||||||
|
def self.mount_p9_shared_folder(machine, folders, options)
|
||||||
|
folders.each do |name, opts|
|
||||||
|
# Expand the guest path so we can handle things like "~/vagrant"
|
||||||
|
expanded_guest_path = machine.guest.capability(
|
||||||
|
:shell_expand_guest_path, opts[:guestpath])
|
||||||
|
|
||||||
|
# Do the actual creating and mounting
|
||||||
|
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
|
||||||
|
|
||||||
|
# Mount
|
||||||
|
mount_tag = name.dup
|
||||||
|
|
||||||
|
mount_opts="-o trans=virtio"
|
||||||
|
mount_opts += ",access=#{options[:owner]}" if options[:owner]
|
||||||
|
mount_opts += ",version=#{options[:version]}" if options[:version]
|
||||||
|
mount_opts += ",#{opts[:mount_options]}" if opts[:mount_options]
|
||||||
|
|
||||||
|
mount_command = "mount -t 9p #{mount_opts} '#{mount_tag}' #{expanded_guest_path}"
|
||||||
|
retryable(:on => Vagrant::Errors::LinuxMountFailed,
|
||||||
|
:tries => 5,
|
||||||
|
:sleep => 3) do
|
||||||
|
machine.communicate.sudo(mount_command,
|
||||||
|
:error_class => Vagrant::Errors::LinuxMountFailed)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
75
lib/vagrant-libvirt/cap/synced_folder.rb
Normal file
75
lib/vagrant-libvirt/cap/synced_folder.rb
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
require "log4r"
|
||||||
|
require 'ostruct'
|
||||||
|
|
||||||
|
|
||||||
|
require "vagrant/util/subprocess"
|
||||||
|
require "vagrant/errors"
|
||||||
|
require "vagrant-libvirt/errors"
|
||||||
|
# require_relative "helper"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module SyncedFolder9p
|
||||||
|
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
||||||
|
include Vagrant::Util
|
||||||
|
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
||||||
|
|
||||||
|
def initialize(*args)
|
||||||
|
super
|
||||||
|
|
||||||
|
@logger = Log4r::Logger.new("vagrant_libvirt::synced_folders::9p")
|
||||||
|
end
|
||||||
|
|
||||||
|
def usable?(machine, raise_error=false)
|
||||||
|
# TODO check for host support (eg in linux is 9p compiled ?)
|
||||||
|
# and support in Qemu for instance ?
|
||||||
|
machine.provider_name == :libvirt
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare(machine, folders, opts)
|
||||||
|
|
||||||
|
raise Vagrant::Errors::Error("No libvirt connection") if ProviderLibvirt.libvirt_connection.nil?
|
||||||
|
|
||||||
|
@conn = ProviderLibvirt.libvirt_connection.client
|
||||||
|
|
||||||
|
begin
|
||||||
|
# loop through folders
|
||||||
|
folders.each do |id, folder_opts|
|
||||||
|
folder_opts.merge!({ :accessmode => "passthrough",
|
||||||
|
:readonly => true })
|
||||||
|
# machine.ui.info "================\nMachine id: #{machine.id}Should be mounting folders\n #{id}, opts: #{folder_opts}"
|
||||||
|
|
||||||
|
xml = to_xml('filesystem', folder_opts )
|
||||||
|
# puts "<<<<< XML:\n #{xml}\n >>>>>"
|
||||||
|
@conn.lookup_domain_by_uuid(machine.id).attach_device(xml, 0)
|
||||||
|
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
# machine.ui.error("could not attach device because: #{e}")
|
||||||
|
raise VagrantPlugins::ProviderLibvirt::Errors::AttachDeviceError,:error_message => e.message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# TODO once up, mount folders
|
||||||
|
def enable(machine, folders, _opts)
|
||||||
|
# Go through each folder and mount
|
||||||
|
machine.ui.info("mounting p9 share in guest")
|
||||||
|
# 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
|
||||||
|
common_opts = {
|
||||||
|
:version => '9p2000.L',
|
||||||
|
}
|
||||||
|
# Mount the actual folder
|
||||||
|
machine.guest.capability(
|
||||||
|
:mount_p9_shared_folder, mount_folders, common_opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup(machine, opts)
|
||||||
|
# driver(machine).clear_shared_folders if machine.id && machine.id != ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -6,7 +6,7 @@ end
|
|||||||
|
|
||||||
# This is a sanity check to make sure no one is attempting to install
|
# This is a sanity check to make sure no one is attempting to install
|
||||||
# this into an early Vagrant version.
|
# this into an early Vagrant version.
|
||||||
if Vagrant::VERSION < '1.4.0'
|
if Vagrant::VERSION < '1.5.0'
|
||||||
raise 'The Vagrant Libvirt plugin is only compatible with Vagrant 1.4+'
|
raise 'The Vagrant Libvirt plugin is only compatible with Vagrant 1.4+'
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -31,6 +31,17 @@ module VagrantPlugins
|
|||||||
require_relative 'provider'
|
require_relative 'provider'
|
||||||
Provider
|
Provider
|
||||||
end
|
end
|
||||||
|
|
||||||
|
guest_capability("linux", "mount_p9_shared_folder") do
|
||||||
|
require_relative "cap/mount_p9"
|
||||||
|
Cap::MountP9
|
||||||
|
end
|
||||||
|
|
||||||
|
# We set p9 as high priority (default 10)
|
||||||
|
synced_folder("9p", 20) do
|
||||||
|
require_relative "cap/synced_folder"
|
||||||
|
VagrantPlugins::SyncedFolder9p::SyncedFolder
|
||||||
|
end
|
||||||
|
|
||||||
# This initializes the internationalization strings.
|
# This initializes the internationalization strings.
|
||||||
def self.setup_i18n
|
def self.setup_i18n
|
||||||
|
8
lib/vagrant-libvirt/templates/filesystem.xml.erb
Normal file
8
lib/vagrant-libvirt/templates/filesystem.xml.erb
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<filesystem type='mount' accessmode='<%= accessmode %>'>
|
||||||
|
<driver type='path' wrpolicy='immediate'/>
|
||||||
|
<source dir='<%= hostpath %>'/>
|
||||||
|
<target dir='<%= guestpath %>'/>
|
||||||
|
<% unless readonly.nil? %>
|
||||||
|
<readonly />
|
||||||
|
<% end %>
|
||||||
|
</filesystem>
|
@ -1,17 +1,21 @@
|
|||||||
require 'erb'
|
require 'erubis'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module ProviderLibvirt
|
module ProviderLibvirt
|
||||||
module Util
|
module Util
|
||||||
module ErbTemplate
|
module ErbTemplate
|
||||||
|
|
||||||
# Taken from fog source.
|
|
||||||
def to_xml template_name = nil
|
# TODO might be a chance to use vagrant template system according to https://github.com/mitchellh/vagrant/issues/3231
|
||||||
|
def to_xml template_name = nil, data = binding
|
||||||
erb = template_name || self.class.to_s.split("::").last.downcase
|
erb = template_name || self.class.to_s.split("::").last.downcase
|
||||||
path = File.join(File.dirname(__FILE__), "..", "templates",
|
path = File.join(File.dirname(__FILE__), "..", "templates",
|
||||||
"#{erb}.xml.erb")
|
"#{erb}.xml.erb")
|
||||||
template = File.read(path)
|
template = File.read(path)
|
||||||
ERB.new(template, nil, '-').result(binding)
|
|
||||||
|
# TODO according to erubis documentation, we should rather use evaluate and forget about
|
||||||
|
# binding since the template may then change variables values
|
||||||
|
Erubis::Eruby.new(template, :trim => true).result(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user