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_options, #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



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

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.



216
217
218
219
220
221
222
# File 'lib/vagrant-vbguest/installers/linux.rb', line 216

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.



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

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.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/vagrant-vbguest/installers/linux.rb', line 92

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.



226
227
228
# File 'lib/vagrant-vbguest/installers/linux.rb', line 226

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

#installer_argumentsObject

The arguments string, which gets passed to the installer script



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

def installer_arguments
  @installer_arguments ||= Array(options[:installer_arguments]).join " "
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.



254
255
256
257
# File 'lib/vagrant-vbguest/installers/linux.rb', line 254

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)
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)


137
138
139
# File 'lib/vagrant-vbguest/installers/linux.rb', line 137

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.



112
113
114
# File 'lib/vagrant-vbguest/installers/linux.rb', line 112

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

def running?(opts=nil, &block)
  opts = {
    :sudo => true
  }.merge(opts || {})
  communicate.test('grep -qE "^vboxguest\b.*vboxsf\b" /proc/modules', opts, &block)
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.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/vagrant-vbguest/installers/linux.rb', line 120

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.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/vagrant-vbguest/installers/linux.rb', line 152

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.



267
268
269
270
# File 'lib/vagrant-vbguest/installers/linux.rb', line 267

def unmount_iso(opts=nil, &block)
  env.ui.info(I18n.t("vagrant_vbguest.unmounting_iso", :mount_point => mount_point))
  communicate.sudo("umount #{mount_point}", opts, &block)
end

#vboxadd_tools_available?Boolean

Returns:

  • (Boolean)


141
142
143
# File 'lib/vagrant-vbguest/installers/linux.rb', line 141

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



236
237
238
239
240
241
242
243
244
# File 'lib/vagrant-vbguest/installers/linux.rb', line 236

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