Class: VagrantPlugins::ProviderLocal::Driver

Inherits:
Object
  • Object
show all
Includes:
Vagrant::Util::Retryable
Defined in:
lib/vagrant-local/driver.rb

Overview

This class does the heavy lifting of the local provider

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(machine) ⇒ Driver

Returns a new instance of Driver.



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/vagrant-local/driver.rb', line 26

def initialize(machine)
  @logger = Log4r::Logger.new('vagrant_local::driver')
  @machine = machine
  @executor = Executor::Exec.new
  @pfexec = if Process.uid.zero?
              ''
            elsif system('sudo -v')
              'sudo'
            else
              'pfexec'
            end
end

Instance Attribute Details

#executorObject

Returns the value of attribute executor.



24
25
26
# File 'lib/vagrant-local/driver.rb', line 24

def executor
  @executor
end

Instance Method Details

#boot(uii) ⇒ Object

Boot the Machine



102
103
104
105
106
107
108
109
# File 'lib/vagrant-local/driver.rb', line 102

def boot(uii)
  config = @machine.config.vm.provisioners[1].config.extra_vars.to_json
  command = "#{@pfexec} ansible-playbook ./providers/ansible/playbook.yml --tags 'boot' -e '#{config}'"
  uii.info(I18n.t('vagrant_local.start'))
  _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
  puts stdout.readline until stdout.eof?
  wait_thr.value
end

#check_support(uii) ⇒ Object

This ensures the host is ready for provisioning



112
113
114
115
116
117
118
119
120
121
# File 'lib/vagrant-local/driver.rb', line 112

def check_support(uii)
  uii.info(I18n.t('vagrant_local.preflight_checks'))
  uii.info(I18n.t('vagrant_local.ansible_playbook_check'))
  playbook_result = execute(false, "#{@pfexec} which ansible-playbook")
  raise Errors::AnsiblePlaybookNotDetected if playbook_result.empty?

  uii.info(I18n.t('vagrant_local.ansible_check'))
  result = execute(false, "#{@pfexec} which ansible")
  raise Errors::AnsibleNotDetected if result.empty?
end

#destroy(id) ⇒ Object

Destroys the instance



203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/vagrant-local/driver.rb', line 203

def destroy(id)
  # byebug
  config = @machine.config.vm.provisioners[1].config.extra_vars.to_json
  if state == :stopped
    id.info(I18n.t('vagrant_local.destroy'))
    command = "#{@pfexec} ansible-playbook ./providers/ansible/playbook.yml --tags 'destroy' -e '#{config}' "
    _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
    puts stdout.readline until stdout.eof?
    wait_thr.value
  end
  id.info(I18n.t('vagrant_local.destroyed'))
end

#executeObject

Execute System commands



64
65
66
# File 'lib/vagrant-local/driver.rb', line 64

def execute(...)
  @executor.execute(...)
end

#get_ip_addressObject



123
124
125
126
127
128
# File 'lib/vagrant-local/driver.rb', line 123

def get_ip_address
  vm_data = YAML.load_file("#{@machine.name}.vmstate")
  return nil unless vm_data.is_a?(Array) && !vm_data.empty? && vm_data.first.is_a?(Hash)

  vm_data.first['public_ip']
end

#halt(uii) ⇒ Object

Halts the instance, first via shutdown command, then a halt.



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
# File 'lib/vagrant-local/driver.rb', line 176

def halt(uii)
  provider_config = @machine.provider_config
  config = @machine.config.vm.provisioners[1].config.extra_vars.to_json
  uii.info(I18n.t('vagrant_local.graceful_shutdown'))
  begin
    Timeout.timeout(provider_config.clean_shutdown_time) do
      command = "#{@pfexec} ansible-playbook ./providers/ansible/playbook.yml --tags 'halt' -e '#{config}' "
      _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
      puts stdout.readline until stdout.eof?
      wait_thr.value
    end
  rescue Timeout::Error
    uii.info(I18n.t('vagrant_local.graceful_shutdown_failed') + provider_config.clean_shutdown_time.to_s)
    begin
      Timeout.timeout(provider_config.clean_shutdown_time) do
        command = "#{@pfexec} ansible-playbook ./providers/ansible/playbook.yml --tags 'halt' -e '#{config}' "
        _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
        puts stdout.readline until stdout.eof?
        wait_thr.value
      end
    rescue Timeout::Error
      raise Errors::TimeoutHalt
    end
  end
