Exemple #1
0
    def testTopLevelLockFile(self):
        """Try a simple process-upload run.

        Expect it to exit earlier due the occupied lockfile
        """
        # acquire the process-upload lockfile locally
        from contrib.glock import GlobalLock
        locker = GlobalLock('/var/lock/process-upload-insecure.lock')
        locker.acquire()

        returncode, out, err = self.runProcessUpload(
            extra_args=['-C', 'insecure'])

        # the process-upload call terminated with ERROR and
        # proper log message
        self.assertEqual(1, returncode)
        self.assert_(
            'INFO    Creating lockfile: '
            '/var/lock/process-upload-insecure.lock' in err.splitlines())
        self.assert_(
            'INFO    Lockfile /var/lock/process-upload-insecure.lock in use' in
            err.splitlines())

        # release the locally acquired lockfile
        locker.release()
Exemple #2
0
    def setup_lock(self):
        """Create lockfile.

        Note that this will create a lockfile even if you don't actually
        use it. GlobalLock.__del__ is meant to clean it up though.
        """
        self.lock = GlobalLock(self.lockfilepath, logger=self.logger)
Exemple #3
0
    def locateDirectories(self, fsroot):
        """Return a list of upload directories in a given queue.

        This method operates on the queue atomically, i.e. it suppresses
        changes in the queue directory, like new uploads, by acquiring
        the shared upload_queue lockfile while the directory are listed.

        :param fsroot: path to a 'queue' directory to be inspected.

        :return: a list of upload directories found in the queue
            alphabetically sorted.
        """
        # Protecting listdir by a lock ensures that we only get completely
        # finished directories listed. See lp.poppy.hooks for the other
        # locking place.
        lockfile_path = os.path.join(fsroot, ".lock")
        fsroot_lock = GlobalLock(lockfile_path)
        mode = stat.S_IMODE(os.stat(lockfile_path).st_mode)

        # XXX cprov 20081024 bug=185731: The lockfile permission can only be
        # changed by its owner. Since we can't predict which process will
        # create it in production systems we simply ignore errors when trying
        # to grant the right permission. At least, one of the process will
        # be able to do so.
        try:
            os.chmod(lockfile_path, mode | stat.S_IWGRP)
        except OSError as err:
            self.log.debug('Could not fix the lockfile permission: %s' % err)

        try:
            fsroot_lock.acquire(blocking=True)
            dir_names = os.listdir(fsroot)
        finally:
            # Skip lockfile deletion, see similar code in lp.poppy.hooks.
            fsroot_lock.release(skip_delete=True)

        sorted_dir_names = sorted(
            dir_name for dir_name in dir_names
            if os.path.isdir(os.path.join(fsroot, dir_name)))

        return sorted_dir_names
Exemple #4
0
    def client_done_hook(self, fsroot, host, port):
        """A client has completed. If it authenticated then it stands a chance
        of having uploaded a file to the set. If not; then it is simply an
        aborted transaction and we remove the fsroot."""

        if fsroot not in self.clients:
            raise PoppyInterfaceFailure("Unable to find fsroot in client set")

        self.logger.debug("Processing session complete in %s" % fsroot)

        client = self.clients[fsroot]
        if "distro" not in client:
            # Login username defines the distribution context of the upload.
            # So abort unauthenticated sessions by removing its contents
            shutil.rmtree(fsroot)
            return

        # Protect from race condition between creating the directory
        # and creating the distro file, and also in cases where the
        # temporary directory and the upload directory are not in the
        # same filesystem (non-atomic "rename").
        lockfile_path = os.path.join(self.targetpath, ".lock")
        self.lock = GlobalLock(lockfile_path)

        # XXX cprov 20071024 bug=156795: We try to acquire the lock as soon
        # as possible after creating the lockfile but are still open to
        # a race.
        self.lock.acquire(blocking=True)
        mode = stat.S_IMODE(os.stat(lockfile_path).st_mode)

        # XXX cprov 20081024 bug=185731: The lockfile permission can only be
        # changed by its owner. Since we can't predict which process will
        # create it in production systems we simply ignore errors when trying
        # to grant the right permission. At least, one of the process will
        # be able to do so.
        try:
            os.chmod(lockfile_path, mode | stat.S_IWGRP)
        except OSError:
            pass

        try:
            timestamp = time.strftime("%Y%m%d-%H%M%S")
            path = "upload%s-%s-%06d" % (self.prefix, timestamp,
                                         self.targetcount)
            target_fsroot = os.path.join(self.targetpath, path)

            # Create file to store the distro used.
            self.logger.debug("Upload was targetted at %s" % client["distro"])
            distro_filename = target_fsroot + ".distro"
            distro_file = open(distro_filename, "w")
            distro_file.write(client["distro"])
            distro_file.close()

            # Move the session directory to the target directory.
            if os.path.exists(target_fsroot):
                self.logger.warn("Targeted upload already present: %s" % path)
                self.logger.warn("System clock skewed ?")
            else:
                try:
                    shutil.move(fsroot, target_fsroot)
                except (OSError, IOError):
                    if not os.path.exists(target_fsroot):
                        raise

            # XXX cprov 20071024: We should replace os.system call by os.chmod
            # and fix the default permission value accordingly in poppy-upload
            if self.perms is not None:
                os.system("chmod %s -R %s" % (self.perms, target_fsroot))

            # Invoke processing script, if provided.
            if self.cmd:
                cmd = self.cmd
                cmd = cmd.replace("@fsroot@", target_fsroot)
                cmd = cmd.replace("@distro@", client["distro"])
                self.logger.debug("Running upload handler: %s" % cmd)
                os.system(cmd)
        finally:
            # We never delete the lockfile, this way the inode will be
            # constant while the machine is up. See comment on 'acquire'
            self.lock.release(skip_delete=True)

        self.clients.pop(fsroot)
        # This is mainly done so that tests know when the
        # post-processing hook has finished.
        self.logger.info(self.LOG_MAGIC)
 def lock(self):
     self.actualLock = GlobalLock(self.lockfilename)
     try:
         self.actualLock.acquire()
     except LockAlreadyAcquired:
         raise LockError(self.lockfilename)