vagrant-vcenter 0.0.2.pre.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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rubocop.yml +34 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +20 -0
  6. data/README.md +5 -0
  7. data/Rakefile +17 -0
  8. data/example_box/README.md +13 -0
  9. data/example_box/Vagrantfile +6 -0
  10. data/example_box/metadata.json +1 -0
  11. data/lib/vagrant-vcenter.rb +18 -0
  12. data/lib/vagrant-vcenter/action.rb +232 -0
  13. data/lib/vagrant-vcenter/action/announce_ssh_exec.rb +19 -0
  14. data/lib/vagrant-vcenter/action/build_vm.rb +130 -0
  15. data/lib/vagrant-vcenter/action/connect_vcenter.rb +37 -0
  16. data/lib/vagrant-vcenter/action/destroy.rb +29 -0
  17. data/lib/vagrant-vcenter/action/disconnect_vcenter.rb +29 -0
  18. data/lib/vagrant-vcenter/action/inventory_check.rb +132 -0
  19. data/lib/vagrant-vcenter/action/is_created.rb +26 -0
  20. data/lib/vagrant-vcenter/action/is_paused.rb +23 -0
  21. data/lib/vagrant-vcenter/action/is_running.rb +23 -0
  22. data/lib/vagrant-vcenter/action/message_already_running.rb +17 -0
  23. data/lib/vagrant-vcenter/action/message_cannot_suspend.rb +19 -0
  24. data/lib/vagrant-vcenter/action/message_not_created.rb +17 -0
  25. data/lib/vagrant-vcenter/action/message_will_not_destroy.rb +18 -0
  26. data/lib/vagrant-vcenter/action/power_off.rb +30 -0
  27. data/lib/vagrant-vcenter/action/power_on.rb +30 -0
  28. data/lib/vagrant-vcenter/action/read_ssh_info.rb +37 -0
  29. data/lib/vagrant-vcenter/action/read_state.rb +52 -0
  30. data/lib/vagrant-vcenter/action/resume.rb +30 -0
  31. data/lib/vagrant-vcenter/action/suspend.rb +30 -0
  32. data/lib/vagrant-vcenter/action/sync_folders.rb +135 -0
  33. data/lib/vagrant-vcenter/config.rb +92 -0
  34. data/lib/vagrant-vcenter/errors.rb +88 -0
  35. data/lib/vagrant-vcenter/plugin.rb +67 -0
  36. data/lib/vagrant-vcenter/provider.rb +46 -0
  37. data/lib/vagrant-vcenter/version.rb +6 -0
  38. data/locales/en.yml +50 -0
  39. data/vagrant-vcenter.gemspec +29 -0
  40. metadata +194 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c733695318829ceed21eafa83e10faa309ccc6ef
