Drop shell wrapper for stopping simulator instances 26/108726/3
authorBartek Grzybowski <b.grzybowski@partner.samsung.com>
Wed, 3 Jun 2020 09:46:51 +0000 (11:46 +0200)
committerMorgan Richomme <morgan.richomme@orange.com>
Fri, 5 Jun 2020 13:47:18 +0000 (13:47 +0000)
Instance method is added to manage stopping simulator
instances and ROP scripts directly in MassPnfSim class.

Change-Id: Ic551f99c0f5f2a177b9c72daac02690b0bbded04
Issue-ID: INT-1610
Signed-off-by: Bartek Grzybowski <b.grzybowski@partner.samsung.com>
test/mocks/mass-pnf-sim/MassPnfSim.py
test/mocks/mass-pnf-sim/test_lifecycle.py

index b6a32fe..42424e6 100755 (executable)
@@ -4,7 +4,7 @@ from subprocess import run, CalledProcessError
 import argparse
 import ipaddress
 from sys import exit
 import argparse
 import ipaddress
 from sys import exit
-from os import chdir, getcwd, path
+from os import chdir, getcwd, path, popen, kill
 from shutil import copytree, rmtree
 from json import dumps
 from yaml import load, SafeLoader
 from shutil import copytree, rmtree
 from json import dumps
 from yaml import load, SafeLoader
@@ -84,10 +84,6 @@ class MassPnfSim:
         def do_action(action_string, cmd):
             def action_decorator(method):
                 def action_wrap(self):
         def do_action(action_string, cmd):
             def action_decorator(method):
                 def action_wrap(self):
-                    cmd_local = cmd
-                    # Append instance # if action is 'stop'
-                    if method.__name__ == 'stop':
-                        cmd_local += " {}"
                     # Alter looping range if action is 'tigger_custom'
                     if method.__name__ == 'trigger_custom':
                         iter_range = [self.args.triggerstart, self.args.triggerend+1]
                     # Alter looping range if action is 'tigger_custom'
                     if method.__name__ == 'trigger_custom':
                         iter_range = [self.args.triggerstart, self.args.triggerend+1]
@@ -101,7 +97,7 @@ class MassPnfSim:
                     method(self)
                     for i in range(*iter_range):
                         self.logger.info(f'{action_string} {self.sim_dirname_pattern}{i} instance:')
                     method(self)
                     for i in range(*iter_range):
                         self.logger.info(f'{action_string} {self.sim_dirname_pattern}{i} instance:')
-                        self._run_cmd(cmd_local.format(i), f"{self.sim_dirname_pattern}{i}")
+                        self._run_cmd(cmd, f"{self.sim_dirname_pattern}{i}")
                 return action_wrap
             return action_decorator
 
                 return action_wrap
             return action_decorator
 
@@ -110,6 +106,7 @@ class MassPnfSim:
     sim_port = 5000
     sim_base_url = 'http://{}:' + str(sim_port) + '/simulator'
     sim_container_name = 'pnf-simulator'
     sim_port = 5000
     sim_base_url = 'http://{}:' + str(sim_port) + '/simulator'
     sim_container_name = 'pnf-simulator'
+    rop_script_name = 'ROP_file_creator.sh'
 
     def __init__(self, args):
         self.args = args
 
     def __init__(self, args):
         self.args = args
@@ -280,9 +277,36 @@ class MassPnfSim:
             else:
                 self.logger.info(' Simulator containers are down')
 
             else:
                 self.logger.info(' Simulator containers are down')
 
-    @_MassPnfSim_Decorators.do_action('Stopping', './simulator.sh stop')
     def stop(self):
     def stop(self):
