Module: Vagrant::Machine::Remote

Includes:
Util::ScopedHashOverride
Defined in:
lib/vagrant/machine/remote.rb

Overview

This module enables the Machine for server mode

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util::ScopedHashOverride

#scoped_hash_override

Class Method Details

.prepended(klass) ⇒ Object

Add an attribute reader for the client when applied to the Machine class



16
17
18
19
20
# File 'lib/vagrant/machine/remote.rb', line 16

def self.prepended(klass)
  klass.class_eval do
    attr_reader :client
  end
end

Instance Method Details

#boxBox

Returns:



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/vagrant/machine/remote.rb', line 66

def box
  box = client.box
  # The box itself can be nil in some cases (e.g. for the docker provider)
  if box.nil?
    return nil
  end
  # If the version isn't set, then the box has not being tracked
  # by Vagrant.
  if box.version.empty?
    box = nil
  end
  return box
end

#check_cwdObject



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/vagrant/machine/remote.rb', line 276

def check_cwd
  desired_encoding = @env.root_path.to_s.encoding
  vagrant_cwd_filepath = @data_dir.join('vagrant_cwd')
  vagrant_cwd = if File.exist?(vagrant_cwd_filepath)
                  File.read(vagrant_cwd_filepath,
                    external_encoding: desired_encoding
                  ).chomp
                end

  if !File.identical?(vagrant_cwd.to_s, @env.root_path.to_s)
    if vagrant_cwd
      ui.warn(I18n.t(
        'vagrant.moved_cwd',
        old_wd:     "#{vagrant_cwd}",
        current_wd: "#{@env.root_path.to_s}"))
    end
    File.write(vagrant_cwd_filepath, @env.root_path.to_s,
      external_encoding: desired_encoding
    )
  end
end

#communicateObject

TODO def config raise NotImplementedError, "TODO" end



85
86
87
88
89
90
# File 'lib/vagrant/machine/remote.rb', line 85

def communicate
  if !@communicate
    @communicate = Vagrant::Plugin::Remote::Communicator.new(self)
  end
  @communicate
end

#data_dirObject



92
93
94
# File 'lib/vagrant/machine/remote.rb', line 92

def data_dir
  client.data_dir
end

#guestObject



96
97
98
99
100
101
102
# File 'lib/vagrant/machine/remote.rb', line 96

def guest
  raise Errors::MachineGuestNotReady if !communicate.ready?
  if !@guest
    @guest = Guest.new(self, nil, nil)
  end
  @guest
end

#idObject



104
105
106
107
# File 'lib/vagrant/machine/remote.rb', line 104

def id
  result = client.id
  result.to_s.empty? ? nil : result
end

#id=(value) ⇒ Object



109
110
111
112
113
114
115
116
117
# File 'lib/vagrant/machine/remote.rb', line 109

def id=(value)
  @logger.info("New machine ID: #{value.inspect}")
  client.set_id(value.to_s)
  # Store the ID locally
  @id = value.nil? ? nil : value.to_s
  # Notify the provider that the ID changed in case it needs to do
  # any accounting from it. This is only used for local Ruby providers
  @provider.machine_id_changed
end

#index_uuidObject



123
124
125
# File 'lib/vagrant/machine/remote.rb', line 123

def index_uuid
  id
end

#initialize(*args, client:) ⇒ Object

Initialize a new machine.

Parameters:

  • name (String)

    Name of the virtual machine.

  • provider (Class)

    The provider backing this machine. This is currently expected to be a V1 provider plugin.

  • provider_config (Object)

    The provider-specific configuration for this machine.

  • provider_options (Hash)

    The provider-specific options from the plugin definition.

  • config (Object)

    The configuration for this machine.

  • data_dir (Pathname)

    The directory where machine-specific data can be stored. This directory is ensured to exist.

  • box (Box)

    The box that is backing this virtual machine.

  • env (Environment)

    The environment that this machine is a part of.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/vagrant/machine/remote.rb', line 37

def initialize(*args, client:)
  @logger = Log4r::Logger.new("vagrant::machine")
  @client = client
  @env = client.environment
  @ui = Vagrant::UI::Prefixed.new(@env.ui, name)
  @box             = client.box
  @config          = client.vagrantfile.config
  @data_dir        = client.data_dir
  @vagrantfile     = client.vagrantfile
  @ui_mutex        = Mutex.new
  @state_mutex     = Mutex.new
  # TODO: get trigger config from go
  @triggers        = Vagrant::Plugin::V2::Trigger.new(@env, @config.trigger, self, @ui)

  # Keep track of where our UUID should be placed
  @index_uuid_file = nil
  @index_uuid_file = @data_dir.join("index_uuid") if @data_dir

  # Output a bunch of information about this machine in
  # machine-readable format in case someone is listening.
  @ui.machine("metadata", "provider", provider_name)
end

#inspectObject



119
120
121
# File 'lib/vagrant/machine/remote.rb', line 119

def inspect
  "<Vagrant::Machine:resource_id=#{client.resource_id}>"
end

#nameObject



127
128
129
# File 'lib/vagrant/machine/remote.rb', line 127

def name
  client.name.to_sym
end

#providerObject



147
148
149
150
151
# File 'lib/vagrant/machine/remote.rb', line 147

def provider
  return @provider if @provider
  @provider = Vagrant.plugin("2").manager.providers[provider_name].first.new(self)
  @provider
end

#provider_configObject



60
61
62
63
# File 'lib/vagrant/machine/remote.rb', line 60

def provider_config
  return @provider_config if @provider_config
  @provider_config = @config.vm.get_provider_config(provider_name)
end

#provider_nameObject



153
154
155
156
# File 'lib/vagrant/machine/remote.rb', line 153

def provider_name
  return @provider_name if @provider_name
  @provider_name = client.provider_name.to_sym
end

#provider_optionsObject



158
159
160
# File 'lib/vagrant/machine/remote.rb', line 158

def provider_options
  @provider_options ||= Vagrant.plugin("2").manager.providers[provider_name].last
end

#recover_machine(*_) ⇒ Object

TODO def index_uuid client.get_uuid end



136
137
138
# File 'lib/vagrant/machine/remote.rb', line 136

def recover_machine(*_)
  nil
end

#reloadObject



166
167
168
# File 'lib/vagrant/machine/remote.rb', line 166

def reload
  id
end

#ssh_infoObject



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/vagrant/machine/remote.rb', line 170

