vixen 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -123,6 +123,8 @@ Vixen::Model::VM
123
123
 
124
124
  * `current_snapshot`
125
125
  * `create_snapshot`
126
+ * `revert_to_snapshot`
127
+ * `remove_snapshot`
126
128
  * Power Operations
127
129
  * `power_on`
128
130
  * `power_off`
@@ -145,7 +147,74 @@ Vixen::Model::Snapshot
145
147
  * `parent` - the parent snapshot, if any
146
148
  * `full_name` - the full name of the snapshot (traverses parent hierarchy)
147
149
 
150
+ Progress Callbacks
151
+ ==================
152
+
153
+ The VIX API allows for progress callbacks which Vixen exposes through the use
154
+ of blocks passed to the method.
155
+
156
+ ```ruby
157
+ require 'rubygems'
158
+ require 'vixen'
159
+
160
+ #Vixen.logger.level = Logger::DEBUG
161
+ start = Time.now
162
+
163
+ def elapsed_time(start)
164
+ "[%s]" % (Time.at(Time.now - start).utc.strftime '%T')
165
+ end
166
+
167
+ host = Vixen.local_connect
168
+
169
+ vm = host.open_vm '/Users/jeff/Desktop/centos-5.8-pe-2.5.3-vmware/centos-5.8-pe-2.5.3-vmware.vmx' do |*args|
170
+ print "\r#{elapsed_time(start)} waiting for my vm to open"
171
+ $stdout.flush
172
+ end
173
+
174
+ vm.resume do |*args|
175
+ print "\r#{elapsed_time(start)} resuming..."
176
+ $stdout.flush
177
+ end
178
+ puts
179
+
180
+ previous_snapshot = vm.current_snapshot
181
+
182
+ puts "#{elapsed_time(start)} previous_snapshot: #{previous_snapshot}"
183
+
184
+ snapshot_name = "vixen-created #{Time.now}"
185
+ new_snapshot = vm.create_snapshot snapshot_name do |*args|
186
+ print "\r#{elapsed_time(start)} creating snapshot: #{snapshot_name}"
187
+ $stdout.flush
188
+ end
189
+ puts
190
+
191
+ vm.revert_to_snapshot previous_snapshot do |*args|
192
+ print "\r#{elapsed_time(start)} reverting to #{previous_snapshot}..."
193
+ $stdout.flush
194
+ end
195
+ puts
196
+
197
+ vm.suspend do |*args|
198
+ print "\r#{elapsed_time(start)} suspending..."
199
+ $stdout.flush
200
+ end
201
+ puts
202
+ ```
203
+
204
+ produces output like
205
+
206
+ ```shell
207
+ $ ruby vixen-example.rb
208
+ [00:00:00] waiting for my vm to open
209
+ [00:00:02] resuming...
210
+ [00:00:02] previous_snapshot: vixen-created
211
+ [00:02:18] creating snapshot: vixen-created Tue Nov 20 02:18:04 -0800 2012
212
+ [00:02:33] reverting to vixen-created...
213
+ [00:02:36] reverting to vixen-created...
214
+ [00:02:38] suspending...
215
+ ```
216
+
148
217
  See Also
149
- --------
218
+ ========
150
219
 
