vagrant-vbguest-update 0.10.1.dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/CHANGELOG.md +209 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE +21 -0
  6. data/Rakefile +11 -0
  7. data/Readme.md +267 -0
  8. data/lib/vagrant-vbguest.rb +57 -0
  9. data/lib/vagrant-vbguest/command.rb +95 -0
  10. data/lib/vagrant-vbguest/config.rb +51 -0
  11. data/lib/vagrant-vbguest/core_ext/string/interpolate.rb +110 -0
  12. data/lib/vagrant-vbguest/download.rb +28 -0
  13. data/lib/vagrant-vbguest/errors.rb +18 -0
  14. data/lib/vagrant-vbguest/hosts/base.rb +118 -0
  15. data/lib/vagrant-vbguest/hosts/virtualbox.rb +103 -0
  16. data/lib/vagrant-vbguest/installer.rb +121 -0
  17. data/lib/vagrant-vbguest/installers/base.rb +201 -0
  18. data/lib/vagrant-vbguest/installers/debian.rb +40 -0
  19. data/lib/vagrant-vbguest/installers/linux.rb +158 -0
  20. data/lib/vagrant-vbguest/installers/redhat.rb +29 -0
  21. data/lib/vagrant-vbguest/installers/ubuntu.rb +44 -0
  22. data/lib/vagrant-vbguest/machine.rb +105 -0
  23. data/lib/vagrant-vbguest/middleware.rb +43 -0
  24. data/lib/vagrant-vbguest/rebootable.rb +39 -0
  25. data/lib/vagrant-vbguest/vagrant_compat.rb +21 -0
  26. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_0/command.rb +17 -0
  27. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_0/download.rb +51 -0
  28. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_0/rebootable.rb +23 -0
  29. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_0/vm_compatible.rb +31 -0
  30. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_1/command.rb +18 -0
  31. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_1/download.rb +1 -0
  32. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_1/rebootable.rb +33 -0
  33. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_1/vm_compatible.rb +31 -0
  34. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_2/command.rb +1 -0
  35. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_2/download.rb +18 -0
  36. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_2/rebootable.rb +1 -0
  37. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_2/vm_compatible.rb +15 -0
  38. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_3/command.rb +1 -0
  39. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_3/download.rb +1 -0
  40. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_3/rebootable.rb +1 -0
  41. data/lib/vagrant-vbguest/vagrant_compat/vagrant_1_3/vm_compatible.rb +1 -0
  42. data/lib/vagrant-vbguest/version.rb +3 -0
  43. data/lib/vagrant_init.rb +38 -0
  44. data/locales/en.yml +63 -0
  45. data/vagrant-vbguest.gemspec +30 -0
  46. metadata +161 -0
