269
269
"""Get last modification time of directory."""
270
270
return sentry_unit.directory_stat(directory)['mtime']
272
def _get_proc_start_time(self, sentry_unit, service, pgrep_full=False):
273
"""Get process' start time.
275
Determine start time of the process based on the last modification
276
time of the /proc/pid directory. If pgrep_full is True, the process
277
name is matched against the full command line.
280
cmd = 'pgrep -o -f {}'.format(service)
282
cmd = 'pgrep -o {}'.format(service)
283
cmd = cmd + ' | grep -v pgrep || exit 0'
284
cmd_out = sentry_unit.run(cmd)
285
self.log.debug('CMDout: ' + str(cmd_out))
287
self.log.debug('Pid for %s %s' % (service, str(cmd_out[0])))
288
proc_dir = '/proc/{}'.format(cmd_out[0].strip())
289
return self._get_dir_mtime(sentry_unit, proc_dir)
272
def _get_proc_start_time(self, sentry_unit, service, pgrep_full=None):
273
"""Get start time of a process based on the last modification time
274
of the /proc/pid directory.
276
:sentry_unit: The sentry unit to check for the service on
277
:service: service name to look for in process table
278
:pgrep_full: [Deprecated] Use full command line search mode with pgrep
279
:returns: epoch time of service process start
280
:param commands: list of bash commands
281
:param sentry_units: list of sentry unit pointers
282
:returns: None if successful; Failure message otherwise
284
if pgrep_full is not None:
285
# /!\ DEPRECATION WARNING (beisner):
286
# No longer implemented, as pidof is now used instead of pgrep.
287
# https://bugs.launchpad.net/charm-helpers/+bug/1474030
288
self.log.warn('DEPRECATION WARNING: pgrep_full bool is no '
289
'longer implemented re: lp 1474030.')
291
pid_list = self.get_process_id_list(sentry_unit, service)
293
proc_dir = '/proc/{}'.format(pid)
294
self.log.debug('Pid for {} on {}: {}'.format(
295
service, sentry_unit.info['unit_name'], pid))
297
return self._get_dir_mtime(sentry_unit, proc_dir)
291
299
def service_restarted(self, sentry_unit, service, filename,
292
pgrep_full=False, sleep_time=20):
300
pgrep_full=None, sleep_time=20):
293
301
"""Check if service was restarted.
295
303
Compare a service's start time vs a file's last modification time
296
304
(such as a config file for that service) to determine if the service
297
305
has been restarted.
307
# /!\ DEPRECATION WARNING (beisner):
308
# This method is prone to races in that no before-time is known.
309
# Use validate_service_config_changed instead.
311
# NOTE(beisner) pgrep_full is no longer implemented, as pidof is now
312
# used instead of pgrep. pgrep_full is still passed through to ensure
313
# deprecation WARNS. lp1474030
314
self.log.warn('DEPRECATION WARNING: use '
315
'validate_service_config_changed instead of '
316
'service_restarted due to known races.')
299
318
time.sleep(sleep_time)
300
319
if (self._get_proc_start_time(sentry_unit, service, pgrep_full) >=
301
320
self._get_file_mtime(sentry_unit, filename)):
306
325
def service_restarted_since(self, sentry_unit, mtime, service,
307
pgrep_full=False, sleep_time=20,
326
pgrep_full=None, sleep_time=20,
327
retry_count=2, retry_sleep_time=30):
309
328
"""Check if service was been started after a given time.
312
331
sentry_unit (sentry): The sentry unit to check for the service on
313
332
mtime (float): The epoch time to check against
314
333
service (string): service name to look for in process table
315
pgrep_full (boolean): Use full command line search mode with pgrep
334
pgrep_full: [Deprecated] Use full command line search mode with pgrep
316
335
sleep_time (int): Seconds to sleep before looking for process
317
336
retry_count (int): If service is not found, how many times to retry
321
340
False if service is older than mtime or if service was
324
self.log.debug('Checking %s restarted since %s' % (service, mtime))
343
# NOTE(beisner) pgrep_full is no longer implemented, as pidof is now
344
# used instead of pgrep. pgrep_full is still passed through to ensure
345
# deprecation WARNS. lp1474030
347
unit_name = sentry_unit.info['unit_name']
348
self.log.debug('Checking that %s service restarted since %s on '
349
'%s' % (service, mtime, unit_name))
325
350
time.sleep(sleep_time)
326
proc_start_time = self._get_proc_start_time(sentry_unit, service,
328
while retry_count > 0 and not proc_start_time:
329
self.log.debug('No pid file found for service %s, will retry %i '
330
'more times' % (service, retry_count))
332
proc_start_time = self._get_proc_start_time(sentry_unit, service,
334
retry_count = retry_count - 1
351
proc_start_time = None
353
while tries <= retry_count and not proc_start_time:
355
proc_start_time = self._get_proc_start_time(sentry_unit,
358
self.log.debug('Attempt {} to get {} proc start time on {} '
359
'OK'.format(tries, service, unit_name))
361
# NOTE(beisner) - race avoidance, proc may not exist yet.
362
# https://bugs.launchpad.net/charm-helpers/+bug/1474030
363
self.log.debug('Attempt {} to get {} proc start time on {} '
364
'failed'.format(tries, service, unit_name))
365
time.sleep(retry_sleep_time)
336
368
if not proc_start_time:
337
369
self.log.warn('No proc start time found, assuming service did '
340
372
if proc_start_time >= mtime:
341
self.log.debug('proc start time is newer than provided mtime'
342
'(%s >= %s)' % (proc_start_time, mtime))
373
self.log.debug('Proc start time is newer than provided mtime'
374
'(%s >= %s) on %s (OK)' % (proc_start_time,
345
self.log.warn('proc start time (%s) is older than provided mtime '
346
'(%s), service did not restart' % (proc_start_time,
378
self.log.warn('Proc start time (%s) is older than provided mtime '
379
'(%s) on %s, service did not '
380
'restart' % (proc_start_time, mtime, unit_name))
350
383
def config_updated_since(self, sentry_unit, filename, mtime,
361
394
bool: True if file was modified more recently than mtime, False if
362
395
file was modified before mtime,
364
self.log.debug('Checking %s updated since %s' % (filename, mtime))
397
self.log.debug('Checking that %s file updated since '
398
'%s' % (filename, mtime))
399
unit_name = sentry_unit.info['unit_name']
365
400
time.sleep(sleep_time)
366
401
file_mtime = self._get_file_mtime(sentry_unit, filename)
367
402
if file_mtime >= mtime:
368
403
self.log.debug('File mtime is newer than provided mtime '
369
'(%s >= %s)' % (file_mtime, mtime))
404
'(%s >= %s) on %s (OK)' % (file_mtime, mtime,
372
408
self.log.warn('File mtime %s is older than provided mtime %s'
376
412
def validate_service_config_changed(self, sentry_unit, mtime, service,
377
filename, pgrep_full=False,
378
sleep_time=20, retry_count=2):
413
filename, pgrep_full=None,
414
sleep_time=20, retry_count=2,
415
retry_sleep_time=30):
379
416
"""Check service and file were updated after mtime
383
420
mtime (float): The epoch time to check against
384
421
service (string): service name to look for in process table
385
422
filename (string): The file to check mtime of
386
pgrep_full (boolean): Use full command line search mode with pgrep
387
sleep_time (int): Seconds to sleep before looking for process
423
pgrep_full: [Deprecated] Use full command line search mode with pgrep
424
sleep_time (int): Initial sleep in seconds to pass to test helpers
388
425
retry_count (int): If service is not found, how many times to retry
426
retry_sleep_time (int): Time in seconds to wait between retries
391
429
u = OpenStackAmuletUtils(ERROR)
402
440
mtime, False if service is older than mtime or if service was
403
441
not found or if filename was modified before mtime.
405
self.log.debug('Checking %s restarted since %s' % (service, mtime))
406
time.sleep(sleep_time)
407
service_restart = self.service_restarted_since(sentry_unit, mtime,
409
pgrep_full=pgrep_full,
411
retry_count=retry_count)
412
config_update = self.config_updated_since(sentry_unit, filename, mtime,
444
# NOTE(beisner) pgrep_full is no longer implemented, as pidof is now
445
# used instead of pgrep. pgrep_full is still passed through to ensure
446
# deprecation WARNS. lp1474030
448
service_restart = self.service_restarted_since(
451
pgrep_full=pgrep_full,
452
sleep_time=sleep_time,
453
retry_count=retry_count,
454
retry_sleep_time=retry_sleep_time)
456
config_update = self.config_updated_since(
414
462
return service_restart and config_update
416
464
def get_sentry_time(self, sentry_unit):