def setUp(self):
        yield self._start_container()

        # use some sort of agent...doesnt really matter what kind, does it
        processes = [{
            'name': 'testAgent',
            'module': 'ion.agents.instrumentagents.SBE49_IA',
            'class': 'SBE49InstrumentAgent'
        }, {
            'name': 'agent_registry',
            'module': 'ion.services.coi.agent_registry',
            'class': 'AgentRegistryService'
        }]
        self.sup = yield self._spawn_processes(processes)
        self.svc_id = self.sup.get_child_id('testAgent')
        self.rr_id = self.sup.get_child_id('agent_registry')

        # Start a client (for the RPC)
        self.RAClient = ResourceAgentClient(proc=self.sup, target=self.svc_id)

        # RR Client is ,,,,,desired only for testing
        self.reg_client = AgentRegistryClient(proc=self.sup)
        yield self.reg_client.clear_registry()

        # need any non-generic resource...use an instrument agent one for now
        self.res_desc = \
            InstrumentAgentResourceDescription.create_new_resource()
        #self.res_desc.version = '1.23'
        self.res_desc.name = 'I am a test IA resource description'

        self.res_inst = InstrumentAgentResourceInstance.create_new_resource()
        self.res_inst.driver_process_id = 'something_for_now.1'
        self.res_inst.name = 'I am an instantiation of a test IA resource'
예제 #2
0
    def setUp(self):
        yield self._start_container()

        # Start an instrument agent
        processes = [
            {'name':'pubsub_registry','module':'ion.services.dm.distribution.pubsub_registry','class':'DataPubSubRegistryService'},
            {'name':'pubsub_service','module':'ion.services.dm.distribution.pubsub_service','class':'DataPubsubService'},
            {'name':'agent_registry',
             'module':'ion.services.coi.agent_registry',
             'class':'ResourceRegistryService'},
            {'name':'testSBE49IA',
             'module':'ion.agents.instrumentagents.SBE49_IA',
             'class':'SBE49InstrumentAgent'},
        ]
        self.sup = yield self._spawn_processes(processes)
        self.svc_id = yield self.sup.get_child_id('testSBE49IA')
        self.reg_id = yield self.sup.get_child_id('agent_registry')

        # Start a client (for the RPC)
        self.IAClient = IA.InstrumentAgentClient(proc=self.sup,
                                                 target=self.svc_id)

        # Start an Agent Registry to test against
        self.reg_client = AgentRegistryClient(proc=self.sup)
        yield self.reg_client.clear_registry()
예제 #3
0
 def plc_init(self):
     """
     The Agent Registry client class to hang onto for all registry manipulations
     """
     self.reg_client = AgentRegistryClient(proc=self)
     """
     Our reference object in the Agent Registry
     """
     self.resource_ref = None
     """
     This is what makes us unique for now. When we register, this is our
     handle
     """
     self.name = None
    def setUp(self):
        yield self._start_container()

        # use some sort of agent...doesnt really matter what kind, does it
        processes = [
            {'name':'testAgent',
             'module':'ion.agents.instrumentagents.SBE49_IA',
             'class':'SBE49InstrumentAgent'},
            {'name':'agent_registry',
             'module':'ion.services.coi.agent_registry',
             'class':'AgentRegistryService'}
        ]
        self.sup = yield self._spawn_processes(processes)
        self.svc_id = self.sup.get_child_id('testAgent')
        self.rr_id = self.sup.get_child_id('agent_registry')

        # Start a client (for the RPC)
        self.RAClient = ResourceAgentClient(proc=self.sup, target=self.svc_id)

        # RR Client is ,,,,,desired only for testing
        self.reg_client = AgentRegistryClient(proc=self.sup)
        yield self.reg_client.clear_registry()

        # need any non-generic resource...use an instrument agent one for now
        self.res_desc = \
            InstrumentAgentResourceDescription.create_new_resource()
        #self.res_desc.version = '1.23'
        self.res_desc.name = 'I am a test IA resource description'

        self.res_inst = InstrumentAgentResourceInstance.create_new_resource()
        self.res_inst.driver_process_id = 'something_for_now.1'
        self.res_inst.name = 'I am an instantiation of a test IA resource'
예제 #5
0
    def plc_init(self):
        """
        The Agent Registry client class to hang onto for all registry manipulations
        """
        self.reg_client = AgentRegistryClient(proc=self)

        """
        Our reference object in the Agent Registry
        """
        self.resource_ref = None

        """
        This is what makes us unique for now. When we register, this is our
        handle
        """
        self.name = None
