lab 0.1.5 → 0.2.0

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.
Files changed (63) hide show
  1. data/.gitignore +4 -0
  2. data/config/test_lab.yml +11 -0
  3. data/config/test_targets.yml +21 -0
  4. data/lib/lab/controller/dynagen_controller.rb +6 -6
  5. data/lib/lab/controller/remote_esx_controller.rb +51 -51
  6. data/lib/lab/controller/remote_esxi_controller.rb +62 -0
  7. data/lib/lab/controller/remote_workstation_controller.rb +12 -12
  8. data/lib/lab/controller/virtualbox_controller.rb +16 -16
  9. data/lib/lab/controller/workstation_controller.rb +9 -9
  10. data/lib/lab/controller/workstation_vixr_controller.rb +9 -9
  11. data/lib/lab/controllers.rb +1 -3
  12. data/lib/lab/driver/dynagen_driver.rb +32 -32
  13. data/lib/lab/driver/fog_driver.rb +144 -144
  14. data/lib/lab/driver/remote_esxi_driver.rb +177 -0
  15. data/lib/lab/driver/remote_workstation_driver.rb +181 -181
  16. data/lib/lab/driver/virtualbox_driver.rb +132 -132
  17. data/lib/lab/driver/vm_driver.rb +177 -177
  18. data/lib/lab/driver/workstation_driver.rb +218 -218
  19. data/lib/lab/driver/workstation_vixr_driver.rb +108 -108
  20. data/lib/lab/drivers.rb +1 -1
  21. data/lib/lab/modifier/backtrack5_modifier.rb +8 -8
  22. data/lib/lab/modifier/dos_modifier.rb +3 -3
  23. data/lib/lab/modifier/test_modifier.rb +6 -6
  24. data/lib/lab/version.rb +1 -1
  25. data/lib/lab/vm.rb +242 -242
  26. data/lib/lab/vm_controller.rb +217 -211
  27. data/src/Gemfile +4 -0
  28. data/src/README.md +80 -0
  29. data/src/Rakefile +1 -0
  30. data/src/TODO +15 -0
  31. data/src/config/test_lab.yml +11 -0
  32. data/src/config/test_targets.yml +21 -0
  33. data/src/lab.gemspec +35 -0
  34. data/src/lib/lab.rb +2 -0
  35. data/src/lib/lab/controller/dynagen_controller.rb +14 -0
  36. data/src/lib/lab/controller/fog_controller.rb +6 -0
  37. data/src/lib/lab/controller/remote_esxi_controller.rb +62 -0
  38. data/src/lib/lab/controller/remote_workstation_controller.rb +22 -0
  39. data/src/lib/lab/controller/virtualbox_controller.rb +25 -0
  40. data/src/lib/lab/controller/vsphere_controller.rb +18 -0
  41. data/src/lib/lab/controller/workstation_controller.rb +17 -0
  42. data/src/lib/lab/controller/workstation_vixr_controller.rb +19 -0
  43. data/src/lib/lab/controllers.rb +9 -0
  44. data/src/lib/lab/driver/dynagen_driver.rb +47 -0
  45. data/src/lib/lab/driver/fog_driver.rb +104 -0
  46. data/src/lib/lab/driver/remote_esxi_driver.rb +177 -0
  47. data/src/lib/lab/driver/remote_workstation_driver.rb +197 -0
  48. data/src/lib/lab/driver/virtualbox_driver.rb +142 -0
  49. data/src/lib/lab/driver/vm_driver.rb +195 -0
  50. data/src/lib/lab/driver/vsphere_driver.rb +120 -0
  51. data/src/lib/lab/driver/workstation_driver.rb +234 -0
  52. data/src/lib/lab/driver/workstation_vixr_driver.rb +126 -0
  53. data/src/lib/lab/drivers.rb +9 -0
  54. data/src/lib/lab/modifier/backtrack5_modifier.rb +16 -0
  55. data/src/lib/lab/modifier/dos_modifier.rb +14 -0
  56. data/src/lib/lab/modifier/test_modifier.rb +16 -0
  57. data/src/lib/lab/modifiers.rb +3 -0
  58. data/src/lib/lab/version.rb +3 -0
  59. data/src/lib/lab/vm.rb +269 -0
  60. data/src/lib/lab/vm_controller.rb +275 -0
  61. data/src/test/.gitkeep +0 -0
  62. metadata +51 -12
  63. data/lib/lab/driver/remote_esx_driver.rb +0 -177
