lab 0.2.2 → 0.2.3

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 (42) hide show
  1. data/config/test_lab.yml +61 -0
  2. data/lab.gemspec +4 -1
  3. data/lib/lab/controller/vsphere_controller.rb +2 -46
  4. data/lib/lab/driver/vsphere_driver.rb +2 -2
  5. data/lib/lab/version.rb +1 -1
  6. data/lib/lab/vm_controller.rb +15 -4
  7. data/util/console.rb +10 -0
  8. metadata +21 -43
  9. data/src/Gemfile +0 -4
  10. data/src/Rakefile +0 -1
  11. data/src/TODO +0 -15
  12. data/src/config/test_lab.yml +0 -11
  13. data/src/config/test_targets.yml +0 -21
  14. data/src/lab.gemspec +0 -35
  15. data/src/lib/lab/controller/dynagen_controller.rb +0 -14
  16. data/src/lib/lab/controller/fog_controller.rb +0 -6
  17. data/src/lib/lab/controller/remote_esxi_controller.rb +0 -62
  18. data/src/lib/lab/controller/remote_workstation_controller.rb +0 -22
  19. data/src/lib/lab/controller/virtualbox_controller.rb +0 -25
  20. data/src/lib/lab/controller/vsphere_controller.rb +0 -18
  21. data/src/lib/lab/controller/workstation_controller.rb +0 -17
  22. data/src/lib/lab/controller/workstation_vixr_controller.rb +0 -19
  23. data/src/lib/lab/controllers.rb +0 -9
  24. data/src/lib/lab/driver/dynagen_driver.rb +0 -47
  25. data/src/lib/lab/driver/fog_driver.rb +0 -104
  26. data/src/lib/lab/driver/remote_esxi_driver.rb +0 -177
  27. data/src/lib/lab/driver/remote_workstation_driver.rb +0 -197
  28. data/src/lib/lab/driver/virtualbox_driver.rb +0 -142
  29. data/src/lib/lab/driver/vm_driver.rb +0 -195
  30. data/src/lib/lab/driver/vsphere_driver.rb +0 -120
  31. data/src/lib/lab/driver/workstation_driver.rb +0 -234
  32. data/src/lib/lab/driver/workstation_vixr_driver.rb +0 -126
  33. data/src/lib/lab/drivers.rb +0 -9
  34. data/src/lib/lab/modifier/backtrack5_modifier.rb +0 -16
  35. data/src/lib/lab/modifier/dos_modifier.rb +0 -14
  36. data/src/lib/lab/modifier/test_modifier.rb +0 -16
  37. data/src/lib/lab/modifiers.rb +0 -3
  38. data/src/lib/lab/version.rb +0 -3
  39. data/src/lib/lab/vm.rb +0 -269
  40. data/src/lib/lab/vm_controller.rb +0 -275
  41. data/src/lib/lab.rb +0 -2
  42. data/src/test/.gitkeep +0 -0
@@ -1,195 +0,0 @@
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
@@ -1,120 +0,0 @@
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
@@ -1,234 +0,0 @@
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
@@ -1,126 +0,0 @@
1
- require 'vm_driver'
2
- ##
3
- ## $Id$
4
- ##
5
-
6
- # This requires rhythmx's vixr driver from https://github.com/rhythmx/vixr
7
- # and below that, the VIX api from vmware http://www.vmware.com/support/developer/vix-api/
8
-
9
- module Lab
10
- module Drivers
11
-
12
- class WorkstationVixrDriver < VmDriver
13
-
14
- attr_accessor :type
15
- attr_accessor :location
16
-
17
- def initialize(vmid, location, os=nil, tools=false, credentials=nil)
18
-
19
- # We have to treat this differently, as it's not in the same tree
20
- begin
21
- require 'vixr'
22
- rescue LoadError
23
- puts "WARNING: Library pro_vixr not found. To resolve this error, please\n" +
24
- " install the vixr gem. Latest is available here:\n" +
25
- "https://github.com/rhythmx/vixr ."
26
- raise "Unable to create vixr driver"
27
- end
28
-
29
- @vmid = filter_command(vmid)
30
- @location = filter_command(location)
31
-
32
- if !File.exist?(@location)
33
- raise ArgumentError,"Couldn't find: " + location
34
- end
35
-
36
- @credentials = credentials
37
- @tools = tools # not used in command lines, no filter
38
- @os = os # not used in command lines, no filter
39
-
40
- # TODO - Currently only implemented for the first set
41
- if @credentials.count > 0
42
- @vm_user = filter_input(@credentials[0]['user']) || "\'\'"
43
- @vm_pass = filter_input(@credentials[0]['pass']) || "\'\'"
44
- end
45
-
46
- host = VixR.connect()
47
- vm = host.open_vmx(@location)
48
-
49
- end
50
-
51
- def start
52
- vm.power_on
53
- end
54
-
55
- def stop
56
- vm.power_off
57
- end
58
-
59
- def suspend
60
- vm.suspend
61
- end
62
-
63
- def pause
64
- vm.pause
65
- end
66
-
67
- def reset
68
- vm.reset
69
- end
70
-
71
- def create_snapshot(snapshot)
72
- snapshot = filter_input(snapshot)
73
- system_command("ssh #{@user}@#{@host} vmrun -T ws snapshot \\\'#{@location}\\\' #{snapshot} nogui")
74
- end
75
-
76
- def revert_snapshot(snapshot)
77
- snapshot = filter_input(snapshot)
78
- system_command("ssh #{@user}@#{@host} vmrun -T ws revertToSnapshot \\\'#{@location}\\\' #{snapshot} nogui")
79
- end
80
-
81
- def delete_snapshot(snapshot)
82
- snapshot = filter_input(snapshot)
83
- system_command("ssh #{@user}@#{@host} vmrun -T ws deleteSnapshot \\\'#{@location}\\\' #{snapshot} nogui" )
84
- end
85
-
86
-
87
- def run_command(command)
88
- command = filter_input(command)
89
- if vm.login(@vm_user,@vm_pass)
90
- vm.run_prog(command)
91
- end
92
- end
93
-
94
- def copy_from(from, to)
95
- from = filter_input(from)
96
- to = filter_input(to)
97
- cp_from_host(from,to)
98
- end
99
-
100
- def copy_to(from, to)
101
- from = filter_input(from)
102
- to = filter_input(to)
103
- vm.cp_to_guest(from,to)
104
- end
105
-
106
- def check_file_exists(file)
107
- file = filter_input(file)
108
- file_exists?(file)
109
- end
110
-
111
- def create_directory(directory)
112
- directory = filter_input(directory)
113
- end
114
-
115
- def cleanup
116
-
117
- end
118
-
119
- def running?
120
- vm.running?
121
- end
122
-
123
- end
124
-
125
- end
126
- end
@@ -1,9 +0,0 @@
1
- require 'driver/workstation_driver'
2
- require 'driver/virtualbox_driver'
3
- require 'driver/fog_driver'
4
- require 'driver/dynagen_driver'
5
- require 'driver/remote_workstation_driver'
6
- require 'driver/remote_esxi_driver'
7
- require 'driver/vsphere_driver'
8
- #require 'driver/qemu_driver'
9
- #require 'driver/qemudo_driver'
@@ -1,16 +0,0 @@
1
- module Lab
2
- module Modifier
3
- module Backtrack5
4
-
5
- def nmap(options)
6
- run_command("nmap #{filter_input(options)}")
7
- end
8
-
9
- def testssl(site)
10
- run_command("/pentest/scanners/testssl/testssl.sh #{filter_input(site)}")
11
- end
12
-
13
- end
14
- end
15
- end
16
-
@@ -1,14 +0,0 @@
1
- # This assumes you're on a recent ubuntu
2
- # TODO - enforce this, or split it out...
3
-
4
- module Lab
5
- module Modifier
6
- module Dos
7
-
8
- def ping(target)
9
- run_command("ping #{filter_input(target)}")
10
- end
11
-
12
- end
13
- end
14
- end