Class: VagrantVbguest::Installers::Linux

Inherits:
Base
  • Object
show all
Defined in:
lib/vagrant-vbguest/installers/linux.rb

Overview

A basic Installer implementation for vanilla or unknown Linux based systems.

Direct Known Subclasses

Archlinux, Debian, Fedora, OpenSuse, RedHat, Suse

Instance Attribute Summary

Attributes inherited from Base

#env, #host, #options, #vm

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

distro, #host_version, #initialize, #installer_version, #iso_file, #reboot_after_install?, #upload, #yield_installation_error_warning, #yield_installation_warning, #yield_rebuild_warning

Methods included from Helpers::VmCompatible

#communicate, #driver, included

Constructor Details

This class inherits a constructor from VagrantVbguest::Installers::Base

Class Method Details

.match?(vm) ⇒ Boolean

Matches if the operating system name prints “Linux” Raises an Error if this class is beeing subclassed but this method was not overridden. This is considered an error because, subclassed Installers usually indicate a more specific distributen like ‘ubuntu’ or ‘arch’ and therefore should do a more specific check.

Returns:

  • (Boolean)

Raises:



14
15
16
17
# File 'lib/vagrant-vbguest/installers/linux.rb', line 14

def self.match?(vm)
  raise Error, :_key => :do_not_inherit_match_method if self != Linux
  communicate_to(vm).test("uname | grep 'Linux'")
end

.os_release(vm) ⇒ Hash|nil

Reads the ‘/etc/os-release` for the given `Vagrant::VM` if present, and returns it’s config as a parsed Hash. The result is cached on a per-vm basis.

Returns:

  • (Hash|nil)

    The os-release configuration as Hash, or ‘nil if file is not present or not parsable.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/vagrant-vbguest/installers/linux.rb', line 23

def self.os_release(vm)
  @@os_release_info ||= {}
  if !@@os_release_info.has_key?(vm_id(vm)) && communicate_to(vm).test("test -f /etc/os-release")
    osr_raw = communicate_to(vm).download("/etc/os-release")
    osr_parsed = begin
      VagrantVbguest::Helpers::OsRelease::Parser.(osr_raw)
    rescue VagrantVbguest::Helpers::OsRelease::FormatError => e
      vm.env.ui.warn(e.message)
      nil
    end
    @@os_release_info[vm_id(vm)] = osr_parsed
  end
  @@os_release_info[vm_id(vm)]
end

Instance Method Details

#cleanup(opts = nil, &block) ⇒ Object



297
298
299
300
301
302
# File 'lib/vagrant-vbguest/installers/linux.rb', line 297

def cleanup(opts=nil, &block)
  unless options[:no_cleanup]
    unmount_iso(opts, &block)
    super
  end
end

#execute_installer(opts = nil) {|type, data| ... } ⇒ Object

A generic helper method to execute the installer. This also yields a installation warning to the user, and an error warning in the event that the installer returns a non-zero exit status.

Parameters:

  • opts (Hash) (defaults to: nil)

    Optional options Hash wich meight get passed to Vagrant::Communication::SSH#execute and firends

Yields:

  • (type, data)

    Takes a Block like Vagrant::Communication::Base#execute for realtime output of the command being executed

Yield Parameters:

  • type (String)

    Type of the output, ‘:stdout`, `:stderr`, etc.

  • data (String)

    Data for the given output.



227
228
229
230
231
232
233
# File 'lib/vagrant-vbguest/installers/linux.rb', line 227

def execute_installer(opts=nil, &block)
  yield_installation_warning(installer)
  opts = {:error_check => false}.merge(opts || {})
  exit_status = communicate.sudo("#{yes}#{installer} #{installer_arguments}", opts, &block)
  yield_installation_error_warning(installer) unless exit_status == 0
  exit_status
end

#find_tool(tool) ⇒ String|nil

Checks for the correct location of the tool provided. It checks for a given list of possible locations. This list got extracted from the ‘VBoxLinuxAdditions.run’ script.

