2e8d816112e88eda75c6db8114c5fbc897927a9c
[functest.git] / testcases / features / sfc / sfc_colorado1.py
1 import os
2 import subprocess
3 import sys
4 import time
5 import argparse
6 import paramiko
7
8 import functest.utils.functest_logger as ft_logger
9 import functest.utils.functest_utils as ft_utils
10 import functest.utils.openstack_utils as os_utils
11
12 parser = argparse.ArgumentParser()
13
14 parser.add_argument("-r", "--report",
15                     help="Create json result file",
16                     action="store_true")
17
18 args = parser.parse_args()
19
20 """ logging configuration """
21 logger = ft_logger.Logger("ODL_SFC").getLogger()
22
23 FUNCTEST_REPO = ft_utils.FUNCTEST_REPO
24
25 HOME = os.environ['HOME'] + "/"
26
27 VM_BOOT_TIMEOUT = 180
28 INSTANCE_NAME = "client"
29 FLAVOR = "custom"
30 IMAGE_NAME = "sf_nsh_colorado"
31 IMAGE_FILENAME = "sf_nsh_colorado.qcow2"
32 IMAGE_FORMAT = "qcow2"
33 IMAGE_PATH = "/home/opnfv/functest/data" + "/" + IMAGE_FILENAME
34
35 # NEUTRON Private Network parameters
36
37 NET_NAME = "example-net"
38 SUBNET_NAME = "example-subnet"
39 SUBNET_CIDR = "11.0.0.0/24"
40 ROUTER_NAME = "example-router"
41
42 SECGROUP_NAME = "example-sg"
43 SECGROUP_DESCR = "Example Security group"
44
45 INSTANCE_NAME_2 = "server"
46
47 # TEST_DB = ft_utils.get_parameter_from_yaml("results.test_db_url")
48
49 PRE_SETUP_SCRIPT = 'sfc_pre_setup.bash'
50 TACKER_SCRIPT = 'sfc_tacker.bash'
51 TEARDOWN_SCRIPT = "sfc_teardown.bash"
52 TACKER_CHANGECLASSI = "sfc_change_classi.bash"
53
54 ssh_options = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
55
56
57 def check_ssh(ip):
58     cmd = "sshpass -p opnfv ssh " + ssh_options + " -q " + ip + " exit"
59     success = subprocess.call(cmd, shell=True) == 0
60     if not success:
61         logger.debug("Wating for SSH connectivity in SF with IP: %s" % ip)
62     return success
63
64
65 def main():
66
67     # Allow any port so that tacker commands reaches the server.
68     # This will be deleted when tacker is included in OPNFV installation
69
70     status = "PASS"
71     failures = 0
72     start_time = time.time()
73     json_results = {}
74
75     contr_cmd = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
76                  " 'fuel node'|grep controller|awk '{print $10}'")
77     logger.info("Executing script to get ip_server: '%s'" % contr_cmd)
78     process = subprocess.Popen(contr_cmd,
79                                shell=True,
80                                stdout=subprocess.PIPE,
81                                stderr=subprocess.PIPE)
82     ip_server = process.stdout.readline().rstrip()
83
84     iptable_cmd1 = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
85                     " ssh " + ip_server + " iptables -P INPUT ACCEPT ")
86     iptable_cmd2 = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
87                     " ssh " + ip_server + " iptables -t nat -P INPUT ACCEPT ")
88     iptable_cmd3 = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
89                     " ssh " + ssh_options + " " + ip_server +
90                     " iptables -A INPUT -m state"
91                     " --state NEW,ESTABLISHED,RELATED -j ACCEPT")
92
93     logger.info("Changing firewall policy in controller: '%s'" % iptable_cmd1)
94     subprocess.call(iptable_cmd1, shell=True, stderr=subprocess.PIPE)
95
96     logger.info("Changing firewall policy in controller: '%s'" % iptable_cmd2)
97     subprocess.call(iptable_cmd2, shell=True, stderr=subprocess.PIPE)
98
99     logger.info("Changing firewall policy in controller: '%s'" % iptable_cmd3)
100     subprocess.call(iptable_cmd2, shell=True, stderr=subprocess.PIPE)
101
102 # Getting the different clients
103
104     nova_client = os_utils.get_nova_client()
105     neutron_client = os_utils.get_neutron_client()
106     glance_client = os_utils.get_glance_client()
107
108 # Download the image
109
110     if not os.path.isfile(IMAGE_PATH):
111         logger.info("Downloading image")
112         ft_utils.download_url(
113             "http://artifacts.opnfv.org/sfc/demo/sf_nsh_colorado.qcow2",
114             "/home/opnfv/functest/data/")
115     else:
116         logger.info("Using old image")
117
118 # Create glance image and the neutron network
119
120     image_id = os_utils.create_glance_image(glance_client,
121                                             IMAGE_NAME,
122                                             IMAGE_PATH,
123                                             disk=IMAGE_FORMAT,
124                                             container="bare",
125                                             public=True)
126
127     network_dic = os_utils.create_network_full(neutron_client,
128                                                NET_NAME,
129                                                SUBNET_NAME,
130                                                ROUTER_NAME,
131                                                SUBNET_CIDR)
132     if not network_dic:
133         logger.error(
134             "There has been a problem when creating the neutron network")
135         sys.exit(-1)
136
137     network_id = network_dic["net_id"]
138
139     sg_id = os_utils.create_security_group_full(neutron_client,
140                                                 SECGROUP_NAME, SECGROUP_DESCR)
141
142     secgroups = os_utils.get_security_groups(neutron_client)
143
144     for sg in secgroups:
145         os_utils.create_secgroup_rule(neutron_client, sg['id'],
146                                       'ingress', 'tcp',
147                                       port_range_min=22,
148                                       port_range_max=22)
149         os_utils.create_secgroup_rule(neutron_client, sg['id'],
150                                       'egress', 'tcp',
151                                       port_range_min=22,
152                                       port_range_max=22)
153         os_utils.create_secgroup_rule(neutron_client, sg['id'],
154                                       'ingress', 'tcp',
155                                       port_range_min=80,
156                                       port_range_max=80)
157         os_utils.create_secgroup_rule(neutron_client, sg['id'],
158                                       'egress', 'tcp',
159                                       port_range_min=80,
160                                       port_range_max=80)
161
162     _, custom_flv_id = os_utils.get_or_create_flavor(
163         'custom', 1500, 10, 1, public=True)
164     if not custom_flv_id:
165         logger.error("Failed to create custom flavor")
166         sys.exit(1)
167
168     iterator = 0
169     while(iterator < 6):
170         # boot INSTANCE
171         logger.info("Creating instance '%s'..." % INSTANCE_NAME)
172         logger.debug(
173             "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
174             "network=%s \n" % (INSTANCE_NAME, FLAVOR, image_id, network_id))
175         instance = os_utils.create_instance_and_wait_for_active(FLAVOR,
176                                                                 image_id,
177                                                                 network_id,
178                                                                 INSTANCE_NAME)
179
180         if instance is None:
181             logger.error("Error while booting instance.")
182             iterator += 1
183             continue
184         # Retrieve IP of INSTANCE
185         instance_ip = instance.networks.get(NET_NAME)[0]
186         logger.debug("Instance '%s' got private ip '%s'." %
187                      (INSTANCE_NAME, instance_ip))
188
189         logger.info("Adding '%s' to security group '%s'..."
190                     % (INSTANCE_NAME, SECGROUP_NAME))
191         os_utils.add_secgroup_to_instance(nova_client, instance.id, sg_id)
192
193         logger.info("Creating floating IP for VM '%s'..." % INSTANCE_NAME)
194         floatip_dic = os_utils.create_floating_ip(neutron_client)
195         floatip_client = floatip_dic['fip_addr']
196         # floatip_id = floatip_dic['fip_id']
197
198         if floatip_client is None:
199             logger.error("Cannot create floating IP.")
200             iterator += 1
201             continue
202         logger.info("Floating IP created: '%s'" % floatip_client)
203
204         logger.info("Associating floating ip: '%s' to VM '%s' "
205                     % (floatip_client, INSTANCE_NAME))
206         if not os_utils.add_floating_ip(nova_client,
207                                         instance.id,
208                                         floatip_client):
209             logger.error("Cannot associate floating IP to VM.")
210             iterator += 1
211             continue
212
213     # STARTING SECOND VM (server) ###
214
215         # boot INTANCE
216         logger.info("Creating instance '%s'..." % INSTANCE_NAME)
217         logger.debug(
218             "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
219             "network=%s \n" % (INSTANCE_NAME_2, FLAVOR, image_id, network_id))
220         instance_2 = os_utils.create_instance_and_wait_for_active(
221             FLAVOR,
222             image_id,
223             network_id,
224             INSTANCE_NAME_2)
225
226         if instance_2 is None:
227             logger.error("Error while booting instance.")
228             iterator += 1
229             continue
230         # Retrieve IP of INSTANCE
231         instance_ip_2 = instance_2.networks.get(NET_NAME)[0]
232         logger.debug("Instance '%s' got private ip '%s'." %
233                      (INSTANCE_NAME_2, instance_ip_2))
234
235         logger.info("Adding '%s' to security group '%s'..."
236                     % (INSTANCE_NAME_2, SECGROUP_NAME))
237         os_utils.add_secgroup_to_instance(nova_client, instance_2.id, sg_id)
238
239         logger.info("Creating floating IP for VM '%s'..." % INSTANCE_NAME_2)
240         floatip_dic = os_utils.create_floating_ip(neutron_client)
241         floatip_server = floatip_dic['fip_addr']
242         # floatip_id = floatip_dic['fip_id']
243
244         if floatip_server is None:
245             logger.error("Cannot create floating IP.")
246             iterator += 1
247             continue
248         logger.info("Floating IP created: '%s'" % floatip_server)
249
250         logger.info("Associating floating ip: '%s' to VM '%s' "
251                     % (floatip_server, INSTANCE_NAME_2))
252
253         if not os_utils.add_floating_ip(nova_client,
254                                         instance_2.id,
255                                         floatip_server):
256             logger.error("Cannot associate floating IP to VM.")
257             iterator += 1
258             continue
259
260         # CREATION OF THE 2 SF ####
261
262         tacker_script = "%s/testcases/features/sfc/%s" % \
263                         (FUNCTEST_REPO, TACKER_SCRIPT)
264         logger.info("Executing tacker script: '%s'" % tacker_script)
265         subprocess.call(tacker_script, shell=True)
266
267         # SSH CALL TO START HTTP SERVER
268         ssh = paramiko.SSHClient()
269         ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
270
271         try:
272             ssh.connect(floatip_server, username="root",
273                         password="opnfv", timeout=2)
274             command = "python -m SimpleHTTPServer 80 > /dev/null 2>&1 &"
275             logger.info("Starting HTTP server")
276             (stdin, stdout, stderr) = ssh.exec_command(command)
277         except:
278             logger.debug("Waiting for %s..." % floatip_server)
279             time.sleep(6)
280             # timeout -= 1
281
282         instances = nova_client.servers.list(search_opts={'all_tenants': 1})
283         ips = []
284         try:
285             for instance in instances:
286                 if "server" not in instance.name:
287                     if "client" not in instance.name:
288                         logger.debug(
289                             "This is the instance name: %s " % instance.name)
290                         floatip_dic = os_utils.create_floating_ip(
291                             neutron_client)
292                         floatip = floatip_dic['fip_addr']
293                         ips.append(floatip)
294                         instance.add_floating_ip(floatip)
295         except:
296             logger.debug("Problems assigning floating IP to SFs")
297
298         # If no IPs were obtained, then we cant continue
299         if not ips:
300             logger.error('Failed to obtain IPs, cant continue, exiting')
301             return
302
303         logger.debug("Floating IPs for SFs: %s..." % ips)
304
305         # Check SSH connectivity to VNFs
306         r = 0
307         retries = 100
308         check = [False, False]
309
310         logger.info("Checking SSH connectivity to the SFs with ips {0}"
311                     .format(str(ips)))
312         while r < retries and not all(check):
313             try:
314                 check = [check_ssh(ips[0]), check_ssh(ips[1])]
315             except Exception:
316                 logger.exception("SSH check failed")
317                 check = [False, False]
318             time.sleep(3)
319             r += 1
320
321         if not all(check):
322             logger.error("Cannot establish SSH connection to the SFs")
323             iterator += 1
324             continue
325
326         logger.info("SSH connectivity to the SFs established")
327
328         # SSH TO START THE VXLAN_TOOL ON SF1
329         logger.info("Configuring the SFs")
330         try:
331             ssh.connect(ips[0], username="root",
332                         password="opnfv", timeout=2)
333             command = ("nohup python vxlan_tool.py -i eth0 "
334                        "-d forward -v off -b 80 > /dev/null 2>&1 &")
335             (stdin, stdout, stderr) = ssh.exec_command(command)
336         except:
337             logger.debug("Waiting for %s..." % ips[0])
338             time.sleep(6)
339             # timeout -= 1
340
341         try:
342             n = 0
343             while 1:
344                 (stdin, stdout, stderr) = ssh.exec_command(
345                     "ps aux | grep \"vxlan_tool.py\" | grep -v grep")
346                 if len(stdout.readlines()) > 0:
347                     logger.debug("HTTP firewall started")
348                     break
349                 else:
350                     n += 1
351                     if (n > 7):
352                         break
353                     logger.debug("HTTP firewall not started")
354                     time.sleep(3)
355         except Exception:
356             logger.exception("vxlan_tool not started in SF1")
357
358         # SSH TO START THE VXLAN_TOOL ON SF2
359         try:
360             ssh.connect(ips[1], username="root",
361                         password="opnfv", timeout=2)
362             command = ("nohup python vxlan_tool.py -i eth0 "
363                        "-d forward -v off -b 22 > /dev/null 2>&1 &")
364             (stdin, stdout, stderr) = ssh.exec_command(command)
365         except:
366             logger.debug("Waiting for %s..." % ips[1])
367             time.sleep(6)
368             # timeout -= 1
369
370         try:
371             n = 0
372             while 1:
373                 (stdin, stdout, stderr) = ssh.exec_command(
374                     "ps aux | grep \"vxlan_tool.py\" | grep -v grep")
375                 if len(stdout.readlines()) > 0:
376                     logger.debug("SSH firewall started")
377                     break
378                 else:
379                     n += 1
380                     if (n > 7):
381                         break
382                     logger.debug("SSH firewall not started")
383                     time.sleep(3)
384         except Exception:
385             logger.exception("vxlan_tool not started in SF2")
386
387         i = 0
388
389         # SSH TO EXECUTE cmd_client
390         logger.info("TEST STARTED")
391         try:
392             ssh.connect(floatip_client, username="root",
393                         password="opnfv", timeout=2)
394             command = "nc -w 5 -zv " + instance_ip_2 + " 22 2>&1"
395             (stdin, stdout, stderr) = ssh.exec_command(command)
396
397             # WRITE THE CORRECT WAY TO DO LOGGING
398             if "timed out" in stdout.readlines()[0]:
399                 logger.info('\033[92m' + "TEST 1 [PASSED] "
400                             "==> SSH BLOCKED" + '\033[0m')
401                 i = i + 1
402                 json_results.update({"Test 1: SSH Blocked": "Passed"})
403             else:
404                 logger.error('\033[91m' + "TEST 1 [FAILED] "
405                              "==> SSH NOT BLOCKED" + '\033[0m')
406                 status = "FAIL"
407                 json_results.update({"Test 1: SSH Blocked": "Failed"})
408                 failures += 1
409         except:
410             logger.debug("Waiting for %s..." % floatip_client)
411             time.sleep(6)
412             # timeout -= 1
413
414         # SSH TO EXECUTE cmd_client
415         try:
416             ssh.connect(floatip_client, username="root",
417                         password="opnfv", timeout=2)
418             command = "nc -w 5 -zv " + instance_ip_2 + " 80 2>&1"
419             (stdin, stdout, stderr) = ssh.exec_command(command)
420
421             if "succeeded" in stdout.readlines()[0]:
422                 logger.info('\033[92m' + "TEST 2 [PASSED] "
423                             "==> HTTP WORKS" + '\033[0m')
424                 i = i + 1
425                 json_results.update({"Test 2: HTTP works": "Passed"})
426             else:
427                 logger.error('\033[91m' + "TEST 2 [FAILED] "
428                              "==> HTTP BLOCKED" + '\033[0m')
429                 status = "FAIL"
430                 json_results.update({"Test 2: HTTP works": "Failed"})
431                 failures += 1
432         except:
433             logger.debug("Waiting for %s..." % floatip_client)
434             time.sleep(6)
435             # timeout -= 1
436
437         # CHANGE OF CLASSIFICATION #
438         logger.info("Changing the classification")
439         tacker_classi = "%s/testcases/features/sfc/%s" % \
440                         (FUNCTEST_REPO, TACKER_CHANGECLASSI)
441         subprocess.call(tacker_classi, shell=True)
442
443         logger.info("Wait for ODL to update the classification rules in OVS")
444         time.sleep(100)
445
446         # SSH TO EXECUTE cmd_client
447
448         try:
449             ssh.connect(floatip_client, username="root",
450                         password="opnfv", timeout=2)
451             command = "nc -w 5 -zv " + instance_ip_2 + " 80 2>&1"
452             (stdin, stdout, stderr) = ssh.exec_command(command)
453
454             if "timed out" in stdout.readlines()[0]:
455                 logger.info('\033[92m' + "TEST 3 [PASSED] "
456                             "==> HTTP BLOCKED" + '\033[0m')
457                 i = i + 1
458                 json_results.update({"Test 3: HTTP Blocked": "Passed"})
459             else:
460                 logger.error('\033[91m' + "TEST 3 [FAILED] "
461                              "==> HTTP NOT BLOCKED" + '\033[0m')
462                 status = "FAIL"
463                 json_results.update({"Test 3: HTTP Blocked": "Failed"})
464                 failures += 1
465         except:
466             logger.debug("Waiting for %s..." % floatip_client)
467             time.sleep(6)
468             # timeout -= 1
469
470         # SSH TO EXECUTE cmd_client
471         try:
472             ssh.connect(floatip_client, username="root",
473                         password="opnfv", timeout=2)
474             command = "nc -w 5 -zv " + instance_ip_2 + " 22 2>&1"
475             (stdin, stdout, stderr) = ssh.exec_command(command)
476
477             if "succeeded" in stdout.readlines()[0]:
478                 logger.info('\033[92m' + "TEST 4 [PASSED] "
479                             "==> SSH WORKS" + '\033[0m')
480                 i = i + 1
481                 json_results.update({"Test 4: SSH works": "Passed"})
482             else:
483                 logger.error('\033[91m' + "TEST 4 [FAILED] "
484                              "==> SSH BLOCKED" + '\033[0m')
485                 status = "FAIL"
486                 json_results.update({"Test 4: SSH works": "Failed"})
487                 failures += 1
488         except:
489             logger.debug("Waiting for %s..." % floatip_client)
490             time.sleep(6)
491             # timeout -= 1
492
493         iterator += 1
494         if i == 4:
495             for x in range(0, 5):
496                 logger.info('\033[92m' + "SFC TEST WORKED"
497                             " :) \n" + '\033[0m')
498             break
499         else:
500             logger.debug("Iterating again!")
501             delete = ("bash delete.sh")
502             subprocess.call(delete, shell=True, stderr=subprocess.PIPE)
503             time.sleep(10)
504
505     if args.report:
506         stop_time = time.time()
507         json_results.update({"tests": "4", "failures": int(failures)})
508         logger.debug("Promise Results json: " + str(json_results))
509         ft_utils.push_results_to_db("sfc",
510                                     "functest-odl-sfc",
511                                     start_time,
512                                     stop_time,
513                                     status,
514                                     json_results)
515     if status == "PASS":
516         sys.exit(0)
517     else:
518         sys.exit(1)
519
520 if __name__ == '__main__':
521     main()