151
220
  * [Official VMware VIX 1.12 documentation](http://www.vmware.com/support/developer/vix-api/vix112_reference/)
@@ -4,12 +4,12 @@ module Vixen
4
4
 
5
5
  @@logger = nil
6
6
 
7
- def self.local_connect(login = nil, password = nil)
8
- connect Vixen::Constants::VixServiceProvider[:vmware_workstation], nil, 0, login, password
7
+ def self.local_connect(login = nil, password = nil, &block)
8
+ connect Vixen::Constants::VixServiceProvider[:vmware_workstation], nil, 0, login, password, &block
9
9
  end
10
10
 
11
- def self.connect(host_type, hostname, port, username, password)
12
- handle = Vixen::Bridge.connect(host_type, hostname, port, username, password)
11
+ def self.connect(host_type, hostname, port, username, password, &block)
12
+ handle = Vixen::Bridge.connect(host_type, hostname, port, username, password, &block)
13
13
  Vixen::Model::Host.new(handle)
14
14
  end
15
15
 
@@ -42,11 +42,30 @@ module Vixen::Bridge
42
42
  attach_function :VixVM_GetCurrentSnapshot, [:handle, :pointer], :int
43
43
  attach_function :VixSnapshot_GetParent, [:handle, :pointer], :int
44
44
  attach_function :VixVM_PowerOn, [:handle, :int, :handle, :VixEventProc, :pointer], :handle
45
+ attach_function :VixVM_PowerOff, [:handle, :int, :VixEventProc, :pointer], :handle
46
+ attach_function :VixVM_Reset, [:handle, :int, :VixEventProc, :pointer], :handle
47
+ attach_function :VixVM_Suspend, [:handle, :int, :VixEventProc, :pointer], :handle
45
48
  attach_function :VixVM_CreateSnapshot, [:handle, :string, :string, :int, :handle, :VixEventProc, :pointer], :handle
49
+ attach_function :VixVM_RevertToSnapshot, [:handle, :handle, :int, :handle, :VixEventProc, :pointer], :handle
50
+ attach_function :VixVM_RemoveSnapshot, [:handle, :handle, :int, :VixEventProc, :pointer], :handle
46
51
  attach_function :VixJob_CheckCompletion, [:handle, :pointer], :int
47
52
  attach_function :Vix_GetHandleType, [:handle], :int
48
53
 
49
- def self.connect(hostType, hostname, port, username, password)
54
+ @@all_my_blocks = []
55
+
56
+ def self.safe_proc_from_block(&block)
57
+ return nil unless block_given?
58
+ Proc.new do |*args|
59
+ begin
60
+ block.call args
61
+ rescue
62
+ puts STDERR, $!
63
+ end
64
+ end
65
+ end
66
+
67
+ def self.connect(hostType, hostname, port, username, password, &block)
68
+ progress_proc = safe_proc_from_block &block
50
69
  hostname = "https://%s%s/sdk" % [hostname, port == 0 ? '' : ":#{port}"] if hostname
51
70
  Vixen.logger.info "connecting to %s with username %s" % [hostname.inspect, username.inspect]
52
71
  job = Vixen::Model::Job.new(VixHost_Connect(VixApiVersion[:api_version],
@@ -57,10 +76,11 @@ module Vixen::Bridge
57
76
  password,
58
77
  0,
59
78
  VixHandle[:invalid],
60
- nil,
79
+ progress_proc,
61
80
  nil))
81
+ spin_until_job_complete("connect to host", job)
62
82
  pointer_to_handle do |host_handle_pointer|
63
- Vixen.logger.debug "waiting for connection to complete"
83
+ Vixen.logger.debug "getting handle from connection job"
64
84
  VixJob_Wait job.handle, VixPropertyId[:job_result_handle],
65
85
  :pointer, host_handle_pointer,
66
86
  :int, VixPropertyId[:none]
@@ -93,10 +113,11 @@ module Vixen::Bridge
93
113
  (pointer_to :int, &block) != 0
94
114
  end
95
115
 
96
- def self.wait_for_async_job(operation, &block)
116
+ def self.wait_for_async_job(operation, initial_sleep_time = 0.1, sleep_increment = 0.02, &block)
97
117
  job = Vixen::Model::Job.new(yield)
98
118
  Vixen.logger.debug "Waiting for async %s job (%s)" %
99
119
  [operation, job.handle]
120
+ spin_until_job_complete(operation, job, initial_sleep_time, sleep_increment)
100
121
  err = VixJob_Wait job.handle, VixPropertyId[:none]
101
122
  unless err == VixError[:ok]
102
123
  Vixen.logger.error "While executing %s VIX API returned error: %s: %s" %
@@ -106,10 +127,11 @@ module Vixen::Bridge
106
127
  end
107
128
  end
108
129
 
109
- def self.wait_for_async_handle_creation_job(operation, pointer_to_handle, &block)
130
+ def self.wait_for_async_handle_creation_job(operation, pointer_to_handle, initial_sleep_time = 0.1, sleep_increment = 0.02, &block)
110
131
  job = Vixen::Model::Job.new(yield)
111
132
  Vixen.logger.debug "Waiting for async %s job (%s) to create a new handle" %
112
133
  [operation, job.handle]
134
+ spin_until_job_complete(operation, job, initial_sleep_time, sleep_increment)
113
135
  err = VixJob_Wait job.handle, VixPropertyId[:job_result_handle],
114
136
  :pointer, pointer_to_handle,
115
137
  :int, VixPropertyId[:none]
@@ -122,15 +144,20 @@ module Vixen::Bridge
122
144
  err
123
145
  end
124
146
 
125
- def self.spin_until_job_complete(operation, job)
147
+ def self.spin_until_job_complete(operation, job, initial_sleep_time = 0.1, sleep_increment = 0.02)
148
+ sleep_time = initial_sleep_time
126
149
  while ( not pointer_to_bool do |bool_pointer|
127
150
  Vixen.logger.debug "sleeping waiting for %s job (%s) to complete" %
128
151
  [operation, job.handle]
129
- sleep 0.01
152
+ sleep sleep_time
153
+ sleep_time += sleep_increment
130
154
  Vixen.logger.debug "checking completion of %s job (%s)" %
131
155
  [operation, job.handle]
132
- thr = Thread.start { VixJob_CheckCompletion(job.handle, bool_pointer) }
133
- thr.value
156
+ thr = Thread.start { sleep 0.01; VixJob_CheckCompletion(job.handle, bool_pointer) }
157
+ Vixen.logger.debug "waiting for thread to complete"
158
+ x = thr.value
159
+ Vixen.logger.debug "thread completed with #{x}"
160
+ x
134
161
  end) do
135
162
  end
136
163
  end
@@ -138,7 +165,7 @@ module Vixen::Bridge
138
165
  def self.running_vms(host_handle, &block)
139
166
  available_vms = []
140
167
 
141
- collect_proc = Proc.new do |job_handle, event_type, more_event_info, client_data|
168
+ collect_proc = safe_proc_from_block do |job_handle, event_type, more_event_info, client_data|
142
169
  if event_type == VixEventType[:find_item]
143
170
  path = get_string_property more_event_info, VixPropertyId[:found_item_location]
144
171
  if path
@@ -176,27 +203,44 @@ module Vixen::Bridge
176
203
  Vix_ReleaseHandle handle
177
204
  end
178
205
 
179
- def self.open_vm(host_handle, vm_path)
206
+ def self.open_vm(host_handle, vm_path, &block)
207
+ progress_proc = safe_proc_from_block &block
180
208
  vm_handle = pointer_to_handle do |vm_handle_pointer|
181
209
  wait_for_async_handle_creation_job "open vm", vm_handle_pointer do
182
210
  Vixen.logger.info "opening %s" % vm_path
183
211
  VixHost_OpenVM host_handle, vm_path, VixVMOpenOptions[:normal],
184
- VixHandle[:invalid], nil, nil
212
+ VixHandle[:invalid], progress_proc, nil
185
213
  end
186
214
  end
187
215
  end
188
216
 
189
- def self.create_snapshot(vm_handle, name, description)
217
+ def self.create_snapshot(vm_handle, name, description, &block)
218
+ progress_proc = safe_proc_from_block &block
190
219
  snapshot_handle = pointer_to_handle do |snapshot_handle_pointer|
191
- wait_for_async_handle_creation_job "create snapshot", snapshot_handle_pointer do
220
+ wait_for_async_handle_creation_job "create snapshot", snapshot_handle_pointer, 1, 0.2 do
192
221
  Vixen.logger.info "creating %s snapshot" % name
193
222
  VixVM_CreateSnapshot vm_handle, name, description,
194
223
  VixCreateSnapshotOptions[:include_memory],
195
- VixHandle[:invalid], nil, nil
224
+ VixHandle[:invalid], progress_proc, nil
196
225
  end
197
226
  end
198
227
  end
199
228
 
229
+ def self.revert_to_snapshot(vm, snapshot, &block)
230
+ progress_proc = safe_proc_from_block &block
231
+ wait_for_async_job(("revert to %s snapshot" % snapshot.display_name), 1, 0.2) do
232
+ VixVM_RevertToSnapshot vm.handle, snapshot.handle, VixVMPowerOptions[:normal],
233
+ VixHandle[:invalid], progress_proc, nil
234
+ end
235
+ end
236
+
237
+ def self.remove_snapshot(vm, snapshot, &block)
238
+ progress_proc = safe_proc_from_block &block
239
+ wait_for_async_job(("remove %s snapshot" % snapshot.display_name), 1, 0.2) do
240
+ VixVM_RemoveSnapshot vm.handle, snapshot.handle, 0, progress_proc, nil
241
+ end
242
+ end
243
+
200
244
  def self.current_snapshot(vm_handle)
201
245
  pointer_to_handle do |snapshot_handle_pointer|
202
246
  Vixen.logger.debug "retrieving current snapshot"
@@ -218,7 +262,7 @@ module Vixen::Bridge
218
262
  :pointer, string_pointer,
219
263
  :int, VixPropertyId[:none])