Returns:

  • (String|nil)

    Absolute path to the tool, or nil if none found.



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
# File 'lib/vagrant-vbguest/installers/linux.rb', line 191

def find_tool(tool)
  candidates = [
    "/usr/lib/i386-linux-gnu/VBoxGuestAdditions/#{tool}",
    "/usr/lib/x86_64-linux-gnu/VBoxGuestAdditions/#{tool}",
    "/usr/lib64/VBoxGuestAdditions/#{tool}",
    "/usr/lib/VBoxGuestAdditions/#{tool}",
    "/lib64/VBoxGuestAdditions/#{tool}",
    "/lib/VBoxGuestAdditions/#{tool}",
    "/etc/init.d/#{tool}",
    "/usr/sbin/rc#{tool}",
    "/sbin/rc#{tool}"
  ]
  cmd = <<-SHELL
  for c in #{candidates.join(" ")}; do
    if test -x "$c"; then
      echo $c
      break
    fi
  done
  SHELL

  path = nil
  communicate.sudo(cmd, {:error_check => false}) do |type, data|
    path = data.strip unless data.empty?
  end
  path
end

#guest_version(reload = false) ⇒ Gem::Version

This overrides Base#guest_version to also query the ‘VBoxService` on the host system (if available) for it’s version. In some scenarios the results of the VirtualBox driver and the additions installed on the host may differ. If this happens, we assume, that the host binaries are right and yield a warning message.

Returns:

  • (Gem::Version)

    The version code of the VirtualBox Guest Additions available on the guest, or ‘nil` if none installed.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/vagrant-vbguest/installers/linux.rb', line 103

def guest_version(reload = false)
  return @guest_version if @guest_version && !reload
  driver_version = VagrantVbguest::Version(super)

  communicate.sudo('VBoxService --version', :error_check => false) do |type, data|
    service_version = VagrantVbguest::Version(data)
    if service_version
      if driver_version != service_version
        @env.ui.warn(I18n.t("vagrant_vbguest.guest_version_reports_differ", :driver => driver_version, :service => service_version))
      end
      @guest_version = service_version
    end
  end
  @guest_version
end

#install(opts = nil) {|type, data| ... } ⇒ Object

a generic way of installing GuestAdditions assuming all dependencies on the guest are installed

Parameters:

  • opts (Hash) (defaults to: nil)

    Optional options Hash wich meight get passed to Vagrant::Communication::SSH#execute and firends

Yields:

  • (type, data)

    Takes a Block like Vagrant::Communication::Base#execute for realtime output of the command being executed

Yield Parameters:

  • type (String)

    Type of the output, ‘:stdout`, `:stderr`, etc.

  • data (String)

    Data for the given output.



64
65
66
67
68
69
70
# File 'lib/vagrant-vbguest/installers/linux.rb', line 64

def install(opts=nil, &block)
  env.ui.warn I18n.t("vagrant_vbguest.errors.installer.generic_linux_installer", distro: self.class.distro(vm)) if self.class == Linux
  upload(iso_file)
  mount_iso(opts, &block)
  execute_installer(opts, &block)
  start(opts, &block)
end

#installerObject

The absolute path to the GuestAdditions installer script. The iso file has to be mounted on mount_point.



237
238
239
# File 'lib/vagrant-vbguest/installers/linux.rb', line 237

def installer
  @installer ||= File.join(mount_point, 'VBoxLinuxAdditions.run')
end

#installer_argumentsObject

The arguments string, which gets passed to the installer script



242
243
244
# File 'lib/vagrant-vbguest/installers/linux.rb', line 242

def installer_arguments
  @installer_arguments ||= Array(options[:installer_arguments]).join " "
end

#installer_optionsObject



246
247
248
249
250
# File 'lib/vagrant-vbguest/installers/linux.rb', line 246

def installer_options
  @installer_options ||= {
    running_kernel_modules: ["vboxguest", "vboxsf"]
  }.merge!(super)
end

#mount_iso(opts = nil) {|type, data| ... } ⇒ Object

A generic helper method for mounting the GuestAdditions iso file on most linux system. Mounts the given uploaded file from tmp_path on mount_point.

Parameters:

  • opts (Hash) (defaults to: nil)

    Optional options Hash wich meight get passed to Vagrant::Communication::SSH#execute and firends

Yields:

  • (type, data)

    Takes a Block like Vagrant::Communication::Base#execute for realtime output of the command being executed

Yield Parameters:

  • type (String)

    Type of the output, ‘:stdout`, `:stderr`, etc.

  • data (String)

    Data for the given output.



271
272
273
274
275
# File 'lib/vagrant-vbguest/installers/linux.rb', line 271

def mount_iso(opts=nil, &block)
  env.ui.info(I18n.t("vagrant_vbguest.mounting_iso", :mount_point => mount_point))
  communicate.sudo("mount #{tmp_path} -o loop #{mount_point}", opts, &block)
  @mounted = true
end

#mount_pointObject

Mount point for the iso file. Configurable via ‘config.vbguest.iso_mount_point`. defaults to “/mnt” for all Linux based systems.



53
54
55
# File 'lib/vagrant-vbguest/installers/linux.rb', line 53

def mount_point
  options[:iso_mount_point] || '/mnt'
end

#os_releaseObject



38
39
40
# File 'lib/vagrant-vbguest/installers/linux.rb', line 38

def os_release
  self.class.os_release(vm)
end

#provides_vboxadd_tools?Boolean

Returns:

  • (Boolean)


148
149
150
# File 'lib/vagrant-vbguest/installers/linux.rb', line 148

def provides_vboxadd_tools?
  true
end

#rebuild(opts = nil) {|type, data| ... } ⇒ Object

Parameters:

  • opts (Hash) (defaults to: nil)

    Optional options Hash wich meight get passed to Vagrant::Communication::SSH#execute and firends

Yields:

  • (type, data)

    Takes a Block like Vagrant::Communication::Base#execute for realtime output of the command being executed

Yield Parameters:

  • type (String)

    Type of the output, ‘:stdout`, `:stderr`, etc.

  • data (String)

    Data for the given output.



123
124
125
# File 'lib/vagrant-vbguest/installers/linux.rb', line 123

def rebuild(opts=nil, &block)
  communicate.sudo("#{find_tool('vboxadd')} setup", opts, &block)
end

#running?(opts = nil) {|type, data| ... } ⇒ Boolean

Parameters:

  • opts (Hash) (defaults to: nil)

    Optional options Hash wich meight get passed to Vagrant::Communication::SSH#execute and firends

Yields:

  • (type, data)

    Takes a Block like Vagrant::Communication::Base#execute for realtime output of the command being executed

Yield Parameters:

  • type (String)

    Type of the output, ‘:stdout`, `:stderr`, etc.

  • data (String)

    Data for the given output.

Returns:

  • (Boolean)


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/vagrant-vbguest/installers/linux.rb', line 76

def running?(opts=nil, &block)
  kmods = []
  communicate.sudo('cat /proc/modules', opts) do |type, data|
    block.call(type, data) if block
    kmods << data if type == :stdout && data
  end

  if kmods.empty?
    env.ui.warn "Could not read /proc/modules"
    return true
  end

  Array(installer_options[:running_kernel_modules]).all? do |mod|
    regexp = /^#{mod}\b/i
    kmods.any? { |d| regexp.match(d) }
  end
end

#start(opts = nil) {|type, data| ... } ⇒ Object

Parameters:

  • opts (Hash) (defaults to: nil)

    Optional options Hash wich meight get passed to Vagrant::Communication::SSH#execute and firends

Yields:

  • (type, data)

    Takes a Block like Vagrant::Communication::Base#execute for realtime output of the command being executed

