vagrant-mount 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rbenv-gemsets +1 -0
  4. data/.rspec +1 -0
  5. data/Gemfile +72 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +2 -0
  8. data/Rakefile +31 -0
  9. data/lib/vagrant-mount/actions/providers/virtualbox/action/message_not_mounted.rb +16 -0
  10. data/lib/vagrant-mount/actions/providers/virtualbox/action/message_not_unmounted.rb +16 -0
  11. data/lib/vagrant-mount/actions/providers/virtualbox/action/mount.rb +19 -0
  12. data/lib/vagrant-mount/actions/providers/virtualbox/action/unmount.rb +28 -0
  13. data/lib/vagrant-mount/actions/providers/virtualbox/action.rb +48 -0
  14. data/lib/vagrant-mount/actions/providers/virtualbox/driver/base.rb +155 -0
  15. data/lib/vagrant-mount/actions/providers/virtualbox/driver/meta.rb +9 -0
  16. data/lib/vagrant-mount/actions/providers/virtualbox/driver.rb +2 -0
  17. data/lib/vagrant-mount/actions/providers/vmware-fusion/action/message_not_mounted.rb +16 -0
  18. data/lib/vagrant-mount/actions/providers/vmware-fusion/action/message_not_unmounted.rb +16 -0
  19. data/lib/vagrant-mount/actions/providers/vmware-fusion/action/mount.rb +19 -0
  20. data/lib/vagrant-mount/actions/providers/vmware-fusion/action/unmount.rb +27 -0
  21. data/lib/vagrant-mount/actions/providers/vmware-fusion/action.rb +47 -0
  22. data/lib/vagrant-mount/actions/providers/vmware-fusion/driver/base.rb +84 -0
  23. data/lib/vagrant-mount/actions/providers/vmware-fusion/driver.rb +1 -0
  24. data/lib/vagrant-mount/commands/mount.rb +39 -0
  25. data/lib/vagrant-mount/commands/unmount.rb +39 -0
  26. data/lib/vagrant-mount/plugin.rb +78 -0
  27. data/lib/vagrant-mount/version.rb +5 -0
  28. data/lib/vagrant-mount.rb +18 -0
  29. data/locales/en.yml +26 -0
  30. data/spec/Vagrantfile +27 -0
  31. data/spec/command_spec.rb +28 -0
  32. data/spec/dummy.iso +0 -0
  33. data/spec/helpers/isolated_environment.rb +52 -0
  34. data/vagrant-mount.gemspec +28 -0
  35. metadata +138 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 656e36f4eda550bc886cd4ffc1491e7b014e47dc
