~ionutbalutoiu/charms/trusty/neutron-api/next

« back to all changes in this revision

Viewing changes to tests/charmhelpers/contrib/amulet/utils.py

  • Committer: James Page
  • Date: 2015-09-09 07:48:54 UTC
  • mfrom: (120.2.6 trunk)
  • Revision ID: james.page@ubuntu.com-20150909074854-ux3q016k4xlzn5x6
[1chb1n,r=james-page] Resync helpers, update amulet tests to avoid races, enable vivid-kilo testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
114
114
        # /!\ DEPRECATION WARNING (beisner):
115
115
        # New and existing tests should be rewritten to use
116
116
        # validate_services_by_name() as it is aware of init systems.
117
 
        self.log.warn('/!\\ DEPRECATION WARNING:  use '
 
117
        self.log.warn('DEPRECATION WARNING:  use '
118
118
                      'validate_services_by_name instead of validate_services '
119
119
                      'due to init system differences.')
120
120
 
269
269
        """Get last modification time of directory."""
270
270
        return sentry_unit.directory_stat(directory)['mtime']
271
271
 
272
 
    def _get_proc_start_time(self, sentry_unit, service, pgrep_full=False):
273
 
        """Get process' start time.
274
 
 
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.
278
 
           """
279
 
        if pgrep_full:
280
 
            cmd = 'pgrep -o -f {}'.format(service)
281
 
        else:
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))
286
 
        if cmd_out[0]:
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.
 
275
 
 
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
 
283
        """
 
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.')
 
290
 
 
291
        pid_list = self.get_process_id_list(sentry_unit, service)
 
292
        pid = pid_list[0]
 
293
        proc_dir = '/proc/{}'.format(pid)
 
294
        self.log.debug('Pid for {} on {}: {}'.format(
 
295
            service, sentry_unit.info['unit_name'], pid))
 
296
 
 
297
        return self._get_dir_mtime(sentry_unit, proc_dir)
290
298
 
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.
294
302
 
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.
298
306
           """
 
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.
 
310
 
 
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.')
 
317
 
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)):
304
323
            return False
305
324
 
306
325
    def service_restarted_since(self, sentry_unit, mtime, service,
307
 
                                pgrep_full=False, sleep_time=20,
308
 
                                retry_count=2):
 
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.
310
329
 
311
330
        Args:
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
318
337
 
321
340
                False if service is older than mtime or if service was
322
341
                not found.
323
342
        """
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
 
346
 
 
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,
327
 
                                                    pgrep_full)
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))
331
 
            time.sleep(30)
332
 
            proc_start_time = self._get_proc_start_time(sentry_unit, service,
333
 
                                                        pgrep_full)
334
 
            retry_count = retry_count - 1
 
351
        proc_start_time = None
 
352
        tries = 0
 
353
        while tries <= retry_count and not proc_start_time:
 
354
            try:
 
355
                proc_start_time = self._get_proc_start_time(sentry_unit,
 
356
                                                            service,
 
357
                                                            pgrep_full)
 
358
                self.log.debug('Attempt {} to get {} proc start time on {} '
 
359
                               'OK'.format(tries, service, unit_name))
 
360
            except IOError:
 
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)
 
366
                tries += 1
335
367
 
336
368
        if not proc_start_time:
337
369
            self.log.warn('No proc start time found, assuming service did '
338
370
                          'not start')
339
371
            return False
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,
 
375
                                                      mtime, unit_name))
343
376
            return True
344
377
        else:
345
 
            self.log.warn('proc start time (%s) is older than provided mtime '
346
 
                          '(%s), service did not restart' % (proc_start_time,
347
 
                                                             mtime))
 
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))
348
381
            return False
349
382
 
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,
363
396
        """
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,
 
405
                                                      unit_name))
370
406
            return True
371
407
        else:
372
408
            self.log.warn('File mtime %s is older than provided mtime %s'
374
410
            return False
375
411
 
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
380
417
 
381
418
        Args:
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
389
427
 
390
428
        Typical Usage:
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.
404
442
        """
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,
408
 
                                                       service,
409
 
                                                       pgrep_full=pgrep_full,
410
 
                                                       sleep_time=0,
411
 
                                                       retry_count=retry_count)
412
 
        config_update = self.config_updated_since(sentry_unit, filename, mtime,
413
 
                                                  sleep_time=0)
 
443
 
 
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
 
447
 
 
448
        service_restart = self.service_restarted_since(
 
449
            sentry_unit, mtime,
 
450
            service,
 
451
            pgrep_full=pgrep_full,
 
452
            sleep_time=sleep_time,
 
453
            retry_count=retry_count,
 
454
            retry_sleep_time=retry_sleep_time)
 
455
 
 
456
        config_update = self.config_updated_since(
 
457
            sentry_unit,
 
458
            filename,
 
459
            mtime,
 
460
            sleep_time=0)
 
461
 
414
462
        return service_restart and config_update
415
463
 
416
464
    def get_sentry_time(self, sentry_unit):