@@ -0,0 +1,195 @@
1
+ ##
2
+ ## $Id$
3
+ ##
4
+
5
+ #
6
+ # !!WARNING!! - All drivers are expected to filter input before running
7
+ # anything based on it. This is particularly important in the case
8
+ # of the drivers which wrap a command line to provide functionality.
9
+ #
10
+
11
+ module Lab
12
+ module Drivers
13
+ class VmDriver
14
+
15
+ attr_accessor :vmid
16
+ attr_accessor :location
17
+ attr_accessor :os
18
+ attr_accessor :tools
19
+ attr_accessor :credentials
20
+
21
+ def initialize(config)
22
+
23
+ @vmid = filter_command(config["vmid"].to_s)
24
+ @location = filter_command(config["location"])
25
+ @credentials = config["credentials"] || []
26
+ @tools = filter_input(config["tools"])
27
+ @arch = filter_input(config["arch"])
28
+ @os = filter_input(config["os"])
29
+ @hostname = filter_input(config["hostname"]) || filter_input(config["vmid"].to_s)
30
+
31
+ # Currently only implemented for the first set
32
+ if @credentials.count > 0
33
+ @vm_user = filter_input(@credentials[0]['user'])
34
+ @vm_pass = filter_input(@credentials[0]['pass'])
35
+ @vm_keyfile = filter_input(@credentials[0]['keyfile'])
36
+ end
37
+ end
38
+
39
+ ## This interface must be implemented in a child driver class
40
+ ## #########################################################
41
+
42
+ def register
43
+ raise "Command not Implemented"
44
+ end
45
+
46
+ def unregister
47
+ raise "Command not Implemented"
48
+ end
49
+
50
+ def start
51
+ raise "Command not Implemented"
52
+ end
53
+
54
+ def stop
55
+ raise "Command not Implemented"
56
+ end
57
+
58
+ def suspend
59
+ raise "Command not Implemented"
60
+ end
61
+
62
+ def pause
63
+ raise "Command not Implemented"
64
+ end
65
+
66
+ def resume
67
+ raise "Command not Implemented"
68
+ end
69
+
70
+ def reset
71
+ raise "Command not Implemented"
72
+ end
73
+
74
+ def create_snapshot(snapshot)
75
+ raise "Command not Implemented"
76
+ end
77
+
78
+ def revert_snapshot(snapshot)
79
+ raise "Command not Implemented"
80
+ end
81
+
82
+ def delete_snapshot(snapshot)
83
+ raise "Command not Implemented"
84
+ end
85
+
86
+ def run_command(command)
87
+ raise "Command not Implemented"
88
+ end
89
+
90
+ def copy_from(from, to)
91
+ raise "Command not Implemented"
92
+ end
93
+
94
+ def copy_to(from, to)
95
+ raise "Command not Implemented"
96
+ end
97
+
98
+ def check_file_exists(file)
99
+ raise "Command not Implemented"
100
+ end
101
+
102
+ def create_directory(directory)
103
+ raise "Command not Implemented"
104
+ end
105
+
106
+ def cleanup
107
+ raise "Command not Implemented"
108
+ end
109
+
110
+ ## End Interface
111
+ ## #########################################################
112
+
113
+ private
114
+
115
+ # The only reason we don't filter here is because we need
116
+ # the ability to still run clean (controlled entirely by us)
117
+ # command lines.
118
+ def system_command(command)
119
+ puts "DEBUG: system command #{command}"
120
+ system(command)
121
+ end
122
+
123
+ def remote_system_command(command)
124
+ puts "DEBUG: remote system command #{command} running with user #{@user}@#{@host}"
125
+ system_command("ssh #{@user}@#{@host} \"#{command}\"")
126
+ end
127
+
128
+ def scp_to(local,remote)
129
+ if @vm_keyfile
130
+ #puts "DEBUG: authenticating to #{@hostname} as #{@vm_user} with key #{@vm_keyfile}"
131
+ Net::SCP.start(@hostname, @vm_user, :keys => [@vm_keyfile]) do |scp|
132
+ puts "DEBUG: uploading #{local} to #{remote}"
133
+ scp.upload!(local,remote)
134
+ end
135
+ else
136
+ Net::SCP.start(@hostname, @vm_user, :password => @vm_pass, :auth_methods => ["password"]) do |scp|
137
+ puts "DEBUG: uploading #{local} to #{remote}"
138
+ scp.upload!(local,remote)
139
+ end
140
+ end
141
+ end
142
+
143
+ def scp_from(remote, local)
144
+ # download a file from a remote server
145
+ if @vm_keyfile
146
+ #puts "DEBUG: authenticating to #{@hostname} as #{@vm_user} with key #{@vm_keyfile}"
147
+ Net::SCP.start(@hostname, @vm_user, :keys => [@vm_keyfile]) do |scp|
148
+ puts "DEBUG: downloading #{remote} to #{local}"
149
+ scp.download!(remote,local)
150
+ end
151
+ else
152
+ Net::SCP.start(@hostname, @vm_user, :password => @vm_pass, :auth_methods => ["password"]) do |scp|
153
+ puts "DEBUG: downloading #{remote} to #{local}"
154
+ scp.download!(remote,local)
155
+ end
156
+ end
157
+ end
158
+
159
+ def ssh_exec(command)
160
+ if @vm_keyfile
161
+ #puts "DEBUG: authenticating to #{@hostname} as #{@vm_user} with key #{@vm_keyfile}"
162
+ Net::SSH.start(@hostname, @vm_user, :keys => [@vm_keyfile]) do |ssh|
163
+ puts "DEBUG: running command: #{command}"
164
+ ssh.exec!(command)
165
+ end
166
+ else
167
+ Net::SSH.start(@hostname, @vm_user, :password => @vm_pass, :auth_methods => ["password"]) do |ssh|
168
+ result = ssh.exec!(command)
169
+ end
170
+ end
171
+ end
172
+
173
+ def filter_input(string)
174
+ return "" unless string # nil becomes empty string
175
+ return unless string.class == String # Allow other types unmodified
176
+
177
+ unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string
178
+ raise "WARNING! Invalid character in: #{string}"
179
+ end
180
+ string
181
+ end
182
+
183
+ def filter_command(string)
184
+ return "" unless string # nil becomes empty string
185
+ return unless string.class == String # Allow other types unmodified
186
+
187
+ unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/.match string
188
+ raise "WARNING! Invalid character in: #{string}"
189
+ end
190
+ string
191
+ end
192
+
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,120 @@
1
+ require 'vm_driver'
2
+
3
+ ##
4
+ ## $Id$
5
+ ##
6
+
7
+ # This driver was built against:
8
+ # VMware Vsphere 4.1
9
+
10
+ module Lab
11
+ module Drivers
12
+
13
+ class VsphereDriver < VmDriver
14
+
15
+ def initialize(config)
16
+ unless config['user'] then raise ArgumentError, "Must provide a username" end
17
+ unless config['host'] then raise ArgumentError, "Must provide a hostname" end
18
+ unless config[''] then raise ArgumentError, "Must provide a password" end
19
+ super(config)
20
+
21
+ @user = filter_command(config['user'])
22
+ @host = filter_command(config['host'])
23
+
24
+ # Soft dependency
25
+ begin
26
+ require 'rbvmomi'
27
+ rescue LoadError
28
+ raise "WARNING: Library rbvmomi not found. Could not create driver!"
29
+ end
30
+
31
+ vim = RbVmomi::VIM.connect host: @host, user: @user, password: @pass
32
+ dc = vim.serviceInstance.find_datacenter("datacenter1") or fail "datacenter not found"
33
+ @vm = dc.find_vm("test") or fail "VM not found"
34
+ end
35
+
36
+ def start
37
+ @vm.PowerOnVM_Task.wait_for_completion
38
+ end
39
+
40
+ def stop
41
+ @vm.PowerOffVM_Task.wait_for_completion
42
+ end
43
+
44
+ def suspend
45
+ @vm.SuspendVM_Task.wait_for_completion
46
+ end
47
+
48
+ def pause
49
+ raise "Unimplemented"
50
+ end
51
+
52
+ def resume
53
+ raise "Unimplemented"
54
+ end
55
+
56
+ def reset
57
+ @vm.ResetVM_Task.wait_for_completion
58
+ end
59
+
60
+ def create_snapshot(snapshot)
61
+ snapshot = filter_input(snapshot)
62
+ raise "Unimplemented"
63
+ end
64
+
65
+ def revert_snapshot(snapshot)
66
+ raise "Unimplemented"
67
+ # If we got here, the snapshot didn't exist
68
+ raise "Invalid Snapshot Name"
69
+ end
70
+
71
+ def delete_snapshot(snapshot, remove_children=false)
72
+ raise "Unimplemented"
73
+ # If we got here, the snapshot didn't exist
74
+ raise "Invalid Snapshot Name"
75
+ end
76
+
77
+ def delete_all_snapshots
78
+ raise "Unimplemented"
79
+ end
80
+
81
+ def run_command(command)
82
+ raise "Unimplemented"
83
+ end
84
+
85
+ def copy_from(from, to)
86
+ if @os == "linux"
87
+ scp_from(from, to)
88
+ else
89
+ raise "Unimplemented"
90
+ end
91
+ end
92
+
93
+ def copy_to(from, to)
94
+ if @os == "linux"
95
+ scp_to(from, to)
96
+ else
97
+ raise "Unimplemented"
98
+ end
99
+ end
100
+
101
+ def check_file_exists(file)
102
+ raise "Unimplemented"
103
+ end
104
+
105
+ def create_directory(directory)
106
+ raise "Unimplemented"
107
+ end
108
+
109
+ def cleanup
110
+ raise "Unimplemented"
111
+ end
112
+
113
+ def running?
114
+ raise "Unimplemented"
115
+ end
116
+
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,234 @@
1
+ require 'vm_driver'
2
+
3
+ ##
4
+ ## $Id$
5
+ ##
6
+
7
+ module Lab
8
+ module Drivers
9
+
10
+ class WorkstationDriver < VmDriver
11
+
12
+ def initialize(config)
13
+ super(config)
14
+
15
+ if !File.exist?(@location)
16
+ raise ArgumentError,"Couldn't find: #{@location}"
17
+ end
18
+ end
19
+
20
+ def start
21
+ system_command("vmrun -T ws start " + "\'#{@location}\' nogui")
22
+ end
23
+
24
+ def stop
25
+ system_command("vmrun -T ws stop " + "\'#{@location}\' nogui")
26
+ end
27
+
28
+ def suspend
29
+ system_command("vmrun -T ws suspend " + "\'#{@location}\' nogui")
30
+ end
31
+
32
+ def pause
33
+ system_command("vmrun -T ws pause " + "\'#{@location}\' nogui")
34
+ end
35
+
36
+ def reset
37
+ system_command("vmrun -T ws reset " + "\'#{@location}\' nogui")
38
+ end
39
+
40
+ def create_snapshot(snapshot)
41
+ snapshot = filter_input(snapshot)
42
+ system_command("vmrun -T ws snapshot " + "\'#{@location}\' \'#{snapshot}\' nogui")
43
+ end
44
+
45
+ def revert_snapshot(snapshot)
46
+ snapshot = filter_input(snapshot)
47
+ system_command("vmrun -T ws revertToSnapshot " + "\'#{@location}\' \'#{snapshot}\' nogui")
48
+ end
49
+
50
+ def delete_snapshot(snapshot)
51
+ snapshot = filter_input(snapshot)
52
+ system_command("vmrun -T ws deleteSnapshot " + "\'#{@location}\' \'#{snapshot}\' nogui" )
53
+ end
54
+
55
+ def run_command(command)
56
+
57
+ #
58
+ # Generate a script name
59
+ #
60
+ script_rand_name = rand(1000000)
61
+
62
+ #
63
+ # Configure paths for each OS - We really can't filter command, so we're gonna
64
+ # stick it in a script
65
+ #
66
+ if @os == "windows"
67
+ local_tempfile_path = "/tmp/lab_script_#{script_rand_name}.bat"
68
+ remote_tempfile_path = "C:\\\\lab_script_#{script_rand_name}.bat"
69
+ remote_output_file = "C:\\\\lab_command_output_#{script_rand_name}"
70
+ remote_run_command = remote_tempfile_path
71
+ File.open(local_tempfile_path, 'w') {|f| f.write(command) }
72
+ else
73
+
74
+ local_tempfile_path = "/tmp/lab_script_#{script_rand_name}.sh"
75
+ remote_tempfile_path = "/tmp/lab_script_#{script_rand_name}.sh"
76
+ remote_output_file = "/tmp/lab_command_output_#{script_rand_name}"
77
+ local_output_file = "/tmp/lab_command_output_#{script_rand_name}"
78
+
79
+ remote_run_command = remote_tempfile_path
80
+
81
+ File.open(local_tempfile_path, 'w') {|f| f.write("#!/bin/sh\n#{command}\n")}
82
+ end
83
+
84
+ if @tools
85
+
86
+ #puts "DEBUG: Running w/ tools"
87
+
88
+ #
89
+ # Copy our local tempfile to the guest
90
+ #
91
+ vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
92
+ "copyFileFromHostToGuest \'#{@location}\' \'#{local_tempfile_path}\'" +
93
+ " \'#{remote_tempfile_path}\'"
94
+ system_command(vmrunstr)
95
+
96
+ if @os == "linux"
97
+ #
98
+ # Now run the command directly on the guest (linux - call w/ /bin/sh)
99
+ #
100
+ vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
101
+ "runProgramInGuest \'#{@location}\' /bin/sh #{remote_tempfile_path} > #{remote_output_file}"
102
+ system_command(vmrunstr)
103
+ else
104
+ #
105
+ # Now run the command directly on the guest (windows)
106
+ #
107
+ vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
108
+ "runProgramInGuest \'#{@location}\' #{remote_tempfile_path} > #{remote_output_file}"
109
+ system_command(vmrunstr)
110
+ end
111
+
112
+ #
113
+ # Cleanup. Delete it on the guest
114
+ #
115
+ vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
116
+ "deleteFileInGuest \'#{@location}\' \'#{remote_tempfile_path}\'"
117
+ system_command(vmrunstr)
118
+
119
+ #
120
+ # Delete it locally
121
+ #
122
+ local_delete_command = "rm #{local_tempfile_path}"
123
+ system_command(local_delete_command)
124
+ else
125
+
126
+ #
127
+ # Use SCP / SSH
128
+ #
129
+
130
+ if @os == "linux"
131
+
132
+ #
133
+ # Copy it over
134
+ #
135
+ scp_to(local_tempfile_path, remote_tempfile_path)
136
+
137
+ #
138
+ # And ... execute it
139
+ #
140
+ ssh_exec("/bin/sh #{remote_tempfile_path} > #{remote_output_file}")
141
+
142
+ #
143
+ # Now copy the output back to us
144
+ #
145
+ scp_from(remote_output_file, local_output_file)
146
+
147
+ # Now, let's look at the output of the command
148
+ output_string = File.open(local_output_file,"r").read
149
+
150
+ #
151
+ # And clean up
152
+ #
153
+ ssh_exec("rm #{remote_output_file}")
154
+ ssh_exec("rm #{remote_tempfile_path}")
155
+
156
+ `rm #{local_output_file}`
157
+
158
+ else
159
+ raise "Hey, no tools, and windows? can't do nuttin for ya man."
160
+ end
161
+
162
+ end
163
+ output_string
164
+ end
165
+
166
+ def copy_from(from, to)
167
+ from = filter_input(from)
168
+ to = filter_input(to)
169
+ if @tools
170
+ vmrunstr = "vmrun -T ws -gu \'#{@vm_user}\' -gp \'#{@vm_pass}\' copyFileFromGuestToHost " +
171
+ "\'#{@location}\' \'#{from}\' \'#{to}\'"
172
+ else
173
+ scp_from(from, to)
174
+ end
175
+ system_command(vmrunstr)
176
+ end
177
+
178
+ def copy_to(from, to)
179
+ from = filter_input(from)
180
+ to = filter_input(to)
181
+ if @tools
182
+ vmrunstr = "vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} copyFileFromHostToGuest " +
183
+ "\'#{@location}\' \'#{from}\' \'#{to}\'"
184
+ system_command(vmrunstr)
185
+ else
186
+ scp_to(from, to)
187
+ end
188
+ end
189
+
190
+ def check_file_exists(file)
191
+ file = filter_input(file)
192
+ if @tools
193
+ vmrunstr = "vmrun -T ws -gu \'#{@vm_user}\' -gp \'#{@vm_pass}\' fileExistsInGuest " +
194
+ "\'#{@location}\' \'#{file}\'"
195
+ system_command(vmrunstr)
196
+ else
197
+ raise "Unsupported"
198
+ end
199
+ end
200
+
201
+ def create_directory(directory)
202
+ directory = filter_input(directory)
203
+ if @tools
204
+ vmrunstr = "vmrun -T ws -gu \'#{@vm_user}\' -gp \'#{@vm_pass}\' createDirectoryInGuest " +
205
+ " \'#{@location}\' \'#{directory}\' "
206
+ system_command(vmrunstr)
207
+ else
208
+ raise "Unsupported"
209
+ end
210
+ end
211
+
212
+ def cleanup
213
+
214
+ end
215
+
216
+ def running?
217
+ ## Get running Vms
218
+ running = `vmrun list`
219
+ running_array = running.split("\n")
220
+ running_array.shift
221
+
222
+ running_array.each do |vmx|
223
+ if vmx.to_s == @location.to_s
224
+ return true
225
+ end
226
+ end
227
+
228
+ return false
229
+ end
230
+
231
+ end
232
+
233
+ end
234
+ end