4
+ data.tar.gz: 95a52dd729748fcdb3ea944f3674361568620d07
5
+ SHA512:
6
+ metadata.gz: 3135b7e6ed6c775bde2f1176c795f9614250497bfe64469309338d94a29341c4395779807ff569d6e0dab0144ba373fd418fb8d23a19c873b1b2c7e32c65ceb5
7
+ data.tar.gz: db2a1fb9232ee85ec4b315372995861ebc01629efdda358196fdfc2204335db83efc84c50285408b87fa0c084fe3882d63ae92b54b146bb954ea4e8ff31fe04a
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .vagrant/*
2
+ pkg/*
3
+ Gemfile.lock
4
+ test-*
data/.rubocop.yml ADDED
@@ -0,0 +1,34 @@
1
+ MethodLength:
2
+ CountComments: false # count full line comments?
3
+ Enabled: false
4
+
5
+ MethodName:
6
+ EnforcedStyle: snake_case
7
+
8
+ AccessorMethodName:
9
+ Description: Check the naming of accessor methods for get_/set_.
10
+ Enabled: false
11
+
12
+ Encoding:
13
+ Description: 'Use UTF-8 as the source file encoding.'
14
+ Enabled: true
15
+
16
+ HashSyntax:
17
+ Description: >-
18
+ Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax
19
+ { :a => 1, :b => 2 }.
20
+ Enabled: false
21
+ EnforcedStyle: hash_rockets
22
+
23
+ LineEndConcatenation:
24
+ Description: 'Use \\ instead of + to concatenate two string literals at line end.'
25
+ Enabled: true
26
+
27
+ LineLength:
28
+ Description: 'Limit lines to 79 characters.'
29
+ Enabled: true
30
+ Max: 80
31
+
32
+ CyclomaticComplexity:
33
+ Description: 'Avoid complex methods.'
34
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git'
7
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Fabio Rapposelli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # vagrant-vcenter
2
+
3
+ Vagrant provider for VMware vCenter ®
4
+
5
+ Please note that this is NOT WORKING yet.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Immediately sync all stdout so that tools like buildbot can
6
+ # immediately load in the output.
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the y of this file.
11
+ Dir.chdir(File.expand_path('../', __FILE__))
12
+
13
+ Bundler::GemHelper.install_tasks
14
+
15
+ RSpec::Core::RakeTask.new
16
+
17
+ task :default => 'spec'
@@ -0,0 +1,13 @@
1
+ # vagrant-vcenter box specifications [WIP]
2
+
3
+ *Note that vagrant-vcenter currently supports only single VM vApp boxes*
4
+
5
+ BOX package should contain:
6
+
7
+ - `metadata.json` -- Vagrant metadata file
8
+ - `<boxname>.ovf` -- OVF descriptor of the vApp.
9
+ - `<boxname>.mf` -- OVF manifest file containing file hashes.
10
+ - `<boxname>-disk-<#>.vmdk` -- Associated VMDK files.
11
+ - `Vagrantfile`-- vagrant-vcenter default Vagrantfile
12
+
13
+ A [task is open](https://github.com/frapposelli/vagrant-vcenter/issues/12) for creating a veewee plugin to facilitate Box creation
@@ -0,0 +1,6 @@
1
+ Vagrant::Config.run do |config|
2
+ config.vm.base_mac = "<mac address>"
3
+ end
4
+
5
+ include_vagrantfile = File.expand_path("../include/_Vagrantfile", __FILE__)
6
+ load include_vagrantfile if File.exist?(include_vagrantfile)
@@ -0,0 +1 @@
1
+ {"provider": "vagrant-vcenter"}
@@ -0,0 +1,18 @@
1
+ require 'pathname'
2
+ require 'vagrant-vcenter/plugin'
3
+
4
+ module VagrantPlugins
5
+ # Initialize the plugin.
6
+ module VCenter
7
+ lib_path = Pathname.new(File.expand_path('../vagrant-vcenter', __FILE__))
8
+ autoload :Action, lib_path.join('action')
9
+ autoload :Errors, lib_path.join('errors')
10
+
11
+ # This returns the path to the source of this plugin.
12
+ #
13
+ # @return [Pathname]
14
+ def self.source_root
15
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,232 @@
1
+ require 'pathname'
2
+ require 'vagrant/action/builder'
3
+
4
+ module VagrantPlugins
5
+ module VCenter
6
+ # Actions to be performed by the vagrant-vcenter provider.
7
+ module Action
8
+ include Vagrant::Action::Builtin
9
+
10
+ # Vagrant commands
11
+ # This action boots the VM, assuming the VM is in a state that requires
12
+ # a bootup (i.e. not saved).
13
+ def self.action_boot
14
+ Vagrant::Action::Builder.new.tap do |b|
15
+ b.use PowerOn
16
+ b.use Provision
17
+ b.use SyncFolders
18
+ end
19
+ end
20
+
21
+ def self.action_reload
22
+ Vagrant::Action::Builder.new.tap do |b|
23
+ b.use ConfigValidate
24
+ b.use Call, IsCreated do |env, b2|
25
+ unless env[:result]
26
+ b2.use MessageNotCreated
27
+ next
28
+ end
29
+ b2.use action_halt
30
+ b2.use action_start
31
+ b2.use DisconnectvCenter
32
+ end
33
+ end
34
+ end
35
+
36
+ # This action starts a VM, assuming it is already imported and exists.
37
+ # A precondition of this action is that the VM exists.
38
+ def self.action_start
39
+ Vagrant::Action::Builder.new.tap do |b|
40
+ b.use ConfigValidate
41
+ b.use ConnectvCenter
42
+ b.use Call, IsRunning do |env, b2|
43
+ # If the VM is running, then our work here is done, exit
44
+ if env[:result]
45
+ b2.use MessageAlreadyRunning
46
+ next
47
+ end
48
+ b2.use Call, IsPaused do |env2, b3|
49
+ if env2[:result]
50
+ b3.use Resume
51
+ next
52
+ end
53
+ b3.use action_boot
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ def self.action_halt
60
+ Vagrant::Action::Builder.new.tap do |b|
61
+ b.use ConnectvCenter
62
+ b.use Call, IsPaused do |env, b2|
63
+ b2.use Resume if env[:result]
64
+ b2.use PowerOff
65
+ end
66
+ end
67
+ end
68
+
69
+ def self.action_suspend
70
+ Vagrant::Action::Builder.new.tap do |b|
71
+ b.use ConnectvCenter
72
+ b.use Call, IsRunning do |env, b2|
73
+ # If the VM is stopped, can't suspend
74
+ if !env[:result]
75
+ b2.use MessageCannotSuspend
76
+ else
77
+ b2.use Suspend
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def self.action_resume
84
+ Vagrant::Action::Builder.new.tap do |b|
85
+ b.use ConnectvCenter
86
+ b.use Resume
87
+ end
88
+ end
89
+
90
+ def self.action_destroy
91
+ Vagrant::Action::Builder.new.tap do |b|
92
+ b.use Call, DestroyConfirm do |env, b2|
93
+ if env[:result]
94
+ b2.use ConfigValidate
95
+ b2.use ConnectvCenter
96
+ b2.use Call, IsRunning do |env2, b3|
97
+ # If the VM is running, must power off
98
+ b3.use action_halt if env2[:result]
99
+ b3.use Destroy
100
+ end
101
+ else
102
+ b2.use MessageWillNotDestroy
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ def self.action_provision
109
+ Vagrant::Action::Builder.new.tap do |b|
110
+ b.use ConfigValidate
111
+ b.use Call, IsCreated do |env, b2|
112
+ unless env[:result]
113
+ b2.use MessageNotCreated
114
+ next
115
+ end
116
+ b2.use Provision
117
+ b2.use SyncFolders
118
+ end
119
+ end
120
+ end
121
+
122
+ # This action is called to read the SSH info of the machine. The
123
+ # resulting state is expected to be put into the `:machine_ssh_info`
124
+ # key.
125
+ def self.action_read_ssh_info
126
+ Vagrant::Action::Builder.new.tap do |b|
127
+ b.use ConfigValidate
128
+ b.use ConnectvCenter
129
+ b.use ReadSSHInfo
130
+ end
131
+ end
132
+
133
+ # This action is called to read the state of the machine. The
134
+ # resulting state is expected to be put into the `:machine_state_id`
135
+ # key.
136
+ def self.action_read_state
137
+ Vagrant::Action::Builder.new.tap do |b|
138
+ b.use ConfigValidate
139
+ b.use ConnectvCenter
140
+ b.use ReadState
141
+ end
142
+ end
143
+
144
+ def self.action_ssh
145
+ Vagrant::Action::Builder.new.tap do |b|
146
+ b.use ConfigValidate
147
+ b.use Call, IsCreated do |env, b2|
148
+ unless env[:result]
149
+ b2.use MessageNotCreated
150
+ next
151
+ end
152
+ b2.use AnnounceSSHExec
153
+ end
154
+ end
155
+ end
156
+
157
+ def self.action_ssh_run
158
+ Vagrant::Action::Builder.new.tap do |b|
159
+ b.use ConfigValidate
160
+ b.use Call, IsCreated do |env, b2|
161
+ unless env[:result]
162
+ b2.use MessageNotCreated
163
+ next
164
+ end
165
+ b2.use SSHRun
166
+ end
167
+ end
168
+ end
169
+
170
+ def self.action_up
171
+ Vagrant::Action::Builder.new.tap do |b|
172
+ b.use ConfigValidate
173
+ b.use Call, IsCreated do |env, b2|
174
+ b2.use HandleBox unless env[:result]
175
+ end
176
+ b.use ConnectvCenter
177
+ b.use InventoryCheck
178
+ b.use Call, IsCreated do |env, b2|
179
+ b2.use BuildVM unless env[:result]
180
+ end
181
+ b.use action_start
182
+ b.use DisconnectvCenter
183
+ end
184
+ end
185
+
186
+ # The autoload farm
187
+ action_root = Pathname.new(File.expand_path('../action', __FILE__))
188
+ autoload :AnnounceSSHExec,
189
+ action_root.join('announce_ssh_exec')
190
+ autoload :BuildVM,
191
+ action_root.join('build_vm')
192
+ autoload :ConnectvCenter,
193
+ action_root.join('connect_vcenter')
194
+ autoload :Destroy,
195
+ action_root.join('destroy')
196
+ autoload :DisconnectvCenter,
197
+ action_root.join('disconnect_vcenter')
198
+ autoload :ForwardPorts,
199
+ action_root.join('forward_ports')
200
+ autoload :InventoryCheck,
201
+ action_root.join('inventory_check')
202
+ autoload :IsCreated,
203
+ action_root.join('is_created')
204
+ autoload :IsPaused,
205
+ action_root.join('is_paused')
206
+ autoload :IsRunning,
207
+ action_root.join('is_running')
208
+ autoload :MessageAlreadyRunning,
209
+ action_root.join('message_already_running')
210
+ autoload :MessageCannotSuspend,
211
+ action_root.join('message_cannot_suspend')
212
+ autoload :MessageNotCreated,
213
+ action_root.join('message_not_created')
214
+ autoload :MessageWillNotDestroy,
215
+ action_root.join('message_will_not_destroy')
216
+ autoload :PowerOff,
217
+ action_root.join('power_off')
218
+ autoload :PowerOn,
219
+ action_root.join('power_on')
220
+ autoload :ReadSSHInfo,
221
+ action_root.join('read_ssh_info')
222
+ autoload :ReadState,
223
+ action_root.join('read_state')
224
+ autoload :Resume,
225
+ action_root.join('resume')
226
+ autoload :Suspend,
227
+ action_root.join('suspend')
228
+ autoload :SyncFolders,
229
+ action_root.join('sync_folders')
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,19 @@
1
+ module VagrantPlugins
2
+ module VCenter
3
+ module Action
4
+ # Extends the Builtin SSHExec and announces the external IP.
5
+ class AnnounceSSHExec < Vagrant::Action::Builtin::SSHExec
6
+ def initialize(app, env)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ ssh_info = env[:machine].ssh_info
12
+ env[:ui].success('External IP for ' +
13
+ "#{env[:machine].name}: #{ssh_info[:host]}")
14
+ super
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,130 @@
1
+ require 'securerandom'
2
+ require 'etc'
3
+
4
+ module VagrantPlugins
5
+ module VCenter
6
+ module Action
7
+ # This class builds the VM to be used by Vagrant.
8
+ class BuildVM
9
+ def initialize(app, env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new('vagrant_vcenter::action::build_vm')
12
+ end
13
+
14
+ def call(env)
15
+ # FIXME: we need to find a way to clean things up when a SIGINT get
16
+ # called... see env[:interrupted] in the vagrant code
17
+
18
+ config = env[:machine].provider_config
19
+ vm_name = env[:machine].name
20
+
21
+ # FIXME: Raise a correct exception
22
+ dc = config.vcenter_cnx.serviceInstance.find_datacenter(
23
+ config.datacenter_name) or abort 'datacenter not found'
24
+
25
+ if config.template_folder_name.nil?
26
+ box_to_search = env[:machine].box.name.to_s
27
+ else
28
+ box_to_search = config.template_folder_name + '/' +
29
+ env[:machine].box.name.to_s
30
+ end
31
+
32
+ # FIXME: Raise a correct exception
33
+ computer = dc.find_compute_resource(
34
+ config.computer_name) or fail 'Host not found'
35
+ rp = computer.resourcePool
36
+
37
+ # FIXME: Raise a correct exception
38
+ template = dc.find_vm(
39
+ box_to_search) or abort 'VM not found'
40
+
41
+ if config.linked_clones
42
+ @logger.debug('DOING LINKED CLONE!')
43
+ # The API for linked clones is quite strange. We can't create a
44
+ # linked straight from any VM. The disks of the VM for which we can
45
+ # create a linked clone need to be read-only and thus VC demands
46
+ # that the VM we are cloning from uses delta-disks. Only then it
47
+ # will allow us to share the base disk.
48
+ #
49
+ # Thus, this code first create a delta disk on top of the base disk
50
+ # for the to-be-cloned VM, if delta disks aren't used already.
51
+ disks = template.config.hardware.device.grep(
52
+ RbVmomi::VIM::VirtualDisk)
53
+ disks.select { |x| x.backing.parent.nil? }.each do |disk|
54
+ spec = {
55
+ :deviceChange => [
56
+ {
57
+ :operation => :remove,
58
+ :device => disk
59
+ },
60
+ {
61
+ :operation => :add,
62
+ :fileOperation => :create,
63
+ :device => disk.dup.tap do |x|
64
+ x.backing = x.backing.dup
65
+ x.backing.fileName = "[#{disk.backing.datastore.name}]"
66
+ x.backing.parent = disk.backing
67
+ end
68
+ }
69
+ ]
70
+ }
71
+ template.ReconfigVM_Task(:spec => spec).wait_for_completion
72
+ end
73
+
74
+ relocate_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(
75
+ :diskMoveType => :moveChildMostDiskBacking,
76
+ :pool => rp)
77
+ else
78
+ relocate_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(
79
+ :pool => rp)
80
+ end
81
+
82
+ @logger.debug("Relocate Spec: #{relocate_spec.pretty_inspect}")
83
+
84
+ spec = RbVmomi::VIM.VirtualMachineCloneSpec(
85
+ :location => relocate_spec,
86
+ :powerOn => false,
87
+ :template => false)
88
+
89
+ @logger.debug("Spec: #{spec.pretty_inspect}")
90
+
91
+ vm_target = "Vagrant-#{Etc.getlogin}-" +
92
+ "#{vm_name}-#{Socket.gethostname.downcase}-" +
93
+ "#{SecureRandom.hex(4)}"
94
+
95
+ @logger.debug("VM name: #{vm_target}")
96
+
97
+ # FIXME: vm.parent brings us to the template folder, fix this with
98
+ # folder_path.
99
+
100
+ root_vm_folder = dc.vmFolder
101
+ vm_folder = root_vm_folder
102
+ unless config.folder_name.nil?
103
+ vm_folder = root_vm_folder.traverse(config.folder_name,
104
+ RbVmomi::VIM::Folder)
105
+ end
106
+ @logger.debug("folder for VM: #{vm_folder}")
107
+
108
+ template.CloneVM_Task(
109
+ :folder => vm_folder,
110
+ :name => vm_target,
111
+ :spec => spec).wait_for_completion
112
+
113
+ if config.folder_name.nil?
114
+ vm_to_search = vm_target
115
+ else
116
+ vm_to_search = config.folder_name + '/' + vm_target
117
+ end
118
+
119
+ @logger.debug("VM to search: #{vm_to_search}")
120
+
121
+ # FIXME: Raise a correct exception
122
+ env[:machine].id = dc.find_vm(
123
+ vm_to_search).config.uuid or abort 'VM not found'
124
+
125
+ @app.call env
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end