Yield Parameters:

  • type (String)

    Type of the output, ‘:stdout`, `:stderr`, etc.

  • data (String)

    Data for the given output.



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/vagrant-vbguest/installers/linux.rb', line 131

def start(opts=nil, &block)
  opts = {:error_check => false}.merge(opts || {})
  if systemd_tool
    communicate.sudo("#{systemd_tool[:path]} vboxadd #{systemd_tool[:up]}", opts, &block)
  else
    communicate.sudo("#{find_tool('vboxadd')} start", opts, &block)
  end

  if guest_version && guest_version >= Gem::Version.new('5.1')
    if systemd_tool
      communicate.sudo("#{systemd_tool[:path]} vboxadd-service #{systemd_tool[:up]}", opts, &block)
    else
      communicate.sudo("#{find_tool('vboxadd-service')} start", opts, &block)
    end
  end
end

#systemd_toolHash|nil

Check for the presence of ‘systemd’ chkconfg or service command.

systemd_tool # => {:path=>"/usr/sbin/service", :up=>"start"}

Returns:

  • (Hash|nil)

    Hash with an absolute path to the tool and the command string for starting. +nil* if neither was found.



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/vagrant-vbguest/installers/linux.rb', line 163

def systemd_tool
  return nil if @systemd_tool == false

  result = nil
  communicate.sudo('(which chkconfg || which service) 2>/dev/null', {:error_check => false}) do |type, data|
    path = data.to_s.strip
    case path
    when /\bservice\b/
      result = { path: path, up: "start", down: "stop" }
    when /\bchkconfg\b/
      result = { path: path, up: "on", down: "off" }
    end
  end

  if result.nil?
    @systemd_tool = false
    nil
  else
    @systemd_tool = result
  end
end

#tmp_pathObject

The temporary path where to upload the iso file to. Configurable via ‘config.vbguest.iso_upload_path`. Defaults the temp path to `/tmp/VBoxGuestAdditions.iso“ for all Linux based systems



46
47
48
# File 'lib/vagrant-vbguest/installers/linux.rb', line 46

def tmp_path
  options[:iso_upload_path] || '/tmp/VBoxGuestAdditions.iso'
end

#unmount_iso(opts = nil) {|type, data| ... } ⇒ Object

A generic helper method for un-mounting the GuestAdditions iso file on most linux system Unmounts the mount_point.

Parameters:

  • opts (Hash) (defaults to: nil)

    Optional options Hash wich meight get passed to Vagrant::Communication::SSH#execute and firends

Yields:

  • (type, data)

    Takes a Block like Vagrant::Communication::Base#execute for realtime output of the command being executed

Yield Parameters:

  • type (String)

    Type of the output, ‘:stdout`, `:stderr`, etc.

  • data (String)

    Data for the given output.



285
286
287
288
289
290
291
292
293
294
295
# File 'lib/vagrant-vbguest/installers/linux.rb', line 285

def unmount_iso(opts=nil, &block)
  unless @mounted
    env.ui.info(I18n.t("vagrant_vbguest.skip_unmounting_iso"))
    return
  end

  env.ui.info(I18n.t("vagrant_vbguest.unmounting_iso", :mount_point => mount_point))
  opts = (opts || {}).merge(:error_check => false)
  communicate.sudo("umount #{mount_point}", opts, &block)
  @mounted = false
end

#vboxadd_tools_available?Boolean

Returns:

  • (Boolean)


152
153
154
# File 'lib/vagrant-vbguest/installers/linux.rb', line 152

def vboxadd_tools_available?
  !!find_tool('vboxadd') || communicate.test('systemctl list-units --type service | grep -q vboxadd', {:sudo => true})
end

#yesObject

Determine if yes needs to be called or not



253
254
255
256
257
258
259
260
261
# File 'lib/vagrant-vbguest/installers/linux.rb', line 253

def yes
  value = @options[:yes]
  # Simple yes if explicitly boolean true
  return "yes | " if !!value == value && value
  # Nothing if set to false
  return "" if !value
  # Otherwise pass input string to yes
  "yes #{value} | "
end