Module: Vixen::Bridge

Extended by:
FFI::Library, Constants
Includes:
Constants
Defined in:
lib/vixen/bridge.rb

Constant Summary

Constants included from Constants

Constants::VixApiVersion, Constants::VixCreateSnapshotOptions, Constants::VixError, Constants::VixEventType, Constants::VixFileAttributes, Constants::VixFindItemType, Constants::VixHandle, Constants::VixHandleType, Constants::VixHostOptions, Constants::VixPowerState, Constants::VixPropertyId, Constants::VixPropertyType, Constants::VixServiceProvider, Constants::VixVMOpenOptions, Constants::VixVMPowerOptions

Class Method Summary collapse

Class Method Details

.connect(hostType, hostname, port, username, password, &block) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/vixen/bridge.rb', line 70

def self.connect(hostType, hostname, port, username, password, &block)
  progress_proc = safe_proc_from_block &block
  hostname = "https://%s%s/sdk" % [hostname, port == 0 ? '' : ":#{port}"] if hostname
  Vixen.logger.info "connecting to %s with username %s" % [hostname.inspect, username.inspect]
  job = Vixen::Model::Job.new(VixHost_Connect(VixApiVersion[:api_version],
                               hostType,
                               hostname,
                               port,
                               username,
                               password,
                               0,
                               VixHandle[:invalid],
                               progress_proc,
                               nil))
  spin_until_job_complete("connect to host", job)
  pointer_to_handle do |host_handle_pointer|
    Vixen.logger.debug "getting handle from connection job"
    VixJob_Wait job.handle, VixPropertyId[:job_result_handle],
                :pointer, host_handle_pointer,
                :int, VixPropertyId[:none]
  end
end

.create_snapshot(vm_handle, name, description, &block) ⇒ Object



220
221
222
223
224
225
226
227
228
229
230
# File 'lib/vixen/bridge.rb', line 220

def self.create_snapshot(vm_handle, name, description, &block)
  progress_proc = safe_proc_from_block &block
  snapshot_handle = pointer_to_handle do |snapshot_handle_pointer|
    wait_for_async_handle_creation_job "create snapshot", snapshot_handle_pointer, 0.2, 0.2 do
      Vixen.logger.info "creating %s snapshot" % name
      VixVM_CreateSnapshot vm_handle, name, description,
                           VixCreateSnapshotOptions[:include_memory],
                           VixHandle[:invalid], progress_proc, nil
    end
  end
end

.current_power_state(vm_handle) ⇒ Object



365
366
367
# File 'lib/vixen/bridge.rb', line 365

def self.current_power_state(vm_handle)
  get_int_property vm_handle, VixPropertyId[:vm_power_state]
end

.current_snapshot(vm_handle) ⇒ Object



247
248
249
250
251
252
# File 'lib/vixen/bridge.rb', line 247

def self.current_snapshot(vm_handle)
  pointer_to_handle do |snapshot_handle_pointer|
    Vixen.logger.debug "retrieving current snapshot"
    VixVM_GetCurrentSnapshot vm_handle, snapshot_handle_pointer
  end
end

.destroy(handle) ⇒ Object



203
204
205
206
207
# File 'lib/vixen/bridge.rb', line 203

def self.destroy(handle)
  Vixen.logger.debug "destroying %s handle (%s)" %
    [Vixen::Constants::VixHandleType[Vix_GetHandleType(handle)], handle]
  Vix_ReleaseHandle handle
end

.disconnect(handle) ⇒ Object



197
198
199
200
201
# File 'lib/vixen/bridge.rb', line 197

def self.disconnect(handle)
  Vixen.logger.debug "disconnecting from %s handle (%s)" %
    [Vixen::Constants::VixHandleType[Vix_GetHandleType(handle)], handle]
  VixHost_Disconnect handle
end

.get_children(snapshot_handle) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/vixen/bridge.rb', line 273

def self.get_children(snapshot_handle)
  count = pointer_to_int { |int_pointer| VixSnapshot_GetNumChildren(snapshot_handle, int_pointer) }
  children = []
  count.times do |n|
    handle = pointer_to_handle do |handle_pointer|
      VixSnapshot_GetChild(snapshot_handle, n, handle_pointer)
    end
    child = Vixen::Model::Snapshot.new( handle )
    children << child
  end
  children
end

.get_int_property(handle, property_id) ⇒ Object



298
299
300
301
302
303
304
305
# File 'lib/vixen/bridge.rb', line 298

def self.get_int_property(handle, property_id)
  pointer_to_int do |int_pointer|
    Vixen.logger.debug "getting %s property" % Vixen::Constants::VixPropertyId[property_id]
    Vix_GetProperties(handle, property_id,
                      :pointer, int_pointer,
                      :int, VixPropertyId[:none])
  end
end

.get_parent(snapshot_handle) ⇒ Object



266
267
268
269
270
271
# File 'lib/vixen/bridge.rb', line 266

def self.get_parent(snapshot_handle)
  pointer_to_handle do |snapshot_handle_pointer|
    Vixen.logger.debug "retrieving snapshot parent"
    VixSnapshot_GetParent snapshot_handle, snapshot_handle_pointer
  end
end

.get_root_snapshots(vm_handle) ⇒ Object



254
255
256
257
258
259
260
261
262
263
264
# File 'lib/vixen/bridge.rb', line 254

def self.get_root_snapshots(vm_handle)
  count = pointer_to_int { |int_pointer| VixVM_GetNumRootSnapshots(vm_handle, int_pointer) }
  snapshots = []
  count.times do |n|
    handle = pointer_to_handle do |handle_pointer|
      VixVM_GetRootSnapshot(vm_handle, n, handle_pointer)
    end
    snapshots << Vixen::Model::Snapshot.new( handle )
  end
  snapshots
end

.get_string_property(handle, property_id) ⇒ Object



286
287
288
289
290
291
292
293
294
295
296
# File 'lib/vixen/bridge.rb', line 286

def self.get_string_property(handle, property_id)
  string = pointer_to_string do |string_pointer|
    Vixen.logger.debug "getting %s property" % Vixen::Constants::VixPropertyId[property_id]
    Vix_GetProperties(handle, property_id,
                      :pointer, string_pointer,
                      :int, VixPropertyId[:none])
  end
  value = string.read_string.dup
  Vix_FreeBuffer(string)
  return value
end

.library_locationObject



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/vixen/bridge.rb', line 11

