Class: VBOX::CmdLineAPI

Inherits:
Object
  • Object
show all
Defined in:
lib/vbox/cli.rb

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ CmdLineAPI

Returns a new instance of CmdLineAPI.



185
186
187
188
189
# File 'lib/vbox/cli.rb', line 185

def initialize options={}
  @options = options
  @options[:verbose] ||= 2 if @options[:dry_run]
  @options[:verbose] ||= 0
end

Instance Method Details

#_clone(old_vm_name) ⇒ Object



353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/vbox/cli.rb', line 353

def _clone old_vm_name
  args = []
  if new_vm_name = @options['name'] || _gen_vm_name(old_vm_name)
    args += ["--name", new_vm_name]
  end

  snapshot = @clone_use_snapshot ||= case @options[:snapshot]
    when 'new', 'take', 'make'
      take_snapshot(old_vm_name, new_vm_name ? {:name => "for #{new_vm_name}"} : {})
    when 'last'
      get_snapshots(old_vm_name).last
    else
      puts "[!] please gimme --snapshot=LAST OR --snapshot=NEW option"
      exit 1
    end
  unless snapshot
    puts "[!] failed to get snapshot, cannot continue".red
    exit 1
  end

  args += ["--options","link"]
  args += ["--register"]
  args += ["--snapshot", snapshot.uuid]

  system "VBoxManage", "clonevm", old_vm_name, *args

  get_vm_info(old_vm_name).each do |k,v|
    if k =~ /^macaddress/
      old_mac = v.tr('"','').downcase
      puts "[.] old #{k}=#{old_mac}"
      old_automac = _name2macpart(old_vm_name)
      if old_automac && old_mac[-old_automac.size..-1] == old_automac
        new_automac = _name2macpart(new_vm_name)
        new_mac = old_mac[0,old_mac.size-new_automac.size] + new_automac
        puts "[.] new #{k}=#{new_mac}"
        modify new_vm_name, k, new_mac, :quiet => true
      end
    end
  end
end

#_gen_vm_name(parent_name) ⇒ Object

d0 -> d1, d2, d3 d1 -> d1.1, d1.2, d1.3 d1.1 -> d1.1.1, d1.1.2, d1.1.3



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/vbox/cli.rb', line 308

def _gen_vm_name parent_name
  # try to guess new name
  numbers = parent_name.scan /\d+/
  if numbers.any?
    lastnum = numbers.last
    names = list_vms.map(&:name)
    if lastnum.to_i == 0
      # d0 -> d1, d2, d3
      newnum = lastnum.to_i + 1
      while true
        newname = parent_name.dup
        newname[parent_name.rindex(lastnum),lastnum.size] = newnum.to_s
        return newname unless names.include?(newname)
        newnum += 1
      end
    else
      # d1   -> d1.1, d1.2, d1.3
      # d1.1 -> d1.1.1, d1.1.2, d1.1.3
      newnum = 1
      while true
        newname = "#{parent_name}.#{newnum}"
        return newname unless names.include?(newname)
        newnum += 1
      end
    end
  end
  nil
end

#_name2macpart(name) ⇒ Object



343
344
345
346
# File 'lib/vbox/cli.rb', line 343

def _name2macpart name
  r = name.scan(/\d+/).map{ |x| "%02x" % x }.join
  r == '' ? nil : r
end

#`(cmd) ⇒ Object

run as in backtick operator, and return result



192
193
194
195
196
197
198
# File 'lib/vbox/cli.rb', line 192

def ` cmd
  puts "[.] #{cmd}".gray if @options[:verbose] >= 2
  exit if @options[:dry_run]
  r = super
  #exit 1 unless $?.success?
  r
end

#clone(old_vm_name) ⇒ Object



348
349
350
351
# File 'lib/vbox/cli.rb', line 348

def clone old_vm_name
  @clone_use_snapshot = nil
  (@options[:clones] || 1).times{ _clone(old_vm_name) }
end

#delete(name) ⇒ Object



402
403
404
# File 'lib/vbox/cli.rb', line 402

def delete name
  system "VBoxManage", "unregistervm", name, "--delete"
end

#get_snapshots(_name) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/vbox/cli.rb', line 284

def get_snapshots _name
  r = []
  name = uuid = nil
  `VBoxManage snapshot "#{_name}" list --machinereadable`.strip.each_line do |line|
    k,v = line.strip.split('=',2)
    next unless v
    v = v.strip.sub(/^"/,'').sub(/"$/,'')
    case k
    when /SnapshotName/
      name = v
    when /SnapshotUUID/
      uuid = v
    end
    if name && uuid
      r << Snapshot.new(name, uuid)
      name = uuid = nil
    end
  end
  r
end

#get_vm_details(vm) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/vbox/cli.rb', line 209

def get_vm_details vm
  data = `VBoxManage showvminfo #{vm.uuid} --machinereadable`
  data.each_line do |line|
    a = line.strip.split('=',2)
    next unless a.size == 2
    k,v = a
    case k
    when 'memory'
      vm.memory_size = v.to_i
    when 'VMState'
      vm.state = v.tr('"','').to_sym
    when 'CfgFile'
      dir = File.dirname(v.tr('"',''))
      s = `du -s -BM "#{dir}"`
      vm.dir_size = s.split("\t").first.tr("M","")
    end
  end
  vm
end

#get_vm_info(name) ⇒ Object



247
248
249
250
251
252
253
254
255
256
# File 'lib/vbox/cli.rb', line 247

def get_vm_info name
  data = `VBoxManage showvminfo "#{name}" --machinereadable`
  h = {}
  data.each_line do |line|
    line.strip!
    k,v = line.split('=',2)
    h[k] = v
  end
  h
end

#list_vms(params = {}) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/vbox/cli.rb', line 229

def list_vms params = {}
  if params[:running]
    data = `VBoxManage list runningvms`
  else
    data = `VBoxManage list vms`
  end
  r = []
  data.strip.each_line do |line|
    if line[UUID_RE]
      vm = VMInfo.new
      vm.uuid = $&
      vm.name = line.gsub($&, '').strip.sub(/^"/,'').sub(/"$/,'')
      r << vm
    end
  end
  r.sort_by{ |vm| vm.name.naturalized }
end

#modify(name, k, v, params = {}) ⇒ Object



394
395
396
397
398
399
400
# File 'lib/vbox/cli.rb', line 394

def modify name, k, v, params = {}
  system "VBoxManage", "modifyvm", name, "--#{k}", v
  if $?.success? && !params[:quiet]
    h = get_vm_info(k == 'name' ? v : name)
    puts "#{k}=#{h[k]}"
  end
end

#show(name) ⇒ Object



258
259
260
261
262
263
# File 'lib/vbox/cli.rb', line 258

def show name
  get_vm_info(name).each do |k,v|
    next if ['"none"', '"off"', '""'].include?(v)
    puts "#{k}=#{v}"
  end
end

#start(name) ⇒ Object



273
274
275
276
277
278
279
280
281
# File 'lib/vbox/cli.rb', line 273

def start name
  if ENV['DISPLAY'] && !@options[:headless]
    system "VBoxManage", "startvm", name
  else
    puts "[.] $DISPLAY is not set, assuming --headless".gray unless @options[:headless]
    @options[:headless] = true
    system "VBoxManage", "startvm", name, "--type", "headless"
  end
end

#system(*args) ⇒ Object

run as in system() call



201
202
203
204
205
206
207
# File 'lib/vbox/cli.rb', line 201

def system *args
  puts "[.] #{args.inspect}".gray if @options[:verbose] >= 2
  exit if @options[:dry_run]
  r = super
  exit 1 unless $?.success?
  r
end

#take_snapshot(vm_name, params = {}) ⇒ Object



337
338
339
340
341
# File 'lib/vbox/cli.rb', line 337

def take_snapshot vm_name, params = {}
  system "VBoxManage", "snapshot", vm_name, "take", params[:name] || "noname"
  exit 1 unless $?.success?
  get_snapshots(vm_name).last
end