def ssh_info
  # First, ask the provider for their information. If the provider
  # returns nil, then the machine is simply not ready for SSH, and
  # we return nil as well.
  info = provider.ssh_info
  return nil if info.nil?

  # Delete out the nil entries.
  info.dup.each do |key, value|
    info.delete(key) if value.nil?
  end

  # We set the defaults
  info[:host] ||= @config.ssh.default.host
  info[:port] ||= @config.ssh.default.port
  info[:private_key_path] ||= @config.ssh.default.private_key_path
  info[:keys_only] ||= @config.ssh.default.keys_only
  info[:verify_host_key] ||= @config.ssh.default.verify_host_key
  info[:username] ||= @config.ssh.default.username
  info[:remote_user] ||= @config.ssh.default.remote_user
  info[:compression] ||= @config.ssh.default.compression
  info[:dsa_authentication] ||= @config.ssh.default.dsa_authentication
  info[:extra_args] ||= @config.ssh.default.extra_args
  info[:config] ||= @config.ssh.default.config

  # We set overrides if they are set. These take precedence over
  # provider-returned data.
  info[:host] = @config.ssh.host if @config.ssh.host
  info[:port] = @config.ssh.port if @config.ssh.port
  info[:keys_only] = @config.ssh.keys_only
  info[:verify_host_key] = @config.ssh.verify_host_key
  info[:compression] = @config.ssh.compression
  info[:dsa_authentication] = @config.ssh.dsa_authentication
  info[:username] = @config.ssh.username if @config.ssh.username
  info[:password] = @config.ssh.password if @config.ssh.password
  info[:remote_user] = @config.ssh.remote_user if @config.ssh.remote_user
  info[:extra_args] = @config.ssh.extra_args if @config.ssh.extra_args
  info[:config] = @config.ssh.config if @config.ssh.config

  # We also set some fields that are purely controlled by Vagrant
  info[:forward_agent] = @config.ssh.forward_agent
  info[:forward_x11] = @config.ssh.forward_x11
  info[:forward_env] = @config.ssh.forward_env
  info[:connect_timeout] = @config.ssh.connect_timeout

  info[:ssh_command] = @config.ssh.ssh_command if @config.ssh.ssh_command

  # Add in provided proxy command config
  info[:proxy_command] = @config.ssh.proxy_command if @config.ssh.proxy_command

  # Set the private key path. If a specific private key is given in
  # the Vagrantfile we set that. Otherwise, we use the default (insecure)
  # private key, but only if the provider didn't give us one.
  if !info[:private_key_path] && !info[:password]
    if @config.ssh.private_key_path
      info[:private_key_path] = @config.ssh.private_key_path
    elsif info[:keys_only]
      info[:private_key_path] = @env.default_private_key_path
    end
  end

  # If we have a private key in our data dir, then use that
  if @data_dir && !@config.ssh.private_key_path
    data_private_key = @data_dir.join("private_key")
    if data_private_key.file?
      info[:private_key_path] = [data_private_key.to_s]
    end
  end

  # Setup the keys
  info[:private_key_path] ||= []
  info[:private_key_path] = Array(info[:private_key_path])

  # Expand the private key path relative to the root path
  info[:private_key_path].map! do |path|
    File.expand_path(path, @env.root_path)
  end

  # Check that the private key permissions are valid
  info[:private_key_path].each do |path|
    key_path = Pathname.new(path)
    if key_path.exist?
      Vagrant::Util::SSH.check_key_permissions(key_path)
    end
  end

  # Return the final compiled SSH info data
  info
end

#stateObject



140
141
142
143
144
145
# File 'lib/vagrant/machine/remote.rb', line 140

def state
  s = provider.state
  raise Errors::MachineStateInvalid if !s.is_a?(MachineState)
  client.set_machine_state(s) unless s.nil?
  return s
end

#synced_foldersObject



298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/vagrant/machine/remote.rb', line 298

def synced_folders
  folders = Vagrant::Plugin::V2::SyncedFolder::Collection.new
  synced_folder_clients = client.synced_folders
  synced_folder_clients.each do |f|
    next if f[:folder][:disabled]
    # :type will be populated when the Vagrantfile has an explicit type
    # coming from the user and empty otherwise. when it is empty we can
    # infer the type from the name of the plugin we get back
    if f[:folder][:type].to_s != ""
      impl = f[:folder][:type].to_sym
    else
      impl = f[:plugin].name.to_sym
    end
    sf = Vagrant::Plugin::Remote::SyncedFolder.new(client: f[:plugin])
    folder_opts = scoped_hash_override(f[:folder], impl)
    # Set plugin, guestpath and hostpath from synced folder info
    new_folder = {f[:folder][:destination] => folder_opts.merge({
      plugin: sf,
      guestpath: f[:folder][:destination],
      hostpath: f[:folder][:source],
    })}
    if folders[impl]
      folders[impl].merge!(new_folder)
    else
      folders[impl] = new_folder
    end
  end
  folders
end

#to_protoObject



328
329
330
# File 'lib/vagrant/machine/remote.rb', line 328

def to_proto
  client.proto
end

#uidObject



260
261
262
# File 'lib/vagrant/machine/remote.rb', line 260

def uid
  client.uid
end

#with_ui(ui) ⇒ Object



264
265
266
267
268
269
270
271
272
273
274
# File 'lib/vagrant/machine/remote.rb', line 264

def with_ui(ui)
  @ui_mutex.synchronize do
    begin
      old_ui = @ui
      @ui    = ui
      yield
    ensure
      @ui = old_ui
    end
  end
end