@@ -0,0 +1,158 @@
1
+ module VagrantVbguest
2
+ module Installers
3
+ # A basic Installer implementation for vanilla or
4
+ # unknown Linux based systems.
5
+ class Linux < Base
6
+
7
+ # A helper method to cache the result of {Vagrant::Guest::Base#distro_dispatch}
8
+ # which speeds up Installer detection runs a lot,
9
+ # when having lots of Linux based Installer classes
10
+ # to check.
11
+ #
12
+ # @see {Vagrant::Guest::Linux#distro_dispatch}
13
+ # @return [Symbol] One of `:debian`, `:ubuntu`, `:gentoo`, `:fedora`, `:redhat`, `:suse`, `:arch`
14
+ def self.distro(vm)
15
+ @@ditro ||= {}
16
+ @@ditro[ vm_id(vm) ] ||= distro_name vm
17
+ end
18
+
19
+ # Matches if the operating system name prints "Linux"
20
+ # Raises an Error if this class is beeing subclassed but
21
+ # this method was not overridden. This is considered an
22
+ # error because, subclassed Installers usually indicate
23
+ # a more specific distributen like 'ubuntu' or 'arch' and
24
+ # therefore should do a more specific check.
25
+ def self.match?(vm)
26
+ raise Error, :_key => :do_not_inherit_match_method if self != Linux
27
+ communicate_to(vm).test("uname | grep 'Linux'")
28
+ end
29
+
30
+ # defaults the temp path to "/tmp/VBoxGuestAdditions.iso" for all Linux based systems
31
+ def tmp_path
32
+ '/tmp/VBoxGuestAdditions.iso'
33
+ end
34
+
35
+ # defaults the mount point to "/mnt" for all Linux based systems
36
+ def mount_point
37
+ '/mnt'
38
+ end
39
+
40
+ # a generic way of installing GuestAdditions assuming all
41
+ # dependencies on the guest are installed
42
+ # @param [Hash] opts Optional options Hash wich meight get passed to {Vagrant::Communication::SSH#execute} and firends
43
+ # @yield [type, data] Takes a Block like {Vagrant::Communication::Base#execute} for realtime output of the command being executed
44
+ # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
45
+ # @yieldparam [String] data Data for the given output.
46
+ def install(opts=nil, &block)
47
+ env.ui.warn I18n.t("vagrant_vbguest.errors.installer.generic_linux_installer") if self.class == Linux
48
+ upload(iso_file)
49
+ mount_iso(opts, &block)
50
+ execute_installer(opts, &block)
51
+ unmount_iso(opts, &block)
52
+ end
53
+
54
+ # @param [Hash] opts Optional options Hash wich meight get passed to {Vagrant::Communication::SSH#execute} and firends
55
+ # @yield [type, data] Takes a Block like {Vagrant::Communication::Base#execute} for realtime output of the command being executed
56
+ # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
57
+ # @yieldparam [String] data Data for the given output.
58
+ def running?(opts=nil, &block)
59
+ opts = {
60
+ :sudo => true
61
+ }.merge(opts || {})
62
+ communicate.test('lsmod | grep vboxsf', opts, &block)
63
+ end
64
+
65
+ # This overrides {VagrantVbguest::Installers::Base#guest_version}
66
+ # to also query the `VBoxService` on the host system (if available)
67
+ # for it's version.
68
+ # In some scenarios the results of the VirtualBox driver and the
69
+ # additions installed on the host may differ. If this happens, we
70
+ # assume, that the host binaries are right and yield a warning message.
71
+ #
72
+ # @return [String] The version code of the VirtualBox Guest Additions
73
+ # available on the guest, or `nil` if none installed.
74
+ def guest_version(reload = false)
75
+ return @guest_version if @guest_version && !reload
76
+ driver_version = super
77
+
78
+ communicate.sudo('VBoxService --version', :error_check => false) do |type, data|
79
+ if (v = data.to_s.match(/^(\d+\.\d+.\d+)/)) && driver_version != v[1]
80
+ @env.ui.warn(I18n.t("vagrant_vbguest.guest_version_reports_differ", :driver => driver_version, :service => v[1]))
81
+ @guest_version = v[1]
82
+ end
83
+ end
84
+ @guest_version
85
+ end
86
+
87
+ # @param [Hash] opts Optional options Hash wich meight get passed to {Vagrant::Communication::SSH#execute} and firends
88
+ # @yield [type, data] Takes a Block like {Vagrant::Communication::Base#execute} for realtime output of the command being executed
89
+ # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
90
+ # @yieldparam [String] data Data for the given output.
91
+ def rebuild(opts=nil, &block)
92
+ communicate.sudo('/etc/init.d/vboxadd setup', opts, &block)
93
+ end
94
+
95
+ # @param [Hash] opts Optional options Hash wich meight get passed to {Vagrant::Communication::SSH#execute} and firends
96
+ # @yield [type, data] Takes a Block like {Vagrant::Communication::Base#execute} for realtime output of the command being executed
97
+ # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
98
+ # @yieldparam [String] data Data for the given output.
99
+ def start(opts=nil, &block)
100
+ opts = {:error_check => false}.merge(opts || {})
101
+ communicate.sudo('/etc/init.d/vboxadd start', opts, &block)
102
+ end
103
+
104
+
105
+ # A generic helper method to execute the installer.
106
+ # This also yields a installation warning to the user, and an error
107
+ # warning in the event that the installer returns a non-zero exit status.
108
+ #
109
+ # @param [Hash] opts Optional options Hash wich meight get passed to {Vagrant::Communication::SSH#execute} and firends
110
+ # @yield [type, data] Takes a Block like {Vagrant::Communication::Base#execute} for realtime output of the command being executed
111
+ # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
112
+ # @yieldparam [String] data Data for the given output.
113
+ def execute_installer(opts=nil, &block)
114
+ yield_installation_waring(installer)
115
+ opts = {:error_check => false}.merge(opts || {})
116
+ exit_status = communicate.sudo("#{installer} #{installer_arguments}", opts, &block)
117
+ yield_installation_error_warning(installer) unless exit_status == 0
118
+ exit_status
119
+ end
120
+
121
+ # The absolute path to the GuestAdditions installer script.
122
+ # The iso file has to be mounted on +mount_point+.
123
+ def installer
124
+ @installer ||= File.join(mount_point, 'VBoxLinuxAdditions.run')
125
+ end
126
+
127
+ # The arguments string, which gets passed to the installer script
128
+ def installer_arguments
129
+ @installer_arguments ||= Array(options[:installer_arguments]).join " "
130
+ end
131
+
132
+ # A generic helper method for mounting the GuestAdditions iso file
133
+ # on most linux system.
134
+ # Mounts the given uploaded file from +tmp_path+ on +mount_point+.
135
+ #
136
+ # @param [Hash] opts Optional options Hash wich meight get passed to {Vagrant::Communication::SSH#execute} and firends
137
+ # @yield [type, data] Takes a Block like {Vagrant::Communication::Base#execute} for realtime output of the command being executed
138
+ # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
139
+ # @yieldparam [String] data Data for the given output.
140
+ def mount_iso(opts=nil, &block)
141
+ communicate.sudo("mount #{tmp_path} -o loop #{mount_point}", opts, &block)
142
+ end
143
+
144
+ # A generic helper method for un-mounting the GuestAdditions iso file
145
+ # on most linux system
146
+ # Unmounts the +mount_point+.
147
+ #
148
+ # @param [Hash] opts Optional options Hash wich meight get passed to {Vagrant::Communication::SSH#execute} and firends
149
+ # @yield [type, data] Takes a Block like {Vagrant::Communication::Base#execute} for realtime output of the command being executed
150
+ # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
151
+ # @yieldparam [String] data Data for the given output.
152
+ def unmount_iso(opts=nil, &block)
153
+ communicate.sudo("umount #{mount_point}", opts, &block)
154
+ end
155
+ end
156
+ end
157
+ end
158
+ VagrantVbguest::Installer.register(VagrantVbguest::Installers::Linux, 2)
@@ -0,0 +1,29 @@
1
+ module VagrantVbguest
2
+ module Installers
3
+ class RedHat < Linux
4
+ # Scientific Linux (and probably CentOS) both show up as :redhat
5
+ # fortunately they're probably both similar enough to RHEL
6
+ # (RedHat Enterprise Linux) not to matter.
7
+ def self.match?(vm)
8
+ :redhat == self.distro(vm)
9
+ end
10
+
11
+ # Install missing deps and yield up to regular linux installation
12
+ def install(opts=nil, &block)
13
+ communicate.sudo(install_dependencies_cmd, opts, &block)
14
+ super
15
+ end
16
+
17
+ protected
18
+ def install_dependencies_cmd
19
+ "yum install -y #{dependencies}"
20
+ end
21
+
22
+ def dependencies
23
+ packages = ['kernel-devel-`uname -r`', 'gcc', 'make', 'perl', 'bzip2']
24
+ packages.join ' '
25
+ end
26
+ end
27
+ end
28
+ end
29
+ VagrantVbguest::Installer.register(VagrantVbguest::Installers::RedHat, 5)
@@ -0,0 +1,44 @@
1
+ module VagrantVbguest
2
+ module Installers
3
+ class Ubuntu < Debian
4
+
5
+ def self.match?(vm)
6
+ :ubuntu == self.distro(vm)
7
+ end
8
+
9
+ def install(opts=nil, &block)
10
+ if packaged_additions?
11
+ unload_packaged_additions(opts, &block)
12
+ remove_packaged_additions(opts, &block)
13
+ end
14
+ super
15
+ end
16
+
17
+ protected
18
+
19
+ def packaged_additions?
20
+ communicate.test("dpkg --list | grep virtualbox-guest")
21
+ end
22
+
23
+ def remove_packaged_additions(opts=nil, &block)
24
+ options = (opts || {}).merge(:error_check => false)
25
+ command = "apt-get -y -q purge virtualbox-guest-dkms virtualbox-guest-utils virtualbox-guest-x11"
26
+ communicate.sudo(command, options, &block)
27
+ end
28
+
29
+ def unload_packaged_additions(opts=nil, &block)
30
+ commands = [
31
+ "service virtualbox-guest-utils stop",
32
+ "umount -a -t vboxsf",
33
+ "rmmod vboxsf",
34
+ "rmmod vboxguest"
35
+ ]
36
+ command = "(" + commands.join("; sleep 1; ") + ")"
37
+ options = (opts || {}).merge(:error_check => false)
38
+ communicate.sudo(command, options, &block)
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ VagrantVbguest::Installer.register(VagrantVbguest::Installers::Ubuntu, 5)
@@ -0,0 +1,105 @@
1
+ module VagrantVbguest
2
+ class Machine
3
+
4
+ require 'micromachine'
5
+
6
+ attr_reader :installer, :env, :vm, :options
7
+
8
+ def initialize vm, options
9
+ @vm = vm
10
+ @env = vm.env
11
+ @options = options
12
+
13
+ @logger = Log4r::Logger.new("vagrant::plugins::vbguest-machine")
14
+ @logger.debug("initialize vbguest machine for VM '#{vm.name}' (#{vm.to_s})")
15
+
16
+ @installer = Installer.new vm, options
17
+ end
18
+
19
+ def run
20
+ current_state = state
21
+ runlist = steps(current_state)
22
+ @logger.debug("Runlist for state #{current_state} is: #{runlist}")
23
+ while (command = runlist.shift)
24
+ @logger.debug("Running command #{command} from runlist")
25
+ if !self.send(command)
26
+ env.ui.error('vagrant_vbguest.machine_loop_guard', :command => command, :state => current_state)
27
+ return false
28
+ end
29
+ return run if current_state != state
30
+ end
31
+ true
32
+ end
33
+
34
+ def install
35
+ return env.ui.warn(I18n.t("vagrant_vbguest.skipped_installation")) if options[:no_install] && !options[:force]
36
+ guest_additions_state.trigger :install
37
+ end
38
+
39
+ def rebuild
40
+ return env.ui.warn(I18n.t("vagrant_vbguest.skipped_rebuild")) if options[:no_install] && !options[:force]
41
+ guest_additions_state.trigger :rebuild
42
+ end
43
+
44
+ def start
45
+ guest_additions_state.trigger :start
46
+ end
47
+
48
+ def installation_ran?; guest_additions_state == :installed end
49
+ def started?; guest_additions_state == :started end
50
+ def rebuilt?; guest_additions_state == :rebuilt end
51
+
52
+ def reboot; box_state.trigger :reboot end
53
+ def reboot?; box_state.state == :rebooted end
54
+
55
+ def steps(state)
56
+ case state
57
+ when :clean, :unmatched
58
+ [:install]
59
+ when :not_running
60
+ installation_ran? ? [:reboot] : [:start, :rebuild, :reboot]
61
+ else
62
+ []
63
+ end
64
+ end
65
+
66
+ def state
67
+ guest_version = installer.guest_version(true)
68
+ host_version = installer.host_version
69
+ running = installer.running?
70
+ @logger.debug("Current states for VM '#{vm.name}' are : guest_version=#{guest_version} : host_version=#{host_version} : running=#{running}")
71
+
72
+ return :clean if !guest_version
73
+ return :unmatched if host_version != guest_version
74
+ return :not_running if !running
75
+ return :ok
76
+ end
77
+
78
+ def info
79
+ {
80
+ :host_version => installer.host_version,
81
+ :guest_version => installer.guest_version
82
+ }
83
+ end
84
+
85
+ protected
86
+
87
+ def guest_additions_state
88
+ @guest_additions_state ||= MicroMachine.new(:pending).tap { |m|
89
+ m.when :install, :pending => :installed
90
+ m.when :start, :pending => :started
91
+ m.when :rebuild, :pending => :rebuilt, :started => :rebuilt
92
+
93
+ m.on(:installed) { installer.install }
94
+ m.on(:started) { installer.start }
95
+ m.on(:rebuilt) { installer.rebuild }
96
+ }
97
+ end
98
+
99
+ def box_state
100
+ @box_state ||= MicroMachine.new(:first_boot).tap { |m|
101
+ m.when :reboot, :first_boot => :rebooted
102
+ }
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,43 @@
1
+ module VagrantVbguest
2
+
3
+ # A Vagrant middleware which checks the installed VirtualBox Guest
4
+ # Additions to match the installed VirtualBox installation on the
5
+ # host system.
6
+
7
+ class Middleware
8
+ include VagrantVbguest::Helpers::Rebootable
9
+
10
+ def initialize(app, env)
11
+ @app = app
12
+ @env = env
13
+ end
14
+
15
+ def call(env)
16
+ @env = env
17
+ vm = env[:vm] || env[:machine]
18
+
19
+ options = override_config(vm.config.vbguest.to_hash).freeze
20
+
21
+ if options[:auto_update]
22
+ machine = VagrantVbguest::Machine.new vm, options
23
+ status = machine.state
24
+ vm.env.ui.send((:ok == status ? :success : :warn), I18n.t("vagrant_vbguest.status.#{status}", machine.info))
25
+ machine.run
26
+ reboot(vm, options) if machine.reboot?
27
+ end
28
+ rescue VagrantVbguest::Installer::NoInstallerFoundError => e
29
+ vm.env.ui.error e.message
30
+ ensure
31
+ @app.call(env)
32
+ end
33
+
34
+ def override_config(opts)
35
+ if opts[:auto_reboot] && Vagrant::VERSION.between?("1.1.0", "1.1.5") && Vagrant::VERSION != "1.1.4"
36
+ @env[:ui].warn I18n.t("vagrant_vbguest.vagrant_11_reload_issues")
37
+ opts.merge!({:auto_reboot => false})
38
+ end
39
+ opts
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,39 @@
1
+ module VagrantVbguest
2
+ module Helpers
3
+
4
+ module Rebootable
5
+ include VmCompatible
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ @@rebooted = {}
11
+
12
+ def rebooted?(vm)
13
+ !!@@rebooted[ self.class.vm_id(vm) ]
14
+ end
15
+
16
+ def reboot?(vm, options)
17
+ if rebooted?(vm)
18
+ vm.env.ui.error(I18n.t("vagrant_vbguest.restart_loop_guard_activated"))
19
+ false
20
+ elsif options[:auto_reboot]
21
+ vm.env.ui.warn(I18n.t("vagrant_vbguest.restart_vm"))
22
+ @@rebooted[ self.class.vm_id(vm) ] = true
23
+ else
24
+ vm.env.ui.warn(I18n.t("vagrant_vbguest.suggest_restart", :name => vm.name))
25
+ false
26
+ end
27
+ end
28
+
29
+ def reboot(vm, options)
30
+ raise NotImplementedError
31
+ end
32
+
33
+ def reboot!(vm, options)
34
+ raise NotImplementedError
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ vagrant_version = Gem::Version.new(Vagrant::VERSION)
2
+ supported_version = {
3
+ "< 1.1.0" => "1_0",
4
+ "~> 1.1.0" => "1_1",
5
+ "~> 1.2.0" => "1_2",
6
+ "~> 1.3.0" => "1_3",
7
+ }
8
+ compat_version = supported_version.find { |requirement, version|
9
+ Gem::Requirement.new(requirement).satisfied_by?(vagrant_version)
10
+ }
11
+
12
+ if compat_version
13
+ compat_version = compat_version[1]
14
+ else
15
+ # @TODO: yield warning
16
+ compat_version = supported_version.to_a.last[1]
17
+ end
18
+
19
+ %w{vm_compatible rebootable command download}.each do |r|
20
+ require File.expand_path("../vagrant_compat/vagrant_#{compat_version}/#{r}", __FILE__)
21
+ end
@@ -0,0 +1,17 @@
1
+ require 'vagrant-vbguest/command'
2
+ require 'vagrant/command/start_mixins'
3
+
4
+ module VagrantVbguest
5
+
6
+ class Command < Vagrant::Command::Base
7
+ include CommandCommons
8
+ include Vagrant::Command::StartMixins
9
+
10
+ def check_runable_on(vm)
11
+ raise Vagrant::Errors::VMNotCreatedError if !vm.created?
12
+ raise Vagrant::Errors::VMInaccessible if !vm.state == :inaccessible
13
+ raise Vagrant::Errors::VMNotRunningError if vm.state != :running
14
+ end
15
+ end
16
+
17
+ end