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)
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()