220
264
  end
221
- value = string.read_string.force_encoding("UTF-8").dup
265
+ value = string.read_string.dup
222
266
  Vix_FreeBuffer(string)
223
267
  return value
224
268
  end
@@ -232,31 +276,61 @@ module Vixen::Bridge
232
276
  end
233
277
  end
234
278
 
235
- def self.power_on(vm_handle)
279
+ def self.power_on(vm_handle, &block)
280
+ progress_proc = safe_proc_from_block &block
236
281
  wait_for_async_job "power on VM" do
237
282
  Vixen.logger.debug "powering on vm (%s)" % vm_handle
238
- VixVM_PowerOn vm_handle, VixVMPowerOptions[:normal], VixHandle[:invalid], nil, nil
283
+ VixVM_PowerOn vm_handle, VixVMPowerOptions[:normal], VixHandle[:invalid], progress_proc, nil
284
+ end
285
+ end
286
+
287
+ def self.power_off_using_guest(vm_handle, &block)
288
+ begin
289
+ progress_proc = safe_proc_from_block &block
290
+ wait_for_async_job "power off VM using tools" do
291
+ Vixen.logger.debug "powering off vm (%s)" % vm_handle
292
+ VixVM_PowerOff vm_handle, VixVMPowerOptions[:from_guest], progress_proc, nil
293
+ end
294
+ true
295
+ rescue
296
+ false
239
297
  end
