def test_file(self): """ An existing file has these attributes """ root = FilePath(self.mktemp()) root.setContent('the content') root.chmod(0777) stdout, stderr, code = self.runScript(['inspect'], json.dumps({ 'kind': 'file', 'path': root.path, })) data = json.loads(stdout) self.assertEqual(data['kind'], 'file') self.assertEqual(data['path'], root.path) self.assertEqual(data['exists'], True) self.assertEqual(data['filetype'], 'file') self.assertEqual(data['owner'], pwd.getpwuid(os.geteuid()).pw_name) self.assertEqual(data['group'], grp.getgrgid(os.getegid()).gr_name) self.assertEqual(data['perms'], '0777') root.restat() self.assertEqual(data['ctime'], int(root.statinfo.st_ctime)) self.assertEqual(type(data['ctime']), int) self.assertEqual(data['mtime'], int(root.statinfo.st_mtime)) self.assertEqual(type(data['mtime']), int) self.assertEqual(data['atime'], int(root.statinfo.st_atime)) self.assertEqual(type(data['atime']), int) self.assertEqual(data['sha1'], sha1('the content').hexdigest()) self.assertEqual(data['size'], len('the content'))
def test_directory(self): """ A directory can exist """ root = FilePath(self.mktemp()) root.makedirs() root.chmod(0777) stdout, stderr, code = self.runScript(['inspect'], json.dumps({ 'kind': 'file', 'path': root.path, })) data = json.loads(stdout) self.assertEqual(data['kind'], 'file') self.assertEqual(data['path'], root.path) self.assertEqual(data['exists'], True) self.assertEqual(data['filetype'], 'dir') self.assertEqual(data['owner'], pwd.getpwuid(os.geteuid()).pw_name) self.assertEqual(data['group'], grp.getgrgid(os.getegid()).gr_name) self.assertEqual(data['perms'], '0777') root.restat() self.assertEqual(data['ctime'], int(root.statinfo.st_ctime)) self.assertEqual(type(data['ctime']), int) self.assertEqual(data['mtime'], int(root.statinfo.st_mtime)) self.assertEqual(type(data['mtime']), int) self.assertEqual(data['atime'], int(root.statinfo.st_atime)) self.assertEqual(type(data['atime']), int)
def test_permissions(self): """ The directory is created with restrictive permissions. """ path = FilePath(self.mktemp()) DockerPluginScript()._create_listening_directory(path) path.restat() self.assertEqual(path.getPermissions().shorthand(), "rwx------")
class ScheduledTask(object): """ Two ScheduledTask instances with same identifier are not permited to run concurrently. There should be no ScheduledTask queue waiting for the lock as SchedulerService ticks quite often. """ _time_format = "%Y-%m-%dT%H:%M:%SZ" schedule = None identifier = None def __init__(self, schedule=None, identifier=None, scheduler_directory=None): if scheduler_directory is None: scheduler_directory = config.scheduler_directory if schedule is not None: self.schedule = schedule if identifier is not None: self.identifier = identifier assert self.identifier is not None, "self.identifier must be set" assert self.schedule is not None, "self.schedule must be set" self._last_run = FilePath(scheduler_directory).child(self.identifier) self._last_run_lock = FileSystemlockAndMutex( FilePath(scheduler_directory).child(self.identifier + ".lock").path) def cancel(self): """ Cancel a currently running task. If it is locked, then release the lock. """ if self._last_run_lock.locked: self._last_run_lock.release() @property def should_run(self): current_time = datetime.utcnow().replace(tzinfo=tz.tzutc()) next_cycle = croniter(self.schedule, self.last_run).get_next(datetime) if next_cycle <= current_time: return True return False @property def last_run(self): self._last_run.restat(False) if not self._last_run.exists(): return CANARY_DATE with self._last_run.open('r') as in_file: date_str = in_file.read() return datetime.strptime(date_str, self._time_format).replace(tzinfo=tz.tzutc()) def _update_last_run(self, last_run_time): """ Update the time at which this task ran successfully last, by running to a file. """ with self._last_run.open('w') as out_file: out_file.write(last_run_time.strftime(self._time_format)) def task(self): raise NotImplementedError def first_run(self): """ This hook is called if it's the first time a particular scheduled operation is run. """ pass @defer.inlineCallbacks def run(self): if self._last_run_lock.locked: # do not allow the queue to grow forever raise DidNotRun yield self._last_run_lock.acquire() if not self.should_run: self._last_run_lock.release() raise DidNotRun try: if self.last_run == CANARY_DATE: log.debug("Detected first run") yield defer.maybeDeferred(self.first_run) last_run_time = datetime.utcnow() yield self.task() self._update_last_run(last_run_time) except: raise finally: self._last_run_lock.release()
class ScheduledTask(object): """ Two ScheduledTask instances with same identifier are not permited to run concurrently. There should be no ScheduledTask queue waiting for the lock as SchedulerService ticks quite often. """ _time_format = "%Y-%m-%dT%H:%M:%SZ" schedule = None identifier = None def __init__(self, schedule=None, identifier=None, scheduler_directory=None): if scheduler_directory is None: scheduler_directory = config.scheduler_directory if schedule is not None: self.schedule = schedule if identifier is not None: self.identifier = identifier assert self.identifier is not None, "self.identifier must be set" assert self.schedule is not None, "self.schedule must be set" # XXX: both _last_run_lock and _smear_coef require that there is single # instance of the ScheduledTask of each type identified by `identifier`. self._last_run = FilePath(scheduler_directory).child(self.identifier) self._last_run_lock = FileSystemlockAndMutex( FilePath(scheduler_directory).child(self.identifier + ".lock").path ) self._smear_coef = random.random() def cancel(self): """ Cancel a currently running task. If it is locked, then release the lock. """ if not self._last_run_lock.locked: # _last_run_lock.release() will throw if we try to release it log.err('BUG: cancelling non-locked task {} without holding lock'.format(self.identifier)) return # probably, cancelling the task TAKEN the lock is even worse :-) self._last_run_lock.release() @property def should_run(self): current_time = datetime.utcnow().replace(tzinfo=tz.tzutc()) next_cycle = croniter(self.schedule, self.last_run).get_next(datetime) delta = (croniter(self.schedule, next_cycle).get_next(datetime) - next_cycle).total_seconds() next_cycle = next_cycle + timedelta(seconds=delta * 0.1 * self._smear_coef) if next_cycle <= current_time: return True return False @property def last_run(self): self._last_run.restat(False) if not self._last_run.exists(): return CANARY_DATE with self._last_run.open('r') as in_file: date_str = in_file.read() return datetime.strptime(date_str, self._time_format).replace( tzinfo=tz.tzutc()) def _update_last_run(self, last_run_time): """ Update the time at which this task ran successfully last, by running to a file. """ with self._last_run.open('w') as out_file: out_file.write(last_run_time.strftime(self._time_format)) def task(self): raise NotImplementedError def first_run(self): """ This hook is called if it's the first time a particular scheduled operation is run. """ pass @defer.inlineCallbacks def run(self): if self._last_run_lock.locked: # do not allow the queue to grow forever raise DidNotRun yield self._last_run_lock.acquire() if not self.should_run: self._last_run_lock.release() raise DidNotRun try: if self.last_run == CANARY_DATE: log.debug("Detected first run") yield defer.maybeDeferred(self.first_run) last_run_time = datetime.utcnow() yield self.task() self._update_last_run(last_run_time) except: raise finally: self._last_run_lock.release()