diff --git a/lib/vagrant/machine/remote.rb b/lib/vagrant/machine/remote.rb index dc151b956..cf309edef 100644 --- a/lib/vagrant/machine/remote.rb +++ b/lib/vagrant/machine/remote.rb @@ -124,78 +124,8 @@ module Vagrant "" end - ### HACKS - def action(name, opts=nil) - @logger.info("Calling action: #{name} on provider #{@provider}") - - opts ||= {} - - # Determine whether we lock or not - lock = true - lock = opts.delete(:lock) if opts.key?(:lock) - - # Extra env keys are the remaining opts - extra_env = opts.dup - # An environment is required for triggers to function properly. This is - # passed in specifically for the `#Action::Warden` class triggers. We call it - # `:trigger_env` instead of `env` in case it collides with an existing environment - extra_env[:trigger_env] = @env - - check_cwd # Warns the UI if the machine was last used on a different dir - - # Create a deterministic ID for this machine - vf = nil - vf = @env.vagrantfile_name[0] if @env.vagrantfile_name - id = Digest::MD5.hexdigest( - "#{@env.root_path}#{vf}#{@env.local_data_path}#{@name}") - - # We only lock if we're not executing an SSH action. In the future - # we will want to do more fine-grained unlocking in actions themselves - # but for a 1.6.2 release this will work. - locker = Proc.new { |*args, &block| block.call } - locker = @env.method(:lock) if lock && !name.to_s.start_with?("ssh") - - # Lock this machine for the duration of this action - return_env = locker.call("machine-action-#{id}") do - # Get the callable from the provider. - callable = @provider.action(name) - - # If this action doesn't exist on the provider, then an exception - # must be raised. - if callable.nil? - raise Errors::UnimplementedProviderAction, - action: name, - provider: @provider.to_s - end - - # Call the action - ui.machine("action", name.to_s, "start") - action_result = action_raw(name, callable, extra_env) - ui.machine("action", name.to_s, "end") - action_result - end - # preserve returning environment after machine action runs - return return_env - rescue Errors::EnvironmentLockedError - raise Errors::MachineActionLockedError, - action: name, - name: @name - end - - def action_raw(name, callable, extra_env={}) - if !extra_env.is_a?(Hash) - extra_env = {} - end - - # Run the action with the action runner on the environment - env = {ui: @ui}.merge(extra_env).merge( - raw_action_name: name, - action_name: "machine_action_#{name}".to_sym, - machine: self, - machine_action: name - ) - @env.action_runner.run(callable, env) + @provider.action(name) end def communicate diff --git a/lib/vagrant/plugin/remote/provider.rb b/lib/vagrant/plugin/remote/provider.rb index afb7cdcae..6b41d6080 100644 --- a/lib/vagrant/plugin/remote/provider.rb +++ b/lib/vagrant/plugin/remote/provider.rb @@ -34,7 +34,7 @@ module Vagrant end def action(name) - client.action(name) + client.action(@machine.to_proto, name) end def machine_id_changed diff --git a/plugins/commands/serve/client/provider.rb b/plugins/commands/serve/client/provider.rb index c025d4d11..68b4c243e 100644 --- a/plugins/commands/serve/client/provider.rb +++ b/plugins/commands/serve/client/provider.rb @@ -28,9 +28,11 @@ module VagrantPlugins res.is_installed end + # @param [Sdk::Args::Machine] # @param [Symbol] name of the action to run - def action(name, *args) - d = Type::Direct.new(arguments: args) + def action(machine, name) + arg_protos = seed_protos + d = Type::Direct.new(arguments: [machine]) da = mapper.map(d, to: Google::Protobuf::Any) arg_protos << SDK::FuncSpec::Value.new( name: "", diff --git a/plugins/commands/serve/service/provider_service.rb b/plugins/commands/serve/service/provider_service.rb index 8031eb195..e1bba3cea 100644 --- a/plugins/commands/serve/service/provider_service.rb +++ b/plugins/commands/serve/service/provider_service.rb @@ -64,7 +64,7 @@ module VagrantPlugins def action_spec(req, _unused_call) SDK::FuncSpec.new( - name: "capability_spec", + name: "action_spec", args: [ SDK::FuncSpec::Value.new( type: "hashicorp.vagrant.sdk.Args.Direct", @@ -75,9 +75,40 @@ module VagrantPlugins ) end - def action_up(req, ctx) - # TODO - nil + def action(req, ctx) + plugins = Vagrant.plugin("2").local_manager.providers + with_plugin(ctx, plugins, broker: broker) do |plugin| + action_name = req.name.to_sym + args = mapper.funcspec_map( + req.func_args, + expect: [Type::Direct] + ) + + machine = args.arguments.find { |a| a.is_a?(Vagrant::Machine) } + provider = plugin.new(machine) + callable = provider.action(action_name) + if callable.nil? + raise Errors::UnimplementedProviderAction, + action: name, + provider: @provider.to_s + end + action_raw(machine, action_name, callable) + Empty.new + end + end + + def action_raw(machine, name, callable, extra_env={}) + if !extra_env.is_a?(Hash) + extra_env = {} + end + # Run the action with the action runner on the environment + env = {ui: machine.ui}.merge(extra_env).merge( + raw_action_name: name, + action_name: "machine_action_#{name}".to_sym, + machine: machine, + machine_action: name + ) + machine.env.action_runner.run(callable, env) end def machine_id_changed_spec(*_)