veewee 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/.gitignore
ADDED
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
veewee (0.0.2)
|
5
|
+
highline (~> 1.6.1)
|
6
|
+
net-ssh (~> 2.1.0)
|
7
|
+
popen4 (~> 0.1.2)
|
8
|
+
progressbar
|
9
|
+
thor (~> 0.14.6)
|
10
|
+
vagrant (~> 0.7.0)
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: http://rubygems.org/
|
14
|
+
specs:
|
15
|
+
Platform (0.4.0)
|
16
|
+
abstract (1.0.0)
|
17
|
+
archive-tar-minitar (0.5.2)
|
18
|
+
erubis (2.6.6)
|
19
|
+
abstract (>= 1.0.0)
|
20
|
+
ffi (0.6.3)
|
21
|
+
rake (>= 0.8.7)
|
22
|
+
highline (1.6.1)
|
23
|
+
i18n (0.5.0)
|
24
|
+
json (1.4.6)
|
25
|
+
mario (0.0.6)
|
26
|
+
net-scp (1.0.4)
|
27
|
+
net-ssh (>= 1.99.1)
|
28
|
+
net-ssh (2.1.0)
|
29
|
+
open4 (1.0.1)
|
30
|
+
popen4 (0.1.2)
|
31
|
+
Platform (>= 0.4.0)
|
32
|
+
open4 (>= 0.4.0)
|
33
|
+
progressbar (0.9.0)
|
34
|
+
rake (0.8.7)
|
35
|
+
thor (0.14.6)
|
36
|
+
vagrant (0.7.1)
|
37
|
+
archive-tar-minitar (= 0.5.2)
|
38
|
+
erubis (~> 2.6.6)
|
39
|
+
i18n (~> 0.5.0)
|
40
|
+
json (~> 1.4.6)
|
41
|
+
mario (~> 0.0.6)
|
42
|
+
net-scp (~> 1.0.4)
|
43
|
+
net-ssh (~> 2.1.0)
|
44
|
+
thor (~> 0.14.6)
|
45
|
+
virtualbox (~> 0.8.3)
|
46
|
+
virtualbox (0.8.3)
|
47
|
+
ffi (~> 0.6.3)
|
48
|
+
|
49
|
+
PLATFORMS
|
50
|
+
ruby
|
51
|
+
|
52
|
+
DEPENDENCIES
|
53
|
+
veewee!
|
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
**VeeWee:** the tool to easily build vagrant base boxes
|
2
|
+
Vagrant is a great tool to test new things or changes in a virtual machine(Virtualbox) using either chef or puppet.
|
3
|
+
The first step is to download an existing 'base box'. I believe this scares a lot of people as they don't know who or how this box was build. Therefore lots of people end up first building their own base box to use with vagrant.
|
4
|
+
|
5
|
+
Veewee tries to automate this and to share the knowledge and sources you need to create a basebox. Instead of creating custom ISO's from your favorite distribution, it leverages the 'keyboardputscancode' command of Virtualbox so send the actual 'boot prompt' keysequence to boot an existing iso.
|
6
|
+
|
7
|
+
Before we can actually build the boxes, we need to take care of the minimal things to install:
|
8
|
+
- Have Virtualbox 4.x installed -> download it from http://download.virtualbox.org/virtualbox/
|
9
|
+
|
10
|
+
|
11
|
+
ALPHA CODE: -> you're on your own....
|
12
|
+
|
13
|
+
## Installation:
|
14
|
+
__from source__
|
15
|
+
$ git clone https://github.com/jedi4ever/veewee.git
|
16
|
+
$ cd veewee
|
17
|
+
$ gem install bundler
|
18
|
+
$ bundle install
|
19
|
+
|
20
|
+
__as a gem__
|
21
|
+
$ gem install veewee
|
22
|
+
|
23
|
+
|
24
|
+
## List all templates
|
25
|
+
$ vagrant basebox templates
|
26
|
+
|
27
|
+
## Define a new box (ex. Ubuntu 10.10 server i386)
|
28
|
+
|
29
|
+
this is essentially making a copy based on the templates provided above.
|
30
|
+
|
31
|
+
$ vagrant basebox define 'myubuntubox' 'ubuntu-10.10-server-i386'
|
32
|
+
template successfully copied
|
33
|
+
|
34
|
+
-> This copies over the templates/ubuntu-10.10-server-i386 to definition/myubuntubox
|
35
|
+
|
36
|
+
$ ls definitions/myubuntubox
|
37
|
+
definition.rb postinstall.sh postinstall2.sh preseed.cfg
|
38
|
+
|
39
|
+
## Optionally modify the definition.rb , postinstall.sh or preseed.cfg
|
40
|
+
|
41
|
+
<pre>
|
42
|
+
Veewee::Session.declare( {
|
43
|
+
:cpu_count => '1', :memory_size=> '256',
|
44
|
+
:disk_size => '10140', :disk_format => 'VDI',:disk_size => '10240' ,
|
45
|
+
:os_type_id => 'Ubuntu',
|
46
|
+
:iso_file => "ubuntu-10.10-server-i386.iso",
|
47
|
+
:iso_src => "http://releases.ubuntu.com/maverick/ubuntu-10.10-server-i386.iso",
|
48
|
+
:iso_md5 => "ce1cee108de737d7492e37069eed538e",
|
49
|
+
:iso_download_timeout => "1000",
|
50
|
+
:boot_wait => "10",
|
51
|
+
:boot_cmd_sequence => [
|
52
|
+
'<Esc><Esc><Enter>',
|
53
|
+
'/install/vmlinuz noapic preseed/url=http://%IP%:%PORT%/preseed.cfg ',
|
54
|
+
'debian-installer=en_US auto locale=en_US kbd-chooser/method=us ',
|
55
|
+
'hostname=%NAME% ',
|
56
|
+
'fb=false debconf/frontend=noninteractive ',
|
57
|
+
'console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us ',
|
58
|
+
'initrd=/install/initrd.gz -- <Enter>'
|
59
|
+
],
|
60
|
+
:kickstart_port => "7122", :kickstart_timeout => "10000",:kickstart_file => "preseed.cfg",
|
61
|
+
:ssh_login_timeout => "10000",:ssh_user => "vagrant", :ssh_password => "vagrant",:ssh_key => "",
|
62
|
+
:ssh_host_port => "2222", :ssh_guest_port => "22",
|
63
|
+
:sudo_cmd => "echo '%p'|sudo -S sh '%f'",
|
64
|
+
:shutdown_cmd => "shutdown -H",
|
65
|
+
:postinstall_files => [ "postinstall.sh"],:postinstall_timeout => "10000"
|
66
|
+
}
|
67
|
+
)
|
68
|
+
</pre>
|
69
|
+
|
70
|
+
If you need to change values in the templates, be sure to run the rake undefine, the rake define again to copy the changes across.
|
71
|
+
|
72
|
+
## Put your isofile inside the $VEEWEE/iso directory or if you don't run
|
73
|
+
$ vagrant basebox build 'myubuntubox'
|
74
|
+
|
75
|
+
-> the build assumes your iso files are in 'currentdir'/iso
|
76
|
+
-> if it can not find it will suggest to download the iso for you
|
77
|
+
|
78
|
+
## Build the new box:
|
79
|
+
$ vagrant basebox build 'myubuntubox'
|
80
|
+
|
81
|
+
- This will create a machine + disk according to the definition.rb
|
82
|
+
- Note: :os_type_id = The internal Name Virtualbox uses for that Distribution
|
83
|
+
- Mount the ISO File :iso_file
|
84
|
+
- Boot up the machine and wait for :boot_time
|
85
|
+
- Send the keystrokes in :boot_cmd_sequence
|
86
|
+
- Startup a webserver on :kickstart_port to wait for a request for the :kickstart_file
|
87
|
+
- Wait for ssh login to work with :ssh_user , :ssh_password
|
88
|
+
- Sudo execute the :postinstall_files
|
89
|
+
|
90
|
+
## Export the vm to a .box file
|
91
|
+
$ vagrant basebox export 'myubuntubox'
|
92
|
+
|
93
|
+
this is actually calling - vagrant package --base 'myubuntubox' --output 'boxes/myubuntubox.box'
|
94
|
+
|
95
|
+
this will result in a myubuntubox.box
|
96
|
+
|
97
|
+
## Add the box as one of your boxes
|
98
|
+
$ vagrant box add 'myubuntubox' 'myubuntubox.box'
|
99
|
+
|
100
|
+
## Use it in vagrant
|
101
|
+
Start vagrant init in another window (as we have set the Virtualbox env to tmp before)
|
102
|
+
$ To import it into vagrant type:
|
103
|
+
|
104
|
+
To use it:
|
105
|
+
vagrant init 'myubuntubox'
|
106
|
+
vagrant up
|
107
|
+
vagrant ssh
|
108
|
+
|
109
|
+
## If you have a setup working, share your 'definition' with me. That would be fun!
|
110
|
+
|
111
|
+
IDEAS:
|
112
|
+
|
113
|
+
- Now you integrate this with your CI build to create a daily basebox
|
114
|
+
|
115
|
+
FUTURE IDEAS:
|
116
|
+
|
117
|
+
- use snapshots to fastforward initial boot, and every postinstall command
|
118
|
+
- export to AMI too
|
119
|
+
- provide for more failsafe execution, testing parameters
|
120
|
+
- use more virtualbox ruby instead of calling the VBoxManage command
|
121
|
+
- Verify the installation with cucumber-nagios (ssh functionality)
|
122
|
+
- Do the same for Vmware Fusion
|
123
|
+
|
124
|
+
BUGS: Lots = Like I said it currently works for me, on my machine and with the correct magic sequence :)
|
data/Rakefile
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'bundler/setup'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
#Setup some base variables to use
|
7
|
+
veewee_dir= "."
|
8
|
+
definition_dir= File.expand_path(File.join(veewee_dir, "definitions"))
|
9
|
+
lib_dir= File.expand_path(File.join(veewee_dir, "lib"))
|
10
|
+
box_dir= File.expand_path(File.join(veewee_dir, "boxes"))
|
11
|
+
template_dir=File.expand_path(File.join(veewee_dir, "templates"))
|
12
|
+
vbox_dir=File.expand_path(File.join(veewee_dir, "tmp"))
|
13
|
+
tmp_dir=File.expand_path(File.join(veewee_dir, "tmp"))
|
14
|
+
iso_dir=File.expand_path(File.join(veewee_dir, "iso"))
|
15
|
+
|
16
|
+
|
17
|
+
#Load Veewee::Session libraries
|
18
|
+
Dir.glob(File.join(lib_dir, '**','*.rb')).each {|f|
|
19
|
+
require f }
|
20
|
+
|
21
|
+
#Initialize
|
22
|
+
Veewee::Session.setenv({:veewee_dir => veewee_dir, :definition_dir => definition_dir,
|
23
|
+
:template_dir => template_dir, :iso_dir => iso_dir, :box_dir => box_dir, :tmp_dir => tmp_dir})
|
24
|
+
|
25
|
+
desc 'Default: list templates'
|
26
|
+
task :default => [:templates]
|
27
|
+
|
28
|
+
desc 'List templates'
|
29
|
+
task :templates do
|
30
|
+
Veewee::Session.list_templates
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Define box'
|
34
|
+
task :define, [:boxname,:template_name] do |t,args|
|
35
|
+
if args.to_hash.size!=2
|
36
|
+
puts "needs two arguments: rake define['boxname','template_name']"
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
Veewee::Session.define(args.boxname,args.template_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Undefine box'
|
43
|
+
task :undefine, [:boxname] do |t,args|
|
44
|
+
if args.to_hash.size!=1
|
45
|
+
puts "needs one arguments: rake undefine[\"yourname\"]"
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
Veewee::Session.undefine(args.boxname)
|
49
|
+
end
|
50
|
+
|
51
|
+
desc 'List Definitions'
|
52
|
+
task :definitions do
|
53
|
+
Veewee::Session.list_definitions
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Build box'
|
57
|
+
task :build, [:boxname] do |t,args|
|
58
|
+
if args.to_hash.size!=1
|
59
|
+
puts "needs one arguments: rake build['boxname']"
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
Veewee::Session.build(args.boxname)
|
63
|
+
end
|
64
|
+
|
65
|
+
desc 'List boxes'
|
66
|
+
task :boxes do
|
67
|
+
Veewee::Session.list_boxes
|
68
|
+
end
|
69
|
+
|
70
|
+
desc 'Export box'
|
71
|
+
task :export, [:boxname] do |t,args|
|
72
|
+
if args.to_hash.size!=1
|
73
|
+
puts "needs one arguments: rake export['boxname']"
|
74
|
+
exit
|
75
|
+
end
|
76
|
+
Veewee::Session.export_box(args.boxname)
|
77
|
+
end
|
78
|
+
|
79
|
+
desc 'Remove box'
|
80
|
+
task :remove_box, [:boxname] do |t,args|
|
81
|
+
Veewee::Session.remove_box(args.boxname)
|
82
|
+
end
|
83
|
+
|
84
|
+
desc 'List ostypes available'
|
85
|
+
task :list_ostypes do |t,args|
|
86
|
+
Veewee::Session.list_ostypes
|
87
|
+
end
|
88
|
+
|
89
|
+
desc 'Clean all unfinished builds'
|
90
|
+
task :clean do
|
91
|
+
Veewee::Session.clean
|
92
|
+
end
|
data/bin/veewee
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'thor'
|
5
|
+
require 'bundler'
|
6
|
+
require 'virtualbox'
|
7
|
+
require 'veewee'
|
8
|
+
|
9
|
+
|
10
|
+
#Setup some base variables to use
|
11
|
+
veewee_dir= File.expand_path(File.join(File.dirname(__FILE__),".."))
|
12
|
+
definition_dir= File.expand_path(File.join(".", "definitions"))
|
13
|
+
lib_dir= File.expand_path(File.join(veewee_dir, "lib"))
|
14
|
+
box_dir= File.expand_path(File.join(veewee_dir, "boxes"))
|
15
|
+
template_dir=File.expand_path(File.join(veewee_dir, "templates"))
|
16
|
+
|
17
|
+
#vbox_dir=File.expand_path(File.join(veewee_dir, "tmp"))
|
18
|
+
tmp_dir=File.expand_path(File.join(veewee_dir, "tmp"))
|
19
|
+
|
20
|
+
iso_dir=File.expand_path(File.join(veewee_dir, "iso"))
|
21
|
+
|
22
|
+
#needs to be moved to the config files to be allowed override
|
23
|
+
#ENV['VBOX_USER_HOME']=vbox_dir
|
24
|
+
|
25
|
+
#Load Veewee::Session libraries
|
26
|
+
Dir.glob(File.join(lib_dir, '**','*.rb')).each {|f|
|
27
|
+
require f }
|
28
|
+
|
29
|
+
#Initialize
|
30
|
+
Veewee::Session.setenv({:veewee_dir => veewee_dir, :definition_dir => definition_dir,
|
31
|
+
:template_dir => template_dir, :iso_dir => iso_dir, :box_dir => box_dir, :tmp_dir => tmp_dir})
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
class VeeweeCLI < Thor
|
36
|
+
|
37
|
+
desc "init [NAME] [TEMPLATE]", "initializes a box from a template"
|
38
|
+
method_options :force => :boolean
|
39
|
+
def init(boxname=nil, template=nil)
|
40
|
+
if (boxname.nil?)
|
41
|
+
puts "please provide a boxname"
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
puts "Init a new box #{boxname}, starting from template #{template}"
|
46
|
+
Veewee::Session.define(boxname,template)
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "templates", "list the template available"
|
51
|
+
def templates
|
52
|
+
Veewee::Session.list_templates
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "build [NAME]", "build the box defined"
|
56
|
+
method_options :force => :boolean
|
57
|
+
def build(boxname)
|
58
|
+
puts "Building box #{boxname}"
|
59
|
+
Veewee::Session.build(boxname)
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "export [NAME]", "export the box"
|
63
|
+
method_options :force => :boolean
|
64
|
+
def export(boxname)
|
65
|
+
if (!boxname.nil?)
|
66
|
+
Veewee::Session.export_box(boxname)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
version=VirtualBox.version
|
75
|
+
if (version.match(/^4./))
|
76
|
+
VeeweeCLI.start
|
77
|
+
else
|
78
|
+
puts "veewee only supports VirtualBox 4.x"
|
79
|
+
end
|
data/iso/.gitignore
ADDED
data/lib/vagrant_init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'veewee'
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'veewee/session'
|
2
|
+
|
3
|
+
#Load Veewee::Session libraries
|
4
|
+
lib_dir= File.expand_path(File.join(File.dirname(__FILE__),"..","..", "lib"))
|
5
|
+
Dir.glob(File.join(lib_dir, '**','*.rb')).each {|f| require f }
|
6
|
+
|
7
|
+
#Setup some base variables to use
|
8
|
+
template_dir=File.expand_path(File.join(lib_dir,"..", "templates"))
|
9
|
+
|
10
|
+
veewee_dir="."
|
11
|
+
definition_dir= File.expand_path(File.join(veewee_dir, "definitions"))
|
12
|
+
tmp_dir=File.expand_path(File.join(veewee_dir, "tmp"))
|
13
|
+
iso_dir=File.expand_path(File.join(veewee_dir, "iso"))
|
14
|
+
box_dir=File.expand_path(File.join(veewee_dir, "boxes"))
|
15
|
+
|
16
|
+
#Initialize
|
17
|
+
Veewee::Session.setenv({:veewee_dir => veewee_dir, :definition_dir => definition_dir,
|
18
|
+
:template_dir => template_dir, :iso_dir => iso_dir, :box_dir => box_dir, :tmp_dir => tmp_dir})
|
19
|
+
|
20
|
+
module Veewee
|
21
|
+
class Command < Vagrant::Command::GroupBase
|
22
|
+
register "basebox","Commands to manage baseboxes"
|
23
|
+
|
24
|
+
desc "templates", "List the currently available box templates"
|
25
|
+
def templates
|
26
|
+
Veewee::Session.list_templates
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "define BOXNAME TEMPLATE", "Define a new box starting from a template"
|
30
|
+
method_option :force,:type => :boolean , :default => false, :aliases => "-f", :desc => "overwrite the definition"
|
31
|
+
def define(boxname, template)
|
32
|
+
Veewee::Session.define(boxname,template,options)
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "build BOXNAME", "Build the box BOXNAME"
|
36
|
+
method_option :force,:type => :boolean , :default => false, :aliases => "-f", :desc => "overwrite the basebox"
|
37
|
+
def build(boxname)
|
38
|
+
Veewee::Session.build(boxname,options)
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "ostypes", "List the available Operating System types"
|
42
|
+
def ostypes
|
43
|
+
Veewee::Session.list_ostypes
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "destroy BOXNAME", "Destroy the virtualmachine of a basebox"
|
47
|
+
def destroy(boxname)
|
48
|
+
puts Veewee::Session.destroy_vm(boxname)
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "list", "Lists all defined boxes"
|
52
|
+
def list
|
53
|
+
Veewee::Session.list_definitions
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "export [NAME]", "export the box"
|
57
|
+
method_options :force => :boolean
|
58
|
+
def export(boxname)
|
59
|
+
if (!boxname.nil?)
|
60
|
+
Veewee::Session.export_box(boxname)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
module Veewee
|
3
|
+
class Export
|
4
|
+
|
5
|
+
# Shellutil.execute("vagrant package --base #{vmname} --include /tmp/Vagrantfile --output /tmp/#{vmname}.box", {:progress => "on"})
|
6
|
+
|
7
|
+
def self.vagrant(boxname,boxdir,definition)
|
8
|
+
|
9
|
+
#Check if box already exists
|
10
|
+
vm=VirtualBox::VM.find(boxname)
|
11
|
+
if vm.nil?
|
12
|
+
puts "#{boxname} is not found, maybe you need to build first?"
|
13
|
+
exit
|
14
|
+
end
|
15
|
+
#We need to shutdown first
|
16
|
+
if vm.running?
|
17
|
+
puts "Vagrant requires the box to be shutdown, before it can export"
|
18
|
+
puts "Sudo also needs to work for user #{definition[:ssh_user]}"
|
19
|
+
puts "Performing a clean shutdown now."
|
20
|
+
ssh_options={ :user => definition[:ssh_user], :port => definition[:ssh_host_port], :password => definition[:ssh_password],
|
21
|
+
:timeout => definition[:ssh_timeout]}
|
22
|
+
|
23
|
+
Veewee::Ssh.execute("localhost","sudo #{definition[:shutdown_cmd]}",ssh_options)
|
24
|
+
|
25
|
+
#Wait for state poweroff
|
26
|
+
while (vm.running?) do
|
27
|
+
print '.'
|
28
|
+
sleep 1
|
29
|
+
end
|
30
|
+
puts
|
31
|
+
puts "Machine #{boxname} is powered off cleanly"
|
32
|
+
end
|
33
|
+
|
34
|
+
#Vagrant requires a relative path for output of boxes
|
35
|
+
|
36
|
+
#4.0.x. not using boxes as a subdir
|
37
|
+
boxdir=Pathname.new(Dir.pwd)
|
38
|
+
|
39
|
+
full_path=File.join(boxdir,boxname+".box")
|
40
|
+
path1=Pathname.new(full_path)
|
41
|
+
path2=Pathname.new(Dir.pwd)
|
42
|
+
box_path=path1.relative_path_from(path2).to_s
|
43
|
+
|
44
|
+
if File.exists?("#{box_path}")
|
45
|
+
puts "box #{boxname} already exists"
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
|
49
|
+
puts "Excuting vagrant voodoo:"
|
50
|
+
export_command="vagrant package --base '#{boxname}' --output '#{box_path}'"
|
51
|
+
puts "#{export_command}"
|
52
|
+
Veewee::Shell.execute("#{export_command}") #hmm, needs to get the gem_home set?
|
53
|
+
puts
|
54
|
+
|
55
|
+
#add_ssh_nat_mapping back!!!!
|
56
|
+
|
57
|
+
puts "To import it into vagrant type:"
|
58
|
+
puts "vagrant box add '#{boxname}' '#{box_path}'"
|
59
|
+
puts ""
|
60
|
+
puts "To use it:"
|
61
|
+
puts "vagrant init '#{boxname}'"
|
62
|
+
puts "vagrant up"
|
63
|
+
puts "vagrant ssh"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# #currently vagrant has a problem with the machine up, it calculates the wrong port to ssh to poweroff the system
|
71
|
+
# thebox.execute("shutdown -h now")
|
72
|
+
# thebox.wait_for_state("poweroff")
|
73
|
+
|
74
|
+
# Shellutil.execute("echo 'Vagrant::Config.run do |config|' > /tmp/Vagrantfile")
|
75
|
+
# Shellutil.execute("echo ' config.ssh.forwarded_port_key = \"ssh\"' >> /tmp/Vagrantfile")
|
76
|
+
# Shellutil.execute("echo ' config.vm.forward_port(\"ssh\",22,#{host_port})' >> /tmp/Vagrantfile")
|
77
|
+
# Shellutil.execute("echo 'end' >> /tmp/Vagrantfile")
|
78
|
+
|
79
|
+
|
80
|
+
#vagrant export disables the machine
|
81
|
+
# thebox.ssh_enable_vmachine({:hostport => host_port , :guestport => 22} )
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Veewee
|
2
|
+
class Scancode
|
3
|
+
|
4
|
+
def self.send_sequence(vboxcmd,vname,sequence)
|
5
|
+
puts
|
6
|
+
counter=0
|
7
|
+
sequence.each { |s|
|
8
|
+
counter=counter+1
|
9
|
+
|
10
|
+
s.gsub!(/%IP%/,Veewee::Session.local_ip);
|
11
|
+
s.gsub!(/%PORT%/,'7122');
|
12
|
+
s.gsub!(/%NAME%/, vname);
|
13
|
+
puts "Typing:[#{counter}]: "+s
|
14
|
+
|
15
|
+
keycodes=string_to_keycode(s)
|
16
|
+
|
17
|
+
# VBox seems to have issues with sending the scancodes as one big
|
18
|
+
# .join()-ed string. It seems to get them out or order or ignore some.
|
19
|
+
# A workaround is to send the scancodes one-by-one.
|
20
|
+
codes=""
|
21
|
+
for keycode in keycodes.split(' ') do
|
22
|
+
send_keycode(vboxcmd,vname,keycode)
|
23
|
+
sleep 0.01
|
24
|
+
end
|
25
|
+
#sleep after each sequence (needs to be param)
|
26
|
+
sleep 1
|
27
|
+
}
|
28
|
+
|
29
|
+
puts "Done typing."
|
30
|
+
puts
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.send_keycode(vboxcmd,vname,keycode)
|
35
|
+
command= "#{vboxcmd} controlvm '#{vname}' keyboardputscancode #{keycode}"
|
36
|
+
#puts "#{command}"
|
37
|
+
IO.popen("#{command}") { |f| print '' }
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.string_to_keycode(thestring)
|
41
|
+
|
42
|
+
#http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
|
43
|
+
|
44
|
+
k=Hash.new
|
45
|
+
k['1'] = '02' ; k['2'] = '03' ; k['3'] = '04'; k['4']= '05' ;k['5']='06'; k['6'] = '07' ; k['7'] = '08'; k['8'] = '09'; k['9']= '0a'; k['0']='0b'; k['-'] = '0c'; k['='] = '0d' ;
|
46
|
+
k['Tab'] = '0f';
|
47
|
+
k['q'] = '10' ; k['w'] = '11' ; k['e'] = '12'; k['r'] = '13' ; k['t'] = '14' ; k['y'] = '15'; k['u']= '16' ; k['i']='17'; k['o'] = '18' ; k['p'] = '19' ;
|
48
|
+
|
49
|
+
k['Q'] = '2a 10 aa' ; k['W'] = '2a 11 aa' ; k['E'] = '2a 12 aa'; k['R'] = '2a 13 aa' ; k['T'] = '2a 14 aa' ; k['Y'] = '2a 15 aa'; k['U']= '2a 16 aa' ; k['I']='2a 17 aa'; k['O'] = '2a 18 aa' ; k['P'] = '2a 19 aa' ;
|
50
|
+
|
51
|
+
k['a'] = '1e'; k['s'] = '1f' ; k['d'] = '20' ; k['f'] = '21'; k['g'] = '22' ; k['h'] = '23' ; k['j'] = '24'; k['k']= '25' ; k['l']='26'; k[';'] = '27'
|
52
|
+
k['A'] = '2a 1e aa'; k['S'] = '2a 1f aa' ; k['D'] = '2a 20 aa' ; k['F'] = '2a 21 aa'; k['G'] = '2a 22 aa' ; k['H'] = '2a 23 aa' ; k['J'] = '2a 24 aa'; k['K']= '2a 25 aa' ; k['L']='2a 26 aa';
|
53
|
+
|
54
|
+
k[';'] = '27' ;k['"']='28';
|
55
|
+
|
56
|
+
k['[']='1a'; k[']']='1b'
|
57
|
+
|
58
|
+
k['z'] = '2c'; k['x'] = '2d' ; k['c'] = '2e' ; k['v'] = '2f'; k['b'] = '30' ; k['n'] = '31' ; k['m'] = '32';
|
59
|
+
k['Z'] = '2a 2c aa'; k['X'] = '2a 2d aa' ; k['C'] = '2a 2e aa' ; k['V'] = '2a 2f aa'; k['B'] = '2a 30 aa' ; k['N'] = '2a 31 aa' ; k['M'] = '2a 32 aa';
|
60
|
+
|
61
|
+
k[',']= '33' ; k['.']='34'; k['/'] = '35' ;k[':'] = '2a 27 aa';
|
62
|
+
k['%'] = '2a 06 aa'; k['_'] = '2a 0c aa';
|
63
|
+
|
64
|
+
special=Hash.new;
|
65
|
+
special['<Enter>'] = '1c';
|
66
|
+
special['<Backspace>'] = '0e';
|
67
|
+
special['<Spacebar>'] = '39';
|
68
|
+
special['<Return>'] = '1c'
|
69
|
+
special['<Esc>'] = '01';
|
70
|
+
#special['<Up>'] = '01';
|
71
|
+
#special['<Down>'] = '01';
|
72
|
+
#special['<PageUp>'] = '01';
|
73
|
+
#special['<PageDown>'] = '01';
|
74
|
+
|
75
|
+
keycodes=''
|
76
|
+
thestring.gsub!(/ /,"<Spacebar>")
|
77
|
+
|
78
|
+
until thestring.length == 0
|
79
|
+
nospecial=true;
|
80
|
+
special.keys.each { |key|
|
81
|
+
if thestring.start_with?(key)
|
82
|
+
#take thestring
|
83
|
+
#check if it starts with a special key + pop special string
|
84
|
+
keycodes=keycodes+special[key]+' ';
|
85
|
+
thestring=thestring.slice(key.length,thestring.length-key.length)
|
86
|
+
nospecial=false;
|
87
|
+
break;
|
88
|
+
end
|
89
|
+
}
|
90
|
+
if nospecial
|
91
|
+
code=k[thestring.slice(0,1)]
|
92
|
+
if !code.nil?
|
93
|
+
keycodes=keycodes+code+' '
|
94
|
+
else
|
95
|
+
puts "no scan code for #{thestring.slice(0,1)}"
|
96
|
+
end
|
97
|
+
#pop one
|
98
|
+
thestring=thestring.slice(1,thestring.length-1)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
return keycodes
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|