def self.library_location
  kernel = Facter.value(:kernel) || ''
  arch = Facter.value(:architecture)
  case kernel.downcase
  when 'darwin'
    ext = 'dylib'
  when 'linux'
    ext = 'so'
  when 'windows'
    ext = 'dll'
  end
  File.join(File.dirname(__FILE__), %W[.. .. ext #{kernel} #{arch} libvixAllProducts.#{ext}])
end

.open_vm(host_handle, vm_path, &block) ⇒ Object



209
210
211
212
213
214
215
216
217
218
# File 'lib/vixen/bridge.rb', line 209

def self.open_vm(host_handle, vm_path, &block)
  progress_proc = safe_proc_from_block &block
  vm_handle = pointer_to_handle do |vm_handle_pointer|
    wait_for_async_handle_creation_job "open vm", vm_handle_pointer do
      Vixen.logger.info "opening %s" % vm_path
      VixHost_OpenVM host_handle, vm_path, VixVMOpenOptions[:normal],
                     VixHandle[:invalid], progress_proc, nil
    end
  end
end

.pointer_to(type, &block) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/vixen/bridge.rb', line 93

def self.pointer_to(type, &block)
  pointer = FFI::MemoryPointer.new type, 1
  err = yield pointer
  unless err == VixError[:ok]
    raise "problem executing pointer_to_#{type} block. (error: %s, %s)" %
      [err, Vix_GetErrorText(err, nil)]
  end
  pointer.send "read_#{type}".to_sym
end

.pointer_to_bool(&block) ⇒ Object



115
116
117
# File 'lib/vixen/bridge.rb', line 115

def self.pointer_to_bool(&block)
  (pointer_to :int, &block) != 0
end

.pointer_to_handle(&block) ⇒ Object



103
104
105
# File 'lib/vixen/bridge.rb', line 103

def self.pointer_to_handle(&block)
  pointer_to :int, &block
end

.pointer_to_int(&block) ⇒ Object



111
112
113
# File 'lib/vixen/bridge.rb', line 111

def self.pointer_to_int(&block)
  pointer_to :int, &block
end

.pointer_to_string(&block) ⇒ Object



107
108
109
# File 'lib/vixen/bridge.rb', line 107

def self.pointer_to_string(&block)
  pointer_to :pointer, &block
end

.power_off(vm_handle, &block) ⇒ Object



328
329
330
331
332
333
334
# File 'lib/vixen/bridge.rb', line 328

def self.power_off(vm_handle, &block)
  progress_proc = safe_proc_from_block &block
  wait_for_async_job "power off VM" do
    Vixen.logger.debug "powering off vm (%s)" % vm_handle
    VixVM_PowerOff vm_handle, VixVMPowerOptions[:normal], progress_proc, nil
  end
end

.power_off_using_guest(vm_handle, &block) ⇒ Object



315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/vixen/bridge.rb', line 315

def self.power_off_using_guest(vm_handle, &block)
  begin
    progress_proc = safe_proc_from_block &block
    wait_for_async_job "power off VM using tools" do
      Vixen.logger.debug "powering off vm (%s)" % vm_handle
      VixVM_PowerOff vm_handle, VixVMPowerOptions[:from_guest], progress_proc, nil
    end
    true
  rescue
    false
  end
end

.power_on(vm_handle, &block) ⇒ Object



307
308
309
310
311
312
313
# File 'lib/vixen/bridge.rb', line 307

def self.power_on(vm_handle, &block)
  progress_proc = safe_proc_from_block &block
  wait_for_async_job "power on VM" do
    Vixen.logger.debug "powering on vm (%s)" % vm_handle
    VixVM_PowerOn vm_handle, VixVMPowerOptions[:normal], VixHandle[:invalid], progress_proc, nil
  end
end

.remove_snapshot(vm, snapshot, &block) ⇒ Object



240
241
242
243
244
245
# File 'lib/vixen/bridge.rb', line 240

def self.remove_snapshot(vm, snapshot, &block)
  progress_proc = safe_proc_from_block &block
  wait_for_async_job(("remove %s snapshot" % snapshot.display_name), 0.2, 0.2) do
    VixVM_RemoveSnapshot vm.handle, snapshot.handle, 0, progress_proc, nil
  end
end

.reset(vm_handle, &block) ⇒ Object



349
350
351
352
353
354
355
# File 'lib/vixen/bridge.rb', line 349

def self.reset(vm_handle, &block)
  progress_proc = safe_proc_from_block &block
  wait_for_async_job "reset VM" do
    Vixen.logger.debug "resetting vm (%s)" % vm_handle
    VixVM_Reset vm_handle, VixVMPowerOptions[:normal], progress_proc, nil
  end
end

.reset_using_guest(vm_handle, &block) ⇒ Object



336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/vixen/bridge.rb', line 336

def self.reset_using_guest(vm_handle, &block)
  begin
    progress_proc = safe_proc_from_block &block
    wait_for_async_job "reset VM using tools" do
      Vixen.logger.debug "resetting vm (%s)" % vm_handle
      VixVM_Reset vm_handle, VixVMPowerOptions[:from_guest], progress_proc, nil
    end
    true
  rescue
    false
  end
end

.revert_to_snapshot(vm, snapshot, &block) ⇒ Object



232
233
234
235
236
237
238
# File 'lib/vixen/bridge.rb', line 232

def self.revert_to_snapshot(vm, snapshot, &block)
  progress_proc = safe_proc_from_block &block
  wait_for_async_job(("revert to %s snapshot" % snapshot.display_name), 0.2, 0.2) do
    VixVM_RevertToSnapshot vm.handle, snapshot.handle, VixVMPowerOptions[:normal],
                           VixHandle[:invalid], progress_proc, nil
  end
end

.running_vms(host_handle, &block) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/vixen/bridge.rb', line 168

def self.running_vms(host_handle, &block)
  available_vms = []

  collect_proc = safe_proc_from_block do |job_handle, event_type, more_event_info, client_data|
    if event_type == VixEventType[:find_item]
      path = get_string_property more_event_info, VixPropertyId[:found_item_location]
      if path
        Vixen.logger.debug "adding running vms %s" % path
        available_vms << path
      end
    end
    if block_given?
      Vixen.logger.debug "preparing to call user-supplied block for running vms progress"
      block.call job_handle, event_type, more_event_info, client_data
    end
  end

  Vixen.logger.debug "finding running vms"
  job = Vixen::Model::Job.new(VixHost_FindItems(host_handle,
                                 VixFindItemType[:running_vms],
                                 VixHandle[:invalid],
                                 -1,
                                 collect_proc,
                                 nil))
  spin_until_job_complete "running vms", job

  available_vms
end

.safe_proc_from_block(&block) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/vixen/bridge.rb', line 59

def self.safe_proc_from_block(&block)
  return nil unless block_given?
  Proc.new do |*args|
    begin
      block.call args
    rescue
      puts STDERR, $!
    end
  end
end

.spin_until_job_complete(operation, job, initial_sleep_time = 0.1, sleep_increment = 0.02) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/vixen/bridge.rb', line 150

def self.spin_until_job_complete(operation, job, initial_sleep_time = 0.1, sleep_increment = 0.02)
  sleep_time = initial_sleep_time
  while ( not pointer_to_bool do |bool_pointer|
    Vixen.logger.debug "sleeping waiting for %s job (%s) to complete" %
      [operation, job.handle]
    sleep sleep_time
    sleep_time += sleep_increment
    Vixen.logger.debug "checking completion of %s job (%s)" %
      [operation, job.handle]
    thr = Thread.start { sleep 0.01; VixJob_CheckCompletion(job.handle, bool_pointer) }
    Vixen.logger.debug "waiting for thread to complete"
    x = thr.value
    Vixen.logger.debug "thread completed with #{x}"
    x
  end) do
  end
end

.suspend(vm_handle, &block) ⇒ Object



357
358
359
360
361
362
363
# File 'lib/vixen/bridge.rb', line 357

def self.suspend(vm_handle, &block)
  progress_proc = safe_proc_from_block &block
  wait_for_async_job "suspend VM" do
    Vixen.logger.debug "suspending vm (%s)" % vm_handle
    VixVM_Suspend vm_handle, VixVMPowerOptions[:normal], progress_proc, nil
  end
end

.wait_for_async_handle_creation_job(operation, pointer_to_handle, initial_sleep_time = 0.1, sleep_increment = 0.02, &block) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/vixen/bridge.rb', line 133

def self.wait_for_async_handle_creation_job(operation, pointer_to_handle, initial_sleep_time = 0.1, sleep_increment = 0.02, &block)
  job = Vixen::Model::Job.new(yield)
  Vixen.logger.debug "Waiting for async %s job (%s) to create a new handle" %
    [operation, job.handle]
  spin_until_job_complete(operation, job, initial_sleep_time, sleep_increment)
  err = VixJob_Wait job.handle, VixPropertyId[:job_result_handle],
              :pointer, pointer_to_handle,
              :int, VixPropertyId[:none]
  unless err == VixError[:ok]
    Vixen.logger.error "While executing %s VIX API returned error: %s: %s" %
      [operation, err, Vix_GetErrorText(err, nil)]
    raise "couldn't %s. (error: %s, %s)" %
      [operation, err, Vix_GetErrorText(err, nil)]
  end
  err
end

.wait_for_async_job(operation, initial_sleep_time = 0.1, sleep_increment = 0.02, &block) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/vixen/bridge.rb', line 119

def self.wait_for_async_job(operation, initial_sleep_time = 0.1, sleep_increment = 0.02, &block)
  job = Vixen::Model::Job.new(yield)
  Vixen.logger.debug "Waiting for async %s job (%s)" %
    [operation, job.handle]
  spin_until_job_complete(operation, job, initial_sleep_time, sleep_increment)
  err = VixJob_Wait job.handle, VixPropertyId[:none]
  unless err == VixError[:ok]
    Vixen.logger.error "While executing %s VIX API returned error: %s: %s" %
      [operation, err, Vix_GetErrorText(err, nil)]
    raise "couldn't %s. (error: %s, %s)" %
      [operation, err, Vix_GetErrorText(err, nil)]
  end
end