-        pass
+        for i in range(*self._get_iter_range()):
+            self.logger.info(f'Stopping {self.sim_dirname_pattern}{i} instance:')
+            self.logger.info(f' PNF-Sim IP: {self._get_sim_instance_data(i)}')
+            # attempt killing ROP script
+            rop_pid = []
+            for ps_line in iter(popen(f'ps --no-headers -C {self.rop_script_name} -o pid,cmd').readline, ''):
+                # try getting ROP script pid
+                try:
+                    ps_line_arr = ps_line.split()
+                    assert self.rop_script_name in ps_line_arr[2]
+                    assert ps_line_arr[3] == str(i)
+                    rop_pid = ps_line_arr[0]
+                except AssertionError:
+                    pass
+                else:
+                    # get rop script childs, kill ROP script and all childs
+                    childs = popen(f'pgrep -P {rop_pid}').read().split()
+                    for pid in [rop_pid] + childs:
+                        kill(int(pid), 15)
+                    self.logger.info(f' ROP_file_creator.sh {i} successfully killed')
+            if not rop_pid:
+                # no process found
+                self.logger.warning(f' ROP_file_creator.sh {i} already not running')
+            # try tearing down docker-compose application
+            if f"{self.sim_container_name}-{i}" in self._get_docker_containers():
+                self._run_cmd('docker-compose down', self.sim_dirname_pattern + str(i))
+                self._run_cmd('docker-compose rm', self.sim_dirname_pattern + str(i))
+            else:
+                self.logger.warning(" Simulator containers are already down")
 
     @_MassPnfSim_Decorators.do_action('Triggering', './simulator.sh trigger-simulator')
     def trigger(self):
 
     @_MassPnfSim_Decorators.do_action('Triggering', './simulator.sh trigger-simulator')
     def trigger(self):
index c61b72d..beaa084 100644 (file)
@@ -133,24 +133,32 @@ def test_trigger_custom(args_trigger_custom, caplog, capfd):
         assert "Cannot start simulator since it's already running" in msg.out
     caplog.clear()
 
         assert "Cannot start simulator since it's already running" in msg.out
     caplog.clear()
 
-def test_stop(args_stop, caplog, capfd):
+def test_stop(args_stop, caplog):
     MassPnfSim(args_stop).stop()
     MassPnfSim(args_stop).stop()
-    msg = capfd.readouterr()
     for instance in range(SIM_INSTANCES):
         instance_ip_offset = instance * 16
         ip_offset = 2
         assert f'Stopping pnf-sim-lw-{instance} instance:' in caplog.text
     for instance in range(SIM_INSTANCES):
         instance_ip_offset = instance * 16
         ip_offset = 2
         assert f'Stopping pnf-sim-lw-{instance} instance:' in caplog.text
-        assert f'PNF-Sim IP:  {str(ip_address(IPSTART) + ip_offset + instance_ip_offset)}' in msg.out
+        assert f'PNF-Sim IP: {str(ip_address(IPSTART) + ip_offset + instance_ip_offset)}' in caplog.text
+        assert f'ROP_file_creator.sh {instance} successfully killed' in caplog.text
         assert f"ROP_file_creator.sh {instance}" not in popen('ps afx').read()
     caplog.clear()
 
         assert f"ROP_file_creator.sh {instance}" not in popen('ps afx').read()
     caplog.clear()
 
-def test_stop_idempotence(args_stop, caplog, capfd):
+def test_stop_status(args_status, docker_containers, caplog):
+    MassPnfSim(args_status).status()
+    for instance in range(SIM_INSTANCES):
+        assert f"{PNF_SIM_CONTAINER_NAME}{instance}" not in docker_containers
+        assert 'Simulator containers are down' in caplog.text
+    caplog.clear()
+
+def test_stop_idempotence(args_stop, caplog, docker_containers):
     MassPnfSim(args_stop).stop()
     MassPnfSim(args_stop).stop()
-    msg = capfd.readouterr()
     for instance in range(SIM_INSTANCES):
         assert f'Stopping pnf-sim-lw-{instance} instance:' in caplog.text
     for instance in range(SIM_INSTANCES):
         assert f'Stopping pnf-sim-lw-{instance} instance:' in caplog.text
-        assert 'ROP_file_creator.sh already not running' in msg.out
-        assert 'Simulator containers are already down' in msg.out
+        assert f'ROP_file_creator.sh {instance} already not running' in caplog.text
+        assert 'Simulator containers are already down' in caplog.text
+        assert f"ROP_file_creator.sh {instance}" not in popen('ps afx').read()
+        assert f"{PNF_SIM_CONTAINER_NAME}{instance}" not in docker_containers
     caplog.clear()
 
 def test_clean(args_clean):
     caplog.clear()
 
 def test_clean(args_clean):