Пример #1
0
    def feed(self):
        """(Greedy) Returns this FeedTask's feed (list of wrappers).

        The first access of this property triggers a GET of the feed if it has
        not already been fetched, so use this only if you need the
        EntryWrappers outside of the execution itself.
        """
        if self._feed is None:
            self._feed = self._getter.get()
        if len(self._feed) == 0:
            raise ex.FeedTaskEmptyFeed()
        # Do we need to refresh the feed based on having been run?
        # If we haven't replicated WrapperTasks yet, there's no chance we're
        # out of sync - and we don't want to trigger GET/replication.
        if self._tx_by_uuid:
            # Rebuild the entire feed from the WrapperTasks' .wrappers.
            # TAG_WRAPPER_SYNC
            # Note that, if this happens while the WrapperTasks are running,
            # we may be grabbing the wrapper from a WrapperTask "while" it is
            # being changed as the result of an update(). This is threadsafe as
            # long as the assignment (by WrapperTask.execute) and the accessor
            # (WrapperTask.wrapper) remain atomic by using simple =/return.
            for wrap in self._feed:
                if self.get_wrapper(wrap.uuid).etag != wrap.etag:
                    # Refresh needed
                    self._feed = [tx.wrapper for tx in
                                  self.wrapper_tasks.values()]
                    break
        return self._feed
Пример #2
0
    def __init__(self,
                 name,
                 feed_or_getter,
                 max_workers=10,
                 update_timeout=-1):
        """Create a FeedTask with a FeedGetter (preferred) or existing feed.

        :param name: A descriptive string name.  This will be used along with
                     each wrapper's UUID to generate the name for that
                     wrapper's WrapperTask.
        :param feed_or_getter: pypowervm.wrappers.entry_wrapper.FeedGetter or
                               an already-fetched feed (list of EntryWrappers)
                               over which to operate.
        :param max_workers: (Optional) Integer indicating the maximum number of
                            worker threads to run in parallel within the .flow
                            or by the .execute method. See
                            concurrent.futures.ThreadPoolExecutor(max_workers).
        :param update_timeout: (Optional) Integer number of seconds after which
                               to time each WrapperTask's POST request.  -1,
                               the default, causes the request to use the
                               timeout value configured on the Session
                               belonging to the Adapter.
        """
        super(FeedTask, self).__init__(name)
        if isinstance(feed_or_getter, ewrap.FeedGetter):
            self._feed = None
            self._getter = feed_or_getter
        elif isinstance(feed_or_getter, list):
            # Make sure the feed has something in it.
            if len(feed_or_getter) == 0:
                raise ex.FeedTaskEmptyFeed()
            # Make sure it's a list of EntryWrapper
            if [
                    i for i in feed_or_getter
                    if not isinstance(i, ewrap.EntryWrapper)
            ]:
                raise ValueError("List must contain EntryWrappers "
                                 "exclusively.")
            self._feed = feed_or_getter
            self._getter = None
        else:
            raise ValueError(
                _("Must supply either a list of EntryWrappers or "
                  "a FeedGetter."))
        # Max WrapperTasks to run in parallel
        self.max_workers = max_workers
        self.update_timeout = update_timeout
        # Map of {uuid: WrapperTask}.  We keep this empty until we need the
        # individual WraperTasks.  This is triggered by .wrapper_tasks and
        # .get_wrapper(uuid) (and obviously executing).
        self._tx_by_uuid = {}
        # Until we *need* individual WrapperTasks, save subtasks in one place.
        # EntryWrapperGetter is a cheat to allow us to build the WrapperTask.
        self._common_tx = WrapperTask(
            'internal', ewrap.EntryWrapperGetter(None, ewrap.Wrapper, None))
        self._post_exec = []