11471Szelenkov@nginx.comimport re 21477Szelenkov@nginx.comimport subprocess 31471Szelenkov@nginx.comimport time 41477Szelenkov@nginx.com 51471Szelenkov@nginx.comfrom unit.applications.lang.python import TestApplicationPython 61730Szelenkov@nginx.comfrom unit.option import option 71471Szelenkov@nginx.com 81471Szelenkov@nginx.com 91471Szelenkov@nginx.comclass TestRespawn(TestApplicationPython): 101471Szelenkov@nginx.com prerequisites = {'modules': {'python': 'any'}} 111471Szelenkov@nginx.com 121471Szelenkov@nginx.com PATTERN_ROUTER = 'unit: router' 131471Szelenkov@nginx.com PATTERN_CONTROLLER = 'unit: controller' 141471Szelenkov@nginx.com 151596Szelenkov@nginx.com def setup_method(self): 161654Szelenkov@nginx.com self.app_name = "app-" + option.temp_dir.split('/')[-1] 171471Szelenkov@nginx.com 181471Szelenkov@nginx.com self.load('empty', self.app_name) 191471Szelenkov@nginx.com 201596Szelenkov@nginx.com assert 'success' in self.conf( 211596Szelenkov@nginx.com '1', 'applications/' + self.app_name + '/processes' 221471Szelenkov@nginx.com ) 231471Szelenkov@nginx.com 24*1769St.nateldemoura@f5.com def pid_by_name(self, name, ppid): 25*1769St.nateldemoura@f5.com output = subprocess.check_output(['ps', 'ax', '-O', 'ppid']).decode() 26*1769St.nateldemoura@f5.com m = re.search(r'\s*(\d+)\s*' + str(ppid) + r'.*' + name, output) 27*1769St.nateldemoura@f5.com return None if m is None else m.group(1) 281471Szelenkov@nginx.com 291471Szelenkov@nginx.com def kill_pids(self, *pids): 301471Szelenkov@nginx.com subprocess.call(['kill', '-9'] + list(pids)) 311471Szelenkov@nginx.com 32*1769St.nateldemoura@f5.com def wait_for_process(self, process, unit_pid): 331471Szelenkov@nginx.com for i in range(50): 34*1769St.nateldemoura@f5.com found = self.pid_by_name(process, unit_pid) 351471Szelenkov@nginx.com 361471Szelenkov@nginx.com if found is not None: 371471Szelenkov@nginx.com break 381471Szelenkov@nginx.com 391471Szelenkov@nginx.com time.sleep(0.1) 401471Szelenkov@nginx.com 411471Szelenkov@nginx.com return found 421471Szelenkov@nginx.com 43*1769St.nateldemoura@f5.com def find_proc(self, name, ppid, ps_output): 44*1769St.nateldemoura@f5.com return re.findall(str(ppid) + r'.*' + name, ps_output) 45*1769St.nateldemoura@f5.com 46*1769St.nateldemoura@f5.com def smoke_test(self, unit_pid): 471471Szelenkov@nginx.com for _ in range(5): 481596Szelenkov@nginx.com assert 'success' in self.conf( 491596Szelenkov@nginx.com '1', 'applications/' + self.app_name + '/processes' 501471Szelenkov@nginx.com ) 511596Szelenkov@nginx.com assert self.get()['status'] == 200 521471Szelenkov@nginx.com 531471Szelenkov@nginx.com # Check if the only one router, controller, 541471Szelenkov@nginx.com # and application processes running. 551471Szelenkov@nginx.com 56*1769St.nateldemoura@f5.com out = subprocess.check_output(['ps', 'ax', '-O', 'ppid']).decode() 57*1769St.nateldemoura@f5.com assert len(self.find_proc(self.PATTERN_ROUTER, unit_pid, out)) == 1 58*1769St.nateldemoura@f5.com assert len(self.find_proc(self.PATTERN_CONTROLLER, unit_pid, out)) == 1 59*1769St.nateldemoura@f5.com assert len(self.find_proc(self.app_name, unit_pid, out)) == 1 601471Szelenkov@nginx.com 61*1769St.nateldemoura@f5.com def test_respawn_router(self, skip_alert, unit_pid): 62*1769St.nateldemoura@f5.com pid = self.pid_by_name(self.PATTERN_ROUTER, unit_pid) 631471Szelenkov@nginx.com 641471Szelenkov@nginx.com self.kill_pids(pid) 651596Szelenkov@nginx.com skip_alert(r'process %s exited on signal 9' % pid) 661471Szelenkov@nginx.com 67*1769St.nateldemoura@f5.com assert self.wait_for_process(self.PATTERN_ROUTER, unit_pid) is not None 681471Szelenkov@nginx.com 69*1769St.nateldemoura@f5.com self.smoke_test(unit_pid) 701471Szelenkov@nginx.com 71*1769St.nateldemoura@f5.com def test_respawn_controller(self, skip_alert, unit_pid): 72*1769St.nateldemoura@f5.com pid = self.pid_by_name(self.PATTERN_CONTROLLER, unit_pid) 731471Szelenkov@nginx.com 741471Szelenkov@nginx.com self.kill_pids(pid) 751596Szelenkov@nginx.com skip_alert(r'process %s exited on signal 9' % pid) 761471Szelenkov@nginx.com 77*1769St.nateldemoura@f5.com assert self.wait_for_process( 78*1769St.nateldemoura@f5.com self.PATTERN_CONTROLLER, unit_pid 79*1769St.nateldemoura@f5.com ) is not None 801471Szelenkov@nginx.com 811596Szelenkov@nginx.com assert self.get()['status'] == 200 821471Szelenkov@nginx.com 83*1769St.nateldemoura@f5.com self.smoke_test(unit_pid) 841471Szelenkov@nginx.com 85*1769St.nateldemoura@f5.com def test_respawn_application(self, skip_alert, unit_pid): 86*1769St.nateldemoura@f5.com pid = self.pid_by_name(self.app_name, unit_pid) 871471Szelenkov@nginx.com 881471Szelenkov@nginx.com self.kill_pids(pid) 891596Szelenkov@nginx.com skip_alert(r'process %s exited on signal 9' % pid) 901471Szelenkov@nginx.com 91*1769St.nateldemoura@f5.com assert self.wait_for_process(self.app_name, unit_pid) is not None 921471Szelenkov@nginx.com 93*1769St.nateldemoura@f5.com self.smoke_test(unit_pid) 94