240
298
  end
241
299
 
242
- def self.power_off(vm_handle)
300
+ def self.power_off(vm_handle, &block)
301
+ progress_proc = safe_proc_from_block &block
243
302
  wait_for_async_job "power off VM" do
244
303
  Vixen.logger.debug "powering off vm (%s)" % vm_handle
245
- VixVM_PowerOff vm_handle, VixVMPowerOptions[:normal], nil, nil
304
+ VixVM_PowerOff vm_handle, VixVMPowerOptions[:normal], progress_proc, nil
305
+ end
306
+ end
307
+
308
+ def self.reset_using_guest(vm_handle, &block)
309
+ begin
310
+ progress_proc = safe_proc_from_block &block
311
+ wait_for_async_job "reset VM using tools" do
312
+ Vixen.logger.debug "resetting vm (%s)" % vm_handle
313
+ VixVM_Reset vm_handle, VixVMPowerOptions[:from_guest], progress_proc, nil
314
+ end
315
+ true
316
+ rescue
317
+ false
246
318
  end
247
319
  end
248
320
 
249
- def self.reset(vm_handle)
321
+ def self.reset(vm_handle, &block)
322
+ progress_proc = safe_proc_from_block &block
250
323
  wait_for_async_job "reset VM" do
251
324
  Vixen.logger.debug "resetting vm (%s)" % vm_handle
252
- VixVM_Reset vm_handle, VixVMPowerOptions[:normal], nil, nil
325
+ VixVM_Reset vm_handle, VixVMPowerOptions[:normal], progress_proc, nil
253
326
  end
254
327
  end
255
328
 
256
- def self.suspend(vm_handle)
329
+ def self.suspend(vm_handle, &block)
330
+ progress_proc = safe_proc_from_block &block
257
331
  wait_for_async_job "suspend VM" do
258
332
  Vixen.logger.debug "suspending vm (%s)" % vm_handle
259
- VixVM_Suspend vm_handle, VixVMPowerOptions[:normal], nil, nil
333
+ VixVM_Suspend vm_handle, VixVMPowerOptions[:normal], progress_proc, nil
260
334
  end
261
335
  end
262
336
 
@@ -7,32 +7,56 @@ class Vixen::Model::VM < Vixen::Model::Base
7
7
  Vixen::Model::Snapshot.new(Vixen::Bridge.current_snapshot(handle))
8
8
  end
9
9
 
10
- def create_snapshot(name, description)
11
- Vixen::Model::Snapshot.new(Vixen::Bridge.create_snapshot handle, name, description)
10
+ def create_snapshot(name, description="", &block)
11
+ Vixen::Model::Snapshot.new(Vixen::Bridge.create_snapshot handle, name, description, &block)
12
12
  end
13
13
 
14
- def power_on
14
+ def revert_to_snapshot(snapshot, &block)
15
+ Vixen::Bridge.revert_to_snapshot self, snapshot, &block
16
+ end
17
+
18
+ def remove_snapshot(snapshot, &block)
19
+ Vixen::Bridge.remove_snaphost self, snapshot, &block
20
+ end
21
+
22
+ def power_on(&block)
15
23
  return self if powered_on? or powering_on? or resuming? or resetting?
