Allow HV-VES tests to be run locally
[integration/csit.git] / tests / dcaegen2-collectors-hv-ves / testcases / libraries / XnfSimulatorLibrary.py
1 # ============LICENSE_START=======================================================
2 # csit-dcaegen2-collectors-hv-ves
3 # ================================================================================
4 # Copyright (C) 2018-2019 NOKIA
5 # ================================================================================
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #      http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 # ============LICENSE_END=========================================================
18
19 import HttpRequests
20 import os
21 import docker
22 from robot.api import logger
23 from time import sleep
24
25 HV_VES_VERSION = os.getenv("HV_VES_VERSION")
26 HV_VES_COLLECTOR_NETWORK = os.getenv("CONTAINERS_NETWORK")
27 HV_VES_COLLECTOR_NAMESPACE = os.getenv("HV_VES_COLLECTOR_NAMESPACE")
28 HV_VES_GROUP_ID = os.getenv("HV_VES_GROUP_ID")
29 HV_VES_SERVICE_NAME = os.getenv("HV_VES_SERVICE_NAME")
30 UNENCRYPTED_HV_VES_SERVICE_NAME = os.getenv("UNENCRYPTED_HV_VES_SERVICE_NAME")
31
32 XNF_SIMULATOR_NAME = "xNF Simulator"
33 XNF_SIMULATOR_CONTAINER_PREFIX = os.getenv("XNF_SIMULATOR_IMAGE")
34 SIMULATOR_IMAGE_NAME = HV_VES_COLLECTOR_NAMESPACE + "/" + HV_VES_GROUP_ID + ".hv-collector-xnf-simulator"
35
36 SIMULATOR_IMAGE_FULL_NAME = os.getenv("DOCKER_REGISTRY_PREFIX") + SIMULATOR_IMAGE_NAME + ":" + HV_VES_VERSION
37 WORKSPACE_ENV = os.getenv("WORKSPACE")
38 CERTIFICATES_DIR_PATH = WORKSPACE_ENV + "/plans/dcaegen2-collectors-hv-ves/testsuites/collector/ssl/"
39 COLLECTOR_CERTS_LOOKUP_DIR = "/etc/ves-hv/"
40 ONE_SECOND_IN_NANOS = 10 ** 9
41
42
43 class XnfSimulatorLibrary:
44
45     def start_xnf_simulators(self, list_of_ports,
46                              should_use_valid_certs=True,
47                              should_disable_ssl=False,
48                              should_connect_to_unencrypted_hv_ves=False):
49         logger.info("Creating " + str(len(list_of_ports)) + " xNF Simulator containers")
50         dockerClient = docker.from_env()
51
52         self.pullImageIfAbsent(dockerClient)
53         logger.info("Using image: " + SIMULATOR_IMAGE_FULL_NAME)
54
55         simulators_addresses = self.create_containers(dockerClient,
56                                                       list_of_ports,
57                                                       should_use_valid_certs,
58                                                       should_disable_ssl,
59                                                       should_connect_to_unencrypted_hv_ves)
60
61         self.assert_containers_startup_was_successful(dockerClient)
62         dockerClient.close()
63         return simulators_addresses
64
65     def pullImageIfAbsent(self, dockerClient):
66         try:
67             dockerClient.images.get(SIMULATOR_IMAGE_FULL_NAME)
68         except:
69             logger.console("Image " + SIMULATOR_IMAGE_FULL_NAME + " will be pulled from repository. "
70                                                                   "This can take a while.")
71             dockerClient.images.pull(SIMULATOR_IMAGE_FULL_NAME)
72
73     def create_containers(self,
74                           dockerClient,
75                           list_of_ports,
76                           should_use_valid_certs,
77                           should_disable_ssl,
78                           should_connect_to_unencrypted_hv_ves):
79         simulators_addresses = []
80         for port in list_of_ports:
81             xnf = XnfSimulator(port, should_use_valid_certs, should_disable_ssl, should_connect_to_unencrypted_hv_ves)
82             container = self.run_simulator(dockerClient, xnf)
83             logger.info("Started container: " + container.name + "  " + container.id)
84             simulators_addresses.append(container.name + ":" + xnf.port)
85         return simulators_addresses
86
87     def run_simulator(self, dockerClient, xnf):
88         xNF_startup_command = xnf.get_startup_command()
89         xNF_healthcheck_command = xnf.get_healthcheck_command()
90         port = xnf.port
91         logger.info("Startup command: " + str(xNF_startup_command))
92         logger.info("Healthcheck command: " + str(xNF_healthcheck_command))
93         return dockerClient.containers.run(SIMULATOR_IMAGE_FULL_NAME,
94                                            command=xNF_startup_command,
95                                            healthcheck=xNF_healthcheck_command,
96                                            detach=True,
97                                            network=HV_VES_COLLECTOR_NETWORK,
98                                            ports={port + "/tcp": port},
99                                            volumes=self.container_volumes(),
100                                            name=XNF_SIMULATOR_CONTAINER_PREFIX + port)
101
102     def container_volumes(self):
103         return {CERTIFICATES_DIR_PATH: {"bind": COLLECTOR_CERTS_LOOKUP_DIR, "mode": 'rw'}}
104
105     def assert_containers_startup_was_successful(self, dockerClient):
106         checks_amount = 6
107         check_interval_in_seconds = 5
108         for _ in range(checks_amount):
109             sleep(check_interval_in_seconds)
110             all_containers_healthy = True
111             for container in self.get_simulators_list(dockerClient):
112                 all_containers_healthy = all_containers_healthy and self.is_container_healthy(container)
113             if (all_containers_healthy):
114                 return
115         raise ContainerException("One of xNF simulators containers did not pass the healthcheck.")
116
117     def is_container_healthy(self, container):
118         container_health = container.attrs['State']['Health']['Status']
119         return container_health == 'healthy' and container.status == 'running'
120
121     def stop_and_remove_all_xnf_simulators(self, suite_name):
122         dockerClient = docker.from_env()
123         for container in self.get_simulators_list(dockerClient):
124             logger.info("Stopping and removing container: " + container.id)
125             log_filename = WORKSPACE_ENV + "/archives/containers_logs/" + \
126                            suite_name.split(".")[-1] + "_" + container.name + ".log"
127             file = open(log_filename, "w+")
128             file.write(str(container.logs()))
129             file.close()
130             container.stop()
131             container.remove()
132         dockerClient.close()
133
134     def get_simulators_list(self, dockerClient):
135         return dockerClient.containers.list(filters={"ancestor": SIMULATOR_IMAGE_FULL_NAME}, all=True)
136
137     def send_messages(self, simulator_url, message_filepath):
138         logger.info("Reading message to simulator from: " + message_filepath)
139
140         file = open(message_filepath, "rb")
141         data = file.read()
142         file.close()
143
144         logger.info("POST at: " + simulator_url)
145         resp = HttpRequests.session_without_env().post(simulator_url, data=data, timeout=5)
146         HttpRequests.checkStatusCode(resp.status_code, XNF_SIMULATOR_NAME)
147
148
149 class XnfSimulator:
150
151     def __init__(self,
152                  port,
153                  should_use_valid_certs,
154                  should_disable_ssl,
155                  should_connect_to_unencrypted_hv_ves):
156         self.port = port
157         self.healthcheck_server_port = "6063"
158         cert_name_prefix = "" if should_use_valid_certs else "untrusted"
159         certificates_path_with_file_prefix = COLLECTOR_CERTS_LOOKUP_DIR + cert_name_prefix
160         self.key_store_path = certificates_path_with_file_prefix + "client.p12"
161         self.trust_store_path = certificates_path_with_file_prefix + "trust.p12"
162         self.sec_store_passwd = "onaponap"
163         self.disable_ssl = should_disable_ssl
164         self.hv_collector_host = UNENCRYPTED_HV_VES_SERVICE_NAME \
165             if should_connect_to_unencrypted_hv_ves else HV_VES_SERVICE_NAME
166
167     def get_startup_command(self):
168         startup_command = ["--listen-port", self.port,
169                            "--health-check-api-port", self.healthcheck_server_port,
170                            "--ves-host", self.hv_collector_host,
171                            "--ves-port", "6061",
172                            "--key-store", self.key_store_path,
173                            "--trust-store", self.trust_store_path,
174                            "--key-store-password", self.sec_store_passwd,
175                            "--trust-store-password", self.sec_store_passwd]
176         if self.disable_ssl:
177             startup_command.append("--ssl-disable")
178         return startup_command
179
180     def get_healthcheck_command(self):
181         return {
182             "interval": 5 * ONE_SECOND_IN_NANOS,
183             "timeout": 3 * ONE_SECOND_IN_NANOS,
184             "retries": 1,
185             "test": ["CMD", "curl", "--request", "GET",
186                      "--fail", "--silent", "--show-error",
187                      "localhost:" + self.healthcheck_server_port + "/health/ready"]
188         }
189
190
191 class ContainerException(Exception):
192     def __init__(self, message):
193         super(ContainerException, self).__init__(message)