Update linters and fix all new issues
[functest.git] / functest / opnfv_tests / openstack / shaker / shaker.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2018 Orange and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 """
11 Shaker_ wraps around popular system network testing tools like iperf, iperf3
12 and netperf (with help of flent). Shaker is able to deploy OpenStack instances
13 and networks in different topologies. Shaker scenario specifies the deployment
14 and list of tests to execute.
15
16 .. _Shaker: http://pyshaker.readthedocs.io/en/latest/
17 """
18
19 import logging
20 import os
21
22 import json
23 import scp
24
25 from functest.core import singlevm
26 from functest.utils import env
27
28
29 class Shaker(singlevm.SingleVm2):
30     """Run shaker full+perf l2 and l3"""
31     # pylint: disable=too-many-instance-attributes
32
33     __logger = logging.getLogger(__name__)
34
35     filename = '/home/opnfv/functest/images/shaker-image-1.3.4+stretch.qcow2'
36     flavor_ram = 512
37     flavor_vcpus = 1
38     flavor_disk = 3
39     username = 'debian'
40     port = 9000
41     ssh_connect_loops = 12
42     create_server_timeout = 300
43     check_console_loop = 12
44     shaker_timeout = '3600'
45     quota_instances = -1
46     quota_cores = -1
47     check_console_loop = 12
48
49     def __init__(self, **kwargs):
50         super().__init__(**kwargs)
51         self.role = None
52
53     def check_requirements(self):
54         if self.count_hypervisors() < 2:
55             self.__logger.warning("Shaker requires at least 2 hypervisors")
56             self.is_skipped = True
57             self.project.clean()
58
59     def prepare(self):
60         super().prepare()
61         self.cloud.create_security_group_rule(
62             self.sec.id, port_range_min=self.port, port_range_max=self.port,
63             protocol='tcp', direction='ingress')
64
65     def execute(self):
66         """
67         Returns:
68             - 0 if success
69             - 1 on operation error
70         """
71         assert self.ssh
72         endpoint = self.get_public_auth_url(self.orig_cloud)
73         self.__logger.debug("keystone endpoint: %s", endpoint)
74         if self.orig_cloud.get_role("admin"):
75             role_name = "admin"
76         elif self.orig_cloud.get_role("Admin"):
77             role_name = "Admin"
78         else:
79             raise Exception("Cannot detect neither admin nor Admin")
80         self.orig_cloud.grant_role(
81             role_name, user=self.project.user.id,
82             project=self.project.project.id,
83             domain=self.project.domain.id)
84         if not self.orig_cloud.get_role("heat_stack_owner"):
85             self.role = self.orig_cloud.create_role("heat_stack_owner")
86         self.orig_cloud.grant_role(
87             "heat_stack_owner", user=self.project.user.id,
88             project=self.project.project.id,
89             domain=self.project.domain.id)
90         self.orig_cloud.set_compute_quotas(
91             self.project.project.name,
92             instances=self.quota_instances,
93             cores=self.quota_cores)
94         scpc = scp.SCPClient(self.ssh.get_transport())
95         scpc.put('/home/opnfv/functest/conf/env_file', remote_path='~/')
96         if os.environ.get('OS_CACERT'):
97             scpc.put(os.environ.get('OS_CACERT'), remote_path='~/os_cacert')
98         opt = 'export OS_CACERT=~/os_cacert && ' if os.environ.get(
99             'OS_CACERT') else ''
100         (_, stdout, stderr) = self.ssh.exec_command(
101             'source ~/env_file && '
102             'export OS_INTERFACE=public && '
103             f'export OS_AUTH_URL={endpoint} && '
104             f'export OS_USERNAME={self.project.user.name} && '
105             f'export OS_PROJECT_NAME={self.project.project.name} && '
106             f'export OS_PROJECT_ID={self.project.project.id} && '
107             'unset OS_TENANT_NAME && '
108             'unset OS_TENANT_ID && '
109             'unset OS_ENDPOINT_TYPE && '
110             f'export OS_PASSWORD="{self.project.password}" && '
111             f'{opt}'
112             'env && '
113             f'timeout {self.shaker_timeout} shaker --debug '
114             f'--image-name {self.image.name} --flavor-name {self.flavor.name} '
115             f'--server-endpoint {self.fip.floating_ip_address}:9000 '
116             f'--external-net {self.ext_net.id} '
117             f"--dns-nameservers {env.get('NAMESERVER')} "
118             '--scenario openstack/full_l2,'
119             'openstack/full_l3_east_west,'
120             'openstack/full_l3_north_south,'
121             'openstack/perf_l3_north_south '
122             '--report report.html --output report.json')
123         self.__logger.info("output:\n%s", stdout.read().decode("utf-8"))
124         self.__logger.info("error:\n%s", stderr.read().decode("utf-8"))
125         if not os.path.exists(self.res_dir):
126             os.makedirs(self.res_dir)
127         try:
128             scpc.get('report.json', self.res_dir)
129             scpc.get('report.html', self.res_dir)
130         except scp.SCPException:
131             self.__logger.exception("cannot get report files")
132             return 1
133         with open(
134                 os.path.join(self.res_dir, 'report.json'),
135                 encoding='utf-8') as json_file:
136             data = json.load(json_file)
137             for value in data["records"].values():
138                 if value["status"] != "ok":
139                     self.__logger.error(
140                         "%s failed\n%s", value["scenario"], value["stderr"])
141                     return 1
142         return stdout.channel.recv_exit_status()
143
144     def clean(self):
145         super().clean()
146         if self.role:
147             self.orig_cloud.delete_role(self.role.id)