16
- Vixen::Bridge.power_on handle
24
+ Vixen::Bridge.power_on handle, &block
17
25
  self
18
26
  end
19
27
 
20
- def resume
21
- power_on
28
+ def resume(&block)
29
+ power_on &block
22
30
  end
23
31
 
24
- def suspend
25
- Vixen::Bridge.suspend handle
32
+ def suspend(&block)
33
+ Vixen::Bridge.suspend handle, &block
26
34
  self
27
35
  end
28
36
 
29
- def power_off
30
- Vixen::Bridge.power_off handle
37
+ def power_off(opts={}, &block)
38
+ hard_power_off = opts[:hard] || :if_necessary
39
+ case hard_power_off
40
+ when :if_necessary
41
+ Vixen::Bridge.power_off_using_guest(handle, &block) || Vixen::Bridge.power_off(handle, &block)
42
+ when :always
43
+ Vixen::Bridge.power_off(handle, &block)
44
+ else
45
+ Vixen::Bridge.power_off_using_guest(handle, &block)
46
+ end
31
47
  self
32
48
  end
33
49
 
34
- def reset
35
- Vixen::Bridge.reset handle
50
+ def reset(opts={}, &block)
51
+ hard_reset = opts[:hard] || :if_necessary
52
+ case hard_reset
53
+ when :if_necessary
54
+ Vixen::Bridge.reset_using_guest(handle, &block) || Vixen::Bridge.reset(handle, &block)
55
+ when :always
56
+ Vixen::Bridge.reset(handle, &block)
57
+ else
58
+ Vixen::Bridge.reset_using_guest(handle, &block)
59
+ end
36
60
  self
37
61
  end
38
62
 
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'vixen'
3
+
4
+ #Vixen.logger.level = Logger::DEBUG
5
+ start = Time.now
6
+
7
+ def elapsed_time(start)
8
+ "[%s]" % (Time.at(Time.now - start).utc.strftime '%T')
9
+ end
10
+
11
+ host = Vixen.local_connect
12
+
13
+ vm = host.open_vm '/Users/jeff/Desktop/centos-5.8-pe-2.5.3-vmware/centos-5.8-pe-2.5.3-vmware.vmx' do |*args|
14
+ print "\r#{elapsed_time(start)} waiting for my vm to open"
15
+ $stdout.flush
16
+ end
17
+
18
+ vm.resume do |*args|
19
+ print "\r#{elapsed_time(start)} resuming..."
20
+ $stdout.flush
21
+ end
22
+ puts
23
+
24
+ previous_snapshot = vm.current_snapshot
25
+
26
+ puts "#{elapsed_time(start)} previous_snapshot: #{previous_snapshot}"
27
+
28
+ snapshot_name = "vixen-created #{Time.now}"
29
+ new_snapshot = vm.create_snapshot snapshot_name do |*args|
30
+ print "\r#{elapsed_time(start)} creating snapshot: #{snapshot_name}"
31
+ $stdout.flush
32
+ end
33
+ puts
34
+
35
+ vm.revert_to_snapshot previous_snapshot do |*args|
36
+ print "\r#{elapsed_time(start)} reverting to #{previous_snapshot}..."
37
+ $stdout.flush
38
+ end
39
+ puts
40
+
41
+ vm.remove_snapshot new_snapshot do |*args|
42
+ print "\r#{elapsed_time(start)} deleting snapshot: #{new_snapshot}"
43
+ $stdout.flush
44
+ end
45
+
46
+ vm.suspend do |*args|
47
+ print "\r#{elapsed_time(start)} suspending..."
48
+ $stdout.flush
49
+ end
50
+ puts
51
+
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'vixen'
3
- s.version = '0.0.7'
3
+ s.version = '0.0.8'
4
4
  s.summary = 'Ruby bindings for VMware VIX API'
5
5
  s.description = <<-EOF
6
6
  Vixen is an easy way to interact with VMware virtual machines from Ruby.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vixen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -66,6 +66,7 @@ files:
66
66
  - lib/vixen/model/job.rb
67
67
  - lib/vixen/model/snapshot.rb
68
68
  - lib/vixen/model/vm.rb
69
+ - vixen-example.rb
69
70
  - vixen.gemspec
70
71
  homepage: https://github.com/jeffweiss/vixen
71
72
  licenses: