root/honeyclient/branches/exp/jpuchalski-esx/t/honeyclient_manager_vm_clone.t

Revision 1582, 17.9 kB (checked in by kindlund, 8 months ago)

Added work_unit_limit logic; where cloned VMs will get recycled after visiting X number of URLs. This resolves the issue where our driving application may have a slow memory leak; where after X URLs the OS memory is completely filled, rendering the VM unusable. Instead, we preemptively destroy the VM and create a new one before we hit X. Initially, we'll let X = 2000 and go from there.

Line 
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Test::More 'no_plan';
5 $| = 1;
6
7
8
9 # =begin testing
10 {
11 # Make sure ExtUtils::MakeMaker loads.
12 BEGIN { use_ok('ExtUtils::MakeMaker', qw(prompt)) or diag("Can't load ExtUtils::MakeMaker package.  Check to make sure the package library is correctly listed within the path."); }
13 require_ok('ExtUtils::MakeMaker');
14 can_ok('ExtUtils::MakeMaker', 'prompt');
15 use ExtUtils::MakeMaker qw(prompt);
16
17 # Make sure Log::Log4perl loads
18 BEGIN { use_ok('Log::Log4perl', qw(:nowarn))
19         or diag("Can't load Log::Log4perl package. Check to make sure the package library is correctly listed within the path.");
20        
21         # Suppress all logging messages, since we need clean output for unit testing.
22         Log::Log4perl->init({
23             "log4perl.rootLogger"                               => "DEBUG, Buffer",
24             "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer",
25             "log4perl.appender.Buffer.min_level"                => "fatal",
26             "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout",
27             "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n",
28         });
29 }
30 require_ok('Log::Log4perl');
31 use Log::Log4perl qw(:easy);
32
33 # Make sure HoneyClient::Util::Config loads.
34 BEGIN { use_ok('HoneyClient::Util::Config', qw(getVar))
35         or diag("Can't load HoneyClient::Util::Config package.  Check to make sure the package library is correctly listed within the path.");
36
37         # Suppress all logging messages, since we need clean output for unit testing.
38         Log::Log4perl->init({
39             "log4perl.rootLogger"                               => "DEBUG, Buffer",
40             "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer",
41             "log4perl.appender.Buffer.min_level"                => "fatal",
42             "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout",
43             "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n",
44         });
45        
46 }
47 require_ok('HoneyClient::Util::Config');
48 can_ok('HoneyClient::Util::Config', 'getVar');
49 use HoneyClient::Util::Config qw(getVar);
50
51 # Make sure HoneyClient::Util::SOAP loads.
52 BEGIN { use_ok('HoneyClient::Util::SOAP', qw(getClientHandle)) or diag("Can't load HoneyClient::Util::SOAP package.  Check to make sure the package library is correctly listed within the path."); }
53 require_ok('HoneyClient::Util::SOAP');
54 can_ok('HoneyClient::Util::SOAP', 'getClientHandle');
55 use HoneyClient::Util::SOAP qw(getClientHandle);
56
57 # Make sure HoneyClient::Manager::VM loads.
58 BEGIN { use_ok('HoneyClient::Manager::VM') or diag("Can't load HoneyClient::Manager::VM package.  Check to make sure the package library is correctly listed within the path."); }
59 require_ok('HoneyClient::Manager::VM');
60 use HoneyClient::Manager::VM;
61
62 # Make sure HoneyClient::Manager::Database loads.
63 BEGIN { use_ok('HoneyClient::Manager::Database') or diag("Can't load HoneyClient::Manager::Database package.  Check to make sure the package library is correctly listed within the path."); }
64 require_ok('HoneyClient::Manager::Database');
65 use HoneyClient::Manager::Database;
66
67 # Make sure VMware::VmPerl loads.
68 BEGIN { use_ok('VMware::VmPerl', qw(VM_EXECUTION_STATE_ON VM_EXECUTION_STATE_OFF VM_EXECUTION_STATE_STUCK VM_EXECUTION_STATE_SUSPENDED)) or diag("Can't load VMware::VmPerl package.  Check to make sure the package library is correctly listed within the path."); }
69 require_ok('VMware::VmPerl');
70 use VMware::VmPerl qw(VM_EXECUTION_STATE_ON VM_EXECUTION_STATE_OFF VM_EXECUTION_STATE_STUCK VM_EXECUTION_STATE_SUSPENDED);
71
72 # Make sure the module loads properly, with the exportable
73 # functions shared.
74 BEGIN { use_ok('HoneyClient::Manager::VM::Clone') or diag("Can't load HoneyClient::Manager::VM::Clone package.  Check to make sure the package library is correctly listed within the path."); }
75 require_ok('HoneyClient::Manager::VM::Clone');
76 use HoneyClient::Manager::VM::Clone;
77
78 # Suppress all logging messages, since we need clean output for unit testing.
79 Log::Log4perl->init({
80     "log4perl.rootLogger"                               => "DEBUG, Buffer",
81     "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer",
82     "log4perl.appender.Buffer.min_level"                => "fatal",
83     "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout",
84     "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n",
85 });
86
87 # Make sure Storable loads.
88 BEGIN { use_ok('Storable', qw(dclone thaw)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); }
89 require_ok('Storable');
90 can_ok('Storable', 'dclone');
91 can_ok('Storable', 'thaw');
92 use Storable qw(dclone thaw);
93
94 # Make sure MIME::Base64 loads.
95 BEGIN { use_ok('MIME::Base64', qw(encode_base64 decode_base64)) or diag("Can't load MIME::Base64 package.  Check to make sure the package library is correctly listed within the path."); }
96 require_ok('MIME::Base64');
97 can_ok('MIME::Base64', 'encode_base64');
98 can_ok('MIME::Base64', 'decode_base64');
99 use MIME::Base64 qw(encode_base64 decode_base64);
100
101 # Make sure Data::Dumper loads
102 BEGIN { use_ok('Data::Dumper')
103         or diag("Can't load Data::Dumper package. Check to make sure the package library is correctly listed within the path."); }
104 require_ok('Data::Dumper');
105 use Data::Dumper;
106
107 # Make sure threads loads.
108 BEGIN { use_ok('threads') or diag("Can't load threads package.  Check to make sure the package library is correctly listed within the path."); }
109 require_ok('threads');
110 use threads;
111
112 # Make sure threads::shared loads.
113 BEGIN { use_ok('threads::shared') or diag("Can't load threads::shared package.  Check to make sure the package library is correctly listed within the path."); }
114 require_ok('threads::shared');
115 use threads::shared;
116
117 # Make sure Thread::Semaphore loads.
118 BEGIN { use_ok('Thread::Semaphore') or diag("Can't load Thread::Semaphore package.  Check to make sure the package library is correctly listed within the path."); }
119 require_ok('Thread::Semaphore');
120 use Thread::Semaphore;
121
122 # Make sure File::Basename loads.
123 BEGIN { use_ok('File::Basename', qw(dirname basename)) or diag("Can't load File::Basename package.  Check to make sure the package library is correctly listed within the path."); }
124 require_ok('File::Basename');
125 can_ok('File::Basename', 'dirname');
126 can_ok('File::Basename', 'basename');
127 use File::Basename qw(dirname basename);
128
129 # Make sure Sys::Hostname loads.
130 BEGIN { use_ok('Sys::Hostname') or diag("Can't load Sys::Hostname package.  Check to make sure the package library is correctly listed within the path."); }
131 require_ok('Sys::Hostname');
132 use Sys::Hostname;
133
134 # Make sure Sys::HostIP loads.
135 BEGIN { use_ok('Sys::HostIP') or diag("Can't load Sys::HostIP package.  Check to make sure the package library is correctly listed within the path."); }
136 require_ok('Sys::HostIP');
137 use Sys::HostIP;
138
139 # Make sure DateTime::HiRes loads.
140 BEGIN { use_ok('DateTime::HiRes') or diag("Can't load Sys::HostIP package.  Check to make sure the package library is correctly listed within the path."); }
141 require_ok('DateTime::HiRes');
142 use DateTime::HiRes;
143
144 # Make sure IO::File loads.
145 BEGIN { use_ok('IO::File') or diag("Can't load IO::File package.  Check to make sure the package library is correctly listed within the path."); }
146 require_ok('IO::File');
147 use IO::File;
148
149 # Make sure Filesys::DfPortable loads
150 BEGIN { use_ok('Filesys::DfPortable')
151         or diag("Can't load Filesys::DfPortable package. Check to make sure the package library is correctly listed within the path."); }
152 require_ok('Filesys::DfPortable');
153 use Filesys::DfPortable;
154 }
155
156
157
158 # =begin testing
159 {
160 # Shared test variables.
161 my ($stub, $som, $URL);
162 my $testVM = $ENV{PWD} . "/" . getVar(name      => "test_vm_config",
163                                       namespace => "HoneyClient::Manager::VM::Test");
164
165 # Include notice, to clarify our assumptions.
166 diag("About to run basic unit tests; these may take some time.");
167 diag("Note: These tests *expect* VMware Server or VMware GSX to be installed and running on this system beforehand.");
168
169 # Catch all errors, in order to make sure child processes are
170 # properly killed.
171 eval {
172
173     $URL = HoneyClient::Manager::VM->init();
174
175     # Connect to daemon as a client.
176     $stub = getClientHandle(namespace => "HoneyClient::Manager::VM");
177
178     # In order to test setMasterVM(), we're going to fully clone
179     # the testVM, then set the newly created clone as a master VM.
180
181     # Get the test VM's parent directory,
182     # in order to create a temporary master VM.
183     my $testVMDir = dirname($testVM);
184     my $masterVMDir = dirname($testVMDir) . "/test_vm_master";
185     my $masterVM = $masterVMDir . "/" . basename($testVM);
186
187     # Create the master VM.
188     $som = $stub->fullCloneVM(src_config => $testVM, dest_dir => $masterVMDir);
189
190     # Wait a small amount of time for the asynchronous clone
191     # to complete.
192     sleep (10);
193
194     # The master VM should be on.
195     $som = $stub->getStateVM(config => $masterVM);
196    
197     # Since the master VM doesn't have an OS installed on it,
198     # the VM may be considered stuck.  Go ahead and answer
199     # this question, if need be.
200     if ($som->result == VM_EXECUTION_STATE_STUCK) {
201         $som = $stub->answerVM(config => $masterVM);
202     }
203
204     # Turn off the master VM.
205     $som = $stub->stopVM(config => $masterVM);
206
207     # Now, kill the VM daemon.
208     HoneyClient::Manager::VM->destroy();
209
210     # Create a generic empty clone, with test state data.
211     my $clone = HoneyClient::Manager::VM::Clone->new(test => 1, master_vm_config => $masterVM, _dont_init => 1, _bypass_firewall => 1);
212     is($clone->{test}, 1, "new(test => 1, master_vm_config => '$masterVM', _dont_init => 1, _bypass_firewall => 1)") or diag("The new() call failed.");
213     isa_ok($clone, 'HoneyClient::Manager::VM::Clone', "new(test => 1, master_vm_config => '$masterVM', _dont_init => 1, _bypass_firewall => 1)") or diag("The new() call failed.");
214     $clone = undef;
215
216     # Destroy the master VM.
217     $som = $stub->destroyVM(config => $masterVM);
218
219     my $question;
220     $question = prompt("#\n" .
221                        "# Note: Testing real clone operations will *ONLY* work\n" .
222                        "# with a fully functional master VM that has the HoneyClient code\n" .
223                        "# loaded upon boot-up.\n" .
224                        "#\n" .
225                        "# This test also requires that the firewall VM is registered,\n" .
226                        "# powered on, and operational.\n" .
227                        "#\n" .
228                        "# Your master VM is: " . getVar(name => "master_vm_config", namespace => "HoneyClient::Manager::VM") . "\n" .
229                        "#\n" .
230                        "# Do you want to test cloning this master VM?", "no");
231     if ($question =~ /^y.*/i) {
232         $clone = HoneyClient::Manager::VM::Clone->new(test => 1);
233         is($clone->{test}, 1, "new(test => 1)") or diag("The new() call failed.");
234         isa_ok($clone, 'HoneyClient::Manager::VM::Clone', "new(test => 1)") or diag("The new() call failed.");
235         my $cloneConfig = $clone->{config};
236         $clone = undef;
237    
238         # Destroy the clone VM.
239         $som = $stub->destroyVM(config => $cloneConfig);
240     }
241 };
242
243 # Kill the child daemon, if it still exists.
244 HoneyClient::Manager::VM->destroy();
245
246 # Report any failure found.
247 if ($@) {
248     fail($@);
249 }
250 }
251
252
253
254 # =begin testing
255 {
256 # Shared test variables.
257 my ($stub, $som, $URL);
258 my $testVM = $ENV{PWD} . "/" . getVar(name      => "test_vm_config",
259                                       namespace => "HoneyClient::Manager::VM::Test");
260
261 # Catch all errors, in order to make sure child processes are
262 # properly killed.
263 eval {
264
265     my $testVMDir = dirname($testVM);
266
267     # Specify where the snapshot should be created.
268     my $snapshot = dirname($testVMDir) . "/test_vm_clone.tar.gz";
269
270     # Pretend as though no other Clone objects have been created prior
271     # to this point.
272     $HoneyClient::Manager::VM::Clone::OBJECT_COUNT = -1;
273    
274     my $question;
275     $question = prompt("#\n" .
276                        "# Note: Testing real suspend/archive operations will *ONLY* work\n" .
277                        "# with a fully functional master VM that has the HoneyClient code\n" .
278                        "# loaded upon boot-up.\n" .
279                        "#\n" .
280                        "# This test also requires that the firewall VM is registered,\n" .
281                        "# powered on, and operational.\n" .
282                        "#\n" .
283                        "# Your master VM is: " . getVar(name => "master_vm_config", namespace => "HoneyClient::Manager::VM") . "\n" .
284                        "#\n" .
285                        "# Do you want to test cloning this master VM and archiving a subsequent clone?", "no");
286     if ($question =~ /^y.*/i) {
287
288         # Create a generic empty clone, with test state data.
289         my $clone = HoneyClient::Manager::VM::Clone->new(_bypass_firewall => 1);
290         my $cloneConfig = $clone->{config};
291
292         # Archive the clone.
293         $clone->suspend(perform_archive => 1, snapshot_file => $snapshot);
294
295         # Wait for the suspend/archive to complete.
296         sleep (45);
297    
298         # Test if the operations worked.
299         is(-f $snapshot, 1, "suspend(perform_archive => 1, snapshot_file => '$snapshot')") or diag("The suspend() call failed.");
300    
301         unlink $snapshot;
302         $clone = undef;
303    
304         # Connect to daemon as a client.
305         $stub = getClientHandle(namespace => "HoneyClient::Manager::VM");
306    
307         # Destroy the clone VM.
308         $som = $stub->destroyVM(config => $cloneConfig);
309     }
310 };
311
312 # Kill the child daemon, if it still exists.
313 HoneyClient::Manager::VM->destroy();
314
315 # Report any failure found.
316 if ($@) {
317     fail($@);
318 }
319 }
320
321
322
323 # =begin testing
324 {
325 # Shared test variables.
326 my ($stub, $som, $URL);
327 my $testVM = $ENV{PWD} . "/" . getVar(name      => "test_vm_config",
328                                       namespace => "HoneyClient::Manager::VM::Test");
329
330 # Catch all errors, in order to make sure child processes are
331 # properly killed.
332 eval {
333
334     my $testVMDir = dirname($testVM);
335
336     # Pretend as though no other Clone objects have been created prior
337     # to this point.
338     $HoneyClient::Manager::VM::Clone::OBJECT_COUNT = -1;
339    
340     my $question;
341     $question = prompt("#\n" .
342                        "# Note: Testing real destroy operations will *ONLY* work\n" .
343                        "# with a fully functional master VM that has the HoneyClient code\n" .
344                        "# loaded upon boot-up.\n" .
345                        "#\n" .
346                        "# This test also requires that the firewall VM is registered,\n" .
347                        "# powered on, and operational.\n" .
348                        "#\n" .
349                        "# Your master VM is: " . getVar(name => "master_vm_config", namespace => "HoneyClient::Manager::VM") . "\n" .
350                        "#\n" .
351                        "# Do you want to test cloning this master VM and destroying a subsequent clone?", "no");
352     if ($question =~ /^y.*/i) {
353
354         # Create a generic empty clone, with test state data.
355         my $clone = HoneyClient::Manager::VM::Clone->new(_bypass_firewall => 1);
356         my $cloneConfig = $clone->{config};
357
358         # Archive the clone.
359         $clone->destroy();
360
361         # Wait for the destroy to complete.
362         sleep (45);
363    
364         # Test if the operations worked.
365         is(!-f $cloneConfig, 1, "destroy()") or diag("The destroy() call failed.");
366    
367         $clone = undef;
368
369         if (-f $cloneConfig) {
370             # Connect to daemon as a client.
371             $stub = getClientHandle(namespace => "HoneyClient::Manager::VM");
372    
373             # Destroy the clone VM.
374             $som = $stub->destroyVM(config => $cloneConfig);
375         }
376     }
377 };
378
379 # Kill the child daemon, if it still exists.
380 HoneyClient::Manager::VM->destroy();
381
382 # Report any failure found.
383 if ($@) {
384     fail($@);
385 }
386 }
387
388
389
390 # =begin testing
391 {
392 # Shared test variables.
393 my ($stub, $som, $URL);
394 my $testVM = $ENV{PWD} . "/" . getVar(name      => "test_vm_config",
395                                       namespace => "HoneyClient::Manager::VM::Test");
396
397 # Catch all errors, in order to make sure child processes are
398 # properly killed.
399 eval {
400
401     # Pretend as though no other Clone objects have been created prior
402     # to this point.
403     $HoneyClient::Manager::VM::Clone::OBJECT_COUNT = -1;
404    
405     my $question;
406     $question = prompt("#\n" .
407                        "# Note: Testing real drive operations will *ONLY* work\n" .
408                        "# with a fully functional master VM that has the HoneyClient code\n" .
409                        "# loaded upon boot-up.\n" .
410                        "#\n" .
411                        "# This test also requires that the firewall VM is registered,\n" .
412                        "# powered on, and operational.\n" .
413                        "#\n" .
414                        "# Your master VM is: " . getVar(name => "master_vm_config", namespace => "HoneyClient::Manager::VM") . "\n" .
415                        "#\n" .
416                        "# Do you want to test cloning and driving this master VM?", "no");
417     if ($question =~ /^y.*/i) {
418
419         # Create a generic empty clone, with test state data.
420         my $clone = HoneyClient::Manager::VM::Clone->new(_bypass_firewall => 1);
421         my $cloneConfig = $clone->{config};
422
423         $clone = $clone->drive(work => { 'http://www.google.com/' => 1 });
424         isa_ok($clone, 'HoneyClient::Manager::VM::Clone', "drive(work => { 'http://www.google.com/' => 1})") or diag("The drive() call failed.");
425         $clone = undef;
426
427         # Connect to daemon as a client.
428         $stub = getClientHandle(namespace => "HoneyClient::Manager::VM");
429    
430         # Destroy the clone VM.
431         $som = $stub->destroyVM(config => $cloneConfig);
432     }
433 };
434
435 # Kill the child daemon, if it still exists.
436 HoneyClient::Manager::VM->destroy();
437
438 # Report any failure found.
439 if ($@) {
440     fail($@);
441 }
442 }
443
444
445
446
447 1;
Note: See TracBrowser for help on using the browser.