module VagrantPlugins module VCloudAir module Action class ForwardPorts include Util::CompileForwardedPorts def initialize(app, env) @app = app @logger = Log4r::Logger.new('vagrant_vcloudair::action::forward_ports') end def call(env) @env = env # Get the ports we are forwarding env[:forwarded_ports] ||= compile_forwarded_ports( env[:machine].config ) forward_ports @app.call(env) end def forward_ports ports = [] edge_ports = [] cfg = @env[:machine].provider_config cnx = cfg.vcloudair_cnx.driver vapp_id = @env[:machine].get_vapp_id vm_name = @env[:machine].name # FIXME: why are we overriding this here ? # It's already been taken care during the initial # InventoryCheck. (tsugliani) # # cfg.org = cnx.get_organization_by_name(cfg.vdc_name) # cfg.vdc_network_id = cfg.org[:networks][cfg.vdc_network_name] @logger.debug('Getting VM info...') vm = cnx.get_vapp(vapp_id) vm_info = vm[:vms_hash][vm_name.to_sym] @env[:forwarded_ports].each do |fp| @env[:ui].info(I18n.t('vagrant_vcloudair.edge.port_forwarding', guest_port: fp.guest_port, host_port: fp.host_port)) # Add the options to the ports array to send to the driver later ports << { :guestip => fp.guest_ip, :nat_internal_port => fp.guest_port, :hostip => fp.host_ip, :nat_external_port => fp.host_port, :name => fp.id, :nat_protocol => fp.protocol.upcase, :vapp_scoped_local_id => vm_info[:vapp_scoped_local_id] } end unless ports.empty? # We only need to forward ports if there are any to forward @logger.debug("Port object to be passed: #{ports.inspect}") @logger.debug("Current network id #{cfg.vdc_network_id}") ### Here we apply the nat_rules to the vApp we just built add_ports = cnx.add_vapp_port_forwarding_rules( vapp_id, 'Vagrant-vApp-Net', { :fence_mode => 'natRouted', :parent_network => cfg.vdc_network_id, :nat_policy_type => 'allowTraffic', :nat_rules => ports } ) wait = cnx.wait_task_completion(add_ports) unless wait[:errormsg].nil? fail Errors::ComposeVAppError, :message => wait[:errormsg] end if cfg.vdc_edge_gateway_ip && \ cfg.vdc_edge_gateway && \ cfg.network_bridge.nil? vapp_edge_ip = cnx.get_vapp_edge_public_ip(vapp_id) @logger.debug('Getting edge gateway port forwarding rules...') edge_gateway_rules = cnx.get_edge_gateway_rules(cfg.vdc_edge_gateway, cfg.vdc_id) vapp_edge_dnat_rules = edge_gateway_rules.select {|r| (r[:rule_type] == 'DNAT' && r[:translated_ip] == vapp_edge_ip)} vapp_edge_ports_in_use = vapp_edge_dnat_rules.map{|r| r[:original_port].to_i}.to_set ports.each do |port| if port[:vapp_scoped_local_id] == vm_info[:vapp_scoped_local_id] && !vapp_edge_ports_in_use.include?(port[:nat_external_port]) @env[:ui].info(I18n.t( 'vagrant_vcloudair.edge.nat_rules_creation', vdc_edge_gateway: cfg.vdc_edge_gateway, vapp_edge_ip: vapp_edge_ip, port: port[:nat_external_port])) edge_ports << port[:nat_external_port] end end unless edge_ports.empty? # Add the vShield Edge Gateway rules add_ports = cnx.add_edge_gateway_rules( cfg.vdc_edge_gateway, cfg.vdc_id, cfg.vdc_edge_gateway_ip, vapp_id, edge_ports ) wait = cnx.wait_task_completion(add_ports) fail Errors::ComposeVAppError, :message => wait[:errormsg] unless wait[:errormsg].nil? end end end end end end end end