Class: VBOX::CLI

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

Constant Summary collapse

SHOW_CATEGORIES =
{
  'GENERAL'          => %w'name cpus memory vram cpuexecutioncap UUID VMState',
  'VIRTUALIZATION OPTIONS' =>
    [
      /^(groups|ostype|hwvirt|nestedpag|largepag|vtxvpid|ioapic|pagefusion|hpet|synthcpu|pae)/,
      /accelerate/, /balloon/i
    ],
  'NET'              => [ /^(nic|nat|mac|bridge|cable|hostonly)/, /^sock/, /^tcp/ ],
  'STORAGE'          => [ /storage/, /SATA/, /IDE/ ],
  'SNAPSHOTS'        => [ /snapshot/i ],
  'VIRTUAL HARDWARE' => [ /^(lpt|uart|audio|ehci|usb|hardware|chipset|monitor|hid|acpi|firmware|USB)/ ],
  'TELEPORTING'      => [ /teleport/i, /cpuid/i ],
  'SHARED FOLDERS'   => [ /SharedFolder/ ]
}

Instance Method Summary collapse

Constructor Details

#initialize(argv = ARGV) ⇒ CLI

Returns a new instance of CLI.



10
11
12
# File 'lib/vbox/cli.rb', line 10

def initialize argv = ARGV
  @argv = argv
end

Instance Method Details



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/vbox/cli.rb', line 33

def banner
  bname = File.basename($0)
  r = []
  r << "USAGE:"
  r << "\t#{bname} [options]                           - list VMs"
  r << "\t#{bname} [options] <vm_name>                 - show VM params"
  r << "\t#{bname} [options] <vm_name> <param>=<value> - change VM params (name, cpus, usb, etc)"
  r << "\t#{bname} [options] <vm_name> <command>       - make some action (start, reset, etc) on VM"

  r << ""
  r << "COMMANDS:"
#      (COMMANDS+['snapshots']).sort.each do |c|
#        r << "\t#{c}"
#      end
  r << "\t" + _join_by_width(COMMANDS+['snapshots'], :newline => ",\n\t", :max_length => 64 )
  r << ""
  r << "OPTIONS:"
  r.join("\n")
end

#examplesObject



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/vbox/cli.rb', line 53

def examples
  bname = File.basename($0)
  space = " "*bname.size
  r = []
  r << "EXAMPLES:"
  r << %Q{\t#{bname} -v                        - list VMs with memory and dir sizes}
  r << %Q{\t#{bname} "d{1-10}" list            - list only VMs named 'd1','d2','d3',...,'d10'}
  r << %Q{\t#{bname} "test*" start             - start VMs which name starts with 'test'}
  r << %Q{\t#{bname} "v[ace]" cpus=2 acpi=on   - set number of cpus & ACPI on VMs named 'va','vc','ve'}
  r << %Q{\t#{bname} d0                        - list all parameters of VM named 'd0'}
  r << %Q{\t#{bname} d0 clone -c 10 -S last    - make 10 new linked clones of vm 'd0' using the}
  r << %Q{\t#{space}                             latest hdd snapshot, if any}
  r << %Q{\t#{bname} d0 clone -c 10 -S new     - make ONE new shapshot of VM 'd0' and then make}
  r << %Q{\t#{space}                             10 new clones linked to this snapshot}
  r << %Q{\t#{bname} "tmp?" delete             - try to destroy all VMs which name is 4 letters long}
  r << %Q{\t#{space}                             and starts with 'tmp'}
  r << %Q{\t#{bname} ae340207-f472-4d63-80e7-855fca6808cb}
  r << %Q{\t#{space}                           - list all parameters of VM with this GUID}
  r << %Q{\t#{bname} --no-glob "*wtf?!*" rm    - destroy VM which name is '*wtf?!*'}
  r.join("\n")
end

#list_vms(name_or_glob) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/vbox/cli.rb', line 123

def list_vms name_or_glob
  vms = _find_vms name_or_glob

  longest = (vms.map(&:name).map(&:size)+[4]).max

  puts "%-*s %5s %6s  %-12s %s".gray % [longest, *%w'NAME MEM DIRSZ STATE UUID']
  vms.each do |vm|
    if @options[:verbose] > 0
      vm.
      state = (vm.state == :poweroff) ? '' : vm.state.to_s.upcase
      s = sprintf "%-*s %5d %6s  %-12s %s", longest, vm.name, vm.memory_size, vm.dir_size,
        state, vm.uuid
    else
      state = (vm.state == :poweroff) ? '' : vm.state.to_s.upcase
      s = sprintf "%-*s %5s %6s  %-12s %s", longest, vm.name, '', '',
        state, vm.uuid
    end
    s = s.green if vm.state == :running
    puts s
  end
end

#parse_argvObject



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/vbox/cli.rb', line 75

def parse_argv
  @options = { :verbose => 0 }
  optparser = OptionParser.new do |opts|
    opts.banner = banner
    opts.summary_indent = "\t"

    opts.on "-g", "--[no-]glob",
    "assume <vm_name> is a wildcard & run on multiple VMs.",
    "All glob(7) patterns are supported plus additional",
    "pattern \"{1-20}\" - expands to a sequence: 1,2,3,...,19,20" do |x|
      @options[:multiple] = x
    end
    opts.on "-n", "--dry-run", "do not change anything, just print commands to be invoked" do
      @options[:dry_run] = true
    end
    opts.on "-v", "--verbose", "increase verbosity" do
      @options[:verbose] ||= 0
      @options[:verbose] += 1
    end
    opts.on "-N", "--clones N", Integer, "clone: make N clones" do |x|
      @options[:clones] = x
    end
    a = 'new last take make'.split.map{ |x| [x, x.upcase] }.flatten
    opts.on "-S", "--snapshot MODE", a, "clone: use LAST shapshot or make NEW" do |x|
      @options[:snapshot] = x.downcase
    end
    opts.on "--name NAME", "clone: name for the clone VM" do |x|
      @options[:name] = x
    end
    opts.on "-H", "--headless", "start: start VM in headless mode" do
      @options[:headless] = true
    end
    opts.on "-h", "--help", "show this message" do
      puts @help
      exit
    end
  end
  @help = optparser.help + "\n" + examples
  @argv = optparser.parse(@argv)

  # disable glob matching if first arg is a UUID
  unless @options.key?(:multiple)
    @options[:multiple] = "{#{@argv.first}}" !~ UUID_RE
  end

  VBOX.verbosity = @options[:verbose]
end

#runObject



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/vbox/cli.rb', line 299

def run
  parse_argv
  # now @argv contains only VM name and commands, if any

  if @argv.empty? || (@argv.size <= 2 && @argv.include?('list'))
    # vbox
    # vbox list
    # vbox list "a*"
    # vbox "a*" list
    @argv.delete_at(@argv.index('list') || 999) # delete only 1st 'list' entry
    list_vms @argv.first
  elsif @argv.empty? || (@argv.size <= 2 && @argv.include?('ls'))
    # vbox
    # vbox ls
    # vbox ls "a*"
    # vbox "a*" ls
    @argv.delete_at(@argv.index('ls') || 999) # delete only 1st 'ls' entry
    list_vms @argv.first
  else
    # vbox VM
    # vbox VM show
    # vbox VM ...
    #  - where 'VM' can be vm name or glob or UUID
    vm_cmd *@argv
  end
end

#vm_cmd(name_or_glob, cmd = 'show', *args) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/vbox/cli.rb', line 145

def vm_cmd name_or_glob, cmd='show', *args
  vms = _find_vms(name_or_glob)
  if vms.empty?
    if cmd == 'create'
      return vm_cmd_create(name_or_glob)
    else
      STDERR.puts "[?] no VMs matching #{name_or_glob.inspect}".red
      exit 1
    end
  end

  method =
    if cmd['=']
      # set some VM variables:
      # vbox vm_name foo=bar bar=baz xxx=yyy
      args.unshift(cmd)
      "vm_cmd_set"
    else
      "vm_cmd_#{cmd}"
    end

  unless self.respond_to?(method)
    STDERR.puts "[?] unknown command #{cmd.inspect}".red
    exit 1
  end
  vms.each do |vm|
    send method, vm, *args
  end
end

#vm_cmd_acpipowerbutton(vm) ⇒ Object

ACPI ‘Power’ Button



272
273
274
# File 'lib/vbox/cli.rb', line 272

def vm_cmd_acpipowerbutton vm
  vm.acpipowerbutton!
end

#vm_cmd_acpisleepbutton(vm) ⇒ Object

ACPI ‘Sleep’ Button



277
278
279
# File 'lib/vbox/cli.rb', line 277

def vm_cmd_acpisleepbutton vm
  vm.acpisleepbutton!
end

#vm_cmd_clone(vm) ⇒ Object

clone VM



282
283
284
285
286
287
288
289
# File 'lib/vbox/cli.rb', line 282

def vm_cmd_clone vm
  # TODO: page fusion
  unless @options[:snapshot]
    puts "[!] please gimme --snapshot=LAST OR --snapshot=NEW option".red
    exit 1
  end
  vm.clone! @options
end

#vm_cmd_create(name) ⇒ Object

create VM



217
218
219
# File 'lib/vbox/cli.rb', line 217

def vm_cmd_create name
  VM.new(:name => name).create!
end

#vm_cmd_destroy(vm) ⇒ Object Also known as: vm_cmd_rm, vm_cmd_delete

destroy VM



222
223
224
# File 'lib/vbox/cli.rb', line 222

def vm_cmd_destroy vm
  vm.destroy!
end

#vm_cmd_pause(vm) ⇒ Object

pause VM



244
245
246
# File 'lib/vbox/cli.rb', line 244

def vm_cmd_pause vm
  vm.pause!
end

#vm_cmd_poweroff(vm) ⇒ Object Also known as: vm_cmd_stop

stop VM



266
267
268
# File 'lib/vbox/cli.rb', line 266

def vm_cmd_poweroff vm
  vm.poweroff!
end

#vm_cmd_reset(vm) ⇒ Object

reset VM



255
256
257
# File 'lib/vbox/cli.rb', line 255

def vm_cmd_reset vm
  vm.reset!
end

#vm_cmd_resume(vm) ⇒ Object Also known as: vm_cmd_unpause

resume VM



249
250
251
# File 'lib/vbox/cli.rb', line 249

def vm_cmd_resume vm
  vm.resume!
end

#vm_cmd_savestate(vm) ⇒ Object Also known as: vm_cmd_save_state

save VM state



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

def vm_cmd_savestate vm
  vm.savestate!
end

#vm_cmd_set(vm, *args) ⇒ Object

set VM variables



229
230
231
232
233
234
235
236
# File 'lib/vbox/cli.rb', line 229

def vm_cmd_set vm, *args
  raise "all arguments must contain '='" unless args.all?{ |arg| arg['='] }
  args.each do |arg|
    k,v = arg.split("=",2)
    vm.set_var k, v
  end
  vm.save
end

#vm_cmd_show(vm) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/vbox/cli.rb', line 191

def vm_cmd_show vm
  vars = vm..dup
  unless @options[:verbose] > 0
    vars.delete_if{ |k,v| ["none","off","disabled","emptydrive","",0,"0",nil].include?(v) }
  end
  maxlen = vars.keys.map(&:size).max

  SHOW_CATEGORIES.each do |name, filters|
    keys = []; title = nil
    filters.each do |filter|
      keys += filter.is_a?(Regexp) ? vars.keys.find_all{ |key| key =~ filter } : [filter]
    end
    keys.each do |k|
      if v = vars.delete(k)
        puts (title = "--- #{name} ".ljust(80,'-')) unless title
        printf("  %-*s: %s\n", maxlen, k, v)
      end
    end
  end
  puts "--- MISC ".ljust(80,'-')
  vars.each do |k,v|
    printf("  %-*s: %s\n", maxlen, k, v)
  end
end

#vm_cmd_snapshots(vm, *args) ⇒ Object Also known as: vm_cmd_snapshot

manage VM snapshots



292
293
294
295
296
# File 'lib/vbox/cli.rb', line 292

def vm_cmd_snapshots vm, *args
  vm.snapshots.each do |s|
    printf "%s  %s\n", s.uuid, s.name
  end
end

#vm_cmd_start(vm) ⇒ Object

start VM



239
240
241
# File 'lib/vbox/cli.rb', line 239

def vm_cmd_start vm
  vm.start! :headless => @options[:headless]
end