vagrant-vcenter 0.0.2.pre.dev

Sign up to get free protection for your applications and to get access to all the features.
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