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)
Ejemplo n.º 2
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):
        """
Ejemplo n.º 3
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):
        """
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)