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.
- data/.gitignore +4 -0
- data/config/test_lab.yml +11 -0
- data/config/test_targets.yml +21 -0
- data/lib/lab/controller/dynagen_controller.rb +6 -6
- data/lib/lab/controller/remote_esx_controller.rb +51 -51
- data/lib/lab/controller/remote_esxi_controller.rb +62 -0
- data/lib/lab/controller/remote_workstation_controller.rb +12 -12
- data/lib/lab/controller/virtualbox_controller.rb +16 -16
- data/lib/lab/controller/workstation_controller.rb +9 -9
- data/lib/lab/controller/workstation_vixr_controller.rb +9 -9
- data/lib/lab/controllers.rb +1 -3
- data/lib/lab/driver/dynagen_driver.rb +32 -32
- data/lib/lab/driver/fog_driver.rb +144 -144
- data/lib/lab/driver/remote_esxi_driver.rb +177 -0
- data/lib/lab/driver/remote_workstation_driver.rb +181 -181
- data/lib/lab/driver/virtualbox_driver.rb +132 -132
- data/lib/lab/driver/vm_driver.rb +177 -177
- data/lib/lab/driver/workstation_driver.rb +218 -218
- data/lib/lab/driver/workstation_vixr_driver.rb +108 -108
- data/lib/lab/drivers.rb +1 -1
- data/lib/lab/modifier/backtrack5_modifier.rb +8 -8
- data/lib/lab/modifier/dos_modifier.rb +3 -3
- data/lib/lab/modifier/test_modifier.rb +6 -6
- data/lib/lab/version.rb +1 -1
- data/lib/lab/vm.rb +242 -242
- data/lib/lab/vm_controller.rb +217 -211
- data/src/Gemfile +4 -0
- data/src/README.md +80 -0
- data/src/Rakefile +1 -0
- data/src/TODO +15 -0
- data/src/config/test_lab.yml +11 -0
- data/src/config/test_targets.yml +21 -0
- data/src/lab.gemspec +35 -0
- data/src/lib/lab.rb +2 -0
- data/src/lib/lab/controller/dynagen_controller.rb +14 -0
- data/src/lib/lab/controller/fog_controller.rb +6 -0
- data/src/lib/lab/controller/remote_esxi_controller.rb +62 -0
- data/src/lib/lab/controller/remote_workstation_controller.rb +22 -0
- data/src/lib/lab/controller/virtualbox_controller.rb +25 -0
- data/src/lib/lab/controller/vsphere_controller.rb +18 -0
- data/src/lib/lab/controller/workstation_controller.rb +17 -0
- data/src/lib/lab/controller/workstation_vixr_controller.rb +19 -0
- data/src/lib/lab/controllers.rb +9 -0
- data/src/lib/lab/driver/dynagen_driver.rb +47 -0
- data/src/lib/lab/driver/fog_driver.rb +104 -0
- data/src/lib/lab/driver/remote_esxi_driver.rb +177 -0
- data/src/lib/lab/driver/remote_workstation_driver.rb +197 -0
- data/src/lib/lab/driver/virtualbox_driver.rb +142 -0
- data/src/lib/lab/driver/vm_driver.rb +195 -0
- data/src/lib/lab/driver/vsphere_driver.rb +120 -0
- data/src/lib/lab/driver/workstation_driver.rb +234 -0
- data/src/lib/lab/driver/workstation_vixr_driver.rb +126 -0
- data/src/lib/lab/drivers.rb +9 -0
- data/src/lib/lab/modifier/backtrack5_modifier.rb +16 -0
- data/src/lib/lab/modifier/dos_modifier.rb +14 -0
- data/src/lib/lab/modifier/test_modifier.rb +16 -0
- data/src/lib/lab/modifiers.rb +3 -0
- data/src/lib/lab/version.rb +3 -0
- data/src/lib/lab/vm.rb +269 -0
- data/src/lib/lab/vm_controller.rb +275 -0
- data/src/test/.gitkeep +0 -0
- metadata +51 -12
- data/lib/lab/driver/remote_esx_driver.rb +0 -177
@@ -8,156 +8,156 @@ module Lab
|
|
8
8
|
module Drivers
|
9
9
|
class FogDriver < VmDriver
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
11
|
+
def initialize(config,fog_config)
|
12
|
+
|
13
|
+
super(config)
|
14
|
+
@fog_config = fog_config
|
15
|
+
|
16
|
+
# Soft dependency
|
17
|
+
begin
|
18
|
+
require 'fog'
|
19
|
+
rescue LoadError
|
20
|
+
raise "WARNING: Library fog not found. Could Not Create Driver"
|
21
|
+
end
|
22
|
+
|
23
|
+
if @fog_config['fog_type'] == "ec2"
|
24
|
+
|
25
|
+
# AWS / EC2 Base Credential Configuration
|
26
|
+
@aws_cert_file = IO.read(fog_config['fog_aws_cert_file']).chomp if fog_config['fog_aws_cert_file']
|
27
|
+
@aws_private_key_file = IO.read(fog_config['fog_aws_private_key_file']).chomp if fog_config['fog_aws_private_key_file']
|
28
|
+
@ec2_access_key_file = IO.read(fog_config['fog_ec2_access_key_file']).chomp if fog_config['fog_ec2_access_key_file']
|
29
|
+
@ec2_secret_access_key_file = IO.read(fog_config['fog_ec2_secret_access_key_file']).chomp if fog_config['fog_ec2_secret_access_key_file']
|
30
|
+
|
31
|
+
# Instance Keys
|
32
|
+
@ec2_instance_public_key_file = IO.read(fog_config['fog_ec2_instance_public_key_file']).chomp if fog_config['fog_ec2_instance_public_key_file']
|
33
|
+
@ec2_instance_private_key_file = IO.read(fog_config['fog_ec2_instance_private_key_file']).chomp if fog_config['fog_ec2_instance_private_key_file']
|
34
|
+
|
35
|
+
# Instance Details
|
36
|
+
@ec2_base_ami = fog_config['fog_ec2_base_ami']
|
37
|
+
@ec2_flavor = fog_config['fog_ec2_flavor']
|
38
|
+
@ec2_user = fog_config['fog_ec2_user']
|
39
|
+
@ec2_region = fog_config['fog_ec2_region']
|
40
|
+
|
41
|
+
# Set up a connection
|
42
|
+
@compute = Fog::Compute.new(
|
43
|
+
:provider => "Aws",
|
44
|
+
:aws_access_key_id => @aws_access_key_file,
|
45
|
+
:aws_secret_access_key => @aws_secret_access_key_file )
|
46
|
+
else
|
47
|
+
raise "Unsupported Fog Type"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def start
|
52
|
+
ec2_settings = {
|
53
|
+
:image_id => @ec2_base_ami,
|
54
|
+
:flavor_id => @ec2_flavor,
|
55
|
+
:public_key_path => @ec2_instance_public_key_file,
|
56
|
+
:private_key_path => @ec2_instance_private_key_file,
|
57
|
+
:username => @ec2_user}
|
58
|
+
|
59
|
+
begin
|
60
|
+
@fog_server = @compute.servers.bootstrap(ec2_settings)
|
61
|
+
rescue Fog::Compute::AWS::Error => e
|
62
|
+
raise "Couldn't authenticate to AWS - did you place keys in the creds/ directory?"
|
63
|
+
exit
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def stop
|
68
|
+
@fog_server.destroy
|
69
|
+
end
|
70
|
+
|
71
|
+
def suspend
|
72
|
+
raise "unimplemented"
|
73
|
+
end
|
74
|
+
|
75
|
+
def pause
|
76
|
+
raise "unimplemented"
|
77
|
+
end
|
78
|
+
|
79
|
+
def reset
|
80
|
+
raise "unimplemented"
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_snapshot(snapshot)
|
84
|
+
raise "unimplemented"
|
85
|
+
end
|
86
|
+
|
87
|
+
def revert_snapshot(snapshot)
|
88
|
+
raise "unimplemented"
|
89
|
+
end
|
90
|
+
|
91
|
+
def delete_snapshot(snapshot)
|
92
|
+
raise "unimplemented"
|
93
|
+
end
|
94
94
|
|
95
95
|
=begin
|
96
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
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
97
|
+
def run_command(command)
|
98
|
+
## vm_driver will need a little patching for this to work, as
|
99
|
+
## amis use keys for auth. i think it's just a matter of not passing the
|
100
|
+
## password to ssh_exec. So maybe the thing to do is have a ssh_key_exec
|
101
|
+
## function in vm_driver.rb that does the right thing.
|
102
|
+
|
103
|
+
script_rand_name = rand(10000)
|
104
|
+
|
105
|
+
if @os == "windows"
|
106
|
+
local_tempfile_path = "/tmp/lab_script_#{script_rand_name}.bat"
|
107
|
+
remote_tempfile_path = "C:\\\\lab_script_#{script_rand_name}.bat"
|
108
|
+
remote_run_command = remote_tempfile_path
|
109
|
+
else
|
110
|
+
local_tempfile_path = "/tmp/lab_script_#{script_rand_name}.sh"
|
111
|
+
remote_tempfile_path = "/tmp/lab_script_#{script_rand_name}.sh"
|
112
|
+
remote_run_command = "/bin/sh #{remote_tempfile_path}"
|
113
|
+
end
|
114
|
+
|
115
|
+
# write out our script locally
|
116
|
+
File.open(local_tempfile_path, 'w') {|f| f.write(command) }
|
117
|
+
|
118
|
+
# since we can't copy easily w/o tools, let's just run it directly :/
|
119
|
+
if @os == "linux"
|
120
|
+
output_file = "/tmp/lab_command_output_#{rand(1000000)}"
|
121
|
+
|
122
|
+
scp_to(local_tempfile_path, remote_tempfile_path)
|
123
|
+
ssh_exec(remote_run_command + "> #{output_file}")
|
124
|
+
scp_from(output_file, output_file)
|
125
|
+
ssh_exec("rm #{output_file}")
|
126
|
+
ssh_exec("rm #{remote_tempfile_path}")
|
127
|
+
|
128
|
+
# Ghettohack!
|
129
|
+
string = File.open(output_file,"r").read
|
130
|
+
`rm #{output_file}`
|
131
|
+
|
132
|
+
else
|
133
|
+
raise "zomgwtfbbqnotools"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def copy_from(from, to)
|
138
|
+
raise "unimplemented"
|
139
|
+
end
|
140
|
+
|
141
|
+
def copy_to(from, to)
|
142
|
+
raise "unimplemented"
|
143
|
+
end
|
144
|
+
|
145
|
+
def check_file_exists(file)
|
146
|
+
raise "unimplemented"
|
147
|
+
end
|
148
|
+
|
149
|
+
def create_directory(directory)
|
150
|
+
raise "unimplemented"
|
151
|
+
end
|
152
152
|
=end
|
153
153
|
|
154
|
-
|
155
|
-
|
156
|
-
|
154
|
+
def cleanup
|
155
|
+
@fog_server.destroy
|
156
|
+
end
|
157
157
|
|
158
|
-
|
159
|
-
|
160
|
-
|
158
|
+
def running?
|
159
|
+
return true #TODO
|
160
|
+
end
|
161
161
|
|
162
162
|
end
|
163
163
|
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'vm_driver'
|
2
|
+
|
3
|
+
##
|
4
|
+
## $Id$
|
5
|
+
##
|
6
|
+
|
7
|
+
# This driver was built against:
|
8
|
+
# VMware ESXi Host Agent 4.1.0 build-348481
|
9
|
+
|
10
|
+
module Lab
|
11
|
+
module Drivers
|
12
|
+
|
13
|
+
class RemoteEsxiDriver < 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
|
+
|
19
|
+
super(config)
|
20
|
+
|
21
|
+
@user = filter_command(config['user'])
|
22
|
+
@host = filter_command(config['host'])
|
23
|
+
@port = config['port']
|
24
|
+
end
|
25
|
+
|
26
|
+
def start
|
27
|
+
remote_system_command("vim-cmd vmsvc/power.on #{@vmid}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def stop
|
31
|
+
remote_system_command("vim-cmd vmsvc/power.off #{@vmid}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def suspend
|
35
|
+
remote_system_command("vim-cmd vmsvc/power.suspend #{@vmid}")
|
36
|
+
end
|
37
|
+
|
38
|
+
def pause
|
39
|
+
remote_system_command("vim-cmd vmsvc/power.suspend #{@vmid}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def resume
|
43
|
+
remote_system_command("vim-cmd vmsvc/power.suspendResume #{@vmid}")
|
44
|
+
end
|
45
|
+
|
46
|
+
def reset
|
47
|
+
remote_system_command("vim-cmd vmsvc/power.reset #{@vmid}")
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_snapshot(snapshot)
|
51
|
+
snapshot = filter_input(snapshot)
|
52
|
+
|
53
|
+
remote_system_command("vim-cmd vmsvc/snapshot.create #{@vmid} #{snapshot} \'lab created snapshot\' 1 true")
|
54
|
+
end
|
55
|
+
|
56
|
+
def revert_snapshot(snapshot)
|
57
|
+
|
58
|
+
snapshots = get_snapshots
|
59
|
+
|
60
|
+
# Look through our snapshot list, choose the right one based on display_name
|
61
|
+
snapshots.each do |snapshot_obj|
|
62
|
+
|
63
|
+
#puts "DEBUG: checking #{snapshot_obj}"
|
64
|
+
|
65
|
+
if snapshot_obj[:display_name].downcase == snapshot.downcase
|
66
|
+
snapshot_identifier = snapshot_obj[:name].join(" ")
|
67
|
+
|
68
|
+
#puts "DEBUG: I would revert to #{snapshot_obj}"
|
69
|
+
remote_system_command("vim-cmd vmsvc/snapshot.revert #{@vmid} 0 #{snapshot_identifier}")
|
70
|
+
return true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# If we got here, the snapshot didn't exist
|
75
|
+
raise "Invalid Snapshot Name"
|
76
|
+
end
|
77
|
+
|
78
|
+
def delete_snapshot(snapshot, remove_children=false)
|
79
|
+
snapshots = get_snapshots
|
80
|
+
|
81
|
+
# Look through our snapshot list, choose the right one based on display_name
|
82
|
+
snapshots.each do |snapshot_obj|
|
83
|
+
|
84
|
+
#puts "DEBUG: checking #{snapshot_obj}"
|
85
|
+
|
86
|
+
if snapshot_obj[:display_name].downcase == snapshot.downcase
|
87
|
+
snapshot_identifier = snapshot_obj[:name].join(" ")
|
88
|
+
remote_system_command("vim-cmd vmsvc/snapshot.remove #{@vmid} #{remove_children} #{snapshot_identifier}")
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# If we got here, the snapshot didn't exist
|
94
|
+
raise "Invalid Snapshot Name"
|
95
|
+
end
|
96
|
+
|
97
|
+
def delete_all_snapshots
|
98
|
+
remote_system_command("vim-cmd vmsvc/snapshot.removeall #{@vmid}")
|
99
|
+
end
|
100
|
+
|
101
|
+
def run_command(command)
|
102
|
+
raise "Not Implemented"
|
103
|
+
end
|
104
|
+
|
105
|
+
def copy_from(from, to)
|
106
|
+
if @os == "linux"
|
107
|
+
scp_from(from, to)
|
108
|
+
else
|
109
|
+
raise "Unimplemented"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def copy_to(from, to)
|
114
|
+
if @os == "linux"
|
115
|
+
scp_to(from, to)
|
116
|
+
else
|
117
|
+
raise "Unimplemented"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def check_file_exists(file)
|
122
|
+
raise "Not Implemented"
|
123
|
+
end
|
124
|
+
|
125
|
+
def create_directory(directory)
|
126
|
+
raise "Not Implemented"
|
127
|
+
end
|
128
|
+
|
129
|
+
def cleanup
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
def running?
|
134
|
+
power_status_string = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.getstate #{@vmid}\"`
|
135
|
+
return true if power_status_string =~ /Powered on/
|
136
|
+
false
|
137
|
+
end
|
138
|
+
|
139
|
+
def get_snapshots
|
140
|
+
# Command take the format:
|
141
|
+
# vmware-vim-cmd vmsvc/snapshot.revert [vmid: int] [snapshotlevel: int] [snapshotindex: int]
|
142
|
+
output = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/snapshot.get #{@vmid}\"`
|
143
|
+
|
144
|
+
# this keeps track of the snapshots, takes the form:
|
145
|
+
#[ {:name => [0,0], :display_name => "String containing the snapshotname},
|
146
|
+
# {:name => [0,1], :display_name => "String containing the snapshotname}, ]
|
147
|
+
# ...
|
148
|
+
snapshots = []
|
149
|
+
|
150
|
+
# Use these to keep track of the parsing...
|
151
|
+
current_tree = -1
|
152
|
+
current_num = 0
|
153
|
+
count = 0
|
154
|
+
|
155
|
+
# Do the parsing & stick the snapshots in the snapshots array
|
156
|
+
output_lines = output.split("\n")
|
157
|
+
output_lines.each do |line|
|
158
|
+
if line.include?("|") # this is a new snapshot
|
159
|
+
if line.include?("ROOT") # it's a root
|
160
|
+
current_num = 0
|
161
|
+
current_tree = current_tree + 1 # new tree
|
162
|
+
snapshots << { :name => [current_num, current_tree], :display_name => output_lines[count+1].split(":").last.strip }
|
163
|
+
else
|
164
|
+
current_num = current_num + 1 # new snapshot in current tree
|
165
|
+
snapshots << { :name => [current_num, current_tree], :display_name => output_lines[count+1].split(":").last.strip }
|
166
|
+
end
|
167
|
+
end
|
168
|
+
count = count+1
|
169
|
+
end
|
170
|
+
|
171
|
+
snapshots
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|