Merge "Refactor tempest common"
[functest.git] / functest / opnfv_tests / openstack / vmtp / vmtp.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 VMTP_ is a small python application that will automatically perform ping
12 connectivity, round trip time measurement (latency) and TCP/UDP throughput
13 measurement for the following East/West flows on any OpenStack deployment:
14
15 - VM to VM same network (private fixed IP, flow #1)
16 - VM to VM different network using fixed IP (same as intra-tenant L3 fixed IP,
17   flow #2)
18 - VM to VM different network using floating IP and NAT (same as floating IP
19   inter-tenant L3, flow #3)
20
21 .. _VMTP: http://vmtp.readthedocs.io/en/latest/
22 """
23
24 import json
25 import logging
26 import os
27 import subprocess
28 import tempfile
29 import time
30 import yaml
31
32 from xtesting.core import testcase
33
34 from functest.core import singlevm
35 from functest.utils import env
36
37
38 class Vmtp(singlevm.VmReady1):
39     """Class to run Vmtp_ as an OPNFV Functest testcase
40
41     .. _Vmtp: http://vmtp.readthedocs.io/en/latest/
42     """
43     # pylint: disable=too-many-instance-attributes
44
45     __logger = logging.getLogger(__name__)
46
47     filename = ('/home/opnfv/functest/images/'
48                 'ubuntu-14.04-server-cloudimg-amd64-disk1.img')
49     flavor_ram = 2048
50     flavor_vcpus = 1
51     flavor_disk = 0
52
53     def __init__(self, **kwargs):
54         if "case_name" not in kwargs:
55             kwargs["case_name"] = 'vmtp'
56         super(Vmtp, self).__init__(**kwargs)
57         self.config = "{}/vmtp.conf".format(self.res_dir)
58         (_, self.privkey_filename) = tempfile.mkstemp()
59         (_, self.pubkey_filename) = tempfile.mkstemp()
60
61     def generate_keys(self):
62         """Generate Keys
63
64         Raises: Exception on error
65         """
66         assert self.cloud
67         name = "vmtp_{}".format(self.guid)
68         self.__logger.info("Creating keypair with name: '%s'", name)
69         keypair = self.cloud.create_keypair(name)
70         self.__logger.debug("keypair: %s", keypair)
71         with open(self.privkey_filename, 'w') as key_file:
72             key_file.write(keypair.private_key)
73         with open(self.pubkey_filename, 'w') as key_file:
74             key_file.write(keypair.public_key)
75         self.cloud.delete_keypair(keypair.id)
76
77     def write_config(self):
78         """Write vmtp.conf
79
80         Raises: Exception on error
81         """
82         assert self.cloud
83         if not os.path.exists(self.res_dir):
84             os.makedirs(self.res_dir)
85         cmd = ['vmtp', '-sc']
86         output = subprocess.check_output(cmd)
87         self.__logger.info("%s\n%s", " ".join(cmd), output)
88         with open(self.config, "w+") as conf:
89             vmtp_conf = yaml.load(output)
90             vmtp_conf["private_key_file"] = self.privkey_filename
91             vmtp_conf["public_key_file"] = self.pubkey_filename
92             vmtp_conf["image_name"] = str(self.image.name)
93             vmtp_conf["router_name"] = "pns_router_{}".format(self.guid)
94             vmtp_conf["flavor_type"] = str(self.flavor.name)
95             vmtp_conf["internal_network_name"] = [
96                 "pns-internal-net_{}".format(self.guid),
97                 "pns-internal-net2_{}".format(self.guid)]
98             vmtp_conf["vm_name_client"] = "TestClient_{}".format(self.guid)
99             vmtp_conf["vm_name_server"] = "TestServer_{}".format(self.guid)
100             vmtp_conf["security_group_name"] = "pns-security{}".format(
101                 self.guid)
102             vmtp_conf["dns_nameservers"] = [env.get('NAMESERVER')]
103             conf.write(yaml.dump(vmtp_conf))
104
105     def run_vmtp(self):
106         """Run Vmtp and generate charts
107
108         Raises: Exception on error
109         """
110         assert self.cloud
111         cmd = ['vmtp', '-d', '--json', '{}/vmtp.json'.format(self.res_dir),
112                '-c', self.config]
113         output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
114         self.__logger.info("%s\n%s", " ".join(cmd), output)
115         cmd = ['vmtp_genchart', '-c', '{}/vmtp.html'.format(self.res_dir),
116                '{}/vmtp.json'.format(self.res_dir)]
117         output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
118         self.__logger.info("%s\n%s", " ".join(cmd), output)
119         with open('{}/vmtp.json'.format(self.res_dir), 'r') as res_file:
120             self.details = json.load(res_file)
121
122     def run(self, **kwargs):
123         self.start_time = time.time()
124         status = testcase.TestCase.EX_RUN_ERROR
125         try:
126             assert self.cloud
127             self.image = self.publish_image()
128             self.flavor = self.create_flavor()
129             self.generate_keys()
130             self.write_config()
131             self.run_vmtp()
132             self.result = 100
133             status = testcase.TestCase.EX_OK
134         except subprocess.CalledProcessError as cpe:
135             self.__logger.error(
136                 "Exception when calling %s\n%s", cpe.cmd, cpe.output)
137             self.result = 0
138         except Exception:  # pylint: disable=broad-except
139             self.__logger.exception("Cannot run vmtp")
140             self.result = 0
141         self.stop_time = time.time()
142         return status
143
144     def clean(self):
145         try:
146             assert self.cloud
147             os.remove(self.privkey_filename)
148             os.remove(self.pubkey_filename)
149             self.cloud.delete_image(self.image)
150             self.cloud.delete_network("pns-internal-net_{}".format(self.guid))
151             self.cloud.delete_network("pns-internal-net2_{}".format(self.guid))
152         except Exception:  # pylint: disable=broad-except
153             pass