2727 Network ,
2828 ServiceOffering ,
2929 NetworkOffering ,
30- VirtualMachine )
30+ VirtualMachine ,
31+ FireWallRule ,
32+ NATRule ,
33+ PublicIPAddress )
3134from marvin .integration .lib .common import (get_domain ,
3235 get_zone ,
3336 get_template ,
34- list_hosts ,
3537 list_routers ,
3638 wait_for_cleanup ,
3739 list_virtual_machines
4143from marvin .cloudstackAPI .createEgressFirewallRule import createEgressFirewallRuleCmd
4244from marvin .cloudstackAPI .deleteEgressFirewallRule import deleteEgressFirewallRuleCmd
4345from marvin .codes import PASS
44- from marvin .sshClient import SshClient
4546import time
4647
4748class Services :
@@ -117,6 +118,11 @@ def __init__(self):
117118 "name" : "Test Network" ,
118119 "displaytext" : "Test Network" ,
119120 },
121+ "natrule" : {
122+ "privateport" : 22 ,
123+ "publicport" : 22 ,
124+ "protocol" : "TCP"
125+ },
120126 "sleep" : 30 ,
121127 "ostype" : 'CentOS 5.3 (64-bit)' ,
122128 "host_password" : 'password' ,
@@ -166,6 +172,8 @@ def tearDownClass(cls):
166172 def setUp (self ):
167173 self .apiclient = self .api_client
168174 self .dbclient = self .testClient .getDbConnection ()
175+ self .cleanup_vms = []
176+ self .cleanup_networks = []
169177 self .cleanup = []
170178 self .snapshot = None
171179 self .egressruleid = None
@@ -202,11 +210,11 @@ def create_vm(self, pfrule=False, egress_policy=True, RR=False):
202210 domainid = self .account .domainid ,
203211 networkofferingid = self .network_offering .id ,
204212 zoneid = self .zone .id )
213+ self .cleanup_networks .append (self .network )
205214 self .debug ("Created network with ID: %s" % self .network .id )
206215 self .debug ("Deploying instance in the account: %s" % self .account .name )
207216
208217 project = None
209- self .virtual_machine = None
210218 try :
211219 self .virtual_machine = VirtualMachine .create (self .apiclient ,
212220 self .services ["virtual_machine" ],
@@ -216,8 +224,8 @@ def create_vm(self, pfrule=False, egress_policy=True, RR=False):
216224 mode = self .zone .networktype if pfrule else 'basic' ,
217225 networkids = [str (self .network .id )],
218226 projectid = project .id if project else None )
227+ self .cleanup_vms .append (self .virtual_machine )
219228 except Exception as e :
220- self .virtual_machine = None
221229 self .fail ("Virtual machine deployment failed with exception: %s" % e )
222230 self .debug ("Deployed instance %s in account: %s" % (self .virtual_machine .id ,self .account .name ))
223231
@@ -226,95 +234,48 @@ def create_vm(self, pfrule=False, egress_policy=True, RR=False):
226234
227235 self .assertEqual (validateList (self .vm_list )[0 ], PASS , "vm list validation failed, vm list is %s" % self .vm_list )
228236 self .assertEqual (str (self .vm_list [0 ].state ).lower (),'running' ,"VM state should be running, it is %s" % self .vm_list [0 ].state )
237+
238+ self .public_ip = PublicIPAddress .create (
239+ self .apiclient ,
240+ accountid = self .account .name ,
241+ zoneid = self .zone .id ,
242+ domainid = self .account .domainid ,
243+ networkid = self .network .id
244+ )
245+
246+ # Open up firewall port for SSH
247+ FireWallRule .create (
248+ self .apiclient ,
249+ ipaddressid = self .public_ip .ipaddress .id ,
250+ protocol = self .services ["natrule" ]["protocol" ],
251+ cidrlist = ['0.0.0.0/0' ],
252+ startport = self .services ["natrule" ]["publicport" ],
253+ endport = self .services ["natrule" ]["publicport" ]
254+ )
255+
256+ self .debug ("Creating NAT rule for VM ID: %s" % self .virtual_machine .id )
257+ #Create NAT rule
258+ NATRule .create (
259+ self .apiclient ,
260+ self .virtual_machine ,
261+ self .services ["natrule" ],
262+ self .public_ip .ipaddress .id
263+ )
229264 return
230265
231266 def exec_script_on_user_vm (self , script , exec_cmd_params , expected_result , negative_test = False ):
232267 try :
233-
234- vm_network_id = self .virtual_machine .nic [0 ].networkid
235- vm_ipaddress = self .virtual_machine .nic [0 ].ipaddress
236- list_routers_response = list_routers (self .apiclient ,
237- account = self .account .name ,
238- domainid = self .account .domainid ,
239- networkid = vm_network_id )
240- self .assertEqual (isinstance (list_routers_response , list ),
241- True ,
242- "Check for list routers response return valid data" )
243- router = list_routers_response [0 ]
244-
245- #Once host or mgt server is reached, SSH to the router connected to VM
246- # look for Router for Cloudstack VM network.
247- if self .apiclient .hypervisor .lower () == 'vmware' :
248- #SSH is done via management server for Vmware
249- sourceip = self .apiclient .connection .mgtSvr
250- else :
251- #For others, we will have to get the ipaddress of host connected to vm
252- hosts = list_hosts (self .apiclient ,
253- id = router .hostid )
254- self .assertEqual (isinstance (hosts , list ),
255- True ,
256- "Check list response returns a valid list" )
257- host = hosts [0 ]
258- sourceip = host .ipaddress
259-
260- self .debug ("Sleep %s seconds for network on router to be up"
261- % self .services ['sleep' ])
262- time .sleep (self .services ['sleep' ])
263-
264- if self .apiclient .hypervisor .lower () == 'vmware' :
265- key_file = " -i /var/cloudstack/management/.ssh/id_rsa "
266- else :
267- key_file = " -i /root/.ssh/id_rsa.cloud "
268-
269- ssh_cmd = "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet"
270- expect_script = "#!/usr/bin/expect\n " + \
271- "spawn %s %s -p 3922 root@%s\n " % (ssh_cmd , key_file , router .linklocalip ) + \
272- "expect \" root@%s:~#\" \n " % (router .name ) + \
273- "send \" %s root@%s %s; exit $?\r \" \n " % (ssh_cmd , vm_ipaddress , script ) + \
274- "expect \" root@%s's password: \" \n " % (vm_ipaddress ) + \
275- "send \" password\r \" \n " + \
276- "interact\n "
277- self .debug ("expect_script>>\n %s<<expect_script" % expect_script )
278-
279- script_file = '/tmp/expect_script.exp'
280- fd = open (script_file ,'w' )
281- fd .write (expect_script )
282- fd .close ()
283-
284- ssh = SshClient (host = sourceip ,
285- port = 22 ,
286- user = 'root' ,
287- passwd = self .services ["host_password" ])
288- self .debug ("SSH client to : %s obtained" % sourceip )
289- ssh .scp (script_file , script_file )
290- ssh .execute ('chmod +x %s' % script_file )
291- self .debug ("%s %s" % (script_file , exec_cmd_params ))
292-
293268 exec_success = False
294- #Timeout set to 12 minutes
295- timeout = 720
296- while timeout :
297- self .debug ('sleep %s seconds for egress rule to affect on Router.' % self .services ['sleep' ])
298- time .sleep (self .services ['sleep' ])
299- result = ssh .execute ("%s %s" % (script_file , exec_cmd_params ))
300- self .debug ('Result is=%s' % result )
301- self .debug ('Expected result is=%s' % expected_result )
302-
303- if str (result ).strip () == expected_result :
304- exec_success = True
305- break
306- else :
307- # This means router network did not come up as yet loop back.
308- if ((result == []) or ("send" in result [0 ])):
309- timeout -= self .services ['sleep' ]
310- else : # Failed due to some other error
311- break
312- #end while
313269
314- if timeout == 0 :
315- self .fail ("Router network failed to come up after 12 minutes." )
270+ self .debug ("getting SSH client for Vm: %s with ip %s" % (self .virtual_machine .id ,self .public_ip .ipaddress .ipaddress ))
271+ sshClient = self .virtual_machine .get_ssh_client (ipaddress = self .public_ip .ipaddress .ipaddress )
272+ result = sshClient .execute (script + exec_cmd_params )
273+
274+ self .debug ("script: %s" % script + exec_cmd_params )
275+ self .debug ("result: %s" % result )
316276
317- ssh .execute ('rm -rf %s' % script_file )
277+ if str (result ).strip () == expected_result :
278+ exec_success = True
318279
319280 if negative_test :
320281 self .assertEqual (exec_success ,
@@ -382,17 +343,40 @@ def tearDown(self):
382343 if self .egressruleid :
383344 self .debug ('remove egress rule id=%s' % self .egressruleid )
384345 self .deleteEgressRule ()
346+
385347 self .debug ("Cleaning up the resources" )
386348
387- if self .virtual_machine is not None :
388- if str (self .vm_list [0 ].state ).lower () == "running" :
389- self .virtual_machine .delete (self .apiclient )
390- # When vm is deployed in error state, it is automatically expunged
391- wait_for_cleanup (self .apiclient , ["expunge.interval" , "expunge.delay" ])
349+ #below components is not a part of cleanup because to mandate the order and to cleanup network
350+ try :
351+ for vm in self .cleanup_vms :
352+ if str (vm .state ).lower () != "error" :
353+ vm .delete (self .api_client )
354+ except Exception as e :
355+ self .fail ("Warning: Exception during virtual machines cleanup : %s" % e )
356+
357+ # Wait for VMs to expunge
358+ wait_for_cleanup (self .api_client , ["expunge.delay" , "expunge.interval" ])
359+
360+ if len (self .cleanup_vms ) > 0 :
361+ retriesCount = 10
362+ while True :
363+ vms = list_virtual_machines (self .api_client , id = self .virtual_machine .id )
364+ if vms is None :
365+ break
366+ elif retriesCount == 0 :
367+ self .fail ("Failed to expunge vm even after 10 minutes" )
368+ time .sleep (60 )
369+ retriesCount -= 1
370+
371+ try :
372+ for network in self .cleanup_networks :
373+ network .delete (self .api_client )
374+ except Exception as e :
375+ self .fail ("Warning: Exception during networks cleanup : %s" % e )
392376
393- self .network .delete (self .apiclient )
394377 self .debug ("Sleep for Network cleanup to complete." )
395378 wait_for_cleanup (self .apiclient , ["network.gc.wait" , "network.gc.interval" ])
379+
396380 cleanup_resources (self .apiclient , reversed (self .cleanup ))
397381 self .debug ("Cleanup complete!" )
398382 except Exception as e :
@@ -479,7 +463,7 @@ def test_03_egress_fr3(self):
479463 negative_test = False )
480464 self .createEgressRule ()
481465 #Egress rule is set for ICMP other traffic is allowed
482- self .exec_script_on_user_vm (' wget -t1 http://apache.claz.org/favicon.ico' ,
466+ self .exec_script_on_user_vm (' wget -t1 http://apache.claz.org/favicon.ico 2>&1 ' ,
483467 "| grep -oP 'failed:'" ,
484468 "[]" ,
485469 negative_test = False )
@@ -500,7 +484,7 @@ def test_03_1_egress_fr3(self):
500484 negative_test = False )
501485 self .createEgressRule ()
502486 #Egress rule is set for ICMP other traffic is not allowed
503- self .exec_script_on_user_vm (' wget -t1 http://apache.claz.org/favicon.ico' ,
487+ self .exec_script_on_user_vm (' wget -t1 http://apache.claz.org/favicon.ico 2>&1 ' ,
504488 "| grep -oP 'failed:'" ,
505489 "['failed:']" ,
506490 negative_test = False )
@@ -659,7 +643,7 @@ def test_07_egress_fr7(self):
659643 # 4. access to public network should not be successfull.
660644 self .create_vm ()
661645 self .createEgressRule (protocol = 'tcp' , start_port = 80 )
662- self .exec_script_on_user_vm (' wget -t1 http://apache.claz.org/favicon.ico' ,
646+ self .exec_script_on_user_vm (' wget -t1 http://apache.claz.org/favicon.ico 2>&1 ' ,
663647 "| grep -oP 'failed:'" ,
664648 "['failed:']" ,
665649 negative_test = False )
@@ -675,7 +659,7 @@ def test_07_1_egress_fr7(self):
675659 # 4. access to public network for tcp port 80 is blocked.
676660 self .create_vm ()
677661 self .createEgressRule (protocol = 'tcp' , start_port = 80 )
678- self .exec_script_on_user_vm (' wget -t1 http://apache.claz.org/favicon.ico' ,
662+ self .exec_script_on_user_vm (' wget -t1 http://apache.claz.org/favicon.ico 2>&1 ' ,
679663 "| grep -oP 'failed:'" ,
680664 "['failed:']" ,
681665 negative_test = False )
@@ -797,7 +781,6 @@ def test_11_1_egress_fr11(self):
797781 # 3. All should work fine.
798782 self .create_vm (pfrule = True , egress_policy = False )
799783
800-
801784 @attr (tags = ["advanced" ])
802785 def test_12_egress_fr12 (self ):
803786 """Test Reboot Router
0 commit comments