class TestResourceAgent(IonTestCase):
    @defer.inlineCallbacks
    def setUp(self):
        yield self._start_container()

        # use some sort of agent...doesnt really matter what kind, does it
        processes = [{
            'name': 'testAgent',
            'module': 'ion.agents.instrumentagents.SBE49_IA',
            'class': 'SBE49InstrumentAgent'
        }, {
            'name': 'agent_registry',
            'module': 'ion.services.coi.agent_registry',
            'class': 'AgentRegistryService'
        }]
        self.sup = yield self._spawn_processes(processes)
        self.svc_id = self.sup.get_child_id('testAgent')
        self.rr_id = self.sup.get_child_id('agent_registry')

        # Start a client (for the RPC)
        self.RAClient = ResourceAgentClient(proc=self.sup, target=self.svc_id)

        # RR Client is ,,,,,desired only for testing
        self.reg_client = AgentRegistryClient(proc=self.sup)
        yield self.reg_client.clear_registry()

        # need any non-generic resource...use an instrument agent one for now
        self.res_desc = \
            InstrumentAgentResourceDescription.create_new_resource()
        #self.res_desc.version = '1.23'
        self.res_desc.name = 'I am a test IA resource description'

        self.res_inst = InstrumentAgentResourceInstance.create_new_resource()
        self.res_inst.driver_process_id = 'something_for_now.1'
        self.res_inst.name = 'I am an instantiation of a test IA resource'

    @defer.inlineCallbacks
    def tearDown(self):
        yield self._stop_container()

    @defer.inlineCallbacks
    def test_reg_direct(self):
        registered_agent_desc = \
           yield self.reg_client.register_agent_definition(self.res_desc)
        # Not committed, so not equal, but parts should be
        self.assertNotEqual(registered_agent_desc, self.res_desc)
        self.assertEqual(registered_agent_desc.RegistryIdentity,
                         self.res_desc.RegistryIdentity)

        registered_agent_instance = \
            yield self.reg_client.register_agent_instance(self.res_inst)
        # Not committed, so not equal, but parts should be
        self.assertNotEqual(registered_agent_instance, self.res_inst)
        self.assertEqual(registered_agent_instance.RegistryIdentity,
                         self.res_inst.RegistryIdentity)

        recv_agent_desc = \
            yield self.reg_client.get_agent_definition(self.res_desc)
        self.assertEqual(recv_agent_desc, registered_agent_desc)
        self.assertEqual(recv_agent_desc.RegistryIdentity,
                         self.res_desc.RegistryIdentity)
        # Not committed, so not equal
        self.assertNotEqual(recv_agent_desc, self.res_desc)

        recv_agent_inst = \
            yield self.reg_client.get_agent_instance(self.res_inst)
        self.assertEqual(recv_agent_inst, registered_agent_instance)
        # Not commiteed, so not equal, but parts should be
        self.assertNotEqual(recv_agent_inst, self.res_inst)
        self.assertEqual(recv_agent_inst.RegistryIdentity,
                         self.res_inst.RegistryIdentity)

    @defer.inlineCallbacks
    def test_registration_with_definitions(self):
        reg_id = yield self.RAClient.register_resource(self.res_inst)
        orig_result = yield self.RAClient.get_resource_instance()
        self.assertNotEqual(orig_result, None)
        self.assertNotEqual(orig_result, self.res_inst)
        self.assertNotEqual(orig_result.RegistryCommit,
                            self.res_inst.RegistryCommit)
        self.assertEqual(reg_id.RegistryCommit, '')
        self.assertNotEqual(orig_result.RegistryCommit, reg_id.RegistryCommit)
        self.assertEqual(reg_id.RegistryIdentity, orig_result.RegistryIdentity)

        # Verify the reference is the same
        result = yield self.RAClient.get_resource_ref()
        self.assertEqual(result, reg_id)

        # test update/repeat reg if a different instance
        new_res_inst = yield self.RAClient.get_resource_instance()
        new_res_inst.name = "REPLACED TestAgentInstance"
        new_res_inst.driver_process_id = 'something_else.1'

        # Even pulling it, modifiying it, then re-registering makes a new one
        new_result = yield self.RAClient.get_resource_instance()
        new_result.name = "UPDATED TestAgentInstance"
        new_result.driver_process_id = 'something_else.2'
        new_reg_ref = yield self.RAClient.register_resource(new_res_inst)
        self.assertNotEqual(reg_id, new_reg_ref)
        new_result2 = yield self.RAClient.get_resource_instance()
        self.assertNotEqual(new_result2.RegistryIdentity,
                            orig_result.RegistryIdentity)
        self.assertNotEqual(new_result2.RegistryCommit,
                            orig_result.RegistryCommit)
        self.assertNotEqual(new_result2.name, orig_result.name)
        self.assertEqual(new_result2.name, new_res_inst.name)
        self.assertEqual(new_result2.driver_process_id,
                         new_res_inst.driver_process_id)
        self.assertNotEqual(new_result2.name, new_result.name)

    @defer.inlineCallbacks
    def test_agent_self_registration(self):
        reg_id = yield self.RAClient.register_resource()
        result = yield self.RAClient.get_resource_instance()
        self.assertNotEqual(result, None)
        self.assertEqual(reg_id.RegistryCommit, '')
        self.assertNotEqual(result.RegistryCommit, reg_id.RegistryCommit)
        self.assertEqual(reg_id.RegistryIdentity, result.RegistryIdentity)

        # Verify the reference is the same
        result = yield self.RAClient.get_resource_ref()
        self.assertEqual(result, reg_id)

        # Make A new agent to verify we have 2
        processes = [{
            'name': 'testAgent2',
            'module': 'ion.agents.instrumentagents.SBE49_IA',
            'class': 'SBE49InstrumentAgent'
        }]

        sup2 = yield self._spawn_processes(processes)
        svc_id2 = self.sup.get_child_id('testAgent2')

        # Start a client (for the RPC)
        RAClient2 = ResourceAgentClient(proc=sup2, target=svc_id2)

        # test update/repeat reg if a different instance
        yield RAClient2.register_resource()
        refinst2 = yield RAClient2.get_resource_instance()
        refinst1 = yield self.RAClient.get_resource_ref()

        self.assertNotEqual(refinst1.RegistryCommit, refinst2.RegistryCommit)
        self.assertNotEqual(refinst1.RegistryIdentity,
                            refinst2.RegistryIdentity)
        self.assertEqual(refinst1.RegistryCommit, result.RegistryCommit)
        self.assertEqual(refinst1.RegistryIdentity, result.RegistryIdentity)

    @defer.inlineCallbacks
    def test_lifecycle(self):
        registered_res = yield self.RAClient.register_resource(self.res_inst)
        self.assertNotEqual(registered_res, None)
        result = yield self.RAClient.get_resource_ref()
        self.assertEqual(result, registered_res)

        active_state = LCState('active')
        inactive_state = LCState('inactive')

        result = yield self.RAClient.set_lifecycle_state(active_state)
        self.assertEqual(result, active_state)
        result = yield self.RAClient.get_lifecycle_state()
        self.assertEqual(result, active_state)

        result = yield self.RAClient.set_lifecycle_state(inactive_state)
        ref = yield self.RAClient.get_resource_ref()
        self.assertNotEqual(ref, None)
        self.assertEqual(ref, registered_res)
        result = yield self.RAClient.get_lifecycle_state()
        self.assertEqual(result, inactive_state)
예제 #7
0
class ResourceAgent(BaseProcess):
    """
    Base class for resource agent processes
    If you are going to write a new agent process, subclass this one and
    setup a ResourceRegistryClient
    """
    def plc_init(self):
        """
        The Agent Registry client class to hang onto for all registry manipulations
        """
        self.reg_client = AgentRegistryClient(proc=self)
        """
        Our reference object in the Agent Registry
        """
        self.resource_ref = None
        """
        This is what makes us unique for now. When we register, this is our
        handle
        """
        self.name = None

    @defer.inlineCallbacks
    def op_get_lifecycle_state(self, content, headers, msg):
        """
        Get the lifecycle state for the resource
        @retval LCState string
        @todo handle errors better
        """
        if (self.resource_ref != None):
            result = \
                yield self.reg_client.get_agent_instance(self.resource_ref)
            assert (isinstance(result, AgentInstance))
            state = result.get_lifecyclestate()
            yield self.reply_ok(msg, str(state))
        else:
            yield self.reply_err(msg, "Resource not registered!")

    @defer.inlineCallbacks
    def op_set_lifecycle_state(self, content, headers, msg):
        """
        Set the lifecycle state for the resource
        @param content Should be a list with a resource id and a string that
            can be turned into an LCState object
        """
        assert (isinstance(content, basestring))
        state = str(content)
        assert (state in LCStateNames)
        state = LCState(state)
        if (self.resource_ref != None):
            result = yield self.reg_client.set_agent_lcstate(
                self.resource_ref, state)
            self.resource_ref = result.reference(head=True)
            if (result):
                yield self.reply_ok(msg, str(state))
                return
            else:
                yield self.reply_err(msg, \
                    "Could not set lifecycle state for %s" \
                        % self.resource_ref.name)
                return
        else:
            yield self.reply_err(msg, \
              "Could not set lifecycle state. Resource %s does not exist." \
              % self.resource_ref.name)

    @defer.inlineCallbacks
    def op_register_resource(self, content, headers, msg):
        """
        Registers or re-registers self in the agent registry.
        @param content Must include an encoded AgentInstance subclass that may
            or may not have been previously filled out. The instance class
            should be appropriate to the type of resource being registered.
            Perhaps the client is checking the type?
        @todo Turn initial parameter asserts into a decode check
        @note Registering an existing InstrumentAgent with an existing registry
        @msc
       	hscale = "2";
	 User, InstrumentAgentClient, InstrumentAgentResourceInstance, InstrumentAgent, ResourceAgent, ResourceAgentClient, AgentRegistryClient, AgentRegistry;
         User -> InstrumentAgent [label="instantiate and spawn IA subclass"];
         User -> InstrumentAgentClient[label="instantiate IAClient subclass"];
         AgentRegistryClient -> InstrumentAgent [label="reference stored in IA"];
         --- [label="All setup now, registry must already have a client on hand"];
         User => InstrumentAgentClient [label="register_resource()"];
         InstrumentAgentClient -> InstrumentAgentResourceInstance [label="instantiate"];
         InstrumentAgentClient -> InstrumentAgentResourceInstance [label="get driver address"];
         InstrumentAgentClient <- InstrumentAgentResourceInstance [label="driver address"];
         InstrumentAgentClient => InstrumentAgentClient [label="ResourceAgentClient.register_resource()"];
         InstrumentAgentClient =>> InstrumentAgent [label="op_register_resource() via AMQP"];
         InstrumentAgent => AgentRegistryClient [label="register_agent_instance(self, custom_descriptor)"];
         AgentRegistryClient => AgentRegistryClient [label="describe_instance(agent_instance, custom_descriptor)"];
         AgentRegistryClient << AgentRegistryClient [label="return AgentDescription"];
         AgentRegistryClient => AgentRegistryClient [label="find_registered_agent_instance_from_description(above)"];
         AgentRegistryClient =>> AgentRegistry [label="register_resource() via base class AMQP"];
         AgentRegistryClient <<= AgentRegistry [label="return via AMQP"];
         InstrumentAgent << AgentRegistryClient [label="Success/failure"];
         InstrumentAgentClient <<= ResourceAgent [label="Success/failure via InstrumentAgent via AMQP"];
         User << InstrumentAgentClient [label="return"];
        @endmsc
        """
        if (content == ""):
            descriptor = None
        elif (content != None):
            descriptor = AgentInstance.decode(content)
        assert ((descriptor == None)
                or (isinstance(descriptor, AgentInstance)))
        assert (descriptor != "")
        # Register the instance/description
        returned_instance = \
            yield self.reg_client.register_agent_instance(self, descriptor)
        self.resource_ref = returned_instance.reference(head=True)
        if (self.resource_ref == None) or (self.resource_ref == False):
            yield self.reply_err(msg, "Could not register instance!")
        else:
            yield self.reply_ok(msg, self.resource_ref.encode())

    @defer.inlineCallbacks
    def op_get_resource_instance(self, content, headers, msg):
        """
        Get the resource instance for this resource from the agent registry
        @retval Via messageg, send the resource instance object for this
            resource, as registered in the agent registry
        """
        if (self.resource_ref != None):
            result = \
                yield self.reg_client.get_agent_instance(self.resource_ref)
            assert (isinstance(result, AgentInstance))
            yield self.reply_ok(msg, result.encode())
        else:
            yield self.reply_err(msg, None)

    @defer.inlineCallbacks
    def op_get_resource_ref(self, content, headers, msg):
        """
        Returns the resource id for the resource agent
        @todo handle case where it isnt registered yet
        @retval An encoded resource reference if the resource has been
            registered, None if not registered
        """
        if (self.resource_ref != None):
            yield self.reply_ok(msg, self.resource_ref.encode())
        else:
            yield self.reply_err(msg, None)

    def op_get(self, content, headers, msg):
        """
        Abstract method for the Resource Agent interface
        """

    def op_set(self, content, headers, msg):
        """
        Abstract method for the Resource Agent interface
        """

    def op_execute(self, content, headers, msg):
        """
        Abstract method for the Resource Agent interface
        """

    def op_get_status(self, content, headers, msg):
        """
        Abstract method for the Resource Agent interface
        """

    def op_get_capabilities(self, content, headers, msg):
        """
예제 #8
0
 def slc_init(self):
     self.irc = InstrumentRegistryClient(proc=self)
     self.dprc = DataProductRegistryClient(proc=self)
     self.arc = AgentRegistryClient(proc=self)
     self.dpsc = DataPubsubClient(proc=self)
예제 #9
0
class InstrumentManagementService(BaseService):
    """
    Instrument management service interface.
    This service provides overall coordination for instrument management within
    an observatory context. In particular it coordinates the access to the
    instrument and data product registries and the interaction with instrument
    agents.
    """

    # Declaration of service
    declare = BaseService.service_declare(name='instrument_management',
                                          version='0.1.0',
                                          dependencies=[])

    def slc_init(self):
        self.irc = InstrumentRegistryClient(proc=self)
        self.dprc = DataProductRegistryClient(proc=self)
        self.arc = AgentRegistryClient(proc=self)
        self.dpsc = DataPubsubClient(proc=self)

    @defer.inlineCallbacks
    def op_create_new_instrument(self, content, headers, msg):
        """
        Service operation: Accepts a dictionary containing user inputs.
        Updates the instrument registry.
        """
        userInput = content['userInput']

        newinstrument = InstrumentResource.create_new_resource()

        if 'name' in userInput:
            newinstrument.name = str(userInput['name'])

        if 'description' in userInput:
            newinstrument.description = str(userInput['description'])

        if 'manufacturer' in userInput:
            newinstrument.manufacturer = str(userInput['manufacturer'])

        if 'model' in userInput:
            newinstrument.model = str(userInput['model'])

        if 'serial_num' in userInput:
            newinstrument.serial_num = str(userInput['serial_num'])

        if 'fw_version' in userInput:
            newinstrument.fw_version = str(userInput['fw_version'])

        instrument_res = yield self.irc.register_instrument_instance(
            newinstrument)

        yield self.reply_ok(msg, instrument_res.encode())

    @defer.inlineCallbacks
    def op_create_new_data_product(self, content, headers, msg):
        """
        Service operation: Accepts a dictionary containing user inputs.
        Updates the data product registry. Also sets up an ingestion pipeline
        for an instrument
        """
        dataProductInput = content['dataProductInput']

        newdp = DataProductResource.create_new_resource()
        if 'instrumentID' in dataProductInput:
            inst_id = str(dataProductInput['instrumentID'])
            int_ref = ResourceReference(RegistryIdentity=inst_id,
                                        RegistryBranch='master')
            newdp.instrument_ref = int_ref

        if 'name' in dataProductInput:
            newdp.name = str(dataProductInput['name'])

        if 'description' in dataProductInput:
            newdp.description = str(dataProductInput['description'])

        if 'dataformat' in dataProductInput:
            newdp.dataformat = str(dataProductInput['dataformat'])

        # Step: Create a data stream
        ## Instantiate a pubsubclient
        #self.dpsc = DataPubsubClient(proc=self)
        #
        ## Create and Register a topic
        #self.topic = PubSubTopicResource.create('SBE49 Topic',"oceans, oil spill")
        #self.topic = yield self.dpsc.define_topic(self.topic)
        #logging.debug('DHE: Defined Topic')
        #
        #self.publisher = PublisherResource.create('Test Publisher', self, self.topic, 'DataObject')
        #self.publisher = yield self.dpsc.define_publisher(self.publisher)

        res = yield self.dprc.register_data_product(newdp)
        ref = res.reference(head=True)

        yield self.reply_ok(msg, res.encode())

    @defer.inlineCallbacks
    def op_execute_command(self, content, headers, msg):
        """
        Service operation: Execute a command on an instrument.
        """

        # Step 1: Extract the arguments from the UI generated message content
        commandInput = content['commandInput']

        if 'instrumentID' in commandInput:
            inst_id = str(commandInput['instrumentID'])
        else:
            raise ValueError("Input for instrumentID not present")

        command = []
        if 'command' in commandInput:
            command_op = str(commandInput['command'])
        else:
            raise ValueError("Input for command not present")

        command.append(command_op)

        arg_idx = 0
        while True:
            argname = 'cmdArg' + str(arg_idx)
            arg_idx += 1
            if argname in commandInput:
                command.append(str(commandInput[argname]))
            else:
                break

        # Step 2: Find the agent id for the given instrument id
        agent_pid = yield self.get_agent_pid_for_instrument(inst_id)
        if not agent_pid:
            yield self.reply_err(
                msg, "No agent found for instrument " + str(inst_id))
            defer.returnValue(None)

        # Step 3: Interact with the agent to execute the command
        iaclient = InstrumentAgentClient(proc=self, target=agent_pid)
        commandlist = [
            command,
        ]
        logging.info("Sending command to IA: " + str(commandlist))
        cmd_result = yield iaclient.execute_instrument(commandlist)

        yield self.reply_ok(msg, cmd_result)

    @defer.inlineCallbacks
    def op_get_instrument_state(self, content, headers, msg):
        """
        Service operation: .
        """
        # Step 1: Extract the arguments from the UI generated message content
        commandInput = content['commandInput']

        if 'instrumentID' in commandInput:
            inst_id = str(commandInput['instrumentID'])
        else:
            raise ValueError("Input for instrumentID not present")

        agent_pid = yield self.get_agent_pid_for_instrument(inst_id)
        if not agent_pid:
            raise StandardError("No agent found for instrument " +
                                str(inst_id))

        iaclient = InstrumentAgentClient(proc=self, target=agent_pid)
        inst_cap = yield iaclient.get_capabilities()
        if not inst_cap:
            raise StandardError("No capabilities available for instrument " +
                                str(inst_id))

        ci_commands = inst_cap['ci_commands']
        instrument_commands = inst_cap['instrument_commands']
        instrument_parameters = inst_cap['instrument_parameters']
        ci_parameters = inst_cap['ci_parameters']

        values = yield iaclient.get_from_instrument(instrument_parameters)
        resvalues = {}
        if values:
            resvalues = values

        yield self.reply_ok(msg, resvalues)

    @defer.inlineCallbacks
    def op_start_instrument_agent(self, content, headers, msg):
        """
        Service operation: Starts an instrument agent for a type of
        instrument.
        """
        if 'instrumentID' in content:
            inst_id = str(content['instrumentID'])
        else:
            raise ValueError("Input for instrumentID not present")

        if 'model' in content:
            model = str(content['model'])
        else:
            raise ValueError("Input for model not present")

        if model != 'SBE49':
            raise ValueError("Only SBE49 supported!")

        agent_pid = yield self.get_agent_pid_for_instrument(inst_id)
        if agent_pid:
            raise StandardError("Agent already started for instrument " +
                                str(inst_id))

        simulator = Simulator(inst_id)
        simulator.start()

        topicname = "Inst/RAW/" + inst_id
        topic = PubSubTopicResource.create(topicname, "")

        # Use the service to create a queue and register the topic
        topic = yield self.dpsc.define_topic(topic)

        iagent_args = {}
        iagent_args['instrument-id'] = inst_id
        driver_args = {}
        driver_args['port'] = simulator.port
        driver_args['publish-to'] = topic.RegistryIdentity
        iagent_args['driver-args'] = driver_args

        iapd = ProcessDesc(
            **{
                'name': 'SBE49IA',
                'module': 'ion.agents.instrumentagents.SBE49_IA',
                'class': 'SBE49InstrumentAgent',
                'spawnargs': iagent_args
            })

        iagent_id = yield self.spawn_child(iapd)
        iaclient = InstrumentAgentClient(proc=self, target=iagent_id)
        yield iaclient.register_resource(inst_id)

        yield self.reply_ok(msg, "OK")

    @defer.inlineCallbacks
    def op_stop_instrument_agent(self, content, headers, msg):
        """
        Service operation: Starts direct access mode.
        """
        yield self.reply_err(msg, "Not yet implemented")

    @defer.inlineCallbacks
    def op_start_direct_access(self, content, headers, msg):
        """
        Service operation: Starts direct access mode.
        """
        yield self.reply_err(msg, "Not yet implemented")

    @defer.inlineCallbacks
    def op_stop_direct_access(self, content, headers, msg):
        """
        Service operation: Stops direct access mode.
        """
        yield self.reply_err(msg, "Not yet implemented")

    @defer.inlineCallbacks
    def get_agent_desc_for_instrument(self, instrument_id):
        logging.info("get_agent_desc_for_instrument() instrumentID=" +
                     str(instrument_id))
        int_ref = ResourceReference(RegistryIdentity=instrument_id,
                                    RegistryBranch='master')
        agent_query = InstrumentAgentResourceInstance()
        agent_query.instrument_ref = int_ref

        if not agent_res:
            defer.returnValue(None)
        agent_pid = agent_res.proc_id
        logging.info("Agent process id for instrument id %s is: %s" %
                     (instrument_id, agent_pid))
        defer.returnValue(agent_pid)

    @defer.inlineCallbacks
    def get_agent_for_instrument(self, instrument_id):
        logging.info("get_agent_for_instrument() instrumentID=" +
                     str(instrument_id))
        int_ref = ResourceReference(RegistryIdentity=instrument_id,
                                    RegistryBranch='master')
        agent_query = InstrumentAgentResourceInstance()
        agent_query.instrument_ref = int_ref
        # @todo Need to list the LC state here. WHY???
        agent_query.lifecycle = LCStates.developed
        agents = yield self.arc.find_registered_agent_instance_from_description(
            agent_query, regex=False)
        logging.info("Found %s agent instances for instrument id %s" %
                     (len(agents), instrument_id))
        agent_res = None
        if len(agents) > 0:
            agent_res = agents[0]
        defer.returnValue(agent_res)

    @defer.inlineCallbacks
    def get_agent_pid_for_instrument(self, instrument_id):
        agent_res = yield self.get_agent_for_instrument(instrument_id)
        if not agent_res:
            defer.returnValue(None)
        agent_pid = agent_res.proc_id
        logging.info("Agent process id for instrument id %s is: %s" %
                     (instrument_id, agent_pid))
        defer.returnValue(agent_pid)
예제 #10
0
class TestInstrumentAgent(IonTestCase):

    @defer.inlineCallbacks
    def setUp(self):
        yield self._start_container()

        # Start an instrument agent
        processes = [
            {'name':'pubsub_registry','module':'ion.services.dm.distribution.pubsub_registry','class':'DataPubSubRegistryService'},
            {'name':'pubsub_service','module':'ion.services.dm.distribution.pubsub_service','class':'DataPubsubService'},
            {'name':'agent_registry',
             'module':'ion.services.coi.agent_registry',
             'class':'ResourceRegistryService'},
            {'name':'testSBE49IA',
             'module':'ion.agents.instrumentagents.SBE49_IA',
             'class':'SBE49InstrumentAgent'},
        ]
        self.sup = yield self._spawn_processes(processes)
        self.svc_id = yield self.sup.get_child_id('testSBE49IA')
        self.reg_id = yield self.sup.get_child_id('agent_registry')

        # Start a client (for the RPC)
        self.IAClient = IA.InstrumentAgentClient(proc=self.sup,
                                                 target=self.svc_id)

        # Start an Agent Registry to test against
        self.reg_client = AgentRegistryClient(proc=self.sup)
        yield self.reg_client.clear_registry()

    @defer.inlineCallbacks
    def tearDown(self):
        yield self._stop_container()

    @defer.inlineCallbacks
    def test_get_SBE49_capabilities(self):
        """
        Test the ability to gather capabilities from the SBE49 instrument
        capabilities
        """
        result = yield self.IAClient.get_capabilities()
        #logging.info("getCapabilities result: "+ str(result))
        self.assert_(set(IACIParameters).issubset(set(result[IA.ci_parameters])))
        self.assert_(IA.driver_address in
                     result[IA.ci_parameters])
        self.assert_(list(IACICommands) == result[IA.ci_commands])
        self.assert_(list(IAInstCommands) ==
                     result[IA.instrument_commands])
        self.assert_(list(IAInstParameters) ==
                     result[IA.instrument_parameters])

    @defer.inlineCallbacks
    def test_get_set_SBE49_params(self):
        """
        Test the ability of the SBE49 driver to send and receive get, set,
        and other messages. Best called as RPC message pairs.
        """

        self.simulator = Simulator("123", 9000)
        self.simulator.start()

        # Sleep for a while to allow simlator to get set up.
        yield pu.asleep(1)

        try:
            
            response = yield self.IAClient.get_from_instrument(['baudrate',
                                                                'outputformat'])
            self.assert_(response['status'] == 'OK')
            self.assertEqual(response['baudrate'], 9600)
            self.assertEqual(response['outputformat'], 0)
    
            response = yield self.IAClient.set_to_instrument({'baudrate': 19200,
                                                'outputformat': 1})
            self.assert_(response['status'] == 'OK')
            self.assertEqual(response['baudrate'], 19200)
            self.assertEqual(response['outputformat'], 1)
            
            response = yield self.IAClient.get_from_instrument(['baudrate',
                                                                'outputformat'])
            self.assert_(response['status'] == 'OK')
            self.assertEqual(response['baudrate'], 19200)
            self.assertEqual(response['outputformat'], 1)
    
            response = yield self.IAClient.set_to_instrument({'outputformat': 2})
            self.assert_(response['status'] == 'OK')
            self.assertEqual(response['outputformat'], 2)
            
            # Try setting something bad
            response = yield self.IAClient.set_to_instrument({'baudrate': 19200,
                                                'badvalue': 1})
            self.assert_(response['status'] == 'ERROR')
            self.assert_('baudrate' not in response)

        finally:
            yield self.simulator.stop()

    @defer.inlineCallbacks
    def test_registration(self):
        """
        Tests the ability of an instrument agent to successfully register
        ifself with the resource registry.
        """
        reg_ref = yield self.IAClient.register_resource("123")

        result = yield self.IAClient.get_resource_instance()
        self.assertNotEqual(result, None)

        self.assert_(isinstance(result, InstrumentAgentResourceInstance))
        self.assertNotEqual(result.driver_process_id, None)
        self.assertEqual(result.instrument_ref.RegistryIdentity, "123")

        self.assertEqual(reg_ref.RegistryCommit, '')
        self.assertNotEqual(result.RegistryCommit, reg_ref.RegistryCommit)
        self.assertEqual(reg_ref.RegistryIdentity, result.RegistryIdentity)

        # Verify the reference is the same
        result = yield self.IAClient.get_resource_ref()

        self.assertEqual(result, reg_ref)

    @defer.inlineCallbacks
    def test_lifecycle_states(self):
        """
        Test the resource lifecycle management
        """
        yield self.IAClient.register_resource("123")

        response = yield self.IAClient.set_lifecycle_state(LCS.inactive)
        self.assertEqual(response, LCS.inactive)

        response = yield self.IAClient.get_lifecycle_state()
        self.assertEqual(response, LCS.inactive)
        self.assertNotEqual(response, LCS.active)

        response = yield self.IAClient.set_lifecycle_state(LCS.active)
        self.assertEqual(response, LCS.active)

        response = yield self.IAClient.get_lifecycle_state()
        self.assertEqual(response, LCS.active)

    @defer.inlineCallbacks
    def test_execute(self):
        """
        Test the ability of the SBE49 driver to execute commands through the
        InstrumentAgentClient class
        """
        self.simulator = Simulator("123", 9000)
        self.simulator.start()

        try:

            response = yield self.IAClient.execute_instrument([['start','now', 1],
                                                               ['stop']])
            print "response ", response
            self.assert_(isinstance(response, dict))
            self.assert_('status' in response.keys())
            self.assertEqual(response['status'], 'OK')
            self.assert_('start' in response['value'])
            self.assert_('stop' in response['value'])
            self.assert_(response['status'] == 'OK')

            response = yield self.IAClient.execute_instrument([['badcommand',
                                                                'now','1']])
            self.assert_(isinstance(response, dict))
            self.assertEqual(response['status'], 'ERROR')

            response = yield self.IAClient.execute_instrument([])
            self.assert_(isinstance(response, dict))
            self.assertEqual(response['status'], 'ERROR')

        finally:
            yield self.simulator.stop()

    @defer.inlineCallbacks
    def test_get_driver_proc(self):
        """
        Test the methods for retreiving the driver process directly from
        the instrument agent.
        """
        response = yield self.IAClient.get_from_CI([IA.driver_address])
        self.assertNotEqual(response, None)
        """
        Not the best test or logic, but see if the format is at least close
        Need a better way to get at the process id of the driver...maybe
        out of the registry?
        """
        self.assertEqual(str(response[IA.driver_address]).rsplit('.', 1)[0],
                         str(self.svc_id).rsplit('.', 1)[0])

    @defer.inlineCallbacks
    def test_status(self):
        """
        Test to see if the status response is correct
        @todo Do we even need this function?
        """
        response = yield self.IAClient.get_status(['some_arg'])
        self.assert_(isinstance(response, dict))
        self.assertEqual(response['status'], "OK")
        self.assertEqual(response['value'], 'a-ok')

    @defer.inlineCallbacks
    def test_translator(self):
        """
        Test to see if the translator function is coming back cleanly
        @todo make this not a stub when we can pass functions through AMQP
        """
        raise unittest.SkipTest('Needs Refactor of LifeCycle State and Resource Descriptions')

        yield
예제 #11
0
class ResourceAgent(BaseProcess):
    """
    Base class for resource agent processes
    If you are going to write a new agent process, subclass this one and
    setup a ResourceRegistryClient
    """

    def plc_init(self):
        """
        The Agent Registry client class to hang onto for all registry manipulations
        """
        self.reg_client = AgentRegistryClient(proc=self)

        """
        Our reference object in the Agent Registry
        """
        self.resource_ref = None

        """
        This is what makes us unique for now. When we register, this is our
        handle
        """
        self.name = None


    @defer.inlineCallbacks
    def op_get_lifecycle_state(self, content, headers, msg):
        """
        Get the lifecycle state for the resource
        @retval LCState string
        @todo handle errors better
        """
        if (self.resource_ref != None):
            result = \
                yield self.reg_client.get_agent_instance(self.resource_ref)
            assert(isinstance(result, AgentInstance))
            state = result.get_lifecyclestate()
            yield self.reply_ok(msg, str(state))
        else:
            yield self.reply_err(msg, "Resource not registered!")

    @defer.inlineCallbacks
    def op_set_lifecycle_state(self, content, headers, msg):
        """
        Set the lifecycle state for the resource
        @param content Should be a list with a resource id and a string that
            can be turned into an LCState object
        """
        assert(isinstance(content, basestring))
        state = str(content)
        assert(state in LCStateNames)
        state = LCState(state)
        if (self.resource_ref != None):
            result = yield self.reg_client.set_agent_lcstate(self.resource_ref,
                                                             state)
            self.resource_ref = result.reference(head=True)
            if (result):
                yield self.reply_ok(msg, str(state))
                return
            else:
                yield self.reply_err(msg, \
                    "Could not set lifecycle state for %s" \
                        % self.resource_ref.name)
                return
        else:
            yield self.reply_err(msg, \
              "Could not set lifecycle state. Resource %s does not exist." \
              % self.resource_ref.name)

    @defer.inlineCallbacks
    def op_register_resource(self, content, headers, msg):
        """
        Registers or re-registers self in the agent registry.
        @param content Must include an encoded AgentInstance subclass that may
            or may not have been previously filled out. The instance class
            should be appropriate to the type of resource being registered.
            Perhaps the client is checking the type?
        @todo Turn initial parameter asserts into a decode check
        @note Registering an existing InstrumentAgent with an existing registry
        @msc
       	hscale = "2";
	 User, InstrumentAgentClient, InstrumentAgentResourceInstance, InstrumentAgent, ResourceAgent, ResourceAgentClient, AgentRegistryClient, AgentRegistry;
         User -> InstrumentAgent [label="instantiate and spawn IA subclass"];
         User -> InstrumentAgentClient[label="instantiate IAClient subclass"];
         AgentRegistryClient -> InstrumentAgent [label="reference stored in IA"];
         --- [label="All setup now, registry must already have a client on hand"];
         User => InstrumentAgentClient [label="register_resource()"];
         InstrumentAgentClient -> InstrumentAgentResourceInstance [label="instantiate"];
         InstrumentAgentClient -> InstrumentAgentResourceInstance [label="get driver address"];
         InstrumentAgentClient <- InstrumentAgentResourceInstance [label="driver address"];
         InstrumentAgentClient => InstrumentAgentClient [label="ResourceAgentClient.register_resource()"];
         InstrumentAgentClient =>> InstrumentAgent [label="op_register_resource() via AMQP"];
         InstrumentAgent => AgentRegistryClient [label="register_agent_instance(self, custom_descriptor)"];
         AgentRegistryClient => AgentRegistryClient [label="describe_instance(agent_instance, custom_descriptor)"];
         AgentRegistryClient << AgentRegistryClient [label="return AgentDescription"];
         AgentRegistryClient => AgentRegistryClient [label="find_registered_agent_instance_from_description(above)"];
         AgentRegistryClient =>> AgentRegistry [label="register_resource() via base class AMQP"];
         AgentRegistryClient <<= AgentRegistry [label="return via AMQP"];
         InstrumentAgent << AgentRegistryClient [label="Success/failure"];
         InstrumentAgentClient <<= ResourceAgent [label="Success/failure via InstrumentAgent via AMQP"];
         User << InstrumentAgentClient [label="return"];
        @endmsc
        """
        if (content == ""):
            descriptor = None
        elif (content != None):
            descriptor = AgentInstance.decode(content)
        assert((descriptor == None) or (isinstance(descriptor, AgentInstance)))
        assert(descriptor != "")
        # Register the instance/description
        returned_instance = \
            yield self.reg_client.register_agent_instance(self, descriptor)
        self.resource_ref = returned_instance.reference(head=True)
        if (self.resource_ref == None) or (self.resource_ref == False):
            yield self.reply_err(msg, "Could not register instance!")
        else:
            yield self.reply_ok(msg, self.resource_ref.encode())

    @defer.inlineCallbacks
    def op_get_resource_instance(self, content, headers, msg):
        """
        Get the resource instance for this resource from the agent registry
        @retval Via messageg, send the resource instance object for this
            resource, as registered in the agent registry
        """
        if (self.resource_ref != None):
            result = \
                yield self.reg_client.get_agent_instance(self.resource_ref)
            assert(isinstance(result, AgentInstance))
            yield self.reply_ok(msg, result.encode())
        else:
            yield self.reply_err(msg, None)

    @defer.inlineCallbacks
    def op_get_resource_ref(self, content, headers, msg):
        """
        Returns the resource id for the resource agent
        @todo handle case where it isnt registered yet
        @retval An encoded resource reference if the resource has been
            registered, None if not registered
        """
        if (self.resource_ref != None):
            yield self.reply_ok(msg, self.resource_ref.encode())
        else:
            yield self.reply_err(msg, None)

    def op_get(self, content, headers, msg):
        """
        Abstract method for the Resource Agent interface
        """

    def op_set(self, content, headers, msg):
        """
        Abstract method for the Resource Agent interface
        """

    def op_execute(self, content, headers, msg):
        """
        Abstract method for the Resource Agent interface
        """

    def op_get_status(self, content, headers, msg):
        """
        Abstract method for the Resource Agent interface
        """

    def op_get_capabilities(self, content, headers, msg):
        """
 def slc_init(self):
     self.irc = InstrumentRegistryClient(proc=self)
     self.dprc = DataProductRegistryClient(proc=self)
     self.arc = AgentRegistryClient(proc=self)
     self.dpsc = DataPubsubClient(proc=self)
class InstrumentManagementService(BaseService):
    """
    Instrument management service interface.
    This service provides overall coordination for instrument management within
    an observatory context. In particular it coordinates the access to the
    instrument and data product registries and the interaction with instrument
    agents.
    """

    # Declaration of service
    declare = BaseService.service_declare(name='instrument_management',
                                          version='0.1.0',
                                          dependencies=[])

    def slc_init(self):
        self.irc = InstrumentRegistryClient(proc=self)
        self.dprc = DataProductRegistryClient(proc=self)
        self.arc = AgentRegistryClient(proc=self)
        self.dpsc = DataPubsubClient(proc=self)

    @defer.inlineCallbacks
    def op_create_new_instrument(self, content, headers, msg):
        """
        Service operation: Accepts a dictionary containing user inputs.
        Updates the instrument registry.
        """
        userInput = content['userInput']

        newinstrument = InstrumentResource.create_new_resource()

        if 'name' in userInput:
            newinstrument.name = str(userInput['name'])

        if 'description' in userInput:
            newinstrument.description = str(userInput['description'])

        if 'manufacturer' in userInput:
            newinstrument.manufacturer = str(userInput['manufacturer'])

        if 'model' in userInput:
            newinstrument.model = str(userInput['model'])

        if 'serial_num' in userInput:
            newinstrument.serial_num = str(userInput['serial_num'])

        if 'fw_version' in userInput:
            newinstrument.fw_version = str(userInput['fw_version'])

        instrument_res = yield self.irc.register_instrument_instance(newinstrument)

        yield self.reply_ok(msg, instrument_res.encode())

    @defer.inlineCallbacks
    def op_create_new_data_product(self, content, headers, msg):
        """
        Service operation: Accepts a dictionary containing user inputs.
        Updates the data product registry. Also sets up an ingestion pipeline
        for an instrument
        """
        dataProductInput = content['dataProductInput']

        newdp = DataProductResource.create_new_resource()
        if 'instrumentID' in dataProductInput:
            inst_id = str(dataProductInput['instrumentID'])
            int_ref = ResourceReference(RegistryIdentity=inst_id, RegistryBranch='master')
            newdp.instrument_ref = int_ref

        if 'name' in dataProductInput:
            newdp.name = str(dataProductInput['name'])

        if 'description' in dataProductInput:
            newdp.description = str(dataProductInput['description'])

        if 'dataformat' in dataProductInput:
            newdp.dataformat = str(dataProductInput['dataformat'])

        # Step: Create a data stream
        ## Instantiate a pubsubclient
        #self.dpsc = DataPubsubClient(proc=self)
        #
        ## Create and Register a topic
        #self.topic = PubSubTopicResource.create('SBE49 Topic',"oceans, oil spill")
        #self.topic = yield self.dpsc.define_topic(self.topic)
        #logging.debug('DHE: Defined Topic')
        #
        #self.publisher = PublisherResource.create('Test Publisher', self, self.topic, 'DataObject')
        #self.publisher = yield self.dpsc.define_publisher(self.publisher)


        res = yield self.dprc.register_data_product(newdp)
        ref = res.reference(head=True)

        yield self.reply_ok(msg, res.encode())

    @defer.inlineCallbacks
    def op_execute_command(self, content, headers, msg):
        """
        Service operation: Execute a command on an instrument.
        """

        # Step 1: Extract the arguments from the UI generated message content
        commandInput = content['commandInput']

        if 'instrumentID' in commandInput:
            inst_id = str(commandInput['instrumentID'])
        else:
            raise ValueError("Input for instrumentID not present")

        command = []
        if 'command' in commandInput:
            command_op = str(commandInput['command'])
        else:
            raise ValueError("Input for command not present")

        command.append(command_op)

        arg_idx = 0
        while True:
            argname = 'cmdArg'+str(arg_idx)
            arg_idx += 1
            if argname in commandInput:
                command.append(str(commandInput[argname]))
            else:
                break

        # Step 2: Find the agent id for the given instrument id
        agent_pid  = yield self.get_agent_pid_for_instrument(inst_id)
        if not agent_pid:
            yield self.reply_err(msg, "No agent found for instrument "+str(inst_id))
            defer.returnValue(None)

        # Step 3: Interact with the agent to execute the command
        iaclient = InstrumentAgentClient(proc=self, target=agent_pid)
        commandlist = [command,]
        logging.info("Sending command to IA: "+str(commandlist))
        cmd_result = yield iaclient.execute_instrument(commandlist)

        yield self.reply_ok(msg, cmd_result)

    @defer.inlineCallbacks
    def op_get_instrument_state(self, content, headers, msg):
        """
        Service operation: .
        """
        # Step 1: Extract the arguments from the UI generated message content
        commandInput = content['commandInput']

        if 'instrumentID' in commandInput:
            inst_id = str(commandInput['instrumentID'])
        else:
            raise ValueError("Input for instrumentID not present")

        agent_pid = yield self.get_agent_pid_for_instrument(inst_id)
        if not agent_pid:
            raise StandardError("No agent found for instrument "+str(inst_id))

        iaclient = InstrumentAgentClient(proc=self, target=agent_pid)
        inst_cap = yield iaclient.get_capabilities()
        if not inst_cap:
            raise StandardError("No capabilities available for instrument "+str(inst_id))

        ci_commands = inst_cap['ci_commands']
        instrument_commands = inst_cap['instrument_commands']
        instrument_parameters = inst_cap['instrument_parameters']
        ci_parameters = inst_cap['ci_parameters']

        values = yield iaclient.get_from_instrument(instrument_parameters)
        resvalues = {}
        if values:
            resvalues = values

        yield self.reply_ok(msg, resvalues)

    @defer.inlineCallbacks
    def op_start_instrument_agent(self, content, headers, msg):
        """
        Service operation: Starts an instrument agent for a type of
        instrument.
        """
        if 'instrumentID' in content:
            inst_id = str(content['instrumentID'])
        else:
            raise ValueError("Input for instrumentID not present")

        if 'model' in content:
            model = str(content['model'])
        else:
            raise ValueError("Input for model not present")

        if model != 'SBE49':
            raise ValueError("Only SBE49 supported!")

        agent_pid = yield self.get_agent_pid_for_instrument(inst_id)
        if agent_pid:
            raise StandardError("Agent already started for instrument "+str(inst_id))

        simulator = Simulator(inst_id)
        simulator.start()

        topicname = "Inst/RAW/"+inst_id
        topic = PubSubTopicResource.create(topicname,"")

        # Use the service to create a queue and register the topic
        topic = yield self.dpsc.define_topic(topic)

        iagent_args = {}
        iagent_args['instrument-id'] = inst_id
        driver_args = {}
        driver_args['port'] = simulator.port
        driver_args['publish-to'] = topic.RegistryIdentity
        iagent_args['driver-args'] = driver_args

        iapd = ProcessDesc(**{'name':'SBE49IA',
                  'module':'ion.agents.instrumentagents.SBE49_IA',
                  'class':'SBE49InstrumentAgent',
                  'spawnargs':iagent_args})

        iagent_id = yield self.spawn_child(iapd)
        iaclient = InstrumentAgentClient(proc=self, target=iagent_id)
        yield iaclient.register_resource(inst_id)

        yield self.reply_ok(msg, "OK")

    @defer.inlineCallbacks
    def op_stop_instrument_agent(self, content, headers, msg):
        """
        Service operation: Starts direct access mode.
        """
        yield self.reply_err(msg, "Not yet implemented")


    @defer.inlineCallbacks
    def op_start_direct_access(self, content, headers, msg):
        """
        Service operation: Starts direct access mode.
        """
        yield self.reply_err(msg, "Not yet implemented")

    @defer.inlineCallbacks
    def op_stop_direct_access(self, content, headers, msg):
        """
        Service operation: Stops direct access mode.
        """
        yield self.reply_err(msg, "Not yet implemented")

    @defer.inlineCallbacks
    def get_agent_desc_for_instrument(self, instrument_id):
        logging.info("get_agent_desc_for_instrument() instrumentID="+str(instrument_id))
        int_ref = ResourceReference(RegistryIdentity=instrument_id, RegistryBranch='master')
        agent_query = InstrumentAgentResourceInstance()
        agent_query.instrument_ref = int_ref


        if not agent_res:
            defer.returnValue(None)
        agent_pid = agent_res.proc_id
        logging.info("Agent process id for instrument id %s is: %s" % (instrument_id, agent_pid))
        defer.returnValue(agent_pid)

    @defer.inlineCallbacks
    def get_agent_for_instrument(self, instrument_id):
        logging.info("get_agent_for_instrument() instrumentID="+str(instrument_id))
        int_ref = ResourceReference(RegistryIdentity=instrument_id, RegistryBranch='master')
        agent_query = InstrumentAgentResourceInstance()
        agent_query.instrument_ref = int_ref
        # @todo Need to list the LC state here. WHY???
        agent_query.lifecycle = LCStates.developed
        agents = yield self.arc.find_registered_agent_instance_from_description(agent_query, regex=False)
        logging.info("Found %s agent instances for instrument id %s" % (len(agents), instrument_id))
        agent_res = None
        if len(agents) > 0:
            agent_res = agents[0]
        defer.returnValue(agent_res)

    @defer.inlineCallbacks
    def get_agent_pid_for_instrument(self, instrument_id):
        agent_res = yield self.get_agent_for_instrument(instrument_id)
        if not agent_res:
            defer.returnValue(None)
        agent_pid = agent_res.proc_id
        logging.info("Agent process id for instrument id %s is: %s" % (instrument_id, agent_pid))
        defer.returnValue(agent_pid)
class TestResourceAgent(IonTestCase):

    @defer.inlineCallbacks
    def setUp(self):
        yield self._start_container()

        # use some sort of agent...doesnt really matter what kind, does it
        processes = [
            {'name':'testAgent',
             'module':'ion.agents.instrumentagents.SBE49_IA',
             'class':'SBE49InstrumentAgent'},
            {'name':'agent_registry',
             'module':'ion.services.coi.agent_registry',
             'class':'AgentRegistryService'}
        ]
        self.sup = yield self._spawn_processes(processes)
        self.svc_id = self.sup.get_child_id('testAgent')
        self.rr_id = self.sup.get_child_id('agent_registry')

        # Start a client (for the RPC)
        self.RAClient = ResourceAgentClient(proc=self.sup, target=self.svc_id)

        # RR Client is ,,,,,desired only for testing
        self.reg_client = AgentRegistryClient(proc=self.sup)
        yield self.reg_client.clear_registry()

        # need any non-generic resource...use an instrument agent one for now
        self.res_desc = \
            InstrumentAgentResourceDescription.create_new_resource()
        #self.res_desc.version = '1.23'
        self.res_desc.name = 'I am a test IA resource description'

        self.res_inst = InstrumentAgentResourceInstance.create_new_resource()
        self.res_inst.driver_process_id = 'something_for_now.1'
        self.res_inst.name = 'I am an instantiation of a test IA resource'

    @defer.inlineCallbacks
    def tearDown(self):
        yield self._stop_container()

    @defer.inlineCallbacks
    def test_reg_direct(self):
        registered_agent_desc = \
           yield self.reg_client.register_agent_definition(self.res_desc)
        # Not committed, so not equal, but parts should be
        self.assertNotEqual(registered_agent_desc, self.res_desc)
        self.assertEqual(registered_agent_desc.RegistryIdentity,
                         self.res_desc.RegistryIdentity)

        registered_agent_instance = \
            yield self.reg_client.register_agent_instance(self.res_inst)
        # Not committed, so not equal, but parts should be
        self.assertNotEqual(registered_agent_instance, self.res_inst)
        self.assertEqual(registered_agent_instance.RegistryIdentity,
                         self.res_inst.RegistryIdentity)

        recv_agent_desc = \
            yield self.reg_client.get_agent_definition(self.res_desc)
        self.assertEqual(recv_agent_desc, registered_agent_desc)
        self.assertEqual(recv_agent_desc.RegistryIdentity,
                         self.res_desc.RegistryIdentity)
        # Not committed, so not equal
        self.assertNotEqual(recv_agent_desc, self.res_desc)

        recv_agent_inst = \
            yield self.reg_client.get_agent_instance(self.res_inst)
        self.assertEqual(recv_agent_inst, registered_agent_instance)
        # Not commiteed, so not equal, but parts should be
        self.assertNotEqual(recv_agent_inst, self.res_inst)
        self.assertEqual(recv_agent_inst.RegistryIdentity,
                         self.res_inst.RegistryIdentity)

    @defer.inlineCallbacks
    def test_registration_with_definitions(self):
        reg_id = yield self.RAClient.register_resource(self.res_inst)
        orig_result = yield self.RAClient.get_resource_instance()
        self.assertNotEqual(orig_result, None)
        self.assertNotEqual(orig_result, self.res_inst)
        self.assertNotEqual(orig_result.RegistryCommit,
                            self.res_inst.RegistryCommit)
        self.assertEqual(reg_id.RegistryCommit, '')
        self.assertNotEqual(orig_result.RegistryCommit, reg_id.RegistryCommit)
        self.assertEqual(reg_id.RegistryIdentity, orig_result.RegistryIdentity)

        # Verify the reference is the same
        result = yield self.RAClient.get_resource_ref()
        self.assertEqual(result, reg_id)

        # test update/repeat reg if a different instance
        new_res_inst = yield self.RAClient.get_resource_instance()
        new_res_inst.name = "REPLACED TestAgentInstance"
        new_res_inst.driver_process_id = 'something_else.1'

        # Even pulling it, modifiying it, then re-registering makes a new one
        new_result = yield self.RAClient.get_resource_instance()
        new_result.name = "UPDATED TestAgentInstance"
        new_result.driver_process_id = 'something_else.2'
        new_reg_ref = yield self.RAClient.register_resource(new_res_inst)
        self.assertNotEqual(reg_id, new_reg_ref)
        new_result2 = yield self.RAClient.get_resource_instance()
        self.assertNotEqual(new_result2.RegistryIdentity,
                            orig_result.RegistryIdentity)
        self.assertNotEqual(new_result2.RegistryCommit,
                            orig_result.RegistryCommit)
        self.assertNotEqual(new_result2.name, orig_result.name)
        self.assertEqual(new_result2.name, new_res_inst.name)
        self.assertEqual(new_result2.driver_process_id,
                         new_res_inst.driver_process_id)
        self.assertNotEqual(new_result2.name, new_result.name)

    @defer.inlineCallbacks
    def test_agent_self_registration(self):
        reg_id = yield self.RAClient.register_resource()
        result = yield self.RAClient.get_resource_instance()
        self.assertNotEqual(result, None)
        self.assertEqual(reg_id.RegistryCommit, '')
        self.assertNotEqual(result.RegistryCommit, reg_id.RegistryCommit)
        self.assertEqual(reg_id.RegistryIdentity, result.RegistryIdentity)

        # Verify the reference is the same
        result = yield self.RAClient.get_resource_ref()
        self.assertEqual(result, reg_id)

        # Make A new agent to verify we have 2
        processes = [{'name':'testAgent2',
                      'module':'ion.agents.instrumentagents.SBE49_IA',
                      'class':'SBE49InstrumentAgent'}]

        sup2 = yield self._spawn_processes(processes)
        svc_id2 = self.sup.get_child_id('testAgent2')

        # Start a client (for the RPC)
        RAClient2 = ResourceAgentClient(proc=sup2, target=svc_id2)

        # test update/repeat reg if a different instance
        yield RAClient2.register_resource()
        refinst2 = yield RAClient2.get_resource_instance()
        refinst1 = yield self.RAClient.get_resource_ref()

        self.assertNotEqual(refinst1.RegistryCommit, refinst2.RegistryCommit)
        self.assertNotEqual(refinst1.RegistryIdentity,
                            refinst2.RegistryIdentity)
        self.assertEqual(refinst1.RegistryCommit, result.RegistryCommit)
        self.assertEqual(refinst1.RegistryIdentity, result.RegistryIdentity)


    @defer.inlineCallbacks
    def test_lifecycle(self):
        registered_res = yield self.RAClient.register_resource(self.res_inst)
        self.assertNotEqual(registered_res, None)
        result = yield self.RAClient.get_resource_ref()
        self.assertEqual(result, registered_res)

        active_state = LCState('active')
        inactive_state = LCState('inactive')

        result = yield self.RAClient.set_lifecycle_state(active_state)
        self.assertEqual(result, active_state)
        result = yield self.RAClient.get_lifecycle_state()
        self.assertEqual(result, active_state)

        result = yield self.RAClient.set_lifecycle_state(inactive_state)
        ref = yield self.RAClient.get_resource_ref()
        self.assertNotEqual(ref, None)
        self.assertEqual(ref, registered_res)
        result = yield self.RAClient.get_lifecycle_state()
        self.assertEqual(result, inactive_state)