vixen 0.0.7 → 0.0.8

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.
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: