veewee 0.0.2
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/.gitignore +7 -0
- data/.rvmrc +2 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +53 -0
- data/README.md +124 -0
- data/Rakefile +92 -0
- data/bin/veewee +79 -0
- data/iso/.gitignore +2 -0
- data/lib/vagrant_init.rb +1 -0
- data/lib/veewee/command.rb +66 -0
- data/lib/veewee/config.rb +5 -0
- data/lib/veewee/export.rb +81 -0
- data/lib/veewee/scancode.rb +108 -0
- data/lib/veewee/session.rb +712 -0
- data/lib/veewee/shell.rb +54 -0
- data/lib/veewee/ssh.rb +164 -0
- data/lib/veewee/transaction.rb +112 -0
- data/lib/veewee/version.rb +3 -0
- data/lib/veewee/web.rb +48 -0
- data/lib/veewee.rb +2 -0
- data/templates/CentOS-4.8-i386/definition.rb +14 -0
- data/templates/CentOS-4.8-i386/ks.cfg +45 -0
- data/templates/CentOS-4.8-i386/postinstall.sh +47 -0
- data/templates/CentOS-5.5-i386/definition.rb +16 -0
- data/templates/CentOS-5.5-i386/ks.cfg +45 -0
- data/templates/CentOS-5.5-i386/postinstall.sh +48 -0
- data/templates/CentOS-5.5-i386-netboot/definition.rb +17 -0
- data/templates/CentOS-5.5-i386-netboot/ks.cfg +45 -0
- data/templates/CentOS-5.5-i386-netboot/postinstall.sh +48 -0
- data/templates/ubuntu-10.04.1-server-amd64/definition.rb +25 -0
- data/templates/ubuntu-10.04.1-server-amd64/postinstall.sh +33 -0
- data/templates/ubuntu-10.04.1-server-amd64/preseed.cfg +87 -0
- data/templates/ubuntu-10.04.1-server-i386/definition.rb +25 -0
- data/templates/ubuntu-10.04.1-server-i386/postinstall.sh +43 -0
- data/templates/ubuntu-10.04.1-server-i386/postinstall2.sh +9 -0
- data/templates/ubuntu-10.04.1-server-i386/preseed.cfg +87 -0
- data/templates/ubuntu-10.10-server-amd64/definition.rb +25 -0
- data/templates/ubuntu-10.10-server-amd64/postinstall.sh +43 -0
- data/templates/ubuntu-10.10-server-amd64/postinstall2.sh +9 -0
- data/templates/ubuntu-10.10-server-amd64/preseed.cfg +87 -0
- data/templates/ubuntu-10.10-server-i386/definition.rb +25 -0
- data/templates/ubuntu-10.10-server-i386/postinstall.sh +43 -0
- data/templates/ubuntu-10.10-server-i386/postinstall2.sh +9 -0
- data/templates/ubuntu-10.10-server-i386/preseed.cfg +87 -0
- data/trials/docu-vbox.txt +83 -0
- data/trials/f.rb +29 -0
- data/trials/t.rb +15 -0
- data/veewee.gemspec +30 -0
- metadata +219 -0
@@ -0,0 +1,712 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'socket'
|
3
|
+
require 'net/scp'
|
4
|
+
require 'pp'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'progressbar'
|
7
|
+
require 'highline/import'
|
8
|
+
require 'tempfile'
|
9
|
+
|
10
|
+
|
11
|
+
module Veewee
|
12
|
+
class Session
|
13
|
+
|
14
|
+
attr_accessor :veewee_dir
|
15
|
+
attr_accessor :definition_dir
|
16
|
+
attr_accessor :template_dir
|
17
|
+
attr_accessor :iso_dir
|
18
|
+
attr_accessor :name
|
19
|
+
attr_accessor :definition
|
20
|
+
|
21
|
+
def self.setenv(env)
|
22
|
+
@veewee_dir=env[:veewee_dir]
|
23
|
+
@definition_dir=env[:definition_dir]
|
24
|
+
@template_dir=env[:template_dir]
|
25
|
+
@box_dir=env[:box_dir]
|
26
|
+
@iso_dir=env[:iso_dir]
|
27
|
+
@tmp_dir=env[:tmp_dir]
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.declare(options)
|
31
|
+
defaults={
|
32
|
+
:cpu_count => '1', :memory_size=> '256',
|
33
|
+
:disk_size => '10140', :disk_format => 'VDI',:disk_size => '10240' ,
|
34
|
+
:os_type_id => 'Ubuntu',
|
35
|
+
:iso_file => "ubuntu-10.10-server-i386.iso", :iso_src => "", :iso_md5 => "", :iso_download_timeout => 1000,
|
36
|
+
:boot_wait => "10", :boot_cmd_sequence => [ "boot"],
|
37
|
+
:kickstart_port => "7122", :kickstart_ip => self.local_ip, :kickstart_timeout => 10000,:kickstart_file => "preseed.cfg",
|
38
|
+
:ssh_login_timeout => "100",:ssh_user => "vagrant", :ssh_password => "vagrant",:ssh_key => "",
|
39
|
+
:ssh_host_port => "2222", :ssh_guest_port => "22",
|
40
|
+
:sudo_cmd => "echo '%p'|sudo -S sh '%f'",
|
41
|
+
:shutdown_cmd => "shutdown -H",
|
42
|
+
:postinstall_files => [ "postinstall.sh"],:postinstall_timeout => 10000}
|
43
|
+
|
44
|
+
@definition=defaults.merge(options)
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.define(boxname,template_name,options = {})
|
49
|
+
#Check if template_name exists
|
50
|
+
|
51
|
+
options = { "force" => false, "format" => "vagrant" }.merge(options)
|
52
|
+
|
53
|
+
if File.directory?(File.join(@template_dir,template_name))
|
54
|
+
else
|
55
|
+
puts "This template can not be found, use vagrant basebox templates to list all templates"
|
56
|
+
exit
|
57
|
+
end
|
58
|
+
if !File.exists?(@definition_dir)
|
59
|
+
FileUtils.mkdir(@definition_dir)
|
60
|
+
end
|
61
|
+
|
62
|
+
if File.directory?(File.join(@definition_dir,boxname))
|
63
|
+
if !options["force"]
|
64
|
+
puts "The definition for #{boxname} already exists. Use --force to overwrite"
|
65
|
+
exit
|
66
|
+
end
|
67
|
+
else
|
68
|
+
FileUtils.mkdir(File.join(@definition_dir,boxname))
|
69
|
+
end
|
70
|
+
FileUtils.cp_r(File.join(@template_dir,template_name,'.'),File.join(@definition_dir,boxname))
|
71
|
+
puts "The basebox '#{boxname}' has been succesfully created from the template ''#{template_name}'"
|
72
|
+
puts "You can now edit the definition files stored in definitions/#{boxname}"
|
73
|
+
puts "or build the box with:"
|
74
|
+
if (options["format"]=='vagrant')
|
75
|
+
puts "vagrant basebox build '#{boxname}'"
|
76
|
+
end
|
77
|
+
if (options["format"]=='veewee')
|
78
|
+
puts "veewee build '#{boxname}'"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
def self.definition_exists?(boxname)
|
87
|
+
if File.directory?(File.join(@definition_dir,boxname))
|
88
|
+
if File.exists?(File.join(@definition_dir,boxname,'definition.rb'))
|
89
|
+
return true
|
90
|
+
else
|
91
|
+
return false
|
92
|
+
end
|
93
|
+
else
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.undefine(boxname)
|
100
|
+
name_dir=File.join(@definition_dir,boxname)
|
101
|
+
if File.directory?(name_dir)
|
102
|
+
#TODO: Needs to be more defensive!!
|
103
|
+
FileUtils.rm_rf(name_dir)
|
104
|
+
else
|
105
|
+
puts "Can not undefine , definition #{boxname} does not exist"
|
106
|
+
exit
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.list_templates( options = { :format => 'vagrant'})
|
111
|
+
puts "The following templates are available:"
|
112
|
+
subdirs=Dir.glob("#{@template_dir}/*")
|
113
|
+
subdirs.each do |sub|
|
114
|
+
if File.directory?("#{sub}")
|
115
|
+
definition=Dir.glob("#{sub}/definition.rb")
|
116
|
+
if definition.length!=0
|
117
|
+
name=sub.sub(/#{@template_dir}\//,'')
|
118
|
+
if (options[:format]=='vagrant')
|
119
|
+
puts "vagrant basebox define '<boxname>' '#{name}'"
|
120
|
+
end
|
121
|
+
if (options[:format]=='veewee')
|
122
|
+
puts "veewee define '<boxname>' '#{name}'"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.list_boxes
|
130
|
+
puts "Not yet implemented"
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.list_definitions
|
134
|
+
puts "Not yet implemented"
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.clean
|
138
|
+
puts "Not yet implemented"
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.verify_iso(filename,autodownload = false)
|
142
|
+
if File.exists?(File.join(@iso_dir,filename))
|
143
|
+
puts
|
144
|
+
puts "Verifying the isofile #{filename} is ok."
|
145
|
+
else
|
146
|
+
full_path=File.join(@iso_dir,filename)
|
147
|
+
path1=Pathname.new(full_path)
|
148
|
+
path2=Pathname.new(Dir.pwd)
|
149
|
+
rel_path=path1.relative_path_from(path2).to_s
|
150
|
+
|
151
|
+
puts
|
152
|
+
puts "The isofile is not found. The definition provided the following information:"
|
153
|
+
puts "- Download url: #{@definition[:iso_src]}"
|
154
|
+
puts "- Md5 Checksum: #{@definition[:iso_md5]}"
|
155
|
+
puts ""
|
156
|
+
|
157
|
+
question=ask("Download? (Yes/No)") {|q| q.default="No"}
|
158
|
+
if question.downcase == "yes"
|
159
|
+
download_progress(@definition[:iso_src],full_path)
|
160
|
+
else
|
161
|
+
puts "You have choosen for manual download: "
|
162
|
+
puts "curl -C - -L '#{@definition[:iso_src]}' -o '#{rel_path}'"
|
163
|
+
puts "md5 '#{rel_path}' "
|
164
|
+
puts
|
165
|
+
exit
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.export_box(boxname)
|
174
|
+
#Now we have to load the definition (reads definition.rb)
|
175
|
+
load_definition(boxname)
|
176
|
+
|
177
|
+
Veewee::Export.vagrant(boxname,@box_dir,@definition)
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.remove_box(boxname)
|
181
|
+
puts "Not yet implemented"
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.build(boxname,options)
|
185
|
+
|
186
|
+
options = { "force" => false, "format" => "vagrant" }.merge(options)
|
187
|
+
|
188
|
+
#Now we have to load the definition (reads definition.rb)
|
189
|
+
load_definition(boxname)
|
190
|
+
|
191
|
+
#Command to execute locally
|
192
|
+
@vboxcmd=determine_vboxcmd
|
193
|
+
|
194
|
+
ssh_options={ :user => @definition[:ssh_user], :port => @definition[:ssh_host_port], :password => @definition[:ssh_password],
|
195
|
+
:timeout => @definition[:ssh_timeout]}
|
196
|
+
|
197
|
+
#Suppress those annoying virtualbox messages
|
198
|
+
suppress_messages
|
199
|
+
|
200
|
+
verify_iso(@definition[:iso_file])
|
201
|
+
|
202
|
+
if (options["force"]==false)
|
203
|
+
else
|
204
|
+
puts "Forcing build by destroying #{boxname} machine"
|
205
|
+
destroy_vm(boxname)
|
206
|
+
end
|
207
|
+
|
208
|
+
checksums=calculate_checksums(@definition,boxname)
|
209
|
+
|
210
|
+
transaction(boxname,"0-initial-#{checksums[0]}",checksums) do
|
211
|
+
|
212
|
+
#Create the Virtualmachine and set all the memory and other stuff
|
213
|
+
create_vm(boxname)
|
214
|
+
|
215
|
+
#Create a disk with the same name as the boxname
|
216
|
+
create_disk(boxname)
|
217
|
+
|
218
|
+
|
219
|
+
#These command actually call the commandline of Virtualbox, I hope to use the virtualbox-ruby library in the future
|
220
|
+
add_ide_controller(boxname)
|
221
|
+
add_sata_controller(boxname)
|
222
|
+
attach_disk(boxname)
|
223
|
+
mount_isofile(boxname,@definition[:iso_file])
|
224
|
+
add_ssh_nat_mapping(boxname)
|
225
|
+
|
226
|
+
#Starting machine
|
227
|
+
#vm.start("vrdp")
|
228
|
+
|
229
|
+
start_vm(boxname,"gui")
|
230
|
+
|
231
|
+
|
232
|
+
#waiting for it to boot
|
233
|
+
puts "Waiting for the machine to boot"
|
234
|
+
sleep @definition[:boot_wait].to_i
|
235
|
+
|
236
|
+
Veewee::Scancode.send_sequence("#{@vboxcmd}","#{boxname}",@definition[:boot_cmd_sequence])
|
237
|
+
|
238
|
+
puts "Starting a webserver on port #{@definition[:kickstart_port]}"
|
239
|
+
#:kickstart_port => "7122", :kickstart_ip => self.local_ip, :kickstart_timeout => 1000,:kickstart_file => "preseed.cfg",
|
240
|
+
Veewee::Web.wait_for_request(@definition[:kickstart_file],{:port => @definition[:kickstart_port],
|
241
|
+
:host => @definition[:kickstart_ip], :timeout => @definition[:kickstart_timeout],
|
242
|
+
:web_dir => File.join(@definition_dir,boxname)})
|
243
|
+
|
244
|
+
Veewee::Ssh.when_ssh_login_works("localhost",ssh_options) do
|
245
|
+
#Transfer version of Virtualbox to $HOME/.vbox_version
|
246
|
+
versionfile=Tempfile.open("vbox.version")
|
247
|
+
versionfile.puts "#{VirtualBox::Global.global.lib.virtualbox.version}"
|
248
|
+
versionfile.rewind
|
249
|
+
Veewee::Ssh.transfer_file("localhost",versionfile.path,".vbox_version", ssh_options)
|
250
|
+
versionfile.close
|
251
|
+
versionfile.delete
|
252
|
+
end
|
253
|
+
end #initial Transaction
|
254
|
+
|
255
|
+
|
256
|
+
counter=1
|
257
|
+
@definition[:postinstall_files].each do |postinstall_file|
|
258
|
+
|
259
|
+
|
260
|
+
filename=File.join(@definition_dir,boxname,postinstall_file)
|
261
|
+
|
262
|
+
transaction(boxname,"#{counter}-#{postinstall_file}-#{checksums[counter]}",checksums) do
|
263
|
+
|
264
|
+
Veewee::Ssh.when_ssh_login_works("localhost",ssh_options) do
|
265
|
+
|
266
|
+
Veewee::Ssh.transfer_file("localhost",filename,ssh_options)
|
267
|
+
command=@definition[:sudo_cmd]
|
268
|
+
command.gsub!(/%p/,"#{@definition[:ssh_password]}")
|
269
|
+
command.gsub!(/%u/,"#{@definition[:ssh_user]}")
|
270
|
+
command.gsub!(/%f/,"#{postinstall_file}")
|
271
|
+
|
272
|
+
Veewee::Ssh.execute("localhost","#{command}",ssh_options)
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
counter+=1
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
end
|
282
|
+
|
283
|
+
|
284
|
+
def self.determine_vboxcmd
|
285
|
+
return "VBoxManage"
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.start_vm(boxname,mode)
|
289
|
+
vm=VirtualBox::VM.find(boxname)
|
290
|
+
vm.start(mode)
|
291
|
+
end
|
292
|
+
|
293
|
+
def self.load_definition(boxname)
|
294
|
+
if definition_exists?(boxname)
|
295
|
+
definition_file=File.join(@definition_dir,boxname,"definition.rb")
|
296
|
+
begin
|
297
|
+
require definition_file
|
298
|
+
rescue LoadError
|
299
|
+
puts "Error loading definition of #{boxname}"
|
300
|
+
exit
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def self.add_ssh_nat_mapping(boxname)
|
306
|
+
vm=VirtualBox::VM.find(boxname)
|
307
|
+
#Map SSH Ports
|
308
|
+
# command => "${vboxcmd} modifyvm '${vname}' --natpf1 'guestssh,tcp,,${hostsshport},,${guestsshport}'",
|
309
|
+
port = VirtualBox::NATForwardedPort.new
|
310
|
+
port.name = "guestssh"
|
311
|
+
port.guestport = @definition[:ssh_guest_port].to_i
|
312
|
+
port.hostport = @definition[:ssh_host_port].to_i
|
313
|
+
vm.network_adapters[0].nat_driver.forwarded_ports << port
|
314
|
+
port.save
|
315
|
+
vm.save
|
316
|
+
end
|
317
|
+
|
318
|
+
def self.destroy_vm(boxname)
|
319
|
+
|
320
|
+
load_definition(boxname)
|
321
|
+
|
322
|
+
#:destroy_medium => :delete, will delete machine + all media attachments
|
323
|
+
#vm.destroy(:destroy_medium => :delete)
|
324
|
+
##vm.destroy(:destroy_image => true)
|
325
|
+
|
326
|
+
#VBoxManage unregistervm "test-machine" --delete
|
327
|
+
#because the destroy does remove the .vbox file on 4.0.x
|
328
|
+
#PDB
|
329
|
+
#vm.destroy()
|
330
|
+
|
331
|
+
|
332
|
+
|
333
|
+
vm=VirtualBox::VM.find(boxname)
|
334
|
+
|
335
|
+
if (!vm.nil? && !(vm.powered_off?))
|
336
|
+
puts "Shutting down vm #{boxname}"
|
337
|
+
#We force it here, maybe vm.shutdown is cleaner
|
338
|
+
vm.stop
|
339
|
+
end
|
340
|
+
sleep 3
|
341
|
+
|
342
|
+
command="#{@vboxcmd} unregistervm '#{boxname}' --delete"
|
343
|
+
|
344
|
+
puts "Deleting vm #{boxname}"
|
345
|
+
|
346
|
+
#Exec and system stop the execution here
|
347
|
+
Veewee::Shell.execute("#{command}")
|
348
|
+
sleep 1
|
349
|
+
|
350
|
+
#if the disk was not attached when the machine was destroyed we also need to delete the disk
|
351
|
+
location=boxname+"."+@definition[:disk_format].downcase
|
352
|
+
found=false
|
353
|
+
VirtualBox::HardDrive.all.each do |d|
|
354
|
+
if !d.location.match(/#{location}/).nil?
|
355
|
+
|
356
|
+
command="#{@vboxcmd} closemedium disk '#{d.location}' --delete"
|
357
|
+
puts "Deleting disk #{d.location}"
|
358
|
+
Veewee::Shell.execute("#{command}")
|
359
|
+
#v.3
|
360
|
+
#d.destroy(true)
|
361
|
+
break
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
end
|
368
|
+
|
369
|
+
def self.create_vm(boxname,force=false)
|
370
|
+
|
371
|
+
#Verifying the os.id with the :os_type_id specified
|
372
|
+
matchfound=false
|
373
|
+
VirtualBox::Global.global.lib.virtualbox.guest_os_types.collect { |os|
|
374
|
+
if @definition[:os_type_id] == os.id
|
375
|
+
matchfound=true
|
376
|
+
end
|
377
|
+
}
|
378
|
+
unless matchfound
|
379
|
+
puts "The ostype: #{@definition[:os_type_id]} is not available in your Virtualbox version"
|
380
|
+
exit
|
381
|
+
end
|
382
|
+
|
383
|
+
|
384
|
+
vm=VirtualBox::VM.find(boxname)
|
385
|
+
|
386
|
+
if (!vm.nil? && !(vm.powered_off?))
|
387
|
+
puts "shutting down box"
|
388
|
+
#We force it here, maybe vm.shutdown is cleaner
|
389
|
+
vm.stop
|
390
|
+
end
|
391
|
+
|
392
|
+
if !vm.nil?
|
393
|
+
puts "Box already exists"
|
394
|
+
#vm.stop
|
395
|
+
#vm.destroy
|
396
|
+
else
|
397
|
+
#TODO One day ruby-virtualbox will be able to handle this creation
|
398
|
+
#Box does not exist, we can start to create it
|
399
|
+
|
400
|
+
command="#{@vboxcmd} createvm --name '#{boxname}' --ostype '#{@definition[:os_type_id]}' --register"
|
401
|
+
|
402
|
+
#Exec and system stop the execution here
|
403
|
+
Veewee::Shell.execute("#{command}")
|
404
|
+
|
405
|
+
end
|
406
|
+
|
407
|
+
vm=VirtualBox::VM.find(boxname)
|
408
|
+
if vm.nil?
|
409
|
+
puts "we tried to create a box or a box was here before"
|
410
|
+
puts "but now it's gone"
|
411
|
+
exit
|
412
|
+
end
|
413
|
+
|
414
|
+
#Set all params we know
|
415
|
+
vm.memory_size=@definition[:memory_size].to_i
|
416
|
+
vm.os_type_id=@definition[:os_type_id]
|
417
|
+
vm.cpu_count=@definition[:cpu_count].to_i
|
418
|
+
vm.name=boxname
|
419
|
+
|
420
|
+
puts "Creating vm #{vm.name} : #{vm.memory_size}M - #{vm.cpu_count} CPU - #{vm.os_type_id}"
|
421
|
+
#setting bootorder
|
422
|
+
vm.boot_order[0]=:hard_disk
|
423
|
+
vm.boot_order[1]=:dvd
|
424
|
+
vm.boot_order[2]=:null
|
425
|
+
vm.boot_order[3]=:null
|
426
|
+
vm.validate
|
427
|
+
vm.save
|
428
|
+
|
429
|
+
end
|
430
|
+
|
431
|
+
def self.create_disk(boxname)
|
432
|
+
#Now check the disks
|
433
|
+
#Maybe one day we can use the name, now we have to check location
|
434
|
+
#disk=VirtualBox::HardDrive.find(boxname)
|
435
|
+
location=boxname+"."+@definition[:disk_format].downcase
|
436
|
+
|
437
|
+
found=false
|
438
|
+
VirtualBox::HardDrive.all.each do |d|
|
439
|
+
if !d.location.match(/#{location}/).nil?
|
440
|
+
found=true
|
441
|
+
break
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
if !found
|
446
|
+
puts "Creating new harddrive of size #{@definition[:disk_size].to_i} "
|
447
|
+
|
448
|
+
#newdisk=VirtualBox::HardDrive.new
|
449
|
+
#newdisk.format=@definition[:disk_format]
|
450
|
+
#newdisk.logical_size=@definition[:disk_size].to_i
|
451
|
+
|
452
|
+
#newdisk.location=location
|
453
|
+
##PDB: again problems with the virtualbox GEM
|
454
|
+
##VirtualBox::Global.global.max_vdi_size=1000000
|
455
|
+
#newdisk.save
|
456
|
+
|
457
|
+
command="VBoxManage list systemproperties|grep '^Default machine'|cut -d ':' -f 2|sed -e 's/^[ ]*//'"
|
458
|
+
results=IO.popen("#{command}")
|
459
|
+
place=results.gets.chop
|
460
|
+
results.close
|
461
|
+
|
462
|
+
command ="#{@vboxcmd} createhd --filename '#{place}/#{boxname}/#{boxname}.#{@definition[:disk_format]}' --size '#{@definition[:disk_size].to_i}' --format #{@definition[:disk_format]} > /dev/null"
|
463
|
+
Veewee::Shell.execute("#{command}")
|
464
|
+
|
465
|
+
end
|
466
|
+
|
467
|
+
end
|
468
|
+
|
469
|
+
def self.add_ide_controller(boxname)
|
470
|
+
#unless => "${vboxcmd} showvminfo '${vname}' | grep 'IDE Controller' "
|
471
|
+
command ="#{@vboxcmd} storagectl '#{boxname}' --name 'IDE Controller' --add ide"
|
472
|
+
Veewee::Shell.execute("#{command}")
|
473
|
+
end
|
474
|
+
|
475
|
+
def self.add_sata_controller(boxname)
|
476
|
+
#unless => "${vboxcmd} showvminfo '${vname}' | grep 'SATA Controller' ";
|
477
|
+
command ="#{@vboxcmd} storagectl '#{boxname}' --name 'SATA Controller' --add sata"
|
478
|
+
Veewee::Shell.execute("#{command}")
|
479
|
+
end
|
480
|
+
|
481
|
+
|
482
|
+
def self.attach_disk(boxname)
|
483
|
+
location=boxname+"."+@definition[:disk_format].downcase
|
484
|
+
|
485
|
+
command="VBoxManage list systemproperties|grep '^Default machine'|cut -d ':' -f 2|sed -e 's/^[ ]*//'"
|
486
|
+
results=IO.popen("#{command}")
|
487
|
+
place=results.gets.chop
|
488
|
+
results.close
|
489
|
+
|
490
|
+
location="#{place}/#{boxname}/"+location
|
491
|
+
puts "Attaching disk: #{location}"
|
492
|
+
|
493
|
+
#command => "${vboxcmd} storageattach '${vname}' --storagectl 'SATA Controller' --port 0 --device 0 --type hdd --medium '${vname}.vdi'",
|
494
|
+
command ="#{@vboxcmd} storageattach '#{boxname}' --storagectl 'SATA Controller' --port 0 --device 0 --type hdd --medium '#{location}'"
|
495
|
+
Veewee::Shell.execute("#{command}")
|
496
|
+
|
497
|
+
end
|
498
|
+
|
499
|
+
def self.mount_isofile(boxname,isofile)
|
500
|
+
full_iso_file=File.join(@iso_dir,isofile)
|
501
|
+
puts "Mounting cdrom: #{full_iso_file}"
|
502
|
+
#command => "${vboxcmd} storageattach '${vname}' --storagectl 'IDE Controller' --type dvddrive --port 1 --device 0 --medium '${isodst}' ";
|
503
|
+
command ="#{@vboxcmd} storageattach '#{boxname}' --storagectl 'IDE Controller' --type dvddrive --port 1 --device 0 --medium '#{full_iso_file}'"
|
504
|
+
Veewee::Shell.execute("#{command}")
|
505
|
+
end
|
506
|
+
|
507
|
+
|
508
|
+
|
509
|
+
def self.suppress_messages
|
510
|
+
#Setting this annoying messages to register
|
511
|
+
VirtualBox::ExtraData.global["GUI/RegistrationData"]="triesLeft=0"
|
512
|
+
VirtualBox::ExtraData.global["GUI/UpdateDate"]="1 d, 2009-09-20"
|
513
|
+
VirtualBox::ExtraData.global["GUI/SuppressMessages"]="confirmInputCapture,remindAboutAutoCapture,remindAboutMouseIntegrationOff"
|
514
|
+
VirtualBox::ExtraData.global["GUI/UpdateCheckCount"]="60"
|
515
|
+
update_date=Time.now+86400
|
516
|
+
VirtualBox::ExtraData.global["GUI/UpdateDate"]="1 d, #{update_date.year}-#{update_date.month}-#{update_date.day}, stable"
|
517
|
+
|
518
|
+
VirtualBox::ExtraData.global.save
|
519
|
+
end
|
520
|
+
|
521
|
+
def self.local_ip
|
522
|
+
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
|
523
|
+
|
524
|
+
UDPSocket.open do |s|
|
525
|
+
s.connect '64.233.187.99', 1
|
526
|
+
s.addr.last
|
527
|
+
end
|
528
|
+
ensure
|
529
|
+
Socket.do_not_reverse_lookup = orig
|
530
|
+
end
|
531
|
+
|
532
|
+
def self.list_ostypes
|
533
|
+
puts
|
534
|
+
puts "Available os types:"
|
535
|
+
VirtualBox::Global.global.lib.virtualbox.guest_os_types.collect { |os|
|
536
|
+
puts "#{os.id}: #{os.description}"
|
537
|
+
}
|
538
|
+
end
|
539
|
+
|
540
|
+
|
541
|
+
def self.calculate_checksums(definition,boxname)
|
542
|
+
|
543
|
+
#TODO: get rid of definitiondir and so one
|
544
|
+
initial=definition.clone
|
545
|
+
|
546
|
+
keys=[:postinstall_files,:sudo_cmd,:postinstall_timeout]
|
547
|
+
keys.each do |key|
|
548
|
+
initial.delete(key)
|
549
|
+
end
|
550
|
+
|
551
|
+
checksums=Array.new
|
552
|
+
checksums << Digest::MD5.hexdigest(initial.to_s)
|
553
|
+
|
554
|
+
postinstall_files=definition[:postinstall_files]
|
555
|
+
unless postinstall_files.nil?
|
556
|
+
for filename in postinstall_files
|
557
|
+
begin
|
558
|
+
full_filename=File.join(@definition_dir,boxname,filename)
|
559
|
+
|
560
|
+
checksums << Digest::MD5.hexdigest(File.read(full_filename))
|
561
|
+
rescue
|
562
|
+
puts "Error reading postinstall file #{filename} - checksum"
|
563
|
+
exit
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
return checksums
|
569
|
+
|
570
|
+
end
|
571
|
+
|
572
|
+
def self.download_progress(url,localfile)
|
573
|
+
pbar = nil
|
574
|
+
URI.parse(url).open(
|
575
|
+
:content_length_proc => lambda {|t|
|
576
|
+
if t && 0 < t
|
577
|
+
pbar = ProgressBar.new("Fetching file", t)
|
578
|
+
pbar.file_transfer_mode
|
579
|
+
end
|
580
|
+
},
|
581
|
+
:progress_proc => lambda {|s|
|
582
|
+
pbar.set s if pbar
|
583
|
+
}) { |src|
|
584
|
+
open("#{localfile}","wb") { |dst|
|
585
|
+
dst.write(src.read)
|
586
|
+
}
|
587
|
+
}
|
588
|
+
|
589
|
+
end
|
590
|
+
|
591
|
+
def self.transaction(boxname,step_name,checksums,&block)
|
592
|
+
|
593
|
+
current_step_nr=step_name.split("-")[0].to_i
|
594
|
+
|
595
|
+
vm=VirtualBox::VM.find(boxname)
|
596
|
+
snapnames=Array.new
|
597
|
+
|
598
|
+
#If vm exists , look for snapshots
|
599
|
+
if !vm.nil?
|
600
|
+
start_snapshot=vm.root_snapshot
|
601
|
+
snapshot=start_snapshot
|
602
|
+
counter=0
|
603
|
+
|
604
|
+
while (snapshot!=nil)
|
605
|
+
#puts "#{counter}:#{snapshot.name}"
|
606
|
+
snapnames[counter]=snapshot.name
|
607
|
+
counter=counter+1
|
608
|
+
snapshot=snapshot.children[0]
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
#find the last snapshot matching the state
|
613
|
+
counter=[snapnames.length, checksums.length].min-1
|
614
|
+
last_good_state=counter
|
615
|
+
for c in 0..counter do
|
616
|
+
#puts "#{c}- #{snapnames[c]} - #{checksums[c]}"
|
617
|
+
if !snapnames[c].match("#{c}.*-#{checksums[c]}")
|
618
|
+
# puts "we found a bad state"
|
619
|
+
last_good_state=c-1
|
620
|
+
break
|
621
|
+
end
|
622
|
+
end
|
623
|
+
#puts "Last good state: #{last_good_state}"
|
624
|
+
|
625
|
+
if (current_step_nr < last_good_state)
|
626
|
+
#puts "fast forwarding #{step_name}"
|
627
|
+
return
|
628
|
+
end
|
629
|
+
|
630
|
+
#puts "Current step: #{current_step_nr}"
|
631
|
+
if (current_step_nr == last_good_state)
|
632
|
+
if vm.running?
|
633
|
+
vm.stop
|
634
|
+
end
|
635
|
+
|
636
|
+
#invalidate later snapshots
|
637
|
+
#puts "remove old snapshots"
|
638
|
+
|
639
|
+
for s in (last_good_state+1)..(snapnames.length-1)
|
640
|
+
puts "Removing step [s] snapshot as it is no more valid"
|
641
|
+
snapshot=vm.find_snapshot(snapnames[s])
|
642
|
+
snapshot.destroy
|
643
|
+
#puts snapshot
|
644
|
+
end
|
645
|
+
|
646
|
+
vm.reload
|
647
|
+
puts "Loading step #{current_step_nr} snapshots as it has not changed"
|
648
|
+
sleep 2
|
649
|
+
goodsnap=vm.find_snapshot(snapnames[last_good_state])
|
650
|
+
goodsnap.restore
|
651
|
+
sleep 2
|
652
|
+
#TODO:Restore snapshot!!!
|
653
|
+
vm.start
|
654
|
+
|
655
|
+
end
|
656
|
+
|
657
|
+
#puts "last good state #{last_good_state}"
|
658
|
+
|
659
|
+
|
660
|
+
if (current_step_nr > last_good_state)
|
661
|
+
|
662
|
+
if (last_good_state==-1)
|
663
|
+
#no initial snapshot is found, clean machine!
|
664
|
+
vm=VirtualBox::VM.find(boxname)
|
665
|
+
|
666
|
+
if !vm.nil?
|
667
|
+
if vm.running?
|
668
|
+
puts "Stopping machine"
|
669
|
+
vm.stop
|
670
|
+
while vm.running?
|
671
|
+
sleep 1
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
#detaching cdroms (used to work in 3.x)
|
676
|
+
# vm.medium_attachments.each do |m|
|
677
|
+
# if m.type==:dvd
|
678
|
+
# #puts "Detaching dvd"
|
679
|
+
# m.detach
|
680
|
+
# end
|
681
|
+
# end
|
682
|
+
|
683
|
+
vm.reload
|
684
|
+
puts "We found no good state so we are destroying the previous machine+disks"
|
685
|
+
destroy_vm(boxname)
|
686
|
+
end
|
687
|
+
|
688
|
+
end
|
689
|
+
|
690
|
+
#puts "(re-)executing step #{step_name}"
|
691
|
+
|
692
|
+
|
693
|
+
yield
|
694
|
+
|
695
|
+
#Need to look it up again because if it was an initial load
|
696
|
+
vm=VirtualBox::VM.find(boxname)
|
697
|
+
puts "Step [#{current_step_nr}] was succesfull - saving state"
|
698
|
+
vm.save_state
|
699
|
+
sleep 2 #waiting for it to be ok
|
700
|
+
#puts "about to snapshot #{vm}"
|
701
|
+
#take snapshot after succesful execution
|
702
|
+
vm.take_snapshot(step_name,"snapshot taken by veewee")
|
703
|
+
sleep 2 #waiting for it to be started again
|
704
|
+
vm.start
|
705
|
+
end
|
706
|
+
|
707
|
+
#pp snapnames
|
708
|
+
end
|
709
|
+
|
710
|
+
|
711
|
+
end #End Class
|
712
|
+
end #End Module
|