blob: 4d2784d0c630677a9486a4f3a78a4100af9a608a [file] [log] [blame]
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -07001#!/usr/bin/env python3
2import logging
Bartek Grzybowskif2b14832020-05-25 00:47:35 -07003from subprocess import run, CalledProcessError
Bartek Grzybowskic85faa42020-05-11 05:38:08 -07004import argparse
5import ipaddress
Bartek Grzybowskib61465f2020-05-14 05:52:40 -07006from sys import exit
Bartek Grzybowski9ab2f402020-06-12 12:20:48 +02007from os import chdir, getcwd, path, popen, kill, getuid, stat, mkdir, getlogin
Bartek Grzybowski138b1992020-06-08 14:25:44 +02008from shutil import copytree, rmtree, move
Bartek Grzybowski626f2862020-06-04 09:55:26 +02009from json import loads, dumps
Bartek Grzybowski700b6072020-06-09 12:41:08 +020010from yaml import load, SafeLoader, dump
Bartek Grzybowskia71704c2020-05-19 04:47:09 -070011from glob import glob
Bartek Grzybowski1fbf8542020-06-10 15:16:23 +020012from time import strftime, tzname, daylight
Bartek Grzybowski110badf2020-06-01 12:31:42 +020013from docker import from_env
Bartek Grzybowski626f2862020-06-04 09:55:26 +020014from requests import get, codes, post
Bartek Grzybowskic85faa42020-05-11 05:38:08 -070015from requests.exceptions import MissingSchema, InvalidSchema, InvalidURL, ConnectionError, ConnectTimeout
16
17def validate_url(url):
18 '''Helper function to perform --urlves input param validation'''
19 logger = logging.getLogger("urllib3")
20 logger.setLevel(logging.WARNING)
21 try:
22 get(url, timeout=0.001)
23 except (MissingSchema, InvalidSchema, InvalidURL):
24 raise argparse.ArgumentTypeError(f'{url} is not a valid URL')
25 except (ConnectionError, ConnectTimeout):
26 pass
27 return url
28
29def validate_ip(ip):
30 '''Helper function to validate input param is a vaild IP address'''
31 try:
32 ip_valid = ipaddress.ip_address(ip)
33 except ValueError:
34 raise argparse.ArgumentTypeError(f'{ip} is not a valid IP address')
35 else:
36 return ip_valid
37
38def get_parser():
39 '''Process input arguments'''
40
41 parser = argparse.ArgumentParser()
42 subparsers = parser.add_subparsers(title='Subcommands', dest='subcommand')
Bartek Grzybowskid2038202020-05-15 00:57:25 -070043 # Build command parser
44 subparsers.add_parser('build', help='Build simulator image')
Bartek Grzybowskic85faa42020-05-11 05:38:08 -070045 # Bootstrap command parser
46 parser_bootstrap = subparsers.add_parser('bootstrap', help='Bootstrap the system')
47 parser_bootstrap.add_argument('--count', help='Instance count to bootstrap', type=int, metavar='INT', default=1)
48 parser_bootstrap.add_argument('--urlves', help='URL of the VES collector', type=validate_url, metavar='URL', required=True)
49 parser_bootstrap.add_argument('--ipfileserver', help='Visible IP of the file server (SFTP/FTPS) to be included in the VES event',
50 type=validate_ip, metavar='IP', required=True)
51 parser_bootstrap.add_argument('--typefileserver', help='Type of the file server (SFTP/FTPS) to be included in the VES event',
52 type=str, choices=['sftp', 'ftps'], required=True)
53 parser_bootstrap.add_argument('--ipstart', help='IP address range beginning', type=validate_ip, metavar='IP', required=True)
54 # Start command parser
55 parser_start = subparsers.add_parser('start', help='Start instances')
Bartek Grzybowski5717b5e2020-05-19 04:50:51 -070056 parser_start.add_argument('--count', help='Instance count to start', type=int, metavar='INT', default=0)
Bartek Grzybowskic85faa42020-05-11 05:38:08 -070057 # Stop command parser
58 parser_stop = subparsers.add_parser('stop', help='Stop instances')
Bartek Grzybowski5717b5e2020-05-19 04:50:51 -070059 parser_stop.add_argument('--count', help='Instance count to stop', type=int, metavar='INT', default=0)
Bartek Grzybowskic85faa42020-05-11 05:38:08 -070060 # Trigger command parser
61 parser_trigger = subparsers.add_parser('trigger', help='Trigger one single VES event from each simulator')
Bartek Grzybowski5717b5e2020-05-19 04:50:51 -070062 parser_trigger.add_argument('--count', help='Instance count to trigger', type=int, metavar='INT', default=0)
Bartek Grzybowskia3737ae2020-06-05 15:07:56 +020063 # Stop-simulator command parser
64 parser_stopsimulator = subparsers.add_parser('stop_simulator', help='Stop sending PNF registration messages')
65 parser_stopsimulator.add_argument('--count', help='Instance count to stop', type=int, metavar='INT', default=0)
Bartek Grzybowskic85faa42020-05-11 05:38:08 -070066 # Trigger-custom command parser
Bartek Grzybowski950cbad2020-05-11 06:00:00 -070067 parser_triggerstart = subparsers.add_parser('trigger_custom', help='Trigger one single VES event from specific simulators')
Bartek Grzybowskic85faa42020-05-11 05:38:08 -070068 parser_triggerstart.add_argument('--triggerstart', help='First simulator id to trigger', type=int,
69 metavar='INT', required=True)
70 parser_triggerstart.add_argument('--triggerend', help='Last simulator id to trigger', type=int,
71 metavar='INT', required=True)
72 # Status command parser
73 parser_status = subparsers.add_parser('status', help='Status')
Bartek Grzybowski5717b5e2020-05-19 04:50:51 -070074 parser_status.add_argument('--count', help='Instance count to show status for', type=int, metavar='INT', default=0)
Bartek Grzybowskic85faa42020-05-11 05:38:08 -070075 # Clean command parser
76 subparsers.add_parser('clean', help='Clean work-dirs')
77 # General options parser
78 parser.add_argument('--verbose', help='Verbosity level', choices=['info', 'debug'],
Bartek Grzybowskib61465f2020-05-14 05:52:40 -070079 type=str, default='info')
Bartek Grzybowskic85faa42020-05-11 05:38:08 -070080 return parser
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -070081
Bartek Grzybowskia89abf82020-05-18 07:30:11 -070082class MassPnfSim:
Bartek Grzybowskibb8249e2020-05-18 04:11:15 -070083
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -070084 log_lvl = logging.INFO
Bartek Grzybowski1fbf8542020-06-10 15:16:23 +020085 sim_compose_template = 'docker-compose-template.yml'
Bartek Grzybowski9ab2f402020-06-12 12:20:48 +020086 sim_vsftpd_template = 'config/vsftpd_ssl-TEMPLATE.conf'
87 sim_vsftpd_config = 'config/vsftpd_ssl.conf'
Bartek Grzybowski07b7d002020-05-28 07:40:02 -070088 sim_config = 'config/config.yml'
Bartek Grzybowski626f2862020-06-04 09:55:26 +020089 sim_msg_config = 'config/config.json'
Bartek Grzybowski572f6442020-06-01 12:38:49 +020090 sim_port = 5000
91 sim_base_url = 'http://{}:' + str(sim_port) + '/simulator'
Bartek Grzybowski626f2862020-06-04 09:55:26 +020092 sim_start_url = sim_base_url + '/start'
93 sim_status_url = sim_base_url + '/status'
Bartek Grzybowskia3737ae2020-06-05 15:07:56 +020094 sim_stop_url = sim_base_url + '/stop'
Bartek Grzybowski572f6442020-06-01 12:38:49 +020095 sim_container_name = 'pnf-simulator'
Bartek Grzybowskic17ed782020-06-03 11:46:51 +020096 rop_script_name = 'ROP_file_creator.sh'
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -070097
98 def __init__(self, args):
99 self.args = args
100 self.logger = logging.getLogger(__name__)
101 self.logger.setLevel(self.log_lvl)
Bartek Grzybowskib61465f2020-05-14 05:52:40 -0700102 self.sim_dirname_pattern = "pnf-sim-lw-"
Bartek Grzybowski54227002020-05-15 07:38:04 -0700103 self.mvn_build_cmd = 'mvn clean package docker:build -Dcheckstyle.skip'
Bartek Grzybowski572f6442020-06-01 12:38:49 +0200104 self.docker_compose_status_cmd = 'docker-compose ps'
Bartek Grzybowskia71704c2020-05-19 04:47:09 -0700105 self.existing_sim_instances = self._enum_sim_instances()
Bartek Grzybowskib61465f2020-05-14 05:52:40 -0700106
Bartek Grzybowski5717b5e2020-05-19 04:50:51 -0700107 # Validate 'trigger_custom' subcommand options
108 if self.args.subcommand == 'trigger_custom':
109 if (self.args.triggerend + 1) > self.existing_sim_instances:
110 self.logger.error('--triggerend value greater than existing instance count.')
111 exit(1)
112
113 # Validate --count option for subcommands that support it
Bartek Grzybowskia3737ae2020-06-05 15:07:56 +0200114 if self.args.subcommand in ['start', 'stop', 'trigger', 'status', 'stop_simulator']:
Bartek Grzybowski5717b5e2020-05-19 04:50:51 -0700115 if self.args.count > self.existing_sim_instances:
116 self.logger.error('--count value greater that existing instance count')
117 exit(1)
118 if not self.existing_sim_instances:
119 self.logger.error('No bootstrapped instance found')
120 exit(1)
121
122 # Validate 'bootstrap' subcommand
123 if (self.args.subcommand == 'bootstrap') and self.existing_sim_instances:
124 self.logger.error('Bootstrapped instances detected, not overwiriting, clean first')
125 exit(1)
126
Bartek Grzybowskib61465f2020-05-14 05:52:40 -0700127 def _run_cmd(self, cmd, dir_context='.'):
Bartek Grzybowskib61465f2020-05-14 05:52:40 -0700128 old_pwd = getcwd()
129 try:
130 chdir(dir_context)
Bartek Grzybowskid0f2a7d2020-06-08 12:13:57 +0200131 self.logger.debug(f'_run_cmd: Current direcotry: {getcwd()}')
132 self.logger.debug(f'_run_cmd: Command string: {cmd}')
Bartek Grzybowskif2b14832020-05-25 00:47:35 -0700133 run(cmd, check=True, shell=True)
Bartek Grzybowskib61465f2020-05-14 05:52:40 -0700134 chdir(old_pwd)
135 except FileNotFoundError:
136 self.logger.error(f"Directory {dir_context} not found")
Bartek Grzybowskif2b14832020-05-25 00:47:35 -0700137 except CalledProcessError as e:
Bartek Grzybowskib61465f2020-05-14 05:52:40 -0700138 exit(e.returncode)
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700139
Bartek Grzybowskia71704c2020-05-19 04:47:09 -0700140 def _enum_sim_instances(self):
141 '''Helper method that returns bootstraped simulator instances count'''
142 return len(glob(f"{self.sim_dirname_pattern}[0-9]*"))
143
Bartek Grzybowski07b7d002020-05-28 07:40:02 -0700144 def _get_sim_instance_data(self, instance_id):
145 '''Helper method that returns specific instance data'''
146 oldpwd = getcwd()
147 chdir(f"{self.sim_dirname_pattern}{instance_id}")
148 with open(self.sim_config) as cfg:
149 yml = load(cfg, Loader=SafeLoader)
150 chdir(oldpwd)
151 return yml['ippnfsim']
152
Bartek Grzybowski110badf2020-06-01 12:31:42 +0200153 def _get_docker_containers(self):
154 '''Returns a list containing 'name' attribute of running docker containers'''
155 dc = from_env()
156 containers = []
157 for container in dc.containers.list():
158 containers.append(container.attrs['Name'][1:])
159 return containers
160
Bartek Grzybowski61ed3662020-06-02 10:25:11 +0200161 def _get_iter_range(self):
162 '''Helper routine to get the iteration range
163 for the lifecycle commands'''
Bartek Grzybowski33a15ff2020-06-04 12:18:41 +0200164 if hasattr(self.args, 'count'):
165 if not self.args.count:
166 return [self.existing_sim_instances]
167 else:
168 return [self.args.count]
169 elif hasattr(self.args, 'triggerstart'):
170 return [self.args.triggerstart, self.args.triggerend + 1]
Bartek Grzybowski61ed3662020-06-02 10:25:11 +0200171 else:
Bartek Grzybowski33a15ff2020-06-04 12:18:41 +0200172 return [self.existing_sim_instances]
Bartek Grzybowski61ed3662020-06-02 10:25:11 +0200173
Bartek Grzybowski138b1992020-06-08 14:25:44 +0200174 def _archive_logs(self, sim_dir):
175 '''Helper function to archive simulator logs or create the log dir'''
176 old_pwd = getcwd()
177 try:
178 chdir(sim_dir)
179 if path.isdir('logs'):
180 arch_dir = f"logs/archive_{strftime('%Y-%m-%d_%T')}"
181 mkdir(arch_dir)
182 self.logger.debug(f'Created {arch_dir}')
183 # Collect file list to move
184 self.logger.debug('Archiving log files')
185 for fpattern in ['*.log', '*.xml']:
186 for f in glob('logs/' + fpattern):
187 # Move files from list to arch dir
188 move(f, arch_dir)
189 self.logger.debug(f'Moving {f} to {arch_dir}')
190 else:
191 mkdir('logs')
192 self.logger.debug("Logs dir didn't exist, created")
193 chdir(old_pwd)
194 except FileNotFoundError:
195 self.logger.error(f"Directory {sim_dir} not found")
196
Bartek Grzybowski700b6072020-06-09 12:41:08 +0200197 def _generate_pnf_sim_config(self, i, port_sftp, port_ftps, pnf_sim_ip):
198 '''Writes a yaml formatted configuration file for Java simulator app'''
199 yml = {}
200 yml['urlves'] = self.args.urlves
201 yml['urlsftp'] = f'sftp://onap:pano@{self.args.ipfileserver}:{port_sftp}'
202 yml['urlftps'] = f'ftps://onap:pano@{self.args.ipfileserver}:{port_ftps}'
203 yml['ippnfsim'] = pnf_sim_ip
204 yml['typefileserver'] = self.args.typefileserver
205 self.logger.debug(f'Generated simulator config:\n{dump(yml)}')
206 with open(f'{self.sim_dirname_pattern}{i}/{self.sim_config}', 'w') as fout:
207 fout.write(dump(yml))
208
Bartek Grzybowskie2f20d02020-06-12 10:45:42 +0200209 def _generate_config_file(self, source, dest, **kwargs):
210 '''Helper private method to generate a file based on a template'''
Bartek Grzybowski1fbf8542020-06-10 15:16:23 +0200211 old_pwd = getcwd()
212 chdir(self.sim_dirname_pattern + str(kwargs['I']))
Bartek Grzybowskie2f20d02020-06-12 10:45:42 +0200213 # Read the template file
214 with open(source, 'r') as f:
Bartek Grzybowski1fbf8542020-06-10 15:16:23 +0200215 template = f.read()
216 # Replace all occurences of env like variable with it's
217 # relevant value from a corresponding key form kwargs
218 for (k,v) in kwargs.items():
219 template = template.replace('${' + k + '}', str(v))
Bartek Grzybowskie2f20d02020-06-12 10:45:42 +0200220 with open(dest, 'w') as f:
Bartek Grzybowski1fbf8542020-06-10 15:16:23 +0200221 f.write(template)
222 chdir(old_pwd)
223
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700224 def bootstrap(self):
225 self.logger.info("Bootstrapping PNF instances")
226
227 start_port = 2000
228 ftps_pasv_port_start = 8000
229 ftps_pasv_port_num_of_ports = 10
230
231 ftps_pasv_port_end = ftps_pasv_port_start + ftps_pasv_port_num_of_ports
232
233 for i in range(self.args.count):
234 self.logger.info(f"PNF simulator instance: {i}")
235
236 # The IP ranges are in distance of 16 compared to each other.
237 # This is matching the /28 subnet mask used in the dockerfile inside.
238 instance_ip_offset = i * 16
239 ip_properties = [
240 'subnet',
241 'gw',
242 'PnfSim',
243 'ftps',
244 'sftp'
245 ]
246
247 ip_offset = 0
248 ip = {}
249 for prop in ip_properties:
250 ip.update({prop: str(self.args.ipstart + ip_offset + instance_ip_offset)})
251 ip_offset += 1
252
253 self.logger.debug(f'Instance #{i} properties:\n {dumps(ip, indent=4)}')
254
255 PortSftp = start_port + 1
256 PortFtps = start_port + 2
257 start_port += 2
258
Bartek Grzybowskibe79e4d2020-05-14 07:38:54 -0700259 self.logger.info(f'\tCreating {self.sim_dirname_pattern}{i}')
Bartek Grzybowski5717b5e2020-05-19 04:50:51 -0700260 copytree('pnf-sim-lightweight', f'{self.sim_dirname_pattern}{i}')
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700261
262 composercmd = " ".join([
263 "./simulator.sh compose",
264 ip['gw'],
265 ip['subnet'],
266 str(i),
267 self.args.urlves,
268 ip['PnfSim'],
269 str(self.args.ipfileserver),
270 self.args.typefileserver,
271 str(PortSftp),
272 str(PortFtps),
273 ip['ftps'],
274 ip['sftp'],
275 str(ftps_pasv_port_start),
276 str(ftps_pasv_port_end)
277 ])
278 self.logger.debug(f"Script cmdline: {composercmd}")
Bartek Grzybowskibe79e4d2020-05-14 07:38:54 -0700279 self.logger.info(f"\tCreating instance #{i} configuration ")
280 self._run_cmd(composercmd, f"{self.sim_dirname_pattern}{i}")
Bartek Grzybowski1fbf8542020-06-10 15:16:23 +0200281 self._generate_pnf_sim_config(i, PortSftp, PortFtps, ip['PnfSim'])
Bartek Grzybowskie2f20d02020-06-12 10:45:42 +0200282 # generate docker-compose for the simulator instance
283 self._generate_config_file(self.sim_compose_template, 'docker-compose.yml',
284 IPGW = ip['gw'], IPSUBNET = ip['subnet'],
285 I = i, IPPNFSIM = ip['PnfSim'],
286 PORTSFTP = str(PortSftp),
287 PORTFTPS = str(PortFtps),
288 IPFTPS = ip['ftps'], IPSFTP = ip['sftp'],
289 FTPS_PASV_MIN = str(ftps_pasv_port_start),
290 FTPS_PASV_MAX = str(ftps_pasv_port_end),
291 TIMEZONE = tzname[daylight])
Bartek Grzybowski9ab2f402020-06-12 12:20:48 +0200292 # generate vsftpd config file for the simulator instance
293 self._generate_config_file(self.sim_vsftpd_template, self.sim_vsftpd_config,
294 I = i, USER = getlogin(),
295 FTPS_PASV_MIN = str(ftps_pasv_port_start),
296 FTPS_PASV_MAX = str(ftps_pasv_port_end),
297 IPFILESERVER = str(self.args.ipfileserver))
Bartek Grzybowski624c1152020-06-15 13:14:45 +0200298 # Run the 3GPP measurements file generator
299 self._run_cmd(f'./ROP_file_creator.sh {i} &', f"{self.sim_dirname_pattern}{i}")
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700300
301 ftps_pasv_port_start += ftps_pasv_port_num_of_ports + 1
302 ftps_pasv_port_end += ftps_pasv_port_num_of_ports + 1
303
Bartek Grzybowski81287bc2020-06-08 14:29:29 +0200304 # ugly hack to chown vsftpd config file to root
305 if getuid():
Bartek Grzybowski9ab2f402020-06-12 12:20:48 +0200306 self._run_cmd(f'sudo chown root {self.sim_vsftpd_config}', f'{self.sim_dirname_pattern}{i}')
307 self.logger.debug(f"vsftpd config file owner UID: {stat(self.sim_dirname_pattern + str(i) + '/' + self.sim_vsftpd_config).st_uid}")
Bartek Grzybowski81287bc2020-06-08 14:29:29 +0200308
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700309 self.logger.info(f'Done setting up instance #{i}')
310
Bartek Grzybowskid2038202020-05-15 00:57:25 -0700311 def build(self):
312 self.logger.info("Building simulator image")
Bartek Grzybowski54227002020-05-15 07:38:04 -0700313 if path.isfile('pnf-sim-lightweight/pom.xml'):
314 self._run_cmd(self.mvn_build_cmd, 'pnf-sim-lightweight')
315 else:
316 self.logger.error('POM file was not found, Maven cannot run')
317 exit(1)
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700318
319 def clean(self):
Bartek Grzybowskib61465f2020-05-14 05:52:40 -0700320 self.logger.info('Cleaning simulators workdirs')
Bartek Grzybowskif2b14832020-05-25 00:47:35 -0700321 for sim_id in range(self.existing_sim_instances):
322 rmtree(f"{self.sim_dirname_pattern}{sim_id}")
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700323
324 def start(self):
Bartek Grzybowski09b5a6f2020-06-08 14:39:01 +0200325 for i in range(*self._get_iter_range()):
326 # If container is not running
327 if f"{self.sim_container_name}-{i}" not in self._get_docker_containers():
328 self.logger.info(f'Starting {self.sim_dirname_pattern}{i} instance:')
329 self.logger.info(f' PNF-Sim IP: {self._get_sim_instance_data(i)}')
330 #Move logs to archive
331 self._archive_logs(self.sim_dirname_pattern + str(i))
332 self.logger.info(' Starting simulator containers using netconf model specified in config/netconf.env')
333 self._run_cmd('docker-compose up -d', self.sim_dirname_pattern + str(i))
334 else:
335 self.logger.warning(f'Instance {self.sim_dirname_pattern}{i} containers are already up')
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700336
337 def status(self):
Bartek Grzybowski61ed3662020-06-02 10:25:11 +0200338 for i in range(*self._get_iter_range()):
Bartek Grzybowski572f6442020-06-01 12:38:49 +0200339 self.logger.info(f'Getting {self.sim_dirname_pattern}{i} instance status:')
340 if f"{self.sim_container_name}-{i}" in self._get_docker_containers():
341 try:
342 sim_ip = self._get_sim_instance_data(i)
343 self.logger.info(f' PNF-Sim IP: {sim_ip}')
344 self._run_cmd(self.docker_compose_status_cmd, f"{self.sim_dirname_pattern}{i}")
Bartek Grzybowski626f2862020-06-04 09:55:26 +0200345 sim_response = get('{}'.format(self.sim_status_url).format(sim_ip))
Bartek Grzybowski572f6442020-06-01 12:38:49 +0200346 if sim_response.status_code == codes.ok:
347 self.logger.info(sim_response.text)
348 else:
349 self.logger.error(f'Simulator request returned http code {sim_response.status_code}')
350 except KeyError:
351 self.logger.error(f'Unable to get sim instance IP from {self.sim_config}')
352 else:
353 self.logger.info(' Simulator containers are down')
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700354
355 def stop(self):
Bartek Grzybowskic17ed782020-06-03 11:46:51 +0200356 for i in range(*self._get_iter_range()):
357 self.logger.info(f'Stopping {self.sim_dirname_pattern}{i} instance:')
358 self.logger.info(f' PNF-Sim IP: {self._get_sim_instance_data(i)}')
359 # attempt killing ROP script
360 rop_pid = []
361 for ps_line in iter(popen(f'ps --no-headers -C {self.rop_script_name} -o pid,cmd').readline, ''):
362 # try getting ROP script pid
363 try:
364 ps_line_arr = ps_line.split()
365 assert self.rop_script_name in ps_line_arr[2]
366 assert ps_line_arr[3] == str(i)
367 rop_pid = ps_line_arr[0]
368 except AssertionError:
369 pass
370 else:
371 # get rop script childs, kill ROP script and all childs
372 childs = popen(f'pgrep -P {rop_pid}').read().split()
373 for pid in [rop_pid] + childs:
374 kill(int(pid), 15)
375 self.logger.info(f' ROP_file_creator.sh {i} successfully killed')
376 if not rop_pid:
377 # no process found
378 self.logger.warning(f' ROP_file_creator.sh {i} already not running')
379 # try tearing down docker-compose application
380 if f"{self.sim_container_name}-{i}" in self._get_docker_containers():
381 self._run_cmd('docker-compose down', self.sim_dirname_pattern + str(i))
382 self._run_cmd('docker-compose rm', self.sim_dirname_pattern + str(i))
383 else:
384 self.logger.warning(" Simulator containers are already down")
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700385
386 def trigger(self):
387 self.logger.info("Triggering VES sending:")
Bartek Grzybowski626f2862020-06-04 09:55:26 +0200388 for i in range(*self._get_iter_range()):
389 sim_ip = self._get_sim_instance_data(i)
390 self.logger.info(f'Triggering {self.sim_dirname_pattern}{i} instance:')
391 self.logger.info(f' PNF-Sim IP: {sim_ip}')
392 # setup req headers
393 req_headers = {
394 "Content-Type": "application/json",
395 "X-ONAP-RequestID": "123",
396 "X-InvocationID": "456"
397 }
398 self.logger.debug(f' Request headers: {req_headers}')
399 try:
400 # get payload for the request
401 with open(f'{self.sim_dirname_pattern}{i}/{self.sim_msg_config}') as data:
402 json_data = loads(data.read())
403 self.logger.debug(f' JSON payload for the simulator:\n{json_data}')
404 # make a http request to the simulator
405 sim_response = post('{}'.format(self.sim_start_url).format(sim_ip), headers=req_headers, json=json_data)
406 if sim_response.status_code == codes.ok:
407 self.logger.info(' Simulator response: ' + sim_response.text)
408 else:
409 self.logger.warning(' Simulator response ' + sim_response.text)
410 except TypeError:
411 self.logger.error(f' Could not load JSON data from {self.sim_dirname_pattern}{i}/{self.sim_msg_config}')
Bartek Grzybowskifeb93cd2020-05-11 04:51:37 -0700412
Bartek Grzybowski33a15ff2020-06-04 12:18:41 +0200413 # Make the 'trigger_custom' an alias to the 'trigger' method
414 trigger_custom = trigger
Bartek Grzybowskia3737ae2020-06-05 15:07:56 +0200415
416 def stop_simulator(self):
417 self.logger.info("Stopping sending PNF registration messages:")
418 for i in range(*self._get_iter_range()):
419 sim_ip = self._get_sim_instance_data(i)
420 self.logger.info(f'Stopping {self.sim_dirname_pattern}{i} instance:')
421 self.logger.info(f' PNF-Sim IP: {sim_ip}')
422 sim_response = post('{}'.format(self.sim_stop_url).format(sim_ip))
423 if sim_response.status_code == codes.ok:
424 self.logger.info(' Simulator response: ' + sim_response.text)
425 else:
426 self.logger.warning(' Simulator response ' + sim_response.text)