mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
Merge pull request #139 from sciurus/forwarded-ports
Add support for port forwarding take two
This commit is contained in:
commit
336c16cf24
@ -162,7 +162,7 @@ Vagrant goes through steps below when creating new project:
|
||||
## Networks
|
||||
|
||||
Networking features in the form of `config.vm.network` support private networks
|
||||
concept. Port Forwarding is currently not supported.
|
||||
concept.
|
||||
|
||||
Public Network interfaces are currently implemented using the macvtap driver. The macvtap
|
||||
driver is only available with the Linux Kernel version >= 2.6.24. See the following libvirt
|
||||
@ -271,6 +271,12 @@ Configurable ssh parameters in Vagrantfile after provider version 0.0.5 are:
|
||||
* `config.ssh.forward_agent` - Default is false.
|
||||
* `config.ssh.forward_x11` - Default is false.
|
||||
|
||||
## Forwarded Ports
|
||||
|
||||
vagrant-libvirt supports Forwarded Ports via ssh port forwarding. For each
|
||||
`forwarded_port` directive you specify in your Vagrantfile, vagrant-libvirt
|
||||
will maintain an active ssh process for the lifetime of the VM.
|
||||
|
||||
## Synced Folders
|
||||
|
||||
There is minimal support for synced folders. Upon `vagrant up`, the Libvirt
|
||||
|
@ -38,6 +38,8 @@ module VagrantPlugins
|
||||
b2.use SyncedFolders
|
||||
end
|
||||
|
||||
b2.use ForwardPorts
|
||||
|
||||
b2.use PrepareNFSSettings
|
||||
b2.use ShareFolders
|
||||
b2.use SetHostname
|
||||
@ -87,6 +89,8 @@ module VagrantPlugins
|
||||
b3.use SyncedFolderCleanup
|
||||
b3.use SyncedFolders
|
||||
end
|
||||
|
||||
b3.use ForwardPorts
|
||||
b3.use PrepareNFSSettings
|
||||
b3.use ShareFolders
|
||||
|
||||
@ -101,6 +105,7 @@ module VagrantPlugins
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use ConnectLibvirt
|
||||
b.use ClearForwardedPorts
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
if !env[:result]
|
||||
b2.use MessageNotCreated
|
||||
@ -150,6 +155,7 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use ClearForwardedPorts
|
||||
b2.use PruneNFSExports
|
||||
b2.use DestroyDomain
|
||||
b2.use DestroyNetworks
|
||||
@ -303,6 +309,8 @@ module VagrantPlugins
|
||||
autoload :CreateNetworks, action_root.join('create_networks')
|
||||
autoload :DestroyDomain, action_root.join('destroy_domain')
|
||||
autoload :DestroyNetworks, action_root.join('destroy_networks')
|
||||
autoload :ForwardPorts, action_root.join('forward_ports')
|
||||
autoload :ClearForwardedPorts, action_root.join('forward_ports')
|
||||
autoload :HaltDomain, action_root.join('halt_domain')
|
||||
autoload :HandleBoxImage, action_root.join('handle_box_image')
|
||||
autoload :HandleStoragePool, action_root.join('handle_storage_pool')
|
||||
|
164
lib/vagrant-libvirt/action/forward_ports.rb
Normal file
164
lib/vagrant-libvirt/action/forward_ports.rb
Normal file
@ -0,0 +1,164 @@
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
# Adds support for vagrant's `forward_ports` configuration directive.
|
||||
class ForwardPorts
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::action::forward_ports')
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@env = env
|
||||
|
||||
# Get the ports we're forwarding
|
||||
env[:forwarded_ports] = compile_forwarded_ports(env[:machine].config)
|
||||
|
||||
# Warn if we're port forwarding to any privileged ports
|
||||
env[:forwarded_ports].each do |fp|
|
||||
if fp[:host] <= 1024
|
||||
env[:ui].warn I18n.t(
|
||||
'vagrant.actions.vm.forward_ports.privileged_ports'
|
||||
)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# Continue, we need the VM to be booted in order to grab its IP
|
||||
@app.call env
|
||||
|
||||
if @env[:forwarded_ports].any?
|
||||
env[:ui].info I18n.t('vagrant.actions.vm.forward_ports.forwarding')
|
||||
forward_ports
|
||||
end
|
||||
end
|
||||
|
||||
def forward_ports
|
||||
@env[:forwarded_ports].each do |fp|
|
||||
message_attributes = {
|
||||
adapter: 'eth0',
|
||||
guest_port: fp[:guest],
|
||||
host_port: fp[:host]
|
||||
}
|
||||
|
||||
@env[:ui].info(I18n.t(
|
||||
'vagrant.actions.vm.forward_ports.forwarding_entry',
|
||||
message_attributes
|
||||
))
|
||||
|
||||
ssh_pid = redirect_port(
|
||||
@env[:machine].name,
|
||||
fp[:host_ip] || '0.0.0.0',
|
||||
fp[:host],
|
||||
fp[:guest_ip] || @env[:machine].provider.ssh_info[:host],
|
||||
fp[:guest]
|
||||
)
|
||||
store_ssh_pid(fp[:host], ssh_pid)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def compile_forwarded_ports(config)
|
||||
mappings = {}
|
||||
|
||||
config.vm.networks.each do |type, options|
|
||||
next if options[:disabled]
|
||||
|
||||
if type == :forwarded_port && options[:id] != 'ssh'
|
||||
if options.fetch(:host_ip, '').to_s.strip.empty?
|
||||
options.delete(:host_ip)
|
||||
end
|
||||
mappings[options[:host]] = options
|
||||
end
|
||||
end
|
||||
|
||||
mappings.values
|
||||
end
|
||||
|
||||
def redirect_port(machine, host_ip, host_port, guest_ip, guest_port)
|
||||
params = %W(
|
||||
#{machine}
|
||||
-L #{host_ip}:#{host_port}:#{guest_ip}:#{guest_port}
|
||||
-N
|
||||
).join(' ')
|
||||
# TODO get options without shelling out
|
||||
options = `vagrant ssh-config #{machine} | awk '{printf " -o "$1"="$2}'`
|
||||
ssh_cmd = "ssh #{options} #{params}"
|
||||
|
||||
@logger.debug "Forwarding port with `#{ssh_cmd}`"
|
||||
spawn(ssh_cmd, [:out, :err] => '/dev/null')
|
||||
end
|
||||
|
||||
def store_ssh_pid(host_port, ssh_pid)
|
||||
data_dir = @env[:machine].data_dir.join('pids')
|
||||
data_dir.mkdir unless data_dir.directory?
|
||||
|
||||
data_dir.join("ssh_#{host_port}.pid").open('w') do |pid_file|
|
||||
pid_file.write(ssh_pid)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
# Cleans up ssh-forwarded ports on VM halt/destroy.
|
||||
class ClearForwardedPorts
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
@logger = Log4r::Logger.new(
|
||||
'vagrant_libvirt::action::clear_forward_ports'
|
||||
)
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@env = env
|
||||
|
||||
if ssh_pids.any?
|
||||
env[:ui].info I18n.t(
|
||||
'vagrant.actions.vm.clear_forward_ports.deleting'
|
||||
)
|
||||
ssh_pids.each do |pid|
|
||||
next unless ssh_pid?(pid)
|
||||
@logger.debug "Killing pid #{pid}"
|
||||
system "kill #{pid}"
|
||||
end
|
||||
|
||||
@logger.info 'Removing ssh pid files'
|
||||
remove_ssh_pids
|
||||
else
|
||||
@logger.info 'No ssh pids found'
|
||||
end
|
||||
|
||||
@app.call env
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def ssh_pids
|
||||
glob = @env[:machine].data_dir.join('pids').to_s + '/ssh_*.pid'
|
||||
@ssh_pids = Dir[glob].map do |file|
|
||||
File.read(file).strip.chomp
|
||||
end
|
||||
end
|
||||
|
||||
def ssh_pid?(pid)
|
||||
@logger.debug 'Checking if #{pid} is an ssh process '\
|
||||
'with `ps -o cmd= #{pid}`'
|
||||
`ps -o cmd= #{pid}`.strip.chomp =~ /ssh/
|
||||
end
|
||||
|
||||
def remove_ssh_pids
|
||||
glob = @env[:machine].data_dir.join('pids').to_s + '/ssh_*.pid'
|
||||
Dir[glob].each do |file|
|
||||
File.delete file
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user