diff --git a/README.md b/README.md index e75f3f0..e38d557 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,8 @@ to the remote machine over SSH. This is good enough for all built-in Vagrant provisioners (shell, chef, and puppet) to work! +if used options :nfs => true, folder will exported by nfs. + ## Box Format You can view an example box in the [example_box/directory](https://github.com/pradels/vagrant-libvirt/tree/master/example_box). That directory also contains instructions on how to build a box. diff --git a/lib/vagrant-libvirt/action.rb b/lib/vagrant-libvirt/action.rb index 6aff1bc..787f875 100644 --- a/lib/vagrant-libvirt/action.rb +++ b/lib/vagrant-libvirt/action.rb @@ -24,6 +24,10 @@ module VagrantPlugins b2.use TimedProvision b2.use CreateNetworks b2.use CreateNetworkInterfaces + + b2.use NFS + b2.use PrepareNFSSettings + b2.use ShareFolders b2.use SetHostname b2.use StartDomain b2.use WaitTillUp @@ -100,6 +104,7 @@ module VagrantPlugins end b2.use ConnectLibvirt + b2.use PruneNFSExports b2.use DestroyDomain b2.use DestroyNetworks end @@ -274,6 +279,9 @@ module VagrantPlugins autoload :WaitTillUp, action_root.join("wait_till_up") autoload :SyncFolders, action_root.join("sync_folders") autoload :SSHRun, "vagrant/action/builtin/ssh_run" + autoload :PrepareNFSSettings, action_root.join("prepare_nfs_settings") + autoload :PruneNFSExports, action_root.join("prune_nfs_exports") + autoload :ShareFolders, action_root.join("share_folders") end end end diff --git a/lib/vagrant-libvirt/action/connect_libvirt.rb b/lib/vagrant-libvirt/action/connect_libvirt.rb index 83ad752..d48236b 100644 --- a/lib/vagrant-libvirt/action/connect_libvirt.rb +++ b/lib/vagrant-libvirt/action/connect_libvirt.rb @@ -18,7 +18,7 @@ module VagrantPlugins env[:libvirt_compute] = Libvirt.libvirt_connection return @app.call(env) end - + # Get config options for libvirt provider. config = env[:machine].provider_config @@ -38,7 +38,7 @@ module VagrantPlugins else uri << '://' uri << config.host if config.host - end + end uri << '/system?no_verify=1' conn_attr = {} @@ -46,7 +46,7 @@ module VagrantPlugins conn_attr[:libvirt_uri] = uri conn_attr[:libvirt_username] = config.username if config.username conn_attr[:libvirt_password] = config.password if config.password - + # Setup command for retrieving IP address for newly created machine # with some MAC address. Get it from dnsmasq leases table - either # /var/lib/libvirt/dnsmasq/*.leases files, or @@ -54,7 +54,7 @@ module VagrantPlugins ip_command = "LEASES='/var/lib/libvirt/dnsmasq/*.leases'; " ip_command << "[ -f /var/lib/misc/dnsmasq.leases ] && " ip_command << "LEASES='/var/lib/misc/dnsmasq.leases'; " - ip_command << "cat $LEASES | grep $mac | awk '{ print $3 }'" + ip_command << "grep $mac $LEASES | awk '{ print $3 }'" conn_attr[:libvirt_ip_command] = ip_command @logger.info("Connecting to Libvirt (#{uri}) ...") diff --git a/lib/vagrant-libvirt/action/prepare_nfs_settings.rb b/lib/vagrant-libvirt/action/prepare_nfs_settings.rb new file mode 100644 index 0000000..bc0ffb7 --- /dev/null +++ b/lib/vagrant-libvirt/action/prepare_nfs_settings.rb @@ -0,0 +1,66 @@ +require 'nokogiri' +module VagrantPlugins + module Libvirt + module Action + class PrepareNFSSettings + def initialize(app,env) + @app = app + @logger = Log4r::Logger.new("vagrant::action::vm::nfs") + end + + def call(env) + @app.call(env) + + using_nfs = false + env[:machine].config.vm.synced_folders.each do |id, opts| + if opts[:nfs] + using_nfs = true + break + end + end + + if using_nfs + @logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP") + env[:nfs_host_ip] = read_host_ip(env[:machine],env) + env[:nfs_machine_ip] = env[:machine].ssh_info[:host] + + raise Vagrant::Errors::NFSNoHostonlyNetwork if !env[:nfs_machine_ip] + end + end + + # Returns the IP address of the first host only network adapter + # + # @param [Machine] machine + # @return [String] + def read_host_ip(machine,env) + nets = env[:libvirt_compute].list_networks + if nets.size == 1 + net = nets.first + else + domain = env[:libvirt_compute].servers.get(machine.id.to_s) + xml=Nokogiri::XML(domain.to_xml) + networkname = xml.xpath('/domain/devices/interface/source').first.attributes['network'].value.to_s + puts "network name = #{networkname}" + net = env[:libvirt_compute].list_networks.map {|netw| netw if netw[:name] == networkname}.first + end + # FIXME better implement by libvirt xml parsing + `ip addr show | grep -A 2 #{net[:bridge_name]} | grep -i 'inet ' | tr -s ' ' | cut -d' ' -f3 | cut -d'/' -f 1`.chomp + end + + # Returns the IP address of the guest by looking at the first + # enabled host only network. + # + # @return [String] + def read_machine_ip(machine) + machine.config.vm.networks.each do |type, options| + if type == :private_network && options[:ip].is_a?(String) + return options[:ip] + end + end + + nil + end + end + end + end +end diff --git a/lib/vagrant-libvirt/action/prune_nfs_exports.rb b/lib/vagrant-libvirt/action/prune_nfs_exports.rb new file mode 100644 index 0000000..435a80e --- /dev/null +++ b/lib/vagrant-libvirt/action/prune_nfs_exports.rb @@ -0,0 +1,26 @@ +require 'yaml' +module VagrantPlugins + module Libvirt + module Action + class PruneNFSExports + + def initialize(app, env) + @app = app + end + + def call(env) + if env[:host] + uuid = env[:machine].id + # get all uuids + uuids = env[:libvirt_compute].servers.all.map(&:id) + # not exiisted in array will removed from nfs + uuids.delete(uuid) + env[:host].nfs_prune(uuids) + end + + @app.call(env) + end + end + end + end +end diff --git a/lib/vagrant-libvirt/action/share_folders.rb b/lib/vagrant-libvirt/action/share_folders.rb new file mode 100644 index 0000000..285b4e7 --- /dev/null +++ b/lib/vagrant-libvirt/action/share_folders.rb @@ -0,0 +1,76 @@ +require "pathname" + +require "log4r" + +module VagrantPlugins + module Libvirt + module Action + class ShareFolders + def initialize(app, env) + @logger = Log4r::Logger.new("vagrant::action::vm::share_folders") + @app = app + end + + def call(env) + @env = env + + prepare_folders + create_metadata + + @app.call(env) + end + + # This method returns an actual list of shared + # folders to create and their proper path. + def shared_folders + {}.tap do |result| + @env[:machine].config.vm.synced_folders.each do |id, data| + # Ignore NFS shared folders + next if !data[:nfs] + + # convert to NFS share + #data[:nfs] = true + + # This to prevent overwriting the actual shared folders data + result[id] = data.dup + end + end + end + + # Prepares the shared folders by verifying they exist and creating them + # if they don't. + def prepare_folders + shared_folders.each do |id, options| + hostpath = Pathname.new(options[:hostpath]).expand_path(@env[:root_path]) + + if !hostpath.directory? && options[:create] + # Host path doesn't exist, so let's create it. + @logger.debug("Host path doesn't exist, creating: #{hostpath}") + + begin + hostpath.mkpath + rescue Errno::EACCES + raise Vagrant::Errors::SharedFolderCreateFailed, + :path => hostpath.to_s + end + end + end + end + + def create_metadata + @env[:ui].info I18n.t("vagrant.actions.vm.share_folders.creating") + + folders = [] + shared_folders.each do |id, data| + folders << { + :name => id, + :hostpath => File.expand_path(data[:hostpath], @env[:root_path]), + :transient => data[:transient] + } + end + end + + end + end + end +end diff --git a/lib/vagrant-libvirt/action/sync_folders.rb b/lib/vagrant-libvirt/action/sync_folders.rb index f16fa02..af5af7d 100644 --- a/lib/vagrant-libvirt/action/sync_folders.rb +++ b/lib/vagrant-libvirt/action/sync_folders.rb @@ -18,6 +18,7 @@ module VagrantPlugins ssh_info = env[:machine].ssh_info env[:machine].config.vm.synced_folders.each do |id, data| + next if data[:nfs] hostpath = File.expand_path(data[:hostpath], env[:root_path]) guestpath = data[:guestpath]