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