4
+ data.tar.gz: 47c9ebc0ae2a0060aea61a82abddd39b1c55afea
5
+ SHA512:
6
+ metadata.gz: e1995672d620827690a0f8b917c70f5d311820ab9e71d676fba566ffece9d2b3df2c1d2876bb52ed43f77fcfd6f7e43852f97b73c40efa13811dc20741e5593f
7
+ data.tar.gz: a45c015231cff289e972136212c6fffe1384ebae4c93ac61a03736ef6b3abb7e1a7e50609276a3ad2eb459b52b0fba142c48de4a836210ba4aaab25cbb3461af
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ .bundle/
2
+ .yardoc
3
+ Gemfile.lock
4
+ _yardoc/
5
+ coverage/
6
+ doc/
7
+ pkg/
8
+ spec/reports/
9
+ tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .vagrant/
16
+ .gems/
17
+ log/
data/.rbenv-gemsets ADDED
@@ -0,0 +1 @@
1
+ .gems
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format documentation
data/Gemfile ADDED
@@ -0,0 +1,72 @@
1
+ source 'http://rubygems.org'
2
+
3
+ def which(command, *additional_paths)
4
+ extensions = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
5
+ ENV['PATH'].split(File::PATH_SEPARATOR).push(*additional_paths).each do |path|
6
+ extensions.each do |extension|
7
+ filepath = File.join(path, "#{command}#{extension}")
8
+ return filepath if File.executable?(filepath) && !File.directory?(filepath)
9
+ end
10
+ end
11
+ return nil
12
+ end
13
+
14
+ def has_vmware_fusion?
15
+ return ! which('vmrun', '/Applications/VMware Fusion.app/Contents/Library').nil?
16
+ end
17
+
18
+ vagrant_locations = %w{ /Applications/Vagrant/embedded /opt/vagrant/embedded C:/HashiCorp/Vagrant/embedded }
19
+ vagrant_location = vagrant_locations.find {|location| File.directory? location }
20
+
21
+ if vagrant_location
22
+ ENV['VAGRANT_INSTALLER_EMBEDDED_DIR'] = vagrant_location
23
+ puts "Using vagrant from #{vagrant_location}" if $DEBUG
24
+ else
25
+ STDERR.puts 'Could not find an official install of vagrant! The RubyEncoder libraries will not work.'
26
+ exit 1
27
+ end
28
+
29
+ puts "We can use VMWare Fusion" if has_vmware_fusion? && $DEBUG
30
+
31
+ group :development do
32
+ gem 'winrm', '~> 1.1.3'
33
+ gem 'vagrant', github: 'mitchellh/vagrant', tag: 'v1.7.2'
34
+ gem 'rake'
35
+
36
+ if has_vmware_fusion?
37
+ require 'fileutils'
38
+
39
+ begin
40
+ STDERR.puts "Loading gem vagrant-vmware-fusion" if $DEBUG
41
+ gem 'vagrant-vmware-fusion', source: 'http://gems.hashicorp.com'
42
+ STDERR.puts "Finding where gem vagrant-vmware-fusion is installed" if $DEBUG
43
+ fusion_location = Gem::Specification.find_by_name('vagrant-vmware-fusion').gem_dir
44
+ puts "VMWare fusion gem is in #{fusion_location}" if $DEBUG
45
+
46
+ gem 'rgloader'
47
+ unless Dir.exists? File.join(fusion_location, 'rgloader')
48
+ STDERR.puts "Linking local 'rgloader' file to embedded installer" if $DEBUG
49
+ FileUtils.ln_s(
50
+ File.join(ENV['VAGRANT_INSTALLER_EMBEDDED_DIR'], 'rgloader'),
51
+ File.join(fusion_location, 'rgloader')
52
+ )
53
+ end
54
+
55
+ unless File.symlink?(File.join(fusion_location, 'license-vagrant-vmware-fusion.lic'))
56
+ STDERR.puts "Linking your license file for vmware plugin" if $DEBUG
57
+ vagrant_home = ENV["VAGRANT_HOME"] || File.join(ENV['HOME'], '.vagrant.d')
58
+ FileUtils.ln_s(
59
+ File.join(vagrant_home, 'license-vagrant-vmware-fusion.lic'),
60
+ File.join(fusion_location, 'license-vagrant-vmware-fusion.lic')
61
+ )
62
+ end
63
+ rescue Gem::LoadError
64
+ STDERR.puts "Cannot load Vagrant VMWare plugin. #{$!}"
65
+ end
66
+ end
67
+ end
68
+
69
+ group :plugins do
70
+ gem 'vagrant-vmware-fusion', source: 'http://gems.hashicorp.com' if has_vmware_fusion?
71
+ gemspec
72
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Gildas Cherruel
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # vagrant-mount
2
+ Mounts ISO files in Virtual Machines for Vagrant
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'bundler/gem_tasks'
4
+ require 'yard'
5
+ require 'rspec/core/rake_task'
6
+
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the directory of this file
11
+ Dir.chdir(File.expand_path("../", __FILE__))
12
+
13
+ # Tasks to help with gem creation and publishing
14
+ Bundler::GemHelper.install_tasks
15
+
16
+ # Test tasks with RSpec
17
+ RSpec::Core::RakeTask.new
18
+
19
+ # Documentation tasks
20
+ YARD::Rake::YardocTask.new do |t|
21
+ t.files = ['lib/**/*.rb']
22
+ end
23
+
24
+ # Build the ctags fo vim
25
+ desc "Builds the tags"
26
+ task :ctags do
27
+ %x[ git ls-files | ctags --tag-relative --sort=no --exclude=.idea -L - -f ".git/tags" ]
28
+ end
29
+
30
+ # By default we test the gem
31
+ task :default => 'spec'
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module ProviderVirtualBox
3
+ module Action
4
+ class MessageNotMounted
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t('vagrant_mount.errors.vm.mount.not_mounted', mount: env[:mount_point]))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module ProviderVirtualBox
3
+ module Action
4
+ class MessageNotUnmounted
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t('vagrant_mount.errors.vm.unmount.not_unmounted', mount: env[:mount_point]))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module VagrantPlugins
2
+ module ProviderVirtualBox
3
+ module Action
4
+ class Mount
5
+ def initialize(app, env)
6
+ @app = app
7
+ @env = env
8
+ end
9
+
10
+ def call(env)
11
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.mount.mounting', mount: env[:mount_point]))
12
+ env[:result] = env[:machine].provider.driver.mount(env[:mount_point])
13
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.mount.mounted', mount: env[:mount_point]))
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module VagrantPlugins
3
+ module ProviderVirtualBox
4
+ module Action
5
+ class Unmount
6
+ def initialize(app, env)
7
+ @app = app
8
+ @env = env
9
+ end
10
+
11
+ def call(env)
12
+ if env[:mount_point]
13
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.unmount.unmounting', mount: env[:mount_point]))
14
+ else
15
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.unmount.unmounting_all'))
16
+ end
17
+ env[:result] = env[:machine].provider.driver.unmount(env[:mount_point], env[:remove_device])
18
+ if env[:mount_point]
19
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.unmount.unmounted', mount: env[:mount_point]))
20
+ else
21
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.unmount.unmounted_all'))
22
+ end
23
+ @app.call(env)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,48 @@
1
+ require 'vagrant'
2
+ require 'vagrant/action/builder'
3
+
4
+ module VagrantPlugins
5
+ module ProviderVirtualBox
6
+ module Action
7
+ autoload :Mount, File.expand_path("../action/mount.rb", __FILE__)
8
+ autoload :Unmount, File.expand_path("../action/unmount.rb", __FILE__)
9
+ autoload :MessageNotMounted, File.expand_path("../action/message_not_mounted.rb", __FILE__)
10
+
11
+ def self.action_mount
12
+ Vagrant::Action::Builder.new.tap do |builder|
13
+ builder.use CheckVirtualbox
14
+ builder.use Call, Created do |created_env, created_builder|
15
+ if created_env[:result]
16
+ created_builder.use CheckAccessible
17
+ created_builder.use Call, Mount do |mount_env, mount_builder|
18
+ unless mount_env[:result]
19
+ mount_builder.use MessageNotMounted
20
+ end
21
+ end
22
+ else
23
+ created_builder.use MessageNotCreated
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.action_unmount
30
+ Vagrant::Action::Builder.new.tap do |builder|
31
+ builder.use CheckVirtualbox
32
+ builder.use Call, Created do |created_env, created_builder|
33
+ if created_env[:result]
34
+ created_builder.use CheckAccessible
35
+ created_builder.use Call, Unmount do |unmount_env, unmount_builder|
36
+ unless unmount_env[:result]
37
+ unmount_builder.use MessageNotUnmounted
38
+ end
39
+ end
40
+ else
41
+ created_builder.use MessageNotCreated
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,155 @@
1
+ module VagrantPlugins
2
+ module ProviderVirtualBox
3
+ module Driver
4
+ class Base
5
+ def mount(mount_point)
6
+ # Find an IDE or SCSI controller
7
+ @logger.debug "Mounting #{mount_point}"
8
+ info = get_vm_info(@uuid)
9
+ begin
10
+ controller_name, device_id, port_id = find_iso(info, mount_point)
11
+ @logger.debug "Already mounted on #{controller_name}, device: #{device_id}, port: #{port_id}"
12
+ return 1
13
+ rescue KeyError
14
+ @logger.debug "Not mounted yet, we are good to go"
15
+ end
16
+ ide_types = ['PIIX3', 'PIIX4', 'ICH6']
17
+ controller_name, device_id, port_id = find_free_port(info, ide_types)
18
+ execute('storageattach', @uuid,
19
+ '--storagectl', controller_name,
20
+ '--device', device_id.to_s,
21
+ '--port', port_id.to_s,
22
+ '--type', 'dvddrive',
23
+ '--medium', mount_point
24
+ )
25
+ end
26
+
27
+ def unmount(mount_point, remove_device=false)
28
+ # Find an IDE or SCSI controller
29
+ @logger.debug "Mounting #{mount_point}"
30
+ info = get_vm_info(@uuid)
31
+ begin
32
+ if mount_point
33
+ controller_name, device_id, port_id = find_iso(info, mount_point)
34
+ else
35
+ controller_name, device_id, port_id = find_first_iso(info)
36
+ end
37
+ @logger.debug "Mounted on #{controller_name}, device: #{device_id}, port: #{port_id}"
38
+ if remove_device
39
+ execute('storageattach', @uuid,
40
+ '--storagectl', controller_name,
41
+ '--device', device_id.to_s,
42
+ '--port', port_id.to_s,
43
+ '--medium', 'none'
44
+ )
45
+ else
46
+ execute('storageattach', @uuid,
47
+ '--storagectl', controller_name,
48
+ '--device', device_id.to_s,
49
+ '--port', port_id.to_s,
50
+ '--type', 'dvddrive',
51
+ '--medium', 'emptydrive'
52
+ )
53
+ end
54
+ rescue KeyError
55
+ @logger.debug "Not mounted, we cannot proceed"
56
+ return 0
57
+ end
58
+ end
59
+
60
+ def find_iso(vm_info, mount_point)
61
+ device_id = port_id = nil
62
+ controller = vm_info[:storagecontrollers].find do |ctrl|
63
+ device_id = ctrl[:devices].find_index do |device|
64
+ port_id = device[:ports].find_index do |port|
65
+ port[:mount].include? mount_point if port
66
+ end
67
+ end
68
+ end
69
+ raise KeyError unless controller
70
+ @logger.debug "Found ISO on Storage: #{controller[:name]}, device ##{device_id}, port ##{port_id}"
71
+ return [controller[:name], device_id, port_id]
72
+ end
73
+
74
+ def find_first_iso(vm_info)
75
+ device_id = port_id = nil
76
+ controller = vm_info[:storagecontrollers].find do |ctrl|
77
+ device_id = ctrl[:devices].find_index do |device|
78
+ port_id = device[:ports].find_index do |port|
79
+ port[:mount] =~ /\.iso$/i if port
80
+ end
81
+ end
82
+ end
83
+ raise KeyError unless controller
84
+ @logger.debug "Found ISO on Storage: #{controller[:name]}, device ##{device_id}, port ##{port_id}"
85
+ return [controller[:name], device_id, port_id]
86
+ end
87
+
88
+ def find_free_port(vm_info, controller_types)
89
+ device_id = port_id = nil
90
+ controller = vm_info[:storagecontrollers].find do |ctrl|
91
+ device_id = ctrl[:devices].find_index do |device|
92
+ port_id = device[:ports].find_index do |port|
93
+ port.nil? || port[:mount] == 'emptydrive'
94
+ end
95
+ end
96
+ end
97
+ raise KeyError, "No suitable Controller on VM #{@uuid}" unless controller
98
+ @logger.debug "Found a suitable Storage: #{controller[:name]}, device ##{device_id}, port ##{port_id}"
99
+ return [controller[:name], device_id, port_id]
100
+ end
101
+
102
+ def get_vm_info(name_or_uuid)
103
+ @logger.debug "Fetching info for VM #{name_or_uuid}"
104
+ output = execute('showvminfo', name_or_uuid, '--machinereadable', retryable: true)
105
+ nic_index = nil
106
+ output.split("\n").inject({storagecontrollers: [], nics: [], lpts: [], uarts: []}) do |hash, line|
107
+ if line =~ /^"?([^="]+)"?="?(|[^"]+)"?$/
108
+ key = $1
109
+ value = $2.to_s
110
+ case key
111
+ when /^storagecontroller([a-z]+)(\d+)$/
112
+ key = $1.tr('- ', '__').to_sym
113
+ controller = hash[:storagecontrollers][$2.to_i]
114
+ if controller
115
+ controller[key] = value
116
+ if key == :portcount
117
+ controller[:devices] = value.to_i.times.inject([]) {|array| array << { ports: [nil, nil] } }
118
+ end
119
+ else
120
+ hash[:storagecontrollers] << { key => value }
121
+ end
122
+ when /^([a-zA-Z ]+)(?:-([a-zA-Z]+))?-(\d+)-(\d+)$/
123
+ unless value == 'none'
124
+ key = ($2 || 'mount').tr('- ', '__').to_sym
125
+ controller = hash[:storagecontrollers].find { |s| s[:name] == $1 }
126
+ raise KeyError, $1 unless controller
127
+ device = controller[:devices][$4.to_i]
128
+ raise IndexError, $4.to_i unless device
129
+ raise IndexError, $3.to_i unless $3.to_i < 2
130
+ device[:ports][$3.to_i] ||= {}
131
+ device[:ports][$3.to_i][key] = value
132
+ end
133
+ when /^natnet(\d+)$/
134
+ nic_index = $1.to_i - 1
135
+ hash[:nics][nic_index] ||= { forwardings: [] }
136
+ hash[:nics][nic_index][:natnet] = value
137
+ when /^(cableconnected|macaddress|nic|nictype|nicspeed)(\d+)$/
138
+ hash[:nics][$2.to_i - 1][$1.to_sym] = value unless value == 'none'
139
+ when /^(mtu|sockSnd|sockRcv|tcpWndSnd|tcpWndRcv)$/
140
+ hash[:nics][nic_index][$1.to_sym] = value
141
+ when /^Forwarding\((\d+)\)$/
142
+ hash[:nics][nic_index][:forwardings][$1.to_i] = value
143
+ when /^(lpt|uart)(\d+)$/
144
+ hash[($1 << 's').to_sym][$2.to_i - 1] = value
145
+ else
146
+ hash[key.tr('- ','__').to_sym] = value
147
+ end
148
+ end
149
+ hash
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,9 @@
1
+ module VagrantPlugins
2
+ module ProviderVirtualBox
3
+ module Driver
4
+ class Meta
5
+ def_delegators :@driver, :mount, :unmount
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'driver/base'
2
+ require_relative 'driver/meta'
@@ -0,0 +1,16 @@
1
+ module HashiCorp
2
+ module VagrantVMwarefusion
3
+ module Action
4
+ class MessageNotMounted
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t('vagrant_mount.errors.vm.mount.not_mounted', mount: env[:mount_point]))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module HashiCorp
2
+ module VagrantVMwarefusion
3
+ module Action
4
+ class MessageNotUnmounted
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t('vagrant_mount.errors.vm.unmount.not_unmounted', mount: env[:mount_point]))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module HashiCorp
2
+ module VagrantVMwarefusion
3
+ module Action
4
+ class Mount
5
+ def initialize(app, env)
6
+ @app = app
7
+ @env = env
8
+ end
9
+
10
+ def call(env)
11
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.mount.mounting', mount: env[:mount_point]))
12
+ env[:result] = env[:machine].provider.driver.mount(env[:mount_point])
13
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.mount.mounted', mount: env[:mount_point]))
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module HashiCorp
2
+ module VagrantVMwarefusion
3
+ module Action
4
+ class Unmount
5
+ def initialize(app, env)
6
+ @app = app
7
+ @env = env
8
+ end
9
+
10
+ def call(env)
11
+ if env[:mount_point]
12
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.unmount.unmounting', mount: env[:mount_point]))
13
+ else
14
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.unmount.unmounting_all'))
15
+ end
16
+ env[:result] = env[:machine].provider.driver.unmount(env[:mount_point], env[:remove_device])
17
+ if env[:mount_point]
18
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.unmount.unmounted', mount: env[:mount_point]))
19
+ else
20
+ env[:ui].info(I18n.t('vagrant_mount.actions.vm.unmount.unmounted_all'))
21
+ end
22
+ @app.call(env)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,47 @@
1
+ require 'vagrant'
2
+ require 'vagrant/action/builder'
3
+
4
+ module HashiCorp
5
+ module VagrantVMwarefusion
6
+ module Action
7
+ autoload :Mount, File.expand_path("../action/mount.rb", __FILE__)
8
+ autoload :Unmount, File.expand_path("../action/unmount.rb", __FILE__)
9
+ autoload :MessageNotMounted, File.expand_path("../action/message_not_mounted.rb", __FILE__)
10
+ autoload :MessageNotUnmounted, File.expand_path("../action/message_not_unmounted.rb", __FILE__)
11
+
12
+ def self.action_mount
13
+ Vagrant::Action::Builder.new.tap do |builder|
14
+ builder.use CheckVMware
15
+ builder.use Call, Created do |created_env, created_builder|
16
+ if created_env[:result]
17
+ created_builder.use Call, Mount do |mount_env, mount_builder|
18
+ unless mount_env[:result]
19
+ mount_builder.use MessageNotMounted
20
+ end
21
+ end
22
+ else
23
+ created_builder.use MessageNotCreated
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.action_unmount
30
+ Vagrant::Action::Builder.new.tap do |builder|
31
+ builder.use CheckVMware
32
+ builder.use Call, Created do |created_env, created_builder|
33
+ if created_env[:result]
34
+ created_builder.use Call, Unmount do |unmount_env, unmount_builder|
35
+ unless unmount_env[:result]
36
+ unmount_builder.use MessageNotUnmounted
37
+ end
38
+ end
39
+ else
40
+ created_builder.use MessageNotCreated
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,84 @@
1
+ require 'pathname'
2
+
3
+ module HashiCorp
4
+ module VagrantVMwarefusion
5
+ module Driver
6
+ class Base
7
+ def mount(mount_point)
8
+ @logger.info "Mounting #{mount_point}"
9
+ info = vminfo(vmx_path)
10
+ begin
11
+ controller_name = find_iso(info, mount_point)
12
+ @logger.debug "Already mounted on #{controller_name}"
13
+ return 1
14
+ rescue KeyError
15
+ @logger.debug "Not mounted, we are good to go"
16
+ end
17
+ begin
18
+ controller_name = find_free_port(info)
19
+ @logger.info "Mounting on: #{controller_name}"
20
+ info["#{controller_name}.devicetype"] = "cdrom-image"
21
+ info["#{controller_name}.filename"] = Pathname.new(mount_point).realpath.to_s
22
+ info["#{controller_name}.present"] = "TRUE"
23
+ info["#{controller_name}.autodetect"] = "TRUE"
24
+ info["#{controller_name}.startconnected"] = "TRUE"
25
+ vmsave(vmx_path, info)
26
+ return 1
27
+ rescue KeyError
28
+ @logger.error "Could not find any free port"
29
+ return 0
30
+ end
31
+ end
32
+
33
+ def unmount(mount_point, remove_device=false)
34
+ @logger.info "Unmounting #{mount_point}"
35
+ info = vminfo(vmx_path)
36
+ begin
37
+ controller_name = find_iso(info, mount_point)
38
+ @logger.info "Mounted on #{controller_name}"
39
+ info["#{controller_name}.devicetype"] = "cdrom-raw"
40
+ info["#{controller_name}.filename"] = "auto detect"
41
+ info["#{controller_name}.present"] = "TRUE"
42
+ info["#{controller_name}.autodetect"] = "TRUE"
43
+ info["#{controller_name}.startconnected"] = "FALSE"
44
+ vmsave(vmx_path, info)
45
+ return 1
46
+ rescue KeyError
47
+ @logger.debug "Not mounted, nothing to do"
48
+ return 0
49
+ end
50
+ end
51
+
52
+ def vminfo(path)
53
+ return Hash[*File.readlines(path).map {|line| line.scan(/^(.+?) = "(.*?)"$/m)}.flatten]
54
+ end
55
+
56
+ def vmsave(path, vm_info)
57
+ temp_path="#{path}.new"
58
+ @logger.debug "Saving in: #{temp_path}"
59
+ File.open("#{temp_path}", "w") { |f| vm_info.each{|k,v| f.puts "#{k} = \"#{v}\""}}
60
+ FileUtils.mv temp_path, path, force: true
61
+ end
62
+
63
+ def find_iso(vm_info, mount_point)
64
+ data = vm_info.find {|k, v| v =~ /.*\/#{mount_point}/ }
65
+ raise KeyError unless data
66
+ @logger.debug "Found data: #{data.inspect}"
67
+ data[0] =~ /([a-z]+)(\d+):(\d+)\.filename/
68
+ raise KeyError unless data[0] =~ /([a-z]+)(\d+):(\d+)\.filename/
69
+ @logger.debug "type: #{$1}, device: #{$2}, port: #{$3}"
70
+ "#{$1}#{$2}:#{$3}"
71
+ end
72
+
73
+ def find_free_port(vm_info)
74
+ data = vm_info.find {|k, v| v == 'cdrom-raw' }
75
+ raise KeyError unless data
76
+ @logger.debug "Found data: #{data.inspect}"
77
+ raise KeyError unless data[0] =~ /([a-z]+)(\d+):(\d+)\.devicetype/
78
+ @logger.debug "type: #{$1}, device: #{$2}, port: #{$3}"
79
+ "#{$1}#{$2}:#{$3}"
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1 @@
1
+ require_relative 'driver/base'
@@ -0,0 +1,39 @@
1
+ require 'optparse'
2
+ require 'vagrant'
3
+
4
+ module VagrantPlugins
5
+ module Mount
6
+ module Command
7
+ class Mount < Vagrant.plugin('2', :command)
8
+ def self.synopsis
9
+ 'Mount ISO in Virtual Machine'
10
+ end
11
+
12
+ def initialize(argv, env)
13
+ @env=env
14
+ super
15
+ end
16
+
17
+ def execute
18
+ options = {}
19
+ parser = OptionParser.new do |opts|
20
+ opts.banner = 'Usage: vagrant mount [options] [vm-name]'
21
+ opts.separator ''
22
+ opts.separator ' Options:'
23
+ opts.on("--iso path", "The path of the ISO to mount") { |arg| options[:path] = arg }
24
+ end
25
+
26
+ argv = parse_options(parser)
27
+ return unless argv
28
+ argv << "default" if argv.empty?
29
+
30
+ raise Vagrant::Errors::CLIInvalidUsage, { help: parser.help.chomp } unless options[:path]
31
+ with_target_vms(argv) do |vm|
32
+ vm.action(:mount, mount_point: options[:path])
33
+ end
34
+ 0
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require 'optparse'
2
+ require 'vagrant'
3
+
4
+ module VagrantPlugins
5
+ module Mount
6
+ module Command
7
+ class Unmount < Vagrant.plugin('2', :command)
8
+ def self.synopsis
9
+ 'Unmount ISO from Virtual Machine'
10
+ end
11
+
12
+ def initialize(argv, env)
13
+ @env=env
14
+ super
15
+ end
16
+
17
+ def execute
18
+ options = { remove_device: false }
19
+ parser = OptionParser.new do |opts|
20
+ opts.banner = 'Usage: vagrant unmount [options] [vm-name]'
21
+ opts.separator ''
22
+ opts.separator ' Options:'
23
+ opts.on("--iso path", "The path of the ISO to unmount") { |arg| options[:path] = arg }
24
+ opts.on("--remove-device", "Remove the controller/device/port after unmounting") { |arg| options[:remove_device] = true }
25
+ end
26
+
27
+ argv = parse_options(parser)
28
+ return unless argv
29
+ argv << "default" if argv.empty?
30
+
31
+ with_target_vms(argv) do |vm|
32
+ vm.action(:unmount, mount_point: options[:path], remove_device: options[:remove_device])
33
+ end
34
+ 0
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,78 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The Vagrant Mount plugin must be run within Vagrant.'
5
+ end
6
+
7
+ raise 'The Vagrant Mount plugin is only compatible with Vagrant 1.2+' if Vagrant::VERSION < '1.2.0'
8
+
9
+ module VagrantPlugins
10
+ module Mount
11
+ class Plugin < Vagrant.plugin('2')
12
+ name 'mount'
13
+ description <<-DESC
14
+ This plugin mount ISO files inside Virtual Machines as DVD/CD
15
+ DESC
16
+ # @logger.info "Loading command :mount"
17
+ command(:mount) do
18
+ require_relative 'commands/mount'
19
+ Command::Mount
20
+ end
21
+
22
+ # @logger.info "Loading command :unmount"
23
+ command(:unmount) do
24
+ require_relative 'commands/unmount'
25
+ Command::Unmount
26
+ end
27
+
28
+ # VirtualBox
29
+ begin
30
+ require_relative 'actions/providers/virtualbox/action'
31
+ require_relative 'actions/providers/virtualbox/driver'
32
+ rescue LoadError
33
+ # If plugin cannot be loaded, silently ignore
34
+ end
35
+
36
+ # Hyper-V
37
+ begin
38
+ require_relative 'actions/providers/hyperv/mount'
39
+ require_relative 'actions/providers/hyperv/driver'
40
+ rescue LoadError
41
+ # If plugin cannot be loaded, silently ignore
42
+ end
43
+
44
+ # VMWare Fusion
45
+ begin
46
+ require 'vagrant-vmware-fusion/action'
47
+ require 'vagrant-vmware-fusion/driver'
48
+
49
+ require_relative 'actions/providers/vmware-fusion/action'
50
+ require_relative 'actions/providers/vmware-fusion/driver'
51
+ rescue LoadError
52
+ # If plugin cannot be loaded, silently ignore
53
+ end
54
+
55
+ # VMWare Workstation
56
+ begin
57
+ require 'vagrant-vmware-workstation/action'
58
+ require 'vagrant-vmware-workstation/driver'
59
+
60
+ require_relative 'actions/providers/vmware-workstation/mount'
61
+ require_relative 'actions/providers/vmware-workstation/driver'
62
+ rescue LoadError
63
+ # If plugin cannot be loaded, silently ignore
64
+ end
65
+
66
+ # Parallels Desktop
67
+ begin
68
+ require 'vagrant-parallels/action'
69
+ require 'vagrant-parallels/driver'
70
+
71
+ require_relative 'actions/providers/parallels/mount'
72
+ require_relative 'actions/providers/parallels/driver'
73
+ rescue LoadError
74
+ # If plugin cannot be loaded, silently ignore
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module Mount
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ require 'vagrant-mount/version'
2
+ require 'vagrant-mount/plugin'
3
+
4
+ module VagrantPlugins
5
+ module Mount
6
+ lib_path = Pathname.new(File.expand_path('../vagrant-mount', __FILE__))
7
+ autoload :Errors, lib_path.join('errors')
8
+
9
+ def self.source_root
10
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
11
+ end
12
+
13
+ Dir.glob(File.expand_path('locales/*.yml', Mount.source_root)).each do |lang|
14
+ I18n.load_path << File.expand_path(lang)
15
+ end
16
+ I18n.reload!
17
+ end
18
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,26 @@
1
+ en:
2
+ vagrant_mount:
3
+ actions:
4
+ vm:
5
+ mount:
6
+ mounting: |-
7
+ Mounting ISO %{mount}...
8
+ mounted: |-
9
+ Successfully mounted ISO %{mount}
10
+ unmount:
11
+ unmounting: |-
12
+ Unmounting ISO %{mount}...
13
+ unmounting_all: |-
14
+ Unmounting all ISOs...
15
+ unmounted: |-
16
+ Successfully unmounted ISO %{mount}
17
+ unmounted_all: |-
18
+ Successfully unmounted all ISOs
19
+ errors:
20
+ vm:
21
+ mount:
22
+ not_mounted: |-
23
+ Failed to mount %{mount}
24
+ unmount:
25
+ not_unmounted: |-
26
+ Failed to unmount %{mount}
data/spec/Vagrantfile ADDED
@@ -0,0 +1,27 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.configure(2) do |config|
5
+ config.vm.define :centos, primary: true do |centos|
6
+ centos.vm.box = "box-cutter/centos70"
7
+ end
8
+
9
+ config.vm.define :ubuntu, autostart: false do |ubuntu|
10
+ ubuntu.vm.box = "box-cutter/ubuntu1404"
11
+ end
12
+
13
+ config.vm.define :windows, autostart: false do |windows|
14
+ windows.vm.box = "windows-2012R2-full-standard-eval"
15
+ windows.vm.box_check_update = false
16
+ windows.vm.guest = :windows
17
+ windows.vm.communicator = :winrm
18
+
19
+ windows.vm.provider :virtualbox do |provider, override|
20
+ provider.gui = true
21
+ provider.customize ['modifyvm', :id, '--ioapic', 'on'] # So we can assign multiple CPUs to the VM
22
+ provider.customize ['modifyvm', :id, '--memory', 2048]
23
+ provider.customize ['modifyvm', :id, '--cpus', 2]
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ require 'rspec'
2
+ require 'helpers/isolated_environment'
3
+ require 'vagrant-mount/commands/mount'
4
+
5
+ describe VagrantPlugins::Mount::Command::Mount do
6
+ describe 'help' do
7
+ let (:argv) { [] }
8
+ let (:env) do
9
+ IsolatedEnvironment.new.create_environment
10
+ end
11
+
12
+ subject { described_class.new(argv, env) }
13
+
14
+ context 'with no arguments' do
15
+ it 'shows help' do
16
+ expect { subject.execute }.to raise_error(Vagrant::Errors::CLIInvalidUsage)
17
+ end
18
+ end
19
+
20
+ context 'with an ISO' do
21
+ let(:argv) { [ 'dummy.iso' ] }
22
+
23
+ it 'mounts it' do
24
+ expect(subject.execute).to eq(0)
25
+ end
26
+ end
27
+ end
28
+ end
data/spec/dummy.iso ADDED
Binary file
@@ -0,0 +1,52 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+ require 'tmpdir'
4
+ require 'logger'
5
+
6
+ class IsolatedEnvironment
7
+ attr_reader :homedir
8
+ attr_reader :workdir
9
+
10
+ def initialize
11
+ Dir.mkdir 'tmp' unless Dir.exists? 'tmp'
12
+ @logger = Logger.new(File.open('tmp/isolated_environment.log', 'a'))
13
+ @tempdir = Dir.mktmpdir('vagrant')
14
+ @logger.info("Initialized Isolated Environment in #{@tempdir}")
15
+ @homedir = Pathname.new(File.join(@tempdir, 'home'))
16
+ @workdir = Pathname.new(File.join(@tempdir, 'work'))
17
+ @homedir.mkdir
18
+ @workdir.mkdir
19
+ end
20
+
21
+ def create_environment(options=nil)
22
+ Vagrant::Environment.new({cwd: workdir, home_path: homedir}.merge(options || {}))
23
+ end
24
+
25
+ def close
26
+ @logger.info("Removing Isolated Environment from #{@tempdir}")
27
+ FileUtils.rm_rf(@tempdir)
28
+ end
29
+
30
+ def file(name, contents, root=nil)
31
+ (root || @workdir).join(name).open('w+') { |f| f.write(contents) }
32
+ end
33
+
34
+ def vagrantfile(contents, root=nil)
35
+ file('Vagrantfile', contents, root)
36
+ end
37
+
38
+ def box(name, vagrantfile_contents='')
39
+ box_dir=boxes_dir.join(name)
40
+ box_dir.mkpath
41
+
42
+ box_dir.join('box.ovf').open('w') { |f| f.write('') }
43
+ vagrantfile(vagrantfile_contents, box_dir)
44
+ box_dir
45
+ end
46
+
47
+ def boxes_dir
48
+ dir=@homedir.join('boxes')
49
+ dir.mkpath
50
+ dir
51
+ end
52
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vagrant-mount/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'vagrant-mount'
8
+ spec.version = VagrantPlugins::Mount::VERSION
9
+ spec.authors = ['Gildas Cherruel']
10
+ spec.email = ['gildas@breizh.org']
11
+ spec.summary = %q{Mounts ISO in Virtual Machines}
12
+ spec.description = %q{Mounts ISO in Virtual Machines via the provider}
13
+ spec.homepage = 'http://www.vagrantup.com'
14
+ spec.license = 'MIT'
15
+
16
+ spec.required_rubygems_version = '>= 1.3.6'
17
+ spec.rubyforge_project = 'vagrant-mount'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ['lib']
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.1'
27
+ spec.add_development_dependency 'yard'
28
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-mount
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gildas Cherruel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Mounts ISO in Virtual Machines via the provider
70
+ email:
71
+ - gildas@breizh.org
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rbenv-gemsets"
78
+ - ".rspec"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - lib/vagrant-mount.rb
84
+ - lib/vagrant-mount/actions/providers/virtualbox/action.rb
85
+ - lib/vagrant-mount/actions/providers/virtualbox/action/message_not_mounted.rb
86
+ - lib/vagrant-mount/actions/providers/virtualbox/action/message_not_unmounted.rb
87
+ - lib/vagrant-mount/actions/providers/virtualbox/action/mount.rb
88
+ - lib/vagrant-mount/actions/providers/virtualbox/action/unmount.rb
89
+ - lib/vagrant-mount/actions/providers/virtualbox/driver.rb
90
+ - lib/vagrant-mount/actions/providers/virtualbox/driver/base.rb
91
+ - lib/vagrant-mount/actions/providers/virtualbox/driver/meta.rb
92
+ - lib/vagrant-mount/actions/providers/vmware-fusion/action.rb
93
+ - lib/vagrant-mount/actions/providers/vmware-fusion/action/message_not_mounted.rb
94
+ - lib/vagrant-mount/actions/providers/vmware-fusion/action/message_not_unmounted.rb
95
+ - lib/vagrant-mount/actions/providers/vmware-fusion/action/mount.rb
96
+ - lib/vagrant-mount/actions/providers/vmware-fusion/action/unmount.rb
97
+ - lib/vagrant-mount/actions/providers/vmware-fusion/driver.rb
98
+ - lib/vagrant-mount/actions/providers/vmware-fusion/driver/base.rb
99
+ - lib/vagrant-mount/commands/mount.rb
100
+ - lib/vagrant-mount/commands/unmount.rb
101
+ - lib/vagrant-mount/plugin.rb
102
+ - lib/vagrant-mount/version.rb
103
+ - locales/en.yml
104
+ - spec/Vagrantfile
105
+ - spec/command_spec.rb
106
+ - spec/dummy.iso
107
+ - spec/helpers/isolated_environment.rb
108
+ - vagrant-mount.gemspec
109
+ homepage: http://www.vagrantup.com
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: 1.3.6
127
+ requirements: []
128
+ rubyforge_project: vagrant-mount
129
+ rubygems_version: 2.2.2
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Mounts ISO in Virtual Machines
133
+ test_files:
134
+ - spec/Vagrantfile
135
+ - spec/command_spec.rb
136
+ - spec/dummy.iso
137
+ - spec/helpers/isolated_environment.rb
138
+ has_rdoc: