Example #1
0
File: model.py Project: pieska/pulp
 def __init__(self, repo_id, details=None):
     """
     :param repo_id: The repository ID.
     :type repo_id: str
     :param details: The repositories details.
     :type details: dict
     """
     Repository.__init__(self, repo_id, details)
     self.poller = TaskPoller(self.binding)
Example #2
0
File: model.py Project: pieska/pulp
class LocalRepository(Local, Repository):
    """
    Represents a repository associated with the local inventory.
    :ivar poller: A task poller used to poll for tasks status and progress.
    :type poller: TaskPoller
    """

    @classmethod
    def fetch_all(cls):
        """
        Fetch all repositories from the local inventory.
        :return: A list of: LocalRepository
        :rtype: list
        """
        all = []
        for repo in cls.binding.repo_search.search():
            repo_id = repo['id']
            details = {
                'repository':repo,
                'distributors':[]
            }
            r = cls(repo_id, details)
            all.append(r)
        return all

    @classmethod
    def fetch(cls, repo_id):
        """
        Fetch a specific repository from the local inventory.
        :param repo_id: Repository ID.
        :type repo_id: str
        :return: The fetched repository.
        :rtype: LocalRepository
        """
        details = {}
        try:
            http = cls.binding.repo.repository(repo_id)
            details['repository'] = http.response_body
            http = cls.binding.repo_distributor.distributors(repo_id)
            details['distributors'] = http.response_body
            http = cls.binding.repo_importer.importers(repo_id)
            details['importers'] = http.response_body
            return cls(repo_id, details)
        except NotFoundException:
            return None

    @classmethod
    def purge_orphans(cls):
        """
        Purge orphaned units within the local inventory.
        """
        http = cls.binding.content_orphan.remove_all()
        if http.response_code != httplib.ACCEPTED:
            raise ModelError('purge_orphans() failed:%d', http.response_code)

    def __init__(self, repo_id, details=None):
        """
        :param repo_id: The repository ID.
        :type repo_id: str
        :param details: The repositories details.
        :type details: dict
        """
        Repository.__init__(self, repo_id, details)
        self.poller = TaskPoller(self.binding)

    def add(self):
        """
        Add the local repository and associated plugins..
        """
        # repository
        self.binding.repo.create(
            self.repo_id,
            self.basic_properties['display_name'],
            self.basic_properties['description'],
            self.basic_properties['notes'])
        # distributors
        for details in self.distributors:
            dist_id = details['id']
            dist = LocalDistributor(self.repo_id, dist_id, details)
            dist.add()
        # importers
        for details in self.importers:
            imp_id = details['id']
            importer = LocalImporter(self.repo_id, imp_id, details)
            importer.add()
        log.info('Repository: %s, added', self.repo_id)

    def update(self, delta):
        """
        Update this local repository.
        :param delta: The properties that need to be updated.
        :type delta: dict
        """
        self.binding.repo.update(self.repo_id, delta)
        log.info('Repository: %s, updated', self.repo_id)

    def delete(self):
        """
        Delete the local repository.
        """
        self.binding.repo.delete(self.repo_id)
        log.info('Repository: %s, deleted', self.repo_id)

    def merge(self, remote):
        """
        Merge remote repositories.
          1. Determine the delta and update the repository properties.
          2. Merge importers
          3. Merge distributors
        :param remote: The remote repository.
        :type remote: RemoteRepository
        """
        delta = {}
        for k,v in remote.basic_properties.items():
            if self.basic_properties.get(k) != v:
                self.basic_properties[k] = v
                delta[k] = v
        if delta:
            self.update(delta)
        self.merge_importers(remote)
        self.merge_distributors(remote)

    def merge_importers(self, remote):
        """
        Merge importers.
          - Delete importers associated to this local repository but not
            associated with the remote repository.
          - Merge importers associated with this local repository AND associated
            with remote repository.
          - Add importers associated with the remote repository but NOT associated
            with this local repository.
        :param remote: The remote repository.
        :type remote: RemoteRepository
        """
        self.delete_importers(remote)
        for details in remote.importers:
            imp_id = details['id']
            imp = Importer(self.repo_id, imp_id, details)
            myimp = LocalImporter.fetch(self.repo_id, imp_id)
            if myimp:
                myimp.merge(imp)
            else:
                myimp = LocalImporter(self.repo_id, imp_id, details)
                myimp.add()

    def delete_importers(self, remote):
        """
        Delete importers associated with this local repository but not
        associated with the remote repository.
        :param remote: The remote repository.
        :type remote: RemoteRepository
        """
        remote_ids = [d['id'] for d in remote.importers]
        for details in self.importers:
            imp_id = details['id']
            if imp_id not in remote_ids:
                imp = LocalImporter(self.repo_id, imp_id)
                imp.delete()

    def merge_distributors(self, remote):
        """
        Merge distributors.
          - Delete distributors associated to this local repository but not
            associated with the remote repository.
          - Merge distributors associated with this local repository AND
            associated with remote repository.
          - Add distributors associated with the remote repository but NOT
            associated with this local repository.
        :param remote: The remote repository.
        :type remote: RemoteRepository
        """
        self.delete_distributors(remote)
        for details in remote.distributors:
            dist_id = details['id']
            dist = Distributor(self.repo_id, dist_id, details)
            mydist = LocalDistributor.fetch(self.repo_id, dist_id)
            if mydist:
                mydist.merge(dist)
            else:
                mydist = LocalDistributor(self.repo_id, dist_id, details)
                mydist.add()

    def delete_distributors(self, remote):
        """
        Delete distributors associated with this local repository but not
        associated with the remote repository.
        :param remote: The remote repository.
        :type remote: RemoteRepository
        """
        remote_ids = [d['id'] for d in remote.distributors]
        for details in self.distributors:
            dist_id = details['id']
            if dist_id not in remote_ids:
                dist = LocalDistributor(self.repo_id, dist_id)
                dist.delete()

    def run_synchronization(self, progress, strategy):
        """
        Run a repo_sync() on this local repository.
        :param progress: A progress report.
        :type progress: pulp_citrus.progress.ProgressReport
        :return: The task result.
        """
        conf = dict(strategy=strategy)
        http = self.binding.repo_actions.sync(self.repo_id, conf)
        if http.response_code == httplib.ACCEPTED:
            task = http.response_body[0]
            return self.poller.join(task.task_id, progress)
        else:
            raise ModelError('synchronization failed: http=%d', http.response_code)

    def cancel_synchronization(self):
        """
        Cancel running synchronization.
        """
        self.poller.abort()