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