end

#install(_uii) ⇒ Object

Begin installation



69
70
71
72
73
74
75
# File 'lib/vagrant-local/driver.rb', line 69

def install(_uii)
  config = @machine.config.vm.provisioners[1].config.extra_vars.to_json
  command = "#{@pfexec} ansible-playbook ./providers/ansible/playbook.yml --tags 'install' -e '#{config}'"
  _stdin, stdout, _stderr, wait_thr = Open3.popen3(command)
  puts stdout.readline until stdout.eof?
  wait_thr.value
end

#ssh_run_command(uii, command) ⇒ Object

Run commands over SSH instead of ZLogin



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/vagrant-local/driver.rb', line 78

def ssh_run_command(uii, command)
  config = @machine.provider_config
  ip = get_ip_address
  user = user(@machine)
  key = userprivatekeypath(@machine).to_s
  port = sshport(@machine).to_s
  port = 22 if sshport(@machine).to_s.nil?
  execute_return = ''
  Util::Timer.time do
    retryable(on: Errors::TimeoutError, tries: 60) do
      # If we're interrupted don't worry about waiting
      ssh_string = "#{@pfexec} ssh -o 'StrictHostKeyChecking=no' -p"
      execute_return = execute(false, %(#{ssh_string} #{port} -i #{key} #{user}@#{ip} "#{command}"))
      uii.info(I18n.t('vagrant_local.ssh_run_command')) if config.debug
      uii.info(I18n.t('vagrant_local.ssh_run_command') + command) if config.debug
      loop do
        break if @machine.communicate.ready?
      end
    end
  end
  execute_return
end

#sshport(machine) ⇒ Object

This filters the sshport



160
161
162
163
164
165
166
# File 'lib/vagrant-local/driver.rb', line 160

def sshport(machine)
  config = machine.provider_config
  sshport = '22'
  sshport = config.sshport.to_s unless config.sshport.to_s.nil? || config.sshport.to_i.zero?
  # uii.info(I18n.t('vagrant_local.sshport')) if config.debug
  sshport
end

#stateObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/vagrant-local/driver.rb', line 39

def state
  data = [{
    'name' => nil,
    'ec2_id' => nil,
    'state' => 'not_created',
    'public_ip' => nil
  }]
  vmstate_file = "#{@machine.name}.vmstate"
  File.write(vmstate_file, data.to_yaml) unless File.exist?(vmstate_file)

  vm_data = YAML.load_file(vmstate_file)
  return :not_created unless vm_data.is_a?(Array) && !vm_data.empty? && vm_data.first.is_a?(Hash)

  vm_state = vm_data.first['state']
  case vm_state
  when 'running'
    :running
  when 'installed', 'stopped'
    :stopped
  else
    :not_created
  end
end

#user(machine) ⇒ Object

This filters the vagrantuser



131
132
133
134
135
136
# File 'lib/vagrant-local/driver.rb', line 131

def user(machine)
  config = machine.provider_config
  user = config.vagrant_user unless config.vagrant_user.nil?
  user = 'vagrant' if config.vagrant_user.nil?
  user
end

#userprivatekeypath(machine) ⇒ Object

This filters the userprivatekeypath



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/vagrant-local/driver.rb', line 139

def userprivatekeypath(machine)
  config = machine.provider_config
  userkey = config.vagrant_user_private_key_path.to_s
  if config.vagrant_user_private_key_path.to_s.nil?
    id_rsa = 'https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant'
    file = './id_rsa'
    command = "#{@pfexec} curl #{id_rsa} -O #{file}"
    Util::Subprocess.new command do |_stdout, stderr, _thread|
      uii.rewriting do |uipkp|
        uipkp.clear_line
        uipkp.info(I18n.t('vagrant_local.importing_vagrant_key'), new_line: false)
        uipkp.report_progress(stderr, 100, false)
      end
    end
    uii.clear_line
    userkey = './id_rsa'
  end
  userkey
end

#vagrantuserpass(machine) ⇒ Object

This filters the vagrantuserpass



169
170
171
172
173
# File 'lib/vagrant-local/driver.rb', line 169

def vagrantuserpass(machine)
  config = machine.provider_config
  # uii.info(I18n.t('vagrant_local.vagrantuserpass')) if config.debug
  config.vagrant_user_pass unless config.vagrant_user_pass.to_s.nil?
end