vagrant-vbguest-update 0.10.1.dev

Sign up to get free protection for your applications and to get access to all the features.
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,57 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant VBGuest plugin must be run within Vagrant."
5
+ end
6
+
7
+ # Add our custom translations to the load path
8
+ I18n.load_path << File.expand_path("../../locales/en.yml", __FILE__)
9
+ I18n.reload!
10
+
11
+ require "vagrant-vbguest/errors"
12
+ require 'vagrant-vbguest/vagrant_compat'
13
+
14
+ require 'vagrant-vbguest/machine'
15
+
16
+ require 'vagrant-vbguest/hosts/base'
17
+ require 'vagrant-vbguest/hosts/virtualbox'
18
+
19
+ require 'vagrant-vbguest/installer'
20
+ require 'vagrant-vbguest/installers/base'
21
+ require 'vagrant-vbguest/installers/linux'
22
+ require 'vagrant-vbguest/installers/debian'
23
+ require 'vagrant-vbguest/installers/ubuntu'
24
+ require 'vagrant-vbguest/installers/redhat'
25
+
26
+ require 'vagrant-vbguest/middleware'
27
+
28
+ module VagrantVbguest
29
+
30
+ class Plugin < Vagrant.plugin("2")
31
+
32
+ name "vagrant-vbguest"
33
+ description <<-DESC
34
+ Provides automatic and/or manual management of the
35
+ VirtualBox Guest Additions inside the Vagrant environment.
36
+ DESC
37
+
38
+ config('vbguest') do
39
+ require File.expand_path("../vagrant-vbguest/config", __FILE__)
40
+ Config
41
+ end
42
+
43
+ command('vbguest') do
44
+ Command
45
+ end
46
+
47
+ # hook after anything that boots:
48
+ # that's all middlewares which will run the buildin "VM::Boot" action
49
+ action_hook('vbguest') do |hook|
50
+ if defined?(VagrantPlugins::ProviderVirtualBox::Action::CheckGuestAdditions)
51
+ hook.before(VagrantPlugins::ProviderVirtualBox::Action::CheckGuestAdditions, VagrantVbguest::Middleware)
52
+ else
53
+ hook.after(VagrantPlugins::ProviderVirtualBox::Action::Boot, VagrantVbguest::Middleware)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,95 @@
1
+ require 'optparse'
2
+
3
+ module VagrantVbguest
4
+
5
+ module CommandCommons
6
+ include VagrantVbguest::Helpers::Rebootable
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ # Runs the vbguest installer on the VMs that are represented
12
+ # by this environment.
13
+ def execute
14
+ options = {
15
+ :_method => :run,
16
+ :_rebootable => true,
17
+ :auto_reboot => false
18
+ }
19
+ opts = OptionParser.new do |opts|
20
+ opts.banner = "Usage: vagrant vbguest [vm-name] [--do start|rebuild|install] [--status] [-f|--force] [-b|--auto-reboot] [-R|--no-remote] [--iso VBoxGuestAdditions.iso]"
21
+ opts.separator ""
22
+
23
+ opts.on("--do COMMAND", [:start, :rebuild, :install], "Manually `start`, `rebuild` or `install` GuestAdditions.") do |command|
24
+ options[:_method] = command
25
+ options[:force] = true
26
+ end
27
+
28
+ opts.on("--status", "Print current GuestAdditions status and exit.") do
29
+ options[:_method] = :status
30
+ options[:_rebootable] = false
31
+ end
32
+
33
+ opts.on("-f", "--force", "Whether to force the installation. (Implied by --do start|rebuild|install)") do
34
+ options[:force] = true
35
+ end
36
+
37
+ opts.on("--auto-reboot", "-b", "Allow rebooting the VM after installation. (when GuestAdditions won't start)") do
38
+ options[:auto_reboot] = true
39
+ end
40
+
41
+ opts.on("--no-remote", "-R", "Do not attempt do download the iso file from a webserver") do
42
+ options[:no_remote] = true
43
+ end
44
+
45
+ opts.on("--iso file_or_uri", "Full path or URI to the VBoxGuestAdditions.iso") do |file_or_uri|
46
+ options[:iso_path] = file_or_uri
47
+ end
48
+
49
+ build_start_options(opts, options)
50
+ end
51
+
52
+
53
+ argv = parse_options(opts)
54
+ return if !argv
55
+
56
+ if argv.empty?
57
+ with_target_vms(nil) { |vm| execute_on_vm(vm, options) }
58
+ else
59
+ argv.each do |vm_name|
60
+ with_target_vms(vm_name) { |vm| execute_on_vm(vm, options) }
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ protected
67
+
68
+ # Executes a command on a specific VM.
69
+ def execute_on_vm(vm, options)
70
+ check_runable_on(vm)
71
+
72
+ options = options.clone
73
+ _method = options.delete(:_method)
74
+ _rebootable = options.delete(:_rebootable)
75
+
76
+ options = vm.config.vbguest.to_hash.merge(options)
77
+ machine = VagrantVbguest::Machine.new(vm, options)
78
+ status = machine.state
79
+ vm.env.ui.send((:ok == status ? :success : :warn), I18n.t("vagrant_vbguest.status.#{status}", machine.info))
80
+
81
+ if _method != :status
82
+ machine.send(_method)
83
+ end
84
+
85
+ reboot!(vm, options) if _rebootable && machine.reboot?
86
+ rescue VagrantVbguest::Installer::NoInstallerFoundError => e
87
+ vm.env.ui.error e.message
88
+ end
89
+
90
+ def check_runable_on(vm)
91
+ raise NotImplementedError
92
+ end
93
+ end
94
+
95
+ end
@@ -0,0 +1,51 @@
1
+ module VagrantVbguest
2
+
3
+ class Config <( Vagrant::VERSION < "1.1.0" ? Vagrant::Config::Base : Vagrant.plugin("2", :config) )
4
+
5
+ module Attributes
6
+ attr_accessor :iso_path, :auto_update, :auto_reboot, :no_install, :no_remote, :installer, :installer_arguments
7
+ end
8
+
9
+ class << self
10
+ include Attributes
11
+
12
+ def auto_update; @auto_update.nil? ? true : @auto_update end
13
+ def auto_reboot; @auto_reboot.nil? ? true : @auto_reboot end
14
+ def no_install; @no_install.nil? ? false : @no_install end
15
+ def no_remote; @no_remote.nil? ? false : @no_remote end
16
+ def installer_arguments; @installer_arguments.nil? ? '--nox11' : @installer_arguments end
17
+
18
+ def iso_path
19
+ return nil if !@iso_path || @iso_path == :auto
20
+ @iso_path
21
+ end
22
+ end
23
+
24
+ include Attributes
25
+
26
+ def auto_update; @auto_update.nil? ? self.class.auto_update : @auto_update end
27
+ def auto_reboot; @auto_reboot.nil? ? self.class.auto_reboot : @auto_reboot end
28
+ def no_install; @no_install.nil? ? self.class.no_install : @no_install end
29
+ def no_remote; @no_remote.nil? ? self.class.no_remote : @no_remote end
30
+ def installer_arguments; @installer_arguments.nil? ? self.class.installer_arguments : @installer_arguments end
31
+
32
+ def iso_path
33
+ return self.class.iso_path if !@iso_path || @iso_path == :auto
34
+ @iso_path
35
+ end
36
+
37
+ # explicit hash, to get symbols in hash keys
38
+ def to_hash
39
+ {
40
+ :installer => installer,
41
+ :installer_arguments => installer_arguments,
42
+ :iso_path => iso_path,
43
+ :auto_update => auto_update,
44
+ :auto_reboot => auto_reboot,
45
+ :no_install => no_install,
46
+ :no_remote => no_remote
47
+ }
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,110 @@
1
+ # This backports the Ruby 1.9 String interpolation syntax to Ruby 1.8.
2
+ #
3
+ # This file is a copy from I18n
4
+ # https://github.com/mattetti/i18n/blob/master/lib/i18n/core_ext/string/interpolate.rb
5
+ # Copyright (c) 2008 The Ruby I18n team
6
+ # It's copied here for the resons given below:
7
+ #
8
+ # This backport has been shipped with I18n for a number of versions. Meanwhile
9
+ # Rails has started to rely on it and we are going to move it to ActiveSupport.
10
+ # See https://rails.lighthouseapp.com/projects/8994/tickets/6013-move-19-string-interpolation-syntax-backport-from-i18n-to-activesupport
11
+ #
12
+ # Once the above patch has been applied to Rails the following code will be
13
+ # removed from I18n.
14
+
15
+ =begin
16
+ heavily based on Masao Mutoh's gettext String interpolation extension
17
+ http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
18
+ Copyright (C) 2005-2009 Masao Mutoh
19
+ You may redistribute it and/or modify it under the same license terms as Ruby.
20
+ =end
21
+
22
+ begin
23
+ raise ArgumentError if ("a %{x}" % {:x=>'b'}) != 'a b'
24
+ rescue ArgumentError
25
+ # KeyError is raised by String#% when the string contains a named placeholder
26
+ # that is not contained in the given arguments hash. Ruby 1.9 includes and
27
+ # raises this exception natively. We define it to mimic Ruby 1.9's behaviour
28
+ # in Ruby 1.8.x
29
+ class KeyError < IndexError
30
+ def initialize(message = nil)
31
+ super(message || "key not found")
32
+ end
33
+ end unless defined?(KeyError)
34
+
35
+ # Extension for String class. This feature is included in Ruby 1.9 or later but not occur TypeError.
36
+ #
37
+ # String#% method which accept "named argument". The translator can know
38
+ # the meaning of the msgids using "named argument" instead of %s/%d style.
39
+ class String
40
+ # For older ruby versions, such as ruby-1.8.5
41
+ alias :bytesize :size unless instance_methods.find {|m| m.to_s == 'bytesize'}
42
+ alias :interpolate_without_ruby_19_syntax :% # :nodoc:
43
+
44
+ INTERPOLATION_PATTERN = Regexp.union(
45
+ /%\{(\w+)\}/, # matches placeholders like "%{foo}"
46
+ /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%<foo>.d"
47
+ )
48
+
49
+ INTERPOLATION_PATTERN_WITH_ESCAPE = Regexp.union(
50
+ /%%/,
51
+ INTERPOLATION_PATTERN
52
+ )
53
+
54
+ # % uses self (i.e. the String) as a format specification and returns the
55
+ # result of applying it to the given arguments. In other words it interpolates
56
+ # the given arguments to the string according to the formats the string
57
+ # defines.
58
+ #
59
+ # There are three ways to use it:
60
+ #
61
+ # * Using a single argument or Array of arguments.
62
+ #
63
+ # This is the default behaviour of the String class. See Kernel#sprintf for
64
+ # more details about the format string.
65
+ #
66
+ # Example:
67
+ #
68
+ # "%d %s" % [1, "message"]
69
+ # # => "1 message"
70
+ #
71
+ # * Using a Hash as an argument and unformatted, named placeholders.
72
+ #
73
+ # When you pass a Hash as an argument and specify placeholders with %{foo}
74
+ # it will interpret the hash values as named arguments.
75
+ #
76
+ # Example:
77
+ #
78
+ # "%{firstname}, %{lastname}" % {:firstname => "Masao", :lastname => "Mutoh"}
79
+ # # => "Masao Mutoh"
80
+ #
81
+ # * Using a Hash as an argument and formatted, named placeholders.
82
+ #
83
+ # When you pass a Hash as an argument and specify placeholders with %<foo>d
84
+ # it will interpret the hash values as named arguments and format the value
85
+ # according to the formatting instruction appended to the closing >.
86
+ #
87
+ # Example:
88
+ #
89
+ # "%<integer>d, %<float>.1f" % { :integer => 10, :float => 43.4 }
90
+ # # => "10, 43.3"
91
+ def %(args)
92
+ if args.kind_of?(Hash)
93
+ dup.gsub(INTERPOLATION_PATTERN_WITH_ESCAPE) do |match|
94
+ if match == '%%'
95
+ '%'
96
+ else
97
+ key = ($1 || $2).to_sym
98
+ raise KeyError unless args.has_key?(key)
99
+ $3 ? sprintf("%#{$3}", args[key]) : args[key]
100
+ end
101
+ end
102
+ elsif self =~ INTERPOLATION_PATTERN
103
+ raise ArgumentError.new('one hash required')
104
+ else
105
+ result = gsub(/%([{<])/, '%%\1')
106
+ result.send :'interpolate_without_ruby_19_syntax', args
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,28 @@
1
+ module VagrantVbguest
2
+
3
+ class DownloadBase
4
+ attr_reader :source, :destination, :downloader
5
+
6
+ def initialize(source, destination, options=nil)
7
+ @downloader = nil
8
+ @source = source
9
+ @destination = destination
10
+ if File.directory?(destination)
11
+ @destination = File.join(destination, "vbguest_download_#{Time.now.to_i.to_s}")
12
+ end
13
+ @ui = options[:ui]
14
+ end
15
+
16
+ def download!
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def cleanup
21
+ if destination && File.exist?(destination)
22
+ @ui.info I18n.t("vagrant_vbguest.download.cleaning")
23
+ File.unlink(destination)
24
+ end
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantVbguest
2
+
3
+ class VbguestError < Vagrant::Errors::VagrantError
4
+ def error_namespace; "vagrant_vbguest.errors"; end
5
+ end
6
+
7
+ class IsoPathAutodetectionError < VagrantVbguest::VbguestError
8
+ error_key :autodetect_iso_path
9
+ end
10
+
11
+ class DownloadingDisabledError < VagrantVbguest::VbguestError
12
+ error_key :downloading_disabled
13
+ end
14
+
15
+ class NoVirtualBoxMachineError < VagrantVbguest::VbguestError
16
+ error_key :no_virtualbox_machine
17
+ end
18
+ end
@@ -0,0 +1,118 @@
1
+ require 'uri'
2
+
3
+ module VagrantVbguest
4
+ module Hosts
5
+ class Base
6
+ include VagrantVbguest::Helpers::VmCompatible
7
+
8
+ attr_reader :env, :vm, :options
9
+
10
+ def initialize(vm, options=nil)
11
+ @vm = vm
12
+ @env = vm.env
13
+ @options = options
14
+ end
15
+
16
+ # Determinates the host's version
17
+ #
18
+ # @return [String] The version code of the *host*'s virtualisation
19
+ def version
20
+ @version ||= driver.version
21
+ end
22
+
23
+
24
+ # Additions-file-detection-magig.
25
+ #
26
+ # Detection runs in those stages:
27
+ # 1. Uses the +iso_path+ config option, if present and not set to +:auto+
28
+ # 2. Look out for a local additions file
29
+ # 3. Use the default web URI
30
+ #
31
+ # If the detected or configured path is not a local file and remote downloads
32
+ # are allowed (the config option +:no_remote+ is NOT set) it will try to
33
+ # download that file into a temp file using Vagrants Downloaders.
34
+ # If remote downloads are prohibited (the config option +:no_remote+ IS set)
35
+ # a +VagrantVbguest::IsoPathAutodetectionError+ will be thrown
36
+ #
37
+ # @return [String] A absolute path to the GuestAdditions iso file.
38
+ # This might be a temp-file, e.g. when downloaded from web.
39
+ def additions_file
40
+ return @additions_file if @additions_file
41
+
42
+ path = options[:iso_path]
43
+ if !path || path.empty? || path == :auto
44
+ path = local_path
45
+ path = web_path if !options[:no_remote] && !path
46
+ end
47
+ raise VagrantVbguest::IsoPathAutodetectionError if !path || path.empty?
48
+
49
+ path = versionize(path)
50
+
51
+ if file_match? path
52
+ @additions_file = path
53
+ else
54
+ # :TODO: This will also raise, if the iso_url points to an invalid local path
55
+ raise VagrantVbguest::DownloadingDisabledError.new(:from => path) if options[:no_remote]
56
+ @additions_file = download path
57
+ end
58
+ end
59
+
60
+ # If needed, remove downloaded temp file
61
+ def cleanup
62
+ @download.cleanup if @download
63
+ end
64
+
65
+ protected
66
+
67
+ # fix bug when the vagrant version is higher than 1.2, by moving method Vagrant::Vagrant::File.match? here
68
+ def file_match?(uri)
69
+ extracted = ::URI.extract(uri, "file")
70
+
71
+ return true if extracted && extracted.include?(uri)
72
+
73
+ return ::File.file?(::File.expand_path(uri))
74
+ end
75
+
76
+ # Default web URI, where "additions file" can be downloaded.
77
+ #
78
+ # @return [String] A URI template containing the versions placeholder.
79
+ def web_path
80
+ raise NotImplementedError
81
+ end
82
+
83
+ # Finds the "additions file" on the host system.
84
+ # Returns +nil+ if none found.
85
+ #
86
+ # @return [String] Absolute path to the local "additions file", or +nil+ if not found.
87
+ def local_path
88
+ raise NotImplementedError
89
+ end
90
+
91
+ # replaces the veriosn placeholder with the additions
92
+ # version string
93
+ #
94
+ # @param [String] A path or URL (or any other String)
95
+ #
96
+ # @retrun [String] A copy of the passed string, with verision
97
+ # placeholder replaced
98
+ def versionize(path)
99
+ path % {:version => version}
100
+ end
101
+
102
+ # Kicks off +VagrantVbguest::Download+ to download the additions file
103
+ # into a temp file.
104
+ #
105
+ # To remove the created tempfile call +cleanup+
106
+ #
107
+ # @param [String] The path or URI to download
108
+ #
109
+ # @return [String] The path to the downloaded file
110
+ def download(path)
111
+ @download = VagrantVbguest::Download.new(path, @env.tmp_path, :ui => @env.ui)
112
+ @download.download!
113
+ @download.destination
114
+ end
115
+
116
+ end
117
+ end
118
+ end