Пример #1
0
    def take_snapshot(self, snapshot_id=None, include_list=None, exclude_list=None, snapshot_kwargs=None):
        if include_list:
            self.snapshots.add(include_list)
        if exclude_list:
            for item in exclude_list:
                self.snapshots.remove(item)
        if not snapshot_id:
            snapshot_id = get_ion_ts()
        if not snapshot_kwargs:
            snapshot_kwargs = {}

        self.snapshot["snapshot_ts_begin"] = get_ion_ts()
        self.snapshot["snapshot_list"] = self.snapshots
        for snap in self.snapshots:
            snap_func = "_snap_%s" % snap
            func = getattr(self, snap_func, None)
            if func:
                try:
                    snap_result = func(**snapshot_kwargs)
                except Exception as ex:
                    log.warn("Could not take snapshot %s: %s" % (snap, str(ex)))
                self.snapshot[snap] = snap_result
            else:
                log.warn("Snapshot function %s undefined" % snap_func)

        self.snap_ts = get_ion_ts()
        self.snapshot["snapshot_ts"] = self.snap_ts
        self.snapshot["snapshot_id"] = snapshot_id
    def cache_resources(self, resource_type, specific_ids=None):
        """
        Save all resources of a given type to memory, for in-memory lookup ops

        This is a PREFETCH operation, and EnhancedResourceRegistryClient objects that use the cache functionality
        should NOT be kept across service calls.
        """
        #log.info("Caching resources: %s", resource_type)
        #log.debug("This cache is %s", self)
        time_caching_start = get_ion_ts()

        resource_objs = []
        if specific_ids is None:
            resource_objs, _ = self.RR.find_resources(restype=resource_type, id_only=False)
        else:
            assert type(specific_ids) is list
            if specific_ids:
                resource_objs = self.RR.read_mult(specific_ids)

        lookups = DotDict()
        lookups.by_id =   {}
        lookups.by_name = {}
        self._cached_resources[resource_type] = lookups

        for r in resource_objs:
            self._add_resource_to_cache(resource_type, r)

        time_caching_stop = get_ion_ts()

        total_time = int(time_caching_stop) - int(time_caching_start)
Пример #3
0
    def test_get_valid_resource_commitment(self):
        from pyon.util.containers import get_ion_ts

        # create ION org and an actor
        ion_org = IonObject(RT.Org, name='ION')
        ion_org_id, _ = self.rr.create(ion_org)
        ion_org._id = ion_org_id
        actor = IonObject(RT.ActorIdentity, name='actor1')
        actor_id, _ = self.rr.create(actor)

        # create an expired commitment in the org
        ts = int(get_ion_ts()) - 50000
        com_obj = IonObject(RT.Commitment, provider=ion_org_id, consumer=actor_id, commitment=True, expiration=ts)
        com_id, _ = self.rr.create(com_obj)
        id = self.rr.create_association(ion_org_id, PRED.hasCommitment, com_id)
        c = get_valid_resource_commitments(ion_org_id, actor_id)
        #verify that the commitment is not returned
        self.assertIsNone(c)

        # create a commitment that has not expired yet
        ts = int(get_ion_ts()) + 50000
        com_obj = IonObject(RT.Commitment, provider=ion_org_id, consumer=actor_id, commitment=True, expiration=ts)
        com_id, _ = self.rr.create(com_obj)
        id = self.rr.create_association(ion_org_id, PRED.hasCommitment, com_id)
        c = get_valid_resource_commitments(ion_org_id, actor_id)

        #verify that the commitment is returned
        self.assertIsNotNone(c)
Пример #4
0
 def _create_dir_entry(self, object_id,  parent, key, attributes=None, ts_created='', ts_updated=''):
     doc = {}
     doc['_id'] = object_id
     doc['type_'] = 'DirEntry'
     doc['attributes'] = attributes or {}
     doc['key'] = key
     doc['parent'] = parent
     doc['ts_created'] = ts_created or get_ion_ts()
     doc['ts_updated'] = ts_updated or get_ion_ts()
     return doc
Пример #5
0
 def _create_dir_entry(self, object_id, parent, key, attributes=None, ts_created="", ts_updated=""):
     doc = {}
     doc["_id"] = object_id
     doc["type_"] = "DirEntry"
     doc["attributes"] = attributes or {}
     doc["key"] = key
     doc["parent"] = parent if parent else "/"
     doc["org"] = self.orgname
     doc["ts_created"] = ts_created or get_ion_ts()
     doc["ts_updated"] = ts_updated or get_ion_ts()
     return doc
Пример #6
0
Файл: state.py Проект: daf/pyon
 def put_state(self, key, state):
     log.debug("Store persistent state for key=%s" % key)
     if not isinstance(state, dict):
         raise BadRequest("state must be type dict, not %s" % type(state))
     try:
         state_obj = self.state_store.read(key)
         state_obj.state = state
         state_obj.ts = get_ion_ts()
         self.state_store.update(state_obj)
     except NotFound as nf:
         state_obj = ProcessState(state=state, ts=get_ion_ts())
         self.state_store.create(state_obj, object_id=key)
Пример #7
0
    def heartbeat(self):
        """
        Returns a tuple indicating everything is ok.

        Should only be called after the process has been started.
        Checks the following:
            - All attached endpoints are alive + listening (this means ready)
            - The control flow greenlet is alive + listening or processing

        @return 3-tuple indicating (listeners ok, ctrl thread ok, heartbeat status). Use all on it for a
                boolean indication of success.
        """
        listeners_ok = True
        for l in self.listeners:
            if not (l in self._listener_map and not self._listener_map[l].proc.dead and l.get_ready_event().is_set()):
                listeners_ok = False

        ctrl_thread_ok = self._ctrl_thread.running

        # are we currently processing something?
        heartbeat_ok = True
        if self._ctrl_current is not None:
            st = traceback.extract_stack(self._ctrl_thread.proc.gr_frame)

            if self._ctrl_current == self._heartbeat_op:

                if st == self._heartbeat_stack:
                    self._heartbeat_count += 1  # we've seen this before! increment count

                    # we've been in this for the last X ticks, or it's been X seconds, fail this part of the heartbeat
                    if (
                        self._heartbeat_count > CFG.get_safe("cc.timeout.heartbeat_proc_count_threshold", 30)
                        or int(get_ion_ts()) - int(self._heartbeat_time)
                        >= CFG.get_safe("cc.timeout.heartbeat_proc_time_threshold", 30) * 1000
                    ):
                        heartbeat_ok = False
                else:
                    # it's made some progress
                    self._heartbeat_count = 1
                    self._heartbeat_stack = st
                    self._heartbeat_time = get_ion_ts()
            else:
                self._heartbeat_op = self._ctrl_current
                self._heartbeat_count = 1
                self._heartbeat_time = get_ion_ts()
                self._heartbeat_stack = st

        else:
            self._heartbeat_op = None
            self._heartbeat_count = 0

        return (listeners_ok, ctrl_thread_ok, heartbeat_ok)
Пример #8
0
    def heartbeat(self):
        """
        Returns a 3-tuple indicating everything is ok.

        Should only be called after the process has been started.
        Checks the following:
            - All attached endpoints are alive + listening (this means ready)
            - The control flow greenlet is alive + listening or processing

        @return 3-tuple indicating (listeners ok, ctrl thread ok, heartbeat status). Use all on it for a
                boolean indication of success.
        """
        listeners_ok = True
        for l in self.listeners:
            if not (l in self._listener_map
                    and not self._listener_map[l].proc.dead
                    and l.get_ready_event().is_set()):
                listeners_ok = False

        ctrl_thread_ok = self._ctrl_thread.running

        # are we currently processing something?
        heartbeat_ok = True
        if self._ctrl_current is not None:
            st = traceback.extract_stack(self._ctrl_thread.proc.gr_frame)

            if self._ctrl_current == self._heartbeat_op:

                if st == self._heartbeat_stack:
                    self._heartbeat_count += 1  # we've seen this before! increment count

                    # we've been in this for the last X ticks, or it's been X seconds, fail this part of the heartbeat
                    if self._heartbeat_count > CFG.get_safe('container.timeout.heartbeat_proc_count_threshold', 30) or \
                       get_ion_ts_millis() - int(self._heartbeat_time) >= CFG.get_safe('container.timeout.heartbeat_proc_time_threshold', 30) * 1000:
                        heartbeat_ok = False
                else:
                    # it's made some progress
                    self._heartbeat_count = 1
                    self._heartbeat_stack = st
                    self._heartbeat_time = get_ion_ts()
            else:
                self._heartbeat_op = self._ctrl_current
                self._heartbeat_count = 1
                self._heartbeat_time = get_ion_ts()
                self._heartbeat_stack = st

        else:
            self._heartbeat_op = None
            self._heartbeat_count = 0

        #log.debug("%s %s %s", listeners_ok, ctrl_thread_ok, heartbeat_ok)
        return (listeners_ok, ctrl_thread_ok, heartbeat_ok)
Пример #9
0
    def _update_cached_resources(self):
        # cache some resources for in-memory lookups
        rsrcs = self._resources_to_cache()
        log.debug("updating cached resources: %s" % rsrcs)
        time_caching_start = get_ion_ts()
        for r in rsrcs:
            log.debug(" - %s", r)
            self.RR2.cache_resources(r)
        time_caching_stop = get_ion_ts()

        total_time = int(time_caching_stop) - int(time_caching_start)

        log.info("Cached %s resource types in %s seconds", len(rsrcs), total_time / 1000.0)
Пример #10
0
    def _update_cached_predicates(self):
        # cache some predicates for in-memory lookups
        preds = self._predicates_to_cache()
        log.debug("updating cached predicates: %s" % preds)
        time_caching_start = get_ion_ts()
        for pred in preds:
            log.debug(" - %s", pred)
            self.RR2.cache_predicate(pred)
        time_caching_stop = get_ion_ts()

        total_time = int(time_caching_stop) - int(time_caching_start)

        log.info("Cached %s predicates in %s seconds", len(preds), total_time / 1000.0)
Пример #11
0
    def test_pub_and_sub(self):
        ar = event.AsyncResult()
        gq = queue.Queue()
        self.count = 0

        def cb(*args, **kwargs):
            self.count += 1
            gq.put(args[0])
            if self.count == 2:
                ar.set()

        sub = EventSubscriber(event_type="ResourceEvent", callback=cb, origin="specific")
        pub = EventPublisher(event_type="ResourceEvent")

        self._listen(sub)
        pub.publish_event(origin="specific", description="hello")

        event_obj = bootstrap.IonObject('ResourceEvent', origin='specific', description='more testing')
        self.assertEqual(event_obj, pub.publish_event_object(event_obj))

        with self.assertRaises(BadRequest) as cm:
            event_obj = bootstrap.IonObject('ResourceEvent', origin='specific', description='more testing', ts_created='2423')
            pub.publish_event_object(event_obj)
        self.assertIn( 'The ts_created value is not a valid timestamp',cm.exception.message)

        with self.assertRaises(BadRequest) as cm:
            event_obj = bootstrap.IonObject('ResourceEvent', origin='specific', description='more testing', ts_created='1000494978462')
            pub.publish_event_object(event_obj)
        self.assertIn( 'This ts_created value is too old',cm.exception.message)

        with self.assertRaises(BadRequest) as cm:
            event_obj = bootstrap.IonObject('ResourceEvent', origin='specific', description='more testing')
            event_obj._id = '343434'
            pub.publish_event_object(event_obj)
        self.assertIn( 'The event object cannot contain a _id field',cm.exception.message)

        ar.get(timeout=5)

        res = []
        for x in xrange(self.count):
            res.append(gq.get(timeout=5))

        self.assertEquals(len(res), self.count)
        self.assertEquals(res[0].description, "hello")
        self.assertAlmostEquals(int(res[0].ts_created), int(get_ion_ts()), delta=5000)

        self.assertEquals(res[1].description, "more testing")
        self.assertAlmostEquals(int(res[1].ts_created), int(get_ion_ts()), delta=5000)
Пример #12
0
    def get_resource_commitments(self, actor_id, resource_id):

        log.debug("Finding commitments for actor_id: %s and resource_id: %s" %
                  (actor_id, resource_id))

        try:

            commitments, _ = self._rr.find_objects(resource_id,
                                                   PRED.hasCommitment,
                                                   RT.Commitment)
            if not commitments:
                return None

            cur_time = int(get_ion_ts())
            commitment_list = []
            for com in commitments:  #TODO - update when Retired is removed from find_objects
                if com.consumer == actor_id and com.lcstate != LCS.RETIRED and ( com.expiration == 0 or \
                ( com.expiration > 0 and cur_time < com.expiration)):
                    commitment_list.append(com)

            if commitment_list:
                return commitment_list

        except Exception, e:
            log.error(e)
Пример #13
0
def get_resource_commitments(actor_id, resource_id):
    '''
    Returns the list of commitments for the specified user and resource
    @param actor_id:
    @param resource_id:
    @return:
    '''
    log.debug("Finding commitments for actor_id: %s and resource_id: %s" % (actor_id, resource_id))

    try:
        gov_controller = bootstrap.container_instance.governance_controller
        commitments,_ = gov_controller.rr.find_objects(resource_id, PRED.hasCommitment, RT.Commitment)
        if not commitments:
            return None

        cur_time = int(get_ion_ts())
        commitment_list = []
        for com in commitments:  #TODO - update when Retired is removed from find_objects
            if com.consumer == actor_id and com.lcstate != LCS.RETIRED and ( com.expiration == 0 or\
                                                                             ( com.expiration > 0 and cur_time < com.expiration)):
                commitment_list.append(com)

        if commitment_list:
            return commitment_list

    except Exception, e:
        log.error(e)
Пример #14
0
    def log_scope_call(scope, log_entry, include_stack=True, stack_first_frame=4):
        try:
            if not trace_data["config"].get("enabled", False):
                return

            log_entry["scope"] = scope
            if not "ts" in log_entry:
                log_entry["ts"] = get_ion_ts()
            trace_data["scope_seq"][scope] += 1
            log_entry["seq"] = trace_data["scope_seq"][scope]

            if include_stack:
                stack = inspect.stack()
                frame_num = stack_first_frame
                context = []
                while len(stack) > frame_num and frame_num < 15:
                    exec_line = "%s:%s:%s" % (stack[frame_num][1], stack[frame_num][2], stack[frame_num][3])
                    context.insert(0, exec_line)
                    if exec_line.endswith("_control_flow") or exec_line.endswith("load_ion") or exec_line.endswith("spawn_process")\
                        or exec_line.endswith(":main") or exec_line.endswith(":dispatch_request"):
                        break
                    frame_num += 1
                log_entry["stack"] = context

            trace_data["trace_log"].append(log_entry)
            if len(trace_data["trace_log"]) > trace_data["config"].get("max_entries", DEFAULT_CONFIG["max_entries"]) + 100:
                trace_data["trace_log"] = trace_data["trace_log"][-trace_data["config"].get("max_entries", DEFAULT_CONFIG["max_entries"]):]

            CallTracer.log_trace(log_entry)
        except Exception as ex:
            log.warn("Count not log trace call: %s", log_entry)
Пример #15
0
    def register(self, parent, key, create_only=False, **kwargs):
        """
        Add/replace an entry within directory, below a parent node or "/".
        Note: Replaces (not merges) the attribute values of the entry if existing
        @param create_only  If True, does not change an existing entry
        @retval  DirEntry if previously existing
        """
        if not (parent and key):
            raise BadRequest("Illegal arguments")
        if not type(parent) is str or not parent.startswith("/"):
            raise BadRequest("Illegal arguments: parent")

        dn = self._get_path(parent, key)
        log.debug("Directory.register(%s): %s", dn, kwargs)

        entry_old = None
        cur_time = get_ion_ts()
        # Must read existing entry by path to make sure to not create path twice
        direntry = self._read_by_path(dn)
        if direntry and create_only:
            # We only wanted to make sure entry exists. Do not change
            return direntry
        elif direntry:
            entry_old = direntry.attributes
            direntry.attributes = kwargs
            direntry.ts_updated = cur_time
            # TODO: This may fail because of concurrent update
            self.dir_store.update(direntry)
        else:
            direntry = self._create_dir_entry(parent, key, attributes=kwargs, ts=cur_time)
            self._ensure_parents_exist([direntry])
            self.dir_store.create(direntry, create_unique_directory_id())

        return entry_old
Пример #16
0
    def retire(self, resource_id):
        """
        This is the official "delete" for resource objects: they are set to RETIRED lcstate.
        All associations are set to retired as well.
        """
        res_obj = self.read(resource_id)
        old_state = res_obj.lcstate
        old_availability = res_obj.availability
        if old_state == LCS.RETIRED:
            raise BadRequest("Resource id=%s already RETIRED" % (resource_id))

        res_obj.lcstate = LCS.RETIRED
        res_obj.availability = AS.PRIVATE
        res_obj.ts_updated = get_ion_ts()

        updres = self.rr_store.update(res_obj)
        log.debug("retire(res_id=%s). Change %s_%s to %s_%s", resource_id,
                  old_state, old_availability, res_obj.lcstate, res_obj.availability)

        assocs = self.find_associations(anyside=resource_id, id_only=False)
        for assoc in assocs:
            assoc.retired = True
        if assocs:
            self.rr_store.update_mult(assocs)
            log.debug("retire(res_id=%s). Retired %s associations", resource_id, len(assocs))

        if self.container.has_capability(self.container.CCAP.EVENT_PUBLISHER):
            self.event_pub.publish_event(event_type="ResourceLifecycleEvent",
                                     origin=res_obj._id, origin_type=res_obj.type_,
                                     sub_type="%s.%s" % (res_obj.lcstate, res_obj.availability),
                                     lcstate=res_obj.lcstate, availability=res_obj.availability,
                                     lcstate_before=old_state, availability_before=old_availability)
Пример #17
0
    def _execute(self, cprefix, command):
        if not command:
            raise iex.BadRequest("execute argument 'command' not present")
        if not command.command:
            raise iex.BadRequest("command not set")

        cmd_res = IonObject("AgentCommandResult", command_id=command.command_id, command=command.command)
        cmd_func = getattr(self, cprefix + str(command.command), None)
        if cmd_func:
            cmd_res.ts_execute = get_ion_ts()
            try:
                res = cmd_func(*command.args, **command.kwargs)
                cmd_res.status = 0
                cmd_res.result = res
            except Exception as ex:
                # TODO: Distinguish application vs. uncaught exception
                cmd_res.status = getattr(ex, 'status_code', -1)
                cmd_res.result = str(ex)
                log.info("Agent function failed with ex=%s msg=%s" % (type(ex), str(ex)))
        else:
            log.info("Agent command not supported: %s" % (command.command))
            ex = iex.NotFound("Command not supported: %s" % command.command)
            cmd_res.status = iex.NotFound.status_code
            cmd_res.result = str(ex)
        return cmd_res
Пример #18
0
    def create_extended_resource_container(self, extended_resource_type, resource_id, computed_resource_type=None,
                                           ext_associations=None, ext_exclude=None):

        if not self.service_provider or not self.resource_registry:
            raise Inconsistent("This class is not initialized properly")

        if extended_resource_type not in getextends(OT.ResourceContainer):
            raise BadRequest('Requested resource %s is not extended from %s' % ( extended_resource_type, OT.ResourceContainer) )

        if computed_resource_type and computed_resource_type not in getextends(OT.ComputedAttributes):
            raise BadRequest('Requested resource %s is not extended from %s' % ( computed_resource_type, OT.ComputedAttributes) )

        resource_object = self.resource_registry.read(resource_id)
        if not resource_object:
            raise NotFound("Resource %s does not exist" % resource_id)

        res_container = IonObject(extended_resource_type)
        res_container._id = resource_object._id
        res_container.resource = resource_object

        self.set_container_field_values(res_container, ext_exclude)

        self.set_computed_attributes(res_container, computed_resource_type, ext_exclude)

        self.set_extended_associations(res_container, ext_associations, ext_exclude)

        res_container.ts_created = get_ion_ts()

        return res_container
Пример #19
0
    def _execute(self, cprefix, command):
        if not command:
            raise iex.BadRequest("execute argument 'command' not present")
        if not command.command:
            raise iex.BadRequest("command not set")

        cmd_res = IonObject("AgentCommandResult", command_id=command.command_id, command=command.command)
        cmd_func = getattr(self, cprefix + str(command.command), None)
        if cmd_func:
            cmd_res.ts_execute = get_ion_ts()
            try:
                res = cmd_func(*command.args, **command.kwargs)
                cmd_res.status = 0
                cmd_res.result = res
            except iex.IonException as ex:
                # TODO: Distinguish application vs. uncaught exception
                cmd_res.status = getattr(ex, 'status_code', -1)
                cmd_res.result = str(ex)
                log.warn("Agent command %s failed with trace=%s" % (command.command, traceback.format_exc()))
        else:
            log.info("Agent command not supported: %s" % (command.command))
            ex = iex.NotFound("Command not supported: %s" % command.command)
            cmd_res.status = iex.NotFound.status_code
            cmd_res.result = str(ex)

        sub_type = "%s.%s" % (command.command, cmd_res.status)
        post_event = self._event_publisher._create_event(event_type=self.COMMAND_EVENT_TYPE,
                                origin=self.resource_id, origin_type=self.ORIGIN_TYPE,
                                sub_type=sub_type, command=command, result=cmd_res)
        post_event = self._post_execute_event_hook(post_event)
        success = self._event_publisher._publish_event(post_event, origin=post_event.origin)

        return cmd_res
Пример #20
0
    def register(self, parent, key, create_only=False, **kwargs):
        """
        Add/replace an entry within directory, below a parent node or "/".
        Note: Replaces (not merges) the attribute values of the entry if existing
        @param create_only  If True, does not change an existing entry
        @retval  DirEntry if previously existing
        """
        if not (parent and key):
            raise BadRequest("Illegal arguments")
        if not type(parent) is str or not parent.startswith("/"):
            raise BadRequest("Illegal arguments: parent")

        dn = self._get_path(parent, key)
        log.debug("Directory.register(%s): %s", dn, kwargs)

        entry_old = None
        cur_time = get_ion_ts()
        # Must read existing entry by path to make sure to not create path twice
        direntry = self._read_by_path(dn)
        if direntry and create_only:
            # We only wanted to make sure entry exists. Do not change
            return direntry
        elif direntry:
            entry_old = direntry.attributes
            direntry.attributes = kwargs
            direntry.ts_updated = cur_time
            # TODO: This may fail because of concurrent update
            self.dir_store.update(direntry)
        else:
            direntry = self._create_dir_entry(parent, key, attributes=kwargs, ts=cur_time)
            self.dir_store.create(direntry, create_unique_directory_id())

        return entry_old
Пример #21
0
    def register(self, parent, key, create_only=False, **kwargs):
        """
        Add/replace an entry within directory, below a parent node or "/".
        Note: Replaces (not merges) the attribute values of the entry if existing
        @retval  DirEntry if previously existing
        """
        if not (parent and key):
            raise BadRequest("Illegal arguments")
        if not type(parent) is str or not parent.startswith("/"):
            raise BadRequest("Illegal arguments: parent")

        dn = self._get_path(parent, key)

        entry_old = None
        direntry = self._read_by_path(dn)
        cur_time = get_ion_ts()

        if direntry and create_only:
            # We only wanted to make sure entry exists. Do not change
            return direntry
        elif direntry:
            # Change existing entry's attributes
            entry_old = direntry.get('attributes')
            direntry['attributes'] = kwargs
            direntry['ts_updated'] = cur_time
            self.datastore.update_doc(direntry)
        else:
            doc = self._create_dir_entry(object_id=create_unique_directory_id(), parent=parent, key=key,
                attributes=kwargs)
            self.datastore.create_doc(doc)

        return entry_old
Пример #22
0
    def sample_other_op(self, foo='bar', num=84, name=''):
        """We overload this YML service operation to do what we need to do"""
        if name == "setstate":
            log.info("StatefulTestProcess OP, state=%s", foo)
            newstate = foo
            oldstate = self._get_state("statevalue") or ""
            self._set_state("statevalue", newstate)
            self._set_state("statets", get_ion_ts())
            return oldstate
        elif name == "concurrent":
            self.error = False
            def worker(num):
                try:
                    for i in xrange(10):
                        value = uuid.uuid4().hex
                        self._set_state("state"+str(num), value)
                        log.debug("Flushing state %s of greenlet %s", i, num)
                        self._flush_state()
                        gevent.sleep(0.1)
                except Exception as ex:
                    log.exception("Error in worker")
                    self.error = True

            greenlets = [gevent.spawn(worker, i) for i in xrange(3)]
            gevent.joinall(greenlets)

            if self.error:
                raise Exception("Error in greenlets")
            return "GOOD"
        elif name == "getstate":
            return self._get_state("statevalue")
        else:
            raise Exception("Unknown mode: %s" % name)
    def execute_resource(self, resource_id='', command=None):
        """Execute command on the resource represented by agent.
        @param resource_id The id of the resource agennt.
        @param command An AgentCommand containing the command.
        @retval result An AgentCommandResult containing the result.
        @throws BadRequest if the command was malformed.
        @throws NotFound if the command is not available in current state.
        @throws ResourceError if the resource produced an error during execution.

        @param resource_id    str
        @param command    AgentCommand
        @retval result    AgentCommandResult
        @throws BadRequest    if the command was malformed.
        @throws NotFound    if the command is not implemented in the agent.
        @throws ResourceError    if the resource produced an error.
        """
        res_type = self._get_resource_type(resource_id)
        if self._has_agent(res_type):
            rac = ResourceAgentClient(resource_id=resource_id)
            return rac.execute_resource(resource_id=resource_id, command=command)

        cmd_res = None
        res_interface = self._get_type_interface(res_type)

        target = get_safe(res_interface, "commands.%s.execute" % command.command, None)
        if target:
            res = self._call_execute(target, resource_id, res_type, command.args, command.kwargs)
            cmd_res = AgentCommandResult(command_id=command.command_id,
                command=command.command,
                ts_execute=get_ion_ts(),
                status=0)
        else:
            log.warn("execute_resource(): command %s not defined", command.command)

        return cmd_res
Пример #24
0
    def _do_get_exclusive_access(self, instrument_id, resource_id):
        """
        Gets exclusive access to a given resource.

        @return  commitment_id
        """
        # TODO Needs review

        from interface.objects import NegotiationTypeEnum
        neg_type = NegotiationTypeEnum.INVITATION
        neg_obj = IonObject(RT.Negotiation, negotiation_type=neg_type)
        negotiation_id, _ = self.RR.create(neg_obj)

        # TODO determine appropriate expiration. Could it be without expiration
        # given that the exclusive access will be removed explicitly upon
        # termination (normal or abnormal) of the the mission?
        expiration = int(get_ion_ts()) + 20 * 60 * 1000

        # the SAP for the acquire resource exclusively proposal:
        arxp = IonObject(OT.AcquireResourceExclusiveProposal,
                         consumer=self._actor_id,
                         resource_id=resource_id,
                         provider=self._provider_id,
                         expiration=str(expiration),
                         negotiation_id=negotiation_id)

        # we are initially opting for only "phase 2" -- just acquire_resource:
        commitment_id = self.ORG.acquire_resource(arxp, headers=self._actor_header)
        log.debug('%r: [xa] AcquireResourceExclusiveProposal: instrument_id=%r resource_id=%s -> '
                  'commitment_id=%s', self._platform_id, instrument_id, resource_id, commitment_id)
        return commitment_id
Пример #25
0
    def target(self, *args, **kwargs):
        """
        Control entrypoint. Setup the base properties for this process (mainly a listener).
        """
        if self.name:
            threading.current_thread().name = "%s-target" % self.name

        # start time
        self._start_time = int(get_ion_ts())

        # spawn control flow loop
        self._ctrl_thread = self.thread_manager.spawn(self._control_flow)

        # wait on control flow loop, heartbeating as appropriate
        while not self._ctrl_thread.ev_exit.wait(timeout=self._heartbeat_secs):
            hbst = self.heartbeat()

            if not all(hbst):
                log.warn("Heartbeat status for process %s returned %s", self, hbst)
                if self._heartbeat_stack is not None:
                    stack_out = "".join(traceback.format_list(self._heartbeat_stack))
                else:
                    stack_out = "N/A"

                #raise PyonHeartbeatError("Heartbeat failed: %s, stacktrace:\n%s" % (hbst, stack_out))
                log.warn("Heartbeat failed: %s, stacktrace:\n%s", hbst, stack_out)

        # this is almost a no-op as we don't fall out of the above loop without
        # exiting the ctrl_thread, but having this line here makes testing much
        # easier.
        self._ctrl_thread.join()
Пример #26
0
    def load_mock_events(self, event_list):
        is_first = len(self.events) == 0

        for cnt, event_entry in enumerate(event_list):
            origin = event_entry.get('o', None)
            origin_type = event_entry.get('ot', None)
            sub_type = event_entry.get('st', None)
            attr = event_entry.get('attr', {})
            evt_obj = IonObject(event_entry['et'],
                                origin=origin,
                                origin_type=origin_type,
                                sub_type=sub_type,
                                ts_created=get_ion_ts(),
                                **attr)
            evt_obj._id = str(cnt)
            self.events.append(evt_obj)

        if is_first:
            self.container_mock.event_repository.find_events = Mock()

            def side_effect(event_type=None, **kwargs):
                return [(evt._id, None, evt) for evt in reversed(self.events)
                        if evt.type_ == event_type]

            self.container_mock.event_repository.find_events.side_effect = side_effect
    def is_resource_acquired_exclusively(self, actor_id='', resource_id=''):
        """Returns True if the specified resource_id has been acquired exclusively. The actor_id is optional, as the operation can
        return True if the resource is acquired exclusively by any actor or specifically by the specified actor_id,
        otherwise False is returned.

        @param actor_id    str
        @param resource_id    str
        @retval success    bool
        @throws BadRequest    if resource_id is not specified
        """
        if not resource_id:
            raise BadRequest("The resource_id parameter is missing")

        try:
            cur_time = int(get_ion_ts())
            commitments,_ = self.clients.resource_registry.find_objects(resource_id,PRED.hasCommitment, RT.Commitment)
            if commitments:
                for com in commitments:
                    if com.lcstate == LCS.RETIRED: #TODO remove when RR find_objects does not include retired objects
                        continue

                    #If the expiration is not 0 make sure it has not expired
                    if ( actor_id is None or actor_id == com.consumer )  and com.commitment.exclusive and\
                       int(com.expiration) > 0 and cur_time < int(com.expiration):
                        return True

        except Exception, e:
            log.error('is_resource_acquired_exclusively: %s for actor_id:%s and resource_id:%s' %  (e.message, actor_id, resource_id))
Пример #28
0
 def sample_other_op(self, foo='bar', num=84, name=''):
     log.info("StatefulTestProcess OP, state=%s", foo)
     newstate = foo
     oldstate = self._get_state("statevalue") or ""
     self._set_state("statevalue", newstate)
     self._set_state("statets", get_ion_ts())
     return oldstate
Пример #29
0
    def create(self, object=None, actor_id=None):
        if object is None:
            raise BadRequest("Object not present")
        if not isinstance(object, IonObjectBase):
            raise BadRequest("Object is not an IonObject")
        if not is_resource(object):
            raise BadRequest("Object is not a Resource")

        lcsm = get_restype_lcsm(object._get_type())
        object.lcstate = lcsm.initial_state if lcsm else "DEPLOYED_AVAILABLE"
        cur_time = get_ion_ts()
        object.ts_created = cur_time
        object.ts_updated = cur_time
        new_res_id = create_unique_resource_id()
        res = self.rr_store.create(object, new_res_id)
        res_id, rev = res

        if actor_id and actor_id != 'anonymous':
            log.debug("Associate resource_id=%s with owner=%s" % (res_id, actor_id))
            self.rr_store.create_association(res_id, PRED.hasOwner, actor_id)

        self.event_pub.publish_event(event_type="ResourceModifiedEvent",
                                     origin=res_id, origin_type=object._get_type(),
                                     sub_type="CREATE",
                                     mod_type=ResourceModificationType.CREATE)

        return res
Пример #30
0
    def _finalize_uirefs(self, ds):
        # Create real resource IDs
        for obj in self.ui_objs.values():
            oid = self.uiid_prefix + obj.uirefid
            obj._id = oid
            self.ui_obj_by_id[oid] = obj

            # Change references for all known UI objects
            for attr in obj.__dict__:
                if attr != 'uirefid' and getattr(obj, attr) in self.ui_objs:
                    setattr(obj, attr, self.uiid_prefix + getattr(obj, attr))
            try:
                json.dumps(obj.__dict__.copy())
            except Exception as ex:
                log.exception("Object %s problem" % obj)

        # Resolve associations to real resource IDs
        for refassoc in self.ref_assocs:
            sub_refid, pred, obj_refid = refassoc
            try:
                subo = self.ui_objs[sub_refid]
                objo = self.ui_objs[obj_refid]
                assoc = objects.Association(at="",
                    s=subo._id, st=subo._get_type(), srv="",
                    p=pred,
                    o=objo._id, ot=objo._get_type(), orv="",
                    ts=get_ion_ts())

                self.ui_assocs.append(assoc)
            except Exception as ex:
                log.warn("Cannot create association for subject=%s pred=%s object=%s: %s" % (sub_refid, pred, obj_refid, ex))
Пример #31
0
def get_valid_resource_commitments(resource_id=None, actor_id=None):
    '''
    Returns the list of valid commitments for the specified resource.
    If optional actor_id is supplied, then filtered by actor_id
    @param resource_id:
    @param actor_id:
    @return:
    '''
    log.debug("Finding commitments for resource_id: %s and actor_id: %s" % (resource_id, actor_id))

    if resource_id is None:
        return None

    try:
        gov_controller = bootstrap.container_instance.governance_controller
        commitments,_ = gov_controller.rr.find_objects(resource_id, PRED.hasCommitment, RT.Commitment)
        if not commitments:
            return None

        cur_time = int(get_ion_ts())
        commitment_list = []
        for com in commitments:
            if ( actor_id == None or com.consumer == actor_id )  and ( int(com.expiration) == 0 or ( int(com.expiration) > 0 and cur_time < int(com.expiration))):
                commitment_list.append(com)

        if commitment_list:
            return commitment_list

    except Exception, e:
        log.error(e)
Пример #32
0
    def _on_command_error(self, cmd, execute_cmd, args, kwargs, ex):
        log.info('Resource agent %s publishing command error event: \
                 cmd=%s, execute_cmd=%s, args=%s, kwargs=%s, \
                 errtype=%s, errmsg=%s, errno=%i, time=%s',
                 self.id, str(cmd), str(execute_cmd), str(args), str(kwargs),
                 str(type(ex)), ex.message, ex.status_code, get_ion_ts())

        if hasattr(ex, 'status_code'):
            status_code = ex.status_code
        else:
            status_code = -1

        event_data = {
            'command': cmd,
            'execute_command': execute_cmd,
            'args': args,
            'kwargs': kwargs,
            'error_type': str(type(ex)),
            'error_msg': ex.message,
            'error_code': status_code
        }

        self._event_publisher.publish_event(event_type='ResourceAgentErrorEvent',
                                            origin=self.resource_id,
                                            **event_data)
Пример #33
0
    def set_lifecycle_state(self, resource_id='', target_lcstate=''):
        if not target_lcstate or target_lcstate not in LCS:
            raise BadRequest("Unknown life-cycle state %s" % target_lcstate)

        res_obj = self.read(resource_id)
        old_state = res_obj.lcstate
        if target_lcstate != LCS.RETIRED:
            restype = res_obj._get_type()
            restype_workflow = get_restype_lcsm(restype)
            if not restype_workflow:
                raise BadRequest("Resource id=%s type=%s has no lifecycle" % (resource_id, restype))

            # Check that target state is allowed
            if not target_lcstate in restype_workflow.get_successors(res_obj.lcstate).values():
                raise BadRequest("Target state %s not reachable for resource in state %s" % (target_lcstate, res_obj.lcstate))

        res_obj.lcstate = target_lcstate
        res_obj.ts_updated = get_ion_ts()

        updres = self.rr_store.update(res_obj)

        self.event_pub.publish_event(event_type="ResourceLifecycleEvent",
                                     origin=res_obj._id, origin_type=res_obj._get_type(),
                                     sub_type=target_lcstate,
                                     old_state=old_state, new_state=target_lcstate)
Пример #34
0
    def register(self, parent, key, **kwargs):
        """
        Add/replace an entry to directory below a parent node.
        Note: Does not merge the attribute values of the entry if existing
        """
        if not (parent and key):
            raise BadRequest("Illegal arguments")
        if not type(parent) is str or not parent.startswith("/"):
            raise BadRequest("Illegal arguments: parent")

        dn = self._get_dn(parent, key)
        log.debug("Directory.add(%s): %s" % (dn, kwargs))

        entry_old = None
        direntry = self._safe_read(dn)
        cur_time = get_ion_ts()
        if direntry:
            entry_old = direntry.attributes
            direntry.attributes = kwargs
            direntry.ts_updated=cur_time
            # TODO: This may fail because of concurrent update
            self.dir_store.update(direntry)
        else:
            parent_dn = self._get_dn(parent)
            direntry = DirEntry(parent=parent_dn, key=key, attributes=kwargs, ts_created=cur_time, ts_updated=cur_time)
            self.dir_store.create(direntry, dn)

        return entry_old
Пример #35
0
    def load_mock_associations(self, assoc_list):
        for assoc_entry in assoc_list:
            sid = assoc_entry[0]
            oid = assoc_entry[2]
            st = self.res_objs[sid]._get_type()
            ot = self.res_objs[oid]._get_type()
            ass_obj = IonObject('Association',
                                s=sid,
                                st=st,
                                o=oid,
                                ot=ot,
                                p=assoc_entry[1],
                                ts=get_ion_ts())
            ass_obj._id = "%s_%s_%s" % (sid, assoc_entry[1], oid)
            self.associations.append(ass_obj)

        self.container_mock.resource_registry.find_associations = Mock()

        def side_effect(subject=None, predicate=None, obj=None, **kwargs):
            if predicate:
                assocs = [
                    assoc for assoc in self.associations
                    if assoc.p == predicate
                ]
            else:
                assocs = self.associations
            return assocs

        self.container_mock.resource_registry.find_associations.side_effect = side_effect
Пример #36
0
    def sample_other_op(self, foo='bar', num=84, name=''):
        """We overload this YML service operation to do what we need to do"""
        if name == "setstate":
            log.info("StatefulTestProcess OP, state=%s", foo)
            newstate = foo
            oldstate = self._get_state("statevalue") or ""
            self._set_state("statevalue", newstate)
            self._set_state("statets", get_ion_ts())
            return oldstate
        elif name == "concurrent":
            self.error = False
            def worker(num):
                try:
                    for i in xrange(10):
                        value = uuid.uuid4().hex
                        self._set_state("state"+str(num), value)
                        log.debug("Flushing state %s of greenlet %s", i, num)
                        self._flush_state()
                        gevent.sleep(0.1)
                except Exception as ex:
                    log.exception("Error in worker")
                    self.error = True

            greenlets = [gevent.spawn(worker, i) for i in xrange(3)]
            gevent.joinall(greenlets)

            if self.error:
                raise Exception("Error in greenlets")
            return "GOOD"
        elif name == "getstate":
            return self._get_state("statevalue")
        else:
            raise Exception("Unknown mode: %s" % name)
Пример #37
0
 def _create_dir_entry(self, parent, key, orgname=None, ts=None, attributes=None):
     """
     Standard way to create a DirEntry object (without persisting it)
     """
     orgname = orgname or self.orgname
     ts = ts or get_ion_ts()
     attributes = attributes if attributes is not None else {}
     de = DirEntry(org=orgname, parent=parent, key=key, attributes=attributes, ts_created=ts